@overdeck/desktop 0.45.21 → 0.45.22
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-BH7ac_1G.js} +2 -2
- package/server/{advancing-selfheal-CPOBO5ZS.js → advancing-selfheal-cSvXNZLZ.js} +6 -6
- package/server/{agent-gc-D6PUckBB.js → agent-gc-Dj2gncak.js} +4 -4
- package/server/{agent-state-BV_6RHnO.js → agent-state-Co5Sy2Fw.js} +1 -1
- package/server/{agent-state-service-DHwemt96.js → agent-state-service-CsQ07Pxe.js} +1 -1
- package/server/{agent-state-service-6MFQqnFy.js → agent-state-service-DistflNn.js} +5 -5
- package/server/{agents-DbrHWunF.js → agents-DXdHmRTC.js} +4 -4
- package/server/{agents-Czz6R57Z.js → agents-DyHKlq1I.js} +1 -1
- package/server/{archive-planning-BOnwJq8M.js → archive-planning-BvDuWNMo.js} +5 -5
- package/server/{archive-planning-MPpvQJL4.js → archive-planning-Cp_DC1j-.js} +1 -1
- package/server/{artifact-index-jobs-BOoySTKD.js → artifact-index-jobs-CDBFL4OU.js} +2 -2
- package/server/{backlog-auto-trigger-BUaFI44J.js → backlog-auto-trigger-DmA1IbYf.js} +3 -3
- package/server/{behavior-Dg-D8eBG.js → behavior-CGj16clS.js} +2 -2
- package/server/{briefing-freshness-OouGbJ7d.js → briefing-freshness-C12WgkaB.js} +2 -2
- package/server/{build-info-Cv6CI7Gu.js → build-info-BRpqQvNd.js} +1 -1
- package/server/{build-info-27NlbKhV.js → build-info-NU3KbXYw.js} +3 -3
- package/server/{checkpoint-manager-D64fCC4p.js → checkpoint-manager-CTPjAmtH.js} +2 -2
- package/server/{checkpoint-manager-C7mFCY_E.js → checkpoint-manager-rOgT98WY.js} +1 -1
- package/server/checkpoint-worker.js +1 -1
- package/server/{checkpoints-DwZqT2qQ.js → checkpoints-B5jFNi2G.js} +1 -1
- package/server/{checkpoints-Vh-J15ge.js → checkpoints-BJum14fs.js} +2 -2
- package/server/{claude-hooks-provision-CS5W_dhI.js → claude-hooks-provision-BhwWK-TQ.js} +1 -1
- package/server/{claude-hooks-provision-BVLGfHrv.js → claude-hooks-provision-D7p5WcKZ.js} +2 -2
- package/server/{claude-permissions-C2OrLYKL.js → claude-permissions-nSFKH78M.js} +2 -2
- package/server/{claude-settings-overlay-DX-fMFpC.js → claude-settings-overlay-BI_UIke0.js} +2 -2
- package/server/{claude-settings-overlay-DWXjafJh.js → claude-settings-overlay-DHBwjS1X.js} +1 -1
- package/server/cli-BRORS9qY.js +3 -0
- package/server/{cli-mvpEOb3w.js → cli-CbKNkFE5.js} +9 -9
- package/server/{cliproxy-Dvsr4ZkW.js → cliproxy-Brf_5MuG.js} +2 -2
- package/server/{cliproxy-7g1nObvB.js → cliproxy-bONZDBbC.js} +1 -1
- package/server/{close-issue-8F6uawYj.js → close-issue-CxReRxIc.js} +5 -5
- package/server/{closed-issue-reaper-BaYQYF6w.js → closed-issue-reaper-CQ3kqha7.js} +9 -9
- package/server/{closed-issue-reaper-BhV-r-tC.js → closed-issue-reaper-DXP2Xyv3.js} +1 -1
- package/server/{codex-D_UBEOwL.js → codex-CbmztVcc.js} +9 -6
- package/server/{codex-BBeZ8c3s.js → codex-DNyiQDKW.js} +1 -1
- package/server/{codex-parser-BTzlOZiV.js → codex-parser-jl8AeAmB.js} +2 -2
- package/server/{config-nAB_F-Gp.js → config-BJKocXKd.js} +1 -1
- package/server/{config-G1TOMJZA.js → config-DeTsoZdR.js} +2 -2
- package/server/{config-CrduXs4a.js → config-q4Gvd8dq.js} +2 -2
- package/server/{config-yaml-Ciyp2mYe.js → config-yaml-ig8Nwtiw.js} +124 -27
- package/server/{conflict-gate-BLUNMs1i.js → conflict-gate-CFqPVxEg.js} +3 -3
- package/server/{conflict-gate-BKalpcjL.js → conflict-gate-CHU9K1vU.js} +1 -1
- package/server/{context-layers-Cg9ZgVfx.js → context-layers-15gDOk20.js} +3 -3
- package/server/{context-layers-YNpf6Q_I.js → context-layers-DlQKkHH2.js} +2 -2
- package/server/{control-settings-D_79A6gp.js → control-settings-D_odMIaC.js} +4 -4
- package/server/{conversation-compaction-DiuZbIUB.js → conversation-compaction-B6YSRLda.js} +8 -8
- package/server/{conversation-compaction-CMIeWW4_.js → conversation-compaction-CN4-5YYt.js} +1 -1
- package/server/{conversation-service-DQybSPUK.js → conversation-service-C3avRVEr.js} +6 -6
- package/server/{conversation-service-CWk8mEym.js → conversation-service-Dq33SYEj.js} +1 -1
- package/server/{conversations-BJ-t3BRm.js → conversations-H9if0bCQ.js} +1 -1
- package/server/{conversations-BUgGvqVL.js → conversations-bYpM9-kZ.js} +4 -4
- package/server/{cost-Drm7qeD5.js → cost-Codk1pc2.js} +2 -2
- package/server/{cost-sync-DzHP6zaR.js → cost-sync-D_cre6WM.js} +3 -3
- package/server/{cost-jJ2cgDcG.js → cost-wH46-WsJ.js} +3 -3
- package/server/{dag-DIji6O2b.js → dag-CJpgf9A3.js} +2 -2
- package/server/{dangerous-git-ops-BebB-61h.js → dangerous-git-ops-D6AF-Hg_.js} +1 -1
- package/server/dashboard-db-worker.js +7 -7
- package/server/{deacon-pleYrvIm.js → deacon-B8HbQdqU.js} +3 -3
- package/server/{deacon-1s7bM5zn.js → deacon-CkT_kznS.js} +1377 -407
- package/server/{deacon-nudge-log-C5VCKtyi.js → deacon-nudge-log-D6K9K-rE.js} +3 -3
- package/server/{deacon-swarm-DmA3rJ7k.js → deacon-swarm-BryRr6AO.js} +13 -13
- package/server/deacon-swarm-CV54eNmU.js +2 -0
- package/server/deacon.js +8 -8
- package/server/{deploy-patrol-DmM6F-yw.js → deploy-patrol-1IrZxicY.js} +6 -6
- package/server/{deploy-window-ClLq1RYf.js → deploy-window-7ZYHh7Zp.js} +1 -1
- package/server/{deploy-window-jw4S_Y-c.js → deploy-window-wDf4UgHt.js} +6 -6
- package/server/{dev-supervisor-Do2Stz49.js → dev-supervisor-C7p9kEpc.js} +2 -2
- package/server/{devcontainer-renderer-D8ylupco.js → devcontainer-renderer-CNmQy0pL.js} +3 -3
- package/server/{dist-yfR7G1BL.js → dist-D-Ed5yVw.js} +1 -1
- package/server/dist-j64RzSrQ.js +3 -0
- package/server/{docker-ClwPQaba.js → docker-BCZ89M9X.js} +2 -2
- package/server/{dod-BLphkhjs.js → dod-DbJLYcHv.js} +1 -1
- package/server/{ensure-devcontainer-BA3bICoY.js → ensure-devcontainer-Cs6W9Yzj.js} +1 -1
- package/server/{ensure-devcontainer-CFpQatOc.js → ensure-devcontainer-V5JWaAva.js} +4 -4
- package/server/{esm-shims-BZw-fTQ6.js → esm-shims-dTeNdq7X.js} +1 -1
- package/server/{event-store-DABarGNz.js → event-store-CpBGsO6_.js} +1 -1
- package/server/{event-store-BVnON3vf.js → event-store-TnWdydfB.js} +3 -3
- package/server/{events-CmERlnwn.js → events-DSUdR-04.js} +3 -3
- package/server/{events-LGeUehYW.js → events-Dsuv6qyB.js} +1 -1
- package/server/{factory-CQNprtHe.js → factory-BMrK4TrE.js} +4 -4
- package/server/{feature-registry-population-D9Z3tYSa.js → feature-registry-population-B-CI9hgE.js} +4 -4
- package/server/{feature-registry-storage-BWymOgXE.js → feature-registry-storage-B972ph_A.js} +2 -2
- package/server/{features--fOza5g5.js → features-Bc-Bmiye.js} +2 -2
- package/server/{feedback-target-Dn9vfPpz.js → feedback-target-DS6NUuSs.js} +1 -1
- package/server/{feedback-target-Dqik2WTe.js → feedback-target-DZ-iAnAa.js} +7 -7
- package/server/{feedback-writer-Wlq5-qgS.js → feedback-writer-BXP6g75N.js} +4 -4
- package/server/{feedback-writer-DDQNV8uc.js → feedback-writer-Bx5z11mF.js} +1 -1
- package/server/{flywheel-DPUc8r3V.js → flywheel-6WHU4O7A.js} +14 -14
- package/server/{flywheel-1Wd8WDlh.js → flywheel-COR0mbRI.js} +12 -12
- package/server/{flywheel-Q-38YhZG.js → flywheel-Ctr5uuvo.js} +1 -1
- package/server/{flywheel-merge-order-CeBuX0EJ.js → flywheel-merge-order-CNKAY489.js} +1 -1
- package/server/{flywheel-merge-order-4SqOXFAr.js → flywheel-merge-order-CTgHeg-W.js} +7 -7
- package/server/forge-B0_opi-V.js +2 -0
- package/server/{forge-DBbDpiYc.js → forge-B1S_KZv4.js} +2 -2
- package/server/{from-hh6vTBGl.js → from-DpwQ-sc3.js} +1 -1
- package/server/{fts-db-6ponMie2.js → fts-db-DmAcuCkV.js} +2 -2
- package/server/{fts-operations-KIRK165y.js → fts-operations-7d_RkmWp.js} +2 -2
- package/server/git-utils-Cc3FHDKd.js +198 -0
- package/server/{git-utils-DmF5xkj8.js → git-utils-CsKGnzFA.js} +1 -1
- package/server/{github-app-B3yfECo8.js → github-app-CDPtGF7J.js} +2 -2
- package/server/{github-app-CeSVFL6C.js → github-app-CU14oYzP.js} +1 -1
- package/server/{github-client-4A6FgA8O.js → github-client-CwBZZ3t7.js} +1 -1
- package/server/{github-client-Dslipypz.js → github-client-XjTJbBm7.js} +2 -2
- package/server/{github-pr-lookup-DBP0YHMr.js → github-pr-lookup-CFGeVhqv.js} +2 -2
- package/server/harness-binary-B2CTcD84.js +106 -0
- package/server/{harness-resolve-BGpO-OVM.js → harness-resolve-D5FVQTmy.js} +9 -15
- package/server/{health-events-CnwV_SSz.js → health-events-C1whmd58.js} +1 -1
- package/server/{health-events-CZGZ5I-A.js → health-events-DREeevle.js} +2 -2
- package/server/{hooks-DvX33gY_.js → hooks-B-HItBiS.js} +1 -1
- package/server/{hooks-CoNscX84.js → hooks-yxRsjk-z.js} +2 -2
- package/server/hume-BmhvfVbV.js +3 -0
- package/server/{hume-DSJt5eA_.js → hume-Dz_OymXE.js} +2 -2
- package/server/{idle-stack-reaper-5DVRoY6P.js → idle-stack-reaper-DrCv0OAG.js} +1 -1
- package/server/{idle-stack-reaper-BfL8HqYy.js → idle-stack-reaper-Yf34xXxY.js} +2 -2
- package/server/{in-flight-guard-tVGiI5ee.js → in-flight-guard-BoWm66Kh.js} +2 -2
- package/server/{infra-DN2wSxle.js → infra-D4iNWMA5.js} +4 -4
- package/server/{injection-DK9zh_HL.js → injection-BVNa4MQW.js} +1 -1
- package/server/{injection-DtlT8Akv.js → injection-D7T75Pye.js} +7 -7
- package/server/{inspect-agent-DKByUS_F.js → inspect-agent-BXCgNeZ4.js} +13 -9
- package/server/inspect-agent-Dq0z1k3H.js +2 -0
- package/server/{internal-token-7bYL5v6K.js → internal-token-C9DdEOKY.js} +1 -1
- package/server/{internal-token-DhfFiwW7.js → internal-token-CXsfxslp.js} +2 -2
- package/server/{io-BiM-7Zsx.js → io-DQR9PMgS.js} +3 -3
- package/server/{issue-closed-Dfw3QDyZ.js → issue-closed-DtmJM0D0.js} +7 -7
- package/server/{issue-lifecycle-ytsEdDlK.js → issue-lifecycle-8PSS9Anq.js} +1 -1
- package/server/{issue-lifecycle-B7HZWnTA.js → issue-lifecycle-CeyW_HoD.js} +21 -21
- package/server/{issue-service-singleton-D5EB5eYr.js → issue-service-singleton-DBZabEl7.js} +1 -1
- package/server/{issue-service-singleton-CPESc4Or.js → issue-service-singleton-D_RVYBuL.js} +8 -8
- package/server/{issues-XYtFMxrH.js → issues-pDW9VUNz.js} +2 -2
- package/server/{jsonl-parser-DJV2eZUP.js → jsonl-parser-C3HVNR5d.js} +3 -3
- package/server/{label-cleanup-CJ4m8iRU.js → label-cleanup-DPwiZlWo.js} +3 -3
- package/server/{label-reconciler-CNf3Ylm3.js → label-reconciler-Df1ZduPH.js} +4 -4
- package/server/{launcher-generator-5DJRiovn.js → launcher-generator-COgR2By1.js} +6 -6
- package/server/{layers-cZx7ibtV.js → layers-Cp1To4L8.js} +2 -2
- package/server/{lifecycle-CE7619Xw.js → lifecycle-CtPDcZ9u.js} +6 -6
- package/server/{lifecycle-io-CUpsxG0p.js → lifecycle-io-DmY2qwCn.js} +1 -1
- package/server/{lifecycle-io-DMurK4oM.js → lifecycle-io-taIb0PoH.js} +4 -4
- package/server/{linear-client-BLyN-NiP.js → linear-client-DsFkIxee.js} +2 -2
- package/server/{linear-client-Bj1l4FOA.js → linear-client-YwZMDIwQ.js} +1 -1
- package/server/memory-fts-worker.js +1 -1
- package/server/{merge-CwX2_AWm.js → merge-BwsyNRJV.js} +1 -1
- package/server/{merge-hSC2BENe.js → merge-C1t-bspg.js} +3 -3
- package/server/{merge-agent-CnORPiri.js → merge-agent-B-SnXOoc.js} +1 -1
- package/server/{merge-agent-DnBsms_V.js → merge-agent-DDiIjzk-.js} +369 -213
- package/server/{merge-batch-C2w2U2eK.js → merge-batch-Byt-QnEl.js} +1 -1
- package/server/{merge-blockers-DhRgh76x.js → merge-blockers-BYjeXrVN.js} +2 -2
- package/server/merge-ops-DwWCkSgo.js +2 -0
- package/server/{merge-rebase-CE-ZyOMY.js → merge-rebase-Cm6fXaZN.js} +2 -2
- package/server/{merge-set-DHkzPCJU.js → merge-set-6LEglm6o.js} +1 -1
- package/server/{merge-set-D7YNU1ZB.js → merge-set-DiISXcC-.js} +3 -3
- package/server/{merge-sync-CpGA9Kg7.js → merge-sync-B95_4in_.js} +1 -1
- package/server/{merge-sync-De1FYva5.js → merge-sync-Do8_q32h.js} +2 -2
- package/server/{merge-train-SvkRJZ-k.js → merge-train-CKana8EH.js} +3 -3
- package/server/{merge-train-deps-CECJTElu.js → merge-train-deps-BgmqwIfA.js} +4 -4
- package/server/{merge-verification-B3meGcXF.js → merge-verification-CqnUzGEK.js} +4 -4
- package/server/{multipart-parser-ByTMgYV5.js → multipart-parser-tdOQDJ3o.js} +2 -2
- package/server/{no-resume-mode-BnInAFKs.js → no-resume-mode-BWOSZjWd.js} +1 -1
- 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-DSvsJ5M7.js} +1 -1
- package/server/{orphan-proposed-reconciler-AxAGUouN.js → orphan-proposed-reconciler-xklgvNA7.js} +19 -12
- package/server/package-lock.json +6 -6
- package/server/package.json +1 -1
- package/server/{pan-dir-Rw17YjT1.js → pan-dir-DOcf6ug3.js} +4 -4
- package/server/{paths-FP8v3lTz.js → paths-DooHpt9p.js} +2 -2
- package/server/{pickup-xi3KTLaJ.js → pickup-CaskQ7j6.js} +2 -2
- package/server/{pipeline-membership-BtKMNY7v.js → pipeline-membership-1LGRjo-k.js} +11 -8
- package/server/{pipeline-notifier-BM2HLF7B.js → pipeline-notifier-B6FVsYF9.js} +2 -2
- package/server/{pipeline-notifier-dQ-U4NSb.js → pipeline-notifier-CZsrU_nj.js} +1 -1
- package/server/{project-pipelines-B59NfN44.js → project-pipelines-CtNG_rvs.js} +2 -2
- package/server/projects-BKkwpH6q.js +3 -0
- package/server/{prompts-CbqaVjbe.js → prompts-EvhMeeHG.js} +2 -2
- package/server/{providers-d3pwXGVE.js → providers-BDDPULlp.js} +7 -7
- package/server/providers-DNSQqy2V.js +3 -0
- package/server/public/assets/{chunk-BO2N2NFS-BxYSL7J-.js → chunk-BO2N2NFS-sym_ufXe.js} +4 -4
- package/server/public/assets/{diagram-OG6HWLK6-C_F9Q2as.js → diagram-OG6HWLK6-CQJPBNBu.js} +1 -1
- package/server/public/assets/{dist-DQNg4CiF.js → dist-Bio7THQU.js} +1 -1
- package/server/public/assets/{dist-CLSlc6cV.js → dist-DukGS2YZ.js} +3 -3
- package/server/public/assets/{ganttDiagram-6RSMTGT7-Cq0my-0C.js → ganttDiagram-6RSMTGT7-D4lWwte3.js} +1 -1
- package/server/public/assets/{highlighted-body-OFNGDK62-eZC03dGh.js → highlighted-body-OFNGDK62-CaLboCt5.js} +1 -1
- package/server/public/assets/{index-C6NLz_1S.css → index-Bdc4V9ba.css} +1 -1
- package/server/public/assets/{index-SLYGA8AQ.js → index-Bwejq-5s.js} +147 -145
- package/server/public/assets/{linear-6Fi3qnGg.js → linear-qUWmMZ-c.js} +1 -1
- package/server/public/assets/mermaid-GHXKKRXX-B5v_r7cI.js +1 -0
- package/server/public/assets/{pieDiagram-4H26LBE5-Dpmc6xsv.js → pieDiagram-4H26LBE5-C4zYulEm.js} +1 -1
- package/server/public/assets/{prod-ojHllFvN.js → prod-C8VtLuWC.js} +4 -4
- package/server/public/assets/{quadrantDiagram-W4KKPZXB-Ulr9gON5.js → quadrantDiagram-W4KKPZXB-qP04zyZC.js} +1 -1
- package/server/public/assets/{sankeyDiagram-5OEKKPKP-CwdHGXfL.js → sankeyDiagram-5OEKKPKP-eMPTX_cG.js} +1 -1
- package/server/public/assets/{xychartDiagram-2RQKCTM6-r-bEDzJh.js → xychartDiagram-2RQKCTM6-Dme1PIt6.js} +1 -1
- package/server/public/index.html +54 -10
- package/server/{pull-requests-CjjPj7v6.js → pull-requests-8z2N1UOV.js} +3 -3
- package/server/{pull-requests-D3N6HQzI.js → pull-requests-By_BteaL.js} +1 -1
- package/server/{queries-B5hl7lMQ.js → queries-ZABd5aXP.js} +95 -71
- package/server/rally-OSJXdiHK.js +3 -0
- package/server/{rally-api-DGaFz5L5.js → rally-api-DqKqIMNR.js} +2 -2
- package/server/{rally-api-CKr0O4DJ.js → rally-api-xHazRk0d.js} +1 -1
- package/server/{rally-client-Cqf6EX_r.js → rally-client-CGWEHaPd.js} +1 -1
- package/server/{rally-client-SVbjGvqj.js → rally-client-COYz1vYR.js} +4 -4
- package/server/{rally-Dp0Gb1DN.js → rally-i_goYmiA.js} +3 -3
- package/server/reap-terminal-sessions-CaMkFOIH.js +4 -0
- package/server/{reap-terminal-sessions-CjqRAGw7.js → reap-terminal-sessions-DG9eiMVz.js} +11 -28
- package/server/{rebuild-stack-DjdpALr1.js → rebuild-stack-CKjJAI8L.js} +1 -1
- package/server/{rebuild-stack-DHqCLvLX.js → rebuild-stack-JUm0jqYP.js} +6 -6
- package/server/{reconstruct-cache-BqrCQt0o.js → reconstruct-cache-wU79aCee.js} +6 -6
- package/server/record-rwK-nKv_.js +3 -0
- package/server/{record-update-RviRDSNs.js → record-update-Crz74r-6.js} +2 -2
- package/server/{record-update-BlB8mpKO.js → record-update-D3N6WMFR.js} +1 -1
- package/server/{recovery-trip-l1Hsi37x.js → recovery-trip-DkzJSej9.js} +2 -2
- package/server/{release-engine-CSI4K6Oj.js → release-engine-DMINVN8S.js} +5 -5
- package/server/{release-set-BywwggrE.js → release-set-DeUSOEHy.js} +3 -3
- package/server/{remote-DYziAkiZ.js → remote-Dr5kGYSZ.js} +3 -3
- package/server/{remote-agents-CZ2rc8I0.js → remote-agents-Ct_WOyke.js} +6 -6
- package/server/{remote-agents-BNORDWAX.js → remote-agents-D6O_zETW.js} +1 -1
- package/server/{remote-cnoeuDWn.js → remote-b-c5bOce.js} +3 -3
- package/server/{remote-completion-W67FNQ-A.js → remote-completion-Dca3hAaa.js} +13 -13
- package/server/resume-wZZsWtzz.js +3 -0
- package/server/{review-agent-CSswH985.js → review-agent-CCum8sGe.js} +1 -1
- package/server/{review-agent-CqSqSHkU.js → review-agent-CThvgK2r.js} +23 -23
- package/server/{review-artifacts-BBgnd5df.js → review-artifacts-CXywD0F2.js} +5 -5
- package/server/{review-context-Ctp9BdNJ.js → review-context-OYfKUprb.js} +8 -8
- package/server/{review-status-DXeqFpk5.js → review-status-Bnh-rdkY.js} +1 -1
- package/server/{review-status-CCgPVK1h.js → review-status-DFRjDFef.js} +21 -37
- package/server/{review-status-enrichment-DtDRGpst.js → review-status-enrichment-crNAtIpL.js} +3 -3
- package/server/review-status-source-CxuEjLGg.js +39 -0
- package/server/{review-status-sync-C792ksoJ.js → review-status-sync-D60PJWNL.js} +1 -1
- package/server/{review-status-sync-jnLgd04F.js → review-status-sync-DpAMD_WO.js} +2 -2
- package/server/{review-verdict-feedback-CMsIpTpy.js → review-verdict-feedback-CpUZl5aE.js} +7 -7
- package/server/{review-verdict-feedback-D5lW0o3k.js → review-verdict-feedback-JImjut0z.js} +1 -1
- package/server/{rollup-B3kQmNpl.js → rollup-CZ02qgxk.js} +1 -1
- package/server/{rollup-CLj_AK9f.js → rollup-SyuF09e4.js} +8 -8
- package/server/{scanner-C4NeC4FE.js → scanner-Br0Z5S6R.js} +7 -7
- package/server/{sequence-io-Ce-6grIY.js → sequence-io-fxU0DlwW.js} +4 -4
- package/server/{sequencer-agent-Bpz0yGmG.js → sequencer-agent-B5YC5XVP.js} +5 -5
- package/server/server.js +583 -387
- package/server/{service-CqAY8Kmk.js → service-Bagb90KZ.js} +150 -47
- package/server/{session-fork-uNo4rMRA.js → session-fork-BqQxd-V6.js} +2 -2
- package/server/{session-history-DUehL3KN.js → session-history-XdS0JKp3.js} +4 -4
- package/server/{settings-DP2OYLXL.js → settings-BNbocWOg.js} +3 -3
- package/server/settings-BlUsVaUc.js +2 -0
- package/server/{settings-D9grjmaP.js → settings-uLc6DEYI.js} +2 -2
- package/server/{shadow-engineering-Bi_oIMtF.js → shadow-engineering-D4X_s3fA.js} +3 -3
- package/server/{shadow-state-a_ztFBJe.js → shadow-state-C_NkP-sa.js} +2 -2
- package/server/{shadow-state-CDxEuPlE.js → shadow-state-CbvsN3qG.js} +1 -1
- package/server/{shadow-utils-CyOg6_Xq.js → shadow-utils-CYMRPeRT.js} +2 -2
- package/server/{ship-log-DDcueaIR.js → ship-log-__QtAFXG.js} +1 -1
- package/server/{smart-compaction--Oj65Uov.js → smart-compaction-CLZOWin1.js} +7 -7
- package/server/{smart-compaction-C1_VVLEd.js → smart-compaction-jdMkG1vo.js} +1 -1
- package/server/{spawn-planning-session-LFtK2QCE.js → spawn-planning-session-8D6mE033.js} +1 -1
- package/server/{spawn-planning-session-AiUSsBnH.js → spawn-planning-session-D5OXo8pT.js} +19 -15
- package/server/{specialist-completion-qOgqdqXH.js → specialist-completion-CqmduO92.js} +1 -1
- package/server/{specialist-context-gjj8Z4Ii.js → specialist-context-CJ-QjFR-.js} +5 -5
- package/server/{specialist-handoff-logger-BsBNvVZv.js → specialist-handoff-logger-Dnjlwt7g.js} +2 -2
- package/server/{specialist-logs-CSLtvPx6.js → specialist-logs-CQnKzuZs.js} +3 -3
- package/server/{specialists-DAegTvRt.js → specialists-Bg9v4z3F.js} +122 -94
- package/server/{specialists-CYRwELzc.js → specialists-CwZHb5cb.js} +18 -18
- package/server/{specialists-D0VBf8g_.js → specialists-D0gGXMZx.js} +1 -1
- package/server/{specialists-C6WkeKFK.js → specialists-Dqe6_HE5.js} +1 -1
- package/server/specs-BhOKBzqk.js +3 -0
- package/server/{src-OLoJhUiJ.js → src-BMMoA_ba.js} +6 -6
- package/server/{src-BqTcrfO_.js → src-Bqdtd6po.js} +3 -3
- package/server/{src-Dpq1yFIl.js → src-k039WVYY.js} +337 -4
- package/server/{stack-health-I713ELld.js → stack-health-Bd06frFn.js} +1 -1
- package/server/{stack-health-DV_f-lK0.js → stack-health-C-ifC7b0.js} +2 -2
- package/server/{stale-task-claims-CQSKZVq0.js → stale-task-claims-L7pJkQFL.js} +4 -4
- package/server/{staleness-BbsGxmF2.js → staleness-BID1BKdr.js} +1 -1
- package/server/{staleness-zGp4P1hd.js → staleness-_Tr-GwdA.js} +1 -1
- package/server/{state-home-DixkE-up.js → state-home-CONQvZR0.js} +36 -23
- package/server/state-migrate-BeBW0KXA.js +478 -0
- package/server/{stuck-remediation-BWkK_O7A.js → stuck-remediation-CKnIryGT.js} +20 -18
- package/server/{stuck-remediation-CTPRC2S5.js → stuck-remediation-CsGD5Ksb.js} +1 -1
- package/server/{substrate-bug-weights-service-DXd0ID83.js → substrate-bug-weights-service-CpIZILj9.js} +3 -3
- package/server/{summary-fork-CdLn8Chr.js → summary-fork-agEMsPSo.js} +2 -2
- package/server/{summary-fork-f3DpgjXh.js → summary-fork-bX6ax6X7.js} +8 -8
- package/server/supervisor-COVHrBTg.js +2 -0
- package/server/{supervisor-Ch8CDuoF.js → supervisor-Ctt4eRYz.js} +3 -3
- package/server/{swarm-readiness-C9P2iPap.js → swarm-readiness-DdmJVX7y.js} +3 -3
- package/server/{system-prerequisites-DkoQBn1q.js → system-prerequisites-DSXBvffY.js} +24 -44
- package/server/{teardown-workspace-D-5yMyit.js → teardown-workspace-DDCf5n-a.js} +15 -15
- package/server/{test-agent-queue-BwpUpu-o.js → test-agent-queue-BJZ9Nfcc.js} +6 -6
- package/server/{test-verdict-BRiSu7eW.js → test-verdict-Cp5tljlJ.js} +1 -1
- package/server/{test-verdict-BQ1yx7d4.js → test-verdict-D_-sXIz_.js} +1 -1
- package/server/{tldr-daemon-BJA7TkqS.js → tldr-daemon-B8_oT5gx.js} +1 -1
- package/server/{tldr-daemon-DjxP5g6Y.js → tldr-daemon-BQFmmFp0.js} +2 -2
- package/server/{tmux-HQLgwo_C.js → tmux-BAvtac_u.js} +1 -1
- package/server/{tmux-y1blSxks.js → tmux-L5LgvGLp.js} +2 -2
- package/server/{token-LUrbM9sU.js → token-BkQLy4yS.js} +2 -2
- package/server/token-util-BArZLN6w.js +3 -0
- package/server/{token-util-BZaDAQ8S.js → token-util-DI8sGlmF.js} +1 -1
- package/server/{tracker-config-DSFZBdXP.js → tracker-config-DdT-nUAM.js} +2 -2
- package/server/{tracker-utils-DiceZN3a.js → tracker-utils-CawsPSS2.js} +2 -2
- package/server/{tracker-utils-WtP_V-yn.js → tracker-utils-DV3h1FYG.js} +1 -1
- package/server/{traefik-connect-BXqfOP4-.js → traefik-connect-C6mJckNs.js} +1 -1
- package/server/{tunnel-WcJImbAC.js → tunnel-BIFl98rc.js} +1 -1
- package/server/{tunnel-DTng1rfQ.js → tunnel-IdK1iTHx.js} +3 -3
- package/server/{types-BjaZ1oqH.js → types-7-GnJn0t.js} +1 -1
- package/server/{types-DqeBMmJN.js → types-hraoaQIp.js} +1 -1
- package/server/{uat-train-Wismge7h.js → uat-train-0Ujk8GCv.js} +1 -1
- package/server/{uat-train-BpLnp7Cx.js → uat-train-j0cPeMSj.js} +25 -25
- package/server/{validation-BA4e5EGm.js → validation-CabEISJT.js} +4 -4
- package/server/{validation-CUWamZ4X.js → validation-DcAgXTQp.js} +1 -1
- package/server/{verification-artifact-Dr_0g9nb.js → verification-artifact-BuTA1QbL.js} +1 -1
- package/server/{verification-artifact-CrbI4tJE.js → verification-artifact-Ck1tefmz.js} +1 -1
- package/server/{verification-runner-Dcksl_P-.js → verification-runner-DlJezzef.js} +1 -1
- package/server/{verification-runner-gAzh3cVD.js → verification-runner-FiuAZ-H2.js} +15 -14
- package/server/{vtt-parser-3VZKsmSm.js → vtt-parser-BnRsYzcz.js} +1 -1
- package/server/{work-agent-prompt-ULdcANl5.js → work-agent-prompt-DLthEPAq.js} +12 -11
- package/server/{workflows-B8ROFlfw.js → workflows-BZNNYkGC.js} +18 -18
- package/server/workflows-C4mR0Reb.js +2 -0
- package/server/{workspace-DSjUJaJN.js → workspace-3IC-UkAi.js} +1 -1
- package/server/{workspace-DhTDA8nB.js → workspace-D9ppycdg.js} +3 -3
- package/server/{workspace-config-BAAsAv-o.js → workspace-config-Bigl_-Lk.js} +1 -1
- package/server/{workspace-manager-CcujONCR.js → workspace-manager-B1WOfKvB.js} +1 -1
- package/server/{workspace-manager-DsN52IMG.js → workspace-manager-ClkCIWTe.js} +13 -13
- package/server/{workspace-metadata-CftOpNLs.js → workspace-metadata-BE0efUv_.js} +1 -1
- package/server/{workspace-metadata-DIL5_U4c.js → workspace-metadata-tiSRIWJP.js} +2 -2
- package/server/{workspaces-Dmlh1YXm.js → workspaces-CFPcL0vl.js} +96 -96
- package/sync-sources/skills/pan-start/SKILL.md +23 -0
- package/server/cli-ChErG518.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/merge-ops-BpTtuO8x.js +0 -2
- package/server/projects-IRHJIPYC.js +0 -3
- package/server/providers-BqCdTryq.js +0 -3
- 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-us0YECMO.js +0 -3
- package/server/resume-OyN3dEXE.js +0 -3
- package/server/settings-BaPXXJsT.js +0 -2
- package/server/specs-BsNcum0h.js +0 -3
- package/server/state-migrate-_zJJ6XKE.js +0 -362
- package/server/supervisor-Qy1QecAs.js +0 -2
- package/server/token-util-Cg-QnowA.js +0 -3
- package/server/workflows-C5c-RPsY.js +0 -2
|
@@ -1,47 +1,49 @@
|
|
|
1
1
|
import { i as __require, t as __commonJSMin } from "./rolldown-runtime-DNCzzKnI.js";
|
|
2
|
-
import {
|
|
3
|
-
import { n as init_build_info, t as getBuildInfo } from "./build-info-
|
|
4
|
-
import { n as getDashboardIdentity, t as recordDeaconNudge } from "./deacon-nudge-log-
|
|
2
|
+
import { Hn as init_projects, In as getProjectSync, Kn as listProjectsSync, Mr as AGENTS_DIR, Nt as init_record, Rt as readIssueRecordSync, Vr as OVERDECK_HOME, b as DEFAULT_CONFIG$1, ci as sessionFilePath, cn as init_auto_commit, f as loadConfigSync, fn as STATE_PLANE_PATHS, gn as isStatePlanePath, ii as init_paths, jr as init_errors, mn as init_state_plane, nr as resolveProjectFromIssueSync, pn as getMainDivergence, s as init_load, un as reconcileStatePlaneDrift, x as init_defaults } from "./config-yaml-ig8Nwtiw.js";
|
|
3
|
+
import { n as init_build_info, t as getBuildInfo } from "./build-info-NU3KbXYw.js";
|
|
4
|
+
import { n as getDashboardIdentity, t as recordDeaconNudge } from "./deacon-nudge-log-D6K9K-rE.js";
|
|
5
5
|
import { a as init_activity_logger, n as emitActivityEntrySync, r as emitActivityTtsSync } from "./activity-logger-DDlOIAML.js";
|
|
6
|
-
import { n as updateIssueRecord, t as init_record_update } from "./record-update-
|
|
7
|
-
import { D as killSession, E as isPaneDead, F as querySessionSync, H as sessionExistsSync, M as listSessions, R as sendKeys, V as sessionExists, i as capturePane, j as listSessionNames, k as listPaneValues, w as init_tmux, z as sendKeysAsync } from "./tmux-
|
|
8
|
-
import { a as init_event_store, i as initEventStore } from "./event-store-
|
|
9
|
-
import {
|
|
10
|
-
import { c as
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { i as
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { l as
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { a as
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import { a as
|
|
30
|
-
import {
|
|
31
|
-
import { a as
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import { n as
|
|
36
|
-
import { n as
|
|
37
|
-
import {
|
|
38
|
-
import { t as
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import { n as
|
|
42
|
-
import {
|
|
43
|
-
import { n as
|
|
44
|
-
import {
|
|
6
|
+
import { n as updateIssueRecord, t as init_record_update } from "./record-update-Crz74r-6.js";
|
|
7
|
+
import { D as killSession, E as isPaneDead, F as querySessionSync, H as sessionExistsSync, M as listSessions, R as sendKeys, V as sessionExists, i as capturePane, j as listSessionNames, k as listPaneValues, w as init_tmux, z as sendKeysAsync } from "./tmux-L5LgvGLp.js";
|
|
8
|
+
import { a as init_event_store, i as initEventStore } from "./event-store-TnWdydfB.js";
|
|
9
|
+
import { C as projectLegacySystemHealthSummary, t as init_src } from "./src-k039WVYY.js";
|
|
10
|
+
import { S as needsReviewDispatch, c as init_review_status, h as reviewGatesPassedSync, s as getReviewStatusSync, u as loadReviewStatuses, x as init_review_dispatch_decision, y as setReviewStatusSync } from "./review-status-DFRjDFef.js";
|
|
11
|
+
import { c as listAllAgentsSync, d as isTerminalIssueStage, o as init_agents, u as getIssueStageSync } from "./agents-DXdHmRTC.js";
|
|
12
|
+
import { $ as stopAgent, Bn as recordAgentFailure, Dn as getAgentDir, F as isContextOverflowTail, Gn as saveAgentStateSync, I as init_messaging, Jn as setAgentYieldedSync, L as messageAgent, Ln as markAgentRunningState, M as resumeAgent, Mn as init_agent_state, N as init_context_overflow, Q as init_termination, St as init_transcript_landing, Tn as clearYieldForResumeSync, Un as resetAgentFailureCount, Wn as saveAgentState, _r as init_codex_auth, a as listRunningAgentsSync, at as getConcurrencyLimits, dr as init_runtime_state, fr as saveAgentRuntimeState, ft as workResumeSlotsAvailable, hr as applyCodexAuthBurnFlag, ht as setCachedMemoryVerdict, i as listRunningAgents, jn as getAgentStateSync, kn as getAgentState, lr as getAgentRuntimeState, lt as resetPatrolDispatchBudget, mt as init_memory_verdict_cache, n as init_queries, ot as init_concurrency, pn as buildDefaultResumeContinueMessage, qn as setAgentPausedSync, r as listAgentStates, rt as describeRunningAgents, s as init_agents$1, st as releaseAdvancingSlot, tt as countRunningAgents, ur as getAgentRuntimeStateSync, ut as tryReserveAdvancingSlot, vr as paneShowsCodexAuthBurn, vt as deliverInitialPromptWithRetry, wn as clearAgentTroubledSync, xt as captureTranscriptUserRecordSnapshot } from "./queries-ZABd5aXP.js";
|
|
13
|
+
import { c as logDeaconEventSync, l as getRuntimeSnapshot, o as init_persistent_logger, s as logAgentLifecycleSync, u as init_agent_runtime_mirror } from "./session-history-XdS0JKp3.js";
|
|
14
|
+
import { i as resolveGitHubIssueSync, n as init_tracker_utils } from "./tracker-utils-CawsPSS2.js";
|
|
15
|
+
import { i as ensureInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-CXsfxslp.js";
|
|
16
|
+
import { c as init_review_status_sync, l as markWorkspaceStuck } from "./review-status-sync-DpAMD_WO.js";
|
|
17
|
+
import { i as readReviewStatusMap, n as init_review_status_source, t as classifyAdvancingSessionLifecycle } from "./review-status-source-CxuEjLGg.js";
|
|
18
|
+
import { m as readWorkspacePlanSync, o as init_io } from "./io-DQR9PMgS.js";
|
|
19
|
+
import { f as init_config, m as loadConfigSync$1, p as loadConfig$1 } from "./config-q4Gvd8dq.js";
|
|
20
|
+
import { T as stampBootReconciliation, h as setBootReconciliationDecision, l as isDeaconGloballyPaused, r as getBootReconciliationState, s as init_control_settings } from "./control-settings-D_odMIaC.js";
|
|
21
|
+
import { c as init_docker_stats, s as DockerStatsCollector } from "./stack-health-C-ifC7b0.js";
|
|
22
|
+
import { l as init_dag, o as getDispatchableItems } from "./dag-CJpgf9A3.js";
|
|
23
|
+
import { a as loadCloisterConfigSync, i as loadCloisterConfig, r as init_config$1 } from "./config-DeTsoZdR.js";
|
|
24
|
+
import { a as findRecreatedLegacyStatePaths, o as init_state_home } from "./state-home-CONQvZR0.js";
|
|
25
|
+
import { a as isAgentIdleForNudge, t as checkStuckAgentRemediation } from "./stuck-remediation-CKnIryGT.js";
|
|
26
|
+
import { n as __filename, r as init_esm_shims } from "./esm-shims-dTeNdq7X.js";
|
|
27
|
+
import { i as init_staleness, r as computeBuildStaleness } from "./staleness-BID1BKdr.js";
|
|
28
|
+
import { a as pidsWithCwdUnder, i as sweepAutoCloseOutCache, n as pruneTerminalStoppedAgents, r as getAutoCloseOutCanonicalState } from "./agent-gc-Dj2gncak.js";
|
|
29
|
+
import { a as writeFeedbackFile, i as init_feedback_writer } from "./feedback-writer-BXP6g75N.js";
|
|
30
|
+
import { r as surfaceIssueFeedbackNeedsYou, t as init_feedback_target } from "./feedback-target-DZ-iAnAa.js";
|
|
31
|
+
import { a as init_review_convoy_liveness, c as init_review_monitor, i as evaluateReviewConvoyLiveness, o as reviewTimestampMs, r as init_in_flight_guard, s as REVIEW_SUB_ROLES, t as createInFlightGuard } from "./in-flight-guard-BoWm66Kh.js";
|
|
32
|
+
import { H as getTmuxSessionName, J as parseReviewerSessionName, _ as getAllProjectSpecialistStatuses, t as init_specialists } from "./specialists-CwZHb5cb.js";
|
|
33
|
+
import { a as inferBranchFromWorkspace, i as findWorkspacePath, o as init_archive_planning } from "./archive-planning-BvDuWNMo.js";
|
|
34
|
+
import { A as withConcurrencyLimit, k as init_concurrency$1 } from "./github-app-CDPtGF7J.js";
|
|
35
|
+
import { n as init_issue_closed, r as isIssueClosed } from "./issue-closed-DtmJM0D0.js";
|
|
36
|
+
import { n as shouldSkipDispatchAsMerged, t as init_merge_verification } from "./merge-verification-CqnUzGEK.js";
|
|
37
|
+
import { n as init_review_verdict_feedback, t as deliverReviewVerdictFeedback } from "./review-verdict-feedback-CpUZl5aE.js";
|
|
38
|
+
import { n as reconcileTraefikNetworks, t as init_traefik_connect } from "./traefik-connect-C6mJckNs.js";
|
|
39
|
+
import { g as decideAgentAutonomousRedrive, r as coordinateSwarmSlots, y as listFeatureWorkspaces } from "./deacon-swarm-BryRr6AO.js";
|
|
40
|
+
import { t as recordRecoveryFailure } from "./recovery-trip-DkzJSej9.js";
|
|
41
|
+
import { n as isExplicitNoResumeRequest, t as init_no_resume_mode } from "./no-resume-mode-BWOSZjWd.js";
|
|
42
|
+
import { n as reconcileClosedIssueAgents } from "./closed-issue-reaper-CQ3kqha7.js";
|
|
43
|
+
import { n as init_label_reconciler, r as reconcilePipelineLabelsPatrol } from "./label-reconciler-Df1ZduPH.js";
|
|
44
|
+
import { a as spawnWorkAgentThroughAgentsEndpoint, i as reconcileOrphanProposedSpecs, o as triggerRebuildAndStart } from "./orphan-proposed-reconciler-xklgvNA7.js";
|
|
45
|
+
import { n as reconcileIdleWorkspaceStacks } from "./idle-stack-reaper-Yf34xXxY.js";
|
|
46
|
+
import { i as readTestVerdictArtifact, n as decideUnsignaledTestAction, r as init_test_verdict } from "./test-verdict-Cp5tljlJ.js";
|
|
45
47
|
import { createRequire } from "node:module";
|
|
46
48
|
import { join } from "node:path";
|
|
47
49
|
import { Effect } from "effect";
|
|
@@ -50,13 +52,128 @@ import { dirname as dirname$1, join as join$1 } from "path";
|
|
|
50
52
|
import { cpus, loadavg } from "os";
|
|
51
53
|
import { cpus as cpus$1, freemem as freemem$1, homedir as homedir$1, loadavg as loadavg$1, platform as platform$1, totalmem as totalmem$1 } from "node:os";
|
|
52
54
|
import { closeSync as closeSync$1, existsSync as existsSync$1, openSync as openSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, unlinkSync as unlinkSync$1, writeFileSync as writeFileSync$1 } from "node:fs";
|
|
53
|
-
import {
|
|
55
|
+
import { readFile } from "node:fs/promises";
|
|
54
56
|
import { readFile as readFile$1, readdir as readdir$1, writeFile as writeFile$1 } from "fs/promises";
|
|
55
57
|
import { exec, execFile, spawn } from "node:child_process";
|
|
56
58
|
import { promisify } from "node:util";
|
|
57
59
|
import { exec as exec$1, execFile as execFile$1, spawn as spawn$1 } from "child_process";
|
|
58
60
|
import { promisify as promisify$1 } from "util";
|
|
59
61
|
import { layer } from "@effect/platform-node/NodeServices";
|
|
62
|
+
//#region ../../lib/agents/health.ts
|
|
63
|
+
init_paths();
|
|
64
|
+
init_errors();
|
|
65
|
+
init_activity_logger();
|
|
66
|
+
init_projects();
|
|
67
|
+
init_state_plane();
|
|
68
|
+
init_auto_commit();
|
|
69
|
+
init_record();
|
|
70
|
+
init_record_update();
|
|
71
|
+
init_tmux();
|
|
72
|
+
init_src();
|
|
73
|
+
init_agents();
|
|
74
|
+
init_agent_runtime_mirror();
|
|
75
|
+
init_persistent_logger();
|
|
76
|
+
init_internal_token();
|
|
77
|
+
init_review_status_sync();
|
|
78
|
+
init_review_status_source();
|
|
79
|
+
init_review_dispatch_decision();
|
|
80
|
+
init_review_status();
|
|
81
|
+
init_codex_auth();
|
|
82
|
+
init_runtime_state();
|
|
83
|
+
init_agent_state();
|
|
84
|
+
init_transcript_landing();
|
|
85
|
+
init_config$1();
|
|
86
|
+
init_memory_verdict_cache();
|
|
87
|
+
init_concurrency();
|
|
88
|
+
init_termination();
|
|
89
|
+
init_messaging();
|
|
90
|
+
init_context_overflow();
|
|
91
|
+
init_agents$1();
|
|
92
|
+
init_queries();
|
|
93
|
+
const STARTUP_GRACE_MS = 300 * 1e3;
|
|
94
|
+
const ACTIVITY_WARNING_MS = 900 * 1e3;
|
|
95
|
+
const ACTIVITY_STALLED_MS = 1800 * 1e3;
|
|
96
|
+
function reason$1(code, severity, message) {
|
|
97
|
+
return {
|
|
98
|
+
code,
|
|
99
|
+
domain: "agent",
|
|
100
|
+
severity,
|
|
101
|
+
message
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function validTimestamp(value) {
|
|
105
|
+
if (!value) return null;
|
|
106
|
+
const timestamp = Date.parse(value);
|
|
107
|
+
return Number.isFinite(timestamp) ? timestamp : null;
|
|
108
|
+
}
|
|
109
|
+
function latestActivity(persisted, runtime) {
|
|
110
|
+
const candidates = [persisted.lastActivity, runtime?.lastActivity].map((value) => ({
|
|
111
|
+
value,
|
|
112
|
+
timestamp: validTimestamp(value)
|
|
113
|
+
})).filter((entry) => entry.value !== void 0 && entry.timestamp !== null);
|
|
114
|
+
if (candidates.length === 0) return void 0;
|
|
115
|
+
return candidates.reduce((latest, entry) => entry.timestamp > latest.timestamp ? entry : latest).value;
|
|
116
|
+
}
|
|
117
|
+
function agentKind(role) {
|
|
118
|
+
if (role === "work") return "work";
|
|
119
|
+
if (role === "plan") return "planning";
|
|
120
|
+
if (role === "review" || role === "test" || role === "ship") return "specialist";
|
|
121
|
+
return "other";
|
|
122
|
+
}
|
|
123
|
+
function intentionalInactive(state) {
|
|
124
|
+
return state.status === "stopped" || state.status === "completed" || state.paused === true || state.stoppedByUser === true || state.stoppedByPause === true;
|
|
125
|
+
}
|
|
126
|
+
function lifecycleFor(input, state) {
|
|
127
|
+
if (input.reviewLifecycle === "warm" || input.reviewLifecycle === "orphaned") return input.reviewLifecycle;
|
|
128
|
+
if (input.liveSessions.has(input.agentId) && !intentionalInactive(state)) return "active";
|
|
129
|
+
return input.reviewLifecycle ?? "unknown";
|
|
130
|
+
}
|
|
131
|
+
function buildSnapshot(input, state, status, reasons) {
|
|
132
|
+
const lastActivityAt = latestActivity(state, input.runtime);
|
|
133
|
+
const observations = input.observations;
|
|
134
|
+
return {
|
|
135
|
+
id: input.agentId,
|
|
136
|
+
...state.issueId ? { issueId: state.issueId } : {},
|
|
137
|
+
...state.role ? { role: state.role } : {},
|
|
138
|
+
kind: agentKind(state.role),
|
|
139
|
+
status,
|
|
140
|
+
lifecycle: lifecycleFor(input, state),
|
|
141
|
+
tmuxActive: input.liveSessions.has(input.agentId),
|
|
142
|
+
...lastActivityAt ? { lastActivityAt } : {},
|
|
143
|
+
...observations?.consecutiveFailures !== void 0 ? { consecutiveFailures: observations.consecutiveFailures } : state.consecutiveFailures !== void 0 ? { consecutiveFailures: state.consecutiveFailures } : {},
|
|
144
|
+
...observations?.killCount !== void 0 ? { killCount: observations.killCount } : {},
|
|
145
|
+
...observations && Object.prototype.hasOwnProperty.call(observations, "contextPercent") ? { contextPercent: observations.contextPercent ?? null } : {},
|
|
146
|
+
reasons
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Classifies one resolved agent snapshot. The function is intentionally free of
|
|
151
|
+
* filesystem, tmux, review-status, and runtime-store imports so every caller
|
|
152
|
+
* supplies one coherent set of evidence and cycle-prone dashboard code remains
|
|
153
|
+
* a thin resolver adapter.
|
|
154
|
+
*/
|
|
155
|
+
function classifyAgentHealth(input) {
|
|
156
|
+
if (input.persisted.status === "unavailable") return buildSnapshot(input, {}, "unavailable", [reason$1("agent.persisted_state.unavailable", "warning", input.persisted.reason)]);
|
|
157
|
+
const state = input.persisted.value;
|
|
158
|
+
if (input.runtime?.contextSaturatedAt) return buildSnapshot(input, state, "wedged", [reason$1("agent.context.saturated", "critical", "Context window exhausted; recovery is required.")]);
|
|
159
|
+
const startedAt = validTimestamp(state.startedAt);
|
|
160
|
+
const startupGraceElapsed = startedAt !== null && input.nowMs - startedAt >= STARTUP_GRACE_MS;
|
|
161
|
+
const expectsLiveSession = state.status === "running" || state.status === "starting";
|
|
162
|
+
if (!input.liveSessions.has(input.agentId) && expectsLiveSession && startupGraceElapsed) return buildSnapshot(input, state, "dead", [reason$1("agent.tmux.missing", "critical", "The persisted agent is running but its tmux session is missing.")]);
|
|
163
|
+
if (state.role === "work" && state.status === "running" && state.kickoffDelivered === false && startupGraceElapsed) return buildSnapshot(input, state, "stalled", [reason$1("agent.kickoff.not_delivered", "warning", "Work agent running with no kickoff delivered since spawn")]);
|
|
164
|
+
if (input.runtime?.state === "waiting-on-human") return buildSnapshot(input, state, "waiting", [reason$1("agent.runtime.waiting_on_human", "info", "The agent is waiting for operator input.")]);
|
|
165
|
+
if (input.reviewLifecycle === "warm" || input.reviewLifecycle === "orphaned" || input.runtime?.state === "idle" || input.runtime?.state === "suspended" || input.runtime?.state === "stopped" || intentionalInactive(state)) return buildSnapshot(input, state, "idle", []);
|
|
166
|
+
if (input.runtime?.state === "active") {
|
|
167
|
+
const lastActivityMs = validTimestamp(latestActivity(state, input.runtime));
|
|
168
|
+
if (lastActivityMs !== null) {
|
|
169
|
+
const inactivityMs = Math.max(0, input.nowMs - lastActivityMs);
|
|
170
|
+
if (inactivityMs >= ACTIVITY_STALLED_MS) return buildSnapshot(input, state, "stalled", [reason$1("agent.runtime.inactive.stalled", "warning", `The active agent has produced no activity for ${Math.round(inactivityMs / 6e4)} minutes.`)]);
|
|
171
|
+
if (inactivityMs >= ACTIVITY_WARNING_MS) return buildSnapshot(input, state, "warning", [reason$1("agent.runtime.inactive.warning", "warning", `The active agent has produced no activity for ${Math.round(inactivityMs / 6e4)} minutes.`)]);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return buildSnapshot(input, state, "healthy", []);
|
|
175
|
+
}
|
|
176
|
+
//#endregion
|
|
60
177
|
//#region ../../../node_modules/.bun/undici@7.25.0/node_modules/undici/lib/core/symbols.js
|
|
61
178
|
var require_symbols = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
62
179
|
module.exports = {
|
|
@@ -21468,9 +21585,7 @@ var require_eventsource = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
21468
21585
|
defaultReconnectionTime
|
|
21469
21586
|
};
|
|
21470
21587
|
}));
|
|
21471
|
-
|
|
21472
|
-
//#region ../../../node_modules/.bun/undici@7.25.0/node_modules/undici/index.js
|
|
21473
|
-
var require_undici = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
21588
|
+
new ((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
21474
21589
|
init_esm_shims();
|
|
21475
21590
|
const Client = require_client();
|
|
21476
21591
|
const Dispatcher = require_dispatcher();
|
|
@@ -21636,37 +21751,7 @@ var require_undici = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
21636
21751
|
globalThis.EventSource = module.exports.EventSource;
|
|
21637
21752
|
}
|
|
21638
21753
|
module.exports.install = install;
|
|
21639
|
-
}));
|
|
21640
|
-
//#endregion
|
|
21641
|
-
//#region ../../../node_modules/.bun/smee-client@5.0.0/node_modules/smee-client/index.js
|
|
21642
|
-
init_paths();
|
|
21643
|
-
init_errors();
|
|
21644
|
-
init_activity_logger();
|
|
21645
|
-
init_projects();
|
|
21646
|
-
init_state_plane();
|
|
21647
|
-
init_auto_commit();
|
|
21648
|
-
init_record();
|
|
21649
|
-
init_record_update();
|
|
21650
|
-
init_tmux();
|
|
21651
|
-
init_agents();
|
|
21652
|
-
init_persistent_logger();
|
|
21653
|
-
init_internal_token();
|
|
21654
|
-
init_review_status_sync();
|
|
21655
|
-
init_review_dispatch_decision();
|
|
21656
|
-
init_review_status();
|
|
21657
|
-
init_codex_auth();
|
|
21658
|
-
init_runtime_state();
|
|
21659
|
-
init_agent_state();
|
|
21660
|
-
init_transcript_landing();
|
|
21661
|
-
init_config$1();
|
|
21662
|
-
init_memory_verdict_cache();
|
|
21663
|
-
init_concurrency();
|
|
21664
|
-
init_termination();
|
|
21665
|
-
init_messaging();
|
|
21666
|
-
init_context_overflow();
|
|
21667
|
-
init_agents$1();
|
|
21668
|
-
init_queries();
|
|
21669
|
-
new (require_undici()).EnvHttpProxyAgent();
|
|
21754
|
+
})))()).EnvHttpProxyAgent();
|
|
21670
21755
|
//#endregion
|
|
21671
21756
|
//#region ../../lib/smee.ts
|
|
21672
21757
|
/**
|
|
@@ -21849,35 +21934,881 @@ function startSmeeProcessSync() {
|
|
|
21849
21934
|
console.log(`[smee] Started process (PID ${child.pid}) relaying to ${target}`);
|
|
21850
21935
|
}
|
|
21851
21936
|
//#endregion
|
|
21852
|
-
//#region
|
|
21853
|
-
init_docker_stats();
|
|
21937
|
+
//#region ../../lib/system-health/config.ts
|
|
21854
21938
|
init_build_info();
|
|
21855
|
-
|
|
21939
|
+
init_docker_stats();
|
|
21940
|
+
init_defaults();
|
|
21941
|
+
init_load();
|
|
21942
|
+
const GIB$2 = 1024 ** 3;
|
|
21943
|
+
const SYSTEM_HEALTH_DEFAULTS = Object.freeze({
|
|
21944
|
+
pollSeconds: 15,
|
|
21945
|
+
memoryWarnGb: DEFAULT_CONFIG$1.resources.memoryWarnGb,
|
|
21946
|
+
memoryBlockGb: DEFAULT_CONFIG$1.resources.memoryBlockGb,
|
|
21947
|
+
agentWarnCount: DEFAULT_CONFIG$1.resources.agentWarnCount,
|
|
21948
|
+
agentBlockCount: DEFAULT_CONFIG$1.resources.agentBlockCount,
|
|
21949
|
+
swapUsedWarningPercent: 20,
|
|
21950
|
+
swapUsedCriticalPercent: 50,
|
|
21951
|
+
cpuLoadWarningPerCore: 1,
|
|
21952
|
+
cpuLoadCriticalPerCore: 1.5,
|
|
21953
|
+
overcommitWarningPercent: 150,
|
|
21954
|
+
overcommitCriticalPercent: 200
|
|
21955
|
+
});
|
|
21956
|
+
function finiteNonnegative(value) {
|
|
21957
|
+
if (value === "" || value == null) return null;
|
|
21958
|
+
const parsed = typeof value === "number" ? value : Number(value);
|
|
21959
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;
|
|
21960
|
+
}
|
|
21961
|
+
/**
|
|
21962
|
+
* Normalizes every health threshold in one pass. Any invalid value or reversed
|
|
21963
|
+
* pair falls back to its named defaults, and the caller receives one warning
|
|
21964
|
+
* describing the complete fallback rather than one warning per field.
|
|
21965
|
+
*/
|
|
21966
|
+
function normalizeSystemHealthThresholds(input, warn = console.warn) {
|
|
21967
|
+
const invalid = [];
|
|
21968
|
+
const scalar = (name, fallback, minimum = 0) => {
|
|
21969
|
+
const value = finiteNonnegative(input[name]);
|
|
21970
|
+
if (value == null || value < minimum) {
|
|
21971
|
+
invalid.push(String(name));
|
|
21972
|
+
return fallback;
|
|
21973
|
+
}
|
|
21974
|
+
return value;
|
|
21975
|
+
};
|
|
21976
|
+
const increasingPair = (warningName, criticalName, warningDefault, criticalDefault) => {
|
|
21977
|
+
const warning = finiteNonnegative(input[warningName]);
|
|
21978
|
+
const critical = finiteNonnegative(input[criticalName]);
|
|
21979
|
+
if (warning == null || critical == null || warning > critical) {
|
|
21980
|
+
invalid.push(`${String(warningName)}/${String(criticalName)}`);
|
|
21981
|
+
return [warningDefault, criticalDefault];
|
|
21982
|
+
}
|
|
21983
|
+
return [warning, critical];
|
|
21984
|
+
};
|
|
21985
|
+
const decreasingPair = (warningName, criticalName, warningDefault, criticalDefault) => {
|
|
21986
|
+
const warning = finiteNonnegative(input[warningName]);
|
|
21987
|
+
const critical = finiteNonnegative(input[criticalName]);
|
|
21988
|
+
if (warning == null || critical == null || warning < critical) {
|
|
21989
|
+
invalid.push(`${String(warningName)}/${String(criticalName)}`);
|
|
21990
|
+
return [warningDefault, criticalDefault];
|
|
21991
|
+
}
|
|
21992
|
+
return [warning, critical];
|
|
21993
|
+
};
|
|
21994
|
+
const [memoryWarnGb, memoryBlockGb] = decreasingPair("memoryWarnGb", "memoryBlockGb", SYSTEM_HEALTH_DEFAULTS.memoryWarnGb, SYSTEM_HEALTH_DEFAULTS.memoryBlockGb);
|
|
21995
|
+
const [agentWarnCountValue, agentBlockCountValue] = increasingPair("agentWarnCount", "agentBlockCount", SYSTEM_HEALTH_DEFAULTS.agentWarnCount, SYSTEM_HEALTH_DEFAULTS.agentBlockCount);
|
|
21996
|
+
const [swapUsedWarningPercent, swapUsedCriticalPercent] = increasingPair("swapUsedWarningPercent", "swapUsedCriticalPercent", SYSTEM_HEALTH_DEFAULTS.swapUsedWarningPercent, SYSTEM_HEALTH_DEFAULTS.swapUsedCriticalPercent);
|
|
21997
|
+
const [cpuLoadWarningPerCore, cpuLoadCriticalPerCore] = increasingPair("cpuLoadWarningPerCore", "cpuLoadCriticalPerCore", SYSTEM_HEALTH_DEFAULTS.cpuLoadWarningPerCore, SYSTEM_HEALTH_DEFAULTS.cpuLoadCriticalPerCore);
|
|
21998
|
+
const [overcommitWarningPercent, overcommitCriticalPercent] = increasingPair("overcommitWarningPercent", "overcommitCriticalPercent", SYSTEM_HEALTH_DEFAULTS.overcommitWarningPercent, SYSTEM_HEALTH_DEFAULTS.overcommitCriticalPercent);
|
|
21999
|
+
const pollSeconds = scalar("pollSeconds", SYSTEM_HEALTH_DEFAULTS.pollSeconds, 1);
|
|
22000
|
+
const agentWarnCount = Math.max(1, Math.floor(agentWarnCountValue));
|
|
22001
|
+
const agentBlockCount = Math.max(1, Math.floor(agentBlockCountValue));
|
|
22002
|
+
if (invalid.length > 0) warn(`[system-health] Invalid thresholds (${invalid.join(", ")}); using named defaults.`);
|
|
22003
|
+
return {
|
|
22004
|
+
pollSeconds: Math.max(1, Math.floor(pollSeconds)),
|
|
22005
|
+
resources: {
|
|
22006
|
+
memoryWarnGb,
|
|
22007
|
+
memoryBlockGb,
|
|
22008
|
+
agentWarnCount,
|
|
22009
|
+
agentBlockCount
|
|
22010
|
+
},
|
|
22011
|
+
thresholds: {
|
|
22012
|
+
memoryAvailableWarningBytes: memoryWarnGb * GIB$2,
|
|
22013
|
+
memoryAvailableCriticalBytes: memoryBlockGb * GIB$2,
|
|
22014
|
+
swapUsedWarningPercent,
|
|
22015
|
+
swapUsedCriticalPercent,
|
|
22016
|
+
cpuLoadWarningPerCore,
|
|
22017
|
+
cpuLoadCriticalPerCore,
|
|
22018
|
+
overcommitWarningPercent,
|
|
22019
|
+
overcommitCriticalPercent
|
|
22020
|
+
}
|
|
22021
|
+
};
|
|
22022
|
+
}
|
|
22023
|
+
function resolveSystemHealthConfig(options = {}) {
|
|
22024
|
+
const resources = options.resources ?? loadConfigSync().config.resources;
|
|
22025
|
+
const env = options.env ?? process.env;
|
|
22026
|
+
return normalizeSystemHealthThresholds({
|
|
22027
|
+
pollSeconds: env["PAN_HEALTH_POLL_SECONDS"] ?? SYSTEM_HEALTH_DEFAULTS.pollSeconds,
|
|
22028
|
+
memoryWarnGb: env["PAN_MEMORY_WARN_GB"] ?? resources.memoryWarnGb,
|
|
22029
|
+
memoryBlockGb: env["PAN_MEMORY_BLOCK_GB"] ?? resources.memoryBlockGb,
|
|
22030
|
+
agentWarnCount: env["PAN_AGENT_WARN_COUNT"] ?? resources.agentWarnCount,
|
|
22031
|
+
agentBlockCount: env["PAN_AGENT_BLOCK_COUNT"] ?? resources.agentBlockCount,
|
|
22032
|
+
swapUsedWarningPercent: env["PAN_HEALTH_SWAP_WARN_PERCENT"] ?? SYSTEM_HEALTH_DEFAULTS.swapUsedWarningPercent,
|
|
22033
|
+
swapUsedCriticalPercent: env["PAN_HEALTH_SWAP_CRITICAL_PERCENT"] ?? SYSTEM_HEALTH_DEFAULTS.swapUsedCriticalPercent,
|
|
22034
|
+
cpuLoadWarningPerCore: env["PAN_HEALTH_LOAD_WARN_PER_CORE"] ?? SYSTEM_HEALTH_DEFAULTS.cpuLoadWarningPerCore,
|
|
22035
|
+
cpuLoadCriticalPerCore: env["PAN_HEALTH_LOAD_CRITICAL_PER_CORE"] ?? SYSTEM_HEALTH_DEFAULTS.cpuLoadCriticalPerCore,
|
|
22036
|
+
overcommitWarningPercent: env["PAN_HEALTH_OVERCOMMIT_WARN_PERCENT"] ?? SYSTEM_HEALTH_DEFAULTS.overcommitWarningPercent,
|
|
22037
|
+
overcommitCriticalPercent: env["PAN_HEALTH_OVERCOMMIT_CRITICAL_PERCENT"] ?? SYSTEM_HEALTH_DEFAULTS.overcommitCriticalPercent
|
|
22038
|
+
}, options.warn);
|
|
22039
|
+
}
|
|
22040
|
+
//#endregion
|
|
22041
|
+
//#region ../../lib/system-health/types.ts
|
|
22042
|
+
function available(value) {
|
|
22043
|
+
return {
|
|
22044
|
+
status: "available",
|
|
22045
|
+
value
|
|
22046
|
+
};
|
|
22047
|
+
}
|
|
22048
|
+
function unavailable(reason) {
|
|
22049
|
+
return {
|
|
22050
|
+
status: "unavailable",
|
|
22051
|
+
reason
|
|
22052
|
+
};
|
|
22053
|
+
}
|
|
22054
|
+
//#endregion
|
|
22055
|
+
//#region ../../lib/system-health/darwin.ts
|
|
22056
|
+
const execFileAsync$8 = promisify(execFile);
|
|
22057
|
+
const COMMAND_TIMEOUT_MS = 5e3;
|
|
22058
|
+
const MIB = 1024 ** 2;
|
|
22059
|
+
const DARWIN_MEMORY_PRESSURE_DEFAULTS = Object.freeze({
|
|
22060
|
+
warningFreePercent: 10,
|
|
22061
|
+
criticalFreePercent: 5,
|
|
22062
|
+
swapActivityWarningBytesPerMinute: 64 * MIB,
|
|
22063
|
+
swapActivityCriticalBytesPerMinute: 256 * MIB
|
|
22064
|
+
});
|
|
22065
|
+
function parseDarwinMemoryPressure(content) {
|
|
22066
|
+
for (const pattern of [/System-wide memory free percentage:\s*([\d.]+)\s*%/i, /System-wide memory free percentage\s*=\s*([\d.]+)\s*%?/i]) {
|
|
22067
|
+
const match = content.match(pattern);
|
|
22068
|
+
if (!match) continue;
|
|
22069
|
+
const value = Number(match[1]);
|
|
22070
|
+
if (Number.isFinite(value) && value >= 0 && value <= 100) return value;
|
|
22071
|
+
}
|
|
22072
|
+
return null;
|
|
22073
|
+
}
|
|
22074
|
+
function parseDarwinVmStat(content) {
|
|
22075
|
+
const pageSizeMatch = content.match(/page size of\s+(\d+)\s+bytes/i);
|
|
22076
|
+
if (!pageSizeMatch) return null;
|
|
22077
|
+
const pageSizeBytes = Number(pageSizeMatch[1]);
|
|
22078
|
+
if (!Number.isFinite(pageSizeBytes) || pageSizeBytes <= 0) return null;
|
|
22079
|
+
const pages = /* @__PURE__ */ new Map();
|
|
22080
|
+
for (const line of content.split("\n")) {
|
|
22081
|
+
const match = line.match(/^([^:]+):\s+(\d+)\.?$/);
|
|
22082
|
+
if (!match) continue;
|
|
22083
|
+
const value = Number(match[2]);
|
|
22084
|
+
if (Number.isFinite(value)) pages.set(match[1].trim(), value);
|
|
22085
|
+
}
|
|
22086
|
+
const availablePageNames = [
|
|
22087
|
+
"Pages free",
|
|
22088
|
+
"Pages inactive",
|
|
22089
|
+
"Pages speculative"
|
|
22090
|
+
];
|
|
22091
|
+
const availablePages = availablePageNames.every((name) => pages.has(name)) ? availablePageNames.reduce((sum, name) => sum + pages.get(name), 0) : void 0;
|
|
22092
|
+
const swapIn = pages.get("Swapins");
|
|
22093
|
+
const swapOut = pages.get("Swapouts");
|
|
22094
|
+
return {
|
|
22095
|
+
pageSizeBytes,
|
|
22096
|
+
availableMemoryBytes: availablePages == null ? void 0 : availablePages * pageSizeBytes,
|
|
22097
|
+
swap: swapIn == null || swapOut == null ? void 0 : {
|
|
22098
|
+
pagesIn: swapIn,
|
|
22099
|
+
pagesOut: swapOut
|
|
22100
|
+
}
|
|
22101
|
+
};
|
|
22102
|
+
}
|
|
22103
|
+
function unitBytes(value, unit) {
|
|
22104
|
+
const parsed = Number(value);
|
|
22105
|
+
if (!Number.isFinite(parsed) || parsed < 0) return null;
|
|
22106
|
+
const multiplier = unit.toUpperCase() === "G" ? 1024 ** 3 : unit.toUpperCase() === "K" ? 1024 : MIB;
|
|
22107
|
+
return Math.round(parsed * multiplier);
|
|
22108
|
+
}
|
|
22109
|
+
function parseDarwinSwapUsage(content) {
|
|
22110
|
+
const total = content.match(/total\s*=\s*([\d.]+)([KMG])/i);
|
|
22111
|
+
const used = content.match(/used\s*=\s*([\d.]+)([KMG])/i);
|
|
22112
|
+
const free = content.match(/free\s*=\s*([\d.]+)([KMG])/i);
|
|
22113
|
+
if (!total || !used || !free) return null;
|
|
22114
|
+
const totalBytes = unitBytes(total[1], total[2]);
|
|
22115
|
+
const usedBytes = unitBytes(used[1], used[2]);
|
|
22116
|
+
const freeBytes = unitBytes(free[1], free[2]);
|
|
22117
|
+
return totalBytes == null || usedBytes == null || freeBytes == null ? null : {
|
|
22118
|
+
totalBytes,
|
|
22119
|
+
usedBytes,
|
|
22120
|
+
freeBytes
|
|
22121
|
+
};
|
|
22122
|
+
}
|
|
22123
|
+
function aggregateDarwinCpuCounters(cpuInfo) {
|
|
22124
|
+
if (cpuInfo.length === 0) return null;
|
|
22125
|
+
let idle = 0;
|
|
22126
|
+
let total = 0;
|
|
22127
|
+
for (const cpu of cpuInfo) {
|
|
22128
|
+
const values = Object.values(cpu.times);
|
|
22129
|
+
if (values.some((value) => !Number.isFinite(value) || value < 0)) return null;
|
|
22130
|
+
idle += cpu.times.idle;
|
|
22131
|
+
total += values.reduce((sum, value) => sum + value, 0);
|
|
22132
|
+
}
|
|
22133
|
+
return {
|
|
22134
|
+
idle,
|
|
22135
|
+
total
|
|
22136
|
+
};
|
|
22137
|
+
}
|
|
22138
|
+
function computeCpuPercent$1(current, previous) {
|
|
22139
|
+
if (!previous) return unavailable("A previous CPU time sample is required.");
|
|
22140
|
+
const totalDelta = current.total - previous.total;
|
|
22141
|
+
const idleDelta = current.idle - previous.idle;
|
|
22142
|
+
if (totalDelta <= 0 || idleDelta < 0 || idleDelta > totalDelta) return unavailable("CPU times did not advance monotonically.");
|
|
22143
|
+
return available(Math.round((totalDelta - idleDelta) / totalDelta * 1e3) / 10);
|
|
22144
|
+
}
|
|
22145
|
+
function computeSwapActivity(current, previous, elapsedMs, pageSizeBytes) {
|
|
22146
|
+
if (!previous) return unavailable("A previous swap counter sample is required.");
|
|
22147
|
+
const pages = current.pagesIn - previous.pagesIn + current.pagesOut - previous.pagesOut;
|
|
22148
|
+
if (pages < 0 || elapsedMs <= 0) return unavailable("Swap counters or sample timing were invalid.");
|
|
22149
|
+
return available(Math.round(pages * pageSizeBytes * 6e4 / elapsedMs));
|
|
22150
|
+
}
|
|
22151
|
+
function percent$1(part, total) {
|
|
22152
|
+
if (total <= 0) return 0;
|
|
22153
|
+
return Math.round(part / total * 1e3) / 10;
|
|
22154
|
+
}
|
|
22155
|
+
const defaultAdapters$1 = {
|
|
22156
|
+
execFile: async (command, args, timeoutMs) => {
|
|
22157
|
+
const { stdout } = await execFileAsync$8(command, [...args], {
|
|
22158
|
+
encoding: "utf-8",
|
|
22159
|
+
timeout: timeoutMs
|
|
22160
|
+
});
|
|
22161
|
+
return stdout;
|
|
22162
|
+
},
|
|
22163
|
+
cpus: cpus$1,
|
|
22164
|
+
loadAverage1m: () => loadavg$1()[0] ?? 0,
|
|
22165
|
+
totalMemoryBytes: totalmem$1,
|
|
22166
|
+
now: () => Date.now()
|
|
22167
|
+
};
|
|
22168
|
+
async function command(adapters, executable, args) {
|
|
22169
|
+
try {
|
|
22170
|
+
return await adapters.execFile(executable, args, COMMAND_TIMEOUT_MS);
|
|
22171
|
+
} catch {
|
|
22172
|
+
return null;
|
|
22173
|
+
}
|
|
22174
|
+
}
|
|
22175
|
+
function createDarwinHostHealthCollector(adapters = defaultAdapters$1) {
|
|
22176
|
+
return {
|
|
22177
|
+
platform: "darwin",
|
|
22178
|
+
async sample(previous) {
|
|
22179
|
+
const sampledAtMs = adapters.now();
|
|
22180
|
+
const [pressureOutput, vmStatOutput, swapOutput] = await Promise.all([
|
|
22181
|
+
command(adapters, "memory_pressure", ["-Q"]),
|
|
22182
|
+
command(adapters, "vm_stat", []),
|
|
22183
|
+
command(adapters, "sysctl", ["-n", "vm.swapusage"])
|
|
22184
|
+
]);
|
|
22185
|
+
const pressureFreePercent = pressureOutput == null ? null : parseDarwinMemoryPressure(pressureOutput);
|
|
22186
|
+
const vmStat = vmStatOutput == null ? null : parseDarwinVmStat(vmStatOutput);
|
|
22187
|
+
const swapUsage = swapOutput == null ? null : parseDarwinSwapUsage(swapOutput);
|
|
22188
|
+
const cpuInfo = adapters.cpus();
|
|
22189
|
+
const cpuCounters = aggregateDarwinCpuCounters(cpuInfo);
|
|
22190
|
+
const totalMemoryBytes = adapters.totalMemoryBytes();
|
|
22191
|
+
const availableMemoryBytes = pressureFreePercent != null ? Math.round(totalMemoryBytes * pressureFreePercent / 100) : vmStat?.availableMemoryBytes ?? null;
|
|
22192
|
+
const usedMemoryBytes = Number.isFinite(totalMemoryBytes) && availableMemoryBytes != null ? Math.max(totalMemoryBytes - availableMemoryBytes, 0) : null;
|
|
22193
|
+
const loadAverage1m = adapters.loadAverage1m();
|
|
22194
|
+
const elapsedMs = previous ? sampledAtMs - previous.sampledAtMs : 0;
|
|
22195
|
+
return {
|
|
22196
|
+
platform: "darwin",
|
|
22197
|
+
sampledAtMs,
|
|
22198
|
+
cpuPercent: cpuCounters ? computeCpuPercent$1(cpuCounters, previous?.counters.cpu) : unavailable("macOS CPU times are unavailable."),
|
|
22199
|
+
loadAverage1m: Number.isFinite(loadAverage1m) && loadAverage1m >= 0 ? available(loadAverage1m) : unavailable("The one-minute load average is unavailable."),
|
|
22200
|
+
loadPerCore1m: Number.isFinite(loadAverage1m) && loadAverage1m >= 0 && cpuInfo.length > 0 ? available(Math.round(loadAverage1m / cpuInfo.length * 100) / 100) : unavailable("Load average or CPU core count is unavailable."),
|
|
22201
|
+
totalMemoryBytes: Number.isFinite(totalMemoryBytes) && totalMemoryBytes > 0 ? available(totalMemoryBytes) : unavailable("Total memory is unavailable."),
|
|
22202
|
+
usedMemoryBytes: usedMemoryBytes == null ? unavailable("Used memory cannot be derived.") : available(usedMemoryBytes),
|
|
22203
|
+
availableMemoryBytes: availableMemoryBytes == null ? unavailable("Available memory is unavailable.") : available(availableMemoryBytes),
|
|
22204
|
+
memoryUsedPercent: usedMemoryBytes == null ? unavailable("Memory utilization cannot be derived.") : available(percent$1(usedMemoryBytes, totalMemoryBytes)),
|
|
22205
|
+
memoryPressureSomeAvg10: unavailable("macOS does not expose Linux memory PSI."),
|
|
22206
|
+
memoryPressureFullAvg10: unavailable("macOS does not expose Linux memory PSI."),
|
|
22207
|
+
memoryPressureFreePercent: pressureFreePercent == null ? unavailable("memory_pressure did not report a recognized free percentage.") : available(pressureFreePercent),
|
|
22208
|
+
swapTotalBytes: swapUsage ? available(swapUsage.totalBytes) : unavailable("vm.swapusage is unavailable."),
|
|
22209
|
+
swapUsedBytes: swapUsage ? available(swapUsage.usedBytes) : unavailable("vm.swapusage is unavailable."),
|
|
22210
|
+
swapUsedPercent: swapUsage ? available(percent$1(swapUsage.usedBytes, swapUsage.totalBytes)) : unavailable("vm.swapusage is unavailable."),
|
|
22211
|
+
swapActivityBytesPerMinute: vmStat?.swap ? computeSwapActivity(vmStat.swap, previous?.counters.swap, elapsedMs, vmStat.pageSizeBytes) : unavailable("vm_stat swap activity counters are unavailable."),
|
|
22212
|
+
committedMemoryBytes: unavailable("macOS does not expose Linux Committed_AS."),
|
|
22213
|
+
commitLimitBytes: unavailable("macOS does not expose Linux CommitLimit."),
|
|
22214
|
+
virtualCommitmentPercent: unavailable("macOS virtual commitment is unavailable."),
|
|
22215
|
+
counters: {
|
|
22216
|
+
cpu: cpuCounters,
|
|
22217
|
+
swap: vmStat?.swap ?? null
|
|
22218
|
+
}
|
|
22219
|
+
};
|
|
22220
|
+
}
|
|
22221
|
+
};
|
|
22222
|
+
}
|
|
22223
|
+
//#endregion
|
|
22224
|
+
//#region ../../lib/system-health/linux.ts
|
|
22225
|
+
const execFileAsync$7 = promisify(execFile);
|
|
22226
|
+
const KB$1 = 1024;
|
|
22227
|
+
const LINUX_MEMORY_PRESSURE_DEFAULTS = Object.freeze({
|
|
22228
|
+
someWarningAvg10: 5,
|
|
22229
|
+
fullCriticalAvg10: 1,
|
|
22230
|
+
swapActivityWarningBytesPerMinute: 64 * 1024 ** 2,
|
|
22231
|
+
swapActivityCriticalBytesPerMinute: 256 * 1024 ** 2
|
|
22232
|
+
});
|
|
22233
|
+
function parseMemInfo(content) {
|
|
22234
|
+
const values = /* @__PURE__ */ new Map();
|
|
22235
|
+
for (const line of content.split("\n")) {
|
|
22236
|
+
const match = line.match(/^(\w+):\s+(\d+)\s+kB$/);
|
|
22237
|
+
if (!match) continue;
|
|
22238
|
+
const value = Number(match[2]);
|
|
22239
|
+
if (Number.isFinite(value)) values.set(match[1], value * KB$1);
|
|
22240
|
+
}
|
|
22241
|
+
return {
|
|
22242
|
+
memTotalBytes: values.get("MemTotal"),
|
|
22243
|
+
memAvailableBytes: values.get("MemAvailable"),
|
|
22244
|
+
swapTotalBytes: values.get("SwapTotal"),
|
|
22245
|
+
swapFreeBytes: values.get("SwapFree"),
|
|
22246
|
+
committedMemoryBytes: values.get("Committed_AS"),
|
|
22247
|
+
commitLimitBytes: values.get("CommitLimit")
|
|
22248
|
+
};
|
|
22249
|
+
}
|
|
22250
|
+
function parseProcStat(content) {
|
|
22251
|
+
const lines = content.split("\n");
|
|
22252
|
+
const cpuLine = lines.find((line) => line.startsWith("cpu "));
|
|
22253
|
+
if (!cpuLine) return null;
|
|
22254
|
+
const values = cpuLine.trim().split(/\s+/).slice(1).map(Number);
|
|
22255
|
+
if (values.length < 4 || values.some((value) => !Number.isFinite(value))) return null;
|
|
22256
|
+
const idle = values[3] + (values[4] ?? 0);
|
|
22257
|
+
const total = values.reduce((sum, value) => sum + value, 0);
|
|
22258
|
+
const coreCount = lines.filter((line) => /^cpu\d+\s/.test(line)).length;
|
|
22259
|
+
if (total < 0 || idle < 0) return null;
|
|
22260
|
+
return {
|
|
22261
|
+
cpu: {
|
|
22262
|
+
idle,
|
|
22263
|
+
total
|
|
22264
|
+
},
|
|
22265
|
+
coreCount: Math.max(coreCount, 1)
|
|
22266
|
+
};
|
|
22267
|
+
}
|
|
22268
|
+
function parseMemoryPressure(content) {
|
|
22269
|
+
const result = {};
|
|
22270
|
+
for (const line of content.split("\n")) {
|
|
22271
|
+
const match = line.match(/^(some|full)\s+.*\bavg10=([^\s]+)/);
|
|
22272
|
+
if (!match) continue;
|
|
22273
|
+
const value = Number(match[2]);
|
|
22274
|
+
if (!Number.isFinite(value) || value < 0) continue;
|
|
22275
|
+
if (match[1] === "some") result.someAvg10 = value;
|
|
22276
|
+
if (match[1] === "full") result.fullAvg10 = value;
|
|
22277
|
+
}
|
|
22278
|
+
return result;
|
|
22279
|
+
}
|
|
22280
|
+
function parseVmstat(content) {
|
|
22281
|
+
let pagesIn = null;
|
|
22282
|
+
let pagesOut = null;
|
|
22283
|
+
for (const line of content.split("\n")) {
|
|
22284
|
+
const match = line.match(/^(pswpin|pswpout)\s+(\d+)$/);
|
|
22285
|
+
if (!match) continue;
|
|
22286
|
+
const value = Number(match[2]);
|
|
22287
|
+
if (!Number.isFinite(value)) continue;
|
|
22288
|
+
if (match[1] === "pswpin") pagesIn = value;
|
|
22289
|
+
if (match[1] === "pswpout") pagesOut = value;
|
|
22290
|
+
}
|
|
22291
|
+
return pagesIn == null || pagesOut == null ? null : {
|
|
22292
|
+
pagesIn,
|
|
22293
|
+
pagesOut
|
|
22294
|
+
};
|
|
22295
|
+
}
|
|
22296
|
+
function parseLoadAverage(content) {
|
|
22297
|
+
const value = Number(content.trim().split(/\s+/)[0]);
|
|
22298
|
+
return Number.isFinite(value) && value >= 0 ? value : null;
|
|
22299
|
+
}
|
|
22300
|
+
function computeCpuPercent(current, previous) {
|
|
22301
|
+
if (!previous) return unavailable("A previous CPU counter sample is required.");
|
|
22302
|
+
const totalDelta = current.total - previous.total;
|
|
22303
|
+
const idleDelta = current.idle - previous.idle;
|
|
22304
|
+
if (totalDelta <= 0 || idleDelta < 0 || idleDelta > totalDelta) return unavailable("CPU counters did not advance monotonically.");
|
|
22305
|
+
return available(Math.round((totalDelta - idleDelta) / totalDelta * 1e3) / 10);
|
|
22306
|
+
}
|
|
22307
|
+
function computeSwapActivityBytesPerMinute(current, previous, elapsedMs, pageSizeBytes) {
|
|
22308
|
+
if (!previous) return unavailable("A previous swap counter sample is required.");
|
|
22309
|
+
const pageDelta = current.pagesIn - previous.pagesIn + current.pagesOut - previous.pagesOut;
|
|
22310
|
+
if (pageDelta < 0 || elapsedMs <= 0 || !Number.isFinite(pageSizeBytes) || pageSizeBytes <= 0) return unavailable("Swap counters or sample timing were invalid.");
|
|
22311
|
+
return available(Math.round(pageDelta * pageSizeBytes * 6e4 / elapsedMs));
|
|
22312
|
+
}
|
|
22313
|
+
const defaultAdapters = {
|
|
22314
|
+
readFile: (path) => readFile(path, "utf-8"),
|
|
22315
|
+
readPageSizeBytes: async () => {
|
|
22316
|
+
const { stdout } = await execFileAsync$7("getconf", ["PAGESIZE"], {
|
|
22317
|
+
encoding: "utf-8",
|
|
22318
|
+
timeout: 5e3
|
|
22319
|
+
});
|
|
22320
|
+
const value = Number(stdout.trim());
|
|
22321
|
+
if (!Number.isFinite(value) || value <= 0) throw new Error("getconf returned an invalid page size");
|
|
22322
|
+
return value;
|
|
22323
|
+
},
|
|
22324
|
+
now: () => Date.now()
|
|
22325
|
+
};
|
|
22326
|
+
async function readParsed(adapters, path, parse) {
|
|
22327
|
+
try {
|
|
22328
|
+
return parse(await adapters.readFile(path));
|
|
22329
|
+
} catch {
|
|
22330
|
+
return null;
|
|
22331
|
+
}
|
|
22332
|
+
}
|
|
22333
|
+
function percent(part, total) {
|
|
22334
|
+
if (total <= 0) return 0;
|
|
22335
|
+
return Math.round(part / total * 1e3) / 10;
|
|
22336
|
+
}
|
|
22337
|
+
function createLinuxHostHealthCollector(adapters = defaultAdapters) {
|
|
22338
|
+
return {
|
|
22339
|
+
platform: "linux",
|
|
22340
|
+
async sample(previous) {
|
|
22341
|
+
const sampledAtMs = adapters.now();
|
|
22342
|
+
const [memInfo, procStat, pressure, vmstat, loadAverage, pageSizeBytes] = await Promise.all([
|
|
22343
|
+
readParsed(adapters, "/proc/meminfo", parseMemInfo),
|
|
22344
|
+
readParsed(adapters, "/proc/stat", parseProcStat),
|
|
22345
|
+
readParsed(adapters, "/proc/pressure/memory", parseMemoryPressure),
|
|
22346
|
+
readParsed(adapters, "/proc/vmstat", parseVmstat),
|
|
22347
|
+
readParsed(adapters, "/proc/loadavg", parseLoadAverage),
|
|
22348
|
+
adapters.readPageSizeBytes().catch(() => null)
|
|
22349
|
+
]);
|
|
22350
|
+
const totalMemoryBytes = memInfo?.memTotalBytes;
|
|
22351
|
+
const availableMemoryBytes = memInfo?.memAvailableBytes;
|
|
22352
|
+
const usedMemoryBytes = totalMemoryBytes != null && availableMemoryBytes != null ? Math.max(totalMemoryBytes - availableMemoryBytes, 0) : null;
|
|
22353
|
+
const swapTotalBytes = memInfo?.swapTotalBytes;
|
|
22354
|
+
const swapFreeBytes = memInfo?.swapFreeBytes;
|
|
22355
|
+
const swapUsedBytes = swapTotalBytes != null && swapFreeBytes != null ? Math.max(swapTotalBytes - swapFreeBytes, 0) : null;
|
|
22356
|
+
const committedMemoryBytes = memInfo?.committedMemoryBytes;
|
|
22357
|
+
const commitLimitBytes = memInfo?.commitLimitBytes;
|
|
22358
|
+
const cpuCounters = procStat?.cpu ?? null;
|
|
22359
|
+
const swapCounters = vmstat ?? null;
|
|
22360
|
+
const elapsedMs = previous ? sampledAtMs - previous.sampledAtMs : 0;
|
|
22361
|
+
return {
|
|
22362
|
+
platform: "linux",
|
|
22363
|
+
sampledAtMs,
|
|
22364
|
+
cpuPercent: cpuCounters ? computeCpuPercent(cpuCounters, previous?.counters.cpu) : unavailable("The aggregate CPU counters are unavailable."),
|
|
22365
|
+
loadAverage1m: loadAverage == null ? unavailable("The one-minute load average is unavailable.") : available(loadAverage),
|
|
22366
|
+
loadPerCore1m: loadAverage == null || !procStat ? unavailable("Load average or CPU core count is unavailable.") : available(Math.round(loadAverage / procStat.coreCount * 100) / 100),
|
|
22367
|
+
totalMemoryBytes: totalMemoryBytes == null ? unavailable("MemTotal is unavailable.") : available(totalMemoryBytes),
|
|
22368
|
+
usedMemoryBytes: usedMemoryBytes == null ? unavailable("Used memory cannot be derived without MemTotal and MemAvailable.") : available(usedMemoryBytes),
|
|
22369
|
+
availableMemoryBytes: availableMemoryBytes == null ? unavailable("MemAvailable is unavailable.") : available(availableMemoryBytes),
|
|
22370
|
+
memoryUsedPercent: usedMemoryBytes == null || totalMemoryBytes == null ? unavailable("Memory utilization cannot be derived.") : available(percent(usedMemoryBytes, totalMemoryBytes)),
|
|
22371
|
+
memoryPressureSomeAvg10: pressure?.someAvg10 == null ? unavailable("Linux memory PSI some.avg10 is unavailable.") : available(pressure.someAvg10),
|
|
22372
|
+
memoryPressureFullAvg10: pressure?.fullAvg10 == null ? unavailable("Linux memory PSI full.avg10 is unavailable.") : available(pressure.fullAvg10),
|
|
22373
|
+
memoryPressureFreePercent: unavailable("Linux reports memory pressure through PSI."),
|
|
22374
|
+
swapTotalBytes: swapTotalBytes == null ? unavailable("SwapTotal is unavailable.") : available(swapTotalBytes),
|
|
22375
|
+
swapUsedBytes: swapUsedBytes == null ? unavailable("Swap usage cannot be derived without SwapTotal and SwapFree.") : available(swapUsedBytes),
|
|
22376
|
+
swapUsedPercent: swapUsedBytes == null || swapTotalBytes == null ? unavailable("Swap utilization cannot be derived.") : available(percent(swapUsedBytes, swapTotalBytes)),
|
|
22377
|
+
swapActivityBytesPerMinute: swapCounters && pageSizeBytes != null ? computeSwapActivityBytesPerMinute(swapCounters, previous?.counters.swap, elapsedMs, pageSizeBytes) : unavailable("Linux swap activity counters are unavailable."),
|
|
22378
|
+
committedMemoryBytes: committedMemoryBytes == null ? unavailable("Committed_AS is unavailable.") : available(committedMemoryBytes),
|
|
22379
|
+
commitLimitBytes: commitLimitBytes == null ? unavailable("CommitLimit is unavailable.") : available(commitLimitBytes),
|
|
22380
|
+
virtualCommitmentPercent: committedMemoryBytes == null || commitLimitBytes == null ? unavailable("Virtual commitment cannot be derived.") : available(percent(committedMemoryBytes, commitLimitBytes)),
|
|
22381
|
+
counters: {
|
|
22382
|
+
cpu: cpuCounters,
|
|
22383
|
+
swap: swapCounters
|
|
22384
|
+
}
|
|
22385
|
+
};
|
|
22386
|
+
}
|
|
22387
|
+
};
|
|
22388
|
+
}
|
|
22389
|
+
//#endregion
|
|
22390
|
+
//#region ../../lib/system-health/collector.ts
|
|
22391
|
+
/**
|
|
22392
|
+
* Selects the platform host-health collector. Linux and macOS expose native
|
|
22393
|
+
* current-pressure signals; unsupported platforms return unavailable signals
|
|
22394
|
+
* so callers never mistake missing measurements for measured zeroes.
|
|
22395
|
+
*/
|
|
22396
|
+
function createUnsupportedCollector(platform = "unsupported") {
|
|
22397
|
+
const signal = () => unavailable("Host health collection is unsupported on this platform.");
|
|
22398
|
+
return {
|
|
22399
|
+
platform,
|
|
22400
|
+
async sample() {
|
|
22401
|
+
return {
|
|
22402
|
+
platform,
|
|
22403
|
+
sampledAtMs: Date.now(),
|
|
22404
|
+
cpuPercent: signal(),
|
|
22405
|
+
loadAverage1m: signal(),
|
|
22406
|
+
loadPerCore1m: signal(),
|
|
22407
|
+
totalMemoryBytes: signal(),
|
|
22408
|
+
usedMemoryBytes: signal(),
|
|
22409
|
+
availableMemoryBytes: signal(),
|
|
22410
|
+
memoryUsedPercent: signal(),
|
|
22411
|
+
memoryPressureSomeAvg10: signal(),
|
|
22412
|
+
memoryPressureFullAvg10: signal(),
|
|
22413
|
+
memoryPressureFreePercent: signal(),
|
|
22414
|
+
swapTotalBytes: signal(),
|
|
22415
|
+
swapUsedBytes: signal(),
|
|
22416
|
+
swapUsedPercent: signal(),
|
|
22417
|
+
swapActivityBytesPerMinute: signal(),
|
|
22418
|
+
committedMemoryBytes: signal(),
|
|
22419
|
+
commitLimitBytes: signal(),
|
|
22420
|
+
virtualCommitmentPercent: signal(),
|
|
22421
|
+
counters: {
|
|
22422
|
+
cpu: null,
|
|
22423
|
+
swap: null
|
|
22424
|
+
}
|
|
22425
|
+
};
|
|
22426
|
+
}
|
|
22427
|
+
};
|
|
22428
|
+
}
|
|
22429
|
+
function createHostHealthCollector(selection = {}) {
|
|
22430
|
+
const platform = selection.platform ?? platform$1();
|
|
22431
|
+
if (platform === "linux") return selection.linux ?? createLinuxHostHealthCollector();
|
|
22432
|
+
if (platform === "darwin") return selection.darwin ?? createDarwinHostHealthCollector();
|
|
22433
|
+
return createUnsupportedCollector();
|
|
22434
|
+
}
|
|
22435
|
+
//#endregion
|
|
22436
|
+
//#region ../../lib/system-health/evaluate.ts
|
|
22437
|
+
function value(signal) {
|
|
22438
|
+
return signal.status === "available" ? signal.value : null;
|
|
22439
|
+
}
|
|
22440
|
+
function reason(code, domain, severity, message, metric, observed, threshold) {
|
|
22441
|
+
return {
|
|
22442
|
+
code,
|
|
22443
|
+
domain,
|
|
22444
|
+
severity,
|
|
22445
|
+
message,
|
|
22446
|
+
metric,
|
|
22447
|
+
observed,
|
|
22448
|
+
threshold
|
|
22449
|
+
};
|
|
22450
|
+
}
|
|
22451
|
+
function evaluateAdmission(sample, thresholds) {
|
|
22452
|
+
const availableMemoryBytes = value(sample.availableMemoryBytes);
|
|
22453
|
+
if (availableMemoryBytes == null) return {
|
|
22454
|
+
state: "unavailable",
|
|
22455
|
+
availableMemoryBytes: null,
|
|
22456
|
+
reasons: [{
|
|
22457
|
+
code: "admission.memory_available.unavailable",
|
|
22458
|
+
domain: "admission",
|
|
22459
|
+
severity: "info",
|
|
22460
|
+
message: "Available memory could not be measured, so admission capacity is unavailable.",
|
|
22461
|
+
metric: "availableMemoryBytes"
|
|
22462
|
+
}]
|
|
22463
|
+
};
|
|
22464
|
+
if (availableMemoryBytes <= thresholds.memoryAvailableCriticalBytes) return {
|
|
22465
|
+
state: "blocked",
|
|
22466
|
+
availableMemoryBytes,
|
|
22467
|
+
reasons: [reason("admission.memory_available.blocked", "admission", "critical", "Available memory is at or below the critical admission reserve.", "availableMemoryBytes", availableMemoryBytes, thresholds.memoryAvailableCriticalBytes)]
|
|
22468
|
+
};
|
|
22469
|
+
if (availableMemoryBytes <= thresholds.memoryAvailableWarningBytes) return {
|
|
22470
|
+
state: "soft",
|
|
22471
|
+
availableMemoryBytes,
|
|
22472
|
+
reasons: [reason("admission.memory_available.soft", "admission", "warning", "Available memory is at or below the warning admission reserve.", "availableMemoryBytes", availableMemoryBytes, thresholds.memoryAvailableWarningBytes)]
|
|
22473
|
+
};
|
|
22474
|
+
return {
|
|
22475
|
+
state: "open",
|
|
22476
|
+
availableMemoryBytes,
|
|
22477
|
+
reasons: []
|
|
22478
|
+
};
|
|
22479
|
+
}
|
|
22480
|
+
function diagnostics(sample, thresholds) {
|
|
22481
|
+
const results = [];
|
|
22482
|
+
const swapUsedPercent = value(sample.swapUsedPercent);
|
|
22483
|
+
if (swapUsedPercent != null && swapUsedPercent > 0) results.push(reason("host.diagnostic.swap_occupancy", "host", "info", "Swap occupancy is historical context and does not represent current pressure.", "swapUsedPercent", swapUsedPercent, thresholds.swapUsedWarningPercent));
|
|
22484
|
+
const virtualCommitmentPercent = value(sample.virtualCommitmentPercent);
|
|
22485
|
+
if (virtualCommitmentPercent != null) results.push(reason("host.diagnostic.virtual_commitment", "host", "info", "Virtual memory commitment is diagnostic and does not represent current pressure.", "virtualCommitmentPercent", virtualCommitmentPercent, thresholds.overcommitWarningPercent));
|
|
22486
|
+
return results;
|
|
22487
|
+
}
|
|
22488
|
+
function linuxPressureReasons(sample, admission) {
|
|
22489
|
+
const results = [];
|
|
22490
|
+
const some = value(sample.memoryPressureSomeAvg10);
|
|
22491
|
+
const full = value(sample.memoryPressureFullAvg10);
|
|
22492
|
+
const swapActivity = value(sample.swapActivityBytesPerMinute);
|
|
22493
|
+
if (admission.state === "blocked") {
|
|
22494
|
+
if (full != null && full >= LINUX_MEMORY_PRESSURE_DEFAULTS.fullCriticalAvg10) results.push(reason("host.linux.psi_full.critical", "host", "critical", "Linux memory PSI full stalls reached the critical band while memory was below reserve.", "memoryPressureFullAvg10", full, LINUX_MEMORY_PRESSURE_DEFAULTS.fullCriticalAvg10));
|
|
22495
|
+
if (swapActivity != null && swapActivity >= LINUX_MEMORY_PRESSURE_DEFAULTS.swapActivityCriticalBytesPerMinute) results.push(reason("host.linux.swap_activity.critical", "host", "critical", "Linux swap activity reached the critical band while memory was below reserve.", "swapActivityBytesPerMinute", swapActivity, LINUX_MEMORY_PRESSURE_DEFAULTS.swapActivityCriticalBytesPerMinute));
|
|
22496
|
+
}
|
|
22497
|
+
if (admission.state === "soft" || admission.state === "blocked") {
|
|
22498
|
+
if (some != null && some >= LINUX_MEMORY_PRESSURE_DEFAULTS.someWarningAvg10) results.push(reason("host.linux.psi_some.warning", "host", "warning", "Linux memory PSI some stalls reached the warning band while memory was below reserve.", "memoryPressureSomeAvg10", some, LINUX_MEMORY_PRESSURE_DEFAULTS.someWarningAvg10));
|
|
22499
|
+
if (swapActivity != null && swapActivity >= LINUX_MEMORY_PRESSURE_DEFAULTS.swapActivityWarningBytesPerMinute && !(admission.state === "blocked" && swapActivity >= LINUX_MEMORY_PRESSURE_DEFAULTS.swapActivityCriticalBytesPerMinute)) results.push(reason("host.linux.swap_activity.warning", "host", "warning", "Linux swap activity reached the warning band while memory was below reserve.", "swapActivityBytesPerMinute", swapActivity, LINUX_MEMORY_PRESSURE_DEFAULTS.swapActivityWarningBytesPerMinute));
|
|
22500
|
+
}
|
|
22501
|
+
return results;
|
|
22502
|
+
}
|
|
22503
|
+
function darwinPressureReasons(sample) {
|
|
22504
|
+
const freePercent = value(sample.memoryPressureFreePercent);
|
|
22505
|
+
if (freePercent == null) return [];
|
|
22506
|
+
if (freePercent <= DARWIN_MEMORY_PRESSURE_DEFAULTS.criticalFreePercent) return [reason("host.darwin.memory_pressure.critical", "host", "critical", "macOS memory pressure free percentage reached the critical band.", "memoryPressureFreePercent", freePercent, DARWIN_MEMORY_PRESSURE_DEFAULTS.criticalFreePercent)];
|
|
22507
|
+
if (freePercent <= DARWIN_MEMORY_PRESSURE_DEFAULTS.warningFreePercent) return [reason("host.darwin.memory_pressure.warning", "host", "warning", "macOS memory pressure free percentage reached the warning band.", "memoryPressureFreePercent", freePercent, DARWIN_MEMORY_PRESSURE_DEFAULTS.warningFreePercent)];
|
|
22508
|
+
return [];
|
|
22509
|
+
}
|
|
22510
|
+
function hasCurrentPressureSignal(sample) {
|
|
22511
|
+
if (sample.platform === "linux") return value(sample.memoryPressureSomeAvg10) != null || value(sample.memoryPressureFullAvg10) != null || value(sample.swapActivityBytesPerMinute) != null;
|
|
22512
|
+
if (sample.platform === "darwin") return value(sample.memoryPressureFreePercent) != null;
|
|
22513
|
+
return false;
|
|
22514
|
+
}
|
|
22515
|
+
function evaluateHostPressure(sample, thresholds) {
|
|
22516
|
+
const admission = evaluateAdmission(sample, thresholds);
|
|
22517
|
+
const diagnosticReasons = diagnostics(sample, thresholds);
|
|
22518
|
+
if (!hasCurrentPressureSignal(sample)) return {
|
|
22519
|
+
state: "unavailable",
|
|
22520
|
+
reasons: [{
|
|
22521
|
+
code: "host.current_pressure.unavailable",
|
|
22522
|
+
domain: "host",
|
|
22523
|
+
severity: "info",
|
|
22524
|
+
message: "The platform collector could not measure a current-pressure signal."
|
|
22525
|
+
}, ...diagnosticReasons],
|
|
22526
|
+
diagnostics: diagnosticReasons,
|
|
22527
|
+
admission
|
|
22528
|
+
};
|
|
22529
|
+
const pressureReasons = sample.platform === "linux" ? linuxPressureReasons(sample, admission) : darwinPressureReasons(sample);
|
|
22530
|
+
return {
|
|
22531
|
+
state: pressureReasons.some((entry) => entry.severity === "critical") ? "critical" : pressureReasons.some((entry) => entry.severity === "warning") ? "warning" : "healthy",
|
|
22532
|
+
reasons: [...pressureReasons, ...diagnosticReasons],
|
|
22533
|
+
diagnostics: diagnosticReasons,
|
|
22534
|
+
admission
|
|
22535
|
+
};
|
|
22536
|
+
}
|
|
22537
|
+
//#endregion
|
|
22538
|
+
//#region ../../lib/system-health/sampler.ts
|
|
22539
|
+
const DEFAULT_WARMUP_INTERVAL_MS = 1e3;
|
|
22540
|
+
const DEFAULT_WARMUP_SAMPLES = 3;
|
|
22541
|
+
const REQUIRED_CONSECUTIVE_SAMPLES = 3;
|
|
22542
|
+
function createMeasuringState(metrics, observedAt) {
|
|
22543
|
+
return {
|
|
22544
|
+
accepted: {
|
|
22545
|
+
state: "measuring",
|
|
22546
|
+
reasons: [{
|
|
22547
|
+
code: "host.sampler.measuring",
|
|
22548
|
+
domain: "host",
|
|
22549
|
+
severity: "info",
|
|
22550
|
+
message: "System health is collecting the initial three samples."
|
|
22551
|
+
}],
|
|
22552
|
+
metrics,
|
|
22553
|
+
sampledAt: observedAt,
|
|
22554
|
+
freshness: {
|
|
22555
|
+
status: "measuring",
|
|
22556
|
+
observedAt
|
|
22557
|
+
},
|
|
22558
|
+
transitionVersion: 0
|
|
22559
|
+
},
|
|
22560
|
+
candidate: null,
|
|
22561
|
+
candidateCount: 0
|
|
22562
|
+
};
|
|
22563
|
+
}
|
|
22564
|
+
function accept(previous, assessment) {
|
|
22565
|
+
const changed = previous.state !== assessment.state;
|
|
22566
|
+
const transitionVersion = changed ? previous.transitionVersion + 1 : previous.transitionVersion;
|
|
22567
|
+
return {
|
|
22568
|
+
state: {
|
|
22569
|
+
accepted: {
|
|
22570
|
+
...assessment,
|
|
22571
|
+
freshness: {
|
|
22572
|
+
status: "fresh",
|
|
22573
|
+
observedAt: assessment.sampledAt
|
|
22574
|
+
},
|
|
22575
|
+
transitionVersion
|
|
22576
|
+
},
|
|
22577
|
+
candidate: null,
|
|
22578
|
+
candidateCount: 0
|
|
22579
|
+
},
|
|
22580
|
+
transition: changed ? {
|
|
22581
|
+
version: transitionVersion,
|
|
22582
|
+
previousState: previous.state,
|
|
22583
|
+
state: assessment.state,
|
|
22584
|
+
reasonCodes: assessment.reasons.map((entry) => entry.code),
|
|
22585
|
+
acceptedAt: assessment.sampledAt
|
|
22586
|
+
} : null
|
|
22587
|
+
};
|
|
22588
|
+
}
|
|
22589
|
+
/**
|
|
22590
|
+
* Applies symmetric three-sample hysteresis to one atomic assessment. Metrics
|
|
22591
|
+
* and reasons move with their state only when that complete assessment is
|
|
22592
|
+
* accepted, so readers never observe a new state paired with old evidence.
|
|
22593
|
+
*/
|
|
22594
|
+
function transitionAcceptedAssessment(previous, raw) {
|
|
22595
|
+
if (raw.status === "invalid") return {
|
|
22596
|
+
state: {
|
|
22597
|
+
accepted: {
|
|
22598
|
+
...previous.accepted,
|
|
22599
|
+
freshness: {
|
|
22600
|
+
status: "stale",
|
|
22601
|
+
observedAt: raw.sampledAt,
|
|
22602
|
+
reason: raw.reason
|
|
22603
|
+
}
|
|
22604
|
+
},
|
|
22605
|
+
candidate: null,
|
|
22606
|
+
candidateCount: 0
|
|
22607
|
+
},
|
|
22608
|
+
transition: null
|
|
22609
|
+
};
|
|
22610
|
+
const assessment = raw.assessment;
|
|
22611
|
+
if (assessment.state === previous.accepted.state) return accept(previous.accepted, assessment);
|
|
22612
|
+
const candidateCount = previous.candidate?.state === assessment.state ? previous.candidateCount + 1 : 1;
|
|
22613
|
+
if (candidateCount >= REQUIRED_CONSECUTIVE_SAMPLES) return accept(previous.accepted, assessment);
|
|
22614
|
+
return {
|
|
22615
|
+
state: {
|
|
22616
|
+
accepted: previous.accepted,
|
|
22617
|
+
candidate: assessment,
|
|
22618
|
+
candidateCount
|
|
22619
|
+
},
|
|
22620
|
+
transition: null
|
|
22621
|
+
};
|
|
22622
|
+
}
|
|
22623
|
+
function resolveMeasuringMetrics(value) {
|
|
22624
|
+
return typeof value === "function" ? value() : value;
|
|
22625
|
+
}
|
|
22626
|
+
function createSystemHealthSampler(options) {
|
|
22627
|
+
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
22628
|
+
const warmupIntervalMs = options.warmupIntervalMs ?? DEFAULT_WARMUP_INTERVAL_MS;
|
|
22629
|
+
const warmupSamples = options.warmupSamples ?? DEFAULT_WARMUP_SAMPLES;
|
|
22630
|
+
let state = createMeasuringState(resolveMeasuringMetrics(options.measuringMetrics), now());
|
|
22631
|
+
let timer = null;
|
|
22632
|
+
let started = false;
|
|
22633
|
+
let stopped = false;
|
|
22634
|
+
let samplesAttempted = 0;
|
|
22635
|
+
const schedule = () => {
|
|
22636
|
+
if (stopped) return;
|
|
22637
|
+
const delay = samplesAttempted < warmupSamples ? warmupIntervalMs : options.pollIntervalMs;
|
|
22638
|
+
timer = setTimeout(() => {
|
|
22639
|
+
collectOnce();
|
|
22640
|
+
}, delay);
|
|
22641
|
+
};
|
|
22642
|
+
const collectOnce = async () => {
|
|
22643
|
+
if (stopped) return;
|
|
22644
|
+
let raw;
|
|
22645
|
+
try {
|
|
22646
|
+
raw = await options.collect();
|
|
22647
|
+
} catch (error) {
|
|
22648
|
+
raw = {
|
|
22649
|
+
status: "invalid",
|
|
22650
|
+
sampledAt: now(),
|
|
22651
|
+
reason: {
|
|
22652
|
+
code: "host.sampler.collection_failed",
|
|
22653
|
+
domain: "host",
|
|
22654
|
+
severity: "info",
|
|
22655
|
+
message: error instanceof Error ? error.message : "System health collection failed."
|
|
22656
|
+
}
|
|
22657
|
+
};
|
|
22658
|
+
}
|
|
22659
|
+
samplesAttempted++;
|
|
22660
|
+
const result = transitionAcceptedAssessment(state, raw);
|
|
22661
|
+
state = result.state;
|
|
22662
|
+
if (result.transition && options.onTransition) try {
|
|
22663
|
+
await options.onTransition(result.transition);
|
|
22664
|
+
} catch (error) {
|
|
22665
|
+
console.error("[system-health] Failed to publish accepted transition:", error);
|
|
22666
|
+
}
|
|
22667
|
+
schedule();
|
|
22668
|
+
};
|
|
22669
|
+
const start = () => {
|
|
22670
|
+
if (started || stopped) return;
|
|
22671
|
+
started = true;
|
|
22672
|
+
collectOnce();
|
|
22673
|
+
};
|
|
22674
|
+
return {
|
|
22675
|
+
getSnapshot() {
|
|
22676
|
+
start();
|
|
22677
|
+
return state.accepted;
|
|
22678
|
+
},
|
|
22679
|
+
stop() {
|
|
22680
|
+
stopped = true;
|
|
22681
|
+
if (timer) clearTimeout(timer);
|
|
22682
|
+
timer = null;
|
|
22683
|
+
}
|
|
22684
|
+
};
|
|
22685
|
+
}
|
|
22686
|
+
//#endregion
|
|
22687
|
+
//#region services/system-health-v2.ts
|
|
21856
22688
|
init_event_store();
|
|
22689
|
+
init_staleness();
|
|
22690
|
+
function runtimeHealthState(runtime) {
|
|
22691
|
+
if (!runtime) return null;
|
|
22692
|
+
switch (runtime.activity) {
|
|
22693
|
+
case "working":
|
|
22694
|
+
case "thinking": return {
|
|
22695
|
+
state: "active",
|
|
22696
|
+
lastActivity: runtime.lastActivity,
|
|
22697
|
+
contextSaturatedAt: runtime.contextSaturatedAt
|
|
22698
|
+
};
|
|
22699
|
+
case "waiting": return {
|
|
22700
|
+
state: "waiting-on-human",
|
|
22701
|
+
lastActivity: runtime.lastActivity,
|
|
22702
|
+
contextSaturatedAt: runtime.contextSaturatedAt
|
|
22703
|
+
};
|
|
22704
|
+
case "idle": return {
|
|
22705
|
+
state: "idle",
|
|
22706
|
+
lastActivity: runtime.lastActivity,
|
|
22707
|
+
contextSaturatedAt: runtime.contextSaturatedAt
|
|
22708
|
+
};
|
|
22709
|
+
case "stopped": return {
|
|
22710
|
+
state: "stopped",
|
|
22711
|
+
lastActivity: runtime.lastActivity,
|
|
22712
|
+
contextSaturatedAt: runtime.contextSaturatedAt
|
|
22713
|
+
};
|
|
22714
|
+
}
|
|
22715
|
+
}
|
|
22716
|
+
function agentLifecycle(role, issueId, tmuxActive, statuses) {
|
|
22717
|
+
if (role !== "review" && role !== "test" && role !== "ship") return "unknown";
|
|
22718
|
+
return classifyAdvancingSessionLifecycle(role, statuses.get(issueId.toUpperCase()), tmuxActive);
|
|
22719
|
+
}
|
|
22720
|
+
function stateToLegacySeverity(state) {
|
|
22721
|
+
return state === "critical" ? "critical" : state === "warning" ? "warning" : "normal";
|
|
22722
|
+
}
|
|
22723
|
+
function signalValue(signal) {
|
|
22724
|
+
return signal.status === "available" ? signal.value : null;
|
|
22725
|
+
}
|
|
22726
|
+
function hostMetrics(sample) {
|
|
22727
|
+
return {
|
|
22728
|
+
cpuPercent: signalValue(sample.cpuPercent),
|
|
22729
|
+
loadAverage1m: signalValue(sample.loadAverage1m),
|
|
22730
|
+
loadPerCore1m: signalValue(sample.loadPerCore1m),
|
|
22731
|
+
totalMemoryBytes: signalValue(sample.totalMemoryBytes),
|
|
22732
|
+
usedMemoryBytes: signalValue(sample.usedMemoryBytes),
|
|
22733
|
+
availableMemoryBytes: signalValue(sample.availableMemoryBytes),
|
|
22734
|
+
memoryUsedPercent: signalValue(sample.memoryUsedPercent),
|
|
22735
|
+
memoryPressureSomeAvg10: signalValue(sample.memoryPressureSomeAvg10),
|
|
22736
|
+
memoryPressureFullAvg10: signalValue(sample.memoryPressureFullAvg10),
|
|
22737
|
+
memoryPressureFreePercent: signalValue(sample.memoryPressureFreePercent),
|
|
22738
|
+
swapTotalBytes: signalValue(sample.swapTotalBytes),
|
|
22739
|
+
swapUsedBytes: signalValue(sample.swapUsedBytes),
|
|
22740
|
+
swapUsedPercent: signalValue(sample.swapUsedPercent),
|
|
22741
|
+
swapActivityBytesPerMinute: signalValue(sample.swapActivityBytesPerMinute),
|
|
22742
|
+
committedMemoryBytes: signalValue(sample.committedMemoryBytes),
|
|
22743
|
+
commitLimitBytes: signalValue(sample.commitLimitBytes),
|
|
22744
|
+
virtualCommitmentPercent: signalValue(sample.virtualCommitmentPercent)
|
|
22745
|
+
};
|
|
22746
|
+
}
|
|
22747
|
+
function serviceHealth(smeeRelay) {
|
|
22748
|
+
if (smeeRelay.status === "running") return [{
|
|
22749
|
+
id: "smee-relay",
|
|
22750
|
+
label: "Webhook relay",
|
|
22751
|
+
required: false,
|
|
22752
|
+
status: "running",
|
|
22753
|
+
message: smeeRelay.message,
|
|
22754
|
+
reasons: []
|
|
22755
|
+
}];
|
|
22756
|
+
if (smeeRelay.status === "not_configured") return [{
|
|
22757
|
+
id: "smee-relay",
|
|
22758
|
+
label: "Webhook relay",
|
|
22759
|
+
required: false,
|
|
22760
|
+
status: "not_configured",
|
|
22761
|
+
message: smeeRelay.message,
|
|
22762
|
+
reasons: []
|
|
22763
|
+
}];
|
|
22764
|
+
const unavailable = smeeRelay.status === "unknown";
|
|
22765
|
+
return [{
|
|
22766
|
+
id: "smee-relay",
|
|
22767
|
+
label: "Webhook relay",
|
|
22768
|
+
required: false,
|
|
22769
|
+
status: unavailable ? "unavailable" : "stopped",
|
|
22770
|
+
message: smeeRelay.message,
|
|
22771
|
+
reasons: [{
|
|
22772
|
+
code: unavailable ? "service.smee_relay.unavailable" : "service.smee_relay.stopped",
|
|
22773
|
+
domain: "service",
|
|
22774
|
+
severity: unavailable ? "info" : "warning",
|
|
22775
|
+
message: smeeRelay.message
|
|
22776
|
+
}]
|
|
22777
|
+
}];
|
|
22778
|
+
}
|
|
22779
|
+
function overallHealthState(hostState, agents, services) {
|
|
22780
|
+
if (hostState === "critical" || agents.some((agent) => agent.status === "dead" || agent.status === "wedged")) return "critical";
|
|
22781
|
+
if (hostState === "warning" || agents.some((agent) => agent.status === "warning" || agent.status === "stalled") || services.some((service) => service.status === "degraded" || service.status === "stopped")) return "warning";
|
|
22782
|
+
if (hostState === "measuring") return "measuring";
|
|
22783
|
+
if (hostState === "unavailable" || agents.some((agent) => agent.status === "unavailable") || services.some((service) => service.status === "unavailable")) return "unavailable";
|
|
22784
|
+
return "healthy";
|
|
22785
|
+
}
|
|
22786
|
+
function acceptedReasons(state, hostReasons, agents, services) {
|
|
22787
|
+
const reasons = [
|
|
22788
|
+
...hostReasons,
|
|
22789
|
+
...agents.flatMap((agent) => agent.reasons),
|
|
22790
|
+
...services.flatMap((service) => service.reasons)
|
|
22791
|
+
];
|
|
22792
|
+
if (state === "measuring" && reasons.length === 0) return [{
|
|
22793
|
+
code: "host.sampler.measuring",
|
|
22794
|
+
domain: "host",
|
|
22795
|
+
severity: "info",
|
|
22796
|
+
message: "System health is collecting the initial three samples."
|
|
22797
|
+
}];
|
|
22798
|
+
return reasons;
|
|
22799
|
+
}
|
|
22800
|
+
//#endregion
|
|
22801
|
+
//#region services/system-health-service.ts
|
|
22802
|
+
init_review_status_source();
|
|
21857
22803
|
const execAsync$4 = promisify(exec);
|
|
21858
|
-
const DEFAULT_HEALTH_POLL_SECONDS = 15;
|
|
21859
|
-
const DEFAULT_RESOURCE_CONFIG = {
|
|
21860
|
-
memoryWarnGb: 4,
|
|
21861
|
-
memoryBlockGb: 2,
|
|
21862
|
-
agentWarnCount: 8,
|
|
21863
|
-
agentBlockCount: 10
|
|
21864
|
-
};
|
|
21865
22804
|
const KB = 1024;
|
|
21866
22805
|
const GIB$1 = 1024 ** 3;
|
|
21867
|
-
const GLOBAL_CONFIG_PATH = join(homedir$1(), ".overdeck", "config.yaml");
|
|
21868
22806
|
let dockerStatsCollector$1 = null;
|
|
21869
|
-
|
|
21870
|
-
let
|
|
21871
|
-
let
|
|
21872
|
-
let cacheExpiresAt = 0;
|
|
21873
|
-
let inflightRefresh = null;
|
|
21874
|
-
let previousSeverity = null;
|
|
21875
|
-
let candidateSeverity = null;
|
|
21876
|
-
let candidateCount = 0;
|
|
21877
|
-
const HYSTERESIS_POLLS = 3;
|
|
22807
|
+
const hostHealthCollector = createHostHealthCollector();
|
|
22808
|
+
let previousHostMetricSample;
|
|
22809
|
+
let systemHealthSampler = null;
|
|
21878
22810
|
let eventStorePromise = null;
|
|
21879
|
-
let
|
|
21880
|
-
let cachedPollSeconds = DEFAULT_HEALTH_POLL_SECONDS;
|
|
22811
|
+
let cachedSystemHealthConfig = null;
|
|
21881
22812
|
let resourceConfigLoadedAt = 0;
|
|
21882
22813
|
let resourceConfigInflight = null;
|
|
21883
22814
|
let cachedDeployStaleness = null;
|
|
@@ -21911,9 +22842,17 @@ function getDockerStatsCollector() {
|
|
|
21911
22842
|
function bytesToGb(bytes) {
|
|
21912
22843
|
return Math.round(bytes / GIB$1 * 100) / 100;
|
|
21913
22844
|
}
|
|
21914
|
-
|
|
21915
|
-
|
|
21916
|
-
return
|
|
22845
|
+
const AGENT_STARTUP_GRACE_MS = 300 * 1e3;
|
|
22846
|
+
function countAdmittedWorkAgents(agents, nowMs = Date.now()) {
|
|
22847
|
+
return agents.filter((agent) => {
|
|
22848
|
+
if (agent.role !== "work") return false;
|
|
22849
|
+
if (agent.status !== "running" && agent.status !== "starting") return false;
|
|
22850
|
+
if (agent.tmuxActive) return true;
|
|
22851
|
+
if (agent.status !== "starting" || !agent.startedAt) return false;
|
|
22852
|
+
const startedAtMs = Date.parse(agent.startedAt);
|
|
22853
|
+
const ageMs = nowMs - startedAtMs;
|
|
22854
|
+
return Number.isFinite(startedAtMs) && ageMs >= 0 && ageMs < AGENT_STARTUP_GRACE_MS;
|
|
22855
|
+
}).length;
|
|
21917
22856
|
}
|
|
21918
22857
|
function classifyAgentKind(agentId, role) {
|
|
21919
22858
|
if (agentId.startsWith("planning-")) return "planning";
|
|
@@ -21925,41 +22864,13 @@ function classifyAgentKind(agentId, role) {
|
|
|
21925
22864
|
if (agentId.endsWith("-agent")) return "specialist";
|
|
21926
22865
|
return "other";
|
|
21927
22866
|
}
|
|
21928
|
-
function resolveFiniteNumber(value, fallback) {
|
|
21929
|
-
if (value == null || value.trim() === "") return fallback;
|
|
21930
|
-
const parsed = Number(value);
|
|
21931
|
-
return Number.isFinite(parsed) ? parsed : fallback;
|
|
21932
|
-
}
|
|
21933
22867
|
async function readGlobalResourceConfig() {
|
|
21934
|
-
|
|
21935
|
-
try {
|
|
21936
|
-
await access(GLOBAL_CONFIG_PATH);
|
|
21937
|
-
const raw = await readFile(GLOBAL_CONFIG_PATH, "utf-8");
|
|
21938
|
-
const memoryWarnMatch = raw.match(/^\s*memory_warn_gb:\s*(\d+(?:\.\d+)?)\s*$/m);
|
|
21939
|
-
const memoryBlockMatch = raw.match(/^\s*memory_block_gb:\s*(\d+(?:\.\d+)?)\s*$/m);
|
|
21940
|
-
const agentWarnMatch = raw.match(/^\s*agent_warn_count:\s*(\d+(?:\.\d+)?)\s*$/m);
|
|
21941
|
-
const agentBlockMatch = raw.match(/^\s*agent_block_count:\s*(\d+(?:\.\d+)?)\s*$/m);
|
|
21942
|
-
const pollSecondsMatch = raw.match(/^\s*poll_seconds:\s*(\d+(?:\.\d+)?)\s*$/m);
|
|
21943
|
-
next = {
|
|
21944
|
-
memoryWarnGb: resolveFiniteNumber(memoryWarnMatch?.[1], DEFAULT_RESOURCE_CONFIG.memoryWarnGb),
|
|
21945
|
-
memoryBlockGb: resolveFiniteNumber(memoryBlockMatch?.[1], DEFAULT_RESOURCE_CONFIG.memoryBlockGb),
|
|
21946
|
-
agentWarnCount: Math.max(1, Math.floor(resolveFiniteNumber(agentWarnMatch?.[1], DEFAULT_RESOURCE_CONFIG.agentWarnCount))),
|
|
21947
|
-
agentBlockCount: Math.max(1, Math.floor(resolveFiniteNumber(agentBlockMatch?.[1], DEFAULT_RESOURCE_CONFIG.agentBlockCount)))
|
|
21948
|
-
};
|
|
21949
|
-
cachedPollSeconds = Math.max(1, Math.floor(resolveFiniteNumber(process.env["PAN_HEALTH_POLL_SECONDS"], resolveFiniteNumber(pollSecondsMatch?.[1], DEFAULT_HEALTH_POLL_SECONDS))));
|
|
21950
|
-
} catch {
|
|
21951
|
-
cachedPollSeconds = Math.max(1, Math.floor(resolveFiniteNumber(process.env["PAN_HEALTH_POLL_SECONDS"], DEFAULT_HEALTH_POLL_SECONDS)));
|
|
21952
|
-
}
|
|
21953
|
-
cachedResourceConfig = {
|
|
21954
|
-
memoryWarnGb: resolveFiniteNumber(process.env["PAN_MEMORY_WARN_GB"], next.memoryWarnGb),
|
|
21955
|
-
memoryBlockGb: resolveFiniteNumber(process.env["PAN_MEMORY_BLOCK_GB"], next.memoryBlockGb),
|
|
21956
|
-
agentWarnCount: Math.max(1, Math.floor(resolveFiniteNumber(process.env["PAN_AGENT_WARN_COUNT"], next.agentWarnCount))),
|
|
21957
|
-
agentBlockCount: Math.max(1, Math.floor(resolveFiniteNumber(process.env["PAN_AGENT_BLOCK_COUNT"], next.agentBlockCount)))
|
|
21958
|
-
};
|
|
22868
|
+
cachedSystemHealthConfig = resolveSystemHealthConfig();
|
|
21959
22869
|
resourceConfigLoadedAt = Date.now();
|
|
21960
22870
|
}
|
|
21961
22871
|
async function ensureResourceConfigLoaded() {
|
|
21962
|
-
const
|
|
22872
|
+
const pollSeconds = cachedSystemHealthConfig?.pollSeconds ?? SYSTEM_HEALTH_DEFAULTS.pollSeconds;
|
|
22873
|
+
const ttl = Math.max(5e3, pollSeconds * 1e3);
|
|
21963
22874
|
if (resourceConfigLoadedAt > 0 && Date.now() - resourceConfigLoadedAt < ttl) return;
|
|
21964
22875
|
if (!resourceConfigInflight) resourceConfigInflight = readGlobalResourceConfig().finally(() => {
|
|
21965
22876
|
resourceConfigInflight = null;
|
|
@@ -21967,23 +22878,8 @@ async function ensureResourceConfigLoaded() {
|
|
|
21967
22878
|
await resourceConfigInflight;
|
|
21968
22879
|
}
|
|
21969
22880
|
function getResourceConfig() {
|
|
21970
|
-
|
|
21971
|
-
|
|
21972
|
-
function getHealthPollTtlMs() {
|
|
21973
|
-
return Math.max(1, cachedPollSeconds) * 1e3;
|
|
21974
|
-
}
|
|
21975
|
-
function defaultThresholds() {
|
|
21976
|
-
const resources = getResourceConfig();
|
|
21977
|
-
return {
|
|
21978
|
-
memoryAvailableWarningBytes: resources.memoryWarnGb * GIB$1,
|
|
21979
|
-
memoryAvailableCriticalBytes: resources.memoryBlockGb * GIB$1,
|
|
21980
|
-
swapUsedWarningPercent: Number(process.env["PAN_HEALTH_SWAP_WARN_PERCENT"] ?? 20),
|
|
21981
|
-
swapUsedCriticalPercent: Number(process.env["PAN_HEALTH_SWAP_CRITICAL_PERCENT"] ?? 50),
|
|
21982
|
-
cpuLoadWarningPerCore: Number(process.env["PAN_HEALTH_LOAD_WARN_PER_CORE"] ?? 1),
|
|
21983
|
-
cpuLoadCriticalPerCore: Number(process.env["PAN_HEALTH_LOAD_CRITICAL_PER_CORE"] ?? 1.5),
|
|
21984
|
-
overcommitWarningPercent: Number(process.env["PAN_HEALTH_OVERCOMMIT_WARN_PERCENT"] ?? 150),
|
|
21985
|
-
overcommitCriticalPercent: Number(process.env["PAN_HEALTH_OVERCOMMIT_CRITICAL_PERCENT"] ?? 200)
|
|
21986
|
-
};
|
|
22881
|
+
cachedSystemHealthConfig ??= resolveSystemHealthConfig();
|
|
22882
|
+
return cachedSystemHealthConfig.resources;
|
|
21987
22883
|
}
|
|
21988
22884
|
async function readProcMemoryLinux() {
|
|
21989
22885
|
const content = await readFile("/proc/meminfo", "utf-8");
|
|
@@ -22049,43 +22945,6 @@ async function readProcMemoryDarwin() {
|
|
|
22049
22945
|
async function readProcMemory() {
|
|
22050
22946
|
return platform$1() === "darwin" ? readProcMemoryDarwin() : readProcMemoryLinux();
|
|
22051
22947
|
}
|
|
22052
|
-
async function readLoadAverage() {
|
|
22053
|
-
if (platform$1() === "darwin") {
|
|
22054
|
-
const load = loadavg$1()[0] ?? 0;
|
|
22055
|
-
return Number.isFinite(load) ? load : 0;
|
|
22056
|
-
}
|
|
22057
|
-
const content = await readFile("/proc/loadavg", "utf-8");
|
|
22058
|
-
const load = Number((content.trim().split(/\s+/)[0] ?? "0").trim());
|
|
22059
|
-
return Number.isFinite(load) ? load : 0;
|
|
22060
|
-
}
|
|
22061
|
-
async function readCpuPercent() {
|
|
22062
|
-
if (platform$1() === "darwin") {
|
|
22063
|
-
const coreCount = Math.max(cpus$1().length, 1);
|
|
22064
|
-
const load = loadavg$1()[0] ?? 0;
|
|
22065
|
-
return Math.round(Math.min(load / coreCount, 1) * 1e3) / 10;
|
|
22066
|
-
}
|
|
22067
|
-
const cpuLine = (await readFile("/proc/stat", "utf-8")).split("\n").find((line) => line.startsWith("cpu "));
|
|
22068
|
-
if (!cpuLine) return 0;
|
|
22069
|
-
const values = cpuLine.trim().split(/\s+/).slice(1).map((value) => Number(value));
|
|
22070
|
-
const current = {
|
|
22071
|
-
idle: (values[3] ?? 0) + (values[4] ?? 0),
|
|
22072
|
-
total: values.reduce((sum, value) => sum + value, 0)
|
|
22073
|
-
};
|
|
22074
|
-
const now = Date.now();
|
|
22075
|
-
if (!previousCpuSample || previousCpuSampleAt > 0 && now - previousCpuSampleAt > getHealthPollTtlMs() * 2) {
|
|
22076
|
-
previousCpuSample = current;
|
|
22077
|
-
previousCpuSampleAt = now;
|
|
22078
|
-
const coreCount = Math.max(cpus$1().length, 1);
|
|
22079
|
-
const fallback = Math.min(await readLoadAverage() / coreCount, 1) * 100;
|
|
22080
|
-
return Math.round(fallback * 10) / 10;
|
|
22081
|
-
}
|
|
22082
|
-
const totalDelta = current.total - previousCpuSample.total;
|
|
22083
|
-
const idleDelta = current.idle - previousCpuSample.idle;
|
|
22084
|
-
previousCpuSample = current;
|
|
22085
|
-
previousCpuSampleAt = now;
|
|
22086
|
-
if (totalDelta <= 0) return 0;
|
|
22087
|
-
return Math.round((totalDelta - idleDelta) / totalDelta * 1e3) / 10;
|
|
22088
|
-
}
|
|
22089
22948
|
async function readProcessTable() {
|
|
22090
22949
|
const { stdout } = await execAsync$4("ps -eo pid=,ppid=,rss=,args=", {
|
|
22091
22950
|
encoding: "utf-8",
|
|
@@ -22127,41 +22986,13 @@ function sumProcessMemory(descendants, processes) {
|
|
|
22127
22986
|
for (const pid of descendants) totalRssKb += processes.get(pid)?.rssKb ?? 0;
|
|
22128
22987
|
return totalRssKb * KB;
|
|
22129
22988
|
}
|
|
22130
|
-
function buildLeakedSpecialists(
|
|
22131
|
-
|
|
22132
|
-
|
|
22133
|
-
|
|
22134
|
-
|
|
22135
|
-
currentIssue: specialist.currentIssue ?? "",
|
|
22136
|
-
reason: `Specialist is active for ${specialist.currentIssue} but no running work agent exists for that issue.`
|
|
22989
|
+
function buildLeakedSpecialists(agents) {
|
|
22990
|
+
return agents.filter((agent) => agent.kind === "specialist" && agent.lifecycle === "orphaned").map((agent) => ({
|
|
22991
|
+
name: agent.id,
|
|
22992
|
+
currentIssue: agent.currentIssue ?? agent.issueId,
|
|
22993
|
+
reason: `Advancing session remains live after ${agent.issueId} merged.`
|
|
22137
22994
|
}));
|
|
22138
22995
|
}
|
|
22139
|
-
function evaluateSeverity(thresholds, data) {
|
|
22140
|
-
const criticalReasons = [];
|
|
22141
|
-
const warningReasons = [];
|
|
22142
|
-
if (data.availableMemoryBytes < thresholds.memoryAvailableCriticalBytes) criticalReasons.push(`Available RAM is low (${bytesToGb(data.availableMemoryBytes)} GB).`);
|
|
22143
|
-
else if (data.availableMemoryBytes < thresholds.memoryAvailableWarningBytes) warningReasons.push(`Available RAM is tight (${bytesToGb(data.availableMemoryBytes)} GB).`);
|
|
22144
|
-
if (data.swapUsedPercent >= thresholds.swapUsedCriticalPercent) criticalReasons.push(`Swap usage is high (${data.swapUsedPercent}%).`);
|
|
22145
|
-
else if (data.swapUsedPercent >= thresholds.swapUsedWarningPercent) warningReasons.push(`Swap usage is elevated (${data.swapUsedPercent}%).`);
|
|
22146
|
-
if (data.loadPerCore1m >= thresholds.cpuLoadCriticalPerCore) criticalReasons.push(`CPU load is high (${data.loadPerCore1m.toFixed(2)} per core).`);
|
|
22147
|
-
else if (data.loadPerCore1m >= thresholds.cpuLoadWarningPerCore) warningReasons.push(`CPU load is elevated (${data.loadPerCore1m.toFixed(2)} per core).`);
|
|
22148
|
-
if (data.overcommitPercent >= thresholds.overcommitCriticalPercent) criticalReasons.push(`Committed memory exceeds the safe limit (${data.overcommitPercent}%).`);
|
|
22149
|
-
else if (data.overcommitPercent >= thresholds.overcommitWarningPercent) warningReasons.push(`Committed memory is near the limit (${data.overcommitPercent}%).`);
|
|
22150
|
-
if (data.leakedSpecialistCount > 0) warningReasons.push(`${data.leakedSpecialistCount} leaked specialist session${data.leakedSpecialistCount === 1 ? "" : "s"} detected.`);
|
|
22151
|
-
if (data.smeeRelay.configured && !data.smeeRelay.running) warningReasons.push("smee-client webhook relay is configured but not running.");
|
|
22152
|
-
if (criticalReasons.length > 0) return {
|
|
22153
|
-
severity: "critical",
|
|
22154
|
-
reasons: criticalReasons.concat(warningReasons)
|
|
22155
|
-
};
|
|
22156
|
-
if (warningReasons.length > 0) return {
|
|
22157
|
-
severity: "warning",
|
|
22158
|
-
reasons: warningReasons
|
|
22159
|
-
};
|
|
22160
|
-
return {
|
|
22161
|
-
severity: "normal",
|
|
22162
|
-
reasons: []
|
|
22163
|
-
};
|
|
22164
|
-
}
|
|
22165
22996
|
function collectSmeeRelayHealth() {
|
|
22166
22997
|
try {
|
|
22167
22998
|
if (!isSmeeConfiguredSync()) return {
|
|
@@ -22190,32 +23021,77 @@ function collectSmeeRelayHealth() {
|
|
|
22190
23021
|
};
|
|
22191
23022
|
}
|
|
22192
23023
|
}
|
|
23024
|
+
function reviewStatusMap() {
|
|
23025
|
+
return new Map(Object.entries(readReviewStatusMap() ?? {}));
|
|
23026
|
+
}
|
|
22193
23027
|
async function collectAgentProcesses() {
|
|
22194
|
-
const
|
|
23028
|
+
const registeredAgents = await Effect.runPromise(listRunningAgents());
|
|
23029
|
+
const nowMs = Date.now();
|
|
23030
|
+
const admittedWorkAgentCount = countAdmittedWorkAgents(registeredAgents, nowMs);
|
|
23031
|
+
const activeAgents = registeredAgents.filter((agent) => agent.status !== "stopped");
|
|
23032
|
+
const liveSessions = new Set(registeredAgents.filter((agent) => agent.tmuxActive).map((agent) => agent.id));
|
|
22195
23033
|
const processTable = await readProcessTable().catch(() => /* @__PURE__ */ new Map());
|
|
22196
|
-
|
|
22197
|
-
|
|
23034
|
+
const reviewStatuses = reviewStatusMap();
|
|
23035
|
+
const collected = await Promise.all(activeAgents.map(async (agent) => {
|
|
23036
|
+
const [runtimeState, runtimeSnapshot] = await Promise.all([Effect.runPromise(getAgentRuntimeState(agent.id)).catch(() => null), Effect.runPromise(getRuntimeSnapshot(agent.id)).catch(() => null)]);
|
|
22198
23037
|
const panePidValue = (await Effect.runPromise(listPaneValues(agent.id, "#{pane_pid}")))[0];
|
|
22199
23038
|
const panePid = Number(panePidValue ?? "0");
|
|
22200
23039
|
const descendants = Number.isFinite(panePid) && panePid > 0 ? getDescendantPids(panePid, processTable) : /* @__PURE__ */ new Set();
|
|
22201
23040
|
const memoryBytes = descendants.size > 0 ? sumProcessMemory(descendants, processTable) : 0;
|
|
23041
|
+
const lifecycle = agentLifecycle(agent.role, agent.issueId, agent.tmuxActive, reviewStatuses);
|
|
22202
23042
|
return {
|
|
22203
|
-
|
|
22204
|
-
|
|
22205
|
-
|
|
22206
|
-
|
|
22207
|
-
|
|
22208
|
-
|
|
22209
|
-
|
|
22210
|
-
|
|
23043
|
+
process: {
|
|
23044
|
+
id: agent.id,
|
|
23045
|
+
issueId: agent.issueId,
|
|
23046
|
+
role: agent.role,
|
|
23047
|
+
kind: classifyAgentKind(agent.id, agent.role),
|
|
23048
|
+
status: agent.status,
|
|
23049
|
+
lifecycle,
|
|
23050
|
+
tmuxActive: agent.tmuxActive,
|
|
23051
|
+
memoryBytes,
|
|
23052
|
+
memoryGb: bytesToGb(memoryBytes),
|
|
23053
|
+
currentIssue: runtimeState?.currentIssue
|
|
23054
|
+
},
|
|
23055
|
+
health: {
|
|
23056
|
+
...classifyAgentHealth({
|
|
23057
|
+
agentId: agent.id,
|
|
23058
|
+
persisted: {
|
|
23059
|
+
status: "available",
|
|
23060
|
+
value: {
|
|
23061
|
+
id: agent.id,
|
|
23062
|
+
issueId: agent.issueId,
|
|
23063
|
+
role: agent.role,
|
|
23064
|
+
status: agent.status,
|
|
23065
|
+
startedAt: agent.startedAt,
|
|
23066
|
+
lastActivity: agent.lastActivity,
|
|
23067
|
+
kickoffDelivered: agent.kickoffDelivered,
|
|
23068
|
+
paused: agent.paused,
|
|
23069
|
+
stoppedByUser: agent.stoppedByUser,
|
|
23070
|
+
stoppedByPause: agent.stoppedByPause,
|
|
23071
|
+
consecutiveFailures: agent.consecutiveFailures
|
|
23072
|
+
}
|
|
23073
|
+
},
|
|
23074
|
+
runtime: runtimeHealthState(runtimeSnapshot),
|
|
23075
|
+
liveSessions,
|
|
23076
|
+
reviewLifecycle: lifecycle,
|
|
23077
|
+
nowMs
|
|
23078
|
+
}),
|
|
23079
|
+
memoryBytes,
|
|
23080
|
+
memoryGb: bytesToGb(memoryBytes),
|
|
23081
|
+
...runtimeState?.currentIssue ? { currentIssue: runtimeState.currentIssue } : {}
|
|
23082
|
+
}
|
|
22211
23083
|
};
|
|
22212
23084
|
}));
|
|
23085
|
+
return {
|
|
23086
|
+
agents: collected.map((entry) => entry.process),
|
|
23087
|
+
healthAgents: collected.map((entry) => entry.health),
|
|
23088
|
+
admittedWorkAgentCount
|
|
23089
|
+
};
|
|
22213
23090
|
}
|
|
22214
|
-
function buildTopConsumers(agents, containers
|
|
22215
|
-
const leakedByName = new Map(leakedSpecialists.map((item) => [item.name, item]));
|
|
23091
|
+
function buildTopConsumers(agents, containers) {
|
|
22216
23092
|
const agentConsumers = agents.map((agent) => {
|
|
22217
23093
|
const isSpecialist = agent.kind === "specialist";
|
|
22218
|
-
const leaked =
|
|
23094
|
+
const leaked = agent.lifecycle === "orphaned";
|
|
22219
23095
|
const currentIssue = agent.currentIssue ?? agent.issueId;
|
|
22220
23096
|
const resolved = currentIssue ? resolveProjectFromIssueSync(currentIssue) : null;
|
|
22221
23097
|
const specialistType = isSpecialist ? agent.id.startsWith("specialist-") ? agent.id.replace(/^specialist-/, "") : agent.id : void 0;
|
|
@@ -22251,122 +23127,215 @@ function buildTopConsumers(agents, containers, leakedSpecialists) {
|
|
|
22251
23127
|
containerId: container.id
|
|
22252
23128
|
}
|
|
22253
23129
|
}));
|
|
22254
|
-
return [...agentConsumers, ...containerConsumers].sort((a, b) => b.memoryBytes - a.memoryBytes)
|
|
23130
|
+
return [...agentConsumers, ...containerConsumers].sort((a, b) => b.memoryBytes - a.memoryBytes);
|
|
22255
23131
|
}
|
|
22256
|
-
|
|
23132
|
+
function createMeasuringSnapshot() {
|
|
23133
|
+
cachedSystemHealthConfig ??= resolveSystemHealthConfig();
|
|
23134
|
+
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
23135
|
+
const smeeRelay = collectSmeeRelayHealth();
|
|
23136
|
+
const services = serviceHealth(smeeRelay);
|
|
23137
|
+
const base = {
|
|
23138
|
+
version: 2,
|
|
23139
|
+
state: "measuring",
|
|
23140
|
+
updatedAt,
|
|
23141
|
+
nextPollMs: cachedSystemHealthConfig.pollSeconds * 1e3,
|
|
23142
|
+
host: {
|
|
23143
|
+
state: "measuring",
|
|
23144
|
+
platform: hostHealthCollector.platform,
|
|
23145
|
+
reasons: [{
|
|
23146
|
+
code: "host.sampler.measuring",
|
|
23147
|
+
domain: "host",
|
|
23148
|
+
severity: "info",
|
|
23149
|
+
message: "System health is collecting the initial three samples."
|
|
23150
|
+
}],
|
|
23151
|
+
metrics: {
|
|
23152
|
+
cpuPercent: null,
|
|
23153
|
+
loadAverage1m: null,
|
|
23154
|
+
loadPerCore1m: null,
|
|
23155
|
+
totalMemoryBytes: null,
|
|
23156
|
+
usedMemoryBytes: null,
|
|
23157
|
+
availableMemoryBytes: null,
|
|
23158
|
+
memoryUsedPercent: null,
|
|
23159
|
+
memoryPressureSomeAvg10: null,
|
|
23160
|
+
memoryPressureFullAvg10: null,
|
|
23161
|
+
memoryPressureFreePercent: null,
|
|
23162
|
+
swapTotalBytes: null,
|
|
23163
|
+
swapUsedBytes: null,
|
|
23164
|
+
swapUsedPercent: null,
|
|
23165
|
+
swapActivityBytesPerMinute: null,
|
|
23166
|
+
committedMemoryBytes: null,
|
|
23167
|
+
commitLimitBytes: null,
|
|
23168
|
+
virtualCommitmentPercent: null
|
|
23169
|
+
}
|
|
23170
|
+
},
|
|
23171
|
+
admission: {
|
|
23172
|
+
state: "unavailable",
|
|
23173
|
+
availableMemoryBytes: null,
|
|
23174
|
+
admittedWorkAgentCount: 0,
|
|
23175
|
+
reasons: [{
|
|
23176
|
+
code: "admission.sampler.measuring",
|
|
23177
|
+
domain: "admission",
|
|
23178
|
+
severity: "info",
|
|
23179
|
+
message: "Admission capacity is unavailable until the initial health sample is accepted."
|
|
23180
|
+
}]
|
|
23181
|
+
},
|
|
23182
|
+
agents: [],
|
|
23183
|
+
services,
|
|
23184
|
+
topConsumers: []
|
|
23185
|
+
};
|
|
23186
|
+
const accepted = {
|
|
23187
|
+
...base,
|
|
23188
|
+
summary: projectLegacySystemHealthSummary(base)
|
|
23189
|
+
};
|
|
23190
|
+
return {
|
|
23191
|
+
accepted,
|
|
23192
|
+
compatibility: {
|
|
23193
|
+
severity: "normal",
|
|
23194
|
+
updatedAt,
|
|
23195
|
+
admission: { admittedWorkAgentCount: 0 },
|
|
23196
|
+
summary: accepted.summary,
|
|
23197
|
+
thresholds: cachedSystemHealthConfig.thresholds,
|
|
23198
|
+
reasons: accepted.host.reasons.map((reason) => reason.message),
|
|
23199
|
+
agents: [],
|
|
23200
|
+
leakedSpecialists: [],
|
|
23201
|
+
topConsumers: [],
|
|
23202
|
+
smeeRelay,
|
|
23203
|
+
deployStaleness: null
|
|
23204
|
+
}
|
|
23205
|
+
};
|
|
23206
|
+
}
|
|
23207
|
+
async function collectSystemHealth() {
|
|
22257
23208
|
await ensureResourceConfigLoaded();
|
|
22258
|
-
const [
|
|
22259
|
-
|
|
22260
|
-
readLoadAverage(),
|
|
22261
|
-
readCpuPercent(),
|
|
23209
|
+
const [sample, agentProcesses, containers, deployStaleness] = await Promise.all([
|
|
23210
|
+
hostHealthCollector.sample(previousHostMetricSample),
|
|
22262
23211
|
collectAgentProcesses(),
|
|
22263
|
-
Promise.resolve(getDockerStatsCollector().getStats())
|
|
23212
|
+
Promise.resolve(getDockerStatsCollector().getStats()),
|
|
23213
|
+
getDeployStaleness()
|
|
22264
23214
|
]);
|
|
22265
|
-
|
|
23215
|
+
previousHostMetricSample = sample;
|
|
23216
|
+
const config = cachedSystemHealthConfig;
|
|
23217
|
+
const host = evaluateHostPressure(sample, config.thresholds);
|
|
22266
23218
|
const smeeRelay = collectSmeeRelayHealth();
|
|
22267
|
-
const
|
|
22268
|
-
const
|
|
22269
|
-
const
|
|
22270
|
-
const
|
|
22271
|
-
const
|
|
22272
|
-
const
|
|
22273
|
-
|
|
22274
|
-
|
|
22275
|
-
|
|
22276
|
-
|
|
22277
|
-
|
|
22278
|
-
|
|
22279
|
-
|
|
22280
|
-
|
|
22281
|
-
|
|
22282
|
-
|
|
22283
|
-
|
|
22284
|
-
|
|
22285
|
-
|
|
22286
|
-
const overdeckMemoryBytes = agents.reduce((sum, agent) => sum + agent.memoryBytes, 0) + containerMemoryBytes;
|
|
22287
|
-
const overdeckMemoryPercent = toPercent(overdeckMemoryBytes, memory.memTotal);
|
|
22288
|
-
const sortedAgents = [...agents].sort((a, b) => b.memoryBytes - a.memoryBytes);
|
|
22289
|
-
const deployStaleness = await getDeployStaleness();
|
|
22290
|
-
let effectiveSeverity;
|
|
22291
|
-
if (previousSeverity == null) effectiveSeverity = evaluation.severity;
|
|
22292
|
-
else if (evaluation.severity === previousSeverity) {
|
|
22293
|
-
candidateSeverity = null;
|
|
22294
|
-
candidateCount = 0;
|
|
22295
|
-
effectiveSeverity = previousSeverity;
|
|
22296
|
-
} else if (evaluation.severity === candidateSeverity) {
|
|
22297
|
-
candidateCount++;
|
|
22298
|
-
effectiveSeverity = candidateCount >= HYSTERESIS_POLLS ? evaluation.severity : previousSeverity;
|
|
22299
|
-
if (effectiveSeverity !== previousSeverity) {
|
|
22300
|
-
candidateSeverity = null;
|
|
22301
|
-
candidateCount = 0;
|
|
22302
|
-
}
|
|
22303
|
-
} else {
|
|
22304
|
-
candidateSeverity = evaluation.severity;
|
|
22305
|
-
candidateCount = 1;
|
|
22306
|
-
effectiveSeverity = previousSeverity;
|
|
22307
|
-
}
|
|
22308
|
-
const result = {
|
|
22309
|
-
severity: effectiveSeverity,
|
|
22310
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22311
|
-
summary: {
|
|
22312
|
-
cpuPercent,
|
|
22313
|
-
loadAverage1m,
|
|
22314
|
-
loadPerCore1m,
|
|
22315
|
-
totalMemoryBytes: memory.memTotal,
|
|
22316
|
-
usedMemoryBytes,
|
|
22317
|
-
availableMemoryBytes: memory.memAvailable,
|
|
22318
|
-
memoryUsedPercent: toPercent(usedMemoryBytes, memory.memTotal),
|
|
22319
|
-
swapTotalBytes: memory.swapTotal,
|
|
22320
|
-
swapUsedBytes,
|
|
22321
|
-
swapUsedPercent,
|
|
22322
|
-
overcommitPercent,
|
|
22323
|
-
agentCount: agents.length,
|
|
22324
|
-
workAgentCount,
|
|
22325
|
-
planningAgentCount,
|
|
22326
|
-
specialistSessionCount,
|
|
22327
|
-
leakedSpecialistCount: leakedSpecialists.length,
|
|
22328
|
-
containerCount: containers.length,
|
|
22329
|
-
containerMemoryBytes,
|
|
22330
|
-
overdeckMemoryBytes,
|
|
22331
|
-
overdeckMemoryPercent
|
|
23219
|
+
const services = serviceHealth(smeeRelay);
|
|
23220
|
+
const consumers = buildTopConsumers(agentProcesses.agents, containers);
|
|
23221
|
+
const state = overallHealthState(host.state, agentProcesses.healthAgents, services);
|
|
23222
|
+
const reasons = acceptedReasons(state, host.reasons, agentProcesses.healthAgents, services);
|
|
23223
|
+
const updatedAt = new Date(sample.sampledAtMs).toISOString();
|
|
23224
|
+
const base = {
|
|
23225
|
+
version: 2,
|
|
23226
|
+
state,
|
|
23227
|
+
updatedAt,
|
|
23228
|
+
nextPollMs: config.pollSeconds * 1e3,
|
|
23229
|
+
host: {
|
|
23230
|
+
state: host.state,
|
|
23231
|
+
platform: sample.platform,
|
|
23232
|
+
reasons: host.reasons,
|
|
23233
|
+
metrics: hostMetrics(sample)
|
|
23234
|
+
},
|
|
23235
|
+
admission: {
|
|
23236
|
+
...host.admission,
|
|
23237
|
+
admittedWorkAgentCount: agentProcesses.admittedWorkAgentCount
|
|
22332
23238
|
},
|
|
22333
|
-
|
|
22334
|
-
|
|
22335
|
-
|
|
22336
|
-
|
|
22337
|
-
|
|
22338
|
-
|
|
22339
|
-
|
|
22340
|
-
};
|
|
22341
|
-
|
|
23239
|
+
agents: agentProcesses.healthAgents,
|
|
23240
|
+
services,
|
|
23241
|
+
topConsumers: consumers
|
|
23242
|
+
};
|
|
23243
|
+
const accepted = {
|
|
23244
|
+
...base,
|
|
23245
|
+
summary: projectLegacySystemHealthSummary(base)
|
|
23246
|
+
};
|
|
23247
|
+
const sortedAgents = [...agentProcesses.agents].sort((left, right) => right.memoryBytes - left.memoryBytes);
|
|
23248
|
+
const leakedSpecialists = buildLeakedSpecialists(sortedAgents);
|
|
23249
|
+
return {
|
|
23250
|
+
accepted,
|
|
23251
|
+
compatibility: {
|
|
23252
|
+
severity: stateToLegacySeverity(state),
|
|
23253
|
+
updatedAt,
|
|
23254
|
+
admission: { admittedWorkAgentCount: agentProcesses.admittedWorkAgentCount },
|
|
23255
|
+
summary: accepted.summary,
|
|
23256
|
+
thresholds: config.thresholds,
|
|
23257
|
+
reasons: reasons.map((reason) => reason.message),
|
|
23258
|
+
agents: sortedAgents,
|
|
23259
|
+
leakedSpecialists,
|
|
23260
|
+
topConsumers: consumers.slice(0, 10),
|
|
23261
|
+
smeeRelay,
|
|
23262
|
+
deployStaleness
|
|
23263
|
+
}
|
|
23264
|
+
};
|
|
23265
|
+
}
|
|
23266
|
+
async function collectRawSystemHealth() {
|
|
23267
|
+
const bundle = await collectSystemHealth();
|
|
23268
|
+
const reasons = acceptedReasons(bundle.accepted.state, bundle.accepted.host.reasons, bundle.accepted.agents, bundle.accepted.services);
|
|
23269
|
+
return {
|
|
23270
|
+
status: "valid",
|
|
23271
|
+
assessment: {
|
|
23272
|
+
state: bundle.accepted.state,
|
|
23273
|
+
reasons,
|
|
23274
|
+
metrics: bundle,
|
|
23275
|
+
sampledAt: bundle.accepted.updatedAt
|
|
23276
|
+
}
|
|
23277
|
+
};
|
|
23278
|
+
}
|
|
23279
|
+
function buildSystemHealthTransitionPayload(transition, leakedSpecialistCount) {
|
|
23280
|
+
return {
|
|
23281
|
+
version: 2,
|
|
23282
|
+
transitionVersion: transition.version,
|
|
23283
|
+
previousSeverity: stateToLegacySeverity(transition.previousState),
|
|
23284
|
+
severity: stateToLegacySeverity(transition.state),
|
|
23285
|
+
previousState: transition.previousState,
|
|
23286
|
+
state: transition.state,
|
|
23287
|
+
reasons: transition.reasonCodes,
|
|
23288
|
+
reasonCodes: transition.reasonCodes,
|
|
23289
|
+
acceptedAt: transition.acceptedAt,
|
|
23290
|
+
leakedSpecialistCount
|
|
23291
|
+
};
|
|
23292
|
+
}
|
|
23293
|
+
async function publishSystemHealthTransition(transition) {
|
|
23294
|
+
const accepted = systemHealthSampler?.getSnapshot();
|
|
23295
|
+
try {
|
|
22342
23296
|
await (await (eventStorePromise ??= initEventStore())).appendAsync({
|
|
22343
23297
|
type: "system.health_severity_changed",
|
|
22344
|
-
timestamp:
|
|
22345
|
-
payload:
|
|
22346
|
-
previousSeverity,
|
|
22347
|
-
severity: result.severity,
|
|
22348
|
-
reasons: result.reasons,
|
|
22349
|
-
leakedSpecialistCount: leakedSpecialists.length
|
|
22350
|
-
}
|
|
23298
|
+
timestamp: transition.acceptedAt,
|
|
23299
|
+
payload: buildSystemHealthTransitionPayload(transition, accepted?.metrics.accepted.summary.leakedSpecialistCount ?? 0)
|
|
22351
23300
|
});
|
|
22352
23301
|
} catch (err) {
|
|
22353
|
-
console.error("[system-health] Failed to append
|
|
23302
|
+
console.error("[system-health] Failed to append accepted transition event:", err);
|
|
22354
23303
|
}
|
|
22355
|
-
previousSeverity = result.severity;
|
|
22356
|
-
cachedHealth = result;
|
|
22357
|
-
cacheExpiresAt = Date.now() + getHealthPollTtlMs();
|
|
22358
|
-
return result;
|
|
22359
23304
|
}
|
|
22360
|
-
|
|
22361
|
-
if (
|
|
22362
|
-
|
|
22363
|
-
|
|
22364
|
-
|
|
22365
|
-
|
|
23305
|
+
function getSystemHealthSampler() {
|
|
23306
|
+
if (!systemHealthSampler) {
|
|
23307
|
+
const config = cachedSystemHealthConfig ?? resolveSystemHealthConfig();
|
|
23308
|
+
cachedSystemHealthConfig = config;
|
|
23309
|
+
systemHealthSampler = createSystemHealthSampler({
|
|
23310
|
+
collect: collectRawSystemHealth,
|
|
23311
|
+
measuringMetrics: createMeasuringSnapshot,
|
|
23312
|
+
pollIntervalMs: config.pollSeconds * 1e3,
|
|
23313
|
+
onTransition: publishSystemHealthTransition
|
|
23314
|
+
});
|
|
23315
|
+
}
|
|
23316
|
+
return systemHealthSampler;
|
|
23317
|
+
}
|
|
23318
|
+
async function getSystemHealthEvidenceSnapshot() {
|
|
23319
|
+
const assessment = getSystemHealthSampler().getSnapshot();
|
|
23320
|
+
return {
|
|
23321
|
+
accepted: assessment.metrics.accepted,
|
|
23322
|
+
compatibility: {
|
|
23323
|
+
...assessment.metrics.compatibility,
|
|
23324
|
+
state: assessment.state,
|
|
23325
|
+
structuredReasons: assessment.reasons,
|
|
23326
|
+
freshness: assessment.freshness,
|
|
23327
|
+
transitionVersion: assessment.transitionVersion
|
|
23328
|
+
}
|
|
23329
|
+
};
|
|
23330
|
+
}
|
|
23331
|
+
async function getAcceptedSystemHealthSnapshot() {
|
|
23332
|
+
return (await getSystemHealthEvidenceSnapshot()).accepted;
|
|
23333
|
+
}
|
|
23334
|
+
async function getSystemHealthSnapshot() {
|
|
23335
|
+
return (await getSystemHealthEvidenceSnapshot()).compatibility;
|
|
22366
23336
|
}
|
|
22367
23337
|
//#endregion
|
|
22368
23338
|
//#region routes/resources/shared.ts
|
|
22369
|
-
init_load();
|
|
22370
23339
|
init_docker_stats();
|
|
22371
23340
|
function getCurrentDockerStats() {
|
|
22372
23341
|
return [];
|
|
@@ -22467,6 +23436,7 @@ function roundOne(value) {
|
|
|
22467
23436
|
}
|
|
22468
23437
|
//#endregion
|
|
22469
23438
|
//#region ../../lib/cloister/memory-governor.ts
|
|
23439
|
+
init_load();
|
|
22470
23440
|
init_projects();
|
|
22471
23441
|
promisify(execFile);
|
|
22472
23442
|
const GIB = 1024 ** 3;
|
|
@@ -22578,7 +23548,7 @@ async function checkInspectAgentTimeouts(now = /* @__PURE__ */ new Date()) {
|
|
|
22578
23548
|
console.warn(`[deacon] Failed to kill inspect session ${sessionName}: ${msg}`);
|
|
22579
23549
|
});
|
|
22580
23550
|
try {
|
|
22581
|
-
const { messageAgent } = await import("./agents-
|
|
23551
|
+
const { messageAgent } = await import("./agents-DyHKlq1I.js");
|
|
22582
23552
|
await messageAgent(`agent-${issueId.toLowerCase()}`, verdict, "deacon:inspect-watchdog");
|
|
22583
23553
|
} catch (err) {
|
|
22584
23554
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -22730,7 +23700,7 @@ async function maybeProactivelyCompactContext(sessionName, now) {
|
|
|
22730
23700
|
if (!agentState?.workspace || !sessionId || !agentState.model) return null;
|
|
22731
23701
|
let usage = null;
|
|
22732
23702
|
try {
|
|
22733
|
-
const { computeContextUsage } = await import("./conversation-service-
|
|
23703
|
+
const { computeContextUsage } = await import("./conversation-service-Dq33SYEj.js");
|
|
22734
23704
|
usage = await computeContextUsage(sessionFilePath(agentState.workspace, sessionId), agentState.model);
|
|
22735
23705
|
} catch {
|
|
22736
23706
|
return null;
|
|
@@ -22840,13 +23810,13 @@ async function checkApiErrorAgents() {
|
|
|
22840
23810
|
const st = getAgentStateSync(sessionName);
|
|
22841
23811
|
const sid = st?.sessionId ?? runtimeState?.claudeSessionId;
|
|
22842
23812
|
if (st?.workspace && sid && st.model) {
|
|
22843
|
-
const { computeContextUsage } = await import("./conversation-service-
|
|
23813
|
+
const { computeContextUsage } = await import("./conversation-service-Dq33SYEj.js");
|
|
22844
23814
|
const usage = await computeContextUsage(sessionFilePath(st.workspace, sid), st.model);
|
|
22845
23815
|
if (usage && usage.percentUsed < 85) recoveredPct = usage.percentUsed;
|
|
22846
23816
|
}
|
|
22847
23817
|
} catch {}
|
|
22848
23818
|
if (recoveredPct !== null) {
|
|
22849
|
-
const { clearWorkspaceStuck } = await import("./review-status-sync-
|
|
23819
|
+
const { clearWorkspaceStuck } = await import("./review-status-sync-D60PJWNL.js");
|
|
22850
23820
|
clearWorkspaceStuck(issueId);
|
|
22851
23821
|
stuckOverflowNativeRecoveryState.delete(sessionName);
|
|
22852
23822
|
actions.push(`Context overflow recovery: cleared stuck flag for ${sessionName} (context back to ${Math.round(recoveredPct)}%)`);
|
|
@@ -22862,7 +23832,7 @@ async function checkApiErrorAgents() {
|
|
|
22862
23832
|
rec.attempts += 1;
|
|
22863
23833
|
rec.lastAttempt = now;
|
|
22864
23834
|
stuckOverflowNativeRecoveryState.set(sessionName, rec);
|
|
22865
|
-
const { resumeAgent } = await import("./agents-
|
|
23835
|
+
const { resumeAgent } = await import("./agents-DyHKlq1I.js");
|
|
22866
23836
|
const recovered = await resumeAgent(sessionName, void 0, { compact: true });
|
|
22867
23837
|
if (recovered.success) {
|
|
22868
23838
|
stuckOverflowNativeRecoveryState.delete(sessionName);
|
|
@@ -22910,7 +23880,7 @@ async function checkApiErrorAgents() {
|
|
|
22910
23880
|
}
|
|
22911
23881
|
const compactAttempts = (ov?.compactAttempts ?? 0) + 1;
|
|
22912
23882
|
if (issueId !== null) {
|
|
22913
|
-
const { resumeAgent } = await import("./agents-
|
|
23883
|
+
const { resumeAgent } = await import("./agents-DyHKlq1I.js");
|
|
22914
23884
|
const resumeResult = await resumeAgent(sessionName, void 0, { compact: true });
|
|
22915
23885
|
contextOverflowRecoveryState.set(sessionName, {
|
|
22916
23886
|
lastAttempt: now,
|
|
@@ -23433,7 +24403,7 @@ function reviewConvoyLiveness(issueId) {
|
|
|
23433
24403
|
*/
|
|
23434
24404
|
async function recoverUnhealthyTestStack(issueId, workspacePath) {
|
|
23435
24405
|
const key = issueId.toUpperCase();
|
|
23436
|
-
const { getWorkspaceStackHealth } = await import("./stack-health-
|
|
24406
|
+
const { getWorkspaceStackHealth } = await import("./stack-health-Bd06frFn.js");
|
|
23437
24407
|
const health = await Effect.runPromise(getWorkspaceStackHealth(issueId, { workspacePath }));
|
|
23438
24408
|
if (health.healthy) {
|
|
23439
24409
|
testStackRebuildState.delete(key);
|
|
@@ -23465,7 +24435,7 @@ async function recoverUnhealthyTestStack(issueId, workspacePath) {
|
|
|
23465
24435
|
record.attempts += 1;
|
|
23466
24436
|
testStackRebuildState.set(key, record);
|
|
23467
24437
|
console.log(`[deacon] Test stack for ${key} unhealthy (${health.reasons.join("; ")}) — rebuilding (attempt ${record.attempts}/${TEST_STACK_REBUILD_MAX_ATTEMPTS})`);
|
|
23468
|
-
const { rebuildWorkspaceStack } = await import("./rebuild-stack-
|
|
24438
|
+
const { rebuildWorkspaceStack } = await import("./rebuild-stack-CKjJAI8L.js");
|
|
23469
24439
|
const result = await Effect.runPromise(rebuildWorkspaceStack(issueId, { onProgress: (m) => console.log(`[deacon] ${key} stack rebuild: ${m}`) }));
|
|
23470
24440
|
if (!result.success) {
|
|
23471
24441
|
console.warn(`[deacon] Test stack rebuild failed for ${key}: ${result.error}`);
|
|
@@ -23633,7 +24603,7 @@ async function handleReviewCoordinatorDied(issueId, _sessionName, _reason) {
|
|
|
23633
24603
|
return actions;
|
|
23634
24604
|
}
|
|
23635
24605
|
try {
|
|
23636
|
-
const { spawnReviewRoleForIssue } = await import("./review-agent-
|
|
24606
|
+
const { spawnReviewRoleForIssue } = await import("./review-agent-CCum8sGe.js");
|
|
23637
24607
|
const dispatchResult = await Effect.runPromise(spawnReviewRoleForIssue({
|
|
23638
24608
|
issueId,
|
|
23639
24609
|
workspace,
|
|
@@ -23785,7 +24755,7 @@ async function reconcileReviewStatusOrphan(issueId, rawStatus, options = {}) {
|
|
|
23785
24755
|
const workspace = agentState?.workspace || (resolved ? findWorkspacePath(resolved.projectPath, issueLower) : null);
|
|
23786
24756
|
if (workspace && resolved && !tryReserveAdvancingSlot() && !await tryYieldForAdvancingDispatch("review", issueId)) actions.push(`Deferred review re-dispatch for ${issueId} — advancing-role concurrency ceiling reached`);
|
|
23787
24757
|
else if (workspace && resolved) try {
|
|
23788
|
-
const { spawnReviewRoleForIssue } = await import("./review-agent-
|
|
24758
|
+
const { spawnReviewRoleForIssue } = await import("./review-agent-CCum8sGe.js");
|
|
23789
24759
|
const dispatchResult = await Effect.runPromise(spawnReviewRoleForIssue({
|
|
23790
24760
|
issueId,
|
|
23791
24761
|
workspace,
|
|
@@ -23810,8 +24780,8 @@ async function reconcileReviewStatusOrphan(issueId, rawStatus, options = {}) {
|
|
|
23810
24780
|
const workspace = agentState?.workspace || (resolved ? findWorkspacePath(resolved.projectPath, issueLower) : null);
|
|
23811
24781
|
if (workspace && resolved) {
|
|
23812
24782
|
const branch = `feature/${issueLower}`;
|
|
23813
|
-
const { spawnRun } = await import("./agents-
|
|
23814
|
-
const { buildTestRolePrompt } = await import("./test-agent-queue-
|
|
24783
|
+
const { spawnRun } = await import("./agents-DyHKlq1I.js");
|
|
24784
|
+
const { buildTestRolePrompt } = await import("./test-agent-queue-BJZ9Nfcc.js");
|
|
23815
24785
|
const stackRecovery = await recoverUnhealthyTestStack(issueId, workspace);
|
|
23816
24786
|
if (stackRecovery === "cooldown" || stackRecovery === "exhausted") {
|
|
23817
24787
|
setReviewStatusSync(issueId, { testStatus: "dispatch_failed" });
|
|
@@ -23949,7 +24919,7 @@ async function recoverStalledReviewConvoys(getCanonicalState = getAutoCloseOutCa
|
|
|
23949
24919
|
record.lastAttempt = now;
|
|
23950
24920
|
record.attempts += 1;
|
|
23951
24921
|
stalledReviewConvoyRecoveryState.set(key, record);
|
|
23952
|
-
const { spawnReviewRoleForIssue } = await import("./review-agent-
|
|
24922
|
+
const { spawnReviewRoleForIssue } = await import("./review-agent-CCum8sGe.js");
|
|
23953
24923
|
try {
|
|
23954
24924
|
const result = await Effect.runPromise(spawnReviewRoleForIssue({
|
|
23955
24925
|
issueId,
|
|
@@ -24020,7 +24990,7 @@ async function checkMissingReviewStatuses() {
|
|
|
24020
24990
|
continue;
|
|
24021
24991
|
}
|
|
24022
24992
|
try {
|
|
24023
|
-
const { spawnReviewRoleForIssue } = await import("./review-agent-
|
|
24993
|
+
const { spawnReviewRoleForIssue } = await import("./review-agent-CCum8sGe.js");
|
|
24024
24994
|
await Effect.runPromise(spawnReviewRoleForIssue({
|
|
24025
24995
|
issueId,
|
|
24026
24996
|
workspace,
|
|
@@ -24073,7 +25043,7 @@ async function checkStuckReviewing() {
|
|
|
24073
25043
|
const actions = [];
|
|
24074
25044
|
const REVIEW_STUCK_THRESHOLD_MS = 1800 * 1e3;
|
|
24075
25045
|
try {
|
|
24076
|
-
const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-
|
|
25046
|
+
const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-Bnh-rdkY.js");
|
|
24077
25047
|
const statuses = loadReviewStatuses();
|
|
24078
25048
|
const now = Date.now();
|
|
24079
25049
|
const activeReviewIssues = /* @__PURE__ */ new Set();
|
|
@@ -24218,7 +25188,7 @@ async function checkCompletedButUnsignaledReviews() {
|
|
|
24218
25188
|
}
|
|
24219
25189
|
const nudge = `Your review synthesis is already written and saved. Your ONLY remaining task is to execute this Bash command immediately — do not analyze, do not summarize, do not ask questions, just run it:\n\n${`pan admin specialists done review ${issueId} --status ${verdict}${verdict === "blocked" || verdict === "failed" ? ` --notes "${topBlocker || "See synthesis.md"}"` : ""}`}\n\nRun this command NOW. Do not write any other response before executing it.`;
|
|
24220
25190
|
try {
|
|
24221
|
-
const { messageAgent } = await import("./agents-
|
|
25191
|
+
const { messageAgent } = await import("./agents-DyHKlq1I.js");
|
|
24222
25192
|
await messageAgent(reviewSession, nudge);
|
|
24223
25193
|
unsignaledReviewNudges.set(latestDir, now);
|
|
24224
25194
|
actions.push(`Nudged ${reviewSession} to signal ${verdict} (synthesis written ${Math.round((now - latestMtime) / 6e4)}min ago)`);
|
|
@@ -24340,7 +25310,7 @@ async function respawnIdleReviewer(state, agentId) {
|
|
|
24340
25310
|
return false;
|
|
24341
25311
|
}
|
|
24342
25312
|
try {
|
|
24343
|
-
const { spawnReviewSubRoleForIssue } = await import("./review-agent-
|
|
25313
|
+
const { spawnReviewSubRoleForIssue } = await import("./review-agent-CCum8sGe.js");
|
|
24344
25314
|
const contextManifestPath = join$1(dirname$1(outputPath), "context.json");
|
|
24345
25315
|
const result = await Effect.runPromise(spawnReviewSubRoleForIssue({
|
|
24346
25316
|
issueId: state.issueId,
|
|
@@ -24469,7 +25439,7 @@ async function nudgeSynthesisForCompleteReviewerReports(states) {
|
|
|
24469
25439
|
"Read the four reports, write synthesis.md, then signal review status exactly as roles/review.md instructs."
|
|
24470
25440
|
].join("\n");
|
|
24471
25441
|
try {
|
|
24472
|
-
const { messageAgent } = await import("./agents-
|
|
25442
|
+
const { messageAgent } = await import("./agents-DyHKlq1I.js");
|
|
24473
25443
|
await messageAgent(state.id, message);
|
|
24474
25444
|
reviewReportsPresentNudges.set(nudgeKey, now);
|
|
24475
25445
|
const action = `Nudged ${state.id} to synthesize from ${REVIEW_SUB_ROLES.length} reviewer reports`;
|
|
@@ -24555,7 +25525,7 @@ async function monitorReviewConvoySignals() {
|
|
|
24555
25525
|
if (!signal) continue;
|
|
24556
25526
|
const message = signal === "ready" ? `REVIEWER_READY ${state.reviewSubRole} ${outputPath}` : signal === "timeout" ? `REVIEWER_TIMEOUT ${state.reviewSubRole} ${reason}` : `REVIEWER_FAILED ${state.reviewSubRole} ${reason}`;
|
|
24557
25527
|
try {
|
|
24558
|
-
const { messageAgent } = await import("./agents-
|
|
25528
|
+
const { messageAgent } = await import("./agents-DyHKlq1I.js");
|
|
24559
25529
|
await messageAgent(state.reviewSynthesisAgentId, message);
|
|
24560
25530
|
state.reviewMonitorSignaled = signal;
|
|
24561
25531
|
saveAgentStateSync(state);
|
|
@@ -24563,7 +25533,7 @@ async function monitorReviewConvoySignals() {
|
|
|
24563
25533
|
actions.push(action);
|
|
24564
25534
|
logDeaconEventSync(`monitorReviewConvoySignals: ${action}`);
|
|
24565
25535
|
if (signal === "ready") try {
|
|
24566
|
-
const { notifyPipelineSync } = await import("./pipeline-notifier-
|
|
25536
|
+
const { notifyPipelineSync } = await import("./pipeline-notifier-CZsrU_nj.js");
|
|
24567
25537
|
notifyPipelineSync({
|
|
24568
25538
|
type: "reviewer_completed",
|
|
24569
25539
|
issueId: state.issueId,
|
|
@@ -24571,7 +25541,7 @@ async function monitorReviewConvoySignals() {
|
|
|
24571
25541
|
});
|
|
24572
25542
|
} catch {}
|
|
24573
25543
|
else if (signal === "timeout") try {
|
|
24574
|
-
const { notifyPipelineSync } = await import("./pipeline-notifier-
|
|
25544
|
+
const { notifyPipelineSync } = await import("./pipeline-notifier-CZsrU_nj.js");
|
|
24575
25545
|
notifyPipelineSync({
|
|
24576
25546
|
type: "reviewer_timed_out",
|
|
24577
25547
|
issueId: state.issueId,
|
|
@@ -24671,7 +25641,7 @@ const FORK_CACHE_CHECK_DELAY_MS = 180 * 1e3;
|
|
|
24671
25641
|
async function checkStalledReviewDiscovery() {
|
|
24672
25642
|
const actions = [];
|
|
24673
25643
|
try {
|
|
24674
|
-
const { listAgentStates } = await import("./agents-
|
|
25644
|
+
const { listAgentStates } = await import("./agents-DyHKlq1I.js");
|
|
24675
25645
|
const states = listAgentStates();
|
|
24676
25646
|
const now = Date.now();
|
|
24677
25647
|
for (const state of states) {
|
|
@@ -24680,7 +25650,7 @@ async function checkStalledReviewDiscovery() {
|
|
|
24680
25650
|
const aged = Number.isFinite(startedMs) && now - startedMs > 48e4;
|
|
24681
25651
|
const dead = !await Effect.runPromise(sessionExists(state.id)).catch(() => false) || await Effect.runPromise(isPaneDead(state.id)).catch(() => true);
|
|
24682
25652
|
if (!aged && !dead) continue;
|
|
24683
|
-
const { handleReviewDiscoveryReady } = await import("./review-agent-
|
|
25653
|
+
const { handleReviewDiscoveryReady } = await import("./review-agent-CCum8sGe.js");
|
|
24684
25654
|
const result = await handleReviewDiscoveryReady(state.issueId, { source: dead ? "deacon-backstop (parent dead)" : "deacon-backstop (discovery timeout)" });
|
|
24685
25655
|
actions.push(result.message);
|
|
24686
25656
|
logDeaconEventSync(`checkStalledReviewDiscovery: ${result.message}`);
|
|
@@ -24703,8 +25673,8 @@ async function checkStalledReviewDiscovery() {
|
|
|
24703
25673
|
async function checkStalledReviewParents() {
|
|
24704
25674
|
const actions = [];
|
|
24705
25675
|
try {
|
|
24706
|
-
const { listAgentStates, markAgentStoppedState } = await import("./agents-
|
|
24707
|
-
const { PARENT_REVIEW_TIMEOUT_MS } = await import("./review-agent-
|
|
25676
|
+
const { listAgentStates, markAgentStoppedState } = await import("./agents-DyHKlq1I.js");
|
|
25677
|
+
const { PARENT_REVIEW_TIMEOUT_MS } = await import("./review-agent-CCum8sGe.js");
|
|
24708
25678
|
const states = listAgentStates();
|
|
24709
25679
|
const now = Date.now();
|
|
24710
25680
|
for (const state of states) {
|
|
@@ -24753,8 +25723,8 @@ async function checkStalledReviewParents() {
|
|
|
24753
25723
|
async function checkReviewForkCacheMisses() {
|
|
24754
25724
|
const actions = [];
|
|
24755
25725
|
try {
|
|
24756
|
-
const { listAgentStates, saveAgentState } = await import("./agents-
|
|
24757
|
-
const { readEventsSync } = await import("./events-
|
|
25726
|
+
const { listAgentStates, saveAgentState } = await import("./agents-DyHKlq1I.js");
|
|
25727
|
+
const { readEventsSync } = await import("./events-Dsuv6qyB.js");
|
|
24758
25728
|
const { emitActivityEntrySync } = await import("./activity-logger-OEUBdfZ8.js");
|
|
24759
25729
|
const states = listAgentStates();
|
|
24760
25730
|
const now = Date.now();
|
|
@@ -24890,7 +25860,7 @@ async function reconcileStaleMergeStatus() {
|
|
|
24890
25860
|
if (!project) continue;
|
|
24891
25861
|
let specStatus;
|
|
24892
25862
|
try {
|
|
24893
|
-
const { findSpecByIssue } = await import("./specs-
|
|
25863
|
+
const { findSpecByIssue } = await import("./specs-BhOKBzqk.js");
|
|
24894
25864
|
const spec = await Effect.runPromise(findSpecByIssue(project.projectPath, issueId));
|
|
24895
25865
|
specStatus = spec?.status;
|
|
24896
25866
|
if (spec && (spec.status === "completed" || spec.status === "cancelled")) {
|
|
@@ -24905,7 +25875,7 @@ async function reconcileStaleMergeStatus() {
|
|
|
24905
25875
|
if (branchTip.stdout.trim() === mainTip.stdout.trim()) console.log(`[deacon] ${issueId}: branch ${branch} points at main; not treating zero-commit branch as merged`);
|
|
24906
25876
|
} catch {}
|
|
24907
25877
|
if (!isMerged) {
|
|
24908
|
-
const { resolveGitHubIssueSync: _resolveGitHubIssue } = await import("./tracker-utils-
|
|
25878
|
+
const { resolveGitHubIssueSync: _resolveGitHubIssue } = await import("./tracker-utils-DV3h1FYG.js");
|
|
24909
25879
|
const ghResolved = _resolveGitHubIssue(issueId);
|
|
24910
25880
|
if (ghResolved.isGitHub) try {
|
|
24911
25881
|
const { stdout } = await execFileAsync$4("gh", [
|
|
@@ -24942,7 +25912,7 @@ async function reconcileStaleMergeStatus() {
|
|
|
24942
25912
|
actions.push(msg);
|
|
24943
25913
|
console.log(`[deacon] ${msg}`);
|
|
24944
25914
|
try {
|
|
24945
|
-
const { postMergeLifecycle } = await import("./merge-agent-
|
|
25915
|
+
const { postMergeLifecycle } = await import("./merge-agent-B-SnXOoc.js");
|
|
24946
25916
|
postMergeLifecycle(issueId, project.projectPath, branch, { skipDeploy: true }).catch((err) => console.warn(`[deacon] postMergeLifecycle (reconcile) failed for ${issueId}: ${err}`));
|
|
24947
25917
|
} catch (err) {
|
|
24948
25918
|
console.warn(`[deacon] Could not import postMergeLifecycle: ${err}`);
|
|
@@ -24967,7 +25937,7 @@ const falseMergedReset = /* @__PURE__ */ new Set();
|
|
|
24967
25937
|
async function reconcileFalseMerged() {
|
|
24968
25938
|
const actions = [];
|
|
24969
25939
|
try {
|
|
24970
|
-
const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-
|
|
25940
|
+
const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-CU14oYzP.js");
|
|
24971
25941
|
if (!isGitHubAppConfigured()) return actions;
|
|
24972
25942
|
const statuses = loadReviewStatuses();
|
|
24973
25943
|
for (const [issueId, status] of Object.entries(statuses)) {
|
|
@@ -25012,7 +25982,7 @@ const CLOSED_PR_RECONCILE_COOLDOWN_MS = 600 * 1e3;
|
|
|
25012
25982
|
async function reconcileClosedPrReadyForMerge() {
|
|
25013
25983
|
const actions = [];
|
|
25014
25984
|
try {
|
|
25015
|
-
const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-
|
|
25985
|
+
const { getPullRequestState, isGitHubAppConfigured } = await import("./github-app-CU14oYzP.js");
|
|
25016
25986
|
if (!isGitHubAppConfigured()) return actions;
|
|
25017
25987
|
const statuses = loadReviewStatuses();
|
|
25018
25988
|
const now = Date.now();
|
|
@@ -25084,7 +26054,7 @@ const STALE_MERGE_BLOCKER_COOLDOWN_MS = 120 * 1e3;
|
|
|
25084
26054
|
async function reconcileStaleMergeBlockers() {
|
|
25085
26055
|
const actions = [];
|
|
25086
26056
|
try {
|
|
25087
|
-
const { resolveConflictGate, buildRealConflictGateDeps } = await import("./conflict-gate-
|
|
26057
|
+
const { resolveConflictGate, buildRealConflictGateDeps } = await import("./conflict-gate-CHU9K1vU.js");
|
|
25088
26058
|
const statuses = loadReviewStatuses();
|
|
25089
26059
|
const now = Date.now();
|
|
25090
26060
|
const deps = buildRealConflictGateDeps();
|
|
@@ -25227,7 +26197,7 @@ async function checkFailedMergeRetry() {
|
|
|
25227
26197
|
if (ciEntry.count === 5) {
|
|
25228
26198
|
console.log(`[deacon] CI check failure for ${issueId} — retries exhausted, notifying work agent`);
|
|
25229
26199
|
const ciNotes = status.mergeNotes || "CI checks are failing on the PR";
|
|
25230
|
-
const { writeFeedbackFile } = await import("./feedback-writer-
|
|
26200
|
+
const { writeFeedbackFile } = await import("./feedback-writer-Bx5z11mF.js");
|
|
25231
26201
|
const ciFileResult = await Effect.runPromise(writeFeedbackFile({
|
|
25232
26202
|
issueId,
|
|
25233
26203
|
specialist: "merge-agent",
|
|
@@ -25259,7 +26229,7 @@ async function checkFailedMergeRetry() {
|
|
|
25259
26229
|
ciRetryMap.set(issueId, ciEntry);
|
|
25260
26230
|
console.log(`[deacon] CI check failure for ${issueId} — notifying agent to re-submit (attempt ${ciEntry.count}/5)`);
|
|
25261
26231
|
const ciNotes = status.mergeNotes || "CI checks are failing on the PR";
|
|
25262
|
-
const { writeFeedbackFile } = await import("./feedback-writer-
|
|
26232
|
+
const { writeFeedbackFile } = await import("./feedback-writer-Bx5z11mF.js");
|
|
25263
26233
|
const ciFileResult2 = await Effect.runPromise(writeFeedbackFile({
|
|
25264
26234
|
issueId,
|
|
25265
26235
|
specialist: "merge-agent",
|
|
@@ -25287,7 +26257,7 @@ async function checkFailedMergeRetry() {
|
|
|
25287
26257
|
const lastNudge = timeoutNudgeCooldowns.get(issueIdForFb);
|
|
25288
26258
|
if (!lastNudge || now - lastNudge >= TIMEOUT_NUDGE_COOLDOWN_MS) {
|
|
25289
26259
|
const timeoutNotes = status.mergeNotes;
|
|
25290
|
-
const { writeFeedbackFile } = await import("./feedback-writer-
|
|
26260
|
+
const { writeFeedbackFile } = await import("./feedback-writer-Bx5z11mF.js");
|
|
25291
26261
|
await Effect.runPromise(writeFeedbackFile({
|
|
25292
26262
|
issueId: issueIdForFb,
|
|
25293
26263
|
specialist: "merge-agent",
|
|
@@ -25392,7 +26362,7 @@ async function autoCloseOut(now = /* @__PURE__ */ new Date()) {
|
|
|
25392
26362
|
} } : {}
|
|
25393
26363
|
};
|
|
25394
26364
|
try {
|
|
25395
|
-
const { closeOut } = await import("./workflows-
|
|
26365
|
+
const { closeOut } = await import("./workflows-C4mR0Reb.js");
|
|
25396
26366
|
const result = await Effect.runPromise(closeOut(ctx));
|
|
25397
26367
|
if (!result.success) {
|
|
25398
26368
|
const failed = result.steps.find((step) => !step.success && !step.skipped);
|
|
@@ -25990,7 +26960,7 @@ async function nudgeStalledResumeWorkAgents() {
|
|
|
25990
26960
|
const message = buildStalledResumePrompt(state);
|
|
25991
26961
|
if (!message) continue;
|
|
25992
26962
|
try {
|
|
25993
|
-
const { messageAgent } = await import("./agents-
|
|
26963
|
+
const { messageAgent } = await import("./agents-DyHKlq1I.js");
|
|
25994
26964
|
await messageAgent(agentId, message);
|
|
25995
26965
|
recordCooldown(agentId, ".last-stalled-resume-nudge");
|
|
25996
26966
|
const action = `Re-sent stalled resume prompt to ${agentId} (${state.issueId})`;
|
|
@@ -26104,7 +27074,7 @@ async function nudgeIdleWorkAgentsWithOpenBeads() {
|
|
|
26104
27074
|
"Continue the per-item workflow without asking — claim it (`pan task claim <item-id>`), implement, commit, push, then complete it through `pan task done <item-id>`. Inspection is conditional on metadata.requiresInspection (default false; check the plan item before deciding to call `pan inspect`). Do NOT end your turn with a multi-paragraph summary; just advance to the next bead."
|
|
26105
27075
|
].join("\n");
|
|
26106
27076
|
try {
|
|
26107
|
-
const { messageAgent } = await import("./agents-
|
|
27077
|
+
const { messageAgent } = await import("./agents-DyHKlq1I.js");
|
|
26108
27078
|
await messageAgent(agentId, message);
|
|
26109
27079
|
writeFileSync(join$1(getAgentDir(agentId), ".last-bead-nudge"), String(Date.now()), "utf-8");
|
|
26110
27080
|
const action = `Nudged idle ${agentId} (${state.issueId}) — ${openTasks.length} ready task(s)`;
|
|
@@ -27373,8 +28343,8 @@ async function cleanupStaleAgentState() {
|
|
|
27373
28343
|
*/
|
|
27374
28344
|
async function cleanupAbandonedFeedback() {
|
|
27375
28345
|
const actions = [];
|
|
27376
|
-
const { getReviewStatusSync } = await import("./review-status-
|
|
27377
|
-
const { clearFeedbackFiles } = await import("./feedback-writer-
|
|
28346
|
+
const { getReviewStatusSync } = await import("./review-status-Bnh-rdkY.js");
|
|
28347
|
+
const { clearFeedbackFiles } = await import("./feedback-writer-Bx5z11mF.js");
|
|
27378
28348
|
for (const { issueId, workspacePath } of listFeatureWorkspaces()) {
|
|
27379
28349
|
const panFeedbackDir = join$1(workspacePath, ".pan", "feedback");
|
|
27380
28350
|
if (!existsSync(panFeedbackDir)) continue;
|
|
@@ -27445,7 +28415,7 @@ async function handleOrphanReviewerSession(sessionName, sessions, creationTimes,
|
|
|
27445
28415
|
if (!issueId) return null;
|
|
27446
28416
|
const agentSession = `agent-${issueId.toLowerCase()}`;
|
|
27447
28417
|
if (sessions.includes(agentSession)) return null;
|
|
27448
|
-
const { getReviewStatusSync } = await import("./review-status-
|
|
28418
|
+
const { getReviewStatusSync } = await import("./review-status-Bnh-rdkY.js");
|
|
27449
28419
|
try {
|
|
27450
28420
|
if (getReviewStatusSync(issueId)?.reviewStatus === "reviewing") return null;
|
|
27451
28421
|
} catch {}
|
|
@@ -27567,7 +28537,7 @@ async function checkOrphanedCompletions() {
|
|
|
27567
28537
|
async function checkPendingTestDispatch() {
|
|
27568
28538
|
const actions = [];
|
|
27569
28539
|
try {
|
|
27570
|
-
const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-
|
|
28540
|
+
const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-Bnh-rdkY.js");
|
|
27571
28541
|
const statuses = loadReviewStatuses();
|
|
27572
28542
|
const now = Date.now();
|
|
27573
28543
|
for (const [issueId, status] of Object.entries(statuses)) {
|
|
@@ -27600,7 +28570,7 @@ async function checkPendingTestDispatch() {
|
|
|
27600
28570
|
console.log(`[deacon] ${issueId}: skipping test re-dispatch — issue is closed`);
|
|
27601
28571
|
continue;
|
|
27602
28572
|
}
|
|
27603
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
28573
|
+
const { resolveProjectFromIssueSync } = await import("./projects-BKkwpH6q.js");
|
|
27604
28574
|
const resolved = resolveProjectFromIssueSync(issueId);
|
|
27605
28575
|
if (!resolved) continue;
|
|
27606
28576
|
const issueLower = issueId.toLowerCase();
|
|
@@ -27615,8 +28585,8 @@ async function checkPendingTestDispatch() {
|
|
|
27615
28585
|
logDeaconEventSync(`checkPendingTestDispatch: deferred test for ${issueId} — advancing ceiling reached (PAN-1665) — ${describeRunningAgents()}`);
|
|
27616
28586
|
continue;
|
|
27617
28587
|
}
|
|
27618
|
-
const { spawnRun } = await import("./agents-
|
|
27619
|
-
const { buildTestRolePrompt } = await import("./test-agent-queue-
|
|
28588
|
+
const { spawnRun } = await import("./agents-DyHKlq1I.js");
|
|
28589
|
+
const { buildTestRolePrompt } = await import("./test-agent-queue-BJZ9Nfcc.js");
|
|
27620
28590
|
try {
|
|
27621
28591
|
const run = await spawnRun(issueId, "test", {
|
|
27622
28592
|
workspace,
|
|
@@ -27739,7 +28709,7 @@ async function checkCompletedButUnsignaledTests() {
|
|
|
27739
28709
|
const cmd = `pan admin specialists done test ${issueId} --status ${decision.status}${noteArg}`;
|
|
27740
28710
|
const nudge = `Your test verdict (${decision.status}) is already written to .pan/test/result.json. Your ONLY remaining task is to execute this Bash command immediately — do not analyze, do not summarize, do not ask questions, just run it:\n\n${cmd}\n\nRun this command NOW. Do not write any other response before executing it.`;
|
|
27741
28711
|
try {
|
|
27742
|
-
const { messageAgent } = await import("./agents-
|
|
28712
|
+
const { messageAgent } = await import("./agents-DyHKlq1I.js");
|
|
27743
28713
|
await messageAgent(testSession, nudge);
|
|
27744
28714
|
unsignaledTestNudges.set(testSession, now);
|
|
27745
28715
|
const msg = `Nudged ${testSession} to signal ${decision.status} (verdict artifact present)`;
|
|
@@ -27753,7 +28723,7 @@ async function checkCompletedButUnsignaledTests() {
|
|
|
27753
28723
|
case "nudge-write": {
|
|
27754
28724
|
const nudge = `Your test run for ${issueId} looks finished but no verdict was recorded. Decide the verdict from the gates/UAT you ran, then do BOTH of these now: (1) write the workspace file .pan/test/result.json as {"status":"passed"|"failed","notes":"<evidence>"}, and (2) run: pan admin specialists done test ${issueId} --status passed|failed. Do this immediately — do not summarize or ask questions, just write the file and run the command.`;
|
|
27755
28725
|
try {
|
|
27756
|
-
const { messageAgent } = await import("./agents-
|
|
28726
|
+
const { messageAgent } = await import("./agents-DyHKlq1I.js");
|
|
27757
28727
|
await messageAgent(testSession, nudge);
|
|
27758
28728
|
unsignaledTestNudges.set(testSession, now);
|
|
27759
28729
|
const msg = `Nudged ${testSession} to write+signal a test verdict (no artifact yet)`;
|
|
@@ -27776,8 +28746,8 @@ async function checkCompletedButUnsignaledTests() {
|
|
|
27776
28746
|
async function checkVerificationReviewContradiction() {
|
|
27777
28747
|
const actions = [];
|
|
27778
28748
|
try {
|
|
27779
|
-
const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-
|
|
27780
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
28749
|
+
const { loadReviewStatuses, setReviewStatusSync } = await import("./review-status-Bnh-rdkY.js");
|
|
28750
|
+
const { resolveProjectFromIssueSync } = await import("./projects-BKkwpH6q.js");
|
|
27781
28751
|
const statuses = loadReviewStatuses();
|
|
27782
28752
|
for (const [issueId, status] of Object.entries(statuses)) if (status.verificationStatus === "passed" && status.reviewStatus === "reviewing" && status.stuckReason === "review_infrastructure_failure") {
|
|
27783
28753
|
let reviewedAtCommit;
|
|
@@ -27826,7 +28796,7 @@ async function checkPostReviewCommits() {
|
|
|
27826
28796
|
const actions = [];
|
|
27827
28797
|
try {
|
|
27828
28798
|
const statuses = loadReviewStatuses();
|
|
27829
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
28799
|
+
const { resolveProjectFromIssueSync } = await import("./projects-BKkwpH6q.js");
|
|
27830
28800
|
for (const [issueId, status] of Object.entries(statuses)) {
|
|
27831
28801
|
if (status.mergeStatus === "merged") continue;
|
|
27832
28802
|
if (!status.reviewedAtCommit) continue;
|
|
@@ -27881,7 +28851,7 @@ async function checkPostReviewCommits() {
|
|
|
27881
28851
|
actions.push(`Deferred post-review re-dispatch for ${issueId} — advancing-role concurrency ceiling reached`);
|
|
27882
28852
|
logDeaconEventSync(`checkPostReviewCommits: deferred review for ${issueId} — advancing ceiling reached (PAN-1665) — ${describeRunningAgents()}`);
|
|
27883
28853
|
} else if (freshStatus?.reviewStatus === "pending") {
|
|
27884
|
-
const { spawnReviewRoleForIssue } = await import("./review-agent-
|
|
28854
|
+
const { spawnReviewRoleForIssue } = await import("./review-agent-CCum8sGe.js");
|
|
27885
28855
|
const branch = `feature/${issueId.toLowerCase()}`;
|
|
27886
28856
|
const dispatchResult = await Effect.runPromise(spawnReviewRoleForIssue({
|
|
27887
28857
|
issueId,
|
|
@@ -27981,7 +28951,7 @@ async function checkReadyForMergeStuck() {
|
|
|
27981
28951
|
const testStatusGreenCiReconcileCooldowns = /* @__PURE__ */ new Map();
|
|
27982
28952
|
const TEST_STATUS_GREEN_CI_RECONCILE_COOLDOWN_MS = 300 * 1e3;
|
|
27983
28953
|
async function reconcileTestStatusFromGreenCi() {
|
|
27984
|
-
const { getCiCheckRunsState, getPullRequestHeadState, isGitHubAppConfigured } = await import("./github-app-
|
|
28954
|
+
const { getCiCheckRunsState, getPullRequestHeadState, isGitHubAppConfigured } = await import("./github-app-CU14oYzP.js");
|
|
27985
28955
|
return reconcileTestStatusFromGreenCiWithDeps({
|
|
27986
28956
|
isGitHubAppConfigured,
|
|
27987
28957
|
loadReviewStatuses,
|
|
@@ -28002,7 +28972,7 @@ async function reconcileTestStatusFromGreenCi() {
|
|
|
28002
28972
|
*/
|
|
28003
28973
|
async function clearStaleCiFeedback(issueId) {
|
|
28004
28974
|
const { readdir, rm } = await import("fs/promises");
|
|
28005
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
28975
|
+
const { resolveProjectFromIssueSync } = await import("./projects-BKkwpH6q.js");
|
|
28006
28976
|
const projectConfig = resolveProjectFromIssueSync(issueId);
|
|
28007
28977
|
if (!projectConfig) return;
|
|
28008
28978
|
const repoDir = projectConfig.projectPath;
|
|
@@ -28298,7 +29268,7 @@ async function checkWorkspaceContainerHealth(sharedState) {
|
|
|
28298
29268
|
}
|
|
28299
29269
|
}
|
|
28300
29270
|
try {
|
|
28301
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
29271
|
+
const { resolveProjectFromIssueSync } = await import("./projects-BKkwpH6q.js");
|
|
28302
29272
|
const resolved = resolveProjectFromIssueSync(issueLower.toUpperCase());
|
|
28303
29273
|
if (resolved) await killOrphanedWorkspaceProcesses(`${resolved.projectPath}/workspaces/feature-${issueLower}`);
|
|
28304
29274
|
} catch {}
|
|
@@ -28347,8 +29317,8 @@ async function checkWorkspaceContainerHealth(sharedState) {
|
|
|
28347
29317
|
async function checkMergedWorkSessions() {
|
|
28348
29318
|
const actions = [];
|
|
28349
29319
|
try {
|
|
28350
|
-
const { selectMergedWorkSessions } = await import("./reap-terminal-sessions-
|
|
28351
|
-
const { setAgentPaused } = await import("./agents-
|
|
29320
|
+
const { selectMergedWorkSessions } = await import("./reap-terminal-sessions-CaMkFOIH.js");
|
|
29321
|
+
const { setAgentPaused } = await import("./agents-DyHKlq1I.js");
|
|
28352
29322
|
const toKill = selectMergedWorkSessions(loadReviewStatuses(), [...await Effect.runPromise(listSessionNames())]);
|
|
28353
29323
|
for (const session of toKill) try {
|
|
28354
29324
|
await Effect.runPromise(setAgentPaused(session, "merged — awaiting close-out (verify on main)", true));
|
|
@@ -28388,7 +29358,7 @@ const AWAITING_TEST_IDLE_REAP_MS = 600 * 1e3;
|
|
|
28388
29358
|
async function checkAwaitingTestWorkSessions() {
|
|
28389
29359
|
const actions = [];
|
|
28390
29360
|
try {
|
|
28391
|
-
const { selectAwaitingTestWorkSessions } = await import("./reap-terminal-sessions-
|
|
29361
|
+
const { selectAwaitingTestWorkSessions } = await import("./reap-terminal-sessions-CaMkFOIH.js");
|
|
28392
29362
|
const candidates = selectAwaitingTestWorkSessions(loadReviewStatuses(), [...await Effect.runPromise(listSessionNames())]);
|
|
28393
29363
|
const now = Date.now();
|
|
28394
29364
|
for (const session of candidates) {
|
|
@@ -28441,14 +29411,14 @@ async function runPatrol() {
|
|
|
28441
29411
|
hasLoggedGlobalPauseSkip = false;
|
|
28442
29412
|
addLog("info", `Patrol cycle ${state.patrolCycle} — checking per-project specialists`, state.patrolCycle);
|
|
28443
29413
|
console.log(`[deacon] Patrol cycle ${state.patrolCycle} - checking per-project specialists`);
|
|
28444
|
-
for (const a of await (await import("./stale-task-claims-
|
|
29414
|
+
for (const a of await (await import("./stale-task-claims-L7pJkQFL.js")).patrolStaleTaskClaims()) {
|
|
28445
29415
|
actions.push(a);
|
|
28446
29416
|
addLog("action", a, state.patrolCycle);
|
|
28447
29417
|
}
|
|
28448
29418
|
const stuckRemediationActions = await checkStuckAgentRemediation();
|
|
28449
29419
|
actions.push(...stuckRemediationActions);
|
|
28450
29420
|
for (const a of stuckRemediationActions) addLog("action", a, state.patrolCycle);
|
|
28451
|
-
const { reconcileInFlightJournals } = await import("./advancing-selfheal-
|
|
29421
|
+
const { reconcileInFlightJournals } = await import("./advancing-selfheal-cSvXNZLZ.js");
|
|
28452
29422
|
const reconciledJournalActions = await reconcileInFlightJournals();
|
|
28453
29423
|
actions.push(...reconciledJournalActions);
|
|
28454
29424
|
for (const a of reconciledJournalActions) addLog("action", a, state.patrolCycle);
|
|
@@ -28460,7 +29430,7 @@ async function runPatrol() {
|
|
|
28460
29430
|
const age = Date.now() - (pending.timestamp ?? 0);
|
|
28461
29431
|
if (age < 3600 * 1e3) {
|
|
28462
29432
|
console.log(`[deacon] Processing pending post-merge lifecycle for ${pending.issueId} (age: ${Math.round(age / 1e3)}s)`);
|
|
28463
|
-
const { postMergeLifecycle } = await import("./merge-agent-
|
|
29433
|
+
const { postMergeLifecycle } = await import("./merge-agent-B-SnXOoc.js");
|
|
28464
29434
|
const { unlinkSync } = await import("fs");
|
|
28465
29435
|
unlinkSync(pendingFile);
|
|
28466
29436
|
await postMergeLifecycle(pending.issueId, pending.projectPath, pending.sourceBranch, { skipDeploy: true });
|
|
@@ -28474,7 +29444,7 @@ async function runPatrol() {
|
|
|
28474
29444
|
} catch (err) {
|
|
28475
29445
|
console.warn(`[deacon] Failed to process pending lifecycle: ${err.message}`);
|
|
28476
29446
|
}
|
|
28477
|
-
if (state.patrolCycle % 5 === 0) await (await import("./deploy-patrol-
|
|
29447
|
+
if (state.patrolCycle % 5 === 0) await (await import("./deploy-patrol-1IrZxicY.js")).runScheduledDeployPatrol();
|
|
28478
29448
|
const livenessActions = await reconcileAgentLiveness();
|
|
28479
29449
|
actions.push(...livenessActions);
|
|
28480
29450
|
for (const a of livenessActions) addLog("action", a, state.patrolCycle);
|
|
@@ -28506,7 +29476,7 @@ async function runPatrol() {
|
|
|
28506
29476
|
actions.push(...suspendActions);
|
|
28507
29477
|
for (const a of suspendActions) addLog("action", a, state.patrolCycle);
|
|
28508
29478
|
try {
|
|
28509
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
29479
|
+
const { resolveProjectFromIssueSync } = await import("./projects-BKkwpH6q.js");
|
|
28510
29480
|
const allStatuses = loadReviewStatuses();
|
|
28511
29481
|
for (const [issueId, status] of Object.entries(allStatuses)) {
|
|
28512
29482
|
if (!status.readyForMerge || status.mergeStatus === "merged") continue;
|
|
@@ -28526,7 +29496,7 @@ async function runPatrol() {
|
|
|
28526
29496
|
} catch (err) {
|
|
28527
29497
|
console.warn(`[deacon] Failed to check workspace existence: ${err.message}`);
|
|
28528
29498
|
}
|
|
28529
|
-
const { checkMergedAdvancingSessions } = await import("./advancing-selfheal-
|
|
29499
|
+
const { checkMergedAdvancingSessions } = await import("./advancing-selfheal-cSvXNZLZ.js");
|
|
28530
29500
|
const reapedWorkActions = await checkMergedWorkSessions();
|
|
28531
29501
|
actions.push(...reapedWorkActions);
|
|
28532
29502
|
for (const a of reapedWorkActions) addLog("action", a, state.patrolCycle);
|
|
@@ -28534,7 +29504,7 @@ async function runPatrol() {
|
|
|
28534
29504
|
actions.push(...reapedMergedAdvancingActions);
|
|
28535
29505
|
for (const a of reapedMergedAdvancingActions) addLog("action", a, state.patrolCycle);
|
|
28536
29506
|
try {
|
|
28537
|
-
const { refreshClaudeCredentialsForActiveRemoteAgents } = await import("./remote-completion-
|
|
29507
|
+
const { refreshClaudeCredentialsForActiveRemoteAgents } = await import("./remote-completion-Dca3hAaa.js");
|
|
28538
29508
|
const remoteCredentialActions = await refreshClaudeCredentialsForActiveRemoteAgents();
|
|
28539
29509
|
actions.push(...remoteCredentialActions);
|
|
28540
29510
|
for (const a of remoteCredentialActions) addLog(a.includes("failed") ? "warn" : "action", a, state.patrolCycle);
|
|
@@ -28542,7 +29512,7 @@ async function runPatrol() {
|
|
|
28542
29512
|
addLog("warn", `Remote credential refresh patrol failed: ${err.message}`, state.patrolCycle);
|
|
28543
29513
|
}
|
|
28544
29514
|
try {
|
|
28545
|
-
const { refreshHostHeartbeatForEphemeralVms } = await import("./remote-agents-
|
|
29515
|
+
const { refreshHostHeartbeatForEphemeralVms } = await import("./remote-agents-D6O_zETW.js");
|
|
28546
29516
|
const heartbeatActions = await refreshHostHeartbeatForEphemeralVms();
|
|
28547
29517
|
actions.push(...heartbeatActions);
|
|
28548
29518
|
for (const a of heartbeatActions) addLog(a.includes("failed") ? "warn" : "action", a, state.patrolCycle);
|
|
@@ -28550,7 +29520,7 @@ async function runPatrol() {
|
|
|
28550
29520
|
addLog("warn", `Remote heartbeat refresh patrol failed: ${err.message}`, state.patrolCycle);
|
|
28551
29521
|
}
|
|
28552
29522
|
try {
|
|
28553
|
-
const { reapCompletedRemoteAgents } = await import("./remote-completion-
|
|
29523
|
+
const { reapCompletedRemoteAgents } = await import("./remote-completion-Dca3hAaa.js");
|
|
28554
29524
|
const remoteReap = await reapCompletedRemoteAgents();
|
|
28555
29525
|
for (const r of remoteReap) if (r.status === "handed-off" || r.status === "error") {
|
|
28556
29526
|
const msg = `Remote reap ${r.issueId}: ${r.status} (${r.details.join("; ")})`;
|
|
@@ -28735,7 +29705,7 @@ async function runPatrol() {
|
|
|
28735
29705
|
const issueId = runtimeState.currentIssue;
|
|
28736
29706
|
try {
|
|
28737
29707
|
if (getReviewStatusSync(issueId)?.mergeStatus === "merging") {
|
|
28738
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
29708
|
+
const { resolveProjectFromIssueSync } = await import("./projects-BKkwpH6q.js");
|
|
28739
29709
|
const resolved = resolveProjectFromIssueSync(issueId);
|
|
28740
29710
|
if (resolved) {
|
|
28741
29711
|
const branch = `feature/${issueId.toLowerCase()}`;
|
|
@@ -28749,7 +29719,7 @@ async function runPatrol() {
|
|
|
28749
29719
|
mergeStatus: "merged",
|
|
28750
29720
|
readyForMerge: false
|
|
28751
29721
|
});
|
|
28752
|
-
const { postMergeLifecycle } = await import("./merge-agent-
|
|
29722
|
+
const { postMergeLifecycle } = await import("./merge-agent-B-SnXOoc.js");
|
|
28753
29723
|
postMergeLifecycle(issueId, resolved.projectPath).catch((err) => console.warn(`[deacon] postMergeLifecycle failed for ${issueId}: ${err}`));
|
|
28754
29724
|
actions.push(`Auto-completed stale merge for ${issueId}`);
|
|
28755
29725
|
} else {
|
|
@@ -28929,7 +29899,7 @@ function startDeacon() {
|
|
|
28929
29899
|
logDeaconEventSync(`startDeacon: health monitor starting (patrol every ${config.patrolIntervalMs / 1e3}s)`);
|
|
28930
29900
|
(async () => {
|
|
28931
29901
|
await reconcileAgentLiveness();
|
|
28932
|
-
const { runBootAdvancingSelfHeal } = await import("./advancing-selfheal-
|
|
29902
|
+
const { runBootAdvancingSelfHeal } = await import("./advancing-selfheal-cSvXNZLZ.js");
|
|
28933
29903
|
await runBootAdvancingSelfHeal();
|
|
28934
29904
|
runScheduledPatrol("startup");
|
|
28935
29905
|
})().catch((err) => {
|
|
@@ -28999,6 +29969,6 @@ function assessDeaconPatrolFreshness(params) {
|
|
|
28999
29969
|
};
|
|
29000
29970
|
}
|
|
29001
29971
|
//#endregion
|
|
29002
|
-
export {
|
|
29972
|
+
export { reconcileClosedPrReadyForMerge as $, reconcileAgentLiveness as A, getAcceptedSystemHealthSnapshot as At, recordDeadEndNeedsYou as B, getLastPatrolResult as C, INSPECT_TIMEOUT_MS as Ct, isDeaconRunning as D, formatUptime as Dt, handleAgentStoppedForOrphanReviewerSessions as E, getResourceStacks as Et, setAgentStatusChangedNotifier as F, isSmeeConfiguredSync as Ft, redeliverUndeliveredKickoffs as G, isRapidPostResumeDeath as H, setAgentStoppedNotifier as I, startSmeeProcessSync as It, startBootReconciliation as J, isBootReconciliationCandidate as K, setMergeReadyNotifier as L, classifyAgentHealth as Lt, resetPatrolHeartbeatForStartup as M, getResourceConfig as Mt, runPatrol as N, getSystemHealthEvidenceSnapshot as Nt, loadConfig as O, getContainerHistory as Ot, saveState as P, getSystemHealthSnapshot as Pt, ciRetryMap as Q, startDeacon as R, getDeaconStatus as S, paneShowsClaudeBootBlockingScreen as St, handleAgentStoppedEvent as T, classifyMemoryPressure as Tt, nudgeIdleWorkAgentsWithOpenBeads as U, isPreKickoffLaunchDeath as V, nudgeStalledResumeWorkAgents as W, checkFailedMergeRetry as X, autoCloseOut as Y, checkFirstCompletionAgents as Z, cleanupOrphanReviewerSessions as _, stalledReviewConvoyRecoveryState as _t, checkCompletedButUnsignaledTests as a, cleanupOrphanedReviewSessions as at, containerRestartBackoffMs as b, contextProactiveCompactState as bt, checkMergedWorkSessions as c, checkCompletedButUnsignaledReviews as ct, checkPostReviewCommits as d, checkMissingReviewStatuses as dt, reconcileFalseMerged as et, checkReadyForMergeStuck as f, checkOrphanedReviewStatuses as ft, cleanupAbandonedFeedback as g, reviewConvoyLiveness as gt, checkWorkspaceContainerHealth as h, recoverStalledReviewConvoys as ht, checkAwaitingTestWorkSessions as i, reconcileStuckReadyForMerge as it, reconcileTestStatusFromGreenCi as j, getDeployStaleness as jt, loadState as k, getCurrentDockerStats as kt, checkOrphanedCompletions as l, checkStuckReviewing as lt, checkVerificationReviewContradiction as m, handleWorkCompleted as mt, assessDeaconPatrolFreshness as n, reconcileStaleMergeBlockers as nt, checkDeadEndAgents as o, monitorReviewConvoySignals as ot, checkStuckWorkAgents as p, handleReviewCoordinatorDied as pt, listBootReconciliationCandidates as q, checkAndSuspendIdleAgents as r, reconcileStaleMergeStatus as rt, checkMassDeath as s, synthesizeReviewFromReports as st, applyBootReconciliationDecision as t, reconcileMergedButReviewing as tt, checkPendingTestDispatch as u, isSynthesisForActiveReviewRun as ut, cleanupOrphanedPlanningSessions as v, checkApiErrorAgents as vt, handleAgentHeartbeatDeadEvent as w, checkInspectAgentTimeouts as wt, getDeaconLogs as x, stuckOverflowNativeRecoveryState as xt, cleanupStaleAgentState as y, contextOverflowRecoveryState as yt, stopDeacon as z };
|
|
29003
29973
|
|
|
29004
|
-
//# sourceMappingURL=deacon-
|
|
29974
|
+
//# sourceMappingURL=deacon-CkT_kznS.js.map
|