akm-cli 0.9.0-rc.8 → 0.9.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/CHANGELOG.md +1063 -44
- package/README.md +51 -25
- package/SECURITY.md +14 -1
- package/STABILITY.md +497 -0
- package/dist/akm +148 -35
- package/dist/{akm-migrate-storage → akm-migrate} +6 -9
- package/dist/assets/hints/cli-hints-full.md +223 -95
- package/dist/assets/hints/cli-hints-short.md +85 -22
- package/dist/assets/improve-strategies/default.json +1 -1
- package/dist/assets/improve-strategies/reflect-distill.json +1 -1
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/stash-skeleton/README.md +6 -5
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +20 -9
- package/dist/assets/tasks/core/extract.yml +1 -1
- package/dist/assets/tasks/core/version-check.yml +1 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
- package/dist/assets/templates/html/health.html +1 -3
- package/dist/assets/workflows/workflow-template.md +32 -15
- package/dist/cli/invocation.js +40 -15
- package/dist/cli/parse-args.js +0 -22
- package/dist/cli/retired-commands.js +121 -0
- package/dist/cli/shared.js +154 -22
- package/dist/cli/unknown-flags.js +236 -0
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +696 -258
- package/dist/commands/agent/agent-dispatch.js +14 -3
- package/dist/commands/agent/contribute-cli.js +73 -88
- package/dist/commands/completions.js +79 -22
- package/dist/commands/config-cli.js +17 -150
- package/dist/commands/env/env-cli.js +59 -143
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +36 -66
- package/dist/commands/env/secret.js +24 -57
- package/dist/commands/feedback-cli.js +141 -87
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +3 -4
- package/dist/commands/health/checks.js +85 -23
- package/dist/commands/health/html-report.js +7 -10
- package/dist/commands/health/improve-metrics.js +25 -83
- package/dist/commands/health/md-report.js +5 -9
- package/dist/commands/health/metrics.js +62 -20
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +4 -5
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +3 -48
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/commands/health/types-improve.js +7 -0
- package/dist/commands/health.js +99 -28
- package/dist/commands/improve/anti-collapse.js +2 -2
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +41 -40
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +140 -1000
- package/dist/commands/improve/distill/promote-memory.js +12 -12
- package/dist/commands/improve/distill/quality-gate.js +6 -6
- package/dist/commands/improve/distill.js +58 -69
- package/dist/commands/improve/eligibility.js +105 -57
- package/dist/commands/improve/extract-cli.js +14 -133
- package/dist/commands/improve/improve-cli.js +98 -114
- package/dist/commands/improve/improve-result-file.js +1 -28
- package/dist/commands/improve/improve-strategies.js +8 -5
- package/dist/commands/improve/improve.js +128 -91
- package/dist/commands/improve/loop-stages.js +182 -20
- package/dist/commands/improve/memory/derived-ref.js +45 -43
- package/dist/commands/improve/memory/memory-belief.js +1 -1
- package/dist/commands/improve/memory/memory-contradiction-detect.js +4 -12
- package/dist/commands/improve/memory/memory-improve.js +6 -5
- package/dist/commands/improve/outcome-loop.js +22 -65
- package/dist/commands/improve/preparation.js +114 -123
- package/dist/commands/improve/proactive-maintenance.js +2 -5
- package/dist/commands/improve/reflect.js +56 -160
- package/dist/commands/improve/salience.js +11 -122
- package/dist/commands/improve/source-identity.js +10 -38
- package/dist/commands/lint/base-linter.js +20 -124
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +249 -43
- package/dist/commands/{events.js → log.js} +33 -38
- package/dist/commands/migrate-cli.js +92 -12
- package/dist/commands/migration-tool.js +46 -0
- package/dist/commands/observability-cli.js +70 -209
- package/dist/commands/proposal/drain.js +101 -29
- package/dist/commands/proposal/proposal-cli.js +76 -48
- package/dist/commands/proposal/proposal.js +54 -18
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +23 -15
- package/dist/commands/proposal/repository.js +701 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +2 -8
- package/dist/commands/proposal/validators/proposal-validators.js +55 -7
- package/dist/commands/proposal/validators/proposals.js +4 -7
- package/dist/commands/read/curate.js +34 -53
- package/dist/commands/read/knowledge.js +150 -95
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +42 -15
- package/dist/commands/read/search-cli.js +180 -78
- package/dist/commands/read/search.js +58 -43
- package/dist/commands/read/show.js +197 -141
- package/dist/commands/registry-cli.js +12 -51
- package/dist/commands/remember.js +14 -57
- package/dist/commands/sources/add-cli.js +100 -31
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +7 -2
- package/dist/commands/sources/info.js +18 -5
- package/dist/commands/sources/init.js +12 -12
- package/dist/commands/sources/installed-stashes.js +382 -98
- package/dist/commands/sources/schema-repair.js +3 -2
- package/dist/commands/sources/self-update.js +131 -38
- package/dist/commands/sources/source-add.js +72 -17
- package/dist/commands/sources/source-clone.js +129 -45
- package/dist/commands/sources/source-manage.js +43 -23
- package/dist/commands/sources/sources-cli.js +57 -208
- package/dist/commands/sources/stash-cli.js +46 -53
- package/dist/commands/tasks/tasks-cli.js +91 -97
- package/dist/commands/tasks/tasks.js +276 -421
- package/dist/commands/workflow-cli.js +175 -450
- package/dist/core/adapter/adapters/akm-adapter.js +47 -28
- package/dist/core/adapter/adapters/akm-lint.js +42 -27
- package/dist/core/adapter/adapters/akm-metadata.js +15 -44
- package/dist/core/adapter/adapters/akm-task-adapter.js +15 -13
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +55 -71
- package/dist/core/adapter/adapters/dotenv-adapter.js +1 -1
- package/dist/core/adapter/adapters/generic-files-adapter.js +2 -0
- package/dist/core/adapter/adapters/index.js +6 -6
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +14 -8
- package/dist/core/adapter/adapters/okf-adapter.js +187 -19
- package/dist/core/adapter/adapters/shared.js +3 -19
- package/dist/core/adapter/adapters/tool-dir-shared.js +8 -3
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +1 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +6 -4
- package/dist/core/adapter/validate-context.js +214 -0
- package/dist/core/asset/akm-markdown.js +63 -0
- package/dist/core/asset/asset-placement.js +20 -6
- package/dist/core/asset/asset-ref.js +11 -9
- package/dist/core/asset/frontmatter-lint.js +30 -0
- package/dist/core/asset/frontmatter.js +37 -9
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +89 -18
- package/dist/core/asset/stash-meta.js +1 -1
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +152 -38
- package/dist/core/config/config-io.js +12 -1
- package/dist/core/config/config-schema.js +35 -8
- package/dist/core/config/config-sources.js +55 -11
- package/dist/core/config/config-walker.js +25 -9
- package/dist/core/config/config.js +9 -48
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +5 -1
- package/dist/core/config/schema/experimental.js +30 -0
- package/dist/core/config/schema/improve-processes.js +0 -6
- package/dist/core/config/schema/improve.js +21 -3
- package/dist/core/config/schema/index-config.js +8 -15
- package/dist/core/config/schema/output.js +4 -1
- package/dist/core/config/schema/setup.js +9 -18
- package/dist/core/config/schema/sources-bundles.js +49 -33
- package/dist/core/config/schema/workflow.js +3 -3
- package/dist/core/env-secret-ref.js +76 -46
- package/dist/core/errors.js +18 -12
- package/dist/core/events.js +46 -128
- package/dist/core/file-change.js +6 -5
- package/dist/core/fs-txn.js +83 -7
- package/dist/core/git-message.js +2 -2
- package/dist/core/improve-result.js +1 -100
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +2 -1
- package/dist/core/migration-operation.js +16 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/parse.js +4 -1
- package/dist/core/paths.js +17 -20
- package/dist/core/recognition-util.js +12 -14
- package/dist/core/redaction.js +34 -0
- package/dist/core/standards/resolve-standards-context.js +2 -14
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +2 -2
- package/dist/core/state/migrations.js +41 -18
- package/dist/core/state-db.js +5 -14
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +6 -4
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/type-presentation.js +3 -3
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +771 -95
- package/dist/indexer/bundle-identity-guard.js +3 -2
- package/dist/indexer/db/graph-db.js +0 -24
- package/dist/indexer/ensure-index.js +1 -0
- package/dist/indexer/graph/graph-boost.js +9 -34
- package/dist/indexer/graph/graph-extraction.js +8 -5
- package/dist/indexer/index-writer-lock.js +53 -17
- package/dist/indexer/index-written-assets.js +16 -22
- package/dist/indexer/indexer.js +497 -239
- package/dist/indexer/installations.js +14 -96
- package/dist/indexer/passes/dir-staleness.js +16 -9
- package/dist/indexer/passes/memory-inference.js +11 -9
- package/dist/indexer/passes/metadata.js +113 -47
- package/dist/indexer/scan/doc-to-entry.js +38 -1
- package/dist/indexer/scan/drain-dir.js +13 -23
- package/dist/indexer/search/db-search.js +99 -54
- package/dist/indexer/search/fts-query.js +47 -24
- package/dist/indexer/search/ranking-contributors.js +42 -20
- package/dist/indexer/search/ranking.js +18 -99
- package/dist/indexer/search/search-fields.js +7 -2
- package/dist/indexer/search/search-source.js +82 -93
- package/dist/indexer/usage/usage-events.js +0 -89
- package/dist/indexer/walk/file-context.js +2 -1
- package/dist/indexer/walk/matchers.js +30 -43
- package/dist/indexer/walk/path-resolver.js +7 -2
- package/dist/indexer/walk/walker.js +38 -12
- package/dist/integrations/agent/builders.js +0 -6
- package/dist/integrations/agent/config.js +2 -2
- package/dist/integrations/agent/detect.js +49 -19
- package/dist/integrations/agent/engine-fallback.js +76 -0
- package/dist/integrations/agent/profiles.js +14 -0
- package/dist/integrations/agent/prompts.js +12 -8
- package/dist/integrations/agent/runner-dispatch.js +4 -2
- package/dist/integrations/agent/runner.js +0 -1
- package/dist/integrations/agent/spawn.js +5 -6
- package/dist/integrations/github.js +1 -1
- package/dist/integrations/harnesses/aider/agent-builder.js +6 -4
- package/dist/integrations/harnesses/amazonq/agent-builder.js +7 -4
- package/dist/integrations/harnesses/claude/session-log.js +0 -10
- package/dist/integrations/harnesses/codex/agent-builder.js +5 -2
- package/dist/integrations/harnesses/copilot/agent-builder.js +5 -3
- package/dist/integrations/harnesses/gemini/agent-builder.js +5 -3
- package/dist/integrations/harnesses/index.js +3 -7
- package/dist/integrations/harnesses/opencode/agent-builder.js +21 -2
- package/dist/integrations/harnesses/opencode/session-log.js +0 -15
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +13 -4
- package/dist/integrations/harnesses/openhands/agent-builder.js +9 -6
- package/dist/integrations/harnesses/pi/agent-builder.js +6 -4
- package/dist/integrations/lockfile.js +101 -6
- package/dist/integrations/session-logs/index.js +3 -28
- package/dist/llm/client.js +136 -100
- package/dist/llm/embedders/remote.js +13 -5
- package/dist/llm/feature-gate.js +4 -12
- package/dist/llm/graph-extract.js +5 -11
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +5 -7
- package/dist/llm/structured-call.js +1 -1
- package/dist/llm/usage-persist.js +26 -5
- package/dist/llm/usage-telemetry.js +25 -2
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +259 -0
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -36
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +56 -83
- package/dist/output/shapes/migrate.js +8 -0
- package/dist/output/shapes/passthrough.js +7 -41
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes.js +2 -9
- package/dist/output/text/{init.js → bundle-create.js} +3 -1
- package/dist/output/text/bundle-show.js +7 -0
- package/dist/output/text/command-format.js +164 -96
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/health-format.js +103 -0
- package/dist/output/text/health.js +7 -0
- package/dist/output/text/helpers.js +10 -8
- package/dist/output/text/lint-format.js +43 -0
- package/dist/output/text/{save.js → lint.js} +2 -2
- package/dist/output/text/migrate.js +88 -0
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +44 -72
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/show-directives.js +15 -7
- package/dist/output/text/status-list.js +32 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +24 -203
- package/dist/output/text/workflow.js +1 -7
- package/dist/output/text.js +16 -17
- package/dist/registry/factory.js +4 -6
- package/dist/registry/origin-resolve.js +16 -27
- package/dist/registry/providers/skills-sh.js +3 -3
- package/dist/registry/providers/static-index.js +13 -23
- package/dist/registry/resolve.js +42 -7
- package/dist/registry/semver.js +34 -84
- package/dist/runtime.js +2 -23
- package/dist/scripts/akm-migrate-node.js +60290 -0
- package/dist/scripts/akm-migrate.js +59628 -0
- package/dist/setup/detect.js +42 -15
- package/dist/setup/registry-stash-loader.js +2 -2
- package/dist/setup/setup.js +236 -136
- package/dist/setup/steps/connection.js +7 -9
- package/dist/setup/steps/platforms.js +9 -9
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +12 -13
- package/dist/setup/steps/stashdir.js +2 -3
- package/dist/setup/steps/tasks.js +237 -120
- package/dist/sources/freshness.js +1 -1
- package/dist/sources/provider-factory.js +11 -17
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +278 -34
- package/dist/sources/providers/git-provider.js +25 -23
- package/dist/sources/providers/git-stash.js +395 -106
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +7 -4
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +6 -1
- package/dist/sources/resolve.js +6 -5
- package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
- package/dist/sources/snapshot-fetchers/content-extract.js +566 -0
- package/dist/sources/snapshot-fetchers/fetcher-util.js +41 -0
- package/dist/sources/snapshot-fetchers/github.js +100 -0
- package/dist/sources/snapshot-fetchers/host-guard.js +291 -0
- package/dist/sources/snapshot-fetchers/registry.js +17 -1
- package/dist/sources/snapshot-fetchers/robots.js +348 -0
- package/dist/sources/snapshot-fetchers/rss.js +282 -0
- package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
- package/dist/sources/snapshot-fetchers/website-ingest.js +566 -268
- package/dist/sources/snapshot-fetchers/x.js +910 -0
- package/dist/storage/database.js +7 -0
- package/dist/storage/engines/sqlite-migrations.js +23 -111
- package/dist/storage/managed-db.js +2 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +27 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -12
- package/dist/storage/repositories/index-connection.js +17 -6
- package/dist/storage/repositories/index-entries-repository.js +151 -240
- package/dist/storage/repositories/index-entry-mapper.js +15 -11
- package/dist/storage/repositories/index-fts-repository.js +5 -2
- package/dist/storage/repositories/index-llm-cache-repository.js +0 -1
- package/dist/storage/repositories/index-meta-repository.js +2 -3
- package/dist/storage/repositories/index-schema.js +10 -25
- package/dist/storage/repositories/index-utility-repository.js +15 -28
- package/dist/storage/repositories/index-vec-repository.js +6 -1
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +296 -59
- package/dist/storage/repositories/registry-cache.js +19 -0
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +15 -13
- package/dist/storage/repositories/workflow-runs-repository.js +52 -40
- package/dist/tasks/backends/cron.js +105 -15
- package/dist/tasks/backends/index.js +1 -1
- package/dist/tasks/backends/launchd.js +85 -38
- package/dist/tasks/backends/schtasks.js +135 -15
- package/dist/tasks/embedded.js +56 -40
- package/dist/tasks/parser.js +7 -157
- package/dist/tasks/resolve-akm-bin.js +137 -59
- package/dist/tasks/runner.js +79 -42
- package/dist/tasks/scheduler-invocation.js +220 -10
- package/dist/tasks/schema.js +24 -1
- package/dist/tasks/task-id.js +1 -3
- package/dist/tasks/validator.js +20 -6
- package/dist/workflows/authoring/authoring.js +94 -143
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/exec/frozen-judge.js +28 -2
- package/dist/workflows/exec/native-executor.js +77 -57
- package/dist/workflows/exec/param-secrets.js +9 -9
- package/dist/workflows/exec/run-workflow.js +133 -79
- package/dist/workflows/exec/step-work.js +219 -346
- package/dist/{migrate-storage-node.mjs → workflows/exec/unit-dispatch.js} +1 -5
- package/dist/workflows/ir/compile.js +141 -270
- package/dist/workflows/ir/freeze.js +40 -30
- package/dist/workflows/ir/params.js +135 -11
- package/dist/workflows/ir/plan-hash.js +1 -1
- package/dist/workflows/ir/schema.js +25 -26
- package/dist/workflows/parser.js +872 -307
- package/dist/workflows/program/expressions.js +20 -208
- package/dist/workflows/program/schema.js +7 -10
- package/dist/workflows/renderer.js +95 -68
- package/dist/workflows/resource-limits.js +2 -0
- package/dist/workflows/runtime/checkin.js +3 -3
- package/dist/workflows/runtime/plan-classifier.js +16 -75
- package/dist/workflows/runtime/runs.js +186 -127
- package/dist/workflows/runtime/unit-checkin.js +1 -1
- package/dist/workflows/runtime/unit-phases.js +2 -2
- package/dist/workflows/runtime/workflow-asset-loader.js +232 -83
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +30 -36
- package/dist/workflows/validator.js +21 -62
- package/docs/README.md +68 -0
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.7.0.md +11 -11
- package/docs/migration/release-notes/0.9.0.md +208 -27
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +564 -208
- package/docs/migration/v0.9.0-troubleshooting.md +561 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/cli.md +2253 -0
- package/docs/reference/configuration.md +358 -0
- package/docs/reference/data-and-telemetry.md +105 -42
- package/docs/reference/workflows.md +647 -0
- package/package.json +22 -11
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +81 -128
- package/schemas/akm-workflow.json +74 -73
- package/dist/assets/tasks/core/backup.yml +0 -5
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/cli/config-migrate.js +0 -1806
- package/dist/cli/config-validate.js +0 -41
- package/dist/commands/backup-cli.js +0 -56
- package/dist/commands/bundle/bundle-cli.js +0 -68
- package/dist/commands/bundle/bundle.js +0 -219
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -489
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/mv-cli.js +0 -1221
- package/dist/commands/sources/history.js +0 -201
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/core/migration-backup.js +0 -1234
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -95
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/migrate/legacy/config-source-migration.js +0 -223
- package/dist/migrate/legacy/content-migration.js +0 -305
- package/dist/migrate/legacy/legacy-layout.js +0 -779
- package/dist/migrate/legacy/legacy-paths.js +0 -25
- package/dist/migrate/legacy/legacy-stash-json.js +0 -72
- package/dist/migrate/legacy/proposal-fs-import.js +0 -168
- package/dist/migrate/legacy/task-target-ref-migration.js +0 -272
- package/dist/migrate/legacy/three-db-cutover.js +0 -841
- package/dist/migrate/legacy/workflow-migrations-bodies.js +0 -52
- package/dist/migrate/legacy/workflow-migrations-frozen.js +0 -21
- package/dist/migrate/legacy-ref-grammar.js +0 -214
- package/dist/output/shapes/distill.js +0 -14
- package/dist/output/shapes/history.js +0 -11
- package/dist/output/text/distill.js +0 -6
- package/dist/output/text/enable-disable.js +0 -8
- package/dist/output/text/history.js +0 -6
- package/dist/registry/build-index.js +0 -382
- package/dist/schemas/akm-config.json +0 -4704
- package/dist/schemas/akm-task.json +0 -87
- package/dist/schemas/akm-workflow.json +0 -372
- package/dist/scripts/migrate-storage.js +0 -3816
- package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
- package/dist/workflows/cli.js +0 -53
- package/dist/workflows/exec/brief.js +0 -481
- package/dist/workflows/exec/report.js +0 -1460
- package/dist/workflows/exec/watch.js +0 -116
- package/dist/workflows/program/parser.js +0 -813
- package/dist/workflows/program/project.js +0 -104
package/dist/cli.js
CHANGED
|
@@ -42,7 +42,7 @@ process.on("unhandledRejection", (reason) => {
|
|
|
42
42
|
}, null, 2));
|
|
43
43
|
if (process.env.AKM_DEBUG === "1" && err.stack)
|
|
44
44
|
console.error(err.stack);
|
|
45
|
-
process.exit(
|
|
45
|
+
process.exit(EXIT_CODES.INTERNAL);
|
|
46
46
|
});
|
|
47
47
|
process.on("uncaughtException", (err) => {
|
|
48
48
|
console.error(JSON.stringify({
|
|
@@ -53,57 +53,56 @@ process.on("uncaughtException", (err) => {
|
|
|
53
53
|
}, null, 2));
|
|
54
54
|
if (process.env.AKM_DEBUG === "1" && err.stack)
|
|
55
55
|
console.error(err.stack);
|
|
56
|
-
process.exit(
|
|
56
|
+
process.exit(EXIT_CODES.INTERNAL);
|
|
57
57
|
});
|
|
58
58
|
import fs from "node:fs";
|
|
59
|
-
import
|
|
60
|
-
import {
|
|
61
|
-
import {
|
|
62
|
-
import { EXIT_CODES, emitJsonError, output, runWithJsonErrors } from "./cli/shared.js";
|
|
63
|
-
import {
|
|
64
|
-
import {
|
|
65
|
-
import { bundleCommand } from "./commands/bundle/bundle-cli.js";
|
|
59
|
+
import { defineCommand, parseArgs, renderUsage, runCommand, showUsage } from "citty";
|
|
60
|
+
import { findCittyTopLevelCommand, findCittyTopLevelCommandIndex, getParsedInvocation, parseAllFlagValues, resolveHelpMigrateVersionArg, setParsedInvocation, } from "./cli/invocation.js";
|
|
61
|
+
import { retiredCommandHint } from "./cli/retired-commands.js";
|
|
62
|
+
import { defineGroupCommand, EXIT_CODES, emitJsonError, GLOBAL_OUTPUT_ARGS, output, runWithJsonErrors, } from "./cli/shared.js";
|
|
63
|
+
import { assertKnownFlags, closestMatch } from "./cli/unknown-flags.js";
|
|
64
|
+
import { agentCommand, lintCommand } from "./commands/agent/contribute-cli.js";
|
|
66
65
|
import { generateBashCompletions, installBashCompletions } from "./commands/completions.js";
|
|
67
66
|
import { configCommand } from "./commands/config-cli.js";
|
|
68
67
|
import { envCommand } from "./commands/env/env-cli.js";
|
|
69
68
|
import { secretCommand } from "./commands/env/secret-cli.js";
|
|
70
69
|
import { feedbackCommand } from "./commands/feedback-cli.js";
|
|
71
|
-
import { graphCommand } from "./commands/graph/graph-cli.js";
|
|
72
70
|
import { akmHealth } from "./commands/health.js";
|
|
73
|
-
import
|
|
71
|
+
import "./commands/health/renderers.js";
|
|
74
72
|
import { parseWindowSpec } from "./commands/health/windows.js";
|
|
75
|
-
import { extractCommand } from "./commands/improve/extract-cli.js";
|
|
76
73
|
import { improveCommand } from "./commands/improve/improve-cli.js";
|
|
77
74
|
import { migrateCommand } from "./commands/migrate-cli.js";
|
|
78
|
-
import {
|
|
79
|
-
import { hintsCommand, lessonsCommand, logCommand } from "./commands/observability-cli.js";
|
|
75
|
+
import { logCommand } from "./commands/observability-cli.js";
|
|
80
76
|
import { proposalCommand } from "./commands/proposal/proposal-cli.js";
|
|
81
77
|
import { rememberCommand } from "./commands/read/remember-cli.js";
|
|
82
78
|
import { curateCommand, searchCommand, showCommand } from "./commands/read/search-cli.js";
|
|
83
|
-
import { normalizeShowArgv } from "./commands/read/show.js";
|
|
84
79
|
import { registryCommand } from "./commands/registry-cli.js";
|
|
85
|
-
import {
|
|
80
|
+
import { bundleCommand } from "./commands/sources/bundle-cli.js";
|
|
86
81
|
import { renderMigrationHelp } from "./commands/sources/migration-help.js";
|
|
87
|
-
import { cloneCommand,
|
|
88
|
-
import { importKnowledgeCommand, indexCommand, infoCommand
|
|
89
|
-
import {
|
|
82
|
+
import { cloneCommand, syncCommand, upgradeCommand } from "./commands/sources/sources-cli.js";
|
|
83
|
+
import { importKnowledgeCommand, indexCommand, infoCommand } from "./commands/sources/stash-cli.js";
|
|
84
|
+
import { taskCommand } from "./commands/tasks/tasks-cli.js";
|
|
90
85
|
import { workflowCommand } from "./commands/workflow-cli.js";
|
|
91
|
-
import { bestEffort } from "./core/best-effort.js";
|
|
92
86
|
import { DEFAULT_CONFIG, loadConfig } from "./core/config/config.js";
|
|
93
87
|
import { UsageError } from "./core/errors.js";
|
|
94
88
|
import { assertNoPendingMigrationOperation } from "./core/migration-operation.js";
|
|
95
|
-
import {
|
|
89
|
+
import { getConfigPath } from "./core/paths.js";
|
|
90
|
+
import { DURATION_UNITS, parseDuration } from "./core/time.js";
|
|
96
91
|
import { plainize } from "./core/tty.js";
|
|
97
92
|
import { info, isQuiet, setQuiet, setVerbose, warn } from "./core/warn.js";
|
|
98
93
|
import { disposeDispatchResources } from "./integrations/agent/runner-dispatch.js";
|
|
99
|
-
import {
|
|
100
|
-
import {
|
|
94
|
+
import { EMBEDDED_HINTS, EMBEDDED_HINTS_FULL } from "./output/cli-hints.js";
|
|
95
|
+
import { getOutputMode, initOutputMode, parseDetailLevel } from "./output/context.js";
|
|
96
|
+
import { isFormatExemptCommand } from "./output/format-exempt.js";
|
|
97
|
+
import { consumeSchedulerContextArg } from "./tasks/scheduler-invocation.js";
|
|
101
98
|
import { pkgVersion } from "./version.js";
|
|
102
99
|
function applyEarlyStderrFlags(argv) {
|
|
103
|
-
|
|
100
|
+
const separator = argv.indexOf("--");
|
|
101
|
+
const ownArgv = separator === -1 ? argv : argv.slice(0, separator);
|
|
102
|
+
if (ownArgv.includes("--quiet") || ownArgv.includes("-q")) {
|
|
104
103
|
setQuiet(true);
|
|
105
104
|
}
|
|
106
|
-
if (
|
|
105
|
+
if (ownArgv.includes("--verbose")) {
|
|
107
106
|
setVerbose(true);
|
|
108
107
|
}
|
|
109
108
|
}
|
|
@@ -129,10 +128,10 @@ function printSetupTtyHint(result) {
|
|
|
129
128
|
return;
|
|
130
129
|
if (isQuiet())
|
|
131
130
|
return;
|
|
132
|
-
if (!result?.
|
|
131
|
+
if (!result?.bundleDir)
|
|
133
132
|
return;
|
|
134
|
-
console.error(plainize(`\n✓
|
|
135
|
-
|
|
133
|
+
console.error(plainize(`\n✓ Bundle created at ${result.bundleDir}\n` +
|
|
134
|
+
' Next: `akm bundle add <source>`, `akm index`, `akm search "<query>"`, `akm help agents`'));
|
|
136
135
|
}
|
|
137
136
|
/**
|
|
138
137
|
* Module Naming:
|
|
@@ -147,9 +146,14 @@ const setupCommand = defineCommand({
|
|
|
147
146
|
description: "Interactive configuration wizard. Configures embeddings/LLM connections (for indexing/enrichment), agent profiles (CLI agent, embedded SDK, or none), sources, and registries. Shows which features are enabled at the end. Use --config <json> or --yes for non-interactive/scripting mode.",
|
|
148
147
|
},
|
|
149
148
|
args: {
|
|
149
|
+
// R-051/S11: `setup` is a raw `defineCommand` (not `defineJsonCommand`),
|
|
150
|
+
// so it does not get `GLOBAL_OUTPUT_ARGS` for free — same gap `health`
|
|
151
|
+
// already had. Three of its four run branches call `output()`; spreading
|
|
152
|
+
// this in is a `--help` visibility fix, not a behavior change.
|
|
153
|
+
...GLOBAL_OUTPUT_ARGS,
|
|
150
154
|
config: {
|
|
151
155
|
type: "string",
|
|
152
|
-
description: 'Config JSON to apply non-interactively, e.g. \'{"
|
|
156
|
+
description: 'Config JSON to apply non-interactively, e.g. \'{"engines":{"local":{"kind":"llm","endpoint":"...","model":"..."}},"defaults":{"llmEngine":"local"}}\'',
|
|
153
157
|
},
|
|
154
158
|
from: {
|
|
155
159
|
type: "string",
|
|
@@ -162,50 +166,29 @@ const setupCommand = defineCommand({
|
|
|
162
166
|
},
|
|
163
167
|
dir: {
|
|
164
168
|
type: "string",
|
|
165
|
-
description: "
|
|
169
|
+
description: "Bundle directory path (overrides defaultBundle in config or --config JSON)",
|
|
166
170
|
},
|
|
167
|
-
|
|
171
|
+
// Declared as the POSITIVE name with `default: true` so citty's native
|
|
172
|
+
// `--no-<name>` negation (it strips a leading `--no-` from ANY token and
|
|
173
|
+
// negates the remainder BEFORE consulting the declared-args table) does
|
|
174
|
+
// the work, matching the `sync --push/--no-push` pattern. A flag
|
|
175
|
+
// DECLARED as `no-init` can never be negated: `--no-init` parses as
|
|
176
|
+
// "negate `init`", a name nothing declared, leaving the real key at its
|
|
177
|
+
// default forever — see `search --no-project-context`'s identical fix.
|
|
178
|
+
init: {
|
|
168
179
|
type: "boolean",
|
|
169
|
-
default:
|
|
170
|
-
description: "
|
|
180
|
+
default: true,
|
|
181
|
+
description: "Scaffold the bundle directory. Use --no-init to write configuration without scaffolding it.",
|
|
171
182
|
},
|
|
172
183
|
probe: {
|
|
173
184
|
type: "boolean",
|
|
174
185
|
default: false,
|
|
175
186
|
description: "Probe LLM/embedding endpoints before writing config to verify connectivity",
|
|
176
187
|
},
|
|
177
|
-
"detect-only": {
|
|
178
|
-
type: "boolean",
|
|
179
|
-
default: false,
|
|
180
|
-
description: "Run environment detection only and print the result (no prompts, no writes). Pair with --format json.",
|
|
181
|
-
},
|
|
182
|
-
"reset-recommended": {
|
|
183
|
-
type: "boolean",
|
|
184
|
-
default: false,
|
|
185
|
-
description: "Merge opinionated, detection-derived defaults into the existing config without removing custom keys.",
|
|
186
|
-
},
|
|
187
188
|
},
|
|
188
189
|
async run({ args }) {
|
|
189
190
|
await runWithJsonErrors(async () => {
|
|
190
|
-
|
|
191
|
-
// so retain the raw argv spelling as the authoritative compatibility form.
|
|
192
|
-
const noInit = getHyphenatedBoolean(args, "no-init") || process.argv.includes("--no-init");
|
|
193
|
-
const detectOnly = args["detect-only"];
|
|
194
|
-
const resetRecommended = args["reset-recommended"];
|
|
195
|
-
if (detectOnly) {
|
|
196
|
-
// Detection only: no prompts, no writes.
|
|
197
|
-
const { runDetectOnly } = await import("./setup/setup.js");
|
|
198
|
-
const detection = await runDetectOnly();
|
|
199
|
-
output("setup", detection);
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
if (resetRecommended) {
|
|
203
|
-
const { runResetRecommended } = await import("./setup/setup.js");
|
|
204
|
-
const result = await runResetRecommended({ dir: args.dir, noInit, probe: args.probe });
|
|
205
|
-
output("setup", result);
|
|
206
|
-
printSetupTtyHint(result);
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
191
|
+
const noInit = !args.init;
|
|
209
192
|
if (args.from && args.config) {
|
|
210
193
|
throw new UsageError("Pass either --from <file> or --config <json>, not both.", "INVALID_FLAG_VALUE");
|
|
211
194
|
}
|
|
@@ -254,7 +237,13 @@ const setupCommand = defineCommand({
|
|
|
254
237
|
printSetupTtyHint(result);
|
|
255
238
|
}
|
|
256
239
|
else {
|
|
257
|
-
// Interactive wizard
|
|
240
|
+
// Interactive wizard. Guard the TTY first: the wizard's prompts read
|
|
241
|
+
// from stdin, so a piped/redirected/CI invocation would render the
|
|
242
|
+
// first prompt and then block forever instead of failing — and `akm
|
|
243
|
+
// setup` is the first command users automate.
|
|
244
|
+
if (process.stdin.isTTY !== true) {
|
|
245
|
+
throw new UsageError("Interactive setup requires a TTY. Pass --yes to accept defaults, or --config <json> / --from <file> to configure non-interactively.", "NON_INTERACTIVE_REQUIRES_YES");
|
|
246
|
+
}
|
|
258
247
|
const { runSetupWizard } = await import("./setup/setup.js");
|
|
259
248
|
await runSetupWizard({ dir: args.dir, noInit });
|
|
260
249
|
}
|
|
@@ -262,8 +251,17 @@ const setupCommand = defineCommand({
|
|
|
262
251
|
},
|
|
263
252
|
});
|
|
264
253
|
const healthCommand = defineCommand({
|
|
265
|
-
meta: {
|
|
254
|
+
meta: {
|
|
255
|
+
name: "health",
|
|
256
|
+
description: "Check akm runtime health, artifacts, and improve metrics",
|
|
257
|
+
},
|
|
266
258
|
args: {
|
|
259
|
+
// R-051: `health` is a raw `defineCommand` (not `defineJsonCommand`), so
|
|
260
|
+
// it does not get `GLOBAL_OUTPUT_ARGS` for free. `--format`/`--detail`/
|
|
261
|
+
// `--shape`/`--output` already parsed correctly here (this command has
|
|
262
|
+
// no positional for a stray value to fall into), so this is purely a
|
|
263
|
+
// `--help` visibility / consistency fix, not a behavior change.
|
|
264
|
+
...GLOBAL_OUTPUT_ARGS,
|
|
267
265
|
since: {
|
|
268
266
|
type: "string",
|
|
269
267
|
description: "Rolling window start (ISO timestamp, date, epoch ms, or shorthand like 24h / 7d)",
|
|
@@ -280,95 +278,234 @@ const healthCommand = defineCommand({
|
|
|
280
278
|
type: "string",
|
|
281
279
|
description: "Explicit comparison window 'name=...,since=ISO,until=ISO' (repeatable, up to 4; mutually exclusive with --window-compare)",
|
|
282
280
|
},
|
|
283
|
-
|
|
284
|
-
type: "
|
|
285
|
-
description: "
|
|
281
|
+
report: {
|
|
282
|
+
type: "boolean",
|
|
283
|
+
description: "Fetch the full report dataset: per-run rows, trend deltas vs the prior window, and the pending proposal queue. Renders as the rich report under --format md/html and as complete data under any other format.",
|
|
284
|
+
default: false,
|
|
286
285
|
},
|
|
287
286
|
},
|
|
288
287
|
async run({ args }) {
|
|
289
288
|
let resultStatus;
|
|
289
|
+
const exitCodeBeforeRun = process.exitCode;
|
|
290
290
|
await runWithJsonErrors(async () => {
|
|
291
291
|
// citty only surfaces the last value of a repeated flag, so read --windows
|
|
292
292
|
// directly from argv to support multi-window comparison.
|
|
293
293
|
const rawWindows = parseAllFlagValues("--windows");
|
|
294
294
|
const windows = rawWindows.length > 0 ? rawWindows.map((raw) => parseWindowSpec(raw)) : undefined;
|
|
295
295
|
const groupBy = args["group-by"];
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
//
|
|
299
|
-
//
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
//
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
deltas,
|
|
320
|
-
});
|
|
321
|
-
deliverRendered(renderHtml(resolveTemplatePath("health"), replacements), mode.outputPath);
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
const result = akmHealth({
|
|
296
|
+
const report = args.report === true;
|
|
297
|
+
// `--report` is a DATA flag: it selects the richer read (per-run rows +
|
|
298
|
+
// window-compare deltas + the proposal queue) and nothing about the read
|
|
299
|
+
// depends on --format. The registered md/html renderers are pure
|
|
300
|
+
// functions of the result — a report-shaped result renders as the rich
|
|
301
|
+
// report, any other shape falls through to the generic rendering.
|
|
302
|
+
//
|
|
303
|
+
// The compare window defaults to the report's own `--since` window so the
|
|
304
|
+
// deltas are like-for-like (e.g. last 7d vs the prior 7d). A fixed 24h
|
|
305
|
+
// default made a `--since 7d` report compare its 7-day totals against a
|
|
306
|
+
// 24-hour prior window, producing meaningless deltas.
|
|
307
|
+
// Comparison-window precedence. An explicit `--window-compare` always
|
|
308
|
+
// wins. Otherwise `--report` seeds a like-for-like comparison from
|
|
309
|
+
// `--since`, but only when `--since` is a DURATION: `resolveWindowCompare`
|
|
310
|
+
// parses durations only, so feeding it an absolute date, ISO timestamp, or
|
|
311
|
+
// epoch value throws. And explicit `--windows` gets no implicit value at
|
|
312
|
+
// all — the two are mutually exclusive, so synthesizing one turned a valid
|
|
313
|
+
// invocation into a usage error.
|
|
314
|
+
const explicitWindows = windows !== undefined && windows.length > 0;
|
|
315
|
+
const sinceIsDuration = args.since !== undefined && parseDuration(args.since, DURATION_UNITS) !== null;
|
|
316
|
+
const implicitCompare = explicitWindows ? undefined : ((sinceIsDuration ? args.since : undefined) ?? "24h");
|
|
317
|
+
const windowCompare = report ? (args["window-compare"] ?? implicitCompare) : args["window-compare"];
|
|
318
|
+
const base = akmHealth({
|
|
325
319
|
since: args.since,
|
|
326
|
-
groupBy: groupBy,
|
|
327
|
-
windowCompare
|
|
320
|
+
groupBy: report ? "run" : groupBy,
|
|
321
|
+
windowCompare,
|
|
328
322
|
windows,
|
|
329
323
|
});
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
324
|
+
const reportCompare = windowCompare ??
|
|
325
|
+
(explicitWindows
|
|
326
|
+
? [...(base.windows ?? [])]
|
|
327
|
+
.sort((a, b) => new Date(a.since).getTime() - new Date(b.since).getTime())
|
|
328
|
+
.map((window) => window.name)
|
|
329
|
+
.join(" → ")
|
|
330
|
+
: undefined) ??
|
|
331
|
+
"24h";
|
|
332
|
+
resultStatus = base.status;
|
|
333
|
+
if (report) {
|
|
334
|
+
const { listPendingProposals } = await import("./commands/proposal/proposal.js");
|
|
335
|
+
const { computeAcceptRateBySource } = await import("./commands/health/accept-rate.js");
|
|
336
|
+
output("health", {
|
|
337
|
+
...base,
|
|
338
|
+
report: {
|
|
339
|
+
window: args.since ?? "24h",
|
|
340
|
+
compare: reportCompare,
|
|
341
|
+
comparisonMode: explicitWindows ? "custom" : "duration",
|
|
342
|
+
pendingProposals: listPendingProposals().map(({ ref, source, createdAt }) => ({ ref, source, createdAt })),
|
|
343
|
+
acceptRateBySource: computeAcceptRateBySource(),
|
|
344
|
+
},
|
|
345
|
+
});
|
|
346
|
+
return;
|
|
347
347
|
}
|
|
348
|
+
output("health", base);
|
|
348
349
|
});
|
|
350
|
+
// R-067: `emitJsonError` (src/cli/shared.ts) no longer force-exits on the
|
|
351
|
+
// error path — it sets `process.exitCode` and returns, so a `--report`
|
|
352
|
+
// failure thrown AFTER `resultStatus` was already assigned (e.g. the
|
|
353
|
+
// proposal-queue read above) would otherwise leave `resultStatus`
|
|
354
|
+
// populated here too. Skip the status-derived exit entirely once
|
|
355
|
+
// `runWithJsonErrors` has already recorded a classified failure, so it is
|
|
356
|
+
// never clobbered by a mismatched health status.
|
|
357
|
+
if (process.exitCode !== exitCodeBeforeRun)
|
|
358
|
+
return;
|
|
349
359
|
if (resultStatus === "fail") {
|
|
350
|
-
process.
|
|
360
|
+
process.exitCode = EXIT_GENERAL;
|
|
351
361
|
}
|
|
352
362
|
if (resultStatus === "warn") {
|
|
353
|
-
process.
|
|
363
|
+
process.exitCode = EXIT_HEALTH_WARN;
|
|
354
364
|
}
|
|
355
365
|
},
|
|
356
366
|
});
|
|
357
|
-
|
|
367
|
+
function loadAgentHints(full) {
|
|
368
|
+
return full ? EMBEDDED_HINTS_FULL : EMBEDDED_HINTS;
|
|
369
|
+
}
|
|
370
|
+
const hintsCommand = defineCommand({
|
|
371
|
+
meta: {
|
|
372
|
+
name: "hints",
|
|
373
|
+
description: "Print agent instructions on how to use akm — the complete guide by default; pass --detail brief for the short one",
|
|
374
|
+
},
|
|
375
|
+
args: {
|
|
376
|
+
detail: {
|
|
377
|
+
type: "string",
|
|
378
|
+
description: "Hints detail level (brief|normal|full). `brief` prints the short guide; `normal`/`full` print the complete guide.",
|
|
379
|
+
default: "normal",
|
|
380
|
+
},
|
|
381
|
+
},
|
|
382
|
+
run({ args }) {
|
|
383
|
+
return runWithJsonErrors(() => {
|
|
384
|
+
const detail = parseDetailLevel(args.detail) ?? "normal";
|
|
385
|
+
process.stdout.write(loadAgentHints(detail !== "brief"));
|
|
386
|
+
});
|
|
387
|
+
},
|
|
388
|
+
});
|
|
389
|
+
const completionsCommand = defineCommand({
|
|
390
|
+
meta: {
|
|
391
|
+
name: "completions",
|
|
392
|
+
description: "Generate or install shell completion script",
|
|
393
|
+
},
|
|
394
|
+
args: {
|
|
395
|
+
install: {
|
|
396
|
+
type: "boolean",
|
|
397
|
+
description: "Install completions to the appropriate directory",
|
|
398
|
+
default: false,
|
|
399
|
+
},
|
|
400
|
+
shell: {
|
|
401
|
+
type: "string",
|
|
402
|
+
description: "Shell type (bash)",
|
|
403
|
+
default: "bash",
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
run({ args }) {
|
|
407
|
+
// R-052(b): this was a bare `run()` throwing directly, so an unsupported
|
|
408
|
+
// `--shell` value escaped straight to citty's top-level error handling
|
|
409
|
+
// instead of the standard JSON envelope — exit 1 with a raw stack trace
|
|
410
|
+
// instead of the classified exit-2 usage error every other command
|
|
411
|
+
// produces (`completions` is format-exempt, so it stays a raw
|
|
412
|
+
// `defineCommand` rather than `defineJsonCommand`, but still needs the
|
|
413
|
+
// same error-classification wrapper other bare `defineCommand`s in this
|
|
414
|
+
// file use, e.g. `help migrate` below).
|
|
415
|
+
return runWithJsonErrors(() => {
|
|
416
|
+
if (args.shell !== "bash") {
|
|
417
|
+
throw new UsageError(`Unsupported shell: ${args.shell}. Only bash is supported.`);
|
|
418
|
+
}
|
|
419
|
+
const script = generateBashCompletions(main);
|
|
420
|
+
if (args.install) {
|
|
421
|
+
const dest = installBashCompletions(script);
|
|
422
|
+
info(`Completions installed to ${dest}`);
|
|
423
|
+
info(`Restart your shell or run: source ${dest}`);
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
process.stdout.write(script);
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
},
|
|
430
|
+
});
|
|
431
|
+
const commands = {
|
|
432
|
+
setup: setupCommand,
|
|
433
|
+
index: indexCommand,
|
|
434
|
+
health: healthCommand,
|
|
435
|
+
info: infoCommand,
|
|
436
|
+
bundle: bundleCommand,
|
|
437
|
+
upgrade: upgradeCommand,
|
|
438
|
+
search: searchCommand,
|
|
439
|
+
curate: curateCommand,
|
|
440
|
+
show: showCommand,
|
|
441
|
+
workflow: workflowCommand,
|
|
442
|
+
remember: rememberCommand,
|
|
443
|
+
import: importKnowledgeCommand,
|
|
444
|
+
sync: syncCommand,
|
|
445
|
+
clone: cloneCommand,
|
|
446
|
+
registry: registryCommand,
|
|
447
|
+
migrate: migrateCommand,
|
|
448
|
+
config: configCommand,
|
|
449
|
+
feedback: feedbackCommand,
|
|
450
|
+
log: logCommand,
|
|
451
|
+
agent: agentCommand,
|
|
452
|
+
lint: lintCommand,
|
|
453
|
+
improve: improveCommand,
|
|
454
|
+
proposal: proposalCommand,
|
|
455
|
+
completions: completionsCommand,
|
|
456
|
+
env: envCommand,
|
|
457
|
+
secret: secretCommand,
|
|
458
|
+
task: taskCommand,
|
|
459
|
+
hints: hintsCommand,
|
|
460
|
+
};
|
|
461
|
+
function commandHelpTopic(name, command) {
|
|
462
|
+
return defineCommand({
|
|
463
|
+
meta: { name, description: `Print help for akm ${name}` },
|
|
464
|
+
async run() {
|
|
465
|
+
await showUsage(command, buildUsageParentForPath([name]));
|
|
466
|
+
},
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
// `migrate` is excluded here even though it's a normal, now-visible SYSTEM
|
|
470
|
+
// command (see HELP_SECTIONS below): `help`'s own `migrate` subcommand
|
|
471
|
+
// (registered below) intentionally shadows this generic command-usage
|
|
472
|
+
// renderer with release-notes lookup instead — `akm help migrate 0.9.0`
|
|
473
|
+
// prints migration guidance, not `migrate`'s own `--help` usage block. That
|
|
474
|
+
// usage block is still reachable directly via `akm migrate --help`.
|
|
475
|
+
const commandHelpTopics = Object.fromEntries(Object.entries(commands)
|
|
476
|
+
.filter(([name]) => name !== "migrate")
|
|
477
|
+
.map(([name, command]) => [name, commandHelpTopic(name, command)]));
|
|
478
|
+
const helpCommand = defineGroupCommand({
|
|
358
479
|
meta: {
|
|
359
480
|
name: "help",
|
|
360
|
-
description: "Print
|
|
481
|
+
description: "Print the command overview, detailed help for a command, agent instructions, or a release's migration guidance",
|
|
361
482
|
},
|
|
362
483
|
subCommands: {
|
|
484
|
+
...commandHelpTopics,
|
|
485
|
+
agents: defineCommand({
|
|
486
|
+
meta: {
|
|
487
|
+
name: "agents",
|
|
488
|
+
description: "Print agent instructions on how to use akm — the short guide by default; pass --full for the complete guide",
|
|
489
|
+
},
|
|
490
|
+
args: {
|
|
491
|
+
full: {
|
|
492
|
+
type: "boolean",
|
|
493
|
+
default: false,
|
|
494
|
+
description: "Print the complete guide instead of the short one.",
|
|
495
|
+
},
|
|
496
|
+
},
|
|
497
|
+
run({ args }) {
|
|
498
|
+
return runWithJsonErrors(() => {
|
|
499
|
+
process.stdout.write(loadAgentHints(args.full === true));
|
|
500
|
+
});
|
|
501
|
+
},
|
|
502
|
+
}),
|
|
363
503
|
migrate: defineCommand({
|
|
364
504
|
meta: {
|
|
365
505
|
name: "migrate",
|
|
366
506
|
description: "Print release notes and migration guidance for a version. Bundled notes live in docs/migration/release-notes/<version>.md; an unknown version lists what's available.",
|
|
367
507
|
},
|
|
368
508
|
args: {
|
|
369
|
-
// Optional in citty so run() is invoked even when omitted; we
|
|
370
|
-
// re-validate below to surface a structured UsageError (exit 2)
|
|
371
|
-
// instead of citty's default help-banner exit-0.
|
|
372
509
|
version: {
|
|
373
510
|
type: "positional",
|
|
374
511
|
description: "Version to review (for example 0.6.0, v0.6.0, 0.6.0-rc1, or latest)",
|
|
@@ -386,123 +523,34 @@ const helpCommand = defineCommand({
|
|
|
386
523
|
},
|
|
387
524
|
}),
|
|
388
525
|
},
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
meta: {
|
|
392
|
-
name: "completions",
|
|
393
|
-
description: "Generate or install shell completion script",
|
|
394
|
-
},
|
|
395
|
-
args: {
|
|
396
|
-
install: {
|
|
397
|
-
type: "boolean",
|
|
398
|
-
description: "Install completions to the appropriate directory",
|
|
399
|
-
default: false,
|
|
400
|
-
},
|
|
401
|
-
shell: {
|
|
402
|
-
type: "string",
|
|
403
|
-
description: "Shell type (bash)",
|
|
404
|
-
default: "bash",
|
|
405
|
-
},
|
|
406
|
-
},
|
|
407
|
-
run({ args }) {
|
|
408
|
-
if (args.shell !== "bash") {
|
|
409
|
-
throw new UsageError(`Unsupported shell: ${args.shell}. Only bash is supported.`);
|
|
410
|
-
}
|
|
411
|
-
const script = generateBashCompletions(main);
|
|
412
|
-
if (args.install) {
|
|
413
|
-
const dest = installBashCompletions(script);
|
|
414
|
-
info(`Completions installed to ${dest}`);
|
|
415
|
-
info(`Restart your shell or run: source ${dest}`);
|
|
416
|
-
}
|
|
417
|
-
else {
|
|
418
|
-
process.stdout.write(script);
|
|
419
|
-
}
|
|
526
|
+
async defaultRun() {
|
|
527
|
+
process.stdout.write(`${await renderSectionedRootHelp()}\n`);
|
|
420
528
|
},
|
|
421
529
|
});
|
|
422
530
|
export const main = defineCommand({
|
|
423
531
|
meta: {
|
|
424
532
|
name: "akm",
|
|
425
533
|
version: pkgVersion,
|
|
426
|
-
description: "Agent Knowledge
|
|
534
|
+
description: "Agent Knowledge Manager — search, show, and manage assets from your bundle.\n\n" +
|
|
427
535
|
"Exit codes:\n" +
|
|
428
536
|
" 0 success\n" +
|
|
429
|
-
" 1
|
|
537
|
+
" 1 not found / command-reported failure\n" +
|
|
430
538
|
" 2 usage error\n" +
|
|
431
539
|
" 4 health warn (akm health only)\n" +
|
|
540
|
+
" 70 internal / unclassified error\n" +
|
|
432
541
|
" 78 config error",
|
|
433
542
|
},
|
|
434
543
|
args: {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
},
|
|
440
|
-
detail: {
|
|
441
|
-
type: "string",
|
|
442
|
-
description: "Detail level (verbosity): brief|normal|full. Default: brief.",
|
|
443
|
-
default: "brief",
|
|
444
|
-
},
|
|
445
|
-
shape: {
|
|
446
|
-
type: "string",
|
|
447
|
-
description: "Output projection: human|agent|summary. 'agent' trims to agent-essential fields; " +
|
|
448
|
-
"'summary' is only valid on 'akm show'. Default: human.",
|
|
449
|
-
},
|
|
450
|
-
quiet: {
|
|
451
|
-
type: "boolean",
|
|
452
|
-
alias: "q",
|
|
453
|
-
description: "Suppress non-essential stderr output (banners, spinners, progress info). " +
|
|
454
|
-
"Safety-critical output is never suppressed: errors, destructive-action confirmation prompts, " +
|
|
455
|
-
"and auto-migration banners always appear regardless of --quiet.",
|
|
456
|
-
default: false,
|
|
457
|
-
},
|
|
458
|
-
verbose: {
|
|
459
|
-
type: "boolean",
|
|
460
|
-
description: "Print per-spec diagnostics to stderr (also honours AKM_VERBOSE env var)",
|
|
461
|
-
default: false,
|
|
462
|
-
},
|
|
544
|
+
// Single-sourced from GLOBAL_OUTPUT_ARGS (src/cli/shared.ts) so root help
|
|
545
|
+
// and leaf help state identical text. format/detail get their `default`
|
|
546
|
+
// added here only — the description text itself is never redeclared.
|
|
547
|
+
...GLOBAL_OUTPUT_ARGS,
|
|
548
|
+
format: { ...GLOBAL_OUTPUT_ARGS.format, default: "json" },
|
|
549
|
+
detail: { ...GLOBAL_OUTPUT_ARGS.detail, default: "brief" },
|
|
463
550
|
},
|
|
464
551
|
subCommands: {
|
|
465
|
-
|
|
466
|
-
init: initCommand,
|
|
467
|
-
index: indexCommand,
|
|
468
|
-
health: healthCommand,
|
|
469
|
-
info: infoCommand,
|
|
470
|
-
graph: graphCommand,
|
|
471
|
-
bundle: bundleCommand,
|
|
472
|
-
add: addCommand,
|
|
473
|
-
list: listCommand,
|
|
474
|
-
remove: removeCommand,
|
|
475
|
-
update: updateCommand,
|
|
476
|
-
upgrade: upgradeCommand,
|
|
477
|
-
search: searchCommand,
|
|
478
|
-
curate: curateCommand,
|
|
479
|
-
show: showCommand,
|
|
480
|
-
workflow: workflowCommand,
|
|
481
|
-
remember: rememberCommand,
|
|
482
|
-
import: importKnowledgeCommand,
|
|
483
|
-
sync: syncCommand,
|
|
484
|
-
clone: cloneCommand,
|
|
485
|
-
mv: mvCommand,
|
|
486
|
-
registry: registryCommand,
|
|
487
|
-
migrate: migrateCommand,
|
|
488
|
-
backup: backupCommand,
|
|
489
|
-
config: configCommand,
|
|
490
|
-
feedback: feedbackCommand,
|
|
491
|
-
history: historyCommand,
|
|
492
|
-
log: logCommand,
|
|
493
|
-
lessons: lessonsCommand,
|
|
494
|
-
agent: agentCommand,
|
|
495
|
-
lint: lintCommand,
|
|
496
|
-
improve: improveCommand,
|
|
497
|
-
extract: extractCommand,
|
|
498
|
-
propose: proposeCommand,
|
|
499
|
-
proposal: proposalCommand,
|
|
552
|
+
...commands,
|
|
500
553
|
help: helpCommand,
|
|
501
|
-
hints: hintsCommand,
|
|
502
|
-
completions: completionsCommand,
|
|
503
|
-
env: envCommand,
|
|
504
|
-
secret: secretCommand,
|
|
505
|
-
tasks: tasksCommand,
|
|
506
554
|
},
|
|
507
555
|
});
|
|
508
556
|
const MAIN_TOP_LEVEL_ARGS = main.args;
|
|
@@ -510,19 +558,45 @@ function isTaskRunWithId(argv) {
|
|
|
510
558
|
const args = argv.slice(2);
|
|
511
559
|
const commandIndex = findCittyTopLevelCommandIndex(args, MAIN_TOP_LEVEL_ARGS);
|
|
512
560
|
const command = commandIndex >= 0 ? args[commandIndex] : undefined;
|
|
513
|
-
if (command !== "
|
|
561
|
+
if (command !== "task")
|
|
514
562
|
return false;
|
|
515
563
|
const taskArgs = args.slice(commandIndex + 1);
|
|
516
|
-
|
|
564
|
+
if (taskArgs[0] !== "run")
|
|
565
|
+
return false;
|
|
566
|
+
const runCommand = taskCommand.subCommands?.run;
|
|
567
|
+
if (!runCommand?.args)
|
|
568
|
+
return false;
|
|
569
|
+
try {
|
|
570
|
+
const parsed = parseArgs(taskArgs.slice(1), runCommand.args);
|
|
571
|
+
return typeof parsed.id === "string" && parsed.id.length > 0;
|
|
572
|
+
}
|
|
573
|
+
catch {
|
|
574
|
+
return false;
|
|
575
|
+
}
|
|
517
576
|
}
|
|
518
577
|
/** Recovery/setup surfaces must remain reachable when config.json is invalid. */
|
|
519
578
|
export function shouldBypassConfigStartup(argv) {
|
|
520
|
-
const
|
|
579
|
+
const userArgs = argv.slice(2);
|
|
580
|
+
const separator = userArgs.indexOf("--");
|
|
581
|
+
const args = separator === -1 ? userArgs : userArgs.slice(0, separator);
|
|
521
582
|
if (args.includes("--help") || args.includes("-h") || args.includes("--version") || args.includes("-v"))
|
|
522
583
|
return true;
|
|
584
|
+
// Bare `akm` (no subcommand at all) renders the same sectioned root-help
|
|
585
|
+
// text as `akm help` — never touches config either.
|
|
586
|
+
if (args.length === 0)
|
|
587
|
+
return true;
|
|
523
588
|
const commandIndex = findCittyTopLevelCommandIndex(args, MAIN_TOP_LEVEL_ARGS);
|
|
524
589
|
const command = commandIndex >= 0 ? args[commandIndex] : undefined;
|
|
525
|
-
if (command === "setup" || command === "
|
|
590
|
+
if (command === "setup" || command === "migrate")
|
|
591
|
+
return true;
|
|
592
|
+
// `help` and `hints` are pure-text surfaces (bundled release notes, static
|
|
593
|
+
// agent-guide text, command usage rendered from `meta` alone) — none of
|
|
594
|
+
// their run bodies read config. The documented recovery path
|
|
595
|
+
// (`akm help migrate 0.9.0`) is only ever run against a config that
|
|
596
|
+
// startup's own load would reject, so both must bypass it the same way
|
|
597
|
+
// `setup`/`migrate` do, or the recovery instructions are themselves
|
|
598
|
+
// unreachable.
|
|
599
|
+
if (command === "help" || command === "hints")
|
|
526
600
|
return true;
|
|
527
601
|
if (isTaskRunWithId(argv))
|
|
528
602
|
return true;
|
|
@@ -530,7 +604,7 @@ export function shouldBypassConfigStartup(argv) {
|
|
|
530
604
|
return false;
|
|
531
605
|
const configIndex = args.indexOf("config");
|
|
532
606
|
const subcommand = args.slice(configIndex + 1).find((arg) => !arg.startsWith("-"));
|
|
533
|
-
return subcommand === "path"
|
|
607
|
+
return subcommand === "path";
|
|
534
608
|
}
|
|
535
609
|
// ── Exit codes ──────────────────────────────────────────────────────────────
|
|
536
610
|
// Canonical table lives in `src/cli/shared.ts` (EXIT_CODES). These aliases keep
|
|
@@ -539,21 +613,308 @@ export function shouldBypassConfigStartup(argv) {
|
|
|
539
613
|
// GENERAL (1) and USAGE (2). CI monitors can map: 0=pass, 4=warn, 1=fail.
|
|
540
614
|
const EXIT_GENERAL = EXIT_CODES.GENERAL;
|
|
541
615
|
const EXIT_HEALTH_WARN = EXIT_CODES.HEALTH_WARN;
|
|
542
|
-
//
|
|
543
|
-
// imported (e.g. by the in-process test harness in tests/_helpers/cli.ts),
|
|
544
|
-
// `import.meta.main` is false and we skip all startup side effects (argv
|
|
545
|
-
// mutation, output-mode init, index cleanup, banner, runMain) so importers
|
|
546
|
-
// can drive the `main` command themselves without the process exiting.
|
|
616
|
+
// ── Top-level driver (replaces citty's `runMain`) ───────────────────────────
|
|
547
617
|
//
|
|
548
|
-
//
|
|
549
|
-
//
|
|
550
|
-
//
|
|
551
|
-
//
|
|
552
|
-
//
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
618
|
+
// R-032: citty's own `runMain` catches EVERY error escaping `runCommand` —
|
|
619
|
+
// including its unexported `CLIError`, thrown for "Unknown command …", "No
|
|
620
|
+
// command specified.", "Missing required argument/positional …", and invalid
|
|
621
|
+
// enum values — and unconditionally calls `process.exit(1)`, regardless of
|
|
622
|
+
// error kind (node_modules/citty/dist/index.mjs). That collapsed usage
|
|
623
|
+
// mistakes (`akm totally-bogus`, `akm wiki list`, bare `akm log`) onto exit
|
|
624
|
+
// code 1 instead of the documented usage-error code 2 (STABILITY.md's
|
|
625
|
+
// exit-code table), and there is no way to override it from outside
|
|
626
|
+
// `runMain`'s own call frame: once it calls `process.exit`, nothing run
|
|
627
|
+
// afterward — including a `finally` further up the stack — gets a chance to
|
|
628
|
+
// execute. So the CLI drives citty's exported `runCommand` directly instead
|
|
629
|
+
// of `runMain`, replicating `runMain`'s `--help` / `--version`
|
|
630
|
+
// short-circuits and its CLIError → usage-banner rendering, but classifying
|
|
631
|
+
// a CLIError as USAGE (2) instead of GENERAL (1). Every other error escaping
|
|
632
|
+
// this boundary keeps the previous GENERAL (1) mapping — this only
|
|
633
|
+
// reclassifies the one error family citty itself throws before any of our
|
|
634
|
+
// own command bodies (and their `runWithJsonErrors` / `emitJsonError`
|
|
635
|
+
// classification) ever run.
|
|
636
|
+
const HELP_FLAGS = ["--help", "-h"];
|
|
637
|
+
const VERSION_FLAGS = ["--version", "-v"];
|
|
638
|
+
/**
|
|
639
|
+
* Duck-types citty's internal, unexported `CLIError`
|
|
640
|
+
* (node_modules/citty/dist/index.mjs) — the class `runCommand` throws for
|
|
641
|
+
* "Unknown command …", "No command specified.", "Missing required
|
|
642
|
+
* argument/positional …", and invalid enum values. citty does not export
|
|
643
|
+
* this class, so `instanceof` isn't available; `name` is set in its
|
|
644
|
+
* constructor (`this.name = "CLIError"`) and is stable across the pinned
|
|
645
|
+
* `citty@^0.2.2` dependency.
|
|
646
|
+
*/
|
|
647
|
+
function isCittyCliError(error) {
|
|
648
|
+
return error instanceof Error && error.name === "CLIError";
|
|
649
|
+
}
|
|
650
|
+
function findCittySubCommandByName(subCommands, name) {
|
|
651
|
+
if (name in subCommands)
|
|
652
|
+
return subCommands[name];
|
|
653
|
+
for (const sub of Object.values(subCommands)) {
|
|
654
|
+
const alias = sub.meta?.alias;
|
|
655
|
+
const aliases = Array.isArray(alias) ? alias : alias ? [alias] : [];
|
|
656
|
+
if (aliases.includes(name))
|
|
657
|
+
return sub;
|
|
658
|
+
}
|
|
659
|
+
return undefined;
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Re-implementation of citty's own (unexported) `resolveSubCommand`: walks
|
|
663
|
+
* `rawArgs` down the subcommand tree the same way its private
|
|
664
|
+
* `findSubCommandIndex` / `_findSubCommand` do, so an explicit `--help`
|
|
665
|
+
* renders the deepest command the user was actually invoking, matching what
|
|
666
|
+
* citty's own `runMain` would have shown.
|
|
667
|
+
*/
|
|
668
|
+
function resolveDeepestCittyCommand(cmd, rawArgs) {
|
|
669
|
+
const subCommands = cmd.subCommands;
|
|
670
|
+
if (subCommands && Object.keys(subCommands).length > 0) {
|
|
671
|
+
const idx = findCittyTopLevelCommandIndex(rawArgs, (cmd.args ?? {}));
|
|
672
|
+
const name = idx >= 0 ? rawArgs[idx] : undefined;
|
|
673
|
+
if (name !== undefined) {
|
|
674
|
+
const sub = findCittySubCommandByName(subCommands, name);
|
|
675
|
+
if (sub)
|
|
676
|
+
return resolveDeepestCittyCommand(sub, rawArgs.slice(idx + 1));
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
return cmd;
|
|
680
|
+
}
|
|
681
|
+
function resolveCittyCommandPath(cmd, rawArgs, path = []) {
|
|
682
|
+
const subCommands = cmd.subCommands;
|
|
683
|
+
if (!subCommands || Object.keys(subCommands).length === 0)
|
|
684
|
+
return [...path];
|
|
685
|
+
const index = findCittyTopLevelCommandIndex(rawArgs, (cmd.args ?? {}));
|
|
686
|
+
const token = index >= 0 ? rawArgs[index] : undefined;
|
|
687
|
+
if (token === undefined)
|
|
688
|
+
return [...path];
|
|
689
|
+
const sub = findCittySubCommandByName(subCommands, token);
|
|
690
|
+
if (!sub)
|
|
691
|
+
return [...path];
|
|
692
|
+
const name = Object.entries(subCommands).find(([, candidate]) => candidate === sub)?.[0] ?? token;
|
|
693
|
+
return resolveCittyCommandPath(sub, rawArgs.slice(index + 1), [...path, name]);
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* `showUsage`/`renderUsage` (citty) render a subcommand's own USAGE line as
|
|
697
|
+
* `${parentMeta.name} ${cmdMeta.name}` using only the DIRECT parent — for a
|
|
698
|
+
* two-deep command (`akm task run`) that renders `task run`, silently
|
|
699
|
+
* dropping the `akm ` root prefix every top-level command's `--help` already
|
|
700
|
+
* shows. Building a synthetic parent whose `meta.name` is the full prefix
|
|
701
|
+
* (`akm task`) fixes it for any depth without patching the vendored
|
|
702
|
+
* dependency (S11 item 4).
|
|
703
|
+
*/
|
|
704
|
+
function buildUsageParentForPath(path) {
|
|
705
|
+
// `version` carries through too — citty's renderUsage falls back to
|
|
706
|
+
// `parentMeta.version` when the resolved command itself declares none
|
|
707
|
+
// (true of every subcommand here), and the real parent it substitutes for
|
|
708
|
+
// always resolves to `main`, which does declare one.
|
|
709
|
+
return {
|
|
710
|
+
meta: {
|
|
711
|
+
name: ["akm", ...path.slice(0, -1)].join(" "),
|
|
712
|
+
version: pkgVersion,
|
|
713
|
+
},
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
// ── Sectioned root help (S11) ────────────────────────────────────────────────
|
|
717
|
+
//
|
|
718
|
+
// citty's own generated COMMANDS list is a flat, unordered dump of every
|
|
719
|
+
// top-level command — fine for a handful of commands, not for the ~28 this
|
|
720
|
+
// CLI has grown to. Groups them instead under fixed sections mirroring
|
|
721
|
+
// how they're actually used, reusing citty's own `renderUsage` for the
|
|
722
|
+
// banner/USAGE/OPTIONS portion (so it stays byte-identical to every
|
|
723
|
+
// subcommand's own `--help`) and replacing only the COMMANDS section.
|
|
724
|
+
const HELP_SECTIONS = [
|
|
725
|
+
{
|
|
726
|
+
title: "AGENT LOOP",
|
|
727
|
+
commands: ["curate", "search", "show", "feedback", "remember"],
|
|
728
|
+
},
|
|
729
|
+
{
|
|
730
|
+
title: "ASSETS",
|
|
731
|
+
commands: ["import", "clone", "bundle", "env", "secret", "sync", "proposal"],
|
|
732
|
+
},
|
|
733
|
+
{ title: "AUTOMATION", commands: ["improve", "agent", "workflow", "task"] },
|
|
734
|
+
{
|
|
735
|
+
title: "SYSTEM",
|
|
736
|
+
commands: [
|
|
737
|
+
"setup",
|
|
738
|
+
"index",
|
|
739
|
+
"lint",
|
|
740
|
+
"health",
|
|
741
|
+
"config",
|
|
742
|
+
"registry",
|
|
743
|
+
"info",
|
|
744
|
+
"log",
|
|
745
|
+
"migrate",
|
|
746
|
+
"help",
|
|
747
|
+
"hints",
|
|
748
|
+
"upgrade",
|
|
749
|
+
"completions",
|
|
750
|
+
],
|
|
751
|
+
},
|
|
752
|
+
];
|
|
753
|
+
/** Abbreviations whose trailing period does not end a sentence. */
|
|
754
|
+
const NON_TERMINAL_ABBREVIATIONS = ["e.g.", "i.e.", "etc.", "vs."];
|
|
755
|
+
/**
|
|
756
|
+
* First sentence of a description, for the root command list.
|
|
757
|
+
*
|
|
758
|
+
* Several commands carry multi-paragraph descriptions that are correct on
|
|
759
|
+
* `akm <cmd> --help` but turn the root listing back into the undifferentiated
|
|
760
|
+
* wall this section replaced (a single command's description ran past 1k
|
|
761
|
+
* characters on one row).
|
|
762
|
+
*/
|
|
763
|
+
function firstSentence(text) {
|
|
764
|
+
const line = text.split("\n", 1)[0]?.trim() ?? "";
|
|
765
|
+
for (let i = 0; i < line.length; i++) {
|
|
766
|
+
if (line[i] !== "." && line[i] !== "!" && line[i] !== "?")
|
|
767
|
+
continue;
|
|
768
|
+
const candidate = line.slice(0, i + 1);
|
|
769
|
+
const next = line[i + 1];
|
|
770
|
+
if (next !== undefined && next !== " ")
|
|
771
|
+
continue;
|
|
772
|
+
if (NON_TERMINAL_ABBREVIATIONS.some((abbr) => candidate.toLowerCase().endsWith(abbr)))
|
|
773
|
+
continue;
|
|
774
|
+
return candidate;
|
|
775
|
+
}
|
|
776
|
+
return line;
|
|
777
|
+
}
|
|
778
|
+
function topLevelCommandDescription(name) {
|
|
779
|
+
const sub = main.subCommands?.[name];
|
|
780
|
+
return firstSentence(sub?.meta?.description ?? "");
|
|
781
|
+
}
|
|
782
|
+
function formatCommandRows(names) {
|
|
783
|
+
const width = Math.max(...names.map((name) => name.length));
|
|
784
|
+
return names.map((name) => ` ${name.padEnd(width)} ${topLevelCommandDescription(name)}`).join("\n");
|
|
785
|
+
}
|
|
786
|
+
function renderCommandSections() {
|
|
787
|
+
return HELP_SECTIONS.map(({ title, commands }) => `${title}\n${formatCommandRows(commands)}`).join("\n\n");
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Sectioned replacement for citty's root COMMANDS list (S11 item 1). Reuses
|
|
791
|
+
* `renderUsage(main)` for the banner + exit-code table (kept verbatim) +
|
|
792
|
+
* USAGE line + global OPTIONS, then cuts the string before citty's own
|
|
793
|
+
* "COMMANDS" heading (present because `main` has `subCommands`) and appends
|
|
794
|
+
* the grouped sections plus a one-line bundle/ref-grammar tagline and the
|
|
795
|
+
* `akm help agents` pointer.
|
|
796
|
+
*/
|
|
797
|
+
async function renderSectionedRootHelp() {
|
|
798
|
+
const base = await renderUsage(main, undefined);
|
|
799
|
+
const commandsHeadingIndex = base.indexOf("COMMANDS");
|
|
800
|
+
// Cut at the START of the heading's own line, not the word itself — the
|
|
801
|
+
// word is preceded by citty's own ANSI bold/underline escape codes, and
|
|
802
|
+
// slicing mid-line would leave a dangling open escape sequence.
|
|
803
|
+
const cutIndex = commandsHeadingIndex === -1 ? -1 : base.lastIndexOf("\n", commandsHeadingIndex);
|
|
804
|
+
const head = (cutIndex === -1 ? base : base.slice(0, cutIndex)).replace(/\n+$/, "");
|
|
805
|
+
const epilogue = [
|
|
806
|
+
'A "bundle" is your managed directory of assets (skills, agents, memories, workflows, ...). Refs use the ' +
|
|
807
|
+
"grammar [bundle//]conceptId[#fragment], where the concept id is the bundle's own path for the asset — " +
|
|
808
|
+
"e.g. `akm show skills/deploy`, or `akm show work//skills/deploy` for a named bundle. Copy ids from " +
|
|
809
|
+
"`akm search` output rather than synthesizing them.",
|
|
810
|
+
"",
|
|
811
|
+
"Run `akm help <command>` or `akm <command> --help` for details on any command.",
|
|
812
|
+
"Agents: run `akm hints` for the complete guide or `akm help agents` for the short guide.",
|
|
813
|
+
].join("\n");
|
|
814
|
+
return [head, "", renderCommandSections(), "", epilogue].join("\n");
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Walk down the subcommand tree the same way {@link resolveDeepestCittyCommand}
|
|
818
|
+
* does, but stop and report the first token that fails to resolve instead of
|
|
819
|
+
* silently giving up — the attempted spelling plus its sibling candidate set,
|
|
820
|
+
* for the did-you-mean suggestion below. Returns undefined when every token
|
|
821
|
+
* resolved (e.g. "no command specified", or a missing positional/flag on an
|
|
822
|
+
* otherwise-valid command) — there is no unknown NAME to suggest a fix for.
|
|
823
|
+
*/
|
|
824
|
+
function findUnknownCommandAttempt(rawArgs) {
|
|
825
|
+
let cmd = main;
|
|
826
|
+
let args = rawArgs;
|
|
827
|
+
const parentPath = [];
|
|
828
|
+
for (;;) {
|
|
829
|
+
const subCommands = cmd.subCommands;
|
|
830
|
+
if (!subCommands || Object.keys(subCommands).length === 0)
|
|
831
|
+
return undefined;
|
|
832
|
+
const idx = findCittyTopLevelCommandIndex(args, (cmd.args ?? {}));
|
|
833
|
+
const token = idx >= 0 ? args[idx] : undefined;
|
|
834
|
+
if (token === undefined)
|
|
835
|
+
return undefined;
|
|
836
|
+
const sub = findCittySubCommandByName(subCommands, token);
|
|
837
|
+
if (!sub)
|
|
838
|
+
return {
|
|
839
|
+
attempted: token,
|
|
840
|
+
candidates: Object.keys(subCommands),
|
|
841
|
+
parentPath,
|
|
842
|
+
};
|
|
843
|
+
parentPath.push(token);
|
|
844
|
+
cmd = sub;
|
|
845
|
+
args = args.slice(idx + 1);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
/** Closest command within a length-scaled distance threshold (shared DP in cli/unknown-flags.ts). */
|
|
849
|
+
function closestCommandMatch(attempted, candidates) {
|
|
850
|
+
return closestMatch(attempted, candidates, Math.max(2, Math.ceil(attempted.length / 2)));
|
|
851
|
+
}
|
|
852
|
+
const CLI_HELP_POINTER = "Run `akm --help` for usage.";
|
|
853
|
+
/**
|
|
854
|
+
* citty's `CLIError` carries its own stable `.code` (not exported in its
|
|
855
|
+
* types, but present on every instance — see {@link isCittyCliError}'s doc
|
|
856
|
+
* comment): `E_UNKNOWN_COMMAND` for an unrecognized command/subcommand name,
|
|
857
|
+
* `EARG`/`E_NO_COMMAND` for a missing required argument/positional or a bare
|
|
858
|
+
* group with no `run`. Maps that to one of this CLI's own stable
|
|
859
|
+
* `UsageErrorCode`s so the reclassified error (below) carries a real code
|
|
860
|
+
* instead of the generic fallback.
|
|
861
|
+
*/
|
|
862
|
+
function cittyCliErrorUsageCode(error) {
|
|
863
|
+
switch (error.code) {
|
|
864
|
+
case "E_UNKNOWN_COMMAND":
|
|
865
|
+
return "UNKNOWN_COMMAND";
|
|
866
|
+
case "EARG":
|
|
867
|
+
case "E_NO_COMMAND":
|
|
868
|
+
return "MISSING_REQUIRED_ARGUMENT";
|
|
869
|
+
default:
|
|
870
|
+
return "INVALID_FLAG_VALUE";
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* Route a citty `CLIError` through the standard JSON envelope instead of
|
|
875
|
+
* citty's own usage-banner + raw `console.error(message)` (S11 item 3): the
|
|
876
|
+
* one-line diagnosis is the error's own message (e.g. "Unknown command
|
|
877
|
+
* foo"), and the hint is a short pointer — with a did-you-mean suggestion
|
|
878
|
+
* prepended when the unresolved token is close to a real sibling command —
|
|
879
|
+
* rather than the full ~46KB usage dump citty would otherwise print.
|
|
880
|
+
*/
|
|
881
|
+
function toUsageErrorFromCliError(error, rawArgs) {
|
|
882
|
+
const code = cittyCliErrorUsageCode(error);
|
|
883
|
+
const attempt = code === "UNKNOWN_COMMAND" ? findUnknownCommandAttempt(rawArgs) : undefined;
|
|
884
|
+
// Retired spellings from the 0.9 hard break get their replacement, not a
|
|
885
|
+
// did-you-mean: edit distance suggests the WRONG command for most of them
|
|
886
|
+
// (`init`→`info`, `update`→`upgrade`), and agents follow suggestions.
|
|
887
|
+
const retired = attempt ? retiredCommandHint(attempt.parentPath, attempt.attempted) : undefined;
|
|
888
|
+
const suggestion = retired === undefined && attempt ? closestCommandMatch(attempt.attempted, attempt.candidates) : undefined;
|
|
889
|
+
const hint = retired ?? (suggestion ? `Did you mean \`${suggestion}\`? ${CLI_HELP_POINTER}` : CLI_HELP_POINTER);
|
|
890
|
+
// citty colorizes error.message with ANSI escapes even when stdout/stderr
|
|
891
|
+
// is not a TTY. Strip them so the JSON envelope's `error` field is plain
|
|
892
|
+
// text instead of embedding raw escape sequences.
|
|
893
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: intentional — strip ANSI escape codes
|
|
894
|
+
const message = error.message.replace(/\x1b\[[0-9;]*m/g, "");
|
|
895
|
+
return new UsageError(message, code, hint);
|
|
896
|
+
}
|
|
897
|
+
/** Normalize citty's private CLIError for the real entrypoint and in-process test harness. */
|
|
898
|
+
export function normalizeCittyCliError(error, rawArgs) {
|
|
899
|
+
return isCittyCliError(error) ? toUsageErrorFromCliError(error, rawArgs) : error;
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* The CLI's real startup sequence, extracted into a function so error paths
|
|
903
|
+
* can `return` early — top-level `return` is a syntax error in an ES module,
|
|
904
|
+
* and this used to rely on `emitJsonError`'s `never` return type (a
|
|
905
|
+
* synchronous `process.exit`) to stop execution instead. Now that
|
|
906
|
+
* `emitJsonError` (src/cli/shared.ts, R-067) only records `process.exitCode`
|
|
907
|
+
* and returns, every direct call site here needs its own explicit `return;`
|
|
908
|
+
* to stop the rest of startup from running after a fatal early error.
|
|
909
|
+
*/
|
|
910
|
+
async function runCli() {
|
|
911
|
+
try {
|
|
912
|
+
process.argv = consumeSchedulerContextArg(process.argv);
|
|
913
|
+
}
|
|
914
|
+
catch (error) {
|
|
915
|
+
emitJsonError(error);
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
557
918
|
// Mint the ParsedInvocation singleton from the (normalized) argv — the ONE
|
|
558
919
|
// place argv is parsed for the whole process (plan §10.7 / chunk-9 WI-9.9).
|
|
559
920
|
// Every out-of-cli.ts command module reads argv state through
|
|
@@ -573,6 +934,7 @@ if (import.meta.main || process.env.AKM_NODE_ENTRY === "1") {
|
|
|
573
934
|
}
|
|
574
935
|
catch (error) {
|
|
575
936
|
emitJsonError(error);
|
|
937
|
+
return;
|
|
576
938
|
}
|
|
577
939
|
// `--shape summary` is only meaningful on `akm show`. Reject it up front for
|
|
578
940
|
// every other command so a write command (e.g. `akm proposal accept …`)
|
|
@@ -580,24 +942,22 @@ if (import.meta.main || process.env.AKM_NODE_ENTRY === "1") {
|
|
|
580
942
|
// output-shaping time after the side effect has already happened. The
|
|
581
943
|
// shape-registry gate in shapeForCommand() remains as defense-in-depth (and
|
|
582
944
|
// covers the in-process test harness, which skips this startup block).
|
|
583
|
-
const
|
|
945
|
+
const commandPath = resolveCittyCommandPath(main, process.argv.slice(2));
|
|
946
|
+
const topLevelCommand = commandPath[0] ?? findCittyTopLevelCommand(process.argv.slice(2), MAIN_TOP_LEVEL_ARGS);
|
|
584
947
|
if (getOutputMode().shape === "summary" && topLevelCommand !== "show") {
|
|
585
948
|
emitJsonError(new UsageError("'--shape summary' is only valid on 'akm show'.", "INVALID_SHAPE_VALUE"));
|
|
949
|
+
return;
|
|
586
950
|
}
|
|
587
|
-
//
|
|
588
|
-
//
|
|
589
|
-
//
|
|
590
|
-
//
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
fs.rmSync(`${oldIndexPath}-wal`, { force: true });
|
|
598
|
-
warn(`Cleaned up stale 0.7.x index from ${oldIndexPath}. Canonical path is now ${getDbPath()}.`);
|
|
599
|
-
}
|
|
600
|
-
}, "stale 0.7.x index cleanup is non-fatal");
|
|
951
|
+
// D7 — every command that renders through output() honours all six --format
|
|
952
|
+
// values. The declared exempt set (src/output/format-exempt.ts) does not
|
|
953
|
+
// render an envelope at all, so warn rather than pretend: silently ignoring
|
|
954
|
+
// the flag is what made the old md/html behaviour so hard to discover. A
|
|
955
|
+
// warning, not an error, because the flag is harmless here and scripts that
|
|
956
|
+
// pass --format globally to a mixed batch of commands should still work.
|
|
957
|
+
const invocation = getParsedInvocation();
|
|
958
|
+
if ((invocation.hasFlag("--format") || invocation.getFlagValue("--format") !== undefined) &&
|
|
959
|
+
isFormatExemptCommand(commandPath)) {
|
|
960
|
+
warn(`[output] '--format' has no effect on 'akm ${commandPath.join(" ")}' — its output is not a result envelope.`);
|
|
601
961
|
}
|
|
602
962
|
// First-time-user breadcrumb: when run with no subcommand AND no config
|
|
603
963
|
// exists yet AND stderr is a TTY, print a friendly pointer to `akm setup`
|
|
@@ -623,10 +983,88 @@ if (import.meta.main || process.env.AKM_NODE_ENTRY === "1") {
|
|
|
623
983
|
}
|
|
624
984
|
console.error(plainize("👋 First time with akm? Run `akm setup` to get started.\n Docs: https://github.com/itlackey/akm#readme\n"));
|
|
625
985
|
})();
|
|
986
|
+
const rawArgs = process.argv.slice(2);
|
|
626
987
|
try {
|
|
627
|
-
|
|
988
|
+
if (rawArgs.length === 0) {
|
|
989
|
+
process.stdout.write(`${await renderSectionedRootHelp()}\n`);
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
// Mirrors citty's own builtin-flag short-circuit in `runMain` (main's own
|
|
993
|
+
// args never declare `help`/`h`/`version`/`v`, so both stay the fixed
|
|
994
|
+
// defaults citty would have computed too).
|
|
995
|
+
//
|
|
996
|
+
// Scan only akm's OWN arguments: everything after a literal `--` belongs to
|
|
997
|
+
// the child process (`akm env run <ref> -- tool --help`, `akm secret run
|
|
998
|
+
// <ref> -- tool -h`). Scanning the tail printed akm's usage and returned
|
|
999
|
+
// without ever launching the requested command.
|
|
1000
|
+
const passthroughAt = rawArgs.indexOf("--");
|
|
1001
|
+
const ownArgs = passthroughAt === -1 ? rawArgs : rawArgs.slice(0, passthroughAt);
|
|
1002
|
+
if (HELP_FLAGS.some((flag) => ownArgs.includes(flag))) {
|
|
1003
|
+
const resolved = resolveDeepestCittyCommand(main, rawArgs);
|
|
1004
|
+
if (resolved === main) {
|
|
1005
|
+
// Root `--help` (S11 item 1): the sectioned overview, not citty's
|
|
1006
|
+
// flat COMMANDS dump.
|
|
1007
|
+
process.stdout.write(`${await renderSectionedRootHelp()}\n`);
|
|
1008
|
+
}
|
|
1009
|
+
else {
|
|
1010
|
+
const path = resolveCittyCommandPath(main, rawArgs);
|
|
1011
|
+
await showUsage(resolved, buildUsageParentForPath(path));
|
|
1012
|
+
}
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
if (rawArgs.length === 1 && VERSION_FLAGS.includes(rawArgs[0])) {
|
|
1016
|
+
console.log(pkgVersion);
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
// citty's parseArgs (strict: false) silently ignores undeclared flags, so
|
|
1020
|
+
// a typo used to run the command with defaults and exit 0. Checked here, after --help and
|
|
1021
|
+
// --version, so those keep working on any command.
|
|
1022
|
+
assertKnownFlags(main, rawArgs);
|
|
1023
|
+
await runCommand(main, { rawArgs });
|
|
1024
|
+
}
|
|
1025
|
+
catch (error) {
|
|
1026
|
+
if (isCittyCliError(error)) {
|
|
1027
|
+
// R-032/S11: reclassify citty's own "unknown command" / "no command
|
|
1028
|
+
// specified" / "missing required argument" family as USAGE (2) and
|
|
1029
|
+
// route it through the SAME JSON envelope every other command's
|
|
1030
|
+
// failure uses (`emitJsonError`), rather than citty's own usage-banner
|
|
1031
|
+
// + raw `console.error(message)` — a one-line diagnosis plus a short
|
|
1032
|
+
// hint (with a did-you-mean suggestion when applicable), not a ~46KB
|
|
1033
|
+
// usage dump.
|
|
1034
|
+
emitJsonError(normalizeCittyCliError(error, rawArgs));
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
// Anything else escaping here is a genuinely unexpected failure outside
|
|
1038
|
+
// any command's own error handling — every command wraps its body in
|
|
1039
|
+
// `runWithJsonErrors`, `defineJsonCommand`, or `defineGroupCommand`, all
|
|
1040
|
+
// three of which route thrown errors through `emitJsonError` before they
|
|
1041
|
+
// could ever reach this boundary. Route it the same way rather than
|
|
1042
|
+
// hard-coding GENERAL(1): the CLI contract reserves 1 for general/not-found
|
|
1043
|
+
// and requires a non-`AkmError` throw to render the JSON failure envelope
|
|
1044
|
+
// with INTERNAL(70) (AGENTS.md "CLI Contract"), which is what lets
|
|
1045
|
+
// automation tell an internal defect apart from an ordinary failure.
|
|
1046
|
+
// `emitJsonError` classifies and sets `process.exitCode` itself.
|
|
1047
|
+
emitJsonError(error);
|
|
628
1048
|
}
|
|
629
1049
|
finally {
|
|
630
1050
|
await disposeDispatchResources();
|
|
631
1051
|
}
|
|
632
1052
|
}
|
|
1053
|
+
// Only run the CLI when this module is the direct entry point. When it is
|
|
1054
|
+
// imported (e.g. by the in-process test harness in tests/_helpers/cli.ts),
|
|
1055
|
+
// `import.meta.main` is false and we skip all startup side effects (argv
|
|
1056
|
+
// mutation, output-mode init, index cleanup, banner, command dispatch) so
|
|
1057
|
+
// importers can drive the `main` command themselves without the process
|
|
1058
|
+
// exiting.
|
|
1059
|
+
//
|
|
1060
|
+
// Node path: this module carries a `#!/usr/bin/env bun` shebang and is launched
|
|
1061
|
+
// under Node via the `dist/cli-node.mjs` wrapper, which `import()`s this file
|
|
1062
|
+
// (so `import.meta.main` is false here even though the CLI is the real entry).
|
|
1063
|
+
// The wrapper sets `AKM_NODE_ENTRY=1` to opt into the startup block. Compiled
|
|
1064
|
+
// standalone binaries are the same shape: their entry is
|
|
1065
|
+
// `scripts/akm-standalone.ts` (which also embeds the akm-migrate tool), and it
|
|
1066
|
+
// sets `AKM_STANDALONE_ENTRY=1` before importing this file. The test harness
|
|
1067
|
+
// sets neither, so importing cli.ts under Bun stays inert as before.
|
|
1068
|
+
if (import.meta.main || process.env.AKM_NODE_ENTRY === "1" || process.env.AKM_STANDALONE_ENTRY === "1") {
|
|
1069
|
+
await runCli();
|
|
1070
|
+
}
|