@repo-os/repoos 0.5.45
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/LICENSE.md +110 -0
- package/README.md +272 -0
- package/dist/.build-info.json +4 -0
- package/dist/.build-stamp.json +3 -0
- package/dist/cli/colors.d.ts +13 -0
- package/dist/cli/colors.js +37 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +221 -0
- package/dist/commands/check.d.ts +170 -0
- package/dist/commands/check.js +1227 -0
- package/dist/commands/docs.d.ts +2 -0
- package/dist/commands/docs.js +70 -0
- package/dist/commands/gc.d.ts +1 -0
- package/dist/commands/gc.js +57 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.js +699 -0
- package/dist/commands/screenshots.d.ts +7 -0
- package/dist/commands/screenshots.js +77 -0
- package/dist/commands/serve.d.ts +55 -0
- package/dist/commands/serve.js +204 -0
- package/dist/commands/status.d.ts +140 -0
- package/dist/commands/status.js +569 -0
- package/dist/commands/stop.d.ts +1 -0
- package/dist/commands/stop.js +59 -0
- package/dist/commands/tasks.d.ts +47 -0
- package/dist/commands/tasks.js +334 -0
- package/dist/commands/tunnel.d.ts +1 -0
- package/dist/commands/tunnel.js +1271 -0
- package/dist/commands/ui-harness.d.ts +53 -0
- package/dist/commands/ui-harness.js +62 -0
- package/dist/commands/ui-smoke.d.ts +6 -0
- package/dist/commands/ui-smoke.js +220 -0
- package/dist/commands/upgrade.d.ts +15 -0
- package/dist/commands/upgrade.js +188 -0
- package/dist/core/auth-store.d.ts +81 -0
- package/dist/core/auth-store.js +530 -0
- package/dist/core/auth.d.ts +75 -0
- package/dist/core/auth.js +124 -0
- package/dist/core/bootstrap.d.ts +41 -0
- package/dist/core/bootstrap.js +236 -0
- package/dist/core/build.d.ts +92 -0
- package/dist/core/build.js +249 -0
- package/dist/core/canary.d.ts +10 -0
- package/dist/core/canary.js +14 -0
- package/dist/core/check-failure-summary.d.ts +10 -0
- package/dist/core/check-failure-summary.js +34 -0
- package/dist/core/config.d.ts +160 -0
- package/dist/core/config.js +1288 -0
- package/dist/core/context-pack.d.ts +74 -0
- package/dist/core/context-pack.js +778 -0
- package/dist/core/db.d.ts +236 -0
- package/dist/core/db.js +747 -0
- package/dist/core/detect.d.ts +69 -0
- package/dist/core/detect.js +251 -0
- package/dist/core/docs.d.ts +76 -0
- package/dist/core/docs.js +225 -0
- package/dist/core/frontmatter.d.ts +29 -0
- package/dist/core/frontmatter.js +215 -0
- package/dist/core/git.d.ts +505 -0
- package/dist/core/git.js +1453 -0
- package/dist/core/indexer.d.ts +33 -0
- package/dist/core/indexer.js +282 -0
- package/dist/core/input.d.ts +66 -0
- package/dist/core/input.js +222 -0
- package/dist/core/logger.d.ts +70 -0
- package/dist/core/logger.js +138 -0
- package/dist/core/models.d.ts +45 -0
- package/dist/core/models.js +291 -0
- package/dist/core/net-probe.d.ts +4 -0
- package/dist/core/net-probe.js +20 -0
- package/dist/core/providers/deepinfra.d.ts +23 -0
- package/dist/core/providers/deepinfra.js +44 -0
- package/dist/core/providers/index.d.ts +24 -0
- package/dist/core/providers/index.js +59 -0
- package/dist/core/providers/openrouter.d.ts +28 -0
- package/dist/core/providers/openrouter.js +82 -0
- package/dist/core/providers/spend.d.ts +86 -0
- package/dist/core/providers/spend.js +286 -0
- package/dist/core/providers/types.d.ts +56 -0
- package/dist/core/providers/types.js +39 -0
- package/dist/core/repoos.d.ts +59 -0
- package/dist/core/repoos.js +221 -0
- package/dist/core/runtime.d.ts +35 -0
- package/dist/core/runtime.js +167 -0
- package/dist/core/skills-registry.d.ts +39 -0
- package/dist/core/skills-registry.js +148 -0
- package/dist/core/skills-registry.test.d.ts +1 -0
- package/dist/core/skills-registry.test.js +52 -0
- package/dist/core/sysmem.d.ts +7 -0
- package/dist/core/sysmem.js +55 -0
- package/dist/core/tailscale.d.ts +2 -0
- package/dist/core/tailscale.js +19 -0
- package/dist/core/task.d.ts +53 -0
- package/dist/core/task.js +310 -0
- package/dist/core/toml-line.d.ts +20 -0
- package/dist/core/toml-line.js +52 -0
- package/dist/core/toml-validate.d.ts +44 -0
- package/dist/core/toml-validate.js +335 -0
- package/dist/core/tunnel-assistant.d.ts +30 -0
- package/dist/core/tunnel-assistant.js +65 -0
- package/dist/core/tunnel-registry.d.ts +96 -0
- package/dist/core/tunnel-registry.js +267 -0
- package/dist/core/tunnel-registry.test.d.ts +1 -0
- package/dist/core/tunnel-registry.test.js +309 -0
- package/dist/core/tunnel.d.ts +103 -0
- package/dist/core/tunnel.js +320 -0
- package/dist/core/types.d.ts +811 -0
- package/dist/core/types.js +27 -0
- package/dist/core/worktree-gc.d.ts +57 -0
- package/dist/core/worktree-gc.js +194 -0
- package/dist/server/__tests__/integration-job.test.d.ts +1 -0
- package/dist/server/__tests__/integration-job.test.js +129 -0
- package/dist/server/agents.d.ts +1020 -0
- package/dist/server/agents.js +4070 -0
- package/dist/server/attachments.d.ts +51 -0
- package/dist/server/attachments.js +130 -0
- package/dist/server/auto-engineering.d.ts +45 -0
- package/dist/server/auto-engineering.js +275 -0
- package/dist/server/branchless-release.d.ts +22 -0
- package/dist/server/branchless-release.js +67 -0
- package/dist/server/built-in-agents.d.ts +305 -0
- package/dist/server/built-in-agents.js +1838 -0
- package/dist/server/cto-monitor.d.ts +35 -0
- package/dist/server/cto-monitor.js +281 -0
- package/dist/server/cto.d.ts +125 -0
- package/dist/server/cto.js +590 -0
- package/dist/server/deployments.d.ts +119 -0
- package/dist/server/deployments.js +325 -0
- package/dist/server/diff-snapshot.d.ts +20 -0
- package/dist/server/diff-snapshot.js +73 -0
- package/dist/server/done.d.ts +160 -0
- package/dist/server/done.js +488 -0
- package/dist/server/freeform.d.ts +55 -0
- package/dist/server/freeform.js +179 -0
- package/dist/server/handoff.d.ts +99 -0
- package/dist/server/handoff.js +575 -0
- package/dist/server/hetzner.d.ts +45 -0
- package/dist/server/hetzner.js +117 -0
- package/dist/server/icons.d.ts +8 -0
- package/dist/server/icons.js +195 -0
- package/dist/server/integration-job.d.ts +75 -0
- package/dist/server/integration-job.js +144 -0
- package/dist/server/integration-orchestrator.d.ts +211 -0
- package/dist/server/integration-orchestrator.js +1299 -0
- package/dist/server/integration-status.d.ts +48 -0
- package/dist/server/integration-status.js +71 -0
- package/dist/server/live-index.d.ts +295 -0
- package/dist/server/live-index.js +452 -0
- package/dist/server/model-test.d.ts +20 -0
- package/dist/server/model-test.js +100 -0
- package/dist/server/ntfy.d.ts +57 -0
- package/dist/server/ntfy.js +112 -0
- package/dist/server/pm-attachments.d.ts +35 -0
- package/dist/server/pm-attachments.js +181 -0
- package/dist/server/pm-runs.d.ts +58 -0
- package/dist/server/pm-runs.js +80 -0
- package/dist/server/preview.d.ts +174 -0
- package/dist/server/preview.js +641 -0
- package/dist/server/release.d.ts +88 -0
- package/dist/server/release.js +449 -0
- package/dist/server/reload.d.ts +194 -0
- package/dist/server/reload.js +586 -0
- package/dist/server/remote-validation.d.ts +132 -0
- package/dist/server/remote-validation.js +478 -0
- package/dist/server/repo-lock.d.ts +36 -0
- package/dist/server/repo-lock.js +141 -0
- package/dist/server/review-guard.d.ts +14 -0
- package/dist/server/review-guard.js +159 -0
- package/dist/server/review.d.ts +243 -0
- package/dist/server/review.js +1211 -0
- package/dist/server/routes/agents.d.ts +6 -0
- package/dist/server/routes/agents.js +28 -0
- package/dist/server/routes/auth.d.ts +60 -0
- package/dist/server/routes/auth.js +755 -0
- package/dist/server/routes/config.d.ts +20 -0
- package/dist/server/routes/config.js +347 -0
- package/dist/server/routes/debugger.d.ts +33 -0
- package/dist/server/routes/debugger.js +360 -0
- package/dist/server/routes/deployments.d.ts +3 -0
- package/dist/server/routes/deployments.js +16 -0
- package/dist/server/routes/docs.d.ts +8 -0
- package/dist/server/routes/docs.js +135 -0
- package/dist/server/routes/helpers.d.ts +21 -0
- package/dist/server/routes/helpers.js +171 -0
- package/dist/server/routes/index.d.ts +19 -0
- package/dist/server/routes/index.js +18 -0
- package/dist/server/routes/info.d.ts +17 -0
- package/dist/server/routes/info.js +177 -0
- package/dist/server/routes/inputs.d.ts +7 -0
- package/dist/server/routes/inputs.js +125 -0
- package/dist/server/routes/model-providers.d.ts +27 -0
- package/dist/server/routes/model-providers.js +94 -0
- package/dist/server/routes/models.d.ts +3 -0
- package/dist/server/routes/models.js +36 -0
- package/dist/server/routes/notify.d.ts +2 -0
- package/dist/server/routes/notify.js +17 -0
- package/dist/server/routes/playground.d.ts +29 -0
- package/dist/server/routes/playground.js +81 -0
- package/dist/server/routes/release.d.ts +20 -0
- package/dist/server/routes/release.js +86 -0
- package/dist/server/routes/router.d.ts +12 -0
- package/dist/server/routes/router.js +32 -0
- package/dist/server/routes/skill-registry.d.ts +5 -0
- package/dist/server/routes/skill-registry.js +51 -0
- package/dist/server/routes/tasks.d.ts +58 -0
- package/dist/server/routes/tasks.js +1442 -0
- package/dist/server/routes/transcribe.d.ts +2 -0
- package/dist/server/routes/transcribe.js +124 -0
- package/dist/server/routes/types.d.ts +68 -0
- package/dist/server/routes/types.js +1 -0
- package/dist/server/routes/ui.d.ts +5 -0
- package/dist/server/routes/ui.js +81 -0
- package/dist/server/routes/utils.d.ts +3 -0
- package/dist/server/routes/utils.js +23 -0
- package/dist/server/serve-reaper.d.ts +135 -0
- package/dist/server/serve-reaper.js +491 -0
- package/dist/server/server.d.ts +49 -0
- package/dist/server/server.js +2171 -0
- package/dist/server/supervisor.d.ts +89 -0
- package/dist/server/supervisor.js +231 -0
- package/dist/server/system.d.ts +198 -0
- package/dist/server/system.js +480 -0
- package/dist/server/task-check.d.ts +45 -0
- package/dist/server/task-check.js +71 -0
- package/dist/server/task-transitions.d.ts +51 -0
- package/dist/server/task-transitions.js +78 -0
- package/dist/server/task-watchdog.d.ts +158 -0
- package/dist/server/task-watchdog.js +681 -0
- package/dist/server/test-run.d.ts +28 -0
- package/dist/server/test-run.js +81 -0
- package/dist/server/watcher.d.ts +21 -0
- package/dist/server/watcher.js +194 -0
- package/dist/server/write.d.ts +94 -0
- package/dist/server/write.js +345 -0
- package/dist/ui/assets/AgentsView-CF4wRvHh.css +1 -0
- package/dist/ui/assets/AgentsView-D-myL-kA.js +1 -0
- package/dist/ui/assets/ContextView-D3TC-RSp.css +1 -0
- package/dist/ui/assets/ContextView-DsOqAdyE.js +4 -0
- package/dist/ui/assets/DashboardView-BOhsIJqO.js +1 -0
- package/dist/ui/assets/DashboardView-Ck9o0RP2.css +1 -0
- package/dist/ui/assets/DeploymentsView--iIUVfEH.css +1 -0
- package/dist/ui/assets/DeploymentsView-DXu_FYR2.js +1 -0
- package/dist/ui/assets/InputsView-24HVbVPk.js +1 -0
- package/dist/ui/assets/InputsView-BLb7GHtx.css +1 -0
- package/dist/ui/assets/LoginView-6QlGg6cx.css +1 -0
- package/dist/ui/assets/LoginView-BqupI0Lt.js +1 -0
- package/dist/ui/assets/ReleasesView-BEG1A0YH.css +1 -0
- package/dist/ui/assets/ReleasesView-CAgMuxpe.js +3 -0
- package/dist/ui/assets/SettingsView-CA-NYSMK.css +1 -0
- package/dist/ui/assets/SettingsView-O3iZSnjg.js +3 -0
- package/dist/ui/assets/WorkView-D8Tl6qwy.js +1 -0
- package/dist/ui/assets/WorkView-DMYL2s3W.css +1 -0
- package/dist/ui/assets/abnfDiagram-VCTEODGH-J5lkSnEE.js +1 -0
- package/dist/ui/assets/arc-BHZnmhhM.js +1 -0
- package/dist/ui/assets/architecture-7GRP2DOG-pLdFt-xS.js +1 -0
- package/dist/ui/assets/architectureDiagram-5GKGNRK7-C3k89uKX.js +36 -0
- package/dist/ui/assets/array-BifhSqXX.js +1 -0
- package/dist/ui/assets/blockDiagram-I7D4REHJ-AWNoBzop.js +129 -0
- package/dist/ui/assets/button-lbikqSph.js +1 -0
- package/dist/ui/assets/c4Diagram-7LVT6UL2-DKG1D5gd.js +38 -0
- package/dist/ui/assets/channel-gA4qBv3A.js +1 -0
- package/dist/ui/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/dist/ui/assets/chunk-4HAMMTFA-D1YR8lF_.js +62 -0
- package/dist/ui/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/dist/ui/assets/chunk-75Z2AOVW-5GuBxfsL.js +2 -0
- package/dist/ui/assets/chunk-DU6HZSFF-DfdNNqwa.js +127 -0
- package/dist/ui/assets/chunk-F27PBJKO-BPZzinQ4.js +1 -0
- package/dist/ui/assets/chunk-FOHPRMQF-l2z4K2jD.js +161 -0
- package/dist/ui/assets/chunk-GMAD6QVW-DGWvSKj5.js +72 -0
- package/dist/ui/assets/chunk-GVQU2GXP-D6Aw75wJ.js +1 -0
- package/dist/ui/assets/chunk-IMKFNOWR-B8mMBKCW.js +231 -0
- package/dist/ui/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/dist/ui/assets/chunk-L3NEJ4N5-D5OJuXYE.js +1 -0
- package/dist/ui/assets/chunk-OSK3NFVY-B7r9w2UW.js +10 -0
- package/dist/ui/assets/chunk-P2QGCYS3-C74X4AQX.js +1 -0
- package/dist/ui/assets/chunk-POPQ4Y6H-C5_u1gUS.js +1 -0
- package/dist/ui/assets/chunk-PWAF6VOD-DfoTLtxn.js +1 -0
- package/dist/ui/assets/chunk-SHT3W25Y-D40m2eqz.js +168 -0
- package/dist/ui/assets/chunk-SVP7TREG-euxi0Kap.js +88 -0
- package/dist/ui/assets/chunk-TICWLB2K-fkdxngzN.js +206 -0
- package/dist/ui/assets/chunk-XXDRQBXY-DFBUG-OT.js +1 -0
- package/dist/ui/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/dist/ui/assets/classDiagram-ZZMXUADV-BzW8bq2P.js +1 -0
- package/dist/ui/assets/classDiagram-v2-VYDZK3BY-BzW8bq2P.js +1 -0
- package/dist/ui/assets/cose-bilkent-JH36ORCC-BTcgMon1.js +1 -0
- package/dist/ui/assets/cynefin-OW5HDTMX-B5m_COsS.js +1 -0
- package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-C-AG6CGe.js +62 -0
- package/dist/ui/assets/cytoscape.esm-FBntH-9t.js +321 -0
- package/dist/ui/assets/dagre-GXQ25YYZ-DDfDnp8L.js +4 -0
- package/dist/ui/assets/dagre-PrKaheQc.js +1 -0
- package/dist/ui/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/dist/ui/assets/diagram-S7CK7UJ4-DjQZAlEY.js +30 -0
- package/dist/ui/assets/diagram-UQ7AKVKN-DAZ9yp1B.js +41 -0
- package/dist/ui/assets/diagram-VSXAHHWV-BWepUKJD.js +3 -0
- package/dist/ui/assets/diagram-VX7I27RA-EcV1J81b.js +24 -0
- package/dist/ui/assets/diagram-Z3DM3KII-Dbz7XU_K.js +24 -0
- package/dist/ui/assets/dist-DTg6UBE_.js +1 -0
- package/dist/ui/assets/ebnfDiagram-PWID7BFC-BUyQw8Mm.js +1 -0
- package/dist/ui/assets/erDiagram-RLTQ6QDP-WVf8ukKt.js +99 -0
- package/dist/ui/assets/eventmodeling-NTZA5JFV-DHqyLOAn.js +1 -0
- package/dist/ui/assets/flowDiagram-HODETNUW-CYk_ze5K.js +1 -0
- package/dist/ui/assets/ganttDiagram-EL5Y4UJY-rB4MZuB-.js +292 -0
- package/dist/ui/assets/gitGraph-4MIJSDKK-BOTWM8dY.js +1 -0
- package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-eYscuhtP.js +106 -0
- package/dist/ui/assets/graphlib-DS17s2tU.js +1 -0
- package/dist/ui/assets/index-BACBfnga.css +1 -0
- package/dist/ui/assets/index-BOQ-ust6.js +26 -0
- package/dist/ui/assets/info-A6RAGUB7-_67wOORe.js +1 -0
- package/dist/ui/assets/infoDiagram-27XIBGKW-XVXbddTA.js +2 -0
- package/dist/ui/assets/init-C-OQMol4.js +1 -0
- package/dist/ui/assets/ishikawaDiagram-5VMMS53U-ClLNiEru.js +70 -0
- package/dist/ui/assets/journeyDiagram-3NMN7TZE-NRawjR6i.js +139 -0
- package/dist/ui/assets/kanban-definition-UXKFOSKX-BgSzBfIx.js +89 -0
- package/dist/ui/assets/katex-DolUETbr.js +257 -0
- package/dist/ui/assets/line-KAyfuul4.js +1 -0
- package/dist/ui/assets/linear-cCCPOpu7.js +1 -0
- package/dist/ui/assets/mermaid-parser.core-CgXZk1iN.js +7 -0
- package/dist/ui/assets/mermaid.core-BUUkChHW.js +44 -0
- package/dist/ui/assets/mindmap-definition-YA3MSWOX-Cpn7vW4r.js +96 -0
- package/dist/ui/assets/ordinal-BDEzSJ7C.js +1 -0
- package/dist/ui/assets/packet-AYTQ26CC-0lZwM-d6.js +1 -0
- package/dist/ui/assets/path-COt_16Va.js +1 -0
- package/dist/ui/assets/pegDiagram-XKGWAZYB-impy0inn.js +1 -0
- package/dist/ui/assets/pie-WAS4IAKB-CqfdGHYg.js +1 -0
- package/dist/ui/assets/pieDiagram-E7YTZNPT-CxjL4I1h.js +39 -0
- package/dist/ui/assets/quadrantDiagram-AXDQQJYC-Cjd1QMIe.js +7 -0
- package/dist/ui/assets/radar-RG4KPBEZ-CRkQIwiv.js +1 -0
- package/dist/ui/assets/railroad-74A4TZTK-i67XSWTB.js +1 -0
- package/dist/ui/assets/railroad-abnf-HS5TGJTU-Cv9m5aS3.js +1 -0
- package/dist/ui/assets/railroad-ebnf-LZEXJU2U-C5ZIn-Jh.js +1 -0
- package/dist/ui/assets/railroad-peg-WCYAUIDC-CGra9Oq-.js +1 -0
- package/dist/ui/assets/railroadDiagram-O6MQD6OU-_pK0qyaY.js +1 -0
- package/dist/ui/assets/releases-B0WNV-SY.js +1 -0
- package/dist/ui/assets/repoos-cto-square.webp +0 -0
- package/dist/ui/assets/repoos-helpful-pm-square.webp +0 -0
- package/dist/ui/assets/repoos-orchestrator-square.webp +0 -0
- package/dist/ui/assets/repoos-performance-agent-square.webp +0 -0
- package/dist/ui/assets/repoos-ross-from-friends-square.webp +0 -0
- package/dist/ui/assets/repoos-tech-debt-agent-square.webp +0 -0
- package/dist/ui/assets/requirementDiagram-BXWQKSXE-CRrFX-yw.js +84 -0
- package/dist/ui/assets/rough.esm-By172zw-.js +1 -0
- package/dist/ui/assets/sankeyDiagram-P5KCCOFB-X_xFRj9E.js +40 -0
- package/dist/ui/assets/sequenceDiagram-WJ2MYXX4-Byb49lKf.js +162 -0
- package/dist/ui/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- package/dist/ui/assets/src-BH-TyZbA.js +1 -0
- package/dist/ui/assets/stateDiagram-D77RDMKH-CzaPrqYF.js +1 -0
- package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-BCXckz7K.js +1 -0
- package/dist/ui/assets/swimlanes-42K2YHIH-Cx_1lnqr.js +1 -0
- package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-54qsKi6A.js +8 -0
- package/dist/ui/assets/timeline-definition-24CTP7MA-B1IbZPQ-.js +120 -0
- package/dist/ui/assets/treeView-Q6P3EWNA-DFWhVE3d.js +1 -0
- package/dist/ui/assets/treemap-WGGIJYW6-BmbYPThn.js +1 -0
- package/dist/ui/assets/vendor-ui-DPm7zLxi.js +3 -0
- package/dist/ui/assets/vendor-vue-CobgyEJp.js +1 -0
- package/dist/ui/assets/vennDiagram-4TSXK5OY-Ae2AtRpt.js +34 -0
- package/dist/ui/assets/wardley-WFR3VGLG-BtD4X4tL.js +1 -0
- package/dist/ui/assets/wardleyDiagram-VM6X3IG4-B3YN2fTd.js +78 -0
- package/dist/ui/assets/xychartDiagram-S5SC5T6Z-CIzJfMKA.js +7 -0
- package/dist/ui/favicon.svg +11 -0
- package/dist/ui/index.html +49 -0
- package/dist/ui/sw.js +48 -0
- package/package.json +91 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { RepoOSConfig } from "../core/types.js";
|
|
2
|
+
import type { LiveIndex } from "./live-index.js";
|
|
3
|
+
import type { CTOManager } from "./cto.js";
|
|
4
|
+
export declare class CTOMonitor {
|
|
5
|
+
private config;
|
|
6
|
+
private index;
|
|
7
|
+
private cto;
|
|
8
|
+
private timer;
|
|
9
|
+
private eventQueue;
|
|
10
|
+
private eventDebounce;
|
|
11
|
+
private lastDigestHash;
|
|
12
|
+
private lastCheckTime;
|
|
13
|
+
/** Cleared as soon as the worktree becomes active again: one nudge per idle stretch. */
|
|
14
|
+
private nudgedIdleTasks;
|
|
15
|
+
constructor(config: RepoOSConfig, index: LiveIndex, cto: CTOManager);
|
|
16
|
+
start(intervalMs?: number): void;
|
|
17
|
+
stop(): void;
|
|
18
|
+
/** Trigger a monitor check from an event (task status change, review complete, etc). */
|
|
19
|
+
onEvent(reason: string): void;
|
|
20
|
+
checkNow(reason?: string): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Resume a session only after durable evidence says its worktree has been
|
|
23
|
+
* quiet for five minutes. AgentRunner rejects a busy turn, so this can never
|
|
24
|
+
* interrupt an engineer who is merely thinking or running a long command.
|
|
25
|
+
*/
|
|
26
|
+
private nudgeIdleActiveTasks;
|
|
27
|
+
private isIdleLongEnough;
|
|
28
|
+
/** Cooldown survives a server reload, while the in-memory set handles normal idle stretches. */
|
|
29
|
+
private wasRecentlyNudged;
|
|
30
|
+
private buildDigest;
|
|
31
|
+
private checkBuildStaleness;
|
|
32
|
+
private checkZombieProcesses;
|
|
33
|
+
private isTaskStuck;
|
|
34
|
+
private describeStuckSignal;
|
|
35
|
+
}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CTO monitoring loop (0174): periodically builds a board digest and runs the
|
|
3
|
+
* CTO agent to detect stuck tasks, stale reviews, and other board health issues.
|
|
4
|
+
*
|
|
5
|
+
* Triggers: every N seconds (configurable cadence), and on key events:
|
|
6
|
+
* - task status change
|
|
7
|
+
* - review run completes
|
|
8
|
+
* - agent turn exits
|
|
9
|
+
*
|
|
10
|
+
* The digest includes:
|
|
11
|
+
* - task counts and staleness (active with no recent output, review stuck)
|
|
12
|
+
* - stuck patterns (handoff requested, no done; session idle > threshold)
|
|
13
|
+
* - serve processes (zombie checks)
|
|
14
|
+
* - build marker freshness
|
|
15
|
+
*
|
|
16
|
+
* The CTO reads the digest and decides: ignore (nothing wrong), report only,
|
|
17
|
+
* or suggest actions (nudge, escalate, file a bug). All actions are
|
|
18
|
+
* logged and visible to the human. The sole automatic action is one bounded
|
|
19
|
+
* completion nudge to an active engineer after five minutes of real inactivity.
|
|
20
|
+
*/
|
|
21
|
+
import { existsSync, statSync } from "node:fs";
|
|
22
|
+
import { execSync } from "node:child_process";
|
|
23
|
+
import { join } from "node:path";
|
|
24
|
+
import { resolveAgentForTask } from "./agents.js";
|
|
25
|
+
import { hasRecentWorktreeActivity } from "./task-watchdog.js";
|
|
26
|
+
const AUTOMATIC_NUDGE_IDLE_MS = 5 * 60 * 1000;
|
|
27
|
+
const AUTOMATIC_NUDGE_COOLDOWN_MS = 60 * 60 * 1000;
|
|
28
|
+
const AUTOMATIC_NUDGE_MARKER = "CTO nudge: sent engineer a completion reminder";
|
|
29
|
+
/** Simple hash for idempotence checks (not cryptographic). */
|
|
30
|
+
function simpleHash(text) {
|
|
31
|
+
let hash = 0;
|
|
32
|
+
for (let i = 0; i < text.length; i++) {
|
|
33
|
+
const char = text.charCodeAt(i);
|
|
34
|
+
hash = (hash << 5) - hash + char;
|
|
35
|
+
hash = hash & hash; // Convert to 32bit integer
|
|
36
|
+
}
|
|
37
|
+
return Math.abs(hash).toString(36);
|
|
38
|
+
}
|
|
39
|
+
export class CTOMonitor {
|
|
40
|
+
config;
|
|
41
|
+
index;
|
|
42
|
+
cto;
|
|
43
|
+
timer = null;
|
|
44
|
+
eventQueue = [];
|
|
45
|
+
eventDebounce = null;
|
|
46
|
+
lastDigestHash = "";
|
|
47
|
+
lastCheckTime = 0;
|
|
48
|
+
/** Cleared as soon as the worktree becomes active again: one nudge per idle stretch. */
|
|
49
|
+
nudgedIdleTasks = new Set();
|
|
50
|
+
constructor(config, index, cto) {
|
|
51
|
+
this.config = config;
|
|
52
|
+
this.index = index;
|
|
53
|
+
this.cto = cto;
|
|
54
|
+
}
|
|
55
|
+
start(intervalMs = 300_000) {
|
|
56
|
+
if (this.timer)
|
|
57
|
+
return;
|
|
58
|
+
this.timer = setInterval(() => {
|
|
59
|
+
void this.checkNow("timer");
|
|
60
|
+
}, intervalMs);
|
|
61
|
+
}
|
|
62
|
+
stop() {
|
|
63
|
+
if (this.timer) {
|
|
64
|
+
clearInterval(this.timer);
|
|
65
|
+
this.timer = null;
|
|
66
|
+
}
|
|
67
|
+
if (this.eventDebounce) {
|
|
68
|
+
clearTimeout(this.eventDebounce);
|
|
69
|
+
this.eventDebounce = null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Trigger a monitor check from an event (task status change, review complete, etc). */
|
|
73
|
+
onEvent(reason) {
|
|
74
|
+
this.eventQueue.push(reason);
|
|
75
|
+
if (this.eventDebounce)
|
|
76
|
+
clearTimeout(this.eventDebounce);
|
|
77
|
+
this.eventDebounce = setTimeout(() => {
|
|
78
|
+
void this.checkNow("event");
|
|
79
|
+
this.eventQueue = [];
|
|
80
|
+
}, 2000);
|
|
81
|
+
}
|
|
82
|
+
async checkNow(reason = "manual") {
|
|
83
|
+
if (!this.cto.enabled())
|
|
84
|
+
return;
|
|
85
|
+
// This is deliberately independent of the CTO's longer report turn: an
|
|
86
|
+
// engineer nudge should still be timely if a report is in progress.
|
|
87
|
+
this.nudgeIdleActiveTasks();
|
|
88
|
+
if (this.cto.isRunning())
|
|
89
|
+
return;
|
|
90
|
+
const digest = this.buildDigest();
|
|
91
|
+
if (!digest)
|
|
92
|
+
return;
|
|
93
|
+
// Idempotence: skip if digest is identical to last run and nothing new happened
|
|
94
|
+
const digestHash = simpleHash(digest);
|
|
95
|
+
const timeSinceLastCheck = Date.now() - this.lastCheckTime;
|
|
96
|
+
if (digestHash === this.lastDigestHash && timeSinceLastCheck < 60_000) {
|
|
97
|
+
// Same digest within 1 minute — no need to run again
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this.lastDigestHash = digestHash;
|
|
101
|
+
this.lastCheckTime = Date.now();
|
|
102
|
+
await this.cto.run(digest);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Resume a session only after durable evidence says its worktree has been
|
|
106
|
+
* quiet for five minutes. AgentRunner rejects a busy turn, so this can never
|
|
107
|
+
* interrupt an engineer who is merely thinking or running a long command.
|
|
108
|
+
*/
|
|
109
|
+
nudgeIdleActiveTasks() {
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
const activeIds = new Set();
|
|
112
|
+
for (const task of this.index.getTasks("active")) {
|
|
113
|
+
activeIds.add(task.id);
|
|
114
|
+
if (hasRecentWorktreeActivity(this.config.root, task.branch, AUTOMATIC_NUDGE_IDLE_MS, now)) {
|
|
115
|
+
this.nudgedIdleTasks.delete(task.id);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (!this.isIdleLongEnough(task, now) || this.nudgedIdleTasks.has(task.id))
|
|
119
|
+
continue;
|
|
120
|
+
if (this.wasRecentlyNudged(task, now)) {
|
|
121
|
+
this.nudgedIdleTasks.add(task.id);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const engineer = resolveAgentForTask(this.config, task);
|
|
125
|
+
const message = "CTO check-in: this task has been idle for five minutes. Please finish the current step, run the relevant verification, then commit and hand off to review — or clearly report the blocker.";
|
|
126
|
+
if (!this.cto.sendTaskMessage(task.id, message, engineer))
|
|
127
|
+
continue;
|
|
128
|
+
// The write emits an SSE task.corrected event for the human. Apply it
|
|
129
|
+
// immediately too; relying solely on the file watcher makes the board
|
|
130
|
+
// lag on some filesystems.
|
|
131
|
+
if (this.cto.recordAutomaticNudge(task)) {
|
|
132
|
+
this.nudgedIdleTasks.add(task.id);
|
|
133
|
+
void this.index.applyFileChange(task.absPath);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
for (const id of this.nudgedIdleTasks) {
|
|
137
|
+
if (!activeIds.has(id))
|
|
138
|
+
this.nudgedIdleTasks.delete(id);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
isIdleLongEnough(task, now) {
|
|
142
|
+
const updated = task.updated_at ? Date.parse(task.updated_at) : NaN;
|
|
143
|
+
return Number.isFinite(updated) && now - updated >= AUTOMATIC_NUDGE_IDLE_MS;
|
|
144
|
+
}
|
|
145
|
+
/** Cooldown survives a server reload, while the in-memory set handles normal idle stretches. */
|
|
146
|
+
wasRecentlyNudged(task, now) {
|
|
147
|
+
const marker = new RegExp(`- ([^\\n]+) · ${AUTOMATIC_NUDGE_MARKER}`, "g");
|
|
148
|
+
let match;
|
|
149
|
+
let last = 0;
|
|
150
|
+
while ((match = marker.exec(task.body)) !== null) {
|
|
151
|
+
const at = Date.parse(match[1]);
|
|
152
|
+
if (Number.isFinite(at))
|
|
153
|
+
last = Math.max(last, at);
|
|
154
|
+
}
|
|
155
|
+
return last > 0 && now - last < AUTOMATIC_NUDGE_COOLDOWN_MS;
|
|
156
|
+
}
|
|
157
|
+
buildDigest() {
|
|
158
|
+
const tasks = this.index.getTasks();
|
|
159
|
+
const lines = [];
|
|
160
|
+
lines.push("## Task Status Summary");
|
|
161
|
+
lines.push("");
|
|
162
|
+
const counts = this.index.counts();
|
|
163
|
+
lines.push(`- **Inbox**: ${counts.inbox} tasks`);
|
|
164
|
+
lines.push(`- **Ready**: ${counts.ready} tasks (waiting to start)`);
|
|
165
|
+
lines.push(`- **Active**: ${counts.active} tasks (in progress)`);
|
|
166
|
+
lines.push(`- **Review**: ${counts.review} tasks (awaiting sign-off)`);
|
|
167
|
+
lines.push(`- **Done**: ${counts.done} tasks`);
|
|
168
|
+
lines.push("");
|
|
169
|
+
lines.push("## Potentially Stuck Tasks");
|
|
170
|
+
lines.push("");
|
|
171
|
+
const stuckTasks = tasks.filter((t) => this.isTaskStuck(t));
|
|
172
|
+
if (stuckTasks.length === 0) {
|
|
173
|
+
lines.push("None — all tasks look healthy.");
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
for (const task of stuckTasks) {
|
|
177
|
+
lines.push(`- **#${task.id}** (${task.status}): ${this.describeStuckSignal(task)}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
lines.push("");
|
|
181
|
+
lines.push("## Build and Process Health");
|
|
182
|
+
lines.push("");
|
|
183
|
+
lines.push(`- Build marker: ${this.checkBuildStaleness()}`);
|
|
184
|
+
lines.push(`- Zombie processes: ${this.checkZombieProcesses()}`);
|
|
185
|
+
lines.push("");
|
|
186
|
+
return lines.join("\n") || null;
|
|
187
|
+
}
|
|
188
|
+
checkBuildStaleness() {
|
|
189
|
+
try {
|
|
190
|
+
const srcDir = join(this.config.root, "src");
|
|
191
|
+
const distDir = join(this.config.root, "dist");
|
|
192
|
+
if (!existsSync(srcDir) || !existsSync(distDir)) {
|
|
193
|
+
return "src or dist directory missing — cannot check staleness";
|
|
194
|
+
}
|
|
195
|
+
const srcStat = statSync(srcDir);
|
|
196
|
+
const distStat = statSync(distDir);
|
|
197
|
+
const srcTime = srcStat.mtimeMs;
|
|
198
|
+
const distTime = distStat.mtimeMs;
|
|
199
|
+
if (distTime < srcTime) {
|
|
200
|
+
const staleSec = Math.round((srcTime - distTime) / 1000);
|
|
201
|
+
return `⚠️ stale — src updated ${staleSec}s ago, dist needs rebuild`;
|
|
202
|
+
}
|
|
203
|
+
return "✓ fresh";
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
return "? unable to check staleness";
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
checkZombieProcesses() {
|
|
210
|
+
try {
|
|
211
|
+
// Check for lingering serve processes or agent processes that should have exited
|
|
212
|
+
// Use ps to find processes with "serve" or "bun" or "node" in their command
|
|
213
|
+
let psOutput = "";
|
|
214
|
+
try {
|
|
215
|
+
psOutput = execSync("ps aux | grep -E '(serve|bun|node)' | grep -v grep || true", {
|
|
216
|
+
encoding: "utf8",
|
|
217
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return "? unable to check processes";
|
|
222
|
+
}
|
|
223
|
+
const lines = psOutput
|
|
224
|
+
.trim()
|
|
225
|
+
.split("\n")
|
|
226
|
+
.filter((l) => l.length > 0);
|
|
227
|
+
if (lines.length === 0) {
|
|
228
|
+
return "✓ no stale processes detected";
|
|
229
|
+
}
|
|
230
|
+
// Simple heuristic: if we have more than 2 serve/node processes running,
|
|
231
|
+
// there may be zombies. This is a conservative check.
|
|
232
|
+
const staleCount = Math.max(0, lines.length - 2);
|
|
233
|
+
if (staleCount > 0) {
|
|
234
|
+
return `⚠️ possibly stale — ${staleCount} extra process(es) running`;
|
|
235
|
+
}
|
|
236
|
+
return "✓ processes look normal";
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
return "? unable to check processes";
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
isTaskStuck(task) {
|
|
243
|
+
// Active task with idle session for too long (no agent running)
|
|
244
|
+
if (task.status === "active" && task.updated_at) {
|
|
245
|
+
const lastActivity = Date.parse(task.updated_at);
|
|
246
|
+
const staleness = Date.now() - lastActivity;
|
|
247
|
+
if (staleness > 15 * 60 * 1000)
|
|
248
|
+
return true; // 15 minutes
|
|
249
|
+
}
|
|
250
|
+
// Review task stuck with no action for too long
|
|
251
|
+
if (task.status === "review" && task.updated_at) {
|
|
252
|
+
const lastActivity = Date.parse(task.updated_at);
|
|
253
|
+
const staleness = Date.now() - lastActivity;
|
|
254
|
+
if (staleness > 30 * 60 * 1000)
|
|
255
|
+
return true; // 30 minutes
|
|
256
|
+
}
|
|
257
|
+
// Check for handoff-but-no-done pattern (0172): task body has handoff marker
|
|
258
|
+
// but status hasn't transitioned to done
|
|
259
|
+
const hasHandoffMarker = task.body.includes("::handoff::");
|
|
260
|
+
if (hasHandoffMarker && task.status !== "done") {
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
describeStuckSignal(task) {
|
|
266
|
+
if (task.status === "active") {
|
|
267
|
+
const lastActivity = task.updated_at ? Date.parse(task.updated_at) : 0;
|
|
268
|
+
const min = Math.round((Date.now() - lastActivity) / 60_000);
|
|
269
|
+
return `active, idle session (${min}m with no output)`;
|
|
270
|
+
}
|
|
271
|
+
if (task.status === "review") {
|
|
272
|
+
const lastActivity = task.updated_at ? Date.parse(task.updated_at) : 0;
|
|
273
|
+
const min = Math.round((Date.now() - lastActivity) / 60_000);
|
|
274
|
+
return `review stuck, no action taken (${min}m stale)`;
|
|
275
|
+
}
|
|
276
|
+
if (task.body.includes("::handoff::") && task.status !== "done") {
|
|
277
|
+
return `handoff requested but not finalized — task still in ${task.status}, should be done`;
|
|
278
|
+
}
|
|
279
|
+
return "possibly stuck";
|
|
280
|
+
}
|
|
281
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { Agent, AgentOutputEntry, RepoOSConfig, Task } from "../core/types.js";
|
|
2
|
+
import type { RepoEvent } from "./live-index.js";
|
|
3
|
+
import { type AgentRunner, type StopResult } from "./agents.js";
|
|
4
|
+
export interface CTOReport {
|
|
5
|
+
id: string;
|
|
6
|
+
at: string;
|
|
7
|
+
agent: string;
|
|
8
|
+
cli: string;
|
|
9
|
+
model: string;
|
|
10
|
+
state: "ok" | "failed";
|
|
11
|
+
markdown: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function ctoMission(config: RepoOSConfig, agent: Agent, boardDigest: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* The CTO manager (0174).
|
|
16
|
+
*
|
|
17
|
+
* Reload-durability note (0288 "Also check"): unlike the reviewer, the CTO is
|
|
18
|
+
* INTENTIONALLY kept on the one-shot `runPrompt` path and is NOT durable. Both
|
|
19
|
+
* roles share the same `runPrompt` reload-death exposure, but the blast radius
|
|
20
|
+
* differs fundamentally:
|
|
21
|
+
*
|
|
22
|
+
* - The review produces a ONE-TIME sign-off artifact (.repoos/reviews/<id>.md)
|
|
23
|
+
* that is permanently lost if the process reloads mid-run — hence #0288 made
|
|
24
|
+
* it durable.
|
|
25
|
+
* - The CTO is a PERIODIC board monitor (default 5-min cadence). A run lost to
|
|
26
|
+
* a reload merely delays the next sweep; the monitor simply re-runs on its
|
|
27
|
+
* own next tick and self-heals. It never produces a one-of-a-kind artifact.
|
|
28
|
+
*
|
|
29
|
+
* So the CTO's `runPrompt` exposure is accepted (and it is force-cancelled on
|
|
30
|
+
* reload/close, which is correct *because* it is non-durable). If the CTO ever
|
|
31
|
+
* needs to guarantee a specific run survives a reload, it should be moved onto
|
|
32
|
+
* the same durable `AgentRunner` path (#0288) — but that is out of scope here.
|
|
33
|
+
*/
|
|
34
|
+
export declare class CTOManager {
|
|
35
|
+
private readonly config;
|
|
36
|
+
private readonly emit;
|
|
37
|
+
private readonly runs;
|
|
38
|
+
private readonly sessions;
|
|
39
|
+
private readonly sessionTimers;
|
|
40
|
+
private readonly runner?;
|
|
41
|
+
/** Database for recording CTO sessions (0230). */
|
|
42
|
+
private readonly db;
|
|
43
|
+
constructor(config: RepoOSConfig, emit: (e: RepoEvent) => void, runner?: AgentRunner);
|
|
44
|
+
enabled(): boolean;
|
|
45
|
+
isRunning(): boolean;
|
|
46
|
+
runningCount(): number;
|
|
47
|
+
path(): string;
|
|
48
|
+
read(): CTOReport | null;
|
|
49
|
+
canRun(): {
|
|
50
|
+
ok: boolean;
|
|
51
|
+
reason?: string;
|
|
52
|
+
};
|
|
53
|
+
run(boardDigest: string): Promise<{
|
|
54
|
+
ok: boolean;
|
|
55
|
+
reason?: string;
|
|
56
|
+
report?: CTOReport;
|
|
57
|
+
}>;
|
|
58
|
+
send(text: string): Promise<{
|
|
59
|
+
ok: boolean;
|
|
60
|
+
reason?: string;
|
|
61
|
+
}>;
|
|
62
|
+
session(): AgentOutputEntry[];
|
|
63
|
+
cancel(): void;
|
|
64
|
+
cancelAll(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Interrupt an in-progress CTO run/response. Stops the in-flight agent process
|
|
67
|
+
* and appends a persistent "response interrupted" marker to the board
|
|
68
|
+
* conversation so it reads as user-stopped rather than completed normally.
|
|
69
|
+
* Idempotent — safe to call when nothing is running.
|
|
70
|
+
*/
|
|
71
|
+
interrupt(): StopResult;
|
|
72
|
+
/**
|
|
73
|
+
* Send a message to a task's agent session (nudge or escalation).
|
|
74
|
+
* The caller records any automatic nudge separately so it is visible to the
|
|
75
|
+
* human in the task activity feed.
|
|
76
|
+
*/
|
|
77
|
+
sendTaskMessage(taskId: string, message: string, agent: Agent | null): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Persist and announce the one automatic action the CTO monitor may take:
|
|
80
|
+
* a completion reminder to an idle active engineer. Keeping this separate
|
|
81
|
+
* from `sendTaskMessage` makes the human-facing audit entry durable even
|
|
82
|
+
* when the agent transcript is later compacted or the server reloads.
|
|
83
|
+
*/
|
|
84
|
+
recordAutomaticNudge(task: Task): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Run repoos check on a task's worktree to verify it passes before
|
|
87
|
+
* taking automatic actions. Returns true if check passes, false otherwise.
|
|
88
|
+
*/
|
|
89
|
+
runRepoosCheck(workdir: string): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Move a task from review to active (or mark needs_input) when genuinely stuck.
|
|
92
|
+
* Only call this after human confirmation or verification that the task is
|
|
93
|
+
* actually stuck (not just slow). The action is logged to task activity.
|
|
94
|
+
*/
|
|
95
|
+
moveTaskStatus(taskAbsPath: string, fromStatus: string, toStatus: string, reason: string): boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Set needs_input flag on a task to escalate to human review.
|
|
98
|
+
* This surfaces the task in the UI and fires notifications.
|
|
99
|
+
*/
|
|
100
|
+
setNeedsInput(taskAbsPath: string, reason: string): boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Create a follow-up bug task for systemic issues detected by the CTO.
|
|
103
|
+
* Returns the new task id on success, null on failure.
|
|
104
|
+
*/
|
|
105
|
+
createFollowUpBug(title: string, body: string, area: string): string | null;
|
|
106
|
+
/**
|
|
107
|
+
* Record a CTO run to the database (0230). Persisted with the cto session
|
|
108
|
+
* type, real wall-clock elapsed time, and any CLI-reported tokens/cost.
|
|
109
|
+
* Best-effort — never crashes the monitor. Cancelled runs record too (0331):
|
|
110
|
+
* the process ran and may have burned tokens before the stop landed, and the
|
|
111
|
+
* board panel must show every role's real spend.
|
|
112
|
+
*/
|
|
113
|
+
private recordRun;
|
|
114
|
+
private sessionId;
|
|
115
|
+
private hasSession;
|
|
116
|
+
private sessionFile;
|
|
117
|
+
private readSession;
|
|
118
|
+
private persistSession;
|
|
119
|
+
private scheduleSessionWrite;
|
|
120
|
+
private resetSession;
|
|
121
|
+
private appendEntry;
|
|
122
|
+
private appendSessionLine;
|
|
123
|
+
private appendMarker;
|
|
124
|
+
private write;
|
|
125
|
+
}
|