@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,752 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for loam CLI client.
|
|
3
|
+
*
|
|
4
|
+
* Uses real loam CLI when available (preferred).
|
|
5
|
+
* All tests are skipped if loam is not installed.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
9
|
+
import { mkdtemp } from "node:fs/promises";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { AgentError } from "../errors.ts";
|
|
13
|
+
import { cleanupTempDir } from "../test-helpers.ts";
|
|
14
|
+
import { createLoamClient } from "./client.ts";
|
|
15
|
+
|
|
16
|
+
// Check if loam is available
|
|
17
|
+
let hasLoam = false;
|
|
18
|
+
try {
|
|
19
|
+
const proc = Bun.spawn(["which", "lm"], { stdout: "pipe", stderr: "pipe" });
|
|
20
|
+
const exitCode = await proc.exited;
|
|
21
|
+
hasLoam = exitCode === 0;
|
|
22
|
+
} catch {
|
|
23
|
+
hasLoam = false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe("createLoamClient", () => {
|
|
27
|
+
let tempDir: string;
|
|
28
|
+
|
|
29
|
+
beforeEach(async () => {
|
|
30
|
+
tempDir = await mkdtemp(join(tmpdir(), "loam-test-"));
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
afterEach(async () => {
|
|
34
|
+
await cleanupTempDir(tempDir);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Helper to initialize git repo in tempDir.
|
|
39
|
+
* Some loam commands (diff, learn) require a git repository.
|
|
40
|
+
*/
|
|
41
|
+
async function initGit(): Promise<void> {
|
|
42
|
+
const initProc = Bun.spawn(["git", "init"], {
|
|
43
|
+
cwd: tempDir,
|
|
44
|
+
stdout: "pipe",
|
|
45
|
+
stderr: "pipe",
|
|
46
|
+
});
|
|
47
|
+
await initProc.exited;
|
|
48
|
+
|
|
49
|
+
const configNameProc = Bun.spawn(["git", "config", "user.name", "Test User"], {
|
|
50
|
+
cwd: tempDir,
|
|
51
|
+
stdout: "pipe",
|
|
52
|
+
stderr: "pipe",
|
|
53
|
+
});
|
|
54
|
+
await configNameProc.exited;
|
|
55
|
+
|
|
56
|
+
const configEmailProc = Bun.spawn(["git", "config", "user.email", "test@example.com"], {
|
|
57
|
+
cwd: tempDir,
|
|
58
|
+
stdout: "pipe",
|
|
59
|
+
stderr: "pipe",
|
|
60
|
+
});
|
|
61
|
+
await configEmailProc.exited;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Helper to initialize loam in tempDir.
|
|
66
|
+
* Creates .loam/ directory and initial structure.
|
|
67
|
+
*/
|
|
68
|
+
async function initLoam(): Promise<void> {
|
|
69
|
+
if (!hasLoam) return;
|
|
70
|
+
const proc = Bun.spawn(["lm", "init"], {
|
|
71
|
+
cwd: tempDir,
|
|
72
|
+
stdout: "pipe",
|
|
73
|
+
stderr: "pipe",
|
|
74
|
+
});
|
|
75
|
+
await proc.exited;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
describe("prime", () => {
|
|
79
|
+
test.skipIf(!hasLoam)("returns non-empty string", async () => {
|
|
80
|
+
await initLoam();
|
|
81
|
+
const client = createLoamClient(tempDir);
|
|
82
|
+
const result = await client.prime();
|
|
83
|
+
expect(result).toBeTruthy();
|
|
84
|
+
expect(typeof result).toBe("string");
|
|
85
|
+
expect(result.length).toBeGreaterThan(0);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test.skipIf(!hasLoam)("passes domain args when provided", async () => {
|
|
89
|
+
await initLoam();
|
|
90
|
+
// Add a domain first so we can prime it
|
|
91
|
+
const addProc = Bun.spawn(["lm", "add", "architecture"], {
|
|
92
|
+
cwd: tempDir,
|
|
93
|
+
stdout: "pipe",
|
|
94
|
+
stderr: "pipe",
|
|
95
|
+
});
|
|
96
|
+
await addProc.exited;
|
|
97
|
+
|
|
98
|
+
const client = createLoamClient(tempDir);
|
|
99
|
+
const result = await client.prime(["architecture"]);
|
|
100
|
+
expect(typeof result).toBe("string");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test.skipIf(!hasLoam)("passes --format flag", async () => {
|
|
104
|
+
await initLoam();
|
|
105
|
+
const client = createLoamClient(tempDir);
|
|
106
|
+
const result = await client.prime([], "markdown");
|
|
107
|
+
expect(typeof result).toBe("string");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test.skipIf(!hasLoam)("passes both domains and format", async () => {
|
|
111
|
+
await initLoam();
|
|
112
|
+
const addProc = Bun.spawn(["lm", "add", "architecture"], {
|
|
113
|
+
cwd: tempDir,
|
|
114
|
+
stdout: "pipe",
|
|
115
|
+
stderr: "pipe",
|
|
116
|
+
});
|
|
117
|
+
await addProc.exited;
|
|
118
|
+
|
|
119
|
+
const client = createLoamClient(tempDir);
|
|
120
|
+
const result = await client.prime(["architecture"], "xml");
|
|
121
|
+
expect(typeof result).toBe("string");
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test.skipIf(!hasLoam)("passes --files flag", async () => {
|
|
125
|
+
await initLoam();
|
|
126
|
+
const client = createLoamClient(tempDir);
|
|
127
|
+
const result = await client.prime([], "markdown", {
|
|
128
|
+
files: ["src/config.ts", "src/types.ts"],
|
|
129
|
+
});
|
|
130
|
+
expect(typeof result).toBe("string");
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test.skipIf(!hasLoam)("passes --exclude-domain flag", async () => {
|
|
134
|
+
await initLoam();
|
|
135
|
+
const addProc = Bun.spawn(["lm", "add", "architecture"], {
|
|
136
|
+
cwd: tempDir,
|
|
137
|
+
stdout: "pipe",
|
|
138
|
+
stderr: "pipe",
|
|
139
|
+
});
|
|
140
|
+
await addProc.exited;
|
|
141
|
+
|
|
142
|
+
const client = createLoamClient(tempDir);
|
|
143
|
+
const result = await client.prime([], "markdown", {
|
|
144
|
+
excludeDomain: ["architecture"],
|
|
145
|
+
});
|
|
146
|
+
expect(typeof result).toBe("string");
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test.skipIf(!hasLoam)("passes both --files and --exclude-domain", async () => {
|
|
150
|
+
await initLoam();
|
|
151
|
+
// Add a domain to exclude
|
|
152
|
+
const addProc = Bun.spawn(["lm", "add", "internal"], {
|
|
153
|
+
cwd: tempDir,
|
|
154
|
+
stdout: "pipe",
|
|
155
|
+
stderr: "pipe",
|
|
156
|
+
});
|
|
157
|
+
await addProc.exited;
|
|
158
|
+
|
|
159
|
+
const client = createLoamClient(tempDir);
|
|
160
|
+
const result = await client.prime([], "markdown", {
|
|
161
|
+
files: ["src/config.ts"],
|
|
162
|
+
excludeDomain: ["internal"],
|
|
163
|
+
});
|
|
164
|
+
expect(typeof result).toBe("string");
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test.skipIf(!hasLoam)("passes --sort-by-score flag in prime options", async () => {
|
|
168
|
+
await initLoam();
|
|
169
|
+
const client = createLoamClient(tempDir);
|
|
170
|
+
// loam prime --sort-by-score may not be supported in older loam versions;
|
|
171
|
+
// the interface and impl are forward-looking — test accepts both outcomes.
|
|
172
|
+
try {
|
|
173
|
+
const result = await client.prime([], "markdown", { sortByScore: true });
|
|
174
|
+
expect(typeof result).toBe("string");
|
|
175
|
+
} catch (error) {
|
|
176
|
+
expect(error).toBeInstanceOf(AgentError);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test.skipIf(!hasLoam)("passes --sort-by-score with --files together", async () => {
|
|
181
|
+
await initLoam();
|
|
182
|
+
const client = createLoamClient(tempDir);
|
|
183
|
+
try {
|
|
184
|
+
const result = await client.prime([], "markdown", {
|
|
185
|
+
files: ["src/config.ts"],
|
|
186
|
+
sortByScore: true,
|
|
187
|
+
});
|
|
188
|
+
expect(typeof result).toBe("string");
|
|
189
|
+
} catch (error) {
|
|
190
|
+
expect(error).toBeInstanceOf(AgentError);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
describe("status", () => {
|
|
196
|
+
test.skipIf(!hasLoam)("returns LoamStatus shape", async () => {
|
|
197
|
+
await initLoam();
|
|
198
|
+
const client = createLoamClient(tempDir);
|
|
199
|
+
const result = await client.status();
|
|
200
|
+
expect(result).toHaveProperty("domains");
|
|
201
|
+
expect(Array.isArray(result.domains)).toBe(true);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test.skipIf(!hasLoam)("with no domains returns empty array", async () => {
|
|
205
|
+
await initLoam();
|
|
206
|
+
const client = createLoamClient(tempDir);
|
|
207
|
+
const result = await client.status();
|
|
208
|
+
expect(result.domains).toEqual([]);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test.skipIf(!hasLoam)("includes domain data when domains exist", async () => {
|
|
212
|
+
await initLoam();
|
|
213
|
+
// Add a domain
|
|
214
|
+
const addProc = Bun.spawn(["lm", "add", "architecture"], {
|
|
215
|
+
cwd: tempDir,
|
|
216
|
+
stdout: "pipe",
|
|
217
|
+
stderr: "pipe",
|
|
218
|
+
});
|
|
219
|
+
await addProc.exited;
|
|
220
|
+
|
|
221
|
+
const client = createLoamClient(tempDir);
|
|
222
|
+
const result = await client.status();
|
|
223
|
+
expect(result.domains.length).toBeGreaterThan(0);
|
|
224
|
+
// Just verify we got an array with entries, don't check specific structure
|
|
225
|
+
// as loam CLI output format may vary
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
describe("record", () => {
|
|
230
|
+
test.skipIf(!hasLoam)("with required args succeeds", async () => {
|
|
231
|
+
await initLoam();
|
|
232
|
+
// Add domain first
|
|
233
|
+
const addProc = Bun.spawn(["lm", "add", "architecture"], {
|
|
234
|
+
cwd: tempDir,
|
|
235
|
+
stdout: "pipe",
|
|
236
|
+
stderr: "pipe",
|
|
237
|
+
});
|
|
238
|
+
await addProc.exited;
|
|
239
|
+
|
|
240
|
+
const client = createLoamClient(tempDir);
|
|
241
|
+
await expect(
|
|
242
|
+
client.record("architecture", {
|
|
243
|
+
type: "convention",
|
|
244
|
+
description: "test convention",
|
|
245
|
+
}),
|
|
246
|
+
).resolves.toBeUndefined();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test.skipIf(!hasLoam)("with optional args succeeds", async () => {
|
|
250
|
+
await initLoam();
|
|
251
|
+
const addProc = Bun.spawn(["lm", "add", "architecture"], {
|
|
252
|
+
cwd: tempDir,
|
|
253
|
+
stdout: "pipe",
|
|
254
|
+
stderr: "pipe",
|
|
255
|
+
});
|
|
256
|
+
await addProc.exited;
|
|
257
|
+
|
|
258
|
+
const client = createLoamClient(tempDir);
|
|
259
|
+
await expect(
|
|
260
|
+
client.record("architecture", {
|
|
261
|
+
type: "pattern",
|
|
262
|
+
name: "test-pattern",
|
|
263
|
+
description: "test description",
|
|
264
|
+
title: "Test Pattern",
|
|
265
|
+
rationale: "testing all options",
|
|
266
|
+
tags: ["testing", "example"],
|
|
267
|
+
}),
|
|
268
|
+
).resolves.toBeUndefined();
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
test.skipIf(!hasLoam)("with multiple tags", async () => {
|
|
272
|
+
await initLoam();
|
|
273
|
+
const addProc = Bun.spawn(["lm", "add", "typescript"], {
|
|
274
|
+
cwd: tempDir,
|
|
275
|
+
stdout: "pipe",
|
|
276
|
+
stderr: "pipe",
|
|
277
|
+
});
|
|
278
|
+
await addProc.exited;
|
|
279
|
+
|
|
280
|
+
const client = createLoamClient(tempDir);
|
|
281
|
+
await expect(
|
|
282
|
+
client.record("typescript", {
|
|
283
|
+
type: "convention",
|
|
284
|
+
description: "multi-tag test",
|
|
285
|
+
tags: ["tag1", "tag2", "tag3"],
|
|
286
|
+
}),
|
|
287
|
+
).resolves.toBeUndefined();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
test.skipIf(!hasLoam)("with --stdin flag passes flag to CLI", async () => {
|
|
291
|
+
await initLoam();
|
|
292
|
+
const addProc = Bun.spawn(["lm", "add", "testing"], {
|
|
293
|
+
cwd: tempDir,
|
|
294
|
+
stdout: "pipe",
|
|
295
|
+
stderr: "pipe",
|
|
296
|
+
});
|
|
297
|
+
await addProc.exited;
|
|
298
|
+
|
|
299
|
+
const client = createLoamClient(tempDir);
|
|
300
|
+
// --stdin expects JSON input, which we're not providing, so this will fail
|
|
301
|
+
// but we're testing that the flag is passed correctly
|
|
302
|
+
await expect(
|
|
303
|
+
client.record("testing", {
|
|
304
|
+
type: "convention",
|
|
305
|
+
description: "stdin test",
|
|
306
|
+
stdin: true,
|
|
307
|
+
}),
|
|
308
|
+
).rejects.toThrow(AgentError);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test.skipIf(!hasLoam)("with outcome flags passes them to CLI", async () => {
|
|
312
|
+
await initLoam();
|
|
313
|
+
const addProc = Bun.spawn(["lm", "add", "testing"], {
|
|
314
|
+
cwd: tempDir,
|
|
315
|
+
stdout: "pipe",
|
|
316
|
+
stderr: "pipe",
|
|
317
|
+
});
|
|
318
|
+
await addProc.exited;
|
|
319
|
+
|
|
320
|
+
const client = createLoamClient(tempDir);
|
|
321
|
+
// May succeed or fail depending on loam version, but verifies flags are passed
|
|
322
|
+
try {
|
|
323
|
+
await client.record("testing", {
|
|
324
|
+
type: "convention",
|
|
325
|
+
description: "outcome test",
|
|
326
|
+
outcomeStatus: "success",
|
|
327
|
+
outcomeDuration: 42,
|
|
328
|
+
outcomeTestResults: "15 passed",
|
|
329
|
+
outcomeAgent: "test-agent",
|
|
330
|
+
});
|
|
331
|
+
expect(true).toBe(true);
|
|
332
|
+
} catch (error) {
|
|
333
|
+
expect(error).toBeInstanceOf(AgentError);
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
test.skipIf(!hasLoam)("with outcomeStatus: failure passes flag to CLI", async () => {
|
|
338
|
+
await initLoam();
|
|
339
|
+
const addProc = Bun.spawn(["lm", "add", "testing"], {
|
|
340
|
+
cwd: tempDir,
|
|
341
|
+
stdout: "pipe",
|
|
342
|
+
stderr: "pipe",
|
|
343
|
+
});
|
|
344
|
+
await addProc.exited;
|
|
345
|
+
|
|
346
|
+
const client = createLoamClient(tempDir);
|
|
347
|
+
try {
|
|
348
|
+
await client.record("testing", {
|
|
349
|
+
type: "failure",
|
|
350
|
+
description: "failure outcome test",
|
|
351
|
+
outcomeStatus: "failure",
|
|
352
|
+
});
|
|
353
|
+
expect(true).toBe(true);
|
|
354
|
+
} catch (error) {
|
|
355
|
+
expect(error).toBeInstanceOf(AgentError);
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
test.skipIf(!hasLoam)("with outcomeDuration: 0 passes zero value to CLI", async () => {
|
|
360
|
+
await initLoam();
|
|
361
|
+
const addProc = Bun.spawn(["lm", "add", "testing"], {
|
|
362
|
+
cwd: tempDir,
|
|
363
|
+
stdout: "pipe",
|
|
364
|
+
stderr: "pipe",
|
|
365
|
+
});
|
|
366
|
+
await addProc.exited;
|
|
367
|
+
|
|
368
|
+
const client = createLoamClient(tempDir);
|
|
369
|
+
try {
|
|
370
|
+
await client.record("testing", {
|
|
371
|
+
type: "convention",
|
|
372
|
+
description: "zero duration test",
|
|
373
|
+
outcomeDuration: 0,
|
|
374
|
+
});
|
|
375
|
+
expect(true).toBe(true);
|
|
376
|
+
} catch (error) {
|
|
377
|
+
expect(error).toBeInstanceOf(AgentError);
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
test.skipIf(!hasLoam)("with --evidence-bead flag passes flag to CLI", async () => {
|
|
382
|
+
await initLoam();
|
|
383
|
+
const addProc = Bun.spawn(["lm", "add", "testing"], {
|
|
384
|
+
cwd: tempDir,
|
|
385
|
+
stdout: "pipe",
|
|
386
|
+
stderr: "pipe",
|
|
387
|
+
});
|
|
388
|
+
await addProc.exited;
|
|
389
|
+
|
|
390
|
+
const client = createLoamClient(tempDir);
|
|
391
|
+
// The flag is passed correctly, but may fail if the task ID is invalid
|
|
392
|
+
// or if other required fields are missing. This test documents that the
|
|
393
|
+
// flag is properly passed to the CLI.
|
|
394
|
+
try {
|
|
395
|
+
await client.record("testing", {
|
|
396
|
+
type: "decision",
|
|
397
|
+
description: "bead evidence test",
|
|
398
|
+
evidenceBead: "beads-abc123",
|
|
399
|
+
});
|
|
400
|
+
// If it succeeds, great!
|
|
401
|
+
expect(true).toBe(true);
|
|
402
|
+
} catch (error) {
|
|
403
|
+
// If it fails, verify it's an AgentError (not a type error or similar)
|
|
404
|
+
// which proves the command was executed with the flag
|
|
405
|
+
expect(error).toBeInstanceOf(AgentError);
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
describe("query", () => {
|
|
411
|
+
test.skipIf(!hasLoam)("passes domain arg when provided", async () => {
|
|
412
|
+
await initLoam();
|
|
413
|
+
const addProc = Bun.spawn(["lm", "add", "architecture"], {
|
|
414
|
+
cwd: tempDir,
|
|
415
|
+
stdout: "pipe",
|
|
416
|
+
stderr: "pipe",
|
|
417
|
+
});
|
|
418
|
+
await addProc.exited;
|
|
419
|
+
|
|
420
|
+
const client = createLoamClient(tempDir);
|
|
421
|
+
const result = await client.query("architecture");
|
|
422
|
+
expect(typeof result).toBe("string");
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
test.skipIf(!hasLoam)("query without domain requires --all flag", async () => {
|
|
426
|
+
await initLoam();
|
|
427
|
+
const client = createLoamClient(tempDir);
|
|
428
|
+
// Current implementation doesn't pass --all, so this will fail
|
|
429
|
+
// This documents the current behavior
|
|
430
|
+
await expect(client.query()).rejects.toThrow(AgentError);
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
describe("search", () => {
|
|
435
|
+
test.skipIf(!hasLoam)("returns string output", async () => {
|
|
436
|
+
await initLoam();
|
|
437
|
+
const client = createLoamClient(tempDir);
|
|
438
|
+
const result = await client.search("test");
|
|
439
|
+
expect(typeof result).toBe("string");
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
test.skipIf(!hasLoam)("searches across domains", async () => {
|
|
443
|
+
await initLoam();
|
|
444
|
+
// Add a domain and record
|
|
445
|
+
const addProc = Bun.spawn(["lm", "add", "testing"], {
|
|
446
|
+
cwd: tempDir,
|
|
447
|
+
stdout: "pipe",
|
|
448
|
+
stderr: "pipe",
|
|
449
|
+
});
|
|
450
|
+
await addProc.exited;
|
|
451
|
+
|
|
452
|
+
const client = createLoamClient(tempDir);
|
|
453
|
+
await client.record("testing", {
|
|
454
|
+
type: "convention",
|
|
455
|
+
description: "searchable keyword here",
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
const result = await client.search("searchable");
|
|
459
|
+
expect(typeof result).toBe("string");
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
test.skipIf(!hasLoam)("passes --file flag when provided", async () => {
|
|
463
|
+
await initLoam();
|
|
464
|
+
const client = createLoamClient(tempDir);
|
|
465
|
+
const result = await client.search("test", { file: "src/config.ts" });
|
|
466
|
+
expect(typeof result).toBe("string");
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
test.skipIf(!hasLoam)("passes --sort-by-score flag when provided", async () => {
|
|
470
|
+
await initLoam();
|
|
471
|
+
const client = createLoamClient(tempDir);
|
|
472
|
+
const result = await client.search("test", { sortByScore: true });
|
|
473
|
+
expect(typeof result).toBe("string");
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
test.skipIf(!hasLoam)("passes both --file and --sort-by-score flags", async () => {
|
|
477
|
+
await initLoam();
|
|
478
|
+
const client = createLoamClient(tempDir);
|
|
479
|
+
const result = await client.search("test", { file: "src/config.ts", sortByScore: true });
|
|
480
|
+
expect(typeof result).toBe("string");
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
test.skipIf(!hasLoam)("passes --classification flag when provided", async () => {
|
|
484
|
+
await initLoam();
|
|
485
|
+
const client = createLoamClient(tempDir);
|
|
486
|
+
const result = await client.search("test", { classification: "foundational" });
|
|
487
|
+
expect(typeof result).toBe("string");
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
test.skipIf(!hasLoam)("passes --outcome-status flag when provided (success)", async () => {
|
|
491
|
+
await initLoam();
|
|
492
|
+
const client = createLoamClient(tempDir);
|
|
493
|
+
const result = await client.search("test", { outcomeStatus: "success" });
|
|
494
|
+
expect(typeof result).toBe("string");
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
test.skipIf(!hasLoam)("passes --outcome-status flag when provided (failure)", async () => {
|
|
498
|
+
await initLoam();
|
|
499
|
+
const client = createLoamClient(tempDir);
|
|
500
|
+
const result = await client.search("test", { outcomeStatus: "failure" });
|
|
501
|
+
expect(typeof result).toBe("string");
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
test.skipIf(!hasLoam)("passes all search filters together", async () => {
|
|
505
|
+
await initLoam();
|
|
506
|
+
const client = createLoamClient(tempDir);
|
|
507
|
+
const result = await client.search("test", {
|
|
508
|
+
classification: "tactical",
|
|
509
|
+
outcomeStatus: "success",
|
|
510
|
+
sortByScore: true,
|
|
511
|
+
file: "src/config.ts",
|
|
512
|
+
});
|
|
513
|
+
expect(typeof result).toBe("string");
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
test.skipIf(!hasLoam)("roundtrip: record via API then search and find it", async () => {
|
|
517
|
+
await initLoam();
|
|
518
|
+
const addProc = Bun.spawn(["lm", "add", "roundtrip"], {
|
|
519
|
+
cwd: tempDir,
|
|
520
|
+
stdout: "pipe",
|
|
521
|
+
stderr: "pipe",
|
|
522
|
+
});
|
|
523
|
+
await addProc.exited;
|
|
524
|
+
|
|
525
|
+
const client = createLoamClient(tempDir);
|
|
526
|
+
await client.record("roundtrip", {
|
|
527
|
+
type: "convention",
|
|
528
|
+
description: "unique-roundtrip-marker-xyz",
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
const result = await client.search("unique-roundtrip-marker-xyz");
|
|
532
|
+
expect(typeof result).toBe("string");
|
|
533
|
+
expect(result).toContain("unique-roundtrip-marker-xyz");
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
describe("diff", () => {
|
|
538
|
+
test.skipIf(!hasLoam)("shows expertise changes", async () => {
|
|
539
|
+
await initGit();
|
|
540
|
+
await initLoam();
|
|
541
|
+
const client = createLoamClient(tempDir);
|
|
542
|
+
const result = await client.diff();
|
|
543
|
+
expect(result).toHaveProperty("success");
|
|
544
|
+
expect(result).toHaveProperty("command");
|
|
545
|
+
expect(result).toHaveProperty("domains");
|
|
546
|
+
expect(Array.isArray(result.domains)).toBe(true);
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
test.skipIf(!hasLoam)("passes --since flag", async () => {
|
|
550
|
+
await initGit();
|
|
551
|
+
await initLoam();
|
|
552
|
+
const client = createLoamClient(tempDir);
|
|
553
|
+
const result = await client.diff({ since: "HEAD~5" });
|
|
554
|
+
expect(result).toHaveProperty("success");
|
|
555
|
+
expect(result).toHaveProperty("since");
|
|
556
|
+
});
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
describe("learn", () => {
|
|
560
|
+
test.skipIf(!hasLoam)("suggests domains for learnings", async () => {
|
|
561
|
+
await initGit();
|
|
562
|
+
await initLoam();
|
|
563
|
+
const client = createLoamClient(tempDir);
|
|
564
|
+
const result = await client.learn();
|
|
565
|
+
expect(result).toHaveProperty("success");
|
|
566
|
+
expect(result).toHaveProperty("command");
|
|
567
|
+
expect(result).toHaveProperty("changedFiles");
|
|
568
|
+
expect(Array.isArray(result.changedFiles)).toBe(true);
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
test.skipIf(!hasLoam)("passes --since flag", async () => {
|
|
572
|
+
await initGit();
|
|
573
|
+
await initLoam();
|
|
574
|
+
const client = createLoamClient(tempDir);
|
|
575
|
+
const result = await client.learn({ since: "HEAD~3" });
|
|
576
|
+
expect(result).toHaveProperty("success");
|
|
577
|
+
expect(result).toHaveProperty("changedFiles");
|
|
578
|
+
});
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
describe("prune", () => {
|
|
582
|
+
test.skipIf(!hasLoam)("prunes records", async () => {
|
|
583
|
+
await initLoam();
|
|
584
|
+
const client = createLoamClient(tempDir);
|
|
585
|
+
const result = await client.prune();
|
|
586
|
+
expect(result).toHaveProperty("success");
|
|
587
|
+
expect(result).toHaveProperty("command");
|
|
588
|
+
expect(result).toHaveProperty("totalPruned");
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
test.skipIf(!hasLoam)("supports --dry-run flag", async () => {
|
|
592
|
+
await initLoam();
|
|
593
|
+
const client = createLoamClient(tempDir);
|
|
594
|
+
const result = await client.prune({ dryRun: true });
|
|
595
|
+
expect(result).toHaveProperty("success");
|
|
596
|
+
expect(result).toHaveProperty("dryRun");
|
|
597
|
+
expect(result.dryRun).toBe(true);
|
|
598
|
+
});
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
describe("doctor", () => {
|
|
602
|
+
test.skipIf(!hasLoam)("runs health checks", async () => {
|
|
603
|
+
await initLoam();
|
|
604
|
+
const client = createLoamClient(tempDir);
|
|
605
|
+
const result = await client.doctor();
|
|
606
|
+
expect(result).toHaveProperty("success");
|
|
607
|
+
expect(result).toHaveProperty("command");
|
|
608
|
+
expect(result).toHaveProperty("checks");
|
|
609
|
+
expect(Array.isArray(result.checks)).toBe(true);
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
test.skipIf(!hasLoam)("passes --fix flag", async () => {
|
|
613
|
+
await initLoam();
|
|
614
|
+
const client = createLoamClient(tempDir);
|
|
615
|
+
const result = await client.doctor({ fix: true });
|
|
616
|
+
expect(result).toHaveProperty("success");
|
|
617
|
+
expect(result).toHaveProperty("checks");
|
|
618
|
+
});
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
describe("ready", () => {
|
|
622
|
+
test.skipIf(!hasLoam)("shows recently updated records", async () => {
|
|
623
|
+
await initLoam();
|
|
624
|
+
const client = createLoamClient(tempDir);
|
|
625
|
+
const result = await client.ready();
|
|
626
|
+
expect(result).toHaveProperty("success");
|
|
627
|
+
expect(result).toHaveProperty("command");
|
|
628
|
+
expect(result).toHaveProperty("entries");
|
|
629
|
+
expect(Array.isArray(result.entries)).toBe(true);
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
test.skipIf(!hasLoam)("passes --limit flag", async () => {
|
|
633
|
+
await initLoam();
|
|
634
|
+
const client = createLoamClient(tempDir);
|
|
635
|
+
const result = await client.ready({ limit: 5 });
|
|
636
|
+
expect(result).toHaveProperty("success");
|
|
637
|
+
expect(result).toHaveProperty("count");
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
test.skipIf(!hasLoam)("passes --domain flag", async () => {
|
|
641
|
+
await initLoam();
|
|
642
|
+
const addProc = Bun.spawn(["lm", "add", "testing"], {
|
|
643
|
+
cwd: tempDir,
|
|
644
|
+
stdout: "pipe",
|
|
645
|
+
stderr: "pipe",
|
|
646
|
+
});
|
|
647
|
+
await addProc.exited;
|
|
648
|
+
|
|
649
|
+
const client = createLoamClient(tempDir);
|
|
650
|
+
const result = await client.ready({ domain: "testing" });
|
|
651
|
+
expect(result).toHaveProperty("success");
|
|
652
|
+
expect(result).toHaveProperty("entries");
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
test.skipIf(!hasLoam)("passes --since flag", async () => {
|
|
656
|
+
await initLoam();
|
|
657
|
+
const client = createLoamClient(tempDir);
|
|
658
|
+
const result = await client.ready({ since: "7d" });
|
|
659
|
+
expect(result).toHaveProperty("success");
|
|
660
|
+
expect(result).toHaveProperty("entries");
|
|
661
|
+
});
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
describe("compact", () => {
|
|
665
|
+
test.skipIf(!hasLoam)("runs with --analyze flag", async () => {
|
|
666
|
+
await initLoam();
|
|
667
|
+
const client = createLoamClient(tempDir);
|
|
668
|
+
const result = await client.compact(undefined, { analyze: true });
|
|
669
|
+
expect(result).toHaveProperty("success");
|
|
670
|
+
expect(result).toHaveProperty("command");
|
|
671
|
+
expect(result).toHaveProperty("action");
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
test.skipIf(!hasLoam)("compacts specific domain with --analyze", async () => {
|
|
675
|
+
await initLoam();
|
|
676
|
+
const addProc = Bun.spawn(["lm", "add", "large"], {
|
|
677
|
+
cwd: tempDir,
|
|
678
|
+
stdout: "pipe",
|
|
679
|
+
stderr: "pipe",
|
|
680
|
+
});
|
|
681
|
+
await addProc.exited;
|
|
682
|
+
|
|
683
|
+
const client = createLoamClient(tempDir);
|
|
684
|
+
const result = await client.compact("large", { analyze: true });
|
|
685
|
+
expect(result).toHaveProperty("success");
|
|
686
|
+
expect(result).toHaveProperty("action");
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
test.skipIf(!hasLoam)("passes --auto with --dry-run flags", async () => {
|
|
690
|
+
await initLoam();
|
|
691
|
+
const client = createLoamClient(tempDir);
|
|
692
|
+
const result = await client.compact(undefined, { auto: true, dryRun: true });
|
|
693
|
+
expect(result).toHaveProperty("success");
|
|
694
|
+
expect(result).toHaveProperty("command");
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
test.skipIf(!hasLoam)("passes multiple options", async () => {
|
|
698
|
+
await initLoam();
|
|
699
|
+
const client = createLoamClient(tempDir);
|
|
700
|
+
const result = await client.compact(undefined, {
|
|
701
|
+
auto: true,
|
|
702
|
+
dryRun: true,
|
|
703
|
+
minGroup: 3,
|
|
704
|
+
maxRecords: 20,
|
|
705
|
+
});
|
|
706
|
+
expect(result).toHaveProperty("success");
|
|
707
|
+
expect(result).toHaveProperty("command");
|
|
708
|
+
});
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
describe("error handling", () => {
|
|
712
|
+
test.skipIf(!hasLoam)("throws AgentError when loam command fails", async () => {
|
|
713
|
+
// Don't init loam - operations will fail with "not initialized" error
|
|
714
|
+
const client = createLoamClient(tempDir);
|
|
715
|
+
await expect(client.status()).rejects.toThrow(AgentError);
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
test.skipIf(!hasLoam)("AgentError message contains exit code", async () => {
|
|
719
|
+
const client = createLoamClient(tempDir);
|
|
720
|
+
try {
|
|
721
|
+
await client.status();
|
|
722
|
+
expect.unreachable("Should have thrown AgentError");
|
|
723
|
+
} catch (error) {
|
|
724
|
+
expect(error).toBeInstanceOf(AgentError);
|
|
725
|
+
const agentError = error as AgentError;
|
|
726
|
+
expect(agentError.message).toContain("exit");
|
|
727
|
+
expect(agentError.message).toContain("status");
|
|
728
|
+
}
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
test.skipIf(!hasLoam)("record auto-creates missing domain", async () => {
|
|
732
|
+
await initLoam();
|
|
733
|
+
const client = createLoamClient(tempDir);
|
|
734
|
+
// loam 0.6.1+ auto-creates missing domains instead of erroring
|
|
735
|
+
await expect(
|
|
736
|
+
client.record("nonexistent-domain", {
|
|
737
|
+
type: "convention",
|
|
738
|
+
description: "test",
|
|
739
|
+
}),
|
|
740
|
+
).resolves.toBeUndefined();
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
test.skipIf(!hasLoam)("handles empty status output correctly", async () => {
|
|
744
|
+
await initLoam();
|
|
745
|
+
const client = createLoamClient(tempDir);
|
|
746
|
+
const result = await client.status();
|
|
747
|
+
// With no domains, should have empty array (not throw)
|
|
748
|
+
expect(result).toHaveProperty("domains");
|
|
749
|
+
expect(result.domains).toEqual([]);
|
|
750
|
+
});
|
|
751
|
+
});
|
|
752
|
+
});
|