@ag-eco/agentplate-cli 0.13.0
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 +21 -0
- package/README.md +462 -0
- package/agents/ap-co-creation.md +90 -0
- package/agents/builder.md +144 -0
- package/agents/coordinator.md +377 -0
- package/agents/lead.md +435 -0
- package/agents/merger.md +164 -0
- package/agents/monitor.md +214 -0
- package/agents/orchestrator.md +239 -0
- package/agents/reviewer.md +140 -0
- package/agents/scout.md +125 -0
- package/agents/supervisor.md +427 -0
- package/package.json +66 -0
- package/src/agents/capabilities.test.ts +85 -0
- package/src/agents/capabilities.ts +125 -0
- package/src/agents/checkpoint.test.ts +88 -0
- package/src/agents/checkpoint.ts +101 -0
- package/src/agents/copilot-hooks-deployer.test.ts +162 -0
- package/src/agents/copilot-hooks-deployer.ts +93 -0
- package/src/agents/guard-rules.test.ts +372 -0
- package/src/agents/guard-rules.ts +97 -0
- package/src/agents/headless-mail-injector.test.ts +709 -0
- package/src/agents/headless-mail-injector.ts +377 -0
- package/src/agents/headless-prompt.test.ts +102 -0
- package/src/agents/headless-prompt.ts +68 -0
- package/src/agents/hooks-deployer.test.ts +3119 -0
- package/src/agents/hooks-deployer.ts +804 -0
- package/src/agents/identity.test.ts +604 -0
- package/src/agents/identity.ts +384 -0
- package/src/agents/lifecycle.test.ts +196 -0
- package/src/agents/lifecycle.ts +183 -0
- package/src/agents/mail-poll-detect.test.ts +153 -0
- package/src/agents/mail-poll-detect.ts +73 -0
- package/src/agents/manifest.test.ts +1026 -0
- package/src/agents/manifest.ts +376 -0
- package/src/agents/overlay.test.ts +1058 -0
- package/src/agents/overlay.ts +490 -0
- package/src/agents/scope-detect.test.ts +190 -0
- package/src/agents/scope-detect.ts +146 -0
- package/src/agents/turn-lock.test.ts +181 -0
- package/src/agents/turn-lock.ts +235 -0
- package/src/agents/turn-runner-dispatch.test.ts +182 -0
- package/src/agents/turn-runner-dispatch.ts +105 -0
- package/src/agents/turn-runner.test.ts +2312 -0
- package/src/agents/turn-runner.ts +1383 -0
- package/src/beads/client.test.ts +217 -0
- package/src/beads/client.ts +230 -0
- package/src/beads/molecules.test.ts +338 -0
- package/src/beads/molecules.ts +198 -0
- package/src/commands/agents.test.ts +328 -0
- package/src/commands/agents.ts +299 -0
- package/src/commands/clean.test.ts +797 -0
- package/src/commands/clean.ts +791 -0
- package/src/commands/completions.test.ts +348 -0
- package/src/commands/completions.ts +981 -0
- package/src/commands/coordinator.test.ts +2975 -0
- package/src/commands/coordinator.ts +1841 -0
- package/src/commands/costs.test.ts +1183 -0
- package/src/commands/costs.ts +599 -0
- package/src/commands/dashboard.test.ts +954 -0
- package/src/commands/dashboard.ts +1212 -0
- package/src/commands/discover.test.ts +288 -0
- package/src/commands/discover.ts +202 -0
- package/src/commands/doctor.test.ts +303 -0
- package/src/commands/doctor.ts +311 -0
- package/src/commands/ecosystem.test.ts +226 -0
- package/src/commands/ecosystem.ts +248 -0
- package/src/commands/errors.test.ts +654 -0
- package/src/commands/errors.ts +197 -0
- package/src/commands/feed.test.ts +709 -0
- package/src/commands/feed.ts +260 -0
- package/src/commands/group.test.ts +475 -0
- package/src/commands/group.ts +546 -0
- package/src/commands/hooks.test.ts +458 -0
- package/src/commands/hooks.ts +263 -0
- package/src/commands/init.test.ts +1011 -0
- package/src/commands/init.ts +967 -0
- package/src/commands/inspect.test.ts +1239 -0
- package/src/commands/inspect.ts +648 -0
- package/src/commands/log.test.ts +1913 -0
- package/src/commands/log.ts +958 -0
- package/src/commands/logs.test.ts +801 -0
- package/src/commands/logs.ts +483 -0
- package/src/commands/mail.test.ts +1501 -0
- package/src/commands/mail.ts +848 -0
- package/src/commands/merge.test.ts +864 -0
- package/src/commands/merge.ts +381 -0
- package/src/commands/metrics.test.ts +458 -0
- package/src/commands/metrics.ts +129 -0
- package/src/commands/monitor.test.ts +191 -0
- package/src/commands/monitor.ts +409 -0
- package/src/commands/nudge.test.ts +579 -0
- package/src/commands/nudge.ts +646 -0
- package/src/commands/orchestrator.ts +42 -0
- package/src/commands/prime.test.ts +612 -0
- package/src/commands/prime.ts +359 -0
- package/src/commands/replay.test.ts +757 -0
- package/src/commands/replay.ts +231 -0
- package/src/commands/run.test.ts +469 -0
- package/src/commands/run.ts +353 -0
- package/src/commands/serve/agent-actions.test.ts +210 -0
- package/src/commands/serve/agent-actions.ts +192 -0
- package/src/commands/serve/build.test.ts +202 -0
- package/src/commands/serve/build.ts +206 -0
- package/src/commands/serve/coordinator-actions.test.ts +339 -0
- package/src/commands/serve/coordinator-actions.ts +410 -0
- package/src/commands/serve/dev.test.ts +168 -0
- package/src/commands/serve/dev.ts +117 -0
- package/src/commands/serve/mail-actions.test.ts +312 -0
- package/src/commands/serve/mail-actions.ts +167 -0
- package/src/commands/serve/rest.test.ts +1680 -0
- package/src/commands/serve/rest.ts +1130 -0
- package/src/commands/serve/static.ts +51 -0
- package/src/commands/serve/ws.test.ts +361 -0
- package/src/commands/serve/ws.ts +332 -0
- package/src/commands/serve.test.ts +459 -0
- package/src/commands/serve.ts +654 -0
- package/src/commands/sling.test.ts +1583 -0
- package/src/commands/sling.ts +1351 -0
- package/src/commands/spec.test.ts +179 -0
- package/src/commands/spec.ts +105 -0
- package/src/commands/status.test.ts +614 -0
- package/src/commands/status.ts +403 -0
- package/src/commands/stop.test.ts +964 -0
- package/src/commands/stop.ts +319 -0
- package/src/commands/supervisor.test.ts +185 -0
- package/src/commands/supervisor.ts +537 -0
- package/src/commands/trace.test.ts +762 -0
- package/src/commands/trace.ts +205 -0
- package/src/commands/update.test.ts +466 -0
- package/src/commands/update.ts +263 -0
- package/src/commands/upgrade.test.ts +48 -0
- package/src/commands/upgrade.ts +240 -0
- package/src/commands/watch.test.ts +257 -0
- package/src/commands/watch.ts +308 -0
- package/src/commands/worktree.test.ts +1297 -0
- package/src/commands/worktree.ts +451 -0
- package/src/config.test.ts +1535 -0
- package/src/config.ts +1064 -0
- package/src/doctor/agents.test.ts +523 -0
- package/src/doctor/agents.ts +399 -0
- package/src/doctor/config-check.test.ts +191 -0
- package/src/doctor/config-check.ts +183 -0
- package/src/doctor/consistency.test.ts +807 -0
- package/src/doctor/consistency.ts +347 -0
- package/src/doctor/databases.test.ts +350 -0
- package/src/doctor/databases.ts +243 -0
- package/src/doctor/dependencies.test.ts +296 -0
- package/src/doctor/dependencies.ts +272 -0
- package/src/doctor/ecosystem.test.ts +308 -0
- package/src/doctor/ecosystem.ts +156 -0
- package/src/doctor/logs.test.ts +253 -0
- package/src/doctor/logs.ts +295 -0
- package/src/doctor/merge-queue.test.ts +315 -0
- package/src/doctor/merge-queue.ts +167 -0
- package/src/doctor/providers.test.ts +409 -0
- package/src/doctor/providers.ts +250 -0
- package/src/doctor/serve.test.ts +95 -0
- package/src/doctor/serve.ts +86 -0
- package/src/doctor/structure.test.ts +423 -0
- package/src/doctor/structure.ts +285 -0
- package/src/doctor/types.ts +43 -0
- package/src/doctor/version.test.ts +241 -0
- package/src/doctor/version.ts +132 -0
- package/src/doctor/watchdog.test.ts +167 -0
- package/src/doctor/watchdog.ts +214 -0
- package/src/e2e/init-sling-lifecycle.test.ts +283 -0
- package/src/errors.test.ts +350 -0
- package/src/errors.ts +217 -0
- package/src/events/store.test.ts +660 -0
- package/src/events/store.ts +369 -0
- package/src/events/tailer.test.ts +719 -0
- package/src/events/tailer.ts +332 -0
- package/src/events/tool-filter.test.ts +330 -0
- package/src/events/tool-filter.ts +126 -0
- package/src/index.ts +533 -0
- package/src/insights/analyzer.test.ts +466 -0
- package/src/insights/analyzer.ts +203 -0
- package/src/insights/quality-gates.test.ts +141 -0
- package/src/insights/quality-gates.ts +156 -0
- package/src/json.test.ts +72 -0
- package/src/json.ts +53 -0
- package/src/loam/client.test.ts +752 -0
- package/src/loam/client.ts +664 -0
- package/src/logging/color.test.ts +252 -0
- package/src/logging/color.ts +105 -0
- package/src/logging/format.test.ts +110 -0
- package/src/logging/format.ts +255 -0
- package/src/logging/logger.test.ts +814 -0
- package/src/logging/logger.ts +266 -0
- package/src/logging/reporter.test.ts +259 -0
- package/src/logging/reporter.ts +110 -0
- package/src/logging/sanitizer.test.ts +190 -0
- package/src/logging/sanitizer.ts +57 -0
- package/src/logging/theme.ts +140 -0
- package/src/mail/broadcast.test.ts +204 -0
- package/src/mail/broadcast.ts +92 -0
- package/src/mail/client.test.ts +774 -0
- package/src/mail/client.ts +236 -0
- package/src/mail/store.test.ts +898 -0
- package/src/mail/store.ts +425 -0
- package/src/merge/lock.test.ts +149 -0
- package/src/merge/lock.ts +140 -0
- package/src/merge/predict.test.ts +387 -0
- package/src/merge/predict.ts +249 -0
- package/src/merge/queue.test.ts +426 -0
- package/src/merge/queue.ts +246 -0
- package/src/merge/resolver.test.ts +1993 -0
- package/src/merge/resolver.ts +926 -0
- package/src/metrics/pricing.test.ts +258 -0
- package/src/metrics/pricing.ts +135 -0
- package/src/metrics/store.test.ts +978 -0
- package/src/metrics/store.ts +501 -0
- package/src/metrics/summary.test.ts +398 -0
- package/src/metrics/summary.ts +178 -0
- package/src/metrics/transcript.test.ts +483 -0
- package/src/metrics/transcript.ts +114 -0
- package/src/runtimes/__fixtures__/claude-stream-fixture.ts +22 -0
- package/src/runtimes/aider.test.ts +124 -0
- package/src/runtimes/aider.ts +147 -0
- package/src/runtimes/amp.test.ts +164 -0
- package/src/runtimes/amp.ts +154 -0
- package/src/runtimes/claude.test.ts +1474 -0
- package/src/runtimes/claude.ts +579 -0
- package/src/runtimes/codex.test.ts +805 -0
- package/src/runtimes/codex.ts +273 -0
- package/src/runtimes/connections.test.ts +214 -0
- package/src/runtimes/connections.ts +103 -0
- package/src/runtimes/copilot.test.ts +707 -0
- package/src/runtimes/copilot.ts +316 -0
- package/src/runtimes/cursor.test.ts +497 -0
- package/src/runtimes/cursor.ts +205 -0
- package/src/runtimes/gemini.test.ts +537 -0
- package/src/runtimes/gemini.ts +243 -0
- package/src/runtimes/goose.test.ts +133 -0
- package/src/runtimes/goose.ts +157 -0
- package/src/runtimes/headless-connection.test.ts +264 -0
- package/src/runtimes/headless-connection.ts +158 -0
- package/src/runtimes/opencode.test.ts +325 -0
- package/src/runtimes/opencode.ts +188 -0
- package/src/runtimes/pi-guards.test.ts +486 -0
- package/src/runtimes/pi-guards.ts +367 -0
- package/src/runtimes/pi.test.ts +789 -0
- package/src/runtimes/pi.ts +305 -0
- package/src/runtimes/registry.test.ts +196 -0
- package/src/runtimes/registry.ts +99 -0
- package/src/runtimes/sapling.test.ts +1267 -0
- package/src/runtimes/sapling.ts +710 -0
- package/src/runtimes/types.ts +266 -0
- package/src/schema-consistency.test.ts +246 -0
- package/src/sessions/compat.test.ts +281 -0
- package/src/sessions/compat.ts +105 -0
- package/src/sessions/store.test.ts +1748 -0
- package/src/sessions/store.ts +858 -0
- package/src/test-helpers.test.ts +124 -0
- package/src/test-helpers.ts +145 -0
- package/src/test-setup.test.ts +31 -0
- package/src/test-setup.ts +28 -0
- package/src/tools/loam/api.ts +368 -0
- package/src/tools/loam/cli.ts +278 -0
- package/src/tools/loam/commands/add.ts +52 -0
- package/src/tools/loam/commands/archive.ts +214 -0
- package/src/tools/loam/commands/audit.ts +276 -0
- package/src/tools/loam/commands/compact.ts +1062 -0
- package/src/tools/loam/commands/completions.ts +79 -0
- package/src/tools/loam/commands/config.ts +381 -0
- package/src/tools/loam/commands/delete-domain.ts +121 -0
- package/src/tools/loam/commands/delete.ts +316 -0
- package/src/tools/loam/commands/diff.ts +200 -0
- package/src/tools/loam/commands/doctor.ts +1113 -0
- package/src/tools/loam/commands/edit.ts +226 -0
- package/src/tools/loam/commands/init.ts +31 -0
- package/src/tools/loam/commands/learn.ts +179 -0
- package/src/tools/loam/commands/move.ts +323 -0
- package/src/tools/loam/commands/onboard.ts +374 -0
- package/src/tools/loam/commands/outcome.ts +185 -0
- package/src/tools/loam/commands/prime.ts +688 -0
- package/src/tools/loam/commands/prune.ts +614 -0
- package/src/tools/loam/commands/query.ts +218 -0
- package/src/tools/loam/commands/rank.ts +180 -0
- package/src/tools/loam/commands/ready.ts +189 -0
- package/src/tools/loam/commands/record.ts +1210 -0
- package/src/tools/loam/commands/restore.ts +166 -0
- package/src/tools/loam/commands/search.ts +327 -0
- package/src/tools/loam/commands/setup.ts +887 -0
- package/src/tools/loam/commands/status.ts +103 -0
- package/src/tools/loam/commands/sync.ts +298 -0
- package/src/tools/loam/commands/update.ts +19 -0
- package/src/tools/loam/commands/upgrade.ts +93 -0
- package/src/tools/loam/commands/validate.ts +190 -0
- package/src/tools/loam/index.ts +62 -0
- package/src/tools/loam/log.ts +127 -0
- package/src/tools/loam/registry/builtins.ts +409 -0
- package/src/tools/loam/registry/custom.ts +431 -0
- package/src/tools/loam/registry/init.ts +55 -0
- package/src/tools/loam/registry/template.ts +40 -0
- package/src/tools/loam/registry/type-registry.ts +113 -0
- package/src/tools/loam/schemas/config-schema.ts +489 -0
- package/src/tools/loam/schemas/config.ts +245 -0
- package/src/tools/loam/schemas/index.ts +18 -0
- package/src/tools/loam/schemas/record-schema.ts +191 -0
- package/src/tools/loam/schemas/record.ts +115 -0
- package/src/tools/loam/utils/active-work.ts +205 -0
- package/src/tools/loam/utils/anchor-validity.ts +80 -0
- package/src/tools/loam/utils/archive.ts +146 -0
- package/src/tools/loam/utils/audit.ts +667 -0
- package/src/tools/loam/utils/bm25.ts +238 -0
- package/src/tools/loam/utils/budget.ts +142 -0
- package/src/tools/loam/utils/config.ts +344 -0
- package/src/tools/loam/utils/dir-anchors.ts +62 -0
- package/src/tools/loam/utils/domain-rules.ts +114 -0
- package/src/tools/loam/utils/expertise.ts +393 -0
- package/src/tools/loam/utils/format-helpers.ts +96 -0
- package/src/tools/loam/utils/format.ts +1234 -0
- package/src/tools/loam/utils/git-context.ts +50 -0
- package/src/tools/loam/utils/git.ts +183 -0
- package/src/tools/loam/utils/hooks.ts +299 -0
- package/src/tools/loam/utils/index.ts +52 -0
- package/src/tools/loam/utils/json-output.ts +13 -0
- package/src/tools/loam/utils/lock.ts +76 -0
- package/src/tools/loam/utils/markers.ts +48 -0
- package/src/tools/loam/utils/numeric-flags.ts +20 -0
- package/src/tools/loam/utils/palette.ts +44 -0
- package/src/tools/loam/utils/prime-ranking.ts +135 -0
- package/src/tools/loam/utils/recipe-discovery.ts +195 -0
- package/src/tools/loam/utils/runtime-flags.ts +28 -0
- package/src/tools/loam/utils/scoring.ts +94 -0
- package/src/tools/loam/utils/version.ts +116 -0
- package/src/tools/sprout/commands/block.ts +64 -0
- package/src/tools/sprout/commands/blocked.ts +86 -0
- package/src/tools/sprout/commands/close.ts +129 -0
- package/src/tools/sprout/commands/completions.ts +198 -0
- package/src/tools/sprout/commands/config.ts +238 -0
- package/src/tools/sprout/commands/create.ts +164 -0
- package/src/tools/sprout/commands/dep.ts +148 -0
- package/src/tools/sprout/commands/doctor.ts +979 -0
- package/src/tools/sprout/commands/init.ts +83 -0
- package/src/tools/sprout/commands/label.ts +178 -0
- package/src/tools/sprout/commands/list.ts +210 -0
- package/src/tools/sprout/commands/migrate.ts +133 -0
- package/src/tools/sprout/commands/onboard.ts +207 -0
- package/src/tools/sprout/commands/plan-show.ts +278 -0
- package/src/tools/sprout/commands/plan.ts +2526 -0
- package/src/tools/sprout/commands/prime.ts +399 -0
- package/src/tools/sprout/commands/ready.ts +245 -0
- package/src/tools/sprout/commands/search.ts +221 -0
- package/src/tools/sprout/commands/show.ts +277 -0
- package/src/tools/sprout/commands/stats.ts +146 -0
- package/src/tools/sprout/commands/sync.ts +134 -0
- package/src/tools/sprout/commands/tpl.ts +364 -0
- package/src/tools/sprout/commands/unblock.ts +115 -0
- package/src/tools/sprout/commands/update.ts +257 -0
- package/src/tools/sprout/commands/upgrade.ts +91 -0
- package/src/tools/sprout/config-schema.ts +152 -0
- package/src/tools/sprout/config.ts +355 -0
- package/src/tools/sprout/filter.ts +107 -0
- package/src/tools/sprout/format.ts +43 -0
- package/src/tools/sprout/id.ts +22 -0
- package/src/tools/sprout/index.ts +204 -0
- package/src/tools/sprout/log.ts +76 -0
- package/src/tools/sprout/markers.ts +22 -0
- package/src/tools/sprout/output.ts +121 -0
- package/src/tools/sprout/plan-backref.ts +93 -0
- package/src/tools/sprout/plan-context.ts +81 -0
- package/src/tools/sprout/plan-domain.ts +139 -0
- package/src/tools/sprout/plan-lifecycle.ts +65 -0
- package/src/tools/sprout/plan-loam.ts +207 -0
- package/src/tools/sprout/plan-schema.ts +209 -0
- package/src/tools/sprout/sort.ts +31 -0
- package/src/tools/sprout/store.ts +172 -0
- package/src/tools/sprout/types.ts +118 -0
- package/src/tools/sprout/validation.ts +119 -0
- package/src/tools/sprout/version.ts +1 -0
- package/src/tools/sprout/yaml.ts +387 -0
- package/src/tools/trellis/commands/archive.ts +87 -0
- package/src/tools/trellis/commands/completions.ts +610 -0
- package/src/tools/trellis/commands/config.ts +382 -0
- package/src/tools/trellis/commands/create.ts +252 -0
- package/src/tools/trellis/commands/diff.ts +150 -0
- package/src/tools/trellis/commands/doctor.ts +771 -0
- package/src/tools/trellis/commands/emit.ts +365 -0
- package/src/tools/trellis/commands/history.ts +83 -0
- package/src/tools/trellis/commands/import.ts +198 -0
- package/src/tools/trellis/commands/init.ts +81 -0
- package/src/tools/trellis/commands/list.ts +103 -0
- package/src/tools/trellis/commands/onboard.ts +156 -0
- package/src/tools/trellis/commands/pin.ts +172 -0
- package/src/tools/trellis/commands/prime.ts +193 -0
- package/src/tools/trellis/commands/render.ts +122 -0
- package/src/tools/trellis/commands/schema.ts +353 -0
- package/src/tools/trellis/commands/show.ts +115 -0
- package/src/tools/trellis/commands/stats.ts +65 -0
- package/src/tools/trellis/commands/sync.ts +112 -0
- package/src/tools/trellis/commands/tree.ts +123 -0
- package/src/tools/trellis/commands/update.ts +330 -0
- package/src/tools/trellis/commands/upgrade.ts +95 -0
- package/src/tools/trellis/commands/validate.ts +166 -0
- package/src/tools/trellis/config-schema.ts +81 -0
- package/src/tools/trellis/config.ts +108 -0
- package/src/tools/trellis/frontmatter.ts +348 -0
- package/src/tools/trellis/id.ts +24 -0
- package/src/tools/trellis/index.ts +209 -0
- package/src/tools/trellis/markers.ts +28 -0
- package/src/tools/trellis/output.ts +84 -0
- package/src/tools/trellis/render.ts +212 -0
- package/src/tools/trellis/store.ts +144 -0
- package/src/tools/trellis/types.ts +82 -0
- package/src/tools/trellis/validate.ts +199 -0
- package/src/tools/trellis/yaml.ts +309 -0
- package/src/tracker/beads.test.ts +454 -0
- package/src/tracker/beads.ts +56 -0
- package/src/tracker/factory.test.ts +90 -0
- package/src/tracker/factory.ts +65 -0
- package/src/tracker/sprout.test.ts +461 -0
- package/src/tracker/sprout.ts +182 -0
- package/src/tracker/types.ts +52 -0
- package/src/trellis/client.test.ts +107 -0
- package/src/trellis/client.ts +179 -0
- package/src/types.ts +970 -0
- package/src/utils/bin.test.ts +10 -0
- package/src/utils/bin.ts +37 -0
- package/src/utils/browser.test.ts +49 -0
- package/src/utils/browser.ts +48 -0
- package/src/utils/fs.test.ts +119 -0
- package/src/utils/fs.ts +62 -0
- package/src/utils/pid.test.ts +152 -0
- package/src/utils/pid.ts +130 -0
- package/src/utils/process-scan.test.ts +53 -0
- package/src/utils/process-scan.ts +76 -0
- package/src/utils/time.test.ts +43 -0
- package/src/utils/time.ts +37 -0
- package/src/utils/version.test.ts +33 -0
- package/src/utils/version.ts +70 -0
- package/src/version.ts +5 -0
- package/src/watchdog/daemon.test.ts +3721 -0
- package/src/watchdog/daemon.ts +1257 -0
- package/src/watchdog/health.test.ts +830 -0
- package/src/watchdog/health.ts +434 -0
- package/src/watchdog/triage.test.ts +205 -0
- package/src/watchdog/triage.ts +205 -0
- package/src/worktree/manager.test.ts +720 -0
- package/src/worktree/manager.ts +405 -0
- package/src/worktree/process.test.ts +172 -0
- package/src/worktree/process.ts +131 -0
- package/src/worktree/tmux.test.ts +1616 -0
- package/src/worktree/tmux.ts +721 -0
- package/templates/CLAUDE.md.tmpl +100 -0
- package/templates/copilot-hooks.json.tmpl +13 -0
- package/templates/hooks.json.tmpl +109 -0
- package/templates/overlay.md.tmpl +88 -0
- package/ui/dist/apple-touch-icon-bdy6teep.png +0 -0
- package/ui/dist/chunk-8s31f05k.css +1 -0
- package/ui/dist/chunk-vm5rz679.js +300 -0
- package/ui/dist/favicon-nzb39vza.svg +4 -0
- package/ui/dist/index.html +17 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command: agentplate run [subcommand] [--json]
|
|
3
|
+
*
|
|
4
|
+
* Manage runs (coordinator session groupings).
|
|
5
|
+
* A "run" groups all agents spawned from one coordinator session.
|
|
6
|
+
*
|
|
7
|
+
* Subcommands:
|
|
8
|
+
* (default) Show current run status
|
|
9
|
+
* list List recent runs
|
|
10
|
+
* complete Mark current run as completed
|
|
11
|
+
* show <id> Show run details with agents
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { Command, CommanderError } from "commander";
|
|
16
|
+
import { loadConfig } from "../config.ts";
|
|
17
|
+
import { ValidationError } from "../errors.ts";
|
|
18
|
+
import { jsonError, jsonOutput } from "../json.ts";
|
|
19
|
+
import { accent, printError, printHint, printSuccess } from "../logging/color.ts";
|
|
20
|
+
import { formatDuration } from "../logging/format.ts";
|
|
21
|
+
import { renderHeader, separator } from "../logging/theme.ts";
|
|
22
|
+
import { createRunStore, createSessionStore } from "../sessions/store.ts";
|
|
23
|
+
import type { AgentSession, Run } from "../types.ts";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get the path to the current-run.txt file.
|
|
27
|
+
*/
|
|
28
|
+
function currentRunPath(agentplateDir: string): string {
|
|
29
|
+
return join(agentplateDir, "current-run.txt");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Read the current run ID from current-run.txt, or null if no active run.
|
|
34
|
+
*/
|
|
35
|
+
async function readCurrentRunId(agentplateDir: string): Promise<string | null> {
|
|
36
|
+
const path = currentRunPath(agentplateDir);
|
|
37
|
+
const file = Bun.file(path);
|
|
38
|
+
if (!(await file.exists())) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const text = await file.text();
|
|
42
|
+
const trimmed = text.trim();
|
|
43
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Compute duration string for a run.
|
|
48
|
+
*/
|
|
49
|
+
function runDuration(run: Run): string {
|
|
50
|
+
const start = new Date(run.startedAt).getTime();
|
|
51
|
+
const end = run.completedAt ? new Date(run.completedAt).getTime() : Date.now();
|
|
52
|
+
return formatDuration(end - start);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Format an agent's duration from startedAt to now (or completion).
|
|
57
|
+
*/
|
|
58
|
+
function formatAgentDuration(agent: AgentSession): string {
|
|
59
|
+
const start = new Date(agent.startedAt).getTime();
|
|
60
|
+
const end =
|
|
61
|
+
agent.state === "completed" || agent.state === "zombie"
|
|
62
|
+
? new Date(agent.lastActivity).getTime()
|
|
63
|
+
: Date.now();
|
|
64
|
+
return formatDuration(end - start);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Show current run status (default subcommand).
|
|
69
|
+
*/
|
|
70
|
+
async function showCurrentRun(agentplateDir: string, json: boolean): Promise<void> {
|
|
71
|
+
const runId = await readCurrentRunId(agentplateDir);
|
|
72
|
+
if (!runId) {
|
|
73
|
+
if (json) {
|
|
74
|
+
jsonOutput("run", { run: null, message: "No active run" });
|
|
75
|
+
} else {
|
|
76
|
+
printHint("No active run");
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const dbPath = join(agentplateDir, "sessions.db");
|
|
82
|
+
const runStore = createRunStore(dbPath);
|
|
83
|
+
try {
|
|
84
|
+
const run = runStore.getRun(runId);
|
|
85
|
+
if (!run) {
|
|
86
|
+
if (json) {
|
|
87
|
+
jsonOutput("run", { run: null, message: `Run ${runId} not found in store` });
|
|
88
|
+
} else {
|
|
89
|
+
process.stdout.write(`Run ${accent(runId)} not found in store\n`);
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (json) {
|
|
95
|
+
jsonOutput("run", { run, duration: runDuration(run) });
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
process.stdout.write(`${renderHeader("Current Run")}\n`);
|
|
100
|
+
process.stdout.write(` ID: ${accent(run.id)}\n`);
|
|
101
|
+
process.stdout.write(` Status: ${run.status}\n`);
|
|
102
|
+
process.stdout.write(` Started: ${run.startedAt}\n`);
|
|
103
|
+
process.stdout.write(` Agents: ${run.agentCount}\n`);
|
|
104
|
+
process.stdout.write(` Duration: ${runDuration(run)}\n`);
|
|
105
|
+
} finally {
|
|
106
|
+
runStore.close();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* List recent runs.
|
|
112
|
+
*/
|
|
113
|
+
async function listRuns(agentplateDir: string, limit: number, json: boolean): Promise<void> {
|
|
114
|
+
const dbPath = join(agentplateDir, "sessions.db");
|
|
115
|
+
const dbFile = Bun.file(dbPath);
|
|
116
|
+
if (!(await dbFile.exists())) {
|
|
117
|
+
if (json) {
|
|
118
|
+
jsonOutput("run list", { runs: [] });
|
|
119
|
+
} else {
|
|
120
|
+
printHint("No runs recorded yet");
|
|
121
|
+
}
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const runStore = createRunStore(dbPath);
|
|
126
|
+
try {
|
|
127
|
+
const runs = runStore.listRuns({ limit });
|
|
128
|
+
|
|
129
|
+
if (json) {
|
|
130
|
+
const runsWithDuration = runs.map((r) => ({ ...r, duration: runDuration(r) }));
|
|
131
|
+
jsonOutput("run list", { runs: runsWithDuration });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (runs.length === 0) {
|
|
136
|
+
printHint("No runs recorded yet");
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
process.stdout.write(`${renderHeader("Recent Runs")}\n`);
|
|
141
|
+
process.stdout.write(
|
|
142
|
+
`${"ID".padEnd(36)} ${"Status".padEnd(10)} ${"Agents".padEnd(7)} Duration\n`,
|
|
143
|
+
);
|
|
144
|
+
process.stdout.write(`${separator()}\n`);
|
|
145
|
+
|
|
146
|
+
for (const run of runs) {
|
|
147
|
+
const id = accent(run.id.length > 35 ? `${run.id.slice(0, 32)}...` : run.id.padEnd(36));
|
|
148
|
+
const status = run.status.padEnd(10);
|
|
149
|
+
const agents = String(run.agentCount).padEnd(7);
|
|
150
|
+
const duration = runDuration(run);
|
|
151
|
+
process.stdout.write(`${id} ${status} ${agents} ${duration}\n`);
|
|
152
|
+
}
|
|
153
|
+
} finally {
|
|
154
|
+
runStore.close();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Mark the current run as completed.
|
|
160
|
+
*/
|
|
161
|
+
async function completeCurrentRun(agentplateDir: string, json: boolean): Promise<void> {
|
|
162
|
+
const runId = await readCurrentRunId(agentplateDir);
|
|
163
|
+
if (!runId) {
|
|
164
|
+
if (json) {
|
|
165
|
+
jsonError("run complete", "No active run to complete");
|
|
166
|
+
} else {
|
|
167
|
+
printError("No active run to complete");
|
|
168
|
+
}
|
|
169
|
+
process.exitCode = 1;
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const dbPath = join(agentplateDir, "sessions.db");
|
|
174
|
+
const runStore = createRunStore(dbPath);
|
|
175
|
+
try {
|
|
176
|
+
runStore.completeRun(runId, "completed");
|
|
177
|
+
} finally {
|
|
178
|
+
runStore.close();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Delete current-run.txt
|
|
182
|
+
const { unlink } = await import("node:fs/promises");
|
|
183
|
+
try {
|
|
184
|
+
await unlink(currentRunPath(agentplateDir));
|
|
185
|
+
} catch {
|
|
186
|
+
// File may already be gone, that's fine
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (json) {
|
|
190
|
+
jsonOutput("run complete", { runId, status: "completed" });
|
|
191
|
+
} else {
|
|
192
|
+
printSuccess("Run completed", runId);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Show detailed information for a specific run.
|
|
198
|
+
*/
|
|
199
|
+
async function showRun(agentplateDir: string, runId: string, json: boolean): Promise<void> {
|
|
200
|
+
const dbPath = join(agentplateDir, "sessions.db");
|
|
201
|
+
const dbFile = Bun.file(dbPath);
|
|
202
|
+
if (!(await dbFile.exists())) {
|
|
203
|
+
if (json) {
|
|
204
|
+
jsonError("run show", `Run ${runId} not found`);
|
|
205
|
+
} else {
|
|
206
|
+
printError("Run not found", runId);
|
|
207
|
+
}
|
|
208
|
+
process.exitCode = 1;
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const runStore = createRunStore(dbPath);
|
|
213
|
+
const sessionStore = createSessionStore(dbPath);
|
|
214
|
+
try {
|
|
215
|
+
const run = runStore.getRun(runId);
|
|
216
|
+
if (!run) {
|
|
217
|
+
if (json) {
|
|
218
|
+
jsonError("run show", `Run ${runId} not found`);
|
|
219
|
+
} else {
|
|
220
|
+
printError("Run not found", runId);
|
|
221
|
+
}
|
|
222
|
+
process.exitCode = 1;
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const agents = sessionStore.getByRun(runId);
|
|
227
|
+
|
|
228
|
+
if (json) {
|
|
229
|
+
jsonOutput("run show", { run, duration: runDuration(run), agents });
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
process.stdout.write(`${renderHeader("Run Details")}\n`);
|
|
234
|
+
process.stdout.write(` ID: ${accent(run.id)}\n`);
|
|
235
|
+
process.stdout.write(` Status: ${run.status}\n`);
|
|
236
|
+
process.stdout.write(` Started: ${run.startedAt}\n`);
|
|
237
|
+
if (run.completedAt) {
|
|
238
|
+
process.stdout.write(` Ended: ${run.completedAt}\n`);
|
|
239
|
+
}
|
|
240
|
+
process.stdout.write(` Agents: ${run.agentCount}\n`);
|
|
241
|
+
process.stdout.write(` Duration: ${runDuration(run)}\n`);
|
|
242
|
+
|
|
243
|
+
if (agents.length > 0) {
|
|
244
|
+
process.stdout.write(`\nAgents (${agents.length}):\n`);
|
|
245
|
+
process.stdout.write(`${separator()}\n`);
|
|
246
|
+
for (const agent of agents) {
|
|
247
|
+
const agentDuration = formatAgentDuration(agent);
|
|
248
|
+
process.stdout.write(
|
|
249
|
+
` ${accent(agent.agentName)} [${agent.capability}] ${agent.state} | ${agentDuration}\n`,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
} else {
|
|
253
|
+
process.stdout.write("\nNo agents recorded for this run.\n");
|
|
254
|
+
}
|
|
255
|
+
} finally {
|
|
256
|
+
runStore.close();
|
|
257
|
+
sessionStore.close();
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
interface RunDefaultOpts {
|
|
262
|
+
json?: boolean;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
interface RunListOpts {
|
|
266
|
+
last?: string;
|
|
267
|
+
json?: boolean;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
interface RunShowOpts {
|
|
271
|
+
json?: boolean;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
interface RunCompleteOpts {
|
|
275
|
+
json?: boolean;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export function createRunCommand(): Command {
|
|
279
|
+
const cmd = new Command("run").description("Manage runs (coordinator session groupings)");
|
|
280
|
+
|
|
281
|
+
// Default action (bare `agentplate run`)
|
|
282
|
+
cmd.option("--json", "Output as JSON").action(async (opts: RunDefaultOpts) => {
|
|
283
|
+
const cwd = process.cwd();
|
|
284
|
+
const config = await loadConfig(cwd);
|
|
285
|
+
const agentplateDir = join(config.project.root, ".agentplate");
|
|
286
|
+
await showCurrentRun(agentplateDir, opts.json ?? false);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// `agentplate run list`
|
|
290
|
+
cmd
|
|
291
|
+
.command("list")
|
|
292
|
+
.description("List recent runs")
|
|
293
|
+
.option("--last <n>", "Number of recent runs to show (default: 10)")
|
|
294
|
+
.option("--json", "Output as JSON")
|
|
295
|
+
.action(async (opts: RunListOpts) => {
|
|
296
|
+
const lastStr = opts.last;
|
|
297
|
+
const limit = lastStr ? Number.parseInt(lastStr, 10) : 10;
|
|
298
|
+
if (Number.isNaN(limit) || limit < 1) {
|
|
299
|
+
throw new ValidationError("--last must be a positive integer", {
|
|
300
|
+
field: "last",
|
|
301
|
+
value: lastStr,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
const cwd = process.cwd();
|
|
305
|
+
const config = await loadConfig(cwd);
|
|
306
|
+
const agentplateDir = join(config.project.root, ".agentplate");
|
|
307
|
+
await listRuns(agentplateDir, limit, opts.json ?? false);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// `agentplate run show <id>`
|
|
311
|
+
cmd
|
|
312
|
+
.command("show")
|
|
313
|
+
.description("Show run details (agents, duration)")
|
|
314
|
+
.argument("<id>", "Run ID")
|
|
315
|
+
.option("--json", "Output as JSON")
|
|
316
|
+
.action(async (id: string, opts: RunShowOpts) => {
|
|
317
|
+
const cwd = process.cwd();
|
|
318
|
+
const config = await loadConfig(cwd);
|
|
319
|
+
const agentplateDir = join(config.project.root, ".agentplate");
|
|
320
|
+
await showRun(agentplateDir, id, opts.json ?? false);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// `agentplate run complete`
|
|
324
|
+
cmd
|
|
325
|
+
.command("complete")
|
|
326
|
+
.description("Mark current run as completed")
|
|
327
|
+
.option("--json", "Output as JSON")
|
|
328
|
+
.action(async (opts: RunCompleteOpts) => {
|
|
329
|
+
const cwd = process.cwd();
|
|
330
|
+
const config = await loadConfig(cwd);
|
|
331
|
+
const agentplateDir = join(config.project.root, ".agentplate");
|
|
332
|
+
await completeCurrentRun(agentplateDir, opts.json ?? false);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
return cmd;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export async function runCommand(args: string[]): Promise<void> {
|
|
339
|
+
const program = new Command("ap").exitOverride().configureOutput({
|
|
340
|
+
writeOut: (str) => process.stdout.write(str),
|
|
341
|
+
writeErr: (str) => process.stderr.write(str),
|
|
342
|
+
});
|
|
343
|
+
program.addCommand(createRunCommand());
|
|
344
|
+
try {
|
|
345
|
+
await program.parseAsync(["node", "ap", "run", ...args]);
|
|
346
|
+
} catch (err: unknown) {
|
|
347
|
+
if (err instanceof CommanderError) {
|
|
348
|
+
if (err.code === "commander.helpDisplayed" || err.code === "commander.version") return;
|
|
349
|
+
throw new ValidationError(err.message, { field: "args" });
|
|
350
|
+
}
|
|
351
|
+
throw err;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the fleet-control action wrappers (sling / stop / merge).
|
|
3
|
+
*
|
|
4
|
+
* Uses a real file-backed SessionStore and dependency-injected fakes for the
|
|
5
|
+
* heavy command cores (slingCommand / stopCommand / mergeCommand /
|
|
6
|
+
* predictConflicts) so no agents are spawned and git is never touched.
|
|
7
|
+
*
|
|
8
|
+
* mock.module() is intentionally avoided per loam record mx-56558b.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
12
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
13
|
+
import { tmpdir } from "node:os";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { ValidationError } from "../../errors.ts";
|
|
16
|
+
import type { SessionStore } from "../../sessions/store.ts";
|
|
17
|
+
import { createSessionStore } from "../../sessions/store.ts";
|
|
18
|
+
import type { AgentplateConfig, AgentSession, ConflictPrediction } from "../../types.ts";
|
|
19
|
+
import {
|
|
20
|
+
type AgentActionDeps,
|
|
21
|
+
mergePreview,
|
|
22
|
+
mergeRun,
|
|
23
|
+
slingAgent,
|
|
24
|
+
stopAgent,
|
|
25
|
+
} from "./agent-actions.ts";
|
|
26
|
+
|
|
27
|
+
interface Ctx {
|
|
28
|
+
tempDir: string;
|
|
29
|
+
sessionStore: SessionStore;
|
|
30
|
+
deps: AgentActionDeps;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function makeSession(name: string, overrides: Partial<AgentSession> = {}): AgentSession {
|
|
34
|
+
const now = new Date().toISOString();
|
|
35
|
+
return {
|
|
36
|
+
id: `session-${name}`,
|
|
37
|
+
agentName: name,
|
|
38
|
+
capability: "builder",
|
|
39
|
+
worktreePath: "/tmp/wt",
|
|
40
|
+
branchName: `agentplate/${name}/t1`,
|
|
41
|
+
taskId: "t1",
|
|
42
|
+
tmuxSession: "",
|
|
43
|
+
state: "working",
|
|
44
|
+
pid: 12345,
|
|
45
|
+
parentAgent: null,
|
|
46
|
+
depth: 0,
|
|
47
|
+
runId: "run-1",
|
|
48
|
+
startedAt: now,
|
|
49
|
+
lastActivity: now,
|
|
50
|
+
escalationLevel: 0,
|
|
51
|
+
stalledSince: null,
|
|
52
|
+
transcriptPath: null,
|
|
53
|
+
...overrides,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function makeCtx(): Ctx {
|
|
58
|
+
const tempDir = mkdtempSync(join(tmpdir(), "ap-agent-actions-"));
|
|
59
|
+
const sessionStore = createSessionStore(join(tempDir, "sessions.db"));
|
|
60
|
+
return {
|
|
61
|
+
tempDir,
|
|
62
|
+
sessionStore,
|
|
63
|
+
deps: { projectRoot: tempDir, _sessionStore: sessionStore },
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
describe("agent-actions", () => {
|
|
68
|
+
let ctx: Ctx;
|
|
69
|
+
|
|
70
|
+
beforeEach(() => {
|
|
71
|
+
ctx = makeCtx();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
afterEach(() => {
|
|
75
|
+
ctx.sessionStore.close();
|
|
76
|
+
rmSync(ctx.tempDir, { recursive: true, force: true });
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// ─── slingAgent ─────────────────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
test("slingAgent forces headless + json and reads back the created session", async () => {
|
|
82
|
+
let calledTaskId: string | null = null;
|
|
83
|
+
let calledOpts: Record<string, unknown> | null = null;
|
|
84
|
+
const deps: AgentActionDeps = {
|
|
85
|
+
...ctx.deps,
|
|
86
|
+
_slingCommand: async (taskId, opts) => {
|
|
87
|
+
calledTaskId = taskId;
|
|
88
|
+
calledOpts = opts as Record<string, unknown>;
|
|
89
|
+
// Simulate the spawn writing a session row.
|
|
90
|
+
ctx.sessionStore.upsert(makeSession("builder-t1", { state: "booting" }));
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const result = await slingAgent(deps, { taskId: "t1", capability: "builder" });
|
|
95
|
+
|
|
96
|
+
expect(calledTaskId as string | null).toBe("t1");
|
|
97
|
+
expect(calledOpts).toMatchObject({ json: true, headless: true, capability: "builder" });
|
|
98
|
+
expect(result).toEqual({ agentName: "builder-t1", state: "booting", spawned: true });
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("slingAgent honors an explicit name", async () => {
|
|
102
|
+
const deps: AgentActionDeps = {
|
|
103
|
+
...ctx.deps,
|
|
104
|
+
_slingCommand: async () => {
|
|
105
|
+
ctx.sessionStore.upsert(makeSession("custom", { capability: "scout" }));
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
const result = await slingAgent(deps, { taskId: "t1", capability: "scout", name: "custom" });
|
|
109
|
+
expect(result.agentName).toBe("custom");
|
|
110
|
+
expect(result.spawned).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("slingAgent rejects a missing taskId", async () => {
|
|
114
|
+
await expect(slingAgent(ctx.deps, { taskId: " " })).rejects.toBeInstanceOf(ValidationError);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// ─── stopAgent ──────────────────────────────────────────────────────────
|
|
118
|
+
|
|
119
|
+
test("stopAgent invokes stopCommand with json + cleanWorktree", async () => {
|
|
120
|
+
let calledName: string | null = null;
|
|
121
|
+
let calledOpts: Record<string, unknown> | null = null;
|
|
122
|
+
const deps: AgentActionDeps = {
|
|
123
|
+
...ctx.deps,
|
|
124
|
+
_stopCommand: async (name, opts) => {
|
|
125
|
+
calledName = name;
|
|
126
|
+
calledOpts = opts as Record<string, unknown>;
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
const result = await stopAgent(deps, "builder-t1", { cleanWorktree: true });
|
|
130
|
+
expect(calledName as string | null).toBe("builder-t1");
|
|
131
|
+
expect(calledOpts).toMatchObject({ json: true, cleanWorktree: true });
|
|
132
|
+
expect(result).toEqual({ stopped: true, agentName: "builder-t1" });
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("stopAgent rejects an empty name", async () => {
|
|
136
|
+
await expect(stopAgent(ctx.deps, " ")).rejects.toBeInstanceOf(ValidationError);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// ─── mergePreview ─────────────────────────────────────────────────────────
|
|
140
|
+
|
|
141
|
+
test("mergePreview uses the explicit target and returns the prediction", async () => {
|
|
142
|
+
const prediction: ConflictPrediction = {
|
|
143
|
+
predictedTier: "clean-merge",
|
|
144
|
+
conflictFiles: [],
|
|
145
|
+
wouldRequireAgent: false,
|
|
146
|
+
reason: "no conflicts",
|
|
147
|
+
};
|
|
148
|
+
let predictTarget: string | null = null;
|
|
149
|
+
const deps: AgentActionDeps = {
|
|
150
|
+
...ctx.deps,
|
|
151
|
+
_predictConflicts: async (entry, canonicalBranch) => {
|
|
152
|
+
predictTarget = canonicalBranch;
|
|
153
|
+
expect(entry.branchName).toBe("agentplate/builder-t1/t1");
|
|
154
|
+
return prediction;
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
const result = await mergePreview(deps, {
|
|
158
|
+
branch: "agentplate/builder-t1/t1",
|
|
159
|
+
into: "develop",
|
|
160
|
+
});
|
|
161
|
+
expect(predictTarget as string | null).toBe("develop");
|
|
162
|
+
expect(result).toMatchObject({
|
|
163
|
+
predictedTier: "clean-merge",
|
|
164
|
+
branch: "agentplate/builder-t1/t1",
|
|
165
|
+
target: "develop",
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("mergePreview falls back to config canonicalBranch when no target given", async () => {
|
|
170
|
+
const deps: AgentActionDeps = {
|
|
171
|
+
...ctx.deps,
|
|
172
|
+
_loadConfig: async () =>
|
|
173
|
+
({ project: { root: ctx.tempDir, canonicalBranch: "main" } }) as AgentplateConfig,
|
|
174
|
+
_predictConflicts: async (_entry, canonicalBranch) => {
|
|
175
|
+
expect(canonicalBranch).toBe("main");
|
|
176
|
+
return {
|
|
177
|
+
predictedTier: "clean-merge",
|
|
178
|
+
conflictFiles: [],
|
|
179
|
+
wouldRequireAgent: false,
|
|
180
|
+
reason: "ok",
|
|
181
|
+
};
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
const result = await mergePreview(deps, { branch: "agentplate/x/y" });
|
|
185
|
+
expect(result.target).toBe("main");
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test("mergePreview rejects a missing branch", async () => {
|
|
189
|
+
await expect(mergePreview(ctx.deps, { branch: "" })).rejects.toBeInstanceOf(ValidationError);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// ─── mergeRun ───────────────────────────────────────────────────────────
|
|
193
|
+
|
|
194
|
+
test("mergeRun forwards branch to mergeCommand", async () => {
|
|
195
|
+
let calledOpts: Record<string, unknown> | null = null;
|
|
196
|
+
const deps: AgentActionDeps = {
|
|
197
|
+
...ctx.deps,
|
|
198
|
+
_mergeCommand: async (opts) => {
|
|
199
|
+
calledOpts = opts as Record<string, unknown>;
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
const result = await mergeRun(deps, { branch: "agentplate/x/y" });
|
|
203
|
+
expect(calledOpts).toMatchObject({ json: true, branch: "agentplate/x/y" });
|
|
204
|
+
expect(result).toEqual({ triggered: true });
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("mergeRun rejects when neither branch nor all is provided", async () => {
|
|
208
|
+
await expect(mergeRun(ctx.deps, {})).rejects.toBeInstanceOf(ValidationError);
|
|
209
|
+
});
|
|
210
|
+
});
|