akm-cli 0.9.0-rc.0 → 0.9.0-rc.13
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 +1283 -22
- package/README.md +62 -37
- package/SECURITY.md +46 -31
- package/dist/akm +162 -38
- package/dist/akm-migrate +44 -0
- package/dist/assets/backends/schtasks-template.xml +2 -1
- package/dist/assets/hints/cli-hints-full.md +268 -118
- package/dist/assets/hints/cli-hints-short.md +87 -24
- package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
- package/dist/assets/improve-strategies/frequent.json +15 -0
- package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
- package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
- package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
- package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
- package/dist/assets/improve-strategies/reflect-distill.json +30 -0
- package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +5 -5
- package/dist/assets/prompts/extract-session.md +2 -6
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
- package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
- package/dist/assets/prompts/reflect-output-repair.md +3 -0
- package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
- package/dist/assets/stash-skeleton/README.md +38 -10
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
- package/dist/assets/tasks/core/extract.yml +3 -2
- package/dist/assets/tasks/core/improve.yml +2 -1
- package/dist/assets/tasks/core/index-refresh.yml +1 -0
- package/dist/assets/tasks/core/sync.yml +1 -0
- package/dist/assets/tasks/core/version-check.yml +2 -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 +5 -4
- package/dist/assets/workflows/workflow-template.md +31 -15
- package/dist/cli/invocation.js +279 -0
- package/dist/cli/parse-args.js +5 -90
- package/dist/cli/retired-commands.js +78 -0
- package/dist/cli/shared.js +158 -48
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +747 -293
- package/dist/commands/agent/agent-dispatch.js +19 -18
- package/dist/commands/agent/agent-support.js +0 -24
- package/dist/commands/agent/contribute-cli.js +43 -97
- package/dist/commands/completions.js +80 -23
- package/dist/commands/config-cli.js +44 -281
- package/dist/commands/env/env-binding.js +99 -0
- package/dist/commands/env/env-cli.js +84 -224
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +45 -61
- package/dist/commands/env/secret.js +32 -62
- package/dist/commands/feedback-cli.js +179 -85
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +7 -8
- package/dist/commands/health/checks.js +279 -94
- package/dist/commands/health/html-report.js +197 -578
- package/dist/commands/health/improve-metrics.js +277 -246
- package/dist/commands/health/llm-usage.js +19 -19
- package/dist/commands/health/md-report.js +16 -7
- package/dist/commands/health/metrics.js +67 -32
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +508 -0
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +16 -56
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
- package/dist/commands/health/types-improve.js +29 -0
- package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
- package/dist/commands/health/types-result.js +7 -0
- package/dist/commands/health/types-runs.js +4 -0
- package/dist/commands/health/types-session-log.js +4 -0
- package/dist/commands/health/types-windows.js +4 -0
- package/dist/commands/health/types.js +26 -21
- package/dist/commands/health/windows.js +2 -3
- package/dist/commands/health.js +296 -167
- package/dist/commands/improve/anti-collapse.js +5 -5
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +65 -52
- package/dist/commands/improve/consolidate/chunking.js +9 -7
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +454 -1354
- package/dist/commands/improve/content-hash.js +39 -0
- package/dist/commands/improve/distill/content-repair.js +4 -10
- package/dist/commands/improve/distill/promote-memory.js +89 -64
- package/dist/commands/improve/distill/quality-gate.js +118 -42
- package/dist/commands/improve/distill-guards.js +1 -1
- package/dist/commands/improve/distill-promotion-policy.js +33 -888
- package/dist/commands/improve/distill.js +607 -363
- package/dist/commands/improve/eligibility.js +165 -79
- package/dist/commands/improve/extract-cli.js +35 -126
- package/dist/commands/improve/extract-prompt.js +6 -35
- package/dist/commands/improve/extract.js +640 -391
- package/dist/commands/improve/feedback-valence.js +2 -12
- package/dist/commands/improve/improve-cli.js +134 -135
- package/dist/commands/improve/improve-result-file.js +30 -50
- package/dist/commands/improve/improve-run-types.js +4 -0
- package/dist/commands/improve/improve-strategies.js +135 -0
- package/dist/commands/improve/improve.js +904 -701
- package/dist/commands/improve/locks.js +64 -111
- package/dist/commands/improve/loop-stages.js +1110 -923
- package/dist/commands/improve/memory/derived-ref.js +124 -0
- package/dist/commands/improve/memory/memory-belief.js +79 -7
- package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
- package/dist/commands/improve/memory/memory-improve.js +25 -37
- package/dist/commands/improve/outcome-loop.js +25 -88
- package/dist/commands/improve/preparation.js +1034 -813
- package/dist/commands/improve/proactive-maintenance.js +34 -9
- package/dist/commands/improve/proposal-envelope.js +31 -0
- package/dist/commands/improve/reflect.js +983 -794
- package/dist/commands/improve/run-context.js +119 -0
- package/dist/commands/improve/salience.js +24 -127
- package/dist/commands/improve/session-asset.js +7 -3
- package/dist/commands/improve/shared.js +14 -34
- package/dist/commands/improve/source-identity.js +28 -0
- package/dist/commands/improve/triage.js +20 -17
- package/dist/commands/lint/base-linter.js +340 -313
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +185 -30
- package/dist/commands/{events.js → log.js} +28 -38
- package/dist/commands/migrate-cli.js +54 -0
- package/dist/commands/migration-tool.js +55 -0
- package/dist/commands/observability-cli.js +70 -208
- package/dist/commands/proposal/diff-format.js +50 -0
- package/dist/commands/proposal/drain-policies.js +0 -6
- package/dist/commands/proposal/drain.js +91 -40
- package/dist/commands/proposal/proposal-cli.js +134 -132
- package/dist/commands/proposal/proposal-types.js +56 -0
- package/dist/commands/proposal/proposal.js +83 -65
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +105 -88
- package/dist/commands/proposal/repository.js +1303 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
- package/dist/commands/proposal/validators/proposal-validators.js +61 -12
- package/dist/commands/proposal/validators/proposals.js +6 -8
- package/dist/commands/read/curate.js +78 -73
- package/dist/commands/read/knowledge.js +510 -13
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +84 -15
- package/dist/commands/read/search-cli.js +203 -96
- package/dist/commands/read/search.js +126 -94
- package/dist/commands/read/show.js +226 -250
- package/dist/commands/registry-cli.js +34 -60
- package/dist/commands/remember.js +18 -57
- package/dist/commands/sources/add-cli.js +104 -49
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +63 -0
- package/dist/commands/sources/info.js +27 -15
- package/dist/commands/sources/init.js +30 -40
- package/dist/commands/sources/installed-stashes.js +469 -172
- package/dist/commands/sources/migration-help.js +7 -4
- package/dist/commands/sources/schema-repair.js +10 -9
- package/dist/commands/sources/self-update.js +182 -121
- package/dist/commands/sources/source-add.js +169 -178
- package/dist/commands/sources/source-clone.js +144 -41
- package/dist/commands/sources/source-manage.js +94 -59
- package/dist/commands/sources/sources-cli.js +64 -205
- package/dist/commands/sources/stash-cli.js +91 -54
- package/dist/commands/sources/stash-skeleton.js +1 -1
- package/dist/commands/tasks/tasks-cli.js +106 -104
- package/dist/commands/tasks/tasks.js +445 -262
- package/dist/commands/workflow-cli.js +232 -121
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/activation-policy.js +49 -0
- package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
- package/dist/core/adapter/adapters/akm-adapter.js +528 -0
- package/dist/core/adapter/adapters/akm-lint.js +392 -0
- package/dist/core/adapter/adapters/akm-metadata.js +387 -0
- package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
- package/dist/core/adapter/adapters/claude-adapter.js +61 -0
- package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
- package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
- package/dist/core/adapter/adapters/index.js +80 -0
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
- package/dist/core/adapter/adapters/okf-adapter.js +391 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
- package/dist/core/adapter/adapters/shared.js +286 -0
- package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
- package/dist/core/adapter/bundle-adapter.js +4 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +44 -0
- package/dist/core/adapter/registry.js +56 -0
- package/dist/core/adapter/types.js +4 -0
- package/dist/core/asset/akm-markdown.js +30 -0
- package/dist/core/asset/asset-placement.js +243 -0
- package/dist/core/asset/asset-ref.js +110 -79
- package/dist/core/asset/asset-serialize.js +20 -0
- package/dist/core/asset/frontmatter.js +28 -12
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +274 -0
- package/dist/core/asset/stash-meta.js +2 -2
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +281 -86
- package/dist/core/config/config-io.js +42 -128
- package/dist/core/config/config-schema.js +233 -834
- package/dist/core/config/config-sources.js +162 -39
- package/dist/core/config/config-types.js +16 -11
- package/dist/core/config/config-version.js +29 -0
- package/dist/core/config/config-walker.js +126 -37
- package/dist/core/config/config.js +154 -331
- package/dist/core/config/deep-merge.js +41 -0
- package/dist/core/config/engine-semantics.js +28 -0
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +38 -0
- package/dist/core/config/schema/engines.js +116 -0
- package/dist/core/config/schema/experimental.js +47 -0
- package/dist/core/config/schema/feedback.js +31 -0
- package/dist/core/config/schema/improve-processes.js +389 -0
- package/dist/core/config/schema/improve.js +94 -0
- package/dist/core/config/schema/index-config.js +176 -0
- package/dist/core/config/schema/output.js +18 -0
- package/dist/core/config/schema/primitives.js +94 -0
- package/dist/core/config/schema/search.js +30 -0
- package/dist/core/config/schema/setup.js +18 -0
- package/dist/core/config/schema/sources-bundles.js +169 -0
- package/dist/core/config/schema/workflow.js +29 -0
- package/dist/core/env-secret-ref.js +155 -20
- package/dist/core/errors.js +17 -15
- package/dist/core/events-types.js +4 -0
- package/dist/core/events.js +46 -128
- package/dist/core/extra-params.js +62 -0
- package/dist/core/file-change.js +17 -0
- package/dist/core/file-lock.js +202 -57
- package/dist/core/fs-txn.js +392 -0
- package/dist/core/git-message.js +59 -0
- package/dist/core/improve-result.js +167 -0
- package/dist/core/json-schema.js +142 -0
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +1 -1
- package/dist/core/maintenance-barrier.js +135 -0
- package/dist/core/migration-operation.js +44 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/paths.js +22 -25
- package/dist/core/platform.js +10 -0
- package/dist/core/recognition-util.js +128 -0
- package/dist/core/redaction.js +392 -0
- package/dist/core/standards/resolve-standards-context.js +36 -65
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +5 -5
- package/dist/core/state/migrations.js +242 -11
- package/dist/core/state-db.js +98 -10
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +303 -0
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/time.js +20 -0
- package/dist/core/type-presentation.js +130 -0
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +834 -118
- package/dist/indexer/bundle-identity-guard.js +92 -0
- package/dist/indexer/db/graph-db.js +1 -25
- package/dist/indexer/db/llm-cache.js +1 -1
- package/dist/indexer/ensure-index.js +30 -9
- package/dist/indexer/graph/graph-boost.js +9 -30
- package/dist/indexer/graph/graph-extraction.js +41 -27
- package/dist/indexer/graph/graph-types.js +4 -0
- package/dist/indexer/index-writer-lock.js +93 -49
- package/dist/indexer/index-written-assets.js +100 -53
- package/dist/indexer/indexer.js +746 -329
- package/dist/indexer/init.js +18 -25
- package/dist/indexer/installations.js +142 -0
- package/dist/indexer/passes/dir-staleness.js +18 -10
- package/dist/indexer/passes/memory-inference.js +25 -15
- package/dist/indexer/passes/metadata.js +412 -243
- package/dist/indexer/scan/doc-to-entry.js +160 -0
- package/dist/indexer/scan/drain-dir.js +134 -0
- package/dist/indexer/search/db-search.js +292 -108
- package/dist/indexer/search/fts-query.js +64 -0
- package/dist/indexer/search/ranking-contributors.js +145 -25
- package/dist/indexer/search/ranking-types.js +4 -0
- package/dist/indexer/search/ranking.js +28 -71
- package/dist/indexer/search/search-attribution.js +67 -0
- package/dist/indexer/search/search-fields.js +18 -3
- package/dist/indexer/search/search-hit-enrichers.js +30 -40
- package/dist/indexer/search/search-source.js +157 -111
- package/dist/indexer/search/semantic-status.js +4 -1
- package/dist/indexer/usage/usage-events.js +10 -30
- package/dist/indexer/walk/file-context.js +3 -45
- package/dist/indexer/walk/matchers.js +42 -34
- package/dist/indexer/walk/path-resolver.js +11 -5
- package/dist/indexer/walk/walker.js +42 -14
- package/dist/integrations/agent/builder-shared.js +7 -0
- package/dist/integrations/agent/builders.js +5 -56
- package/dist/integrations/agent/config.js +3 -143
- package/dist/integrations/agent/detect.js +17 -2
- package/dist/integrations/agent/engine-resolution.js +231 -0
- package/dist/integrations/agent/index.js +1 -2
- package/dist/integrations/agent/model-aliases.js +16 -2
- package/dist/integrations/agent/profiles.js +36 -62
- package/dist/integrations/agent/prompts.js +46 -18
- package/dist/integrations/agent/runner-dispatch.js +93 -4
- package/dist/integrations/agent/runner.js +76 -208
- package/dist/integrations/agent/spawn.js +88 -196
- package/dist/integrations/harnesses/aider/agent-builder.js +114 -0
- package/dist/integrations/harnesses/aider/index.js +48 -0
- package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
- package/dist/integrations/harnesses/amazonq/agent-builder.js +147 -0
- package/dist/integrations/harnesses/amazonq/index.js +45 -0
- package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
- package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
- package/dist/integrations/harnesses/claude/config-import.js +1 -3
- package/dist/integrations/harnesses/claude/index.js +24 -35
- package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
- package/dist/integrations/harnesses/claude/session-log.js +27 -75
- package/dist/integrations/harnesses/codex/agent-builder.js +138 -0
- package/dist/integrations/harnesses/codex/index.js +52 -0
- package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
- package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
- package/dist/integrations/harnesses/copilot/index.js +48 -0
- package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
- package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
- package/dist/integrations/harnesses/gemini/index.js +48 -0
- package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
- package/dist/integrations/harnesses/ids.js +24 -0
- package/dist/integrations/harnesses/index.js +54 -34
- package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
- package/dist/integrations/harnesses/opencode/config-import.js +1 -3
- package/dist/integrations/harnesses/opencode/index.js +14 -32
- package/dist/integrations/harnesses/opencode/session-log.js +67 -125
- package/dist/integrations/harnesses/opencode-sdk/harness.js +51 -0
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
- package/dist/integrations/harnesses/openhands/agent-builder.js +128 -0
- package/dist/integrations/harnesses/openhands/index.js +48 -0
- package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
- package/dist/integrations/harnesses/pi/agent-builder.js +97 -0
- package/dist/integrations/harnesses/pi/index.js +45 -0
- package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
- package/dist/integrations/harnesses/shared.js +17 -0
- package/dist/integrations/harnesses/types.js +43 -32
- package/dist/integrations/lockfile.js +211 -24
- package/dist/integrations/session-logs/index.js +36 -39
- package/dist/integrations/session-logs/provider-base.js +113 -0
- package/dist/llm/client.js +182 -110
- package/dist/llm/embedders/deterministic.js +2 -2
- package/dist/llm/embedders/remote.js +21 -9
- package/dist/llm/feature-gate.js +17 -57
- package/dist/llm/graph-extract.js +12 -13
- package/dist/llm/index-passes.js +8 -42
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +45 -30
- package/dist/llm/structured-call.js +16 -8
- package/dist/llm/usage-persist.js +30 -5
- package/dist/llm/usage-telemetry.js +59 -6
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/command-registry.js +27 -0
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +251 -0
- package/dist/output/html-render.js +11 -16
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -279
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +58 -84
- package/dist/output/shapes/passthrough.js +11 -39
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes/registry.js +12 -6
- package/dist/output/shapes.js +0 -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 +562 -0
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/helpers.js +15 -1164
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +202 -0
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/registry.js +12 -6
- package/dist/output/text/show-directives.js +117 -0
- package/dist/output/text/show-format.js +103 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +332 -0
- package/dist/output/text/workflow.js +3 -2
- package/dist/output/text.js +10 -19
- 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 +15 -25
- package/dist/registry/resolve.js +43 -94
- package/dist/registry/semver.js +43 -0
- package/dist/runtime.js +81 -12
- package/dist/scripts/akm-migrate.js +35529 -0
- package/dist/setup/detect.js +5 -7
- package/dist/setup/detected-engines.js +136 -0
- package/dist/setup/engine-config.js +100 -0
- package/dist/setup/registry-stash-loader.js +3 -3
- package/dist/setup/semantic-assets.js +12 -9
- package/dist/setup/setup.js +444 -208
- package/dist/setup/steps/connection-shared.js +120 -0
- package/dist/setup/steps/connection.js +108 -305
- package/dist/setup/steps/platforms.js +13 -12
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +21 -15
- package/dist/setup/steps/stashdir.js +6 -4
- package/dist/setup/steps/tasks.js +236 -119
- package/dist/setup/steps.js +3 -2
- package/dist/sources/freshness.js +39 -0
- 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 +54 -56
- package/dist/sources/providers/git-stash.js +420 -91
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +47 -22
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +11 -10
- package/dist/sources/snapshot-fetchers/types.js +4 -0
- package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
- package/dist/storage/database.js +60 -4
- package/dist/storage/engines/sqlite-migrations.js +156 -5
- package/dist/storage/locations.js +1 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +51 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -32
- package/dist/storage/repositories/index-connection.js +79 -0
- package/dist/storage/repositories/index-db.js +4 -3
- package/dist/storage/repositories/index-entries-repository.js +863 -0
- package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
- package/dist/storage/repositories/index-entry-types.js +4 -0
- package/dist/storage/repositories/index-fts-repository.js +167 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
- package/dist/storage/repositories/index-meta-repository.js +49 -0
- package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
- package/dist/storage/repositories/index-sql.js +12 -0
- package/dist/storage/repositories/index-utility-repository.js +356 -0
- package/dist/storage/repositories/index-vec-repository.js +250 -0
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +317 -75
- package/dist/storage/repositories/registry-cache.js +1 -1
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +110 -3
- package/dist/storage/repositories/workflow-runs-repository.js +240 -19
- package/dist/tasks/backends/cron.js +169 -46
- package/dist/tasks/backends/exec-utils.js +76 -3
- package/dist/tasks/backends/index.js +6 -9
- package/dist/tasks/backends/launchd.js +292 -55
- package/dist/tasks/backends/schtasks.js +557 -70
- package/dist/tasks/backends/types.js +4 -0
- package/dist/tasks/command-executable.js +93 -0
- package/dist/tasks/embedded.js +56 -38
- package/dist/tasks/parser.js +156 -64
- package/dist/tasks/resolve-akm-bin.js +144 -51
- package/dist/tasks/runner.js +377 -209
- package/dist/tasks/schedule.js +108 -19
- package/dist/tasks/scheduler-invocation.js +296 -0
- package/dist/tasks/schema.js +1 -1
- package/dist/tasks/task-id.js +35 -0
- package/dist/tasks/validator.js +30 -16
- package/dist/text-import-hook.mjs +1 -1
- package/dist/workflows/authoring/authoring.js +104 -43
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/cli.js +0 -16
- package/dist/workflows/concurrency-policy.js +15 -0
- package/dist/workflows/exec/brief.js +450 -0
- package/dist/workflows/exec/frozen-judge.js +47 -0
- package/dist/workflows/exec/native-executor.js +1038 -0
- package/dist/workflows/exec/param-secrets.js +115 -0
- package/dist/workflows/exec/report.js +1460 -0
- package/dist/workflows/exec/run-workflow.js +602 -0
- package/dist/workflows/exec/scheduler.js +71 -0
- package/dist/workflows/exec/step-work.js +1190 -0
- package/dist/workflows/exec/unit-writer.js +23 -0
- package/dist/workflows/exec/workflow-engine-gate.js +67 -0
- package/dist/workflows/exec/worktree.js +171 -0
- package/dist/workflows/ir/compile.js +246 -0
- package/dist/workflows/ir/freeze.js +233 -0
- package/dist/workflows/ir/params.js +54 -0
- package/dist/workflows/ir/plan-hash.js +68 -0
- package/dist/workflows/ir/schema.js +540 -0
- package/dist/workflows/parser.js +878 -304
- package/dist/workflows/program/expressions.js +181 -0
- package/dist/workflows/program/schema.js +51 -0
- package/dist/workflows/renderer.js +100 -45
- package/dist/workflows/resource-limits.js +22 -0
- package/dist/workflows/runtime/agent-identity.js +59 -14
- package/dist/workflows/runtime/checkin.js +1 -1
- package/dist/workflows/runtime/plan-classifier.js +131 -0
- package/dist/workflows/runtime/runs.js +376 -119
- package/dist/workflows/runtime/unit-checkin.js +45 -0
- package/dist/workflows/runtime/unit-phases.js +20 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +241 -40
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +2 -3
- package/dist/workflows/validator.js +52 -30
- package/docs/README.md +42 -78
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +9 -8
- package/docs/migration/release-notes/0.9.0.md +158 -14
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +844 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/data-and-telemetry.md +333 -0
- package/package.json +21 -17
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +4636 -0
- package/schemas/akm-task.json +87 -0
- package/schemas/akm-workflow.json +373 -0
- package/dist/akm-migrate-storage +0 -38
- package/dist/assets/help/help-accept.md +0 -12
- package/dist/assets/help/help-improve.md +0 -84
- package/dist/assets/help/help-proposals.md +0 -17
- package/dist/assets/help/help-propose.md +0 -17
- package/dist/assets/help/help-reject.md +0 -11
- package/dist/assets/profiles/frequent.json +0 -13
- package/dist/assets/profiles/recombine-only.json +0 -21
- package/dist/assets/profiles/reflect-distill.json +0 -30
- package/dist/assets/profiles/synthesize.json +0 -15
- package/dist/assets/prompts/procedural-system.md +0 -44
- package/dist/assets/prompts/recombine-system.md +0 -40
- package/dist/assets/prompts/staleness-detect-system.md +0 -6
- package/dist/assets/tasks/core/backup.yml +0 -4
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/assets/templates/html/default.html +0 -78
- package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
- package/dist/assets/wiki/index-template.md +0 -12
- package/dist/assets/wiki/ingest-workflow-template.md +0 -83
- package/dist/assets/wiki/log-template.md +0 -8
- package/dist/assets/wiki/schema-template.md +0 -61
- package/dist/cli/config-migrate.js +0 -150
- package/dist/cli/config-validate.js +0 -39
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -487
- package/dist/commands/improve/calibration.js +0 -161
- package/dist/commands/improve/dedup.js +0 -482
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/improve/hot-probation.js +0 -45
- package/dist/commands/improve/improve-auto-accept.js +0 -276
- package/dist/commands/improve/improve-profiles.js +0 -168
- package/dist/commands/improve/procedural.js +0 -398
- package/dist/commands/improve/recombine.js +0 -818
- package/dist/commands/improve/schema-similarity-gate.js +0 -168
- package/dist/commands/lint/agent-linter.js +0 -44
- package/dist/commands/lint/command-linter.js +0 -44
- package/dist/commands/lint/default-linter.js +0 -16
- package/dist/commands/lint/fact-linter.js +0 -39
- package/dist/commands/lint/knowledge-linter.js +0 -16
- package/dist/commands/lint/memory-linter.js +0 -61
- package/dist/commands/lint/registry.js +0 -41
- package/dist/commands/lint/skill-linter.js +0 -45
- package/dist/commands/lint/task-linter.js +0 -50
- package/dist/commands/lint/workflow-linter.js +0 -81
- package/dist/commands/proposal/legacy-import.js +0 -115
- package/dist/commands/sources/history.js +0 -196
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/commands/wiki-cli.js +0 -292
- package/dist/core/asset/asset-registry.js +0 -76
- package/dist/core/asset/asset-spec.js +0 -259
- package/dist/core/config/config-migration.js +0 -602
- package/dist/core/deep-merge.js +0 -38
- package/dist/core/eval/rank-metrics.js +0 -113
- package/dist/core/ripgrep/install.js +0 -163
- package/dist/core/ripgrep/resolve.js +0 -81
- package/dist/indexer/db/db.js +0 -1413
- package/dist/indexer/manifest.js +0 -170
- package/dist/indexer/passes/metadata-contributors.js +0 -31
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -49
- package/dist/llm/call-ai.js +0 -62
- package/dist/llm/memory-infer-impl.js +0 -138
- 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/output/text/wiki.js +0 -16
- package/dist/registry/build-index.js +0 -386
- package/dist/scripts/migrate-storage.js +0 -19108
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -9411
- package/dist/scripts/migrations/v16-to-v17.js +0 -141
- package/dist/setup/legacy-config.js +0 -106
- package/dist/storage/repositories/consolidation-repository.js +0 -38
- package/dist/storage/repositories/recombine-repository.js +0 -213
- package/dist/wiki/wiki-templates.js +0 -15
- package/dist/wiki/wiki.js +0 -1012
- package/dist/workflows/db.js +0 -215
- package/docs/data-and-telemetry.md +0 -226
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
|
@@ -19,24 +19,22 @@
|
|
|
19
19
|
import { spawnSync } from "node:child_process";
|
|
20
20
|
import fs from "node:fs";
|
|
21
21
|
import path from "node:path";
|
|
22
|
+
import { getParsedInvocation } from "../../cli/invocation.js";
|
|
22
23
|
import { getStringArg } from "../../cli/parse-args.js";
|
|
23
24
|
import { defineGroupCommand, defineJsonCommand, output } from "../../cli/shared.js";
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import { isWithin, writeFileAtomic } from "../../core/common.js";
|
|
25
|
+
import { deriveCanonicalAssetName } from "../../core/asset/asset-placement.js";
|
|
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 { appendEvent } from "../../core/events.js";
|
|
31
|
-
import { isQuiet } from "../../core/warn.js";
|
|
32
30
|
import { resolveSourceEntries } from "../../indexer/search/search-source.js";
|
|
33
|
-
import { parseFlagValue } from "../../output/context.js";
|
|
34
31
|
import { readStdin } from "../../runtime.js";
|
|
35
32
|
import { buildChildEnv } from "./child-env.js";
|
|
33
|
+
import { sensitiveMarkerPath } from "./marker-path.js";
|
|
36
34
|
/**
|
|
37
35
|
* Walk each stash's env files and return one entry per `.env` file, using the
|
|
38
36
|
* env asset spec's canonical-name logic (e.g. `env/team/prod.env` →
|
|
39
|
-
* `env
|
|
37
|
+
* `env/team/prod`, `env/team/.env` → `env/team/default`).
|
|
40
38
|
*/
|
|
41
39
|
function listEnvsRecursive(listKeysFn) {
|
|
42
40
|
const result = [];
|
|
@@ -59,7 +57,7 @@ function listEnvsRecursive(listKeysFn) {
|
|
|
59
57
|
if (!canonical)
|
|
60
58
|
continue;
|
|
61
59
|
// Skip sensitive envs: a sibling .sensitive marker file suppresses listing.
|
|
62
|
-
const markerPath = full
|
|
60
|
+
const markerPath = sensitiveMarkerPath(full, "env");
|
|
63
61
|
if (fs.existsSync(markerPath))
|
|
64
62
|
continue;
|
|
65
63
|
const { keys } = listKeysFn(full);
|
|
@@ -71,7 +69,7 @@ function listEnvsRecursive(listKeysFn) {
|
|
|
71
69
|
return result;
|
|
72
70
|
}
|
|
73
71
|
const envListCommand = defineJsonCommand({
|
|
74
|
-
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)" },
|
|
75
73
|
async run() {
|
|
76
74
|
const { listKeys } = await import("./env.js");
|
|
77
75
|
output("env-list", { envs: listEnvsRecursive(listKeys) });
|
|
@@ -99,31 +97,29 @@ const envCreateCommand = defineJsonCommand({
|
|
|
99
97
|
description: "Exclude this env file from env list output and the search index",
|
|
100
98
|
default: false,
|
|
101
99
|
},
|
|
100
|
+
target: {
|
|
101
|
+
type: "string",
|
|
102
|
+
description: "Override the write destination. Accepts a source name from your config; falls back to defaultWriteTarget then the working bundle.",
|
|
103
|
+
},
|
|
102
104
|
},
|
|
103
105
|
async run({ args }) {
|
|
104
106
|
const { createEnv, writeEnv } = await import("./env.js");
|
|
105
|
-
// `create` always targets env/, never the frozen vaults/ copy.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const source = findEnvSource(parsed.origin);
|
|
111
|
-
const envRoot = path.join(source.path, "env");
|
|
112
|
-
const absPath = resolveAssetPathFromName("env", envRoot, parsed.name);
|
|
113
|
-
if (!isWithin(absPath, envRoot)) {
|
|
114
|
-
throw new UsageError(`Env name "${parsed.name}" escapes the env directory.`);
|
|
115
|
-
}
|
|
107
|
+
// `create` always targets env/, never the frozen vaults/ copy. `--path` is
|
|
108
|
+
// the subdirectory; `--target` selects the writable destination source.
|
|
109
|
+
const { name, absPath, target, ref } = resolveEnvWriteTarget(args.name, args.target, {
|
|
110
|
+
subPath: getStringArg(args, "path"),
|
|
111
|
+
});
|
|
116
112
|
const fromFile = args["from-file"];
|
|
117
113
|
const fromStdin = args["from-stdin"] === true;
|
|
118
114
|
if (fromFile !== undefined && fromStdin) {
|
|
119
115
|
throw new UsageError("Pass only one of --from-file or --from-stdin.", "INVALID_FLAG_VALUE");
|
|
120
116
|
}
|
|
117
|
+
let content;
|
|
121
118
|
if (fromFile !== undefined || fromStdin) {
|
|
122
119
|
// Ingest path: never silently clobber an existing env file.
|
|
123
120
|
if (fs.existsSync(absPath)) {
|
|
124
|
-
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");
|
|
125
122
|
}
|
|
126
|
-
let content;
|
|
127
123
|
if (fromFile !== undefined) {
|
|
128
124
|
if (!fs.existsSync(fromFile)) {
|
|
129
125
|
throw new NotFoundError(`Source file not found: ${fromFile}`, "FILE_NOT_FOUND");
|
|
@@ -135,18 +131,24 @@ const envCreateCommand = defineJsonCommand({
|
|
|
135
131
|
const buf = await readStdin(MAX_ENV_BYTES, () => new UsageError("Env file exceeds 1 MB limit.", "INVALID_FLAG_VALUE"));
|
|
136
132
|
content = buf.toString("utf8");
|
|
137
133
|
}
|
|
138
|
-
writeEnv(absPath, content);
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
createEnv(absPath);
|
|
142
134
|
}
|
|
135
|
+
const written = [absPath];
|
|
136
|
+
const markerPath = sensitiveMarkerPath(absPath, "env");
|
|
143
137
|
if (args.sensitive) {
|
|
144
|
-
|
|
145
|
-
if (!fs.existsSync(markerPath)) {
|
|
146
|
-
fs.writeFileSync(markerPath, "", { mode: 0o600 });
|
|
147
|
-
}
|
|
138
|
+
written.push(markerPath);
|
|
148
139
|
}
|
|
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
|
});
|
|
@@ -205,11 +223,10 @@ const envExportCommand = defineJsonCommand({
|
|
|
205
223
|
* for process-hijacking variables.
|
|
206
224
|
*/
|
|
207
225
|
async function runEnvInjected(target, opts) {
|
|
208
|
-
const
|
|
209
|
-
if (
|
|
226
|
+
const command = getParsedInvocation().passthroughArgs();
|
|
227
|
+
if (command.length === 0) {
|
|
210
228
|
throw new UsageError("Missing command. Usage: akm env run <ref> -- <command>");
|
|
211
229
|
}
|
|
212
|
-
const command = process.argv.slice(dashIndex + 1);
|
|
213
230
|
const { name, absPath, source } = resolveEnvPath(target);
|
|
214
231
|
if (!fs.existsSync(absPath)) {
|
|
215
232
|
// Help users who reach for the removed single-key `ref/KEY` form.
|
|
@@ -226,70 +243,20 @@ async function runEnvInjected(target, opts) {
|
|
|
226
243
|
}
|
|
227
244
|
if (baseExists) {
|
|
228
245
|
throw new UsageError(`'akm env run' injects the whole file; the single-key '<ref>/${maybeKey}' form was removed.\n` +
|
|
229
|
-
` 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");
|
|
230
247
|
}
|
|
231
248
|
}
|
|
232
249
|
}
|
|
233
250
|
throw new NotFoundError(`Env not found: ${makeEnvRef(name, source)}`);
|
|
234
251
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
//
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const wanted = new Set(opts.only);
|
|
244
|
-
const missing = opts.only.filter((k) => !(k in allValues));
|
|
245
|
-
if (missing.length > 0) {
|
|
246
|
-
process.stderr.write(`warning: --only key(s) not present in ${makeEnvRef(name, source)}: ${missing.join(", ")}\n`);
|
|
247
|
-
}
|
|
248
|
-
envValues = Object.fromEntries(Object.entries(allValues).filter(([k]) => wanted.has(k)));
|
|
249
|
-
}
|
|
250
|
-
else if (opts.except) {
|
|
251
|
-
const excluded = new Set(opts.except);
|
|
252
|
-
envValues = Object.fromEntries(Object.entries(allValues).filter(([k]) => !excluded.has(k)));
|
|
253
|
-
}
|
|
254
|
-
// Substitute `${secret:NAME}` tokens in values with the value of the sibling
|
|
255
|
-
// secret asset in the SAME stash. The lookup is injected so commands/env.ts
|
|
256
|
-
// keeps its narrow dependency surface; we resolve each name against this env's
|
|
257
|
-
// own `source`. A missing secret is a hard error — inject NOTHING (no partial
|
|
258
|
-
// injection). Resolved values are never logged or printed.
|
|
259
|
-
const { resolveSecretTokens } = await import("./env.js");
|
|
260
|
-
const { readValue } = await import("./secret.js");
|
|
261
|
-
const secretsRoot = path.join(source.path, "secrets");
|
|
262
|
-
const resolveSecret = (secretName) => {
|
|
263
|
-
const secretPath = resolveAssetPathFromName("secret", secretsRoot, secretName);
|
|
264
|
-
// Defense-in-depth: ensure the resolved path stays inside the secrets dir.
|
|
265
|
-
if (!isWithin(secretPath, secretsRoot)) {
|
|
266
|
-
throw new UsageError(`Secret name "${secretName}" escapes the secrets directory.`);
|
|
267
|
-
}
|
|
268
|
-
if (!fs.existsSync(secretPath))
|
|
269
|
-
return undefined;
|
|
270
|
-
// Match `secret run`: read utf8, do not trim (stay consistent with that path).
|
|
271
|
-
return readValue(secretPath).toString("utf8");
|
|
272
|
-
};
|
|
273
|
-
const { values: substituted, missing } = resolveSecretTokens(envValues, resolveSecret);
|
|
274
|
-
if (missing.length > 0) {
|
|
275
|
-
const envRef = makeEnvRef(name, source);
|
|
276
|
-
throw new NotFoundError(`Env "${envRef}" references secret(s) not found in its stash: ${missing.map((n) => `secret:${n}`).join(", ")}. Nothing was injected.`, "FILE_NOT_FOUND", `Create the missing secret, e.g. \`akm secret set secret:${missing[0]}\`.`);
|
|
277
|
-
}
|
|
278
|
-
envValues = substituted;
|
|
279
|
-
const keys = Object.keys(envValues);
|
|
280
|
-
// Scan injected keys for known process-hijacking variables (LD_PRELOAD,
|
|
281
|
-
// PATH, ...). Block for third-party-sourced stashes (origin has a registryId);
|
|
282
|
-
// warn for the operator's own first-party stash, where they own the file.
|
|
283
|
-
const { isDangerousEnvKey } = await import("../lint/env-key-rules.js");
|
|
284
|
-
const dangerous = keys.filter(isDangerousEnvKey);
|
|
285
|
-
if (dangerous.length > 0) {
|
|
286
|
-
const detail = `Env "${makeEnvRef(name, source)}" injects process-hijacking variable(s): ${dangerous.join(", ")}.`;
|
|
287
|
-
if (source.registryId) {
|
|
288
|
-
throw new UsageError(`Refusing to inject env from a third-party stash. ${detail}\n` +
|
|
289
|
-
` Review the file, then copy the values into a first-party env if you trust them.`, "INVALID_FLAG_VALUE");
|
|
290
|
-
}
|
|
291
|
-
process.stderr.write(`warning: ${detail} Injecting anyway (first-party stash).\n`);
|
|
292
|
-
}
|
|
252
|
+
// Load → filter → secret-substitute → dangerous-key policy → keys-only
|
|
253
|
+
// audit event. Shared with the workflow engine's per-unit env bindings —
|
|
254
|
+
// see env-binding.ts for the extracted core and its safety invariants.
|
|
255
|
+
const { resolveEnvBinding } = await import("./env-binding.js");
|
|
256
|
+
const { values: envValues } = resolveEnvBinding(target, {
|
|
257
|
+
only: opts.only,
|
|
258
|
+
except: opts.except,
|
|
259
|
+
});
|
|
293
260
|
const mergedEnv = buildChildEnv(process.env, {
|
|
294
261
|
clean: opts.clean === true,
|
|
295
262
|
inherit: opts.inherit ?? [],
|
|
@@ -297,12 +264,6 @@ async function runEnvInjected(target, opts) {
|
|
|
297
264
|
for (const [envKey, envValue] of Object.entries(envValues)) {
|
|
298
265
|
mergedEnv[envKey] = envValue;
|
|
299
266
|
}
|
|
300
|
-
// Audit trail: keys only, never values.
|
|
301
|
-
appendEvent({
|
|
302
|
-
eventType: "env_access",
|
|
303
|
-
ref: makeEnvRef(name, source),
|
|
304
|
-
metadata: { keys },
|
|
305
|
-
});
|
|
306
267
|
const result = spawnSync(command[0], command.slice(1), {
|
|
307
268
|
stdio: "inherit",
|
|
308
269
|
env: mergedEnv,
|
|
@@ -320,7 +281,15 @@ async function runEnvInjected(target, opts) {
|
|
|
320
281
|
}
|
|
321
282
|
throw err;
|
|
322
283
|
}
|
|
323
|
-
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;
|
|
324
293
|
}
|
|
325
294
|
/** Parse a comma/space-separated key list flag into a trimmed, non-empty array. */
|
|
326
295
|
function parseKeyListFlag(raw) {
|
|
@@ -337,7 +306,7 @@ const envRunCommand = defineJsonCommand({
|
|
|
337
306
|
name: "run",
|
|
338
307
|
description:
|
|
339
308
|
// biome-ignore lint/suspicious/noTemplateCurlyInString: literal `${secret:NAME}` token syntax documented for users, not interpolation
|
|
340
|
-
"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.",
|
|
341
310
|
},
|
|
342
311
|
args: {
|
|
343
312
|
target: { type: "positional", description: "Env ref", required: true },
|
|
@@ -370,15 +339,13 @@ const envRemoveCommand = defineJsonCommand({
|
|
|
370
339
|
args: {
|
|
371
340
|
ref: { type: "positional", description: "Env ref", required: true },
|
|
372
341
|
yes: { type: "boolean", alias: "y", description: "Skip confirmation prompt", default: false },
|
|
342
|
+
target: {
|
|
343
|
+
type: "string",
|
|
344
|
+
description: "Override the write destination. Accepts a source name from your config; falls back to defaultWriteTarget then the working bundle.",
|
|
345
|
+
},
|
|
373
346
|
},
|
|
374
347
|
async run({ args }) {
|
|
375
|
-
const
|
|
376
|
-
const source = findEnvSource(parsed.origin);
|
|
377
|
-
const envRoot = path.join(source.path, "env");
|
|
378
|
-
const absPath = resolveAssetPathFromName("env", envRoot, parsed.name);
|
|
379
|
-
if (!isWithin(absPath, envRoot)) {
|
|
380
|
-
throw new UsageError(`Env name "${parsed.name}" escapes the env directory.`);
|
|
381
|
-
}
|
|
348
|
+
const { name, absPath, target, ref } = resolveEnvWriteTarget(args.ref, args.target);
|
|
382
349
|
const { confirmDestructive } = await import("../../cli/confirm.js");
|
|
383
350
|
const confirmed = await confirmDestructive(`Remove env "${args.ref}"? This cannot be undone.`, {
|
|
384
351
|
yes: args.yes === true,
|
|
@@ -388,122 +355,18 @@ const envRemoveCommand = defineJsonCommand({
|
|
|
388
355
|
return;
|
|
389
356
|
}
|
|
390
357
|
if (!fs.existsSync(absPath)) {
|
|
391
|
-
throw new NotFoundError(`Env not found: ${
|
|
358
|
+
throw new NotFoundError(`Env not found: ${ref}`);
|
|
392
359
|
}
|
|
393
360
|
const { removeEnv } = await import("./env.js");
|
|
394
|
-
const removed = removeEnv(absPath);
|
|
395
|
-
output("env-remove", { ref
|
|
396
|
-
},
|
|
397
|
-
});
|
|
398
|
-
const envSetCommand = defineJsonCommand({
|
|
399
|
-
meta: {
|
|
400
|
-
name: "set",
|
|
401
|
-
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.",
|
|
402
|
-
},
|
|
403
|
-
args: {
|
|
404
|
-
ref: { type: "positional", description: "Env ref (e.g. env:prod or just prod)", required: true },
|
|
405
|
-
key: { type: "positional", description: "Key name to set (e.g. API_URL)", required: true },
|
|
406
|
-
"from-env": { type: "string", description: "Read the value from the named environment variable" },
|
|
407
|
-
"from-file": { type: "string", description: "Read the value from this file" },
|
|
408
|
-
},
|
|
409
|
-
async run({ args }) {
|
|
410
|
-
const parsed = parseEnvRef(args.ref);
|
|
411
|
-
const source = findEnvSource(parsed.origin);
|
|
412
|
-
const envRoot = path.join(source.path, "env");
|
|
413
|
-
const absPath = resolveAssetPathFromName("env", envRoot, parsed.name);
|
|
414
|
-
if (!isWithin(absPath, envRoot)) {
|
|
415
|
-
throw new UsageError(`Env name "${parsed.name}" escapes the env directory.`);
|
|
416
|
-
}
|
|
417
|
-
const key = String(args.key);
|
|
418
|
-
const { ENV_KEY_RE, setEnvKey } = await import("./env.js");
|
|
419
|
-
if (!ENV_KEY_RE.test(key)) {
|
|
420
|
-
throw new UsageError(`Invalid env key "${key}". Keys match [A-Za-z_][A-Za-z0-9_]*.`, "INVALID_FLAG_VALUE");
|
|
421
|
-
}
|
|
422
|
-
const fromEnv = args["from-env"];
|
|
423
|
-
const fromFile = args["from-file"];
|
|
424
|
-
if (fromEnv !== undefined && fromFile !== undefined) {
|
|
425
|
-
throw new UsageError("Pass only one of --from-file or --from-env (or use stdin).", "INVALID_FLAG_VALUE");
|
|
426
|
-
}
|
|
427
|
-
const MAX_ENV_VALUE_BYTES = 1024 * 1024; // 1 MB
|
|
428
|
-
let value;
|
|
429
|
-
if (fromFile !== undefined) {
|
|
430
|
-
if (!fs.existsSync(fromFile)) {
|
|
431
|
-
throw new NotFoundError(`File not found: ${fromFile}`, "FILE_NOT_FOUND");
|
|
432
|
-
}
|
|
433
|
-
const buf = fs.readFileSync(fromFile);
|
|
434
|
-
if (buf.byteLength > MAX_ENV_VALUE_BYTES)
|
|
435
|
-
throw new UsageError("Value exceeds the 1 MB limit.");
|
|
436
|
-
value = buf.toString("utf8");
|
|
437
|
-
}
|
|
438
|
-
else if (fromEnv !== undefined) {
|
|
439
|
-
const v = process.env[fromEnv];
|
|
440
|
-
if (v === undefined) {
|
|
441
|
-
throw new UsageError(`Environment variable "${fromEnv}" is not set.`, "INVALID_FLAG_VALUE");
|
|
442
|
-
}
|
|
443
|
-
value = v;
|
|
444
|
-
}
|
|
445
|
-
else {
|
|
446
|
-
const buf = await readStdin(MAX_ENV_VALUE_BYTES, () => new UsageError("Value exceeds the 1 MB limit."));
|
|
447
|
-
// Strip a single trailing newline so `echo "$VAL" | akm env set` is exact.
|
|
448
|
-
value = buf.toString("utf8").replace(/\n$/, "");
|
|
449
|
-
}
|
|
450
|
-
setEnvKey(absPath, key, value);
|
|
451
|
-
// Warn (never block) on process-hijacking key names, matching the env-run audit.
|
|
452
|
-
const { isDangerousEnvKey } = await import("../lint/env-key-rules.js");
|
|
453
|
-
if (isDangerousEnvKey(key) && !isQuiet()) {
|
|
454
|
-
process.stderr.write(`warning: "${key}" can influence process execution when this env is loaded via 'akm env run'.\n`);
|
|
455
|
-
}
|
|
456
|
-
output("env-set", { ref: makeEnvRef(parsed.name, source), key });
|
|
457
|
-
},
|
|
458
|
-
});
|
|
459
|
-
const envUnsetCommand = defineJsonCommand({
|
|
460
|
-
meta: {
|
|
461
|
-
name: "unset",
|
|
462
|
-
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`.",
|
|
463
|
-
},
|
|
464
|
-
args: {
|
|
465
|
-
ref: { type: "positional", description: "Env ref (e.g. env:prod or just prod)", required: true },
|
|
466
|
-
// `key` is read from the raw positionals (one or more) in run(); declared
|
|
467
|
-
// non-required so citty doesn't block before we emit a structured error.
|
|
468
|
-
key: { type: "positional", description: "Key name(s) to remove (one or more)", required: false },
|
|
469
|
-
},
|
|
470
|
-
async run({ args }) {
|
|
471
|
-
const parsed = parseEnvRef(args.ref);
|
|
472
|
-
const source = findEnvSource(parsed.origin);
|
|
473
|
-
const envRoot = path.join(source.path, "env");
|
|
474
|
-
const absPath = resolveAssetPathFromName("env", envRoot, parsed.name);
|
|
475
|
-
if (!isWithin(absPath, envRoot)) {
|
|
476
|
-
throw new UsageError(`Env name "${parsed.name}" escapes the env directory.`);
|
|
477
|
-
}
|
|
478
|
-
if (!fs.existsSync(absPath)) {
|
|
479
|
-
throw new NotFoundError(`Env not found: ${makeEnvRef(parsed.name, source)}`);
|
|
480
|
-
}
|
|
481
|
-
// citty puts every positional in `args._` (incl. the ref at [0]); the keys
|
|
482
|
-
// are the remaining positionals. citty also mis-captures the space-separated
|
|
483
|
-
// value of a global flag (`--format json`) as a positional, so drop any
|
|
484
|
-
// token that is actually a global flag's value (cli.ts:1335 documents this).
|
|
485
|
-
const globalFlagValues = new Set(["--format", "--shape", "--detail", "--scope", "--filter", "--target"]
|
|
486
|
-
.map((flag) => parseFlagValue(process.argv, flag))
|
|
487
|
-
.filter((v) => typeof v === "string"));
|
|
488
|
-
const keys = (Array.isArray(args._) ? args._.map(String) : [])
|
|
489
|
-
.slice(1)
|
|
490
|
-
.filter((k) => !globalFlagValues.has(k));
|
|
491
|
-
if (keys.length === 0) {
|
|
492
|
-
throw new UsageError("Usage: akm env unset <ref> <KEY...> (one or more keys).", "MISSING_REQUIRED_ARGUMENT");
|
|
493
|
-
}
|
|
494
|
-
const { ENV_KEY_RE, unsetEnvKeys } = await import("./env.js");
|
|
495
|
-
const invalid = keys.filter((k) => !ENV_KEY_RE.test(k));
|
|
496
|
-
if (invalid.length > 0) {
|
|
497
|
-
throw new UsageError(`Invalid env key(s): ${invalid.join(", ")}.`, "INVALID_FLAG_VALUE");
|
|
498
|
-
}
|
|
499
|
-
const { removed, missing } = unsetEnvKeys(absPath, keys);
|
|
500
|
-
output("env-unset", { ref: makeEnvRef(parsed.name, source), removed, missing });
|
|
361
|
+
const removed = withEnvSecretWrite(target, { type: "env", name }, "Remove", [absPath, sensitiveMarkerPath(absPath, "env")], () => removeEnv(absPath));
|
|
362
|
+
output("env-remove", { ref, removed });
|
|
501
363
|
},
|
|
502
364
|
});
|
|
503
365
|
export const envCommand = defineGroupCommand({
|
|
504
366
|
meta: {
|
|
505
367
|
name: "env",
|
|
506
|
-
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`.",
|
|
507
370
|
},
|
|
508
371
|
subCommands: {
|
|
509
372
|
list: envListCommand,
|
|
@@ -511,12 +374,9 @@ export const envCommand = defineGroupCommand({
|
|
|
511
374
|
export: envExportCommand,
|
|
512
375
|
run: envRunCommand,
|
|
513
376
|
create: envCreateCommand,
|
|
514
|
-
set: envSetCommand,
|
|
515
|
-
unset: envUnsetCommand,
|
|
516
377
|
remove: envRemoveCommand,
|
|
517
378
|
},
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
},
|
|
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.
|
|
522
382
|
});
|