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
|
@@ -11,14 +11,11 @@
|
|
|
11
11
|
* `configVersion` is controlled by the config lifecycle. All execution
|
|
12
12
|
* settings use their canonical engine/strategy paths; retired aliases are not
|
|
13
13
|
* rewritten at this boundary.
|
|
14
|
-
* - `parseConfigValue` returns a Partial<AkmConfig> so it can be merged with
|
|
15
|
-
* the runtime config object via `mergeConfigValue`.
|
|
16
14
|
*/
|
|
17
15
|
import { defineGroupCommand, defineJsonCommand, output } from "../cli/shared.js";
|
|
18
16
|
import { resolveStashDir } from "../core/common.js";
|
|
19
17
|
import { DEFAULT_CONFIG, loadConfig, mutateConfig } from "../core/config/config.js";
|
|
20
18
|
import { configGet, configSet, configUnset, unknownKeyHint } from "../core/config/config-walker.js";
|
|
21
|
-
import { UsageError } from "../core/errors.js";
|
|
22
19
|
import { getCacheDir, getConfigPath, getDbPath, getDefaultStashDir } from "../core/paths.js";
|
|
23
20
|
// ── Public API ──────────────────────────────────────────────────────────────
|
|
24
21
|
export function getConfigValue(config, key) {
|
|
@@ -30,25 +27,6 @@ export function setConfigValue(config, key, rawValue) {
|
|
|
30
27
|
export function unsetConfigValue(config, key) {
|
|
31
28
|
return configUnset(config, key);
|
|
32
29
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Compatibility shim: returns a `Partial<AkmConfig>` containing just the
|
|
35
|
-
* change. Older code merged this onto the live config — new code should call
|
|
36
|
-
* `setConfigValue` directly (which returns the full merged config).
|
|
37
|
-
*/
|
|
38
|
-
export function parseConfigValue(key, value) {
|
|
39
|
-
// Use a "marker" base so we can detect which top-level fields actually got
|
|
40
|
-
// touched by the set call. Anything still equal to the marker is untouched.
|
|
41
|
-
const SENTINEL = Symbol("untouched");
|
|
42
|
-
const base = { semanticSearchMode: SENTINEL };
|
|
43
|
-
const next = setConfigValue(base, key, value);
|
|
44
|
-
const patch = {};
|
|
45
|
-
for (const k of Object.keys(next)) {
|
|
46
|
-
if (next[k] !== SENTINEL) {
|
|
47
|
-
patch[k] = next[k];
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return patch;
|
|
51
|
-
}
|
|
52
30
|
export function listConfig(config) {
|
|
53
31
|
// 0.9.0 (spec §10.1): sources live in `bundles` (spread from config); the
|
|
54
32
|
// retired top-level `sources[]` array is no longer surfaced.
|
|
@@ -71,63 +49,28 @@ function redactConfigValue(value) {
|
|
|
71
49
|
export { unknownKeyHint };
|
|
72
50
|
// ── `akm config` command surface ────────────────────────────────────────────
|
|
73
51
|
// Extracted verbatim from src/cli.ts (WS6). The `main.subCommands.config` key
|
|
74
|
-
// and every config subcommand's args/output shape are byte-identical.
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const SKILLS_SH_PROVIDER = "skills-sh";
|
|
83
|
-
function normalizeToggleTarget(target) {
|
|
84
|
-
const normalized = target.trim().toLowerCase();
|
|
85
|
-
if (normalized === "skills.sh" || normalized === "skills-sh")
|
|
86
|
-
return "skills.sh";
|
|
87
|
-
throw new UsageError(`Unsupported target "${target}". Supported targets: skills.sh`);
|
|
88
|
-
}
|
|
89
|
-
function toggleSkillsShRegistry(enabled) {
|
|
90
|
-
let changed = false;
|
|
91
|
-
mutateConfig((config) => {
|
|
92
|
-
const registries = (config.registries ?? DEFAULT_CONFIG.registries ?? []).map((registry) => ({ ...registry }));
|
|
93
|
-
const idx = registries.findIndex((registry) => registry.provider === SKILLS_SH_PROVIDER || registry.name === SKILLS_SH_NAME || registry.url === SKILLS_SH_URL);
|
|
94
|
-
if (idx >= 0) {
|
|
95
|
-
const target = registries[idx];
|
|
96
|
-
const wasEnabled = target.enabled !== false;
|
|
97
|
-
target.enabled = enabled;
|
|
98
|
-
changed = wasEnabled !== enabled;
|
|
99
|
-
return { ...config, registries };
|
|
100
|
-
}
|
|
101
|
-
registries.push({ url: SKILLS_SH_URL, name: SKILLS_SH_NAME, provider: SKILLS_SH_PROVIDER, enabled });
|
|
102
|
-
changed = true;
|
|
103
|
-
return { ...config, registries };
|
|
104
|
-
});
|
|
105
|
-
return { changed, component: SKILLS_SH_NAME, enabled };
|
|
106
|
-
}
|
|
107
|
-
function toggleComponent(targetRaw, enabled) {
|
|
108
|
-
const target = normalizeToggleTarget(targetRaw);
|
|
109
|
-
if (target === "skills.sh")
|
|
110
|
-
return toggleSkillsShRegistry(enabled);
|
|
111
|
-
// normalizeToggleTarget throws for any unsupported target; this is unreachable.
|
|
112
|
-
throw new UsageError(`Unsupported target "${targetRaw}". Supported targets: skills.sh`);
|
|
113
|
-
}
|
|
52
|
+
// and every config subcommand's args/output shape are byte-identical. Leaf
|
|
53
|
+
// handlers whose body is a plain `runWithJsonErrors(() => { … })` are
|
|
54
|
+
// migrated to `defineJsonCommand`, which emits the same JSON envelope
|
|
55
|
+
// (stdout/stderr/exit-code) as the inline form.
|
|
56
|
+
//
|
|
57
|
+
// `akm config enable|disable` (a hardcoded alias for toggling the skills.sh
|
|
58
|
+
// registry) was removed in 0.9.0 (C4). Use `akm registry add|remove`, the
|
|
59
|
+
// general mechanism, instead.
|
|
114
60
|
export const configCommand = defineGroupCommand({
|
|
115
61
|
meta: { name: "config", description: "Show and manage configuration" },
|
|
116
|
-
args: {
|
|
117
|
-
list: { type: "boolean", description: "List current configuration", default: false },
|
|
118
|
-
},
|
|
119
62
|
subCommands: {
|
|
120
63
|
path: defineJsonCommand({
|
|
121
|
-
meta: { name: "path", description: "Show paths to config,
|
|
64
|
+
meta: { name: "path", description: "Show paths to config, bundle, cache, and index" },
|
|
122
65
|
args: {
|
|
123
|
-
all: { type: "boolean", description: "Show all paths (config,
|
|
66
|
+
all: { type: "boolean", description: "Show all paths (config, bundle, cache, index)", default: false },
|
|
124
67
|
},
|
|
125
68
|
run({ args }) {
|
|
126
69
|
const configPath = getConfigPath();
|
|
127
70
|
if (args.all) {
|
|
128
71
|
let stashDir;
|
|
129
72
|
try {
|
|
130
|
-
stashDir = resolveStashDir(
|
|
73
|
+
stashDir = resolveStashDir();
|
|
131
74
|
}
|
|
132
75
|
catch {
|
|
133
76
|
stashDir = `${getDefaultStashDir()} (not initialized)`;
|
|
@@ -135,7 +78,7 @@ export const configCommand = defineGroupCommand({
|
|
|
135
78
|
const cacheDir = getCacheDir();
|
|
136
79
|
const result = {
|
|
137
80
|
config: configPath,
|
|
138
|
-
|
|
81
|
+
bundle: stashDir,
|
|
139
82
|
cache: cacheDir,
|
|
140
83
|
index: getDbPath(),
|
|
141
84
|
};
|
|
@@ -152,16 +95,10 @@ export const configCommand = defineGroupCommand({
|
|
|
152
95
|
output("config", listConfig(loadConfig()));
|
|
153
96
|
},
|
|
154
97
|
}),
|
|
155
|
-
show: defineJsonCommand({
|
|
156
|
-
meta: { name: "show", description: "Alias for `akm config list` — list current configuration" },
|
|
157
|
-
run() {
|
|
158
|
-
output("config", listConfig(loadConfig()));
|
|
159
|
-
},
|
|
160
|
-
}),
|
|
161
98
|
get: defineJsonCommand({
|
|
162
99
|
meta: { name: "get", description: "Get a configuration value by key" },
|
|
163
100
|
args: {
|
|
164
|
-
key: { type: "positional", required: true, description: "Config key (for example: embedding,
|
|
101
|
+
key: { type: "positional", required: true, description: "Config key (for example: embedding, defaultBundle)" },
|
|
165
102
|
},
|
|
166
103
|
run({ args }) {
|
|
167
104
|
output("config", getConfigValue(loadConfig(), args.key));
|
|
@@ -184,22 +121,8 @@ export const configCommand = defineGroupCommand({
|
|
|
184
121
|
description: "Suppress the post-write config dump on stdout. Use from hooks and CI scripts; the write still happens and errors still print.",
|
|
185
122
|
default: false,
|
|
186
123
|
},
|
|
187
|
-
// #463: explicit layer flag for forward-compat. User layer is the only
|
|
188
|
-
// settable layer today; the flag exists so plugin authors can encode
|
|
189
|
-
// intent and the surface stays stable if project-layer writes return.
|
|
190
|
-
layer: {
|
|
191
|
-
type: "string",
|
|
192
|
-
description: "Config layer to write to. Currently only `user` is supported.",
|
|
193
|
-
default: "user",
|
|
194
|
-
},
|
|
195
124
|
},
|
|
196
125
|
run({ args }) {
|
|
197
|
-
if (args.layer && args.layer !== "user") {
|
|
198
|
-
throw new UsageError(`Unsupported --layer "${args.layer}". Only "user" is settable in 0.9.0.`, "INVALID_FLAG_VALUE");
|
|
199
|
-
}
|
|
200
|
-
// Use loadConfig (not loadUserConfig) so the project-config
|
|
201
|
-
// deprecation warning fires consistently with `akm config get`
|
|
202
|
-
// (#457). Effective merged shape is identical post-0.8.0.
|
|
203
126
|
const updated = mutateConfig((current) => setConfigValue(current, args.key, args.value)).config;
|
|
204
127
|
if (!args.silent) {
|
|
205
128
|
output("config", listConfig(updated));
|
|
@@ -215,16 +138,8 @@ export const configCommand = defineGroupCommand({
|
|
|
215
138
|
description: "Suppress the post-write config dump on stdout.",
|
|
216
139
|
default: false,
|
|
217
140
|
},
|
|
218
|
-
layer: {
|
|
219
|
-
type: "string",
|
|
220
|
-
description: "Config layer to write to. Currently only `user` is supported.",
|
|
221
|
-
default: "user",
|
|
222
|
-
},
|
|
223
141
|
},
|
|
224
142
|
run({ args }) {
|
|
225
|
-
if (args.layer && args.layer !== "user") {
|
|
226
|
-
throw new UsageError(`Unsupported --layer "${args.layer}". Only "user" is settable in 0.9.0.`, "INVALID_FLAG_VALUE");
|
|
227
|
-
}
|
|
228
143
|
const result = mutateConfig((current) => unsetConfigValue(current, args.key), { absentNoop: true });
|
|
229
144
|
const updated = result.config;
|
|
230
145
|
if (!args.silent) {
|
|
@@ -232,60 +147,12 @@ export const configCommand = defineGroupCommand({
|
|
|
232
147
|
}
|
|
233
148
|
},
|
|
234
149
|
}),
|
|
235
|
-
validate: defineJsonCommand({
|
|
236
|
-
meta: {
|
|
237
|
-
name: "validate",
|
|
238
|
-
description: "Validate the on-disk config file against the schema. Exits non-zero on errors.",
|
|
239
|
-
},
|
|
240
|
-
async run() {
|
|
241
|
-
const { runConfigValidate } = await import("../cli/config-validate.js");
|
|
242
|
-
await runConfigValidate();
|
|
243
|
-
},
|
|
244
|
-
}),
|
|
245
|
-
migrate: defineJsonCommand({
|
|
246
|
-
meta: {
|
|
247
|
-
name: "migrate",
|
|
248
|
-
description: "Compatibility alias for the canonical top-level migrate status/apply coordinator.",
|
|
249
|
-
},
|
|
250
|
-
args: {
|
|
251
|
-
config: {
|
|
252
|
-
type: "string",
|
|
253
|
-
description: "Path to an operator-prepared current-version config to validate and install",
|
|
254
|
-
},
|
|
255
|
-
dryRun: { type: "boolean", default: false, description: "Validate and report without changing files" },
|
|
256
|
-
},
|
|
257
|
-
async run({ args }) {
|
|
258
|
-
const { runConfigMigrate } = await import("../cli/config-migrate.js");
|
|
259
|
-
await runConfigMigrate({ preparedConfigPath: args.config, dryRun: args.dryRun });
|
|
260
|
-
},
|
|
261
|
-
}),
|
|
262
|
-
enable: defineJsonCommand({
|
|
263
|
-
meta: { name: "enable", description: "Enable an optional component (skills.sh)" },
|
|
264
|
-
args: {
|
|
265
|
-
target: { type: "positional", description: "Component to enable (skills.sh)", required: true },
|
|
266
|
-
},
|
|
267
|
-
run({ args }) {
|
|
268
|
-
const result = toggleComponent(args.target, true);
|
|
269
|
-
output("enable", result);
|
|
270
|
-
},
|
|
271
|
-
}),
|
|
272
|
-
disable: defineJsonCommand({
|
|
273
|
-
meta: { name: "disable", description: "Disable an optional component (skills.sh)" },
|
|
274
|
-
args: {
|
|
275
|
-
target: { type: "positional", description: "Component to disable (skills.sh)", required: true },
|
|
276
|
-
},
|
|
277
|
-
run({ args }) {
|
|
278
|
-
const result = toggleComponent(args.target, false);
|
|
279
|
-
output("disable", result);
|
|
280
|
-
},
|
|
281
|
-
}),
|
|
282
150
|
},
|
|
283
151
|
// The bare `akm config` invocation (and `akm config --list`) dumps the
|
|
284
152
|
// current config. defineGroupCommand short-circuits this body when a
|
|
285
153
|
// registered subcommand ran, so the routing set stays derived from the
|
|
286
|
-
// subCommands map and can never desync
|
|
287
|
-
//
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
},
|
|
154
|
+
// subCommands map and can never desync.
|
|
155
|
+
// No `defaultRun`: bare `akm config` is a usage error (exit 2), the canonical
|
|
156
|
+
// bare-group behavior — owner ruling 12. Run `akm config list` for what the
|
|
157
|
+
// bare form used to print.
|
|
291
158
|
});
|
|
@@ -25,16 +25,16 @@ import { defineGroupCommand, defineJsonCommand, output } from "../../cli/shared.
|
|
|
25
25
|
import { deriveCanonicalAssetName } from "../../core/asset/asset-placement.js";
|
|
26
26
|
import { writeFileAtomic } from "../../core/common.js";
|
|
27
27
|
import { loadConfig } from "../../core/config/config.js";
|
|
28
|
-
import {
|
|
28
|
+
import { makeEnvRef, resolveEnvPath, resolveEnvWriteTarget, withEnvSecretWrite } from "../../core/env-secret-ref.js";
|
|
29
29
|
import { ConfigError, NotFoundError, UsageError } from "../../core/errors.js";
|
|
30
|
-
import { isQuiet } from "../../core/warn.js";
|
|
31
30
|
import { resolveSourceEntries } from "../../indexer/search/search-source.js";
|
|
32
31
|
import { readStdin } from "../../runtime.js";
|
|
33
32
|
import { buildChildEnv } from "./child-env.js";
|
|
33
|
+
import { sensitiveMarkerPath } from "./marker-path.js";
|
|
34
34
|
/**
|
|
35
35
|
* Walk each stash's env files and return one entry per `.env` file, using the
|
|
36
36
|
* env asset spec's canonical-name logic (e.g. `env/team/prod.env` →
|
|
37
|
-
* `env
|
|
37
|
+
* `env/team/prod`, `env/team/.env` → `env/team/default`).
|
|
38
38
|
*/
|
|
39
39
|
function listEnvsRecursive(listKeysFn) {
|
|
40
40
|
const result = [];
|
|
@@ -57,7 +57,7 @@ function listEnvsRecursive(listKeysFn) {
|
|
|
57
57
|
if (!canonical)
|
|
58
58
|
continue;
|
|
59
59
|
// Skip sensitive envs: a sibling .sensitive marker file suppresses listing.
|
|
60
|
-
const markerPath = full
|
|
60
|
+
const markerPath = sensitiveMarkerPath(full, "env");
|
|
61
61
|
if (fs.existsSync(markerPath))
|
|
62
62
|
continue;
|
|
63
63
|
const { keys } = listKeysFn(full);
|
|
@@ -69,7 +69,7 @@ function listEnvsRecursive(listKeysFn) {
|
|
|
69
69
|
return result;
|
|
70
70
|
}
|
|
71
71
|
const envListCommand = defineJsonCommand({
|
|
72
|
-
meta: { name: "list", description: "List all env files across all
|
|
72
|
+
meta: { name: "list", description: "List all env files across all bundles with their key names (no values)" },
|
|
73
73
|
async run() {
|
|
74
74
|
const { listKeys } = await import("./env.js");
|
|
75
75
|
output("env-list", { envs: listEnvsRecursive(listKeys) });
|
|
@@ -99,28 +99,27 @@ const envCreateCommand = defineJsonCommand({
|
|
|
99
99
|
},
|
|
100
100
|
target: {
|
|
101
101
|
type: "string",
|
|
102
|
-
description: "Override the write destination. Accepts a source name from your config; falls back to defaultWriteTarget then the working
|
|
102
|
+
description: "Override the write destination. Accepts a source name from your config; falls back to defaultWriteTarget then the working bundle.",
|
|
103
103
|
},
|
|
104
104
|
},
|
|
105
105
|
async run({ args }) {
|
|
106
106
|
const { createEnv, writeEnv } = await import("./env.js");
|
|
107
107
|
// `create` always targets env/, never the frozen vaults/ copy. `--path` is
|
|
108
108
|
// the subdirectory; `--target` selects the writable destination source.
|
|
109
|
-
const { name, absPath, target } = resolveEnvWriteTarget(args.name, args.target, {
|
|
109
|
+
const { name, absPath, target, ref } = resolveEnvWriteTarget(args.name, args.target, {
|
|
110
110
|
subPath: getStringArg(args, "path"),
|
|
111
111
|
});
|
|
112
|
-
const displaySource = writeTargetDisplaySource(target);
|
|
113
112
|
const fromFile = args["from-file"];
|
|
114
113
|
const fromStdin = args["from-stdin"] === true;
|
|
115
114
|
if (fromFile !== undefined && fromStdin) {
|
|
116
115
|
throw new UsageError("Pass only one of --from-file or --from-stdin.", "INVALID_FLAG_VALUE");
|
|
117
116
|
}
|
|
117
|
+
let content;
|
|
118
118
|
if (fromFile !== undefined || fromStdin) {
|
|
119
119
|
// Ingest path: never silently clobber an existing env file.
|
|
120
120
|
if (fs.existsSync(absPath)) {
|
|
121
|
-
throw new UsageError(`Env "${
|
|
121
|
+
throw new UsageError(`Env "${ref}" already exists. Remove it first (\`akm env remove\`) or edit the file directly.`, "RESOURCE_ALREADY_EXISTS");
|
|
122
122
|
}
|
|
123
|
-
let content;
|
|
124
123
|
if (fromFile !== undefined) {
|
|
125
124
|
if (!fs.existsSync(fromFile)) {
|
|
126
125
|
throw new NotFoundError(`Source file not found: ${fromFile}`, "FILE_NOT_FOUND");
|
|
@@ -132,21 +131,24 @@ const envCreateCommand = defineJsonCommand({
|
|
|
132
131
|
const buf = await readStdin(MAX_ENV_BYTES, () => new UsageError("Env file exceeds 1 MB limit.", "INVALID_FLAG_VALUE"));
|
|
133
132
|
content = buf.toString("utf8");
|
|
134
133
|
}
|
|
135
|
-
writeEnv(absPath, content);
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
createEnv(absPath);
|
|
139
134
|
}
|
|
140
135
|
const written = [absPath];
|
|
136
|
+
const markerPath = sensitiveMarkerPath(absPath, "env");
|
|
141
137
|
if (args.sensitive) {
|
|
142
|
-
const markerPath = absPath.replace(/\.env$/, ".sensitive");
|
|
143
|
-
if (!fs.existsSync(markerPath)) {
|
|
144
|
-
fs.writeFileSync(markerPath, "", { mode: 0o600 });
|
|
145
|
-
}
|
|
146
138
|
written.push(markerPath);
|
|
147
139
|
}
|
|
148
|
-
|
|
149
|
-
|
|
140
|
+
withEnvSecretWrite(target, { type: "env", name }, "Update", written, () => {
|
|
141
|
+
if (content !== undefined)
|
|
142
|
+
writeEnv(absPath, content);
|
|
143
|
+
else
|
|
144
|
+
createEnv(absPath);
|
|
145
|
+
if (args.sensitive) {
|
|
146
|
+
if (!fs.existsSync(markerPath)) {
|
|
147
|
+
writeFileAtomic(markerPath, "", 0o600);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
output("env-create", { ref });
|
|
150
152
|
},
|
|
151
153
|
});
|
|
152
154
|
const envPathCommand = defineJsonCommand({
|
|
@@ -170,6 +172,22 @@ const envPathCommand = defineJsonCommand({
|
|
|
170
172
|
process.stderr.write(`warning: this is the raw file path. Do NOT \`source\` it (shell substitutions in the file would execute).\n` +
|
|
171
173
|
` To inject values run: akm env run ${args.ref} -- <command>\n`);
|
|
172
174
|
}
|
|
175
|
+
// F3/B3: this stdout write IS the payload — a bare absolute path for
|
|
176
|
+
// shell substitution (`$(akm env path <ref>)`, Docker `_FILE` /
|
|
177
|
+
// `--env-file`) — not a field inside a result envelope. `env path` is
|
|
178
|
+
// now declared format-exempt (src/output/format-exempt.ts, same
|
|
179
|
+
// classification as `env run`/`secret run`/`help`), so `--format`
|
|
180
|
+
// WARNS rather than doing anything to this write (src/cli.ts's startup
|
|
181
|
+
// `isFormatExemptCommand` check). An earlier version of this fix routed
|
|
182
|
+
// this through `output()` with a `{ path }` envelope so `--format`
|
|
183
|
+
// "worked" — but the CLI's process-wide default format is `json`, so a
|
|
184
|
+
// bare `akm env path <ref>` (exactly how `$(akm env path foo)` is
|
|
185
|
+
// written, with no explicit `--format`) started emitting
|
|
186
|
+
// `{"path":"..."}` instead of the raw path, breaking every existing
|
|
187
|
+
// shell substitution silently. Declaring the exemption is the correct
|
|
188
|
+
// fix: it keeps this byte-identical to history and makes the
|
|
189
|
+
// already-broken combination (`--format` + this command) loud instead
|
|
190
|
+
// of silent, per STABILITY.md's promise for exempt commands.
|
|
173
191
|
process.stdout.write(`${absPath}\n`);
|
|
174
192
|
},
|
|
175
193
|
});
|
|
@@ -225,7 +243,7 @@ async function runEnvInjected(target, opts) {
|
|
|
225
243
|
}
|
|
226
244
|
if (baseExists) {
|
|
227
245
|
throw new UsageError(`'akm env run' injects the whole file; the single-key '<ref>/${maybeKey}' form was removed.\n` +
|
|
228
|
-
` For one value use a secret: \`akm secret run
|
|
246
|
+
` For one value use a secret: \`akm secret run secrets/${maybeKey} ${maybeKey} -- <command>\`.`, "INVALID_FLAG_VALUE");
|
|
229
247
|
}
|
|
230
248
|
}
|
|
231
249
|
}
|
|
@@ -263,7 +281,15 @@ async function runEnvInjected(target, opts) {
|
|
|
263
281
|
}
|
|
264
282
|
throw err;
|
|
265
283
|
}
|
|
266
|
-
process.exit(result.status ?? 0)
|
|
284
|
+
// R-067: was `process.exit(result.status ?? 0)`, which terminates the
|
|
285
|
+
// process synchronously and skips the `finally { await
|
|
286
|
+
// disposeDispatchResources(); }` block in src/cli.ts's `runCommand` — even
|
|
287
|
+
// on the success path, since this call was unconditional. Setting
|
|
288
|
+
// `process.exitCode` and returning lets cleanup run while still exiting
|
|
289
|
+
// with the child's exact status once the event loop drains, matching the
|
|
290
|
+
// pattern `emitJsonError` (src/cli/shared.ts) already established.
|
|
291
|
+
process.exitCode = result.status ?? 0;
|
|
292
|
+
return;
|
|
267
293
|
}
|
|
268
294
|
/** Parse a comma/space-separated key list flag into a trimmed, non-empty array. */
|
|
269
295
|
function parseKeyListFlag(raw) {
|
|
@@ -280,7 +306,7 @@ const envRunCommand = defineJsonCommand({
|
|
|
280
306
|
name: "run",
|
|
281
307
|
description:
|
|
282
308
|
// biome-ignore lint/suspicious/noTemplateCurlyInString: literal `${secret:NAME}` token syntax documented for users, not interpolation
|
|
283
|
-
"Run a command with the env file injected into its environment: `akm env run <ref> -- <command>`. Use `-- $SHELL` for an interactive session. Restrict which variables are injected with --only / --except. Values may embed `${secret:NAME}` tokens, replaced at run time with the sibling
|
|
309
|
+
"Run a command with the env file injected into its environment: `akm env run <ref> -- <command>`. Use `-- $SHELL` for an interactive session. Restrict which variables are injected with --only / --except. Values may embed `${secret:NAME}` tokens, replaced at run time with the sibling `${secret:NAME}` value from the same bundle. Pass --clean to start the child with a minimal inherited environment instead of the full parent environment.",
|
|
284
310
|
},
|
|
285
311
|
args: {
|
|
286
312
|
target: { type: "positional", description: "Env ref", required: true },
|
|
@@ -315,12 +341,11 @@ const envRemoveCommand = defineJsonCommand({
|
|
|
315
341
|
yes: { type: "boolean", alias: "y", description: "Skip confirmation prompt", default: false },
|
|
316
342
|
target: {
|
|
317
343
|
type: "string",
|
|
318
|
-
description: "Override the write destination. Accepts a source name from your config; falls back to defaultWriteTarget then the working
|
|
344
|
+
description: "Override the write destination. Accepts a source name from your config; falls back to defaultWriteTarget then the working bundle.",
|
|
319
345
|
},
|
|
320
346
|
},
|
|
321
347
|
async run({ args }) {
|
|
322
|
-
const { name, absPath, target } = resolveEnvWriteTarget(args.ref, args.target);
|
|
323
|
-
const displaySource = writeTargetDisplaySource(target);
|
|
348
|
+
const { name, absPath, target, ref } = resolveEnvWriteTarget(args.ref, args.target);
|
|
324
349
|
const { confirmDestructive } = await import("../../cli/confirm.js");
|
|
325
350
|
const confirmed = await confirmDestructive(`Remove env "${args.ref}"? This cannot be undone.`, {
|
|
326
351
|
yes: args.yes === true,
|
|
@@ -330,124 +355,18 @@ const envRemoveCommand = defineJsonCommand({
|
|
|
330
355
|
return;
|
|
331
356
|
}
|
|
332
357
|
if (!fs.existsSync(absPath)) {
|
|
333
|
-
throw new NotFoundError(`Env not found: ${
|
|
358
|
+
throw new NotFoundError(`Env not found: ${ref}`);
|
|
334
359
|
}
|
|
335
360
|
const { removeEnv } = await import("./env.js");
|
|
336
|
-
const removed = removeEnv(absPath);
|
|
337
|
-
|
|
338
|
-
output("env-remove", { ref: makeEnvRef(name, displaySource), removed });
|
|
339
|
-
},
|
|
340
|
-
});
|
|
341
|
-
const envSetCommand = defineJsonCommand({
|
|
342
|
-
meta: {
|
|
343
|
-
name: "set",
|
|
344
|
-
description: "Set (create or update) a single KEY in an env file: `akm env set <ref> <KEY>`. The value is read from stdin by default (never via argv); use --from-env <VAR> or --from-file <path>. Preserves existing comments and key order; the value is never printed. Creates the env file if it does not exist.",
|
|
345
|
-
},
|
|
346
|
-
args: {
|
|
347
|
-
ref: { type: "positional", description: "Env ref (e.g. env:prod or just prod)", required: true },
|
|
348
|
-
key: { type: "positional", description: "Key name to set (e.g. API_URL)", required: true },
|
|
349
|
-
"from-env": { type: "string", description: "Read the value from the named environment variable" },
|
|
350
|
-
"from-file": { type: "string", description: "Read the value from this file" },
|
|
351
|
-
target: {
|
|
352
|
-
type: "string",
|
|
353
|
-
description: "Override the write destination. Accepts a source name from your config; falls back to defaultWriteTarget then the working stash.",
|
|
354
|
-
},
|
|
355
|
-
},
|
|
356
|
-
async run({ args }) {
|
|
357
|
-
const { name, absPath, target } = resolveEnvWriteTarget(args.ref, args.target);
|
|
358
|
-
const displaySource = writeTargetDisplaySource(target);
|
|
359
|
-
const key = String(args.key);
|
|
360
|
-
const { ENV_KEY_RE, setEnvKey } = await import("./env.js");
|
|
361
|
-
if (!ENV_KEY_RE.test(key)) {
|
|
362
|
-
throw new UsageError(`Invalid env key "${key}". Keys match [A-Za-z_][A-Za-z0-9_]*.`, "INVALID_FLAG_VALUE");
|
|
363
|
-
}
|
|
364
|
-
const fromEnv = args["from-env"];
|
|
365
|
-
const fromFile = args["from-file"];
|
|
366
|
-
if (fromEnv !== undefined && fromFile !== undefined) {
|
|
367
|
-
throw new UsageError("Pass only one of --from-file or --from-env (or use stdin).", "INVALID_FLAG_VALUE");
|
|
368
|
-
}
|
|
369
|
-
const MAX_ENV_VALUE_BYTES = 1024 * 1024; // 1 MB
|
|
370
|
-
let value;
|
|
371
|
-
if (fromFile !== undefined) {
|
|
372
|
-
if (!fs.existsSync(fromFile)) {
|
|
373
|
-
throw new NotFoundError(`File not found: ${fromFile}`, "FILE_NOT_FOUND");
|
|
374
|
-
}
|
|
375
|
-
const buf = fs.readFileSync(fromFile);
|
|
376
|
-
if (buf.byteLength > MAX_ENV_VALUE_BYTES)
|
|
377
|
-
throw new UsageError("Value exceeds the 1 MB limit.");
|
|
378
|
-
value = buf.toString("utf8");
|
|
379
|
-
}
|
|
380
|
-
else if (fromEnv !== undefined) {
|
|
381
|
-
const v = process.env[fromEnv];
|
|
382
|
-
if (v === undefined) {
|
|
383
|
-
throw new UsageError(`Environment variable "${fromEnv}" is not set.`, "INVALID_FLAG_VALUE");
|
|
384
|
-
}
|
|
385
|
-
value = v;
|
|
386
|
-
}
|
|
387
|
-
else {
|
|
388
|
-
const buf = await readStdin(MAX_ENV_VALUE_BYTES, () => new UsageError("Value exceeds the 1 MB limit."));
|
|
389
|
-
// Strip a single trailing newline so `echo "$VAL" | akm env set` is exact.
|
|
390
|
-
value = buf.toString("utf8").replace(/\n$/, "");
|
|
391
|
-
}
|
|
392
|
-
setEnvKey(absPath, key, value);
|
|
393
|
-
commitEnvSecretWrite(target, { type: "env", name }, "Update", [absPath]);
|
|
394
|
-
// Warn (never block) on process-hijacking key names, matching the env-run audit.
|
|
395
|
-
const { isDangerousEnvKey } = await import("../lint/env-key-rules.js");
|
|
396
|
-
if (isDangerousEnvKey(key) && !isQuiet()) {
|
|
397
|
-
process.stderr.write(`warning: "${key}" can influence process execution when this env is loaded via 'akm env run'.\n`);
|
|
398
|
-
}
|
|
399
|
-
output("env-set", { ref: makeEnvRef(name, displaySource), key });
|
|
400
|
-
},
|
|
401
|
-
});
|
|
402
|
-
const envUnsetCommand = defineJsonCommand({
|
|
403
|
-
meta: {
|
|
404
|
-
name: "unset",
|
|
405
|
-
description: "Remove one or more KEYs from an env file: `akm env unset <ref> <KEY...>`. Preserves other keys and comments. To remove the whole file, use `akm env remove`.",
|
|
406
|
-
},
|
|
407
|
-
args: {
|
|
408
|
-
ref: { type: "positional", description: "Env ref (e.g. env:prod or just prod)", required: true },
|
|
409
|
-
// `key` is read from the raw positionals (one or more) in run(); declared
|
|
410
|
-
// non-required so citty doesn't block before we emit a structured error.
|
|
411
|
-
key: { type: "positional", description: "Key name(s) to remove (one or more)", required: false },
|
|
412
|
-
target: {
|
|
413
|
-
type: "string",
|
|
414
|
-
description: "Override the write destination. Accepts a source name from your config; falls back to defaultWriteTarget then the working stash.",
|
|
415
|
-
},
|
|
416
|
-
},
|
|
417
|
-
async run({ args }) {
|
|
418
|
-
const { name, absPath, target } = resolveEnvWriteTarget(args.ref, args.target);
|
|
419
|
-
const displaySource = writeTargetDisplaySource(target);
|
|
420
|
-
if (!fs.existsSync(absPath)) {
|
|
421
|
-
throw new NotFoundError(`Env not found: ${makeEnvRef(name, displaySource)}`);
|
|
422
|
-
}
|
|
423
|
-
// citty puts every positional in `args._` (incl. the ref at [0]); the keys
|
|
424
|
-
// are the remaining positionals. citty also mis-captures the space-separated
|
|
425
|
-
// value of a global flag (`--format json`) as a positional, so drop any
|
|
426
|
-
// token that is actually a global flag's value (cli.ts:1335 documents this).
|
|
427
|
-
const invocation = getParsedInvocation();
|
|
428
|
-
const globalFlagValues = new Set(["--format", "--shape", "--detail", "--scope", "--filter", "--target"]
|
|
429
|
-
.map((flag) => invocation.getFlagValue(flag))
|
|
430
|
-
.filter((v) => typeof v === "string"));
|
|
431
|
-
const keys = (Array.isArray(args._) ? args._.map(String) : [])
|
|
432
|
-
.slice(1)
|
|
433
|
-
.filter((k) => !globalFlagValues.has(k));
|
|
434
|
-
if (keys.length === 0) {
|
|
435
|
-
throw new UsageError("Usage: akm env unset <ref> <KEY...> (one or more keys).", "MISSING_REQUIRED_ARGUMENT");
|
|
436
|
-
}
|
|
437
|
-
const { ENV_KEY_RE, unsetEnvKeys } = await import("./env.js");
|
|
438
|
-
const invalid = keys.filter((k) => !ENV_KEY_RE.test(k));
|
|
439
|
-
if (invalid.length > 0) {
|
|
440
|
-
throw new UsageError(`Invalid env key(s): ${invalid.join(", ")}.`, "INVALID_FLAG_VALUE");
|
|
441
|
-
}
|
|
442
|
-
const { removed, missing } = unsetEnvKeys(absPath, keys);
|
|
443
|
-
commitEnvSecretWrite(target, { type: "env", name }, "Update", [absPath]);
|
|
444
|
-
output("env-unset", { ref: makeEnvRef(name, displaySource), removed, missing });
|
|
361
|
+
const removed = withEnvSecretWrite(target, { type: "env", name }, "Remove", [absPath, sensitiveMarkerPath(absPath, "env")], () => removeEnv(absPath));
|
|
362
|
+
output("env-remove", { ref, removed });
|
|
445
363
|
},
|
|
446
364
|
});
|
|
447
365
|
export const envCommand = defineGroupCommand({
|
|
448
366
|
meta: {
|
|
449
367
|
name: "env",
|
|
450
|
-
description: "Manage `.env` files —
|
|
368
|
+
description: "Manage `.env` files — configuration values an app loads together (URLs, flags, and any credentials it needs).\n\n" +
|
|
369
|
+
"Values may or may not be sensitive; akm protects them all the same way — key names are visible, values never appear in structured output. For a single sensitive value used on its own (an auth token, key, or cert), use `akm secret`.",
|
|
451
370
|
},
|
|
452
371
|
subCommands: {
|
|
453
372
|
list: envListCommand,
|
|
@@ -455,12 +374,9 @@ export const envCommand = defineGroupCommand({
|
|
|
455
374
|
export: envExportCommand,
|
|
456
375
|
run: envRunCommand,
|
|
457
376
|
create: envCreateCommand,
|
|
458
|
-
set: envSetCommand,
|
|
459
|
-
unset: envUnsetCommand,
|
|
460
377
|
remove: envRemoveCommand,
|
|
461
378
|
},
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
},
|
|
379
|
+
// No `defaultRun`: bare `akm env` is a usage error (exit 2), the canonical
|
|
380
|
+
// bare-group behavior — owner ruling 12. Run `akm env list` for what the
|
|
381
|
+
// bare form used to print.
|
|
466
382
|
});
|