@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,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RepoOS core types.
|
|
3
|
+
*
|
|
4
|
+
* The repo is the source of truth. A "task" is a markdown file with YAML
|
|
5
|
+
* frontmatter living under the configured work directory (default: `work/`).
|
|
6
|
+
* Task *status* is a frontmatter field — files never move between folders.
|
|
7
|
+
*/
|
|
8
|
+
/** Canonical lifecycle states. Order matters: it defines board column order. */
|
|
9
|
+
export const STATUSES = ["draft", "inbox", "ready", "active", "review", "done"];
|
|
10
|
+
export const PRIORITIES = ["p0", "p1", "p2", "p3"];
|
|
11
|
+
export const TASK_TYPES = ["feature", "bug", "chore", "spec", "refactor"];
|
|
12
|
+
/**
|
|
13
|
+
* Machine-readable reasons `needsInput` gets set, one per escalation call
|
|
14
|
+
* site. Stored alongside the flag so a later automated success (e.g. a
|
|
15
|
+
* review that finally completes cleanly) can tell whether IT is what the
|
|
16
|
+
* human was waited on for, and clear the flag itself rather than leaving it
|
|
17
|
+
* stuck forever once the underlying problem resolves. A boolean alone can't
|
|
18
|
+
* make that call safely — clearing on every success would just as happily
|
|
19
|
+
* wipe out an unrelated flag (e.g. a CTO policy question) that happened to
|
|
20
|
+
* still be pending.
|
|
21
|
+
*/
|
|
22
|
+
export const NEEDS_INPUT_REASONS = [
|
|
23
|
+
"review-failed",
|
|
24
|
+
"dev-error",
|
|
25
|
+
"watchdog-stuck",
|
|
26
|
+
"cto-escalation",
|
|
27
|
+
];
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { RepoOSConfig, Task } from "./types.js";
|
|
2
|
+
export type GcMode = "integrate-only" | "full";
|
|
3
|
+
export interface GcKept {
|
|
4
|
+
branch: string;
|
|
5
|
+
path: string;
|
|
6
|
+
/** Why it was left in place. */
|
|
7
|
+
reason: string;
|
|
8
|
+
}
|
|
9
|
+
export interface GcReport {
|
|
10
|
+
mode: GcMode;
|
|
11
|
+
dryRun: boolean;
|
|
12
|
+
/** Worktrees removed (or that would be, when dryRun). `branch` is "" for detached. */
|
|
13
|
+
removedWorktrees: Array<{
|
|
14
|
+
branch: string;
|
|
15
|
+
path: string;
|
|
16
|
+
}>;
|
|
17
|
+
/** Branches deleted (or that would be). */
|
|
18
|
+
removedBranches: string[];
|
|
19
|
+
/** Stale entries left in place with the reason. */
|
|
20
|
+
keptDirty: GcKept[];
|
|
21
|
+
/** True when `git worktree prune` ran (metadata for vanished directories). */
|
|
22
|
+
prunedMetadata: boolean;
|
|
23
|
+
/** Non-fatal problems (a `git worktree remove` that would not take, etc.). */
|
|
24
|
+
errors: string[];
|
|
25
|
+
}
|
|
26
|
+
export interface SweepOptions {
|
|
27
|
+
mode: GcMode;
|
|
28
|
+
dryRun?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Task ids whose `repoos/integrate/<id>` candidate must be spared — a job is
|
|
31
|
+
* still queued/running/recovering for them. The boot sweep passes this.
|
|
32
|
+
*/
|
|
33
|
+
activeJobIds?: Set<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Every task on the board. Only needed for `mode: "full"`; omitted, it is read
|
|
36
|
+
* from a fresh `buildIndex`. `mode: "integrate-only"` never looks at tasks.
|
|
37
|
+
*/
|
|
38
|
+
tasks?: Task[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Sweep stale worktrees/branches. Synchronous and fail-soft — any git hiccup is
|
|
42
|
+
* recorded in `report.errors` and the sweep moves on.
|
|
43
|
+
*/
|
|
44
|
+
export declare function sweepStaleWorktrees(config: RepoOSConfig, opts: SweepOptions): GcReport;
|
|
45
|
+
/** Number of registered git worktrees, including the main checkout. */
|
|
46
|
+
export declare function countWorktrees(root: string): number;
|
|
47
|
+
/**
|
|
48
|
+
* Run the conservative `integrate-only` sweep, then log its result and — when
|
|
49
|
+
* the surviving worktree count exceeds `threshold` (0 disables) — a
|
|
50
|
+
* "run `repoos gc`" warning. Shared by the boot path and every close-out.
|
|
51
|
+
* Fully fail-soft: a git hiccup is swallowed, never surfaced to the caller.
|
|
52
|
+
*/
|
|
53
|
+
export declare function sweepAndWarn(config: RepoOSConfig, opts: {
|
|
54
|
+
activeJobIds?: Set<string>;
|
|
55
|
+
threshold?: number;
|
|
56
|
+
log: (level: "info" | "warn", msg: string, meta?: Record<string, unknown>) => void;
|
|
57
|
+
}): void;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Garbage-collect leaked task worktrees and branches.
|
|
3
|
+
*
|
|
4
|
+
* Two things leak them:
|
|
5
|
+
* - a close-out job that FAILS never removes its `repoos/integrate/<id>`
|
|
6
|
+
* candidate worktree (the success path does, in the orchestrator's
|
|
7
|
+
* `cleanup()`), and
|
|
8
|
+
* - historically, close-outs that predate the non-blocking merge queue — plus
|
|
9
|
+
* CLI `repoos mv <id> done`, which is a pure status edit — left the feature
|
|
10
|
+
* worktree/branch behind entirely.
|
|
11
|
+
*
|
|
12
|
+
* Left alone they accumulate without bound, and every server cold boot pays one
|
|
13
|
+
* `git status` per registered worktree while enriching the index
|
|
14
|
+
* (`buildIndexAsync` -> `resolveWorktreeStatuses`).
|
|
15
|
+
*
|
|
16
|
+
* Scope boundary: this ONLY ever touches worktrees whose path is inside
|
|
17
|
+
* `worktreesDir(root)` (the `<root>-worktrees/` sibling directory that
|
|
18
|
+
* `ensureWorktree` always uses). The main checkout, this Claude Code session's
|
|
19
|
+
* `<root>/.claude/worktrees/*`, and any other coding agent's or tool's worktrees
|
|
20
|
+
* live outside that directory and are never RepoOS-managed — so no
|
|
21
|
+
* agent-specific branch-name matching is used anywhere.
|
|
22
|
+
*/
|
|
23
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
24
|
+
import { relative, isAbsolute } from "node:path";
|
|
25
|
+
import { spawnSync } from "node:child_process";
|
|
26
|
+
import { worktreesDir } from "./config.js";
|
|
27
|
+
import { buildIndex } from "./indexer.js";
|
|
28
|
+
import { isGitRepo, currentBranch, listWorktrees, removeWorktree, deleteBranch, pruneWorktrees, isAncestor, } from "./git.js";
|
|
29
|
+
const CANDIDATE_BRANCH_PREFIX = "repoos/integrate/";
|
|
30
|
+
/**
|
|
31
|
+
* True when the worktree has no meaningful uncommitted work. `dist/` and
|
|
32
|
+
* `screenshots/` are generated build output (routinely committed on a branch
|
|
33
|
+
* and re-dirtied) — excluded here the same way `DIFF_SOURCE_PATHS` does for the
|
|
34
|
+
* review diff. A missing directory counts as clean (nothing left to lose).
|
|
35
|
+
*/
|
|
36
|
+
function worktreeClean(path) {
|
|
37
|
+
if (!existsSync(path))
|
|
38
|
+
return true;
|
|
39
|
+
const run = spawnSync("git", ["status", "--porcelain", "--", ".", ":(exclude)dist", ":(exclude)screenshots"], { cwd: path, encoding: "utf8", timeout: 4000 });
|
|
40
|
+
if (run.status !== 0)
|
|
41
|
+
return false; // can't tell -> be conservative
|
|
42
|
+
return (run.stdout ?? "").trim() === "";
|
|
43
|
+
}
|
|
44
|
+
/** Resolve symlinks (macOS `/var` -> `/private/var`) so path containment checks line up. */
|
|
45
|
+
function realpath(p) {
|
|
46
|
+
try {
|
|
47
|
+
return realpathSync(p);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return p;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function isInside(dir, candidate) {
|
|
54
|
+
const rel = relative(realpath(dir), realpath(candidate));
|
|
55
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Sweep stale worktrees/branches. Synchronous and fail-soft — any git hiccup is
|
|
59
|
+
* recorded in `report.errors` and the sweep moves on.
|
|
60
|
+
*/
|
|
61
|
+
export function sweepStaleWorktrees(config, opts) {
|
|
62
|
+
const root = config.root;
|
|
63
|
+
const report = {
|
|
64
|
+
mode: opts.mode,
|
|
65
|
+
dryRun: !!opts.dryRun,
|
|
66
|
+
removedWorktrees: [],
|
|
67
|
+
removedBranches: [],
|
|
68
|
+
keptDirty: [],
|
|
69
|
+
prunedMetadata: false,
|
|
70
|
+
errors: [],
|
|
71
|
+
};
|
|
72
|
+
if (!isGitRepo(root)) {
|
|
73
|
+
report.errors.push("not a git repository");
|
|
74
|
+
return report;
|
|
75
|
+
}
|
|
76
|
+
const wtDir = worktreesDir(root);
|
|
77
|
+
const mainBranch = currentBranch(root) ?? "main";
|
|
78
|
+
const activeJobIds = opts.activeJobIds ?? new Set();
|
|
79
|
+
// branch -> task, for the "is this worktree still live" check (full mode only).
|
|
80
|
+
const taskByBranch = new Map();
|
|
81
|
+
if (opts.mode === "full") {
|
|
82
|
+
const tasks = opts.tasks ?? buildIndex(config).tasks;
|
|
83
|
+
for (const t of tasks) {
|
|
84
|
+
if (t.branch)
|
|
85
|
+
taskByBranch.set(t.branch, t);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const scoped = listWorktrees(root).filter((w) => !w.isMain && !w.isBare && isInside(wtDir, w.path));
|
|
89
|
+
const remove = (branch, path, forceBranch) => {
|
|
90
|
+
if (report.dryRun) {
|
|
91
|
+
report.removedWorktrees.push({ branch, path });
|
|
92
|
+
if (branch)
|
|
93
|
+
report.removedBranches.push(branch);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (!removeWorktree(root, branch || path)) {
|
|
97
|
+
report.errors.push(`could not remove worktree for ${branch || path}`);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
report.removedWorktrees.push({ branch, path });
|
|
101
|
+
if (branch && deleteBranch(root, branch, { force: forceBranch })) {
|
|
102
|
+
report.removedBranches.push(branch);
|
|
103
|
+
}
|
|
104
|
+
else if (branch) {
|
|
105
|
+
report.errors.push(`worktree gone but branch ${branch} not deleted`);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
for (const w of scoped) {
|
|
109
|
+
const branch = w.branch ?? "";
|
|
110
|
+
// --- repoos/integrate/<id> candidates: throwaway, both modes ---
|
|
111
|
+
if (branch.startsWith(CANDIDATE_BRANCH_PREFIX)) {
|
|
112
|
+
const taskId = branch.slice(CANDIDATE_BRANCH_PREFIX.length);
|
|
113
|
+
if (activeJobIds.has(taskId)) {
|
|
114
|
+
report.keptDirty.push({ branch, path: w.path, reason: "close-out job still active" });
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
remove(branch, w.path, /* forceBranch */ true);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (opts.mode === "integrate-only")
|
|
121
|
+
continue;
|
|
122
|
+
// --- feature worktrees ---
|
|
123
|
+
if (!branch) {
|
|
124
|
+
// Detached HEAD with no branch ref: only safe to drop when its directory
|
|
125
|
+
// is already gone (pure stale metadata).
|
|
126
|
+
if (!existsSync(w.path)) {
|
|
127
|
+
report.removedWorktrees.push({ branch: "", path: w.path });
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
report.keptDirty.push({
|
|
131
|
+
branch: "",
|
|
132
|
+
path: w.path,
|
|
133
|
+
reason: "detached worktree, directory present",
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const task = taskByBranch.get(branch);
|
|
139
|
+
if (task && task.status !== "done")
|
|
140
|
+
continue; // live work — leave it
|
|
141
|
+
const merged = isAncestor(root, branch, mainBranch) === true;
|
|
142
|
+
const clean = worktreeClean(w.path);
|
|
143
|
+
if (merged && clean) {
|
|
144
|
+
remove(branch, w.path, /* forceBranch */ false);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
report.keptDirty.push({
|
|
148
|
+
branch,
|
|
149
|
+
path: w.path,
|
|
150
|
+
reason: !merged ? `commits not in ${mainBranch}` : "uncommitted changes",
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Clear metadata for any directory that is now (or was already) gone.
|
|
155
|
+
if (!report.dryRun) {
|
|
156
|
+
pruneWorktrees(root);
|
|
157
|
+
report.prunedMetadata = true;
|
|
158
|
+
}
|
|
159
|
+
return report;
|
|
160
|
+
}
|
|
161
|
+
/** Number of registered git worktrees, including the main checkout. */
|
|
162
|
+
export function countWorktrees(root) {
|
|
163
|
+
return listWorktrees(root).length;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Run the conservative `integrate-only` sweep, then log its result and — when
|
|
167
|
+
* the surviving worktree count exceeds `threshold` (0 disables) — a
|
|
168
|
+
* "run `repoos gc`" warning. Shared by the boot path and every close-out.
|
|
169
|
+
* Fully fail-soft: a git hiccup is swallowed, never surfaced to the caller.
|
|
170
|
+
*/
|
|
171
|
+
export function sweepAndWarn(config, opts) {
|
|
172
|
+
try {
|
|
173
|
+
const report = sweepStaleWorktrees(config, {
|
|
174
|
+
mode: "integrate-only",
|
|
175
|
+
activeJobIds: opts.activeJobIds,
|
|
176
|
+
});
|
|
177
|
+
if (report.removedWorktrees.length || report.errors.length) {
|
|
178
|
+
opts.log("info", "worktree gc", {
|
|
179
|
+
removed: report.removedWorktrees.map((w) => w.branch || w.path),
|
|
180
|
+
errors: report.errors,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
const threshold = opts.threshold ?? 20;
|
|
184
|
+
if (threshold > 0) {
|
|
185
|
+
const n = countWorktrees(config.root);
|
|
186
|
+
if (n > threshold) {
|
|
187
|
+
opts.log("warn", `${n} git worktrees registered (advisory ceiling ${threshold}) — run \`repoos gc\` to reclaim leftovers from done/abandoned tasks`, { worktrees: n, threshold });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (e) {
|
|
192
|
+
opts.log("warn", `worktree gc failed: ${e.message}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { execSync } from "node:child_process";
|
|
6
|
+
import { createJobCoordinator } from "../integration-job.js";
|
|
7
|
+
import { createRepositoryLock } from "../repo-lock.js";
|
|
8
|
+
describe("integration jobs (0118)", () => {
|
|
9
|
+
let testRepo;
|
|
10
|
+
let testRepoGit;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
// Create a temporary git repo for testing
|
|
13
|
+
testRepo = join(tmpdir(), `repoos-test-${Date.now()}`);
|
|
14
|
+
mkdirSync(testRepo, { recursive: true });
|
|
15
|
+
testRepoGit = `git -C ${testRepo}`;
|
|
16
|
+
// Initialize git repo
|
|
17
|
+
execSync(`${testRepoGit} init`, { stdio: "ignore" });
|
|
18
|
+
execSync(`${testRepoGit} config user.email "test@example.com"`, { stdio: "ignore" });
|
|
19
|
+
execSync(`${testRepoGit} config user.name "Test User"`, { stdio: "ignore" });
|
|
20
|
+
// Create an initial commit on main
|
|
21
|
+
writeFileSync(join(testRepo, "README.md"), "# Test Repo\n");
|
|
22
|
+
execSync(`${testRepoGit} add README.md`, { stdio: "ignore" });
|
|
23
|
+
execSync(`${testRepoGit} commit -m "Initial commit"`, { stdio: "ignore" });
|
|
24
|
+
});
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
try {
|
|
27
|
+
rmSync(testRepo, { recursive: true, force: true });
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
/* ignore cleanup errors */
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
it("should enqueue jobs and maintain FIFO order", () => {
|
|
34
|
+
const coordinator = createJobCoordinator(testRepo);
|
|
35
|
+
// Enqueue two tasks
|
|
36
|
+
const job1 = coordinator.enqueue({ id: "task1", branch: "feat/task1" });
|
|
37
|
+
const job2 = coordinator.enqueue({ id: "task2", branch: "feat/task2" });
|
|
38
|
+
expect(job1).toBeDefined();
|
|
39
|
+
expect(job2).toBeDefined();
|
|
40
|
+
expect(job1.taskId).toBe("task1");
|
|
41
|
+
expect(job2.taskId).toBe("task2");
|
|
42
|
+
const all = coordinator.allJobs();
|
|
43
|
+
expect(all).toHaveLength(2);
|
|
44
|
+
expect(all[0].taskId).toBe("task1");
|
|
45
|
+
expect(all[1].taskId).toBe("task2");
|
|
46
|
+
});
|
|
47
|
+
it("should be idempotent: repeated enqueue returns existing job", () => {
|
|
48
|
+
const coordinator = createJobCoordinator(testRepo);
|
|
49
|
+
const job1 = coordinator.enqueue({ id: "task1", branch: "feat/task1" });
|
|
50
|
+
const job1Again = coordinator.enqueue({ id: "task1", branch: "feat/task1" });
|
|
51
|
+
expect(job1.enqueuedAt).toBe(job1Again.enqueuedAt);
|
|
52
|
+
expect(coordinator.allJobs()).toHaveLength(1);
|
|
53
|
+
});
|
|
54
|
+
it("should recover interrupted jobs on startup", () => {
|
|
55
|
+
const coordinator = createJobCoordinator(testRepo);
|
|
56
|
+
// Create a job in syncing phase
|
|
57
|
+
const job = coordinator.enqueue({ id: "task1", branch: "feat/task1" });
|
|
58
|
+
coordinator.updateJob("task1", { phase: "syncing", startedAt: new Date().toISOString() });
|
|
59
|
+
// Create a new coordinator (simulating restart)
|
|
60
|
+
const coordinator2 = createJobCoordinator(testRepo);
|
|
61
|
+
const interrupted = coordinator2.findInterruptedJobs();
|
|
62
|
+
expect(interrupted).toHaveLength(1);
|
|
63
|
+
expect(interrupted[0].taskId).toBe("task1");
|
|
64
|
+
expect(interrupted[0].phase).toBe("syncing");
|
|
65
|
+
});
|
|
66
|
+
it("should not recover done/failed jobs", () => {
|
|
67
|
+
const coordinator = createJobCoordinator(testRepo);
|
|
68
|
+
const job1 = coordinator.enqueue({ id: "task1", branch: "feat/task1" });
|
|
69
|
+
coordinator.updateJob("task1", { phase: "done" });
|
|
70
|
+
const job2 = coordinator.enqueue({ id: "task2", branch: "feat/task2" });
|
|
71
|
+
coordinator.updateJob("task2", { phase: "failed", reason: "test failure" });
|
|
72
|
+
const interrupted = coordinator.findInterruptedJobs();
|
|
73
|
+
expect(interrupted).toHaveLength(0);
|
|
74
|
+
});
|
|
75
|
+
it("should serialize repo lock across concurrent jobs", () => {
|
|
76
|
+
const lock = createRepositoryLock(testRepo);
|
|
77
|
+
// First job acquires lock
|
|
78
|
+
expect(lock.acquire("task1")).toBe(true);
|
|
79
|
+
expect(lock.isLocked()).toBe(true);
|
|
80
|
+
expect(lock.getHolder()).toBe("task1");
|
|
81
|
+
// Second job cannot acquire
|
|
82
|
+
expect(lock.acquire("task2")).toBe(false);
|
|
83
|
+
// First job releases
|
|
84
|
+
expect(lock.release("task1")).toBe(true);
|
|
85
|
+
expect(lock.isLocked()).toBe(false);
|
|
86
|
+
// Now second job can acquire
|
|
87
|
+
expect(lock.acquire("task2")).toBe(true);
|
|
88
|
+
});
|
|
89
|
+
it("should clean up stale locks after timeout", () => {
|
|
90
|
+
const lock = createRepositoryLock(testRepo);
|
|
91
|
+
// Write a stale lock file (>60 seconds old)
|
|
92
|
+
const lockPath = join(testRepo, ".repoos/close-out.lock");
|
|
93
|
+
const staleTime = new Date(Date.now() - 70_000); // 70 seconds ago
|
|
94
|
+
writeFileSync(lockPath, JSON.stringify({ taskId: "stale", acquiredAt: staleTime.toISOString() }));
|
|
95
|
+
// Should be able to acquire even though file exists (it's stale)
|
|
96
|
+
expect(lock.acquire("task1")).toBe(true);
|
|
97
|
+
});
|
|
98
|
+
it("should track baseMainSha and detect drift", () => {
|
|
99
|
+
const coordinator = createJobCoordinator(testRepo);
|
|
100
|
+
const job = coordinator.enqueue({ id: "task1", branch: "feat/task1" });
|
|
101
|
+
expect(job.baseMainSha).toBeNull();
|
|
102
|
+
// Simulate recording baseMainSha during validation
|
|
103
|
+
coordinator.updateJob("task1", {
|
|
104
|
+
phase: "validating",
|
|
105
|
+
baseMainSha: "abc123",
|
|
106
|
+
});
|
|
107
|
+
const updated = coordinator.getJob("task1");
|
|
108
|
+
expect(updated?.baseMainSha).toBe("abc123");
|
|
109
|
+
});
|
|
110
|
+
it("should persist and recover full job state", () => {
|
|
111
|
+
const coordinator = createJobCoordinator(testRepo);
|
|
112
|
+
const job = coordinator.enqueue({ id: "task1", branch: "feat/task1" });
|
|
113
|
+
coordinator.updateJob("task1", {
|
|
114
|
+
phase: "publishing",
|
|
115
|
+
startedAt: new Date().toISOString(),
|
|
116
|
+
baseMainSha: "main-sha-abc",
|
|
117
|
+
branchSha: "branch-sha-def",
|
|
118
|
+
candidateSha: "candidate-sha-ghi",
|
|
119
|
+
});
|
|
120
|
+
// Create new coordinator and verify state persisted
|
|
121
|
+
const coordinator2 = createJobCoordinator(testRepo);
|
|
122
|
+
const recovered = coordinator2.getJob("task1");
|
|
123
|
+
expect(recovered).toBeDefined();
|
|
124
|
+
expect(recovered?.phase).toBe("publishing");
|
|
125
|
+
expect(recovered?.baseMainSha).toBe("main-sha-abc");
|
|
126
|
+
expect(recovered?.branchSha).toBe("branch-sha-def");
|
|
127
|
+
expect(recovered?.candidateSha).toBe("candidate-sha-ghi");
|
|
128
|
+
});
|
|
129
|
+
});
|