akm-cli 0.10.261012-beta → 0.10.261014-beta
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 +710 -3
- package/README.md +15 -0
- package/SECURITY.md +11 -10
- package/STABILITY.md +47 -51
- package/dist/assets/hints/cli-hints-full.md +21 -19
- package/dist/assets/hints/cli-hints-short.md +3 -4
- package/dist/assets/opencode/akm-plugin.js +177 -0
- package/dist/assets/stash-skeleton/README.md +1 -1
- package/dist/assets/tasks/core/improve.yml +1 -1
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
- package/dist/assets/ui/config.js +27 -10
- package/dist/assets/workflows/workflow-template.md +2 -2
- package/dist/cli/clack.js +3 -1
- package/dist/cli/selection.js +33 -0
- package/dist/cli/shared.js +14 -1
- package/dist/cli/unknown-flags.js +6 -37
- package/dist/cli.js +69 -48
- package/dist/commands/agent/agent-dispatch.js +17 -25
- package/dist/commands/agent/contribute-cli.js +9 -8
- package/dist/commands/command/command-cli.js +4 -8
- package/dist/commands/command/command-execution.js +25 -39
- package/dist/commands/command/execution-source-loader.js +10 -14
- package/dist/commands/completions.js +1 -1
- package/dist/commands/config-cli.js +14 -5
- package/dist/commands/env/child-env.js +12 -14
- package/dist/commands/env/env-binding.js +47 -58
- package/dist/commands/env/env-cli.js +22 -24
- package/dist/commands/env/env.js +10 -58
- package/dist/commands/env/secret-cli.js +11 -29
- package/dist/commands/env/secret.js +3 -10
- package/dist/commands/health/checks.js +10 -849
- package/dist/commands/health/connections-and-harnesses-check.js +109 -0
- package/dist/commands/health/egress.js +3 -3
- package/dist/commands/health/html-report.js +9 -10
- package/dist/commands/health/plugin-staleness.js +18 -11
- package/dist/commands/health/report-view-model.js +16 -12
- package/dist/commands/health/scheduler-binary.js +1 -1
- package/dist/commands/health/semantic-search-check.js +85 -0
- package/dist/commands/health/type-directory-check.js +0 -3
- package/dist/commands/health.js +30 -42
- package/dist/commands/improve/consolidate/pair-pass.js +10 -25
- package/dist/commands/improve/consolidate.js +10 -15
- package/dist/commands/improve/distill.js +5 -17
- package/dist/commands/improve/eligibility.js +1 -3
- package/dist/commands/improve/execution.js +37 -40
- package/dist/commands/improve/extract-cli.js +6 -11
- package/dist/commands/improve/extract-prompt.js +2 -2
- package/dist/commands/improve/extract.js +67 -97
- package/dist/commands/improve/improve-cli.js +22 -128
- package/dist/commands/improve/improve-report.js +1 -1
- package/dist/commands/improve/improve-strategies.js +25 -108
- package/dist/commands/improve/improve.js +10 -14
- package/dist/commands/improve/loop-stages.js +3 -0
- package/dist/commands/improve/memory/memory-improve.js +1 -1
- package/dist/commands/improve/preparation.js +8 -13
- package/dist/commands/improve/reflect.js +203 -332
- package/dist/commands/improve/retrieval-scope.js +1 -1
- package/dist/commands/improve/session-asset.js +3 -2
- package/dist/commands/improve/stage.js +87 -115
- package/dist/commands/lint/base-linter.js +3 -3
- package/dist/commands/lint/env-key-rules.js +7 -6
- package/dist/commands/lint/index.js +3 -3
- package/dist/commands/models-cli.js +103 -63
- package/dist/commands/proposal/drain.js +26 -39
- package/dist/commands/proposal/proposal-cli.js +14 -18
- package/dist/commands/proposal/propose-cli.js +4 -2
- package/dist/commands/proposal/propose.js +37 -64
- package/dist/commands/proposal/repository.js +17 -17
- package/dist/commands/proposal/validators/proposal-validators.js +3 -6
- package/dist/commands/read/curate.js +10 -6
- package/dist/commands/read/registry-search.js +2 -48
- package/dist/commands/read/search-cli.js +1 -8
- package/dist/commands/read/search.js +5 -6
- package/dist/commands/read/show.js +6 -29
- package/dist/commands/remember.js +25 -40
- package/dist/commands/sources/add-cli.js +8 -63
- package/dist/commands/sources/bundle-cli.js +8 -9
- package/dist/commands/sources/bundle-config-ops.js +2 -2
- package/dist/commands/sources/info.js +12 -1
- package/dist/commands/sources/init.js +1 -1
- package/dist/commands/sources/installed-stashes.js +119 -63
- package/dist/commands/sources/migration-help.js +1 -1
- package/dist/commands/sources/plugin-upgrade.js +8 -15
- package/dist/commands/sources/schema-repair.js +4 -10
- package/dist/commands/sources/source-add.js +2 -2
- package/dist/commands/sources/source-clone.js +31 -7
- package/dist/commands/sources/source-manage.js +4 -4
- package/dist/commands/targets.js +175 -0
- package/dist/commands/tasks/explain.js +104 -69
- package/dist/commands/tasks/tasks-cli.js +9 -11
- package/dist/commands/tasks/tasks.js +75 -97
- package/dist/commands/ui/api.js +11 -3
- package/dist/commands/ui/redact.js +5 -31
- package/dist/commands/ui/workspace-actions.js +1 -1
- package/dist/commands/workflow/plan.js +48 -9
- package/dist/commands/workflow-cli.js +40 -45
- package/dist/core/adapter/adapters/agent-skills-adapter.js +10 -11
- package/dist/core/adapter/adapters/akm-adapter.js +36 -41
- package/dist/core/adapter/adapters/akm-lint.js +10 -12
- package/dist/core/adapter/adapters/akm-metadata.js +2 -2
- package/dist/core/adapter/adapters/akm-task-adapter.js +8 -9
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +5 -5
- package/dist/core/adapter/adapters/claude-adapter.js +1 -1
- package/dist/core/adapter/adapters/dotenv-adapter.js +7 -6
- package/dist/core/adapter/adapters/generic-files-adapter.js +5 -5
- package/dist/core/adapter/adapters/index.js +3 -4
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +12 -14
- package/dist/core/adapter/adapters/okf-adapter.js +8 -10
- package/dist/core/adapter/adapters/opencode-adapter.js +1 -1
- package/dist/core/adapter/adapters/shared.js +3 -3
- package/dist/core/adapter/adapters/tool-dir-shared.js +7 -25
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +3 -3
- package/dist/core/adapter/detect-adapter.js +1 -1
- package/dist/core/adapter/execution-source.js +13 -35
- package/dist/core/adapter/registry.js +1 -1
- package/dist/core/adapter/validate-context.js +2 -4
- package/dist/core/asset/asset-placement.js +1 -1
- package/dist/core/asset/asset-ref.js +3 -3
- package/dist/core/asset/resolve-ref.js +5 -0
- package/dist/core/bundle-rename.js +12 -4
- package/dist/core/closest-match.js +37 -0
- package/dist/core/common.js +37 -57
- package/dist/core/config/config-io.js +26 -18
- package/dist/core/config/config-schema.js +19 -106
- package/dist/core/config/config-sources.js +3 -3
- package/dist/core/config/config-types.js +4 -4
- package/dist/core/config/config-walker.js +50 -77
- package/dist/core/config/config.js +438 -109
- package/dist/core/config/convert-engine-references.js +114 -0
- package/dist/core/config/convert-engines-shared.js +40 -0
- package/dist/core/config/convert-engines.js +300 -0
- package/dist/core/config/convert-models-overlay.js +137 -0
- package/dist/core/config/credentials.js +304 -0
- package/dist/core/config/engine-semantics.js +3 -3
- package/dist/core/config/migrate-keys.js +222 -0
- package/dist/core/config/model-aliases.js +37 -0
- package/dist/core/config/models-file.js +34 -0
- package/dist/core/config/retired-engines.js +53 -0
- package/dist/core/config/schema/connections.js +41 -0
- package/dist/core/config/schema/embedding.js +2 -2
- package/dist/core/config/schema/harnesses.js +41 -0
- package/dist/core/config/schema/improve-processes.js +9 -28
- package/dist/core/config/schema/improve.js +36 -1
- package/dist/core/config/schema/index-config.js +18 -20
- package/dist/core/config/schema/primitives.js +42 -17
- package/dist/core/config/schema/search.js +6 -11
- package/dist/core/config/schema/sources-bundles.js +9 -9
- package/dist/core/config/schema/workflow.js +2 -6
- package/dist/core/config/unusable-entries.js +66 -0
- package/dist/core/content-safety.js +3 -6
- package/dist/core/endpoint-url.js +47 -0
- package/dist/core/env-secret-ref.js +84 -73
- package/dist/core/errors.js +10 -16
- package/dist/core/extra-params.js +3 -3
- package/dist/core/improve-result.js +8 -9
- package/dist/core/json-schema.js +1 -1
- package/dist/core/lesson-lint.js +1 -1
- package/dist/core/llm-inference.js +80 -0
- package/dist/core/parse.js +2 -2
- package/dist/core/paths.js +33 -10
- package/dist/core/recognition-util.js +8 -10
- package/dist/core/redaction.js +94 -55
- package/dist/core/ref-token.js +82 -0
- package/dist/core/secret-value.js +14 -0
- package/dist/core/state/migrations.js +17 -22
- package/dist/core/structured.js +2 -68
- package/dist/core/subprocess.js +63 -22
- package/dist/core/type-presentation.js +10 -14
- package/dist/core/write-source.js +20 -4
- package/dist/execution/input-contract.js +3 -6
- package/dist/execution/notices.js +49 -0
- package/dist/execution/resolved-request.js +24 -40
- package/dist/execution/source.js +21 -45
- package/dist/execution/target-ref.js +2 -2
- package/dist/indexer/bundle-identity-guard.js +6 -5
- package/dist/indexer/ensure-index.js +1 -1
- package/dist/indexer/index-writer-lock.js +1 -1
- package/dist/indexer/indexer.js +46 -42
- package/dist/indexer/installations.js +12 -22
- package/dist/indexer/lookup/adapter-concept-owner.js +40 -14
- package/dist/indexer/materialize-embeddings.js +20 -16
- package/dist/indexer/passes/memory-inference.js +21 -50
- package/dist/indexer/passes/metadata.js +5 -5
- package/dist/indexer/scan/doc-to-entry.js +1 -1
- package/dist/indexer/scan/drain-dir.js +9 -11
- package/dist/indexer/search/db-search.js +9 -7
- package/dist/indexer/search/search-source.js +42 -22
- package/dist/indexer/usage/usage-events.js +2 -3
- package/dist/indexer/walk/index-context.js +2 -1
- package/dist/indexer/walk/matchers.js +3 -11
- package/dist/indexer/walk/path-resolver.js +13 -68
- package/dist/indexer/walk/walker.js +32 -26
- package/dist/integrations/agent/akm-read-tools.js +81 -0
- package/dist/integrations/agent/config.js +1 -1
- package/dist/integrations/agent/detect.js +32 -36
- package/dist/integrations/agent/execution.js +130 -428
- package/dist/integrations/agent/index.js +1 -1
- package/dist/integrations/agent/profiles.js +24 -28
- package/dist/integrations/agent/prompts.js +17 -30
- package/dist/integrations/agent/request-lowering.js +67 -101
- package/dist/integrations/agent/resolution.js +332 -0
- package/dist/integrations/agent/runner-dispatch.js +156 -181
- package/dist/integrations/agent/runner.js +20 -70
- package/dist/integrations/agent/runtime-port.js +4 -0
- package/dist/integrations/agent/runtime.js +10 -0
- package/dist/integrations/agent/spawn.js +65 -190
- package/dist/integrations/harnesses/aider/index.js +19 -39
- package/dist/integrations/harnesses/amazonq/index.js +17 -32
- package/dist/integrations/harnesses/claude/index.js +59 -28
- package/dist/integrations/harnesses/claude/session-log.js +7 -5
- package/dist/integrations/harnesses/codex/index.js +19 -31
- package/dist/integrations/harnesses/copilot/index.js +17 -35
- package/dist/integrations/harnesses/gemini/index.js +18 -34
- package/dist/integrations/harnesses/harness.js +36 -0
- package/dist/integrations/harnesses/index.js +20 -51
- package/dist/integrations/harnesses/opencode/agent-builder.js +132 -100
- package/dist/integrations/harnesses/opencode/index.js +11 -33
- package/dist/integrations/harnesses/opencode/roots.js +50 -0
- package/dist/integrations/harnesses/opencode/runtime/binary.js +206 -0
- package/dist/integrations/harnesses/opencode/runtime/command.js +152 -0
- package/dist/integrations/harnesses/opencode/runtime/index.js +177 -0
- package/dist/integrations/harnesses/opencode/runtime/tar.js +107 -0
- package/dist/integrations/harnesses/opencode/session-log-v1.js +15 -7
- package/dist/integrations/harnesses/opencode/session-log-v2.js +72 -48
- package/dist/integrations/harnesses/opencode/session-log.js +58 -137
- package/dist/integrations/harnesses/opencode/version.js +34 -53
- package/dist/integrations/harnesses/openhands/index.js +13 -37
- package/dist/integrations/harnesses/pi/index.js +21 -32
- package/dist/integrations/lockfile.js +1 -1
- package/dist/integrations/session-logs/index.js +11 -31
- package/dist/llm/client.js +93 -111
- package/dist/llm/embedder.js +19 -34
- package/dist/llm/embedders/connection.js +31 -0
- package/dist/llm/embedders/local-model-files.js +56 -0
- package/dist/llm/embedders/local.js +146 -115
- package/dist/llm/embedders/remote.js +26 -23
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/index-passes.js +33 -39
- package/dist/llm/memory-infer.js +67 -77
- package/dist/llm/model-list.js +35 -0
- package/dist/llm/rerank-client.js +8 -14
- package/dist/llm/structured-call.js +45 -99
- package/dist/llm/structured.js +60 -0
- package/dist/output/renderers.js +2 -8
- package/dist/output/shapes/helpers.js +18 -44
- package/dist/output/shapes/passthrough.js +1 -0
- package/dist/output/shapes.js +1 -7
- package/dist/output/text/command-format.js +41 -39
- package/dist/output/text/health-format.js +8 -2
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/migrate.js +12 -0
- package/dist/output/text/models.js +3 -2
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/show-directives.js +16 -28
- package/dist/output/text/show-format.js +0 -2
- package/dist/output/text/targets-table.js +70 -0
- package/dist/output/text/workflow-format.js +44 -15
- package/dist/output/text.js +1 -1
- package/dist/registry/providers/skills-sh.js +1 -28
- package/dist/registry/providers/static-index.js +1 -71
- package/dist/runtime.js +6 -2
- package/dist/scripts/akm-migrate-node.js +47095 -44905
- package/dist/scripts/akm-migrate.js +46946 -44755
- package/dist/setup/detect.js +28 -273
- package/dist/setup/endpoint.js +36 -0
- package/dist/setup/semantic-assets.js +13 -19
- package/dist/setup/setup-flags.js +77 -0
- package/dist/setup/setup-plan.js +144 -0
- package/dist/setup/setup.js +134 -358
- package/dist/setup/steps/connection-shared.js +49 -101
- package/dist/setup/steps/connection.js +121 -524
- package/dist/setup/steps/embeddings.js +151 -0
- package/dist/setup/steps/harnesses.js +118 -0
- package/dist/setup/steps/platforms.js +2 -81
- package/dist/setup/steps/tasks.js +1 -2
- package/dist/setup/steps.js +10 -0
- package/dist/setup/summary.js +67 -0
- package/dist/sources/freshness.js +16 -21
- package/dist/sources/providers/git-provider.js +2 -9
- package/dist/sources/providers/provider-utils.js +13 -5
- package/dist/sources/resolve.js +12 -16
- package/dist/sources/snapshot-fetchers/robots.js +11 -12
- package/dist/sources/snapshot-fetchers/secret-seam.js +2 -4
- package/dist/sources/snapshot-fetchers/website-ingest.js +8 -15
- package/dist/sources/snapshot-fetchers/x.js +1 -1
- package/dist/standalone/onnxruntime-library.js +52 -0
- package/dist/storage/repositories/improve-ledger-repository.js +1 -1
- package/dist/storage/repositories/improve-runs-repository.js +0 -13
- package/dist/storage/repositories/index-entries-repository.js +2 -2
- package/dist/storage/repositories/proposals-repository.js +2 -2
- package/dist/storage/repositories/task-history-repository.js +2 -2
- package/dist/storage/repositories/workflow-runs-repository.js +44 -129
- package/dist/storage/sqlite-read-snapshot.js +33 -29
- package/dist/tasks/embedded.js +1 -1
- package/dist/tasks/log-redaction.js +7 -119
- package/dist/tasks/prepare/prepare-support.js +8 -7
- package/dist/tasks/prepare/prepare.js +8 -9
- package/dist/tasks/prepare/script-capture.js +9 -25
- package/dist/tasks/run/attempt-lifecycle.js +17 -35
- package/dist/tasks/run/load-task.js +54 -27
- package/dist/tasks/run/run-command-task.js +15 -10
- package/dist/tasks/run/run-native-task.js +8 -21
- package/dist/tasks/run/run-task.js +5 -8
- package/dist/tasks/run/run-workflow-task.js +14 -21
- package/dist/tasks/run/task-history.js +9 -17
- package/dist/tasks/run/task-log.js +1 -5
- package/dist/tasks/scheduler-invocation.js +13 -18
- package/dist/tasks/scheduler-sync.js +0 -1
- package/dist/tasks/source/bounded-document.js +31 -117
- package/dist/tasks/source/parse-task-source.js +0 -1
- package/dist/tasks/source/project-v4.js +5 -3
- package/dist/tasks/source/task-input-diagnostics.js +3 -4
- package/dist/tasks/source/task-source-v4.js +48 -72
- package/dist/tasks/source-v3.js +2 -5
- package/dist/tasks/task-run-reserved-flags.js +1 -2
- package/dist/workflows/authoring/authoring.js +2 -7
- package/dist/workflows/compile.js +1 -15
- package/dist/workflows/concurrency-policy.js +4 -4
- package/dist/workflows/exec/child-workflow.js +1 -4
- package/dist/workflows/exec/dispatch-redaction.js +35 -86
- package/dist/workflows/exec/environment.js +13 -77
- package/dist/workflows/exec/exec-unit.js +14 -55
- package/dist/workflows/exec/frozen-judge.js +26 -28
- package/dist/workflows/exec/native-executor.js +126 -71
- package/dist/workflows/exec/run-workflow.js +38 -42
- package/dist/workflows/exec/step-work.js +13 -17
- package/dist/workflows/exec/unit-dispatch.js +7 -21
- package/dist/workflows/freeze/environment.js +14 -119
- package/dist/workflows/freeze/freeze.js +14 -33
- package/dist/workflows/freeze/step-values.js +6 -13
- package/dist/workflows/freeze/targets/child-workflow.js +3 -5
- package/dist/workflows/freeze/targets/command.js +9 -15
- package/dist/workflows/freeze/targets/shell.js +0 -3
- package/dist/workflows/freeze/task-bindings.js +0 -1
- package/dist/workflows/parser.js +50 -59
- package/dist/workflows/plan.js +8 -2
- package/dist/workflows/renderer.js +83 -9
- package/dist/workflows/resource-limits.js +2 -2
- package/dist/workflows/runtime/run-plan.js +38 -23
- package/dist/workflows/runtime/runs.js +55 -93
- package/dist/workflows/runtime/workflow-asset-loader.js +55 -86
- package/dist/workflows/source-files.js +7 -19
- package/docs/README.md +10 -16
- package/docs/architecture/README.md +2 -37
- package/docs/architecture/adapters.md +2 -2
- package/docs/architecture/akm-core-principles.md +256 -118
- package/docs/architecture/architecture.md +283 -99
- package/docs/architecture/improvement.md +8 -2
- package/docs/architecture/internals/classification.md +1 -3
- package/docs/architecture/internals/fresh-host-rebuild-runbook.md +7 -6
- package/docs/architecture/internals/health-advisories.md +35 -74
- package/docs/architecture/internals/improve-workflow.md +27 -26
- package/docs/architecture/internals/indexing.md +3 -3
- package/docs/architecture/internals/storage-locations.md +48 -15
- package/docs/architecture/persisted-data-compat.md +10 -6
- package/docs/architecture/specs/okf-support.md +9 -11
- package/docs/architecture/specs/ref.md +7 -9
- package/docs/architecture/testing/testing-workflow.md +172 -52
- package/docs/architecture/workflow-engine.md +51 -34
- package/docs/guides/README.md +0 -1
- package/docs/guides/author-bundles.md +15 -20
- package/docs/guides/author-workflows.md +93 -71
- package/docs/guides/bundles.md +20 -16
- package/docs/guides/discover-and-load.md +1 -1
- package/docs/guides/getting-started.md +49 -3
- package/docs/guides/improve-the-library.md +10 -4
- package/docs/guides/recipes/headless-install.md +11 -16
- package/docs/guides/run-workflows.md +29 -20
- package/docs/guides/scheduling.md +2 -2
- package/docs/guides/use-with-any-agent.md +20 -22
- package/docs/integration/bundling-akm.md +19 -9
- package/docs/maintainers/README.md +2 -6
- package/docs/maintainers/release-checklist.md +73 -126
- package/docs/migration/README.md +10 -3
- package/docs/migration/release-notes/0.10.0.md +81 -16
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +1 -1
- package/docs/migration/release-notes/0.9.0.md +1 -1
- package/docs/migration/release-notes/README.md +1 -1
- package/docs/migration/v0.9-to-v0.10.md +300 -60
- package/docs/migration/v0.9.1-to-v0.9.2.md +6 -5
- package/docs/posts/config-v2-lessons-16.md +1 -1
- package/docs/posts/llm-mode-reflect-13.md +1 -1
- package/docs/posts/release-0.6.0.md +11 -11
- package/docs/posts/release-0.8.0.md +4 -4
- package/docs/posts/workflows-vaults-09.md +1 -1
- package/docs/reference/README.md +1 -1
- package/docs/reference/asset-types.md +2 -2
- package/docs/reference/cli.md +477 -388
- package/docs/reference/configuration.md +569 -550
- package/docs/reference/data-and-telemetry.md +9 -6
- package/docs/reference/env-and-secrets.md +72 -15
- package/docs/reference/refs.md +3 -20
- package/docs/reference/registry.md +12 -38
- package/docs/reference/supported-formats.md +1 -1
- package/docs/reference/tasks.md +22 -11
- package/docs/reference/ui-api.md +14 -9
- package/docs/reference/workflow-schema.md +199 -154
- package/docs/reference/workflows.md +4 -6
- package/package.json +9 -11
- package/schemas/akm-config.json +1696 -2922
- package/schemas/akm-task.json +4 -4
- package/schemas/akm-workflow.json +36 -9
- package/ROADMAP.md +0 -112
- package/dist/assets/models.json +0 -35
- package/dist/commands/health/engine-usage.js +0 -45
- package/dist/commands/sources/dangerous-env-audit.js +0 -134
- package/dist/core/activation-policy.js +0 -67
- package/dist/core/config/schema/engines.js +0 -160
- package/dist/core/config/schema/execution.js +0 -23
- package/dist/core/spawn-env.js +0 -268
- package/dist/execution/directory-identity.js +0 -78
- package/dist/integrations/agent/builder-shared.js +0 -33
- package/dist/integrations/agent/builders.js +0 -43
- package/dist/integrations/agent/engine-fallback.js +0 -59
- package/dist/integrations/agent/engine-resolution.js +0 -333
- package/dist/integrations/agent/model-map.js +0 -475
- package/dist/integrations/harnesses/aider/agent-builder.js +0 -107
- package/dist/integrations/harnesses/aider/result-extractor.js +0 -53
- package/dist/integrations/harnesses/amazonq/agent-builder.js +0 -138
- package/dist/integrations/harnesses/amazonq/result-extractor.js +0 -48
- package/dist/integrations/harnesses/claude/agent-builder.js +0 -106
- package/dist/integrations/harnesses/claude/config-import.js +0 -67
- package/dist/integrations/harnesses/claude/result-extractor.js +0 -67
- package/dist/integrations/harnesses/codex/agent-builder.js +0 -150
- package/dist/integrations/harnesses/codex/result-extractor.js +0 -110
- package/dist/integrations/harnesses/copilot/agent-builder.js +0 -117
- package/dist/integrations/harnesses/copilot/result-extractor.js +0 -178
- package/dist/integrations/harnesses/gemini/agent-builder.js +0 -114
- package/dist/integrations/harnesses/gemini/result-extractor.js +0 -149
- package/dist/integrations/harnesses/opencode/config-import.js +0 -149
- package/dist/integrations/harnesses/opencode/model-config.js +0 -33
- package/dist/integrations/harnesses/opencode/model-work-agent.js +0 -115
- package/dist/integrations/harnesses/opencode/session-log-types.js +0 -12
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -44
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +0 -1052
- package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +0 -199
- package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +0 -254
- package/dist/integrations/harnesses/opencode-sdk/wire.js +0 -66
- package/dist/integrations/harnesses/openhands/agent-builder.js +0 -120
- package/dist/integrations/harnesses/openhands/result-extractor.js +0 -135
- package/dist/integrations/harnesses/pi/agent-builder.js +0 -89
- package/dist/integrations/harnesses/pi/result-extractor.js +0 -168
- package/dist/integrations/harnesses/shared.js +0 -18
- package/dist/integrations/harnesses/types.js +0 -55
- package/dist/llm/feature-gate.js +0 -115
- package/dist/output/shapes/models-list.js +0 -16
- package/dist/output/shapes/registry-search.js +0 -10
- package/dist/setup/detected-engines.js +0 -136
- package/dist/setup/engine-config.js +0 -97
- package/dist/setup/harness-config-import.js +0 -47
- package/dist/setup/providers.js +0 -14
- package/dist/setup/steps/semantic.js +0 -39
- package/dist/workflows/authoring/scope-key.js +0 -79
- package/dist/workflows/exec/lowering-notices.js +0 -23
- package/dist/workflows/source-semantics.js +0 -110
- package/docs/architecture/0.10-process-rules.md +0 -832
- package/docs/architecture/akm-architecture-decision-history.md +0 -2055
- package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +0 -550
- package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +0 -72
- package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +0 -142
- package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +0 -189
- package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +0 -97
- package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +0 -108
- package/docs/architecture/decisions/0006-task-source-version-routing.md +0 -124
- package/docs/architecture/decisions/0007-workflow-composition-bounds.md +0 -83
- package/docs/architecture/decisions/0008-task-binding-normalization.md +0 -88
- package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +0 -80
- package/docs/architecture/decisions/0010-driver-protocol-cut.md +0 -36
- package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +0 -125
- package/docs/architecture/decisions/README.md +0 -62
- package/docs/architecture/internals/functional-contract-patterns.md +0 -340
- package/docs/architecture/internals/registry-network-boundary.md +0 -57
- package/docs/architecture/internals/search.md +0 -248
- package/docs/architecture/reviews/env-secret-access.md +0 -319
- package/docs/architecture/runtime-boundary-design.md +0 -153
- package/docs/architecture/specs/0.9.0-close-out-plan.md +0 -361
- package/docs/architecture/specs/0.9.0-decisions.md +0 -532
- package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +0 -745
- package/docs/architecture/specs/0.9.0-open-items-register.md +0 -135
- package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +0 -740
- package/docs/architecture/specs/0.9.0-release-surface-review.md +0 -636
- package/docs/architecture/specs/agent-command-engine-model-design.md +0 -513
- package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +0 -501
- package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +0 -291
- package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +0 -2059
- package/docs/architecture/specs/di-seams-plan.md +0 -539
- package/docs/architecture/specs/driver-protocol-keep-or-cut.md +0 -275
- package/docs/architecture/specs/fact-asset-type.md +0 -142
- package/docs/architecture/specs/improve-collapse-churn-detector-design.md +0 -634
- package/docs/architecture/specs/reviews/task-workflow-unification/README.md +0 -72
- package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +0 -152
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +0 -352
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +0 -300
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +0 -402
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +0 -758
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +0 -645
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +0 -602
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +0 -27
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +0 -27
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +0 -74
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +0 -15
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +0 -132
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +0 -147
- package/docs/architecture/specs/stash-conventions-code-spec.md +0 -275
- package/docs/architecture/specs/stash-organization-conventions.md +0 -377
- package/docs/architecture/specs/task-workflow-format-unification.md +0 -721
- package/docs/architecture/specs/workflow-engine-buy-vs-build.md +0 -231
- package/docs/architecture/specs/workflow-format-unification.md +0 -432
- package/docs/architecture/testing/manual-testing-checklist.md +0 -3411
- package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +0 -924
- package/docs/architecture/testing/task-workflow-manual-tests.md +0 -1720
- package/docs/guides/claude-code-vs-akm-workflows.md +0 -29
- package/docs/guides/knowledge-management.md +0 -18
- package/docs/maintainers/curate-workmap.md +0 -335
- package/docs/migration/v0.5-to-v0.6.md +0 -759
- package/docs/migration/v0.7-to-v0.8.md +0 -1378
- package/docs/plans/0.9.2-agent-command-workflow-plan.md +0 -423
|
@@ -25,58 +25,46 @@ migrate` / `akm upgrade`; ordinary runtime code reads only the current shape.
|
|
|
25
25
|
```jsonc
|
|
26
26
|
{
|
|
27
27
|
"configVersion": "0.9.0",
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"endpoint": "http://localhost:11434/v1/chat/completions",
|
|
33
|
-
"model": "qwen3",
|
|
34
|
-
"apiKey": "${LOCAL_LLM_API_KEY}"
|
|
35
|
-
},
|
|
36
|
-
"reviewer": {
|
|
37
|
-
"kind": "agent",
|
|
38
|
-
"platform": "opencode",
|
|
39
|
-
"model": "anthropic/claude-sonnet-4-6"
|
|
28
|
+
"connections": {
|
|
29
|
+
"default": {
|
|
30
|
+
"endpoint": "http://localhost:11434/v1",
|
|
31
|
+
"models": { "fast": "qwen3-8b", "balanced": "qwen3-32b", "reasoning": "qwen3-32b" }
|
|
40
32
|
}
|
|
41
33
|
},
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"improveStrategy": "default"
|
|
46
|
-
},
|
|
47
|
-
"workflow": {
|
|
48
|
-
"maxConcurrency": 8,
|
|
49
|
-
"judgeEngine": "reviewer"
|
|
50
|
-
},
|
|
51
|
-
"execution": {
|
|
52
|
-
"allowedTools": ["read_file", "search"]
|
|
53
|
-
},
|
|
34
|
+
"harnesses": { "claude": {} },
|
|
35
|
+
"embedding": { "model": "nomic-embed-text" },
|
|
36
|
+
"workflow": { "maxConcurrency": 8 },
|
|
54
37
|
"improve": {
|
|
38
|
+
"strategy": "nightly",
|
|
39
|
+
"processes": {
|
|
40
|
+
"memoryInference": { "model": "qwen3-8b", "llm": { "temperature": 0.1 } }
|
|
41
|
+
},
|
|
55
42
|
"strategies": {
|
|
56
43
|
"nightly": {
|
|
57
|
-
"
|
|
58
|
-
"processes": {
|
|
59
|
-
"reflect": {},
|
|
60
|
-
"memoryInference": { "model": "qwen3-small", "llm": { "temperature": 0.1 } }
|
|
61
|
-
}
|
|
44
|
+
"processes": { "reflect": { "limit": 10 } }
|
|
62
45
|
}
|
|
63
46
|
}
|
|
64
47
|
}
|
|
65
48
|
}
|
|
66
49
|
```
|
|
67
50
|
|
|
51
|
+
A config with no connection and no harness is valid: everything that needs no
|
|
52
|
+
model works. [Connections](#connections), [Harnesses](#harnesses) and [Where
|
|
53
|
+
each process runs](#where-each-process-runs) say how models are added.
|
|
54
|
+
|
|
68
55
|
## Scheduler activation
|
|
69
56
|
|
|
70
57
|
`scheduler.enabled` is this host's list of scheduled refs, such as
|
|
71
|
-
`stash//tasks/nightly
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
58
|
+
`stash//tasks/nightly`, held and written as plain refs. A ref that is not
|
|
59
|
+
listed is disabled, and removing a bundle drops its refs. The older
|
|
60
|
+
`{kind, ref, sourceId}` entries are read as their `ref` and written back
|
|
61
|
+
plain.
|
|
75
62
|
A config without the list (written before 0.9.17) means "keep what is
|
|
76
|
-
installed": the first `akm task sync`
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
put themselves on the
|
|
63
|
+
installed": the first `akm task sync`, `akm setup`, `akm task enable`, `akm task
|
|
64
|
+
disable` or `akm task add` fills it from the akm-written native scheduler rows.
|
|
65
|
+
There are no grants, source identities or fire-time checks. Authored
|
|
66
|
+
task/workflow files may describe schedules but cannot put themselves on the
|
|
67
|
+
list.
|
|
80
68
|
|
|
81
69
|
This key is deliberately local: if a config uses `extends`, any `scheduler`
|
|
82
70
|
section in the base is ignored with a warning. Only the top-level local config
|
|
@@ -85,25 +73,129 @@ can activate schedules. Prefer `akm task enable <ref>` and `akm task disable
|
|
|
85
73
|
affected bundle. An unscoped `akm task sync` reconciles enabled refs across all
|
|
86
74
|
enabled configured bundles.
|
|
87
75
|
|
|
88
|
-
##
|
|
76
|
+
## Connections
|
|
89
77
|
|
|
90
|
-
|
|
91
|
-
|
|
78
|
+
A connection is an OpenAI-compatible endpoint akm sends model requests to, and
|
|
79
|
+
the models it serves. `connections` maps a name to one. A name is lowercase
|
|
80
|
+
kebab-case, at most 63 characters, and cannot start with `akm-`. The
|
|
81
|
+
connection named `default` is the default connection; a lone connection is the
|
|
82
|
+
default whatever it is called. `akm setup` names the first one `default`.
|
|
92
83
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
84
|
+
```jsonc
|
|
85
|
+
{
|
|
86
|
+
"connections": {
|
|
87
|
+
"default": {
|
|
88
|
+
"endpoint": "http://localhost:11434/v1",
|
|
89
|
+
"models": {
|
|
90
|
+
"fast": "qwen3-8b",
|
|
91
|
+
"balanced": "qwen3-32b",
|
|
92
|
+
"reasoning": { "model": "glm-5", "reasoning_effort": "high" }
|
|
93
|
+
},
|
|
94
|
+
"top_p": 0.9
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
97
99
|
|
|
98
|
-
|
|
100
|
+
akm reads these keys of a connection:
|
|
101
|
+
|
|
102
|
+
| Key | Meaning |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| `endpoint` | Required. The OpenAI-compatible base URL (`http://localhost:11434/v1`) or the chat-completions URL itself, starting with `http://` or `https://`. Requests go to `<base>/chat/completions` and the model list is read from `<base>/models`; a query string on the URL (a gateway's `api-version`, say) stays after the path on every request, and a `#fragment` is dropped. A username or password in the URL is warned about; put the key in `apiKey` or `credentials.json`. |
|
|
105
|
+
| `apiKey` | A `$VAR` or `${VAR}` reference to an environment variable. Absent, the key is the one stored in `credentials.json` for the connection and its endpoint. See [Credentials](#credentials). |
|
|
106
|
+
| `apiKeyFile` | Retired. `akm migrate apply` leaves an engine's key file here, as written, when it cannot read the file yet; akm ignores it (never reads it or sends it) and a later `akm migrate apply` moves the key it names into `credentials.json`. |
|
|
107
|
+
| `models` | Alias to model. See [Aliases](#aliases). |
|
|
108
|
+
| `contextLength` | The model's context window in tokens. `akm improve` sizes its prompts from it (consolidate's chunks, reflect's asset content); unset, it assumes 4096. |
|
|
109
|
+
| `timeoutMs` | How long one call may take, in milliseconds; `null` runs unbounded. Unset, a model call stops after 600 000 (ten minutes) and agent work runs until it finishes. The ceiling is 2 147 483 647. |
|
|
110
|
+
| `concurrency` | How many requests a workflow `map` step may have in flight on this connection, clamped to 1–64. Unset, 1 on a loopback endpoint (a local model server runs one inference at a time) and 4 on a remote one. akm never sends it. |
|
|
111
|
+
|
|
112
|
+
Every other key, on the connection or in a model entry, is a request field in
|
|
113
|
+
the endpoint's own spelling and is sent with each request as written (`top_p`,
|
|
114
|
+
`reasoning_effort`, `chat_template_kwargs`, ...). A connection's fields apply to
|
|
115
|
+
all its models and a model entry's override them; an object field on both sides
|
|
116
|
+
(`chat_template_kwargs`) merges key by key. `model`, `messages`, `tools`,
|
|
117
|
+
`stream` and `response_format` are akm's, on a direct call and in akm's own
|
|
118
|
+
runtime alike: the resolved model, the conversation and tool state, whether the
|
|
119
|
+
reply streams and the response format a caller asks for are never replaced. A
|
|
120
|
+
connection or model entry, or an `extraParams` of a call, a process or a
|
|
121
|
+
workflow step, that writes one of them is ignored for that field, with one
|
|
122
|
+
warning (the final fields are checked, whichever layer brought it).
|
|
123
|
+
|
|
124
|
+
A transient failure (an HTTP 5xx, a dropped connection) is retried once, within
|
|
125
|
+
what is left of the call's timeout. A 4xx is not.
|
|
126
|
+
|
|
127
|
+
### Settings a call asks for
|
|
128
|
+
|
|
129
|
+
A command, agent, workflow step or task can run against any endpoint, so it asks
|
|
130
|
+
for these in akm's words, and akm writes them as the endpoint's fields over the
|
|
131
|
+
connection's own:
|
|
132
|
+
|
|
133
|
+
| Setting | Request field |
|
|
134
|
+
| --- | --- |
|
|
135
|
+
| `temperature` | `temperature` |
|
|
136
|
+
| `maxTokens` | `max_tokens` |
|
|
137
|
+
| `reasoningEffort` (an asset's `effort` is the same setting) | `reasoning_effort` |
|
|
138
|
+
| `enableThinking` | `chat_template_kwargs.enable_thinking` and `enable_thinking` |
|
|
139
|
+
|
|
140
|
+
They are written `akm.inference` (and top-level `temperature` and `effort`) in
|
|
141
|
+
an asset's frontmatter, `llm:` on a workflow step (`max_tokens`,
|
|
142
|
+
`enable_thinking`, `reasoning_effort`), `inference` in a task, and `llm` on an
|
|
143
|
+
improve process, the quality gate or an index pass. Nearest wins: the asset,
|
|
144
|
+
then the process, then the model entry, then the connection. A connection and
|
|
145
|
+
akm's own runtime take all of them. A harness takes none: set them in the
|
|
146
|
+
program's own configuration, and akm reports each as an `untranslated-field`
|
|
147
|
+
notice while the call goes on.
|
|
148
|
+
|
|
149
|
+
akm sends no `max_tokens` unless one is written, on a connection, on a model
|
|
150
|
+
entry or by the call: the model and its endpoint know their own limits, and a
|
|
151
|
+
default cap would truncate replies silently. A direct chat call (model work on a
|
|
152
|
+
connection) does send `temperature: 0.3` when nothing writes one; the
|
|
153
|
+
connection's, a model entry's or the call's own `temperature` wins. akm's own
|
|
154
|
+
runtime sends none and leaves it to the endpoint.
|
|
155
|
+
|
|
156
|
+
`enableThinking: false` turns thinking off and `reasoningEffort` takes a value
|
|
157
|
+
such as `"none"`, `"low"` or `"high"`. akm sends **both** thinking fields,
|
|
158
|
+
because which one an endpoint honors is a fact about it and any gateway in front
|
|
159
|
+
of it. llama.cpp direct honors both (`reasoning_effort` from build b10644); vLLM
|
|
160
|
+
honors `chat_template_kwargs`; Bifrost drops `chat_template_kwargs` and passes
|
|
161
|
+
`reasoning_effort` through, so also set `reasoningEffort: "none"` behind it. A
|
|
162
|
+
strict hosted API that rejects the two fields (OpenAI answers 400 `Unknown
|
|
163
|
+
parameter: 'chat_template_kwargs'`) gets one retry without both, and akm stops
|
|
164
|
+
sending them to that endpoint and model for the rest of the process. A response
|
|
165
|
+
with reasoning tokens despite `enableThinking: false` triggers a runtime
|
|
166
|
+
warning.
|
|
167
|
+
|
|
168
|
+
Improve's `consolidate` and `reflect` always ask for thinking off, for a
|
|
169
|
+
machine-readable payload, and the quality-gate and triage judges do too unless
|
|
170
|
+
the judge's connection turns thinking on (`enable_thinking: true` as a request
|
|
171
|
+
field, or `llm.enableThinking: true`).
|
|
172
|
+
|
|
173
|
+
When a call asks for JSON that matches a schema, a connection receives the
|
|
174
|
+
schema as `response_format` (`json_schema`, strict). If the endpoint rejects it
|
|
175
|
+
with a 4xx other than 429, or with a 5xx that names the response format, akm
|
|
176
|
+
retries once without `response_format` and stops sending it to that endpoint and
|
|
177
|
+
model for the rest of the process. A harness receives the schema as one
|
|
178
|
+
instruction at the end of its prompt (`Respond with ONLY a JSON value matching
|
|
179
|
+
this JSON Schema (no prose, no code fences):` followed by the schema).
|
|
180
|
+
|
|
181
|
+
## Harnesses
|
|
182
|
+
|
|
183
|
+
A harness is an agent program you already have. `harnesses` maps a name to an
|
|
184
|
+
entry; an entry named for a platform enables it, so `{ "claude": {} }` enables
|
|
185
|
+
Claude Code. A second install of the same program sets `platform`: `{
|
|
186
|
+
"claude-work": { "platform": "claude", "bin": "/opt/claude-work/bin/claude" }
|
|
187
|
+
}`. The harness named `default` is the default harness; a lone harness is the
|
|
188
|
+
default whatever it is called. With several and none named `default`, there is no
|
|
189
|
+
default harness. `akm setup` names the default one `default`.
|
|
190
|
+
|
|
191
|
+
The platforms (generated from the harness registry; do not edit):
|
|
99
192
|
|
|
100
193
|
<!-- harness-table:start (generated by scripts/gen-config-schema.ts) -->
|
|
101
|
-
| `platform` | Harness | Binary | Session logs |
|
|
194
|
+
| `platform` | Harness | Binary | Session logs | Restricted model work | Native `agent` |
|
|
102
195
|
| --- | --- | --- | --- | --- | --- |
|
|
103
|
-
| `opencode` | OpenCode | `opencode` | yes |
|
|
196
|
+
| `opencode` | OpenCode | `opencode` | yes | depends on the install | yes |
|
|
104
197
|
| `claude` | Claude Code | `claude` | yes | yes | yes |
|
|
105
|
-
| `
|
|
106
|
-
| `codex` | OpenAI Codex CLI | `codex` | yes | no | no |
|
|
198
|
+
| `codex` | OpenAI Codex CLI | `codex` | yes | yes | no |
|
|
107
199
|
| `copilot` | GitHub Copilot CLI | `copilot` | no | no | no |
|
|
108
200
|
| `pi` | Pi | `pi` | no | no | no |
|
|
109
201
|
| `gemini` | Gemini CLI | `gemini` | no | no | no |
|
|
@@ -112,373 +204,321 @@ The registered harnesses (generated from the harness registry; do not edit):
|
|
|
112
204
|
| `openhands` | OpenHands | `openhands` | no | no | no |
|
|
113
205
|
<!-- harness-table:end -->
|
|
114
206
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
`
|
|
121
|
-
|
|
122
|
-
`
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
`
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
`
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
runs
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
the
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
(`
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
the
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
`opencode` and `opencode-sdk` (see
|
|
277
|
-
[Inference on an agent engine](#inference-on-an-agent-engine)); on any other
|
|
278
|
-
agent engine it is reported as `untranslated-field` notices, not errors.
|
|
279
|
-
- opencode model work may read the stash and write only its working directory.
|
|
280
|
-
`akm_search` and `akm_show` come from the akm-opencode plugin (0.9.21 or
|
|
281
|
-
later), which akm does not load: put it in your opencode config
|
|
282
|
-
(`"plugin": ["akm-opencode"]` for OpenCode 1; for OpenCode 2 install
|
|
283
|
-
`akm-opencode-v2` with `opencode plugin add akm-opencode-v2`, see
|
|
284
|
-
[Use AKM With Any Agent](https://github.com/itlackey/akm/blob/main/docs/guides/use-with-any-agent.md#opencode-plugins-one-package-per-opencode-major)). akm turns off the plugin's curation, learning
|
|
285
|
-
and write gate for these dispatches and keeps its state in akm's state
|
|
286
|
-
directory. The stash is protected from edits only while the temporary
|
|
287
|
-
directory is outside a git repository.
|
|
288
|
-
|
|
289
|
-
### Model-map files
|
|
290
|
-
|
|
291
|
-
AKM ships an immutable `models.json` package asset with three intent aliases:
|
|
292
|
-
`fast`, `balanced`, and `reasoning`. The installed starter has separate
|
|
293
|
-
columns for Claude Code, OpenCode, and OpenCode SDK only. A provider-specific
|
|
294
|
-
identifier is not pretended to work on unrelated engines. Add mappings for
|
|
295
|
-
Gemini, Codex, named direct LLM engines, or other harnesses in your user file.
|
|
296
|
-
Config-root and per-engine `modelAliases` are rejected; this file is the only
|
|
297
|
-
alias definition surface.
|
|
298
|
-
|
|
299
|
-
An optional operator-owned file lives beside `config.json` at
|
|
300
|
-
`$XDG_CONFIG_HOME/akm/models.json` (or `<AKM_CONFIG_DIR>/models.json`). It uses
|
|
301
|
-
the same version-1 schema as the installed file:
|
|
302
|
-
|
|
303
|
-
```json
|
|
207
|
+
An entry sets any of:
|
|
208
|
+
|
|
209
|
+
| Key | Meaning |
|
|
210
|
+
| --- | --- |
|
|
211
|
+
| `platform` | One of the platforms above. Absent, the entry's name must be one. |
|
|
212
|
+
| `bin` | The program to run. Default: the platform's binary above, looked up on `PATH`. Set it when that is not the one you mean, for example `opencode2` when OpenCode 2 installed it beside an older `opencode` that comes first on your `PATH`. |
|
|
213
|
+
| `args` | Arguments placed before the ones akm adds. |
|
|
214
|
+
| `workspace` | The directory agent work runs in. Default: the directory akm was started in. |
|
|
215
|
+
| `agent` | The harness's native agent to run when a request names none (`claude` and `opencode` only). A request's own agent wins, an agent asset's persona is kept, and model work runs no native agent. |
|
|
216
|
+
| `timeoutMs` | How long a run may take, in milliseconds; `null` runs unbounded. Unset, agent work runs until it finishes and model work stops after 600 000. |
|
|
217
|
+
| `models` | Alias to model name for this harness, over the map akm ships for its platform. See [Aliases](#aliases). |
|
|
218
|
+
| `modelWork` | `false` keeps akm's own model calls (improve, judging, extraction) off this harness when it is the default for them: with no connection to run them on, they are off. A call that names the harness (`--harness`, `improve.harness`) still runs there. Absent or `true`, the default harness takes model calls when no connection does. `akm info` and `akm health` list a harness set this way. |
|
|
219
|
+
|
|
220
|
+
Asset frontmatter cannot set `workspace`, `environment` or opaque `runtime`
|
|
221
|
+
values; those belong to this configuration or to a workflow's environment
|
|
222
|
+
bindings.
|
|
223
|
+
|
|
224
|
+
### How akm runs a harness
|
|
225
|
+
|
|
226
|
+
What asks for a harness decides how akm runs it.
|
|
227
|
+
|
|
228
|
+
**Agent work** (`akm agent`, `akm command run`, `akm proposal new`, agent tasks and workflow agent steps) runs your program the way you would run it yourself. It gets your environment as it is, with nothing filtered out, and your configuration, plugins, settings and logins as they are. akm sets only its own variables for the run: the directories this akm resolved (`AKM_CONFIG_DIR`, `AKM_DATA_DIR`, `AKM_CACHE_DIR`, `AKM_STATE_DIR`, and `AKM_BUNDLE_DIR` when you set one), so a program that runs `akm` uses the same installation, and, when a task runs it, `AKM_EVENT_SOURCE` (unless already set), so the akm commands the program runs count as machine use, not yours. A workflow unit's or task's own `env:` bindings are set over them. On the command line, after your `args` as you wrote them, akm adds the model or agent the asset or flag names, the agent asset's persona where the program takes one there, and what the program needs to run without a person at the terminal: its print or exec mode and its approve-all switch where it asks before acting. Codex runs with the sandbox your Codex configuration sets, or the one your `args` name; model work runs it with `--sandbox read-only` (below). The prompt goes on standard input where the program reads it there and on the command line where it does not; standard output is the reply. `akm agent` with no `--prompt` starts the program interactively instead. What akm scrubs from the output it captures is in [Architecture: Connections and Harnesses](../architecture/architecture.md#connections-and-harnesses) and, for a workflow, [Workflow Schema](workflow-schema.md#the-childs-environment).
|
|
229
|
+
|
|
230
|
+
**Model work** (see [Where each process runs](#where-each-process-runs)) is akm's own process, so akm sets the call up as it needs it. The program has the same environment. akm runs it in a scratch directory that it creates for the call and removes after it, stamps the akm commands it runs `improve`, and runs no native agent of yours. Where the program can be restricted, akm also limits its tools. The "Restricted model work" column of the table says on which platforms (OpenCode: on version 2):
|
|
231
|
+
|
|
232
|
+
- Claude Code runs with `--restricted`, so none of your settings files can widen the tools; with `Read` and `Bash` only for `akm search`, `akm show` and `akm curate`; with no MCP servers; and with no transcript saved.
|
|
233
|
+
- Codex runs with `--sandbox read-only`.
|
|
234
|
+
- OpenCode 2 runs as the `akm-model-work` agent, which akm passes inline with the run, merged into your `OPENCODE_CONFIG_CONTENT` and keeping the rest of it; akm reads that variable as OpenCode does, as JSONC (comments and trailing commas), with its `{env:NAME}` references replaced as OpenCode replaces them when the content reads only that way (a reference written outside a string, such as a number), and leaves it out, with one warning, when it is not valid JSONC holding an object. akm writes it in OpenCode 2's native `agents` map, which OpenCode reads over the legacy `agent` map, so an entry of that name in your config, in either map, inline or in a file, does not change it (a same-named entry in your inline `agent` map is left out). Its tools are limited to reading and searching: every tool is denied except `read`, `glob` and `grep`, and `akm_search`, `akm_show` and `akm_curate` when you have the akm OpenCode plugin installed. A tool that a plugin of yours adds is denied too. The limit is on tools: your plugins' own setup and hooks still run in the session. The run is `--standalone`, one process that ends with it, with no background service left behind, and `--title akm`, which names the session and spares the second model request that would generate a title.
|
|
235
|
+
- On Claude Code, Codex and OpenCode, `args` do not apply to model work, except a `--model` they name.
|
|
236
|
+
- OpenCode 1 and every other platform cannot be restricted: the run is unrestricted, in the scratch directory, and akm reports that. The other platforms get the agent-work command line, `args` included.
|
|
237
|
+
- OpenCode model work sets `OPENCODE_DISABLE_FREE_MODELS=1`, which OpenCode 2.1.2 and later honor: a call with no usable provider fails instead of sending the prompt to OpenCode's hosted free model, and so does a call whose model (named, or your OpenCode's default) is one of its free ones. Agent work does not set it: your OpenCode's models are as you would get running it by hand.
|
|
238
|
+
|
|
239
|
+
Where model work is restricted, its tools cannot change the library, so what it changes there reaches it only as a proposal, through the review queue. Where it cannot be restricted, nothing but its scratch working directory stands between the run and your files: the program keeps its own tools and runs with the file and command authority of the user running akm, in your environment, so it can edit files and run commands, in or outside the library, and akm does not check what it did. Any harness may be enabled for model calls; a connection is the way to keep them from touching anything. `akm setup` says so when you enable such a harness for akm's model calls, and saves `modelWork: false` on the harness when you decline ([setup](cli.md#setup)).
|
|
240
|
+
|
|
241
|
+
**History.** A harness run leaves a session in the program's own history, and `akm proposal extract` and improve read that history like any other. The exceptions are the model-work sessions akm marked: Claude Code keeps no transcript of them, and OpenCode 2 records them under the `akm-model-work` agent, which the reader skips. Codex and OpenCode 1 cannot be marked, so their model-work sessions are read like any other. akm's own runtime (below) keeps its sessions in `<akm data dir>/opencode-runtime/data/opencode/opencode.db`, read the same way.
|
|
242
|
+
|
|
243
|
+
**Stopping.** When akm stops a run (a timeout, an abort or a signal to akm) it sends the program's process group SIGINT, as Ctrl-C would. If anything in the group still runs after 5 seconds, or as soon as the program itself has exited and left members behind, it sends SIGTERM, and 5 seconds after that SIGKILL if anything still runs. Workflow `exec` units and task commands are stopped the same way. Windows has no process groups, and a signal sent to a process there ends it at once. A program that records how a run ended acts on the SIGINT: OpenCode 2 marks its session interrupted and releases it, and only a run that had to be terminated or killed stays suspended in your OpenCode history, where your own OpenCode's background service may resume it when it next starts (up to ten attempts, OpenCode's own policy). Through OpenCode 2's background service (measured on 2.1.4) the interrupt ends the `opencode` command and the service's turn alike: the service abandons the turn's model request and marks the session interrupted, and keeps running itself.
|
|
244
|
+
|
|
245
|
+
**OpenCode.** The `opencode` platform runs your installed OpenCode, either major version, as `opencode run`; the reply is its standard output. Agent work is that command with the prompt on stdin, your `args` as written, `--model` when akm names a model and `--agent` when the asset names an agent. Your OpenCode owns its configuration, logins, token refresh and sessions: akm reads, copies and embeds nothing of yours.
|
|
246
|
+
- OpenCode 2 runs agent work through its own background service, which stays up after the command. Add `--standalone` to the harness's `args` for a run that is one process.
|
|
247
|
+
- A model name is OpenCode's `provider/model`, from the request, else the `--model` in the harness's `args`; without one, your OpenCode's default decides.
|
|
248
|
+
|
|
249
|
+
Nobody can answer an akm run. OpenCode's headless `run` cancels every question
|
|
250
|
+
and rejects every permission request that would ask, and the model carries on
|
|
251
|
+
without it; that holds for akm's own runtime and for the `opencode` harness
|
|
252
|
+
alike.
|
|
253
|
+
|
|
254
|
+
### Without a harness
|
|
255
|
+
|
|
256
|
+
Agent work runs on akm's own runtime when no harness is configured: a pinned
|
|
257
|
+
OpenCode 2 binary (2.1.4) that akm runs as a process for each run, driven by the
|
|
258
|
+
default connection. The npm package and the standalone binary do the same.
|
|
259
|
+
|
|
260
|
+
- **The first run fetches OpenCode.** akm downloads the binary for your platform
|
|
261
|
+
from the npm registry, one package of about 114 MB (240 MB on disk), checks it
|
|
262
|
+
against the registry's integrity hash, and keeps it in
|
|
263
|
+
`<akm cache dir>/opencode/2.1.4/`; later runs, and later versions of akm that
|
|
264
|
+
pin the same OpenCode, fetch nothing. Nothing else is downloaded: the binary
|
|
265
|
+
carries the package it reaches the endpoint with. If the fetch fails the run
|
|
266
|
+
fails as not started, naming the package, its URL and the cache path. With no
|
|
267
|
+
network access for this step, enable the `opencode` harness with an installed
|
|
268
|
+
OpenCode 2 instead: no setting points akm's runtime at a binary of your own.
|
|
269
|
+
On Alpine (musl) the binary needs `libstdc++` and `libgcc`: the Alpine Node
|
|
270
|
+
image has them, a bare Alpine needs `apk add libstdc++ libgcc`. akm's cache
|
|
271
|
+
and data directories must not be mounted `noexec`: the binary runs from the
|
|
272
|
+
first and unpacks its own native pieces into the second.
|
|
273
|
+
- It uses your connections. The connection a run is dispatched with (its
|
|
274
|
+
endpoint, key, model and context window, as they were when the run was planned)
|
|
275
|
+
is the process's only provider, so a connection edited or removed afterwards
|
|
276
|
+
cannot redirect a run that was already planned. Your OpenCode's configuration is
|
|
277
|
+
not read: its config, data, cache, state and temp directories are akm's, under
|
|
278
|
+
`<akm data dir>/opencode-runtime/`, so none of your plugins, MCP servers or
|
|
279
|
+
agents load, and no `OPENCODE_*` variable of your environment reaches it.
|
|
280
|
+
OpenCode still reads `~/.agents` and its system config (`/etc/opencode`, or
|
|
281
|
+
macOS managed preferences); a project's `AGENTS.md` and `opencode.json` and
|
|
282
|
+
your Claude Code skills (`~/.claude/skills`) are not read; OpenCode's free
|
|
283
|
+
models and its model-catalog fetch are off.
|
|
284
|
+
- It has OpenCode's default agent and tools, editing files and running commands
|
|
285
|
+
included, and akm's `akm_search`, `akm_show` and `akm_curate`, which run the
|
|
286
|
+
`akm` that started the run. A request's `persona` goes in the prompt, as for
|
|
287
|
+
the `opencode` harness.
|
|
288
|
+
- The connection's request fields (`reasoning_effort`, `top_p`, a `max_tokens`
|
|
289
|
+
and the rest) are sent with each model request as written. OpenCode's own
|
|
290
|
+
output cap is not: a request carries the cap the connection or the call writes,
|
|
291
|
+
and none otherwise, as a direct request does.
|
|
292
|
+
- Its sessions are in `<akm data dir>/opencode-runtime/data/opencode/opencode.db`,
|
|
293
|
+
and all of its files under `<akm data dir>/opencode-runtime/`. Nothing is
|
|
294
|
+
written under `~/.local/share/opencode`.
|
|
295
|
+
- The connection's key is in no process's environment: akm writes it for the
|
|
296
|
+
run to a file under `<akm data dir>/opencode-runtime/keys/` (readable by you
|
|
297
|
+
alone), names that file in the runtime's config, and removes it when the run
|
|
298
|
+
ends.
|
|
299
|
+
- The commands the agent runs get the environment akm runs in, with the
|
|
300
|
+
directories this akm resolved and the run's variables set over it, less your
|
|
301
|
+
`OPENCODE_*` variables. What akm sets for the OpenCode process itself (its
|
|
302
|
+
directories and its OpenCode settings) is not in it: akm's plugin puts those
|
|
303
|
+
variables back to what akm runs in, or removes them, for each command.
|
|
304
|
+
- A run reports its session id and the tokens its turn used, read from that
|
|
305
|
+
session once the process has ended; a workflow's `budget.max_tokens` counts
|
|
306
|
+
them. A failed run is a non-zero exit with OpenCode's own message
|
|
307
|
+
(`non_zero_exit`), as for a harness.
|
|
308
|
+
- Runs that start together, in one akm process or several, wait while the first
|
|
309
|
+
run of this OpenCode version prepares its database alone.
|
|
310
|
+
|
|
311
|
+
## Credentials
|
|
312
|
+
|
|
313
|
+
akm reads an API key from one of two places, and nowhere else:
|
|
314
|
+
|
|
315
|
+
- **A `$VAR` reference.** `"apiKey": "$LOCAL_LLM_KEY"` (or `"${LOCAL_LLM_KEY}"`)
|
|
316
|
+
names an environment variable, read when the call is made. An unset or empty
|
|
317
|
+
variable is warned about once and the request goes without a key.
|
|
318
|
+
- **`credentials.json`.** With no `apiKey`, the key is the entry stored for the
|
|
319
|
+
block in `credentials.json`, next to `config.json`, written with mode 0600:
|
|
320
|
+
|
|
321
|
+
```json
|
|
322
|
+
{ "connections": { "<name>": { "key": "…", "endpoint": "…" } },
|
|
323
|
+
"services": { "embedding": { "key": "…", "endpoint": "…" } } }
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
A key is stored for one endpoint and read for that endpoint alone. Change a
|
|
327
|
+
block's endpoint and the old key is not sent to the new one (it is named once,
|
|
328
|
+
without its value, and the block goes without until a key is stored for the new
|
|
329
|
+
endpoint). A connection's name and a service (`embedding`, `curateRerank`) are
|
|
330
|
+
different namespaces, so a connection called `embedding` and the embedding
|
|
331
|
+
service hold different keys. An `embedding` that runs on the default connection
|
|
332
|
+
uses that connection's entry. A connection that only an `extends` base defines
|
|
333
|
+
gets its endpoint from that base, so it never uses a stored key: stored keys
|
|
334
|
+
are for the connections your own `config.json` names (name it there, even with
|
|
335
|
+
only its `models`, and a key stored for the endpoint it ends up with is used).
|
|
336
|
+
A key in the older flat `{ "<name>": "<key>" }` form names no endpoint and is
|
|
337
|
+
not used; `akm migrate apply` files it under the endpoint your own config gives
|
|
338
|
+
that block, after copying `credentials.json` to `<cache dir>/config-backups/`.
|
|
339
|
+
A block that already has a stored key is never overwritten by it: the same key
|
|
340
|
+
for the same endpoint just drops the older entry, and any other leaves both in
|
|
341
|
+
the file, with a note. A flat key called `connections` or `services` (a
|
|
342
|
+
connection of that name) is told from the namespace of that name by its shape and
|
|
343
|
+
filed first; until it is, a write that would replace it stops with an error
|
|
344
|
+
instead.
|
|
345
|
+
|
|
346
|
+
`akm setup` asks for a key at a masked prompt and stores it in
|
|
347
|
+
`credentials.json` for the endpoint it was typed for; `--api-key-env NAME` sets
|
|
348
|
+
`apiKey: "$NAME"` instead. Setup an endpoint change that comes with no key does
|
|
349
|
+
not carry the old key to the new endpoint (a `$VAR` is dropped from the entry, a
|
|
350
|
+
stored key stays for the old endpoint), and says so. A key
|
|
351
|
+
is never written to `config.json` or passed on a command line. A literal
|
|
352
|
+
`apiKey` in the file, or a `${secrets/...}` reference, is warned about once and
|
|
353
|
+
ignored (never sent), and `akm config set` refuses to write one. `akm migrate
|
|
354
|
+
apply` moves such a key into `credentials.json`. The key is sent as
|
|
355
|
+
`Authorization: Bearer <key>` and redacted from everything akm prints and logs.
|
|
356
|
+
|
|
357
|
+
The bundle's `secrets/` store, `akm secret` and `akm env` are for the secrets
|
|
358
|
+
your own agents and tasks need, and have nothing to do with these keys.
|
|
359
|
+
|
|
360
|
+
## Aliases
|
|
361
|
+
|
|
362
|
+
A model alias names "a model of this kind", so the same bundle means the same
|
|
363
|
+
thing on every machine. `fast`, `balanced` and `reasoning` are the standard
|
|
364
|
+
ones; add any other you like. A connection's `models` and a harness's `models`
|
|
365
|
+
say which of their models answers each:
|
|
366
|
+
|
|
367
|
+
```jsonc
|
|
304
368
|
{
|
|
305
|
-
"
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
"
|
|
309
|
-
},
|
|
310
|
-
"reasoning": {
|
|
311
|
-
"claude": {
|
|
312
|
-
"inference": {
|
|
313
|
-
"effort": "medium"
|
|
314
|
-
}
|
|
315
|
-
},
|
|
316
|
-
"local-reasoner": {
|
|
317
|
-
"model": "qwen3:30b",
|
|
318
|
-
"inference": {
|
|
319
|
-
"effort": "high"
|
|
320
|
-
}
|
|
321
|
-
}
|
|
369
|
+
"connections": {
|
|
370
|
+
"default": {
|
|
371
|
+
"endpoint": "http://localhost:11434/v1",
|
|
372
|
+
"models": { "fast": "qwen3-8b", "balanced": "qwen3-32b", "reasoning": "qwen3-32b" }
|
|
322
373
|
}
|
|
323
|
-
}
|
|
374
|
+
},
|
|
375
|
+
"harnesses": { "claude": { "models": { "fast": "claude-haiku-4-5-20251001" } } }
|
|
324
376
|
}
|
|
325
377
|
```
|
|
326
378
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
`
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
379
|
+
A model is asked for by `model:` in an asset's frontmatter, `--model` on a
|
|
380
|
+
command, or `model` on an improve process, and it is an alias or an exact model
|
|
381
|
+
name:
|
|
382
|
+
- An alias is looked up in the selected connection's `models` (or harness's).
|
|
383
|
+
- A name that is not an alias is used as written.
|
|
384
|
+
- An alias the connection does not map answers with its first model. A
|
|
385
|
+
connection with no `models` at all cannot answer an alias; the error names
|
|
386
|
+
`akm models set`.
|
|
387
|
+
- A harness passes no model for an alias it has none for, and the program uses
|
|
388
|
+
its own default; when the harness maps other aliases, akm says so once. Claude
|
|
389
|
+
Code ships a map (`fast` Haiku 4.5, `balanced` Sonnet 4.6, `reasoning` Opus
|
|
390
|
+
4.7), which a `models` entry overrides. No other harness ships one. A
|
|
391
|
+
harness is passed the model name only: an alias written as an object
|
|
392
|
+
(`{ "model": "...", "effort": "high" }`) gives its `model`, and akm says once
|
|
393
|
+
that its other fields are ignored.
|
|
394
|
+
|
|
395
|
+
A kind of work that names no model asks for a default alias: improve's
|
|
396
|
+
processes, the index passes, extraction and `akm remember --enrich` ask for
|
|
397
|
+
`fast`; the quality and triage judges and a workflow gate ask for `balanced`;
|
|
398
|
+
agent work asks for `balanced`.
|
|
399
|
+
|
|
400
|
+
`akm models` lists a connection's aliases, then the models its endpoint lists,
|
|
401
|
+
and `akm models set <alias> <model>` changes one; see the [CLI
|
|
402
|
+
reference](cli.md#models). A harness's `models` is edited with `akm config set`.
|
|
403
|
+
|
|
404
|
+
## Where each process runs
|
|
405
|
+
|
|
406
|
+
akm's work is of two kinds, and each has a default place to run.
|
|
407
|
+
|
|
408
|
+
- **Model work** asks a model for an answer with nobody watching: the improve
|
|
409
|
+
processes (reflect, distill, consolidate, memory inference, extract, and
|
|
410
|
+
validation's repair), the quality and triage judges, the judge of a workflow
|
|
411
|
+
`### gate`, the index passes, and `akm remember --enrich`. It runs on the
|
|
412
|
+
default connection, as a direct request to the endpoint. With no connection it
|
|
413
|
+
runs on the default harness, unless that harness has `modelWork: false`. On a
|
|
414
|
+
harness it is akm's own process, not your use of the program ([How akm runs a
|
|
415
|
+
harness](#how-akm-runs-a-harness)).
|
|
416
|
+
- **Agent work** runs an agent: `akm agent`, `akm command run`, `akm proposal
|
|
417
|
+
new`, agent tasks and workflow agent steps. It runs on the default harness.
|
|
418
|
+
With no harness it runs on akm's own runtime, over the default connection.
|
|
419
|
+
|
|
420
|
+
With neither a connection nor a harness, model features and agent work are off:
|
|
421
|
+
each command that needs one says so and points at `akm setup`, and everything
|
|
422
|
+
that needs no model keeps working.
|
|
423
|
+
|
|
424
|
+
Anywhere a connection or harness can be named (config, a flag, an asset's
|
|
425
|
+
`connection:` or `harness:`) and none is, the default is used. A name that is
|
|
426
|
+
not configured is an error (exit 78), never a reason to use the default: the
|
|
427
|
+
message names the selector, says it is not configured, lists the configured
|
|
428
|
+
connections (or harnesses) and the nearest name when one is close, and the same
|
|
429
|
+
holds for the retired `engine:` and `--engine`. Defaults apply only when nothing
|
|
430
|
+
was named, so a call for a private connection is never sent to a remote service,
|
|
431
|
+
nor a call that must not touch files to a harness that can, by a typo, a removed
|
|
432
|
+
entry, or an entry akm ignored when it loaded the config (`akm health` lists
|
|
433
|
+
what is configured).
|
|
434
|
+
|
|
435
|
+
A harness is named by its name or by its platform, so a shared asset that says
|
|
436
|
+
`harness: claude` runs wherever Claude Code is set up, whatever the entry is
|
|
437
|
+
called. The name comes first. Failing that, the one harness that runs the
|
|
438
|
+
platform (its `platform`, else its key) is chosen; when several do, the one
|
|
439
|
+
named `default` is, and with none named `default` the call fails like any
|
|
440
|
+
unconfigured name, naming them. akm never picks the first.
|
|
441
|
+
|
|
442
|
+
These settings, all optional, choose another place for one piece of work:
|
|
443
|
+
|
|
444
|
+
| Key | Chooses where |
|
|
445
|
+
| --- | --- |
|
|
446
|
+
| `improve.connection`, `improve.harness` | All of `akm improve`'s model work |
|
|
447
|
+
| `improve.processes.<process>` | One improve process: `reflect`, `distill`, `consolidate`, `memoryInference`, `extract`, `validation`, or `triage` (its judgment) |
|
|
448
|
+
| `improve.qualityGate` | The judge of the reflect and distill quality gates |
|
|
449
|
+
| `index.connection`, `index.<pass>` | The index passes (`index.memory`) |
|
|
450
|
+
|
|
451
|
+
Each takes `connection` or `harness`, `model` (an alias or a name), `llm` (the
|
|
452
|
+
[settings a call asks for](#settings-a-call-asks-for)) and `timeoutMs`. A pass
|
|
453
|
+
under `index` takes `connection`, not `harness` (one that names nothing runs
|
|
454
|
+
where model work does: the default connection, else the default harness), and
|
|
455
|
+
`enabled: false` turns it off:
|
|
456
|
+
|
|
457
|
+
```jsonc
|
|
342
458
|
{
|
|
343
|
-
"
|
|
344
|
-
|
|
345
|
-
"
|
|
346
|
-
"
|
|
347
|
-
|
|
348
|
-
|
|
459
|
+
"improve": {
|
|
460
|
+
"connection": "default",
|
|
461
|
+
"processes": {
|
|
462
|
+
"reflect": { "connection": "cloud", "model": "reasoning" },
|
|
463
|
+
"memoryInference": { "model": "qwen3-8b", "llm": { "temperature": 0.1 } }
|
|
464
|
+
},
|
|
465
|
+
"qualityGate": { "connection": "judge", "llm": { "enableThinking": true } }
|
|
466
|
+
},
|
|
467
|
+
"index": { "connection": "default", "memory": { "enabled": false } }
|
|
349
468
|
}
|
|
350
469
|
```
|
|
351
470
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
so the value must already be meaningful for the column's platform (e.g. a
|
|
361
|
-
`kind: "agent", platform: "opencode"` engine's `model` should already be a
|
|
362
|
-
string opencode itself understands, such as `krang/qwen3.5-9b`). Run
|
|
363
|
-
`akm models list` to see, for every alias/column, the resolved model and
|
|
364
|
-
whether it came from the installed defaults, the user overlay, and a literal
|
|
365
|
-
value or an `engine` reference.
|
|
366
|
-
|
|
367
|
-
The user file overlays the installed file by alias, engine, and nested object
|
|
368
|
-
field. Objects merge recursively. Arrays, scalars, and explicit `null` replace
|
|
369
|
-
the lower value; omitted fields preserve it. A layer setting a literal `model`
|
|
370
|
-
clears any `engine` inherited from a farther layer, and vice versa — the
|
|
371
|
-
nearer layer's choice of literal-vs-engine always wins outright rather than
|
|
372
|
-
merging. Alias and engine keys are case-normalized, and case-colliding
|
|
373
|
-
definitions are rejected. Unknown model inputs still pass through
|
|
374
|
-
byte-for-byte as exact identifiers. Once a name is a known merged alias,
|
|
375
|
-
selecting an engine with no mapping is an actionable configuration error
|
|
376
|
-
rather than silently sending the alias as a model ID.
|
|
377
|
-
|
|
378
|
-
The common execution cascade reads these files for current direct command and
|
|
379
|
-
non-interactive agent calls, task source v4 runs, and improve/proposal/index
|
|
380
|
-
model work routed through that resolver. A structured alias expands as
|
|
381
|
-
defaults at the layer that selected it; explicit sibling fields and nearer
|
|
382
|
-
layers still win. The resulting request carries the exact model ID and merged
|
|
383
|
-
inference object. Engine lowerers consume that exact selection and never run
|
|
384
|
-
alias resolution again. New workflow starts persist the exact request and
|
|
385
|
-
symbolic runner selection in the durable plan v4 family's executable
|
|
386
|
-
`irVersion: 5`; resume consumes that frozen material without resolving aliases
|
|
387
|
-
again.
|
|
388
|
-
|
|
389
|
-
Copy the complete installed starter into the user configuration directory when
|
|
390
|
-
you want to customize all fields:
|
|
471
|
+
The nearest setting wins, farthest to nearest: the shipped alias of the kind of
|
|
472
|
+
work, `improve.connection` and `improve.harness`, the process's entry in
|
|
473
|
+
`improve.processes`, and `--connection`, `--harness` and `--model` on the run,
|
|
474
|
+
which reach every call in it, the judges included. The quality-gate judge is the
|
|
475
|
+
exception: a process's own entry is the writer's, so `improve.qualityGate`
|
|
476
|
+
replaces it, and a `reasoning` model chosen for reflect is not the one that
|
|
477
|
+
judges it. An index pass reads `index.*`, then `index.<pass>`. A strategy adds no
|
|
478
|
+
layer: it says which processes run, never where.
|
|
391
479
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
akm models copy-defaults --overwrite # explicit replacement confirmation
|
|
395
|
-
```
|
|
480
|
+
`akm health` and `akm info` print this as a table, resolved by the same code the
|
|
481
|
+
calls use: for each kind of work, the connection or harness and the model.
|
|
396
482
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
that never follows the target when it is a symlink. AKM verifies the observed
|
|
405
|
-
regular-file identity again immediately before rename, but the portable
|
|
406
|
-
filesystem APIs do not provide a conditional compare-and-swap rename. Another
|
|
407
|
-
process can still change the directory entry after that check; AKM replaces
|
|
408
|
-
the entry at the pathname without dereferencing it. Consequently,
|
|
409
|
-
`overwritten: true` means overwrite was requested for an entry AKM observed,
|
|
410
|
-
not that an inode identity was transactionally locked. Symlinks and other
|
|
411
|
-
non-regular targets observed at either check are refused.
|
|
412
|
-
|
|
413
|
-
AKM does not auto-create or sync this file, and authoritative defaults never
|
|
414
|
-
live in the cache. npm/Node and normal Bun installs read the packaged
|
|
415
|
-
`dist/assets/models.json` lazily, so `akm health` can report a missing or
|
|
416
|
-
malformed package asset as a `model-map-files` failure. A standalone binary has
|
|
417
|
-
the same authoritative bytes embedded at compile time and therefore has no
|
|
418
|
-
external model-map asset that can later disappear; its health check validates
|
|
419
|
-
the embedded copy, and release tests pin copied bytes to `src/assets/models.json`.
|
|
420
|
-
The health check passes when the optional user file is absent and warns with
|
|
421
|
-
its path and JSON location when the user file is unreadable or invalid.
|
|
422
|
-
|
|
423
|
-
`defaults.engine` names an LLM or agent engine. `defaults.llmEngine` names the
|
|
424
|
-
default engine for unattended model work, so it follows
|
|
425
|
-
[the one rule](#engines-for-unattended-model-work). There is no first-engine
|
|
426
|
-
fallback: an unset `defaults.engine`
|
|
427
|
-
never resolves to some arbitrary entry in `engines`. It resolves instead to a
|
|
428
|
-
synthesized, config-free `opencode-sdk` engine when the `opencode` binary is on
|
|
429
|
-
PATH — announced once per run, and preempted by any `opencode-sdk` engine you
|
|
430
|
-
configure yourself. Naming an engine that is not configured is always an error
|
|
431
|
-
and is never rescued by that fallback.
|
|
432
|
-
|
|
433
|
-
`defaults.llmEngine` is not an `opencode-sdk` engine's fallback connection. An
|
|
434
|
-
SDK engine gets an LLM fallback only from its own `llmEngine`, so the
|
|
435
|
-
synthesized engine, which sets none, runs on opencode's own provider, model and
|
|
436
|
-
auth.
|
|
437
|
-
|
|
438
|
-
Index passes select engines through `index.defaults.engine` or
|
|
439
|
-
`index.<pass>.engine`, which follow
|
|
440
|
-
[the one rule](#engines-for-unattended-model-work). Per-pass `model`, `timeoutMs`, and `llm` fields are
|
|
441
|
-
invocation overrides; `enabled: false` disables that pass. Connection fields
|
|
442
|
-
such as `endpoint`, `provider`, `apiKey`, and `apiKeyFile` belong only on
|
|
443
|
-
named engines.
|
|
444
|
-
|
|
445
|
-
`workflow.maxConcurrency` is the native workflow engine ceiling. An explicit
|
|
446
|
-
value is clamped to `1..64`. When absent, AKM derives the cap once from the CPU
|
|
447
|
-
count (`min(16, max(1, cores - 2))`) and freezes it into the run plan, so resume
|
|
448
|
-
does not change policy on a different host or after config edits.
|
|
483
|
+
## Workflows
|
|
484
|
+
|
|
485
|
+
`workflow.maxConcurrency` is the ceiling on units a workflow run executes at
|
|
486
|
+
once. An explicit value is clamped to `1..64`. When absent, akm derives it once
|
|
487
|
+
from the CPU count (`min(16, max(1, cores - 2))`) and freezes it into the run
|
|
488
|
+
plan, so resuming on a different host or after a config edit does not change the
|
|
489
|
+
policy.
|
|
449
490
|
|
|
450
491
|
`workflow.defaultMapConcurrency` is the width a `map` step freezes when it
|
|
451
|
-
declares no `concurrency:` of its own. Unset means
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
`
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
completion criteria and is frozen into each new run, so later config edits do
|
|
463
|
-
not change an in-flight run's verifier. Missing, failed, or malformed verifier
|
|
464
|
-
results reject the gate; criteria are never silently bypassed.
|
|
492
|
+
declares no `concurrency:` of its own. Unset means 4. An explicit value is
|
|
493
|
+
clamped to `1..64`; set it to `1` for serial fan-out. It is only a default: an
|
|
494
|
+
authored `map.concurrency` always wins, and a step never runs wider than
|
|
495
|
+
`workflow.maxConcurrency`, the selected connection's `concurrency`, or the host
|
|
496
|
+
CPU cap.
|
|
497
|
+
|
|
498
|
+
The judge of a `### gate` rubric is model work, so a workflow with completion
|
|
499
|
+
criteria needs a connection or a harness before a new run can be frozen. The
|
|
500
|
+
choice is frozen into each run, so later config edits do not change an
|
|
501
|
+
in-flight run's verifier. A missing, failed or malformed verdict rejects the
|
|
502
|
+
gate; criteria are never silently bypassed.
|
|
465
503
|
|
|
466
504
|
## Strategies
|
|
467
505
|
|
|
468
506
|
Improve presets live under `improve.strategies`; invoke one with
|
|
469
507
|
`akm improve --strategy <name>`. The selection order is `--strategy`,
|
|
470
|
-
`
|
|
471
|
-
|
|
508
|
+
`improve.strategy`, then built-in `default`. A strategy says which processes run
|
|
509
|
+
and how each is tuned (`enabled`, limits, gates), never where: where each process
|
|
510
|
+
runs is [Where each process runs](#where-each-process-runs), whichever strategy
|
|
511
|
+
is selected.
|
|
472
512
|
|
|
473
513
|
```jsonc
|
|
474
514
|
{
|
|
475
515
|
"improve": {
|
|
516
|
+
"strategy": "nightly",
|
|
476
517
|
"strategies": {
|
|
477
518
|
"nightly": {
|
|
478
|
-
"engine": "fast",
|
|
479
519
|
"processes": {
|
|
480
|
-
"reflect": { "
|
|
481
|
-
"memoryInference": { "
|
|
520
|
+
"reflect": { "limit": 10 },
|
|
521
|
+
"memoryInference": { "enabled": false }
|
|
482
522
|
}
|
|
483
523
|
}
|
|
484
524
|
}
|
|
@@ -486,32 +526,24 @@ can select `engine`, `model`, `timeoutMs`, and LLM request overrides:
|
|
|
486
526
|
}
|
|
487
527
|
```
|
|
488
528
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
`
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
`
|
|
505
|
-
`
|
|
506
|
-
|
|
507
|
-
`processes.triage.judgment` explicitly controls the optional judgment tier.
|
|
508
|
-
Use `true` to enable it, `false` to disable it, or an object with `enabled`,
|
|
509
|
-
`engine`, `model`, `timeoutMs`, and/or `llm` overrides. Existing object values
|
|
510
|
-
such as `{}` and `{ "engine": "reviewer" }` remain enabled by default. Unknown
|
|
511
|
-
object keys are rejected so misspellings cannot silently change execution;
|
|
512
|
-
the retired `mode` and `profile` keys continue to report their engine migration
|
|
513
|
-
guidance. When enabled, engine selection is judgment → triage → strategy →
|
|
514
|
-
`defaults.llmEngine`, and resolution fails closed if none is available.
|
|
529
|
+
The built-in strategies are `default` and `consolidate`. `consolidate` is a
|
|
530
|
+
patch that is deep-merged onto `default`, and a user-defined strategy of the
|
|
531
|
+
same name is merged on top of that; so every strategy, built-in or user-defined,
|
|
532
|
+
inherits omitted fields from `default`. A name that is neither built-in nor
|
|
533
|
+
defined under `improve.strategies` is refused: `improve.strategy` when the config
|
|
534
|
+
loads, `--strategy` when the command runs. A block named `quick`, `thorough`,
|
|
535
|
+
`catchup`, `reflect-distill` or `proactive-maintenance` is an ordinary
|
|
536
|
+
user-defined strategy that inherits `default`, and `--strategy` naming one with
|
|
537
|
+
no such block fails with an error that names `default`. For a judged triage
|
|
538
|
+
drain, set `processes.triage` (`enabled`, `applyMode: "promote"`,
|
|
539
|
+
`judgment: true`) in your own strategy.
|
|
540
|
+
|
|
541
|
+
`processes.triage.judgment` controls the optional judgment tier: `true` enables
|
|
542
|
+
it, `false` disables it, and an object holds `enabled` (default `true`). The
|
|
543
|
+
judgment is a model call; it runs where `improve.processes.triage` says
|
|
544
|
+
(`connection` or `harness`, `model`, `llm`, `timeoutMs`), over `improve.connection`
|
|
545
|
+
and `improve.harness`, and over the defaults. Enabling it with no connection or
|
|
546
|
+
harness configured fails before the run starts, naming `akm setup`.
|
|
515
547
|
|
|
516
548
|
The `default` strategy runs triage in `promote` mode with judgment off and
|
|
517
549
|
`maxAcceptsPerRun: 200` (#1143), so the proposal backlog drains through the
|
|
@@ -532,14 +564,10 @@ gpt-5.6-terra it was very cautious (precision 1.0, recall 0.17).
|
|
|
532
564
|
```jsonc
|
|
533
565
|
{
|
|
534
566
|
"improve": {
|
|
567
|
+
"processes": { "triage": { "harness": "claude" } },
|
|
535
568
|
"strategies": {
|
|
536
569
|
"nightly": {
|
|
537
|
-
"processes": {
|
|
538
|
-
"triage": {
|
|
539
|
-
"enabled": true,
|
|
540
|
-
"judgment": { "enabled": true, "engine": "reviewer" }
|
|
541
|
-
}
|
|
542
|
-
}
|
|
570
|
+
"processes": { "triage": { "enabled": true, "judgment": true } }
|
|
543
571
|
}
|
|
544
572
|
}
|
|
545
573
|
}
|
|
@@ -552,38 +580,30 @@ each process's LLM-as-judge quality gate. Each is on unless it sets
|
|
|
552
580
|
judge passes is staged for the triage drain to accept; a distill lesson it
|
|
553
581
|
passes is deferred for a person (reason `distill-review`), which the drain and
|
|
554
582
|
its judgment tier leave alone. With the distill gate off nothing is judged, and
|
|
555
|
-
the drain decides. The judge is
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
temperature 0 with thinking off unless its
|
|
583
|
+
the drain decides. The judge is a model call that
|
|
584
|
+
runs where `improve.qualityGate` says (`connection` or `harness`, `model`, `llm`,
|
|
585
|
+
`timeoutMs`), for both gates, over `improve.connection` and `improve.harness`
|
|
586
|
+
and the defaults: with no `qualityGate`, the default connection answers with its
|
|
587
|
+
`balanced` model. The process's own entry in `improve.processes` is the writer's
|
|
588
|
+
and does not reach the judge. The judge may be a connection or a harness; a
|
|
589
|
+
harness that cannot be restricted runs it unrestricted, with a notice ([How akm
|
|
590
|
+
runs a harness](#how-akm-runs-a-harness)). It runs
|
|
591
|
+
at temperature 0 with thinking off unless its connection turns thinking on.
|
|
564
592
|
Thinking is slow: on a 27B llama.cpp server, a thinking judgment took a median
|
|
565
593
|
of 30–67 s and up to about 3 minutes, against about 5 s without.
|
|
566
594
|
Behind a gateway that drops `chat_template_kwargs` (Bifrost), point a thinking
|
|
567
|
-
judge's
|
|
595
|
+
judge's connection at the server directly.
|
|
568
596
|
|
|
569
597
|
```jsonc
|
|
570
598
|
{
|
|
571
|
-
"
|
|
599
|
+
"connections": {
|
|
572
600
|
"judge": {
|
|
573
|
-
"
|
|
574
|
-
"
|
|
575
|
-
"model": "qwen3-27b",
|
|
576
|
-
"enableThinking": true
|
|
601
|
+
"endpoint": "http://127.0.0.1:8080/v1",
|
|
602
|
+
"models": { "balanced": "qwen3-27b" }
|
|
577
603
|
}
|
|
578
604
|
},
|
|
579
605
|
"improve": {
|
|
580
|
-
"
|
|
581
|
-
"nightly": {
|
|
582
|
-
"processes": {
|
|
583
|
-
"reflect": { "qualityGate": { "engine": "judge" } }
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
}
|
|
606
|
+
"qualityGate": { "connection": "judge", "llm": { "enableThinking": true } }
|
|
587
607
|
}
|
|
588
608
|
}
|
|
589
609
|
```
|
|
@@ -658,7 +678,7 @@ metadata placed before body content.
|
|
|
658
678
|
|
|
659
679
|
## Semantic search
|
|
660
680
|
|
|
661
|
-
`semanticSearchMode` (top-level, `"off" | "auto"`, default `"off"`) gates
|
|
681
|
+
`semanticSearchMode` (top-level, `"off" | "auto"`, default `"off"`, or `"auto"` when `embedding` is set) gates
|
|
662
682
|
embedding-based search. `"auto"` lets AKM set up embeddings (which downloads
|
|
663
683
|
a local model unless you point `embedding` at a remote provider) and falls
|
|
664
684
|
back to keyword-only FTS if the embedding runtime is unavailable; `"off"`
|
|
@@ -669,14 +689,26 @@ This is distinct from `searchMode: "keyword"`, which is the normal result when
|
|
|
669
689
|
semantic search is disabled or has not been built. A read-only sandbox that
|
|
670
690
|
cannot record best-effort usage telemetry does not by itself mark search as
|
|
671
691
|
degraded.
|
|
672
|
-
The
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
692
|
+
The local embedder runs its model (`Xenova/bge-small-en-v1.5` unless
|
|
693
|
+
`embedding.localModel` names another) on `onnxruntime-node`, with
|
|
694
|
+
`@huggingface/tokenizers` for the token ids. Both are normal dependencies of the
|
|
695
|
+
package, imported directly; AKM does not carry a copied runtime under `src/` or
|
|
696
|
+
`dist/`. The model's four files (about 127 MB) are fetched from the Hugging Face
|
|
697
|
+
Hub on first use into `$HF_HOME/<repo>/` (default `<cache dir>/models`), and
|
|
698
|
+
`HF_HUB_OFFLINE=1` forbids the fetch. `akm index --format json` reports the
|
|
699
|
+
runtime it embedded with as `verification.embeddingRuntime`.
|
|
700
|
+
If the runtime cannot load, because the dependency is missing or the platform
|
|
701
|
+
has no native ONNX Runtime library (Alpine/musl, Intel macOS), the index reports
|
|
702
|
+
semantic search `blocked` with the reason and search stays keyword-only:
|
|
703
|
+
reinstall `akm-cli` for a missing dependency, or configure a remote
|
|
704
|
+
`embedding.endpoint`. A standalone binary copies the library it embeds once into
|
|
705
|
+
`<cache dir>/onnxruntime/` (see
|
|
706
|
+
[Getting Started](../guides/getting-started.md#standalone-binary-and-semantic-search)).
|
|
707
|
+
Setup does not mutate a global installation to add runtime packages.
|
|
677
708
|
The default is `"off"` so a bare or headless install (`akm bundle create`, `--yes`,
|
|
678
709
|
`--config`) never silently downloads the local embedding model on first
|
|
679
|
-
index.
|
|
710
|
+
index. A config that has an `embedding` block and sets no `semanticSearchMode`
|
|
711
|
+
reads as `"auto"`: writing the block says semantic search is wanted.
|
|
680
712
|
The interactive `akm setup` wizard pre-selects semantic search **on**
|
|
681
713
|
regardless of this default, and warns that choosing it downloads the model
|
|
682
714
|
unless a remote `embedding` config is provided.
|
|
@@ -687,11 +719,15 @@ unless a remote `embedding` config is provided.
|
|
|
687
719
|
|
|
688
720
|
`embedding` configures the connection used for semantic search and
|
|
689
721
|
`akm improve`'s memory-inference/consolidate passes when they call an
|
|
690
|
-
embedding model: `provider`, `endpoint`, `model`, `apiKey` (
|
|
691
|
-
|
|
722
|
+
embedding model: `provider`, `endpoint`, `model`, `apiKey` (a `$VAR` reference,
|
|
723
|
+
or the `embedding` service's entry in `credentials.json`; see
|
|
724
|
+
[Credentials](#credentials)), `dimension`, `localModel`,
|
|
692
725
|
`maxInputTokens`, `maxTokens`, `batchSize`, `contextLength`, `timeoutMs`,
|
|
693
726
|
`queryTimeoutMs`, `queryTemplate`, `documentTemplate`, `concurrency`, and
|
|
694
|
-
`ollamaOptions.num_ctx`.
|
|
727
|
+
`ollamaOptions.num_ctx`. An `embedding` with a `model` and no `endpoint` names a
|
|
728
|
+
model the default connection serves, at its endpoint and with its key; with no
|
|
729
|
+
default connection there is nothing to serve it, and the built-in local embedder
|
|
730
|
+
runs, with a warning.
|
|
695
731
|
|
|
696
732
|
Retrieval models expect a prompt around queries and documents. akm picks it by
|
|
697
733
|
model name (`src/llm/embedders/profile.ts`): Qwen3-Embedding gets
|
|
@@ -818,8 +854,8 @@ taking about the same wall time as a single one against a healthy endpoint.
|
|
|
818
854
|
### Curate rerank (#951)
|
|
819
855
|
|
|
820
856
|
An optional cross-encoder rerank pass over the top fused search candidates
|
|
821
|
-
`akm curate` fetches, via a standalone `/rerank`-style HTTP endpoint (
|
|
822
|
-
|
|
857
|
+
`akm curate` fetches, via a standalone `/rerank`-style HTTP endpoint (not a
|
|
858
|
+
connection or a harness). Each candidate is sent as its
|
|
823
859
|
name, description and the start of its indexed content (2,000 characters in
|
|
824
860
|
all). Disabled by default; a misconfigured endpoint, network failure, timeout,
|
|
825
861
|
or malformed response keeps the fused order.
|
|
@@ -829,7 +865,7 @@ or malformed response keeps the fused order.
|
|
|
829
865
|
| `search.curateRerank.enabled` | Turn the rerank pass on (default `false`) |
|
|
830
866
|
| `search.curateRerank.endpoint` | Full URL of the reranker's rerank endpoint |
|
|
831
867
|
| `search.curateRerank.model` | Model name sent to the endpoint (optional) |
|
|
832
|
-
| `search.curateRerank.apiKey` | `$VAR
|
|
868
|
+
| `search.curateRerank.apiKey` | `$VAR` reference (optional); absent, the `curateRerank` service's entry in `credentials.json` |
|
|
833
869
|
| `search.curateRerank.timeoutMs` | Request timeout (default `10000`) |
|
|
834
870
|
| `search.curateRerank.topN` | How many of the top fused candidates to rerank (default `30`, max `50`) |
|
|
835
871
|
|
|
@@ -943,16 +979,18 @@ section, an absent key, and an explicit `false` all read identically as off.
|
|
|
943
979
|
|
|
944
980
|
```sh
|
|
945
981
|
akm config list
|
|
946
|
-
akm config get
|
|
947
|
-
akm config set
|
|
948
|
-
akm config set
|
|
949
|
-
akm config unset
|
|
982
|
+
akm config get connections.default
|
|
983
|
+
akm config set connections.fast '{"endpoint":"http://localhost:11434/v1","models":{"fast":"qwen3-8b"}}'
|
|
984
|
+
akm config set connections.fast.apiKey '$LOCAL_LLM_API_KEY'
|
|
985
|
+
akm config unset connections.old
|
|
950
986
|
```
|
|
951
987
|
|
|
952
988
|
Object values passed to `config set` deep-merge with their current value.
|
|
953
989
|
Arrays replace, `null` is only valid for nullable fields, and `config unset` is
|
|
954
|
-
the only deletion operation.
|
|
955
|
-
|
|
990
|
+
the only deletion operation. It removes the named key and nothing else: a
|
|
991
|
+
parent object left empty stays, because `harnesses.opencode: {}` is how a
|
|
992
|
+
harness is enabled. `configVersion` cannot be set or unset with the generic
|
|
993
|
+
walker.
|
|
956
994
|
|
|
957
995
|
`config get <key> --show-source` wraps the (redacted) value as
|
|
958
996
|
`{ value, source }`, where `source` is `"local"` when the local file's own
|
|
@@ -962,20 +1000,19 @@ that sets it, or `"default"` when neither does. It is opt-in — plain
|
|
|
962
1000
|
|
|
963
1001
|
### Sharing configuration across installs
|
|
964
1002
|
|
|
965
|
-
Five hosts running the same fleet often carry an identical `
|
|
966
|
-
`improve.strategies` block, differing only in credential delivery
|
|
967
|
-
|
|
968
|
-
across hosts drifts silently. `extends` fixes this: put the shared block in
|
|
1003
|
+
Five hosts running the same fleet often carry an identical `connections` map and
|
|
1004
|
+
`improve.strategies` block, differing only in credential delivery, bundle paths,
|
|
1005
|
+
and cron offsets. Hand-syncing that block across hosts drifts silently. `extends` fixes this: put the shared block in
|
|
969
1006
|
one file, and have each host's local config extend it.
|
|
970
1007
|
|
|
971
1008
|
```jsonc
|
|
972
1009
|
// bundles/fleet/config/shared.json — versioned with the bundle, shared by every host
|
|
973
1010
|
{
|
|
974
1011
|
"configVersion": "0.9.0",
|
|
975
|
-
"
|
|
976
|
-
"fast": { "
|
|
1012
|
+
"connections": {
|
|
1013
|
+
"fast": { "endpoint": "https://api.example.test/v1", "models": { "fast": "qwen3", "balanced": "qwen3" } }
|
|
977
1014
|
},
|
|
978
|
-
"improve": { "strategies": { "nightly": { "
|
|
1015
|
+
"improve": { "connection": "fast", "strategies": { "nightly": { "processes": { "reflect": { "limit": 10 } } } } }
|
|
979
1016
|
}
|
|
980
1017
|
```
|
|
981
1018
|
|
|
@@ -989,7 +1026,7 @@ one file, and have each host's local config extend it.
|
|
|
989
1026
|
"stash": { "path": "~/akm-stash", "writable": true }
|
|
990
1027
|
},
|
|
991
1028
|
"defaultBundle": "stash",
|
|
992
|
-
"
|
|
1029
|
+
"connections": { "fast": { "apiKey": "$FAST_API_KEY" } }
|
|
993
1030
|
}
|
|
994
1031
|
```
|
|
995
1032
|
|
|
@@ -1010,10 +1047,11 @@ one file, and have each host's local config extend it.
|
|
|
1010
1047
|
|
|
1011
1048
|
Shared layers carry portable policy, not host authority. `bundles`, source and
|
|
1012
1049
|
write defaults, registries, embedding connections, scheduler activation,
|
|
1013
|
-
`
|
|
1014
|
-
|
|
1015
|
-
(`apiKey`, `
|
|
1016
|
-
the local file
|
|
1050
|
+
`experimental`, and setup state are ignored when inherited.
|
|
1051
|
+
Connection and harness definitions may be shared, but credentials and
|
|
1052
|
+
executable authority (`apiKey`, `bin`, `args`, and `workspace`) are ignored
|
|
1053
|
+
when inherited and must be supplied by the local file; a key in the host's
|
|
1054
|
+
`credentials.json` needs no entry at all. Improve publication (`strategies.*.sync`) and reranker network
|
|
1017
1055
|
configuration are local as well. Bundle-relative chains stay physically inside
|
|
1018
1056
|
the bundle root for every hop; lexical `..` paths and symlink escapes are both
|
|
1019
1057
|
rejected before a referenced file is read.
|
|
@@ -1057,9 +1095,6 @@ akm config diff fleet//config/shared.json
|
|
|
1057
1095
|
| Variable | Purpose |
|
|
1058
1096
|
| --- | --- |
|
|
1059
1097
|
| `AKM_CONFIG_DIR` | Override the user config directory (or set `XDG_CONFIG_HOME`) |
|
|
1060
|
-
| `AKM_ENGINE_<NAME>_API_KEY` | Fallback credential for LLM engine `<name>` |
|
|
1061
|
-
| `AKM_LLM_API_KEY` | Fallback only for the selected `defaults.llmEngine` |
|
|
1062
|
-
| `AKM_EMBED_API_KEY` | Embedding credential |
|
|
1063
1098
|
| `AKM_BUNDLE_DIR` | Override the bundle directory |
|
|
1064
1099
|
| `AKM_DATA_DIR` | Override the data directory — `index.db`, durable `state.db`, and `akm.lock` (or set `XDG_DATA_HOME`) |
|
|
1065
1100
|
| `AKM_CACHE_DIR` | Override the cache directory — regenerable caches (or set `XDG_CACHE_HOME`) |
|
|
@@ -1068,80 +1103,64 @@ akm config diff fleet//config/shared.json
|
|
|
1068
1103
|
| `AKM_VERBOSE` | Truthy value enables the same diagnostics as `--verbose` |
|
|
1069
1104
|
| `AKM_DEBUG` | `1` prints a stack trace on unexpected internal errors |
|
|
1070
1105
|
|
|
1071
|
-
For an engine named `fast`, its fallback variable is
|
|
1072
|
-
`AKM_ENGINE_FAST_API_KEY`. An explicit `apiKey` symbolic reference is
|
|
1073
|
-
authoritative and does not fall through to another variable.
|
|
1074
|
-
|
|
1075
|
-
`engines.<name>.apiKeyFile` is a file-backed alternative to `apiKey`, for a
|
|
1076
|
-
host that refuses to put secrets in the process environment (a container
|
|
1077
|
-
runtime's mounted secret, for example). It is a plain filesystem path — `~`
|
|
1078
|
-
expands to the home directory — read at dispatch time and trimmed of one
|
|
1079
|
-
trailing newline; the raw path is safe to keep in `config.json` since it is
|
|
1080
|
-
not itself a secret. Setting both `apiKey` and `apiKeyFile` on the same
|
|
1081
|
-
engine is rejected. A missing, unreadable, or empty file fails the call
|
|
1082
|
-
closed, naming the engine and path but never the file's content.
|
|
1083
|
-
|
|
1084
|
-
`engines.<name>.apiKey` also accepts `secret://<name>`, a reference into
|
|
1085
|
-
AKM's own secret store (`akm secret set <name> --from-file <file>`), for a
|
|
1086
|
-
launch context where the credential's environment variable is deliberately
|
|
1087
|
-
not sourced into the process — a scheduled task's crontab preamble, or a
|
|
1088
|
-
container entrypoint that keeps the user's env out on purpose — and a
|
|
1089
|
-
file-backed credential is not an option. Like `apiKeyFile`, only the
|
|
1090
|
-
reference is kept in `config.json`; the store lookup happens at dispatch
|
|
1091
|
-
time, and an unresolved reference fails the call closed, naming the
|
|
1092
|
-
reference but never the value. `akm improve`, workflow LLM steps, and `akm
|
|
1093
|
-
health`'s engine probes all resolve `secret://` the same way direct LLM and
|
|
1094
|
-
embedding calls have since 0.9.13 (#917); resolution order for a single
|
|
1095
|
-
`apiKey` field is: an env reference (`$VAR`/`${VAR}`) first, then
|
|
1096
|
-
`apiKeyFile`, then `secret://<name>` — though in practice a config sets only
|
|
1097
|
-
one of the three per engine.
|
|
1098
|
-
|
|
1099
|
-
`embedding.apiKey` accepts the same three forms and resolves `secret://` the
|
|
1100
|
-
same way, on every path that sends an embedding request: `akm index`
|
|
1101
|
-
(including the reindex `akm bundle update` runs and the targeted re-embed a
|
|
1102
|
-
write command like `akm remember` triggers), `akm improve`'s
|
|
1103
|
-
consolidate pass (memory dedup and similarity clustering). All of them build the
|
|
1104
|
-
provider request through the same `RemoteEmbedder`/`resolveSecret` boundary,
|
|
1105
|
-
so a `secret://` reference resolves identically regardless of which command
|
|
1106
|
-
triggered the request (#953).
|
|
1107
|
-
|
|
1108
1106
|
Use `AKM_SQLITE_JOURNAL_MODE=DELETE` or `TRUNCATE` when WAL is unavailable,
|
|
1109
1107
|
such as on some NFS/SMB mounts. With the default `WAL` setting, AKM detects a
|
|
1110
1108
|
network filesystem for the data directory and falls back to `DELETE`.
|
|
1111
1109
|
|
|
1112
1110
|
## Retired Configuration
|
|
1113
1111
|
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
`defaults.
|
|
1117
|
-
|
|
1118
|
-
`
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
`
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
`
|
|
1138
|
-
|
|
1139
|
-
`defaults.
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
`
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1112
|
+
A key akm no longer reads is named once, ignored, and dropped by `akm migrate
|
|
1113
|
+
apply`. That covers `profiles`, `llm`, `agent`, `features`, `stashes`,
|
|
1114
|
+
`defaults.llm`, `defaults.agent`, `defaults.improve`, the settings that sat
|
|
1115
|
+
under `index.<pass>` (`endpoint`, `provider`, `apiKey`, `baseUrl`,
|
|
1116
|
+
`temperature`, `maxTokens`, `capabilities`), `index.graph.*`, every strategy's
|
|
1117
|
+
`processes.graphExtraction.*`, a strategy's `processes.feedbackDistillation`
|
|
1118
|
+
(use `processes.distill.enabled`), `processes.consolidate.incrementalSince`
|
|
1119
|
+
and `neighborsPerChanged`, and `embedding.chunkSize`. The strategy name
|
|
1120
|
+
`graph-refresh` is always refused, even when `improve.strategies["graph-refresh"]`
|
|
1121
|
+
holds an override; `akm migrate apply` drops the override.
|
|
1122
|
+
|
|
1123
|
+
### The `engines` form
|
|
1124
|
+
|
|
1125
|
+
A config that holds `engines` or `defaults` loads: akm reads it in memory as
|
|
1126
|
+
`connections` and `harnesses`, with one warning that names `akm migrate apply`.
|
|
1127
|
+
`akm migrate apply` makes the same conversion permanent, under a backup, and
|
|
1128
|
+
prints a note for everything it cannot carry. Credentials, `models.json` and
|
|
1129
|
+
asset keys move as the table says.
|
|
1130
|
+
|
|
1131
|
+
| In the file | What `akm migrate apply` does |
|
|
1132
|
+
| --- | --- |
|
|
1133
|
+
| `engines.<name>` with `kind: "llm"` | `connections.<name>`. `endpoint`, `contextLength`, `timeoutMs`, `concurrency` and an `apiKey` that is a `$VAR` are kept. `model` becomes `models`, with `fast`, `balanced` and `reasoning` all naming it. `temperature`, `maxTokens`, `enableThinking`, `reasoningEffort` and `extraParams` become request fields (`temperature`, `max_tokens`, `enable_thinking` with `chat_template_kwargs.enable_thinking`, `reasoning_effort`, and the extras as written). `kind`, `provider` and `supportsJsonSchema` are dropped, with a note. |
|
|
1134
|
+
| `engines.<name>` with `kind: "agent"` and `platform: "opencode-sdk"` | Removed: akm's own runtime has no entry. Its `llmEngine` connection becomes `default`. |
|
|
1135
|
+
| `engines.<name>` with `kind: "agent"`, any other platform | `harnesses.<name>`, keeping `platform`, `bin`, `args`, `workspace`, `agent` and `timeoutMs`. `model` becomes `models`, naming it for all three aliases. |
|
|
1136
|
+
| `defaults.llmEngine`, else `defaults.engine` when it names an LLM engine | That connection is renamed `default`, and every reference to the old name follows. An entry already called `default` moves aside to `legacy-default`, or the first `legacy-default-<n>` nothing else has: the renaming is one name to one name, so no two entries share a name and none is lost. |
|
|
1137
|
+
| `defaults.engine` naming an agent engine, when there are several | That harness is renamed `default`. |
|
|
1138
|
+
| `defaults.improveStrategy` | `improve.strategy`. |
|
|
1139
|
+
| `models.json` | Folded into the `models` of the connections and harnesses it names; what it cannot place is listed in the notes. The file moves to `config-backups/` in the cache directory. |
|
|
1140
|
+
| `apiKeyFile`, a literal `apiKey`, a `${secrets/...}` `apiKey` | The key moves to `credentials.json` for the connection and its endpoint; a note names where it was, never its value. A key that cannot be read stays on the connection as it was (`apiKey`, or `apiKeyFile` for a key file), with a note that it is still to do; a later run moves it once it can be read. |
|
|
1141
|
+
| `AKM_ENGINE_<NAME>_API_KEY` or `AKM_LLM_API_KEY` set in the environment | `apiKey: "$AKM_ENGINE_<NAME>_API_KEY"` (or `$AKM_LLM_API_KEY`) on that connection. Set in no variable, an engine that names no key gets none, and a note names the variables 0.9 read. |
|
|
1142
|
+
| `improve.strategies.<name>.engine`, `model`, `llm`, `timeoutMs` | Dropped, with a note: a strategy says which processes run, not where. |
|
|
1143
|
+
| `engine`, `model`, `llm`, `timeoutMs` on a strategy's process, its `qualityGate` or its `triage.judgment` | Moved to `improve.processes.<process>` or `improve.qualityGate`, with `engine` becoming `connection` or `harness` by what it named. When that place already says, the first one is kept, with a note. |
|
|
1144
|
+
| `index.defaults.*`, `index.<pass>.engine` | `index.*`, and `connection`. An index pass cannot name a harness, so an engine that named one is dropped, with a note; a pass that names nothing runs where model work does: on the default connection, else the default harness. |
|
|
1145
|
+
| `workflow.judgeEngine` | Dropped, with a note. |
|
|
1146
|
+
| `engine:` in an asset's frontmatter, a workflow step or a task source | `connection:` or `harness:`, by what the configured target is; a name it cannot place becomes `harness:`, with a note. A bundle akm may not change, and an asset that is a symbolic link, are skipped. |
|
|
1147
|
+
|
|
1148
|
+
An `engine:` key on an asset that has not been migrated is read the same way,
|
|
1149
|
+
with a one-time notice, and so is `--engine NAME` (hidden from `--help`): both
|
|
1150
|
+
name a connection by that name, else a harness. While the config file is still
|
|
1151
|
+
in the `engines` form they name the connection or harness that engine became, so
|
|
1152
|
+
`engine: lab` still means the engine called `lab` after the conversion has
|
|
1153
|
+
renamed it `default`. Once `akm migrate apply` has rewritten the file, the names
|
|
1154
|
+
the engines had are kept in akm's data directory
|
|
1155
|
+
(`migrate/engine-targets.json`), and the key and the flag go on meaning the same
|
|
1156
|
+
engine until the migrator has rewritten every `engine:` key it can reach; an
|
|
1157
|
+
asset in a read-only bundle, or a block it could not splice, is rewritten under
|
|
1158
|
+
the same names by a later run, and an asset that is a symbolic link is read but
|
|
1159
|
+
never rewritten, so it is listed as skipped and keeps the names until you change
|
|
1160
|
+
the file it leads to. Then the names are forgotten, an old name that is
|
|
1161
|
+
neither a connection nor a harness fails like any unconfigured name (exit 78),
|
|
1162
|
+
and the run that forgets them prints one note listing each renamed engine and
|
|
1163
|
+
the flag that replaces it. A script or scheduled command that passes `--engine`
|
|
1164
|
+
is not one the migrator can reach: change it to `--connection` or `--harness`. A
|
|
1165
|
+
remembered name whose connection is no longer configured fails like any
|
|
1166
|
+
selection of an unconfigured name.
|