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
|
@@ -1,812 +1,13 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
import { spawnSync } from "node:child_process";
|
|
5
|
-
import { loadConfig } from "../../core/config/config.js";
|
|
6
|
-
import { listEnvsRecursive } from "../../core/env-secret-ref.js";
|
|
7
|
-
import { ConfigError } from "../../core/errors.js";
|
|
8
4
|
import { EXTRACT_INFRASTRUCTURE_SKIP_REASONS } from "../../core/improve-types.js";
|
|
9
5
|
import { listPendingStateMigrations } from "../../core/state-db.js";
|
|
10
|
-
import { withEngineFallback } from "../../integrations/agent/engine-fallback.js";
|
|
11
|
-
import { isLlmCredentialAvailable, resolveEngine, } from "../../integrations/agent/engine-resolution.js";
|
|
12
|
-
import { executionEngineDefinitionsFromConfig } from "../../integrations/agent/execution.js";
|
|
13
|
-
import { loadModelMap, mergeModelMapLayers, parseModelMapLayer, readInstalledModelMapText, resolveModelMapAlias, userModelMapPath, } from "../../integrations/agent/model-map.js";
|
|
14
|
-
import { detectOpencodeMajor, resolveOpencodeBin, } from "../../integrations/harnesses/opencode/version.js";
|
|
15
|
-
import { OPENCODE_CLIENT_PACKAGE } from "../../integrations/harnesses/opencode-sdk/wire.js";
|
|
16
|
-
import { probeEndpointOnce } from "../../llm/client.js";
|
|
17
6
|
import { STATE_DB_FREELIST_WARN_RATIO, } from "../../storage/state-db-integrity.js";
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { ENGINE_LAST_USED_LOOKBACK_DAYS } from "./engine-usage.js";
|
|
21
|
-
import { ACTIVE_RUN_WARN_MS, TASK_FAIL_RATE_WARN, } from "./types.js";
|
|
22
|
-
/** Probe one connection's reachability, once per endpoint; `undefined` when no probe seam is supplied. */
|
|
23
|
-
function probeConnectionReachable(connection, deps, cache) {
|
|
24
|
-
if (!deps.probeReachable)
|
|
25
|
-
return Promise.resolve(undefined);
|
|
26
|
-
return probeEndpointOnce(connection, cache, deps.probeReachable);
|
|
27
|
-
}
|
|
28
|
-
function reachabilityEvidence(reach) {
|
|
29
|
-
return reach
|
|
30
|
-
? { probed: true, reachable: reach.reachable, ...(reach.error ? { error: reach.error } : {}) }
|
|
31
|
-
: { probed: false, reachable: null };
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* #914: an unreachable LLM engine is a hard `fail` when it is the resolved
|
|
35
|
-
* `default-llm-engine` (extraction and improve depend on it) but only a
|
|
36
|
-
* `warn` elsewhere. Only a reachability warn escalates; a credential warn
|
|
37
|
-
* stays a warn.
|
|
38
|
-
*/
|
|
39
|
-
function escalateDefaultLlmEngineFailure(result) {
|
|
40
|
-
if (result.status === "warn" && result.evidence?.reachable === false) {
|
|
41
|
-
return { ...result, status: "fail" };
|
|
42
|
-
}
|
|
43
|
-
return result;
|
|
44
|
-
}
|
|
7
|
+
import { semanticSearchCheck } from "./semantic-search-check.js";
|
|
8
|
+
import { ACTIVE_RUN_WARN_MS, TASK_FAIL_RATE_WARN } from "./types.js";
|
|
45
9
|
/** Rolling window the `session-extraction` check reads from the extract ledger (#914). */
|
|
46
10
|
export const SESSION_EXTRACTION_LEDGER_WINDOW_DAYS = 7;
|
|
47
|
-
/**
|
|
48
|
-
* Delegates to {@link isLlmCredentialAvailable} (#953) so `akm health` and the
|
|
49
|
-
* improve-strategy probe (#957 builds on this same helper) share one
|
|
50
|
-
* non-throwing "is a credential present" check with the real dispatch
|
|
51
|
-
* boundary — env value, file-backed (#905), or secret-store-backed (#953).
|
|
52
|
-
*/
|
|
53
|
-
function credentialAvailable(credential, env, apiKeyFile, apiKeySecretRef) {
|
|
54
|
-
return isLlmCredentialAvailable({ credential, apiKeyFile, apiKeySecretRef }, env);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* #950: when a required `$VAR`-style credential is missing from the shell,
|
|
58
|
-
* find the env asset (if any) whose key names include one of
|
|
59
|
-
* `credential.names` — so the warn can say "run under env/lab" instead of a
|
|
60
|
-
* bare "unavailable". Returns the asset's ref, or `null` when no credential,
|
|
61
|
-
* no candidate names, or no matching env asset. Never returns or logs the
|
|
62
|
-
* variable name itself (only ref/path/keys ever leave `listEnvsRecursive`,
|
|
63
|
-
* and only the ref is read here) — `tests/health-engine-probe.test.ts` pins
|
|
64
|
-
* that a credential's env-var name never appears in health's JSON output.
|
|
65
|
-
* Best-effort: any failure walking env assets (unreadable stash, bad config)
|
|
66
|
-
* degrades to `null`, never a crash. `deps.listEnvAssets` is expected to
|
|
67
|
-
* already be normalised (see {@link withMemoizedEnvAssets}) by the time this
|
|
68
|
-
* runs, so the walk happens at most once per probe run — every caller of
|
|
69
|
-
* this function passes deps that have already gone through
|
|
70
|
-
* {@link withMemoizedEnvAssets}, so there is no separate default to fall
|
|
71
|
-
* back to here.
|
|
72
|
-
*/
|
|
73
|
-
function findSuppliedByEnvAsset(credential, deps) {
|
|
74
|
-
if (!credential || credential.names.length === 0)
|
|
75
|
-
return null;
|
|
76
|
-
try {
|
|
77
|
-
const envs = deps.listEnvAssets?.();
|
|
78
|
-
if (!envs)
|
|
79
|
-
return null;
|
|
80
|
-
for (const envAsset of envs) {
|
|
81
|
-
if (credential.names.some((name) => envAsset.keys.includes(name)))
|
|
82
|
-
return envAsset.ref;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
// Best-effort — env-asset discovery must never break a health probe.
|
|
87
|
-
}
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* #950: normalise `deps.listEnvAssets` once per probe run so
|
|
92
|
-
* {@link findSuppliedByEnvAsset}'s env-asset walk happens at most once even
|
|
93
|
-
* when a run probes several engines with missing credentials — the walk is
|
|
94
|
-
* real IO (or config-injected IO in tests) with no reason to repeat per
|
|
95
|
-
* engine. Wraps whatever seam is already present (test-injected or the
|
|
96
|
-
* config-honouring default) in a memoising closure; called once by each of
|
|
97
|
-
* the four probe entry points that share {@link runConfiguredEngineProbe}
|
|
98
|
-
* (`runDefaultEngineProbe`, `runDefaultLlmEngineProbe`,
|
|
99
|
-
* `runConfiguredEnginesProbe`, `runHealthEngineProbes`).
|
|
100
|
-
*/
|
|
101
|
-
function withMemoizedEnvAssets(deps) {
|
|
102
|
-
const listEnvAssets = deps.listEnvAssets ?? (() => listEnvsRecursive(listKeys, (deps.loadConfig ?? loadConfig)()));
|
|
103
|
-
let cached;
|
|
104
|
-
return { ...deps, listEnvAssets: () => (cached ??= listEnvAssets()) };
|
|
105
|
-
}
|
|
106
|
-
async function runConfiguredEngineProbe(checkName, engineName, config, deps, reachabilityCache) {
|
|
107
|
-
if (!engineName) {
|
|
108
|
-
return {
|
|
109
|
-
name: checkName,
|
|
110
|
-
kind: "deterministic",
|
|
111
|
-
status: "unknown",
|
|
112
|
-
confidence: "high",
|
|
113
|
-
message: checkName === "default-llm-engine"
|
|
114
|
-
? "No default LLM engine is configured."
|
|
115
|
-
: "No default engine is configured.",
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
const env = deps.env ?? process.env;
|
|
119
|
-
const configuredEngine = config.engines?.[engineName];
|
|
120
|
-
if (configuredEngine?.kind === "agent" && configuredEngine.platform === "opencode-sdk") {
|
|
121
|
-
const binary = resolveOpencodeBin(configuredEngine.bin);
|
|
122
|
-
let detected;
|
|
123
|
-
try {
|
|
124
|
-
detected = detectOpencodeMajor(binary, {
|
|
125
|
-
probe: (bin) => {
|
|
126
|
-
const run = (deps.spawnSync ?? spawnSync)(bin, ["--version"], { encoding: "utf8", timeout: 5_000 });
|
|
127
|
-
return (run.status ?? 1) === 0 ? String(run.stdout ?? "").trim() : undefined;
|
|
128
|
-
},
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
catch {
|
|
132
|
-
return {
|
|
133
|
-
name: checkName,
|
|
134
|
-
kind: "deterministic",
|
|
135
|
-
status: "warn",
|
|
136
|
-
confidence: "high",
|
|
137
|
-
message: `SDK engine "${engineName}" executable availability could not be checked.`,
|
|
138
|
-
evidence: { engine: engineName, runtimeKind: "sdk", binaryAvailable: false },
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
const binaryAvailable = detected.runnable;
|
|
142
|
-
// The client package of the OpenCode major the binary reports; never the other major's.
|
|
143
|
-
const clientPackage = OPENCODE_CLIENT_PACKAGE[detected.major];
|
|
144
|
-
let packageAvailable = false;
|
|
145
|
-
try {
|
|
146
|
-
const resolvePackage = deps.resolvePackage ?? ((name) => import.meta.resolve(name));
|
|
147
|
-
resolvePackage(clientPackage);
|
|
148
|
-
packageAvailable = true;
|
|
149
|
-
}
|
|
150
|
-
catch {
|
|
151
|
-
packageAvailable = false;
|
|
152
|
-
}
|
|
153
|
-
const fallbackEngine = configuredEngine.llmEngine;
|
|
154
|
-
let fallback;
|
|
155
|
-
let fallbackCredential;
|
|
156
|
-
let fallbackApiKeyFile;
|
|
157
|
-
let fallbackApiKeySecretRef;
|
|
158
|
-
let sdkRunner;
|
|
159
|
-
const resolve = deps.resolveEngine ?? resolveEngine;
|
|
160
|
-
try {
|
|
161
|
-
const resolved = resolve(engineName, config);
|
|
162
|
-
if (resolved.kind === "sdk")
|
|
163
|
-
sdkRunner = resolved;
|
|
164
|
-
}
|
|
165
|
-
catch {
|
|
166
|
-
sdkRunner = undefined;
|
|
167
|
-
}
|
|
168
|
-
if (sdkRunner?.fallbackConnection && fallbackEngine) {
|
|
169
|
-
fallback = { kind: "llm", engine: fallbackEngine, connection: sdkRunner.fallbackConnection };
|
|
170
|
-
fallbackCredential = sdkRunner.fallbackCredential;
|
|
171
|
-
fallbackApiKeyFile = sdkRunner.fallbackApiKeyFile;
|
|
172
|
-
fallbackApiKeySecretRef = sdkRunner.fallbackApiKeySecretRef;
|
|
173
|
-
}
|
|
174
|
-
else if (fallbackEngine) {
|
|
175
|
-
try {
|
|
176
|
-
const resolved = resolve(fallbackEngine, config);
|
|
177
|
-
if (resolved.kind === "llm") {
|
|
178
|
-
fallback = resolved;
|
|
179
|
-
fallbackCredential = resolved.credential;
|
|
180
|
-
fallbackApiKeyFile = resolved.apiKeyFile;
|
|
181
|
-
fallbackApiKeySecretRef = resolved.apiKeySecretRef;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
catch {
|
|
185
|
-
fallback = undefined;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
const configuredModel = configuredEngine.model;
|
|
189
|
-
const effectiveModel = sdkRunner?.profile.model ?? configuredModel ?? fallback?.connection.model;
|
|
190
|
-
const fallbackCredentialAvailable = credentialAvailable(fallbackCredential, env, fallbackApiKeyFile, fallbackApiKeySecretRef);
|
|
191
|
-
const fallbackSuppliedByEnvAsset = !fallbackCredentialAvailable
|
|
192
|
-
? findSuppliedByEnvAsset(fallbackCredential, deps)
|
|
193
|
-
: null;
|
|
194
|
-
const missing = [
|
|
195
|
-
!packageAvailable ? `${clientPackage} package` : undefined,
|
|
196
|
-
!binaryAvailable ? `${binary} binary` : undefined,
|
|
197
|
-
fallbackEngine && !fallback ? "configured fallback LLM connection" : undefined,
|
|
198
|
-
!fallbackCredentialAvailable
|
|
199
|
-
? fallbackSuppliedByEnvAsset
|
|
200
|
-
? `required fallback credential (available via env asset ${fallbackSuppliedByEnvAsset}; run under it: akm env run ${fallbackSuppliedByEnvAsset} -- ...)`
|
|
201
|
-
: "required fallback credential"
|
|
202
|
-
: undefined,
|
|
203
|
-
].filter((value) => value !== undefined);
|
|
204
|
-
const sdkEvidence = {
|
|
205
|
-
engine: engineName,
|
|
206
|
-
platform: configuredEngine.platform,
|
|
207
|
-
runtimeKind: "sdk",
|
|
208
|
-
binary,
|
|
209
|
-
binaryAvailable,
|
|
210
|
-
package: clientPackage,
|
|
211
|
-
detectedVersion: detected.version || null,
|
|
212
|
-
detectedMajor: detected.major,
|
|
213
|
-
packageAvailable,
|
|
214
|
-
model: effectiveModel ?? null,
|
|
215
|
-
configuredModel: configuredModel ?? null,
|
|
216
|
-
modelSource: configuredModel ? "sdk" : effectiveModel ? "fallback" : null,
|
|
217
|
-
fallbackEngine: fallbackEngine ?? null,
|
|
218
|
-
fallbackEndpoint: fallback?.connection.endpoint ?? null,
|
|
219
|
-
fallbackModel: fallback?.connection.model ?? null,
|
|
220
|
-
requiredCredentialAvailable: fallbackCredentialAvailable,
|
|
221
|
-
suppliedByEnvAsset: fallbackSuppliedByEnvAsset,
|
|
222
|
-
};
|
|
223
|
-
if (missing.length > 0) {
|
|
224
|
-
return {
|
|
225
|
-
name: checkName,
|
|
226
|
-
kind: "deterministic",
|
|
227
|
-
status: "warn",
|
|
228
|
-
confidence: "high",
|
|
229
|
-
message: `SDK engine "${engineName}" is incomplete: missing ${missing.join(", ")}.`,
|
|
230
|
-
evidence: sdkEvidence,
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
// The SDK's LLM fallback is the only endpoint this engine talks to;
|
|
234
|
-
// probe it once every local precondition above is satisfied (#914).
|
|
235
|
-
const reach = fallback ? await probeConnectionReachable(fallback.connection, deps, reachabilityCache) : undefined;
|
|
236
|
-
return {
|
|
237
|
-
name: checkName,
|
|
238
|
-
kind: "deterministic",
|
|
239
|
-
status: reach && !reach.reachable ? "warn" : "pass",
|
|
240
|
-
confidence: "high",
|
|
241
|
-
message: !fallback
|
|
242
|
-
? `SDK engine "${engineName}" is available.`
|
|
243
|
-
: !reach
|
|
244
|
-
? `SDK engine "${engineName}" is available. Reachability was not probed.`
|
|
245
|
-
: reach.reachable
|
|
246
|
-
? `SDK engine "${engineName}" is available and its LLM fallback is reachable.`
|
|
247
|
-
: `SDK engine "${engineName}" is available, but its LLM fallback is not reachable: ${reach.error ?? "unknown error"}`,
|
|
248
|
-
evidence: fallback ? { ...sdkEvidence, ...reachabilityEvidence(reach) } : sdkEvidence,
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
try {
|
|
252
|
-
const runner = (deps.resolveEngine ?? resolveEngine)(engineName, config);
|
|
253
|
-
if (runner.kind === "llm") {
|
|
254
|
-
const requiredCredentialAvailable = credentialAvailable(runner.credential, env, runner.apiKeyFile, runner.apiKeySecretRef);
|
|
255
|
-
const llmEvidence = {
|
|
256
|
-
engine: engineName,
|
|
257
|
-
platform: null,
|
|
258
|
-
runtimeKind: "llm",
|
|
259
|
-
model: runner.connection.model,
|
|
260
|
-
endpoint: runner.connection.endpoint,
|
|
261
|
-
requiredCredentialAvailable,
|
|
262
|
-
};
|
|
263
|
-
if (!requiredCredentialAvailable) {
|
|
264
|
-
// #950: a missing-in-shell credential is common when the operator's
|
|
265
|
-
// real workflow is `akm env run env/lab -- akm improve` — name the env
|
|
266
|
-
// asset that supplies it (never the variable name) so the warn is
|
|
267
|
-
// actionable instead of looking like a broken engine.
|
|
268
|
-
const suppliedByEnvAsset = findSuppliedByEnvAsset(runner.credential, deps);
|
|
269
|
-
return {
|
|
270
|
-
name: checkName,
|
|
271
|
-
kind: "deterministic",
|
|
272
|
-
status: "warn",
|
|
273
|
-
confidence: "high",
|
|
274
|
-
message: suppliedByEnvAsset
|
|
275
|
-
? `LLM engine "${engineName}" is configured, but its required credential is not available in this shell; env asset ${suppliedByEnvAsset} supplies it — run under it (akm env run ${suppliedByEnvAsset} -- ...).`
|
|
276
|
-
: `LLM engine "${engineName}" is configured, but its required credential is unavailable.`,
|
|
277
|
-
evidence: { ...llmEvidence, suppliedByEnvAsset },
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
const reach = await probeConnectionReachable(runner.connection, deps, reachabilityCache);
|
|
281
|
-
return {
|
|
282
|
-
name: checkName,
|
|
283
|
-
kind: "deterministic",
|
|
284
|
-
status: reach && !reach.reachable ? "warn" : "pass",
|
|
285
|
-
confidence: "high",
|
|
286
|
-
message: !reach
|
|
287
|
-
? `LLM engine "${engineName}" is configured. Reachability was not probed.`
|
|
288
|
-
: reach.reachable
|
|
289
|
-
? `LLM engine "${engineName}" is configured and reachable.`
|
|
290
|
-
: `LLM engine "${engineName}" is not reachable: ${reach.error ?? "unknown error"}`,
|
|
291
|
-
evidence: { ...llmEvidence, ...reachabilityEvidence(reach) },
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
const profile = runner.profile;
|
|
295
|
-
if (runner.kind === "sdk")
|
|
296
|
-
throw new Error(`SDK engine "${engineName}" has no matching SDK config.`);
|
|
297
|
-
const version = (deps.spawnSync ?? spawnSync)(profile.bin, ["--version"], { encoding: "utf8", timeout: 5_000 });
|
|
298
|
-
if ((version.status ?? 1) !== 0) {
|
|
299
|
-
return {
|
|
300
|
-
name: checkName,
|
|
301
|
-
kind: "deterministic",
|
|
302
|
-
status: "warn",
|
|
303
|
-
confidence: "medium",
|
|
304
|
-
message: `Agent engine "${engineName}" was found but \`--version\` failed.`,
|
|
305
|
-
evidence: {
|
|
306
|
-
engine: engineName,
|
|
307
|
-
platform: profile.platform ?? null,
|
|
308
|
-
runtimeKind: "agent",
|
|
309
|
-
model: profile.model ?? null,
|
|
310
|
-
},
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
return {
|
|
314
|
-
name: checkName,
|
|
315
|
-
kind: "deterministic",
|
|
316
|
-
status: "pass",
|
|
317
|
-
confidence: "high",
|
|
318
|
-
message: `Agent engine "${engineName}" is available.`,
|
|
319
|
-
evidence: {
|
|
320
|
-
engine: engineName,
|
|
321
|
-
platform: profile.platform ?? null,
|
|
322
|
-
runtimeKind: "agent",
|
|
323
|
-
model: profile.model ?? null,
|
|
324
|
-
},
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
catch (error) {
|
|
328
|
-
return {
|
|
329
|
-
name: checkName,
|
|
330
|
-
kind: "deterministic",
|
|
331
|
-
status: "warn",
|
|
332
|
-
confidence: "high",
|
|
333
|
-
message: error instanceof Error ? error.message : String(error),
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
function projectEngineProbe(result, name) {
|
|
338
|
-
return result.name === name ? result : { ...result, name };
|
|
339
|
-
}
|
|
340
|
-
function projectSelectedEngineProbe(availability, engineName, checkName) {
|
|
341
|
-
const result = availability.get(engineName);
|
|
342
|
-
if (result) {
|
|
343
|
-
const projected = projectEngineProbe(result, checkName);
|
|
344
|
-
return checkName === "default-llm-engine" ? escalateDefaultLlmEngineFailure(projected) : projected;
|
|
345
|
-
}
|
|
346
|
-
return {
|
|
347
|
-
name: checkName,
|
|
348
|
-
kind: "deterministic",
|
|
349
|
-
status: "warn",
|
|
350
|
-
confidence: "high",
|
|
351
|
-
message: `Engine "${engineName}" availability could not be checked.`,
|
|
352
|
-
evidence: { engine: engineName },
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
function unconfiguredEngineProbe(name) {
|
|
356
|
-
return {
|
|
357
|
-
name,
|
|
358
|
-
kind: "deterministic",
|
|
359
|
-
status: "unknown",
|
|
360
|
-
confidence: "high",
|
|
361
|
-
message: name === "default-llm-engine" ? "No default LLM engine is configured." : "No default engine is configured.",
|
|
362
|
-
};
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* #949: `enableThinking: false` is a request an engine's endpoint (or a
|
|
366
|
-
* gateway in front of it) can silently ignore — `chatCompletionAttemptOnce`
|
|
367
|
-
* (src/llm/client.ts) already warns to stderr whenever a response reports
|
|
368
|
-
* reasoning tokens despite it. This makes that same signal visible in
|
|
369
|
-
* `akm health` as a structured finding, purely by re-reading the window's
|
|
370
|
-
* `llm_usage` aggregate already threaded into the context: no extra
|
|
371
|
-
* completion call, no live probe — a cold local model must not be woken just
|
|
372
|
-
* to run `akm health`.
|
|
373
|
-
*/
|
|
374
|
-
function projectThinkingControlCheck(thinkingOffEngines, llmUsage, since) {
|
|
375
|
-
if (thinkingOffEngines.length === 0) {
|
|
376
|
-
return {
|
|
377
|
-
name: "thinking-control",
|
|
378
|
-
kind: "deterministic",
|
|
379
|
-
status: "unknown",
|
|
380
|
-
confidence: "high",
|
|
381
|
-
message: "No configured engine sets enableThinking: false — nothing to verify.",
|
|
382
|
-
evidence: { engines: [] },
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
const engines = [...thinkingOffEngines].sort().map((engine) => {
|
|
386
|
-
const usage = llmUsage.byEngine[engine];
|
|
387
|
-
const calls = usage?.calls ?? 0;
|
|
388
|
-
const reasoningTokens = usage?.reasoningTokens ?? 0;
|
|
389
|
-
const status = calls === 0 ? "unknown" : reasoningTokens > 0 ? "warn" : "pass";
|
|
390
|
-
return { engine, status, calls, reasoningTokens };
|
|
391
|
-
});
|
|
392
|
-
const warning = engines.filter((e) => e.status === "warn");
|
|
393
|
-
const status = warning.length > 0 ? "warn" : engines.every((e) => e.status === "unknown") ? "unknown" : "pass";
|
|
394
|
-
let message;
|
|
395
|
-
if (warning.length > 0) {
|
|
396
|
-
message = warning
|
|
397
|
-
.map((e) => `LLM engine "${e.engine}" returned ${e.reasoningTokens} reasoning tokens since ${since} despite enableThinking: false — the endpoint (or a gateway in front of it) is not honouring the thinking-off control.`)
|
|
398
|
-
.join(" ");
|
|
399
|
-
}
|
|
400
|
-
else if (status === "unknown") {
|
|
401
|
-
message = `No calls were recorded for the engine(s) configured with enableThinking: false (${engines.map((e) => e.engine).join(", ")}) in the report window.`;
|
|
402
|
-
}
|
|
403
|
-
else {
|
|
404
|
-
message = `${engines.length} engine(s) configured with enableThinking: false (${engines.map((e) => e.engine).join(", ")}) returned no reasoning tokens in the report window.`;
|
|
405
|
-
}
|
|
406
|
-
return {
|
|
407
|
-
name: "thinking-control",
|
|
408
|
-
kind: "deterministic",
|
|
409
|
-
status,
|
|
410
|
-
confidence: "high",
|
|
411
|
-
message,
|
|
412
|
-
evidence: { engines },
|
|
413
|
-
};
|
|
414
|
-
}
|
|
415
|
-
function configuredEnginesProjection(engineNames, availability) {
|
|
416
|
-
if (engineNames.length === 0) {
|
|
417
|
-
return {
|
|
418
|
-
name: "configured-engines",
|
|
419
|
-
kind: "deterministic",
|
|
420
|
-
status: "unknown",
|
|
421
|
-
confidence: "high",
|
|
422
|
-
message: "No engines are explicitly configured.",
|
|
423
|
-
evidence: { engines: [] },
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
const engines = engineNames.map((engine) => ({
|
|
427
|
-
engine,
|
|
428
|
-
status: availability.get(engine)?.status === "pass" ? "pass" : "warn",
|
|
429
|
-
}));
|
|
430
|
-
const unavailable = engines.filter((engine) => engine.status === "warn").length;
|
|
431
|
-
return {
|
|
432
|
-
name: "configured-engines",
|
|
433
|
-
kind: "deterministic",
|
|
434
|
-
status: unavailable === 0 ? "pass" : "warn",
|
|
435
|
-
confidence: "high",
|
|
436
|
-
message: unavailable === 0
|
|
437
|
-
? `All ${engines.length} explicitly configured engines are available.`
|
|
438
|
-
: `${unavailable} of ${engines.length} explicitly configured engines ${unavailable === 1 ? "is" : "are"} unavailable.`,
|
|
439
|
-
evidence: { engines },
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
export async function runDefaultEngineProbe(deps = {}) {
|
|
443
|
-
// Probe the effective view: an install with no `defaults.engine` but a usable
|
|
444
|
-
// opencode binary DOES have a working default, and reporting otherwise would
|
|
445
|
-
// contradict what `workflow run` / `task run` actually do.
|
|
446
|
-
const { config } = withEngineFallback(deps.loadConfig?.() ?? loadConfig(), deps.which);
|
|
447
|
-
return runConfiguredEngineProbe("default-engine", config.defaults?.engine, config, withMemoizedEnvAssets(deps), new Map());
|
|
448
|
-
}
|
|
449
|
-
export async function runDefaultLlmEngineProbe(deps = {}) {
|
|
450
|
-
const config = deps.loadConfig?.() ?? loadConfig();
|
|
451
|
-
const engineName = config.defaults?.llmEngine;
|
|
452
|
-
if (!engineName)
|
|
453
|
-
return unconfiguredEngineProbe("default-llm-engine");
|
|
454
|
-
const result = await runConfiguredEngineProbe("configured-engine", engineName, config, withMemoizedEnvAssets(deps), new Map());
|
|
455
|
-
return projectSelectedEngineProbe(new Map([[engineName, result]]), engineName, "default-llm-engine");
|
|
456
|
-
}
|
|
457
|
-
/** Probe every explicitly configured engine without exposing connection or model material. */
|
|
458
|
-
export async function runConfiguredEnginesProbe(deps = {}) {
|
|
459
|
-
const config = deps.loadConfig?.() ?? loadConfig();
|
|
460
|
-
const engineNames = Object.keys(config.engines ?? {}).sort();
|
|
461
|
-
const cache = new Map();
|
|
462
|
-
const runDeps = withMemoizedEnvAssets(deps);
|
|
463
|
-
const availability = new Map(await Promise.all(engineNames.map(async (engine) => [engine, await runConfiguredEngineProbe("configured-engine", engine, config, runDeps, cache)])));
|
|
464
|
-
return configuredEnginesProjection(engineNames, availability);
|
|
465
|
-
}
|
|
466
|
-
/**
|
|
467
|
-
* Build the per-health-run availability snapshot. Each distinct selected or
|
|
468
|
-
* explicitly configured engine is probed once (reachability probes further
|
|
469
|
-
* de-duped by endpoint, see {@link ReachabilityCache}); the three public
|
|
470
|
-
* checks are projections of that immutable result set.
|
|
471
|
-
*/
|
|
472
|
-
export async function runHealthEngineProbes(deps = {}) {
|
|
473
|
-
const configured = deps.loadConfig?.() ?? loadConfig();
|
|
474
|
-
const effective = withEngineFallback(configured, deps.which).config;
|
|
475
|
-
const defaultEngineName = effective.defaults?.engine;
|
|
476
|
-
const defaultLlmEngineName = configured.defaults?.llmEngine;
|
|
477
|
-
const explicitEngineNames = Object.keys(configured.engines ?? {}).sort();
|
|
478
|
-
const probeNames = [...new Set([...explicitEngineNames, defaultEngineName, defaultLlmEngineName])]
|
|
479
|
-
.filter((name) => name !== undefined)
|
|
480
|
-
.sort();
|
|
481
|
-
const cache = new Map();
|
|
482
|
-
const runDeps = withMemoizedEnvAssets(deps);
|
|
483
|
-
const availability = new Map(await Promise.all(probeNames.map(async (engine) => [engine, await runConfiguredEngineProbe("configured-engine", engine, effective, runDeps, cache)])));
|
|
484
|
-
return Object.freeze({
|
|
485
|
-
defaultEngine: defaultEngineName
|
|
486
|
-
? projectSelectedEngineProbe(availability, defaultEngineName, "default-engine")
|
|
487
|
-
: unconfiguredEngineProbe("default-engine"),
|
|
488
|
-
defaultLlmEngine: defaultLlmEngineName
|
|
489
|
-
? projectSelectedEngineProbe(availability, defaultLlmEngineName, "default-llm-engine")
|
|
490
|
-
: unconfiguredEngineProbe("default-llm-engine"),
|
|
491
|
-
configuredEngines: configuredEnginesProjection(explicitEngineNames, availability),
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
/**
|
|
495
|
-
* #950: probes the active improve strategy and returns both its
|
|
496
|
-
* `HealthCheckResult` and the typed process→engine map, computed once. See
|
|
497
|
-
* {@link runActiveImproveStrategyProbe} for the plain-`HealthCheckResult`
|
|
498
|
-
* wrapper existing callers/tests use.
|
|
499
|
-
*/
|
|
500
|
-
export function probeActiveImproveStrategy(deps = {}) {
|
|
501
|
-
const config = deps.loadConfig?.() ?? loadConfig();
|
|
502
|
-
const strategyName = config.defaults?.improveStrategy ?? "default";
|
|
503
|
-
const env = deps.env ?? process.env;
|
|
504
|
-
try {
|
|
505
|
-
// #957: credential availability (including the triage-judgment engine) is
|
|
506
|
-
// now derived once, inside `buildImprovePlan` itself — the same
|
|
507
|
-
// `plan.engineUnavailable` the real `improve` run reads to skip processes
|
|
508
|
-
// and populate `AkmImproveResult.skippedProcesses`. This check is a pure
|
|
509
|
-
// projection of that list rather than its own re-derivation.
|
|
510
|
-
//
|
|
511
|
-
// `allowAllDisabled: true` because a strategy left with every process
|
|
512
|
-
// disabled purely by credential unavailability must still come back as
|
|
513
|
-
// an inspectable plan here, not a thrown ConfigError — the
|
|
514
|
-
// `allRequiredUnavailable`/`fail` logic below needs `plan.engineUnavailable`
|
|
515
|
-
// to run this check's fail path instead of falling into the generic
|
|
516
|
-
// catch block's warn/unknown fallback (round 2 finding on #957). A
|
|
517
|
-
// strategy with no engine configured at all still throws (see
|
|
518
|
-
// `allowAllDisabled`'s doc comment) and keeps hitting that catch block,
|
|
519
|
-
// unchanged from before this fix.
|
|
520
|
-
const plan = resolveImprovePlan(strategyName, config, { env, allowAllDisabled: true });
|
|
521
|
-
const unavailableProcesses = plan.engineUnavailable.map((item) => item.process);
|
|
522
|
-
// #913: name the engine each process actually resolved to, so a
|
|
523
|
-
// strategy-level `engine` pin that shadows `defaults.llmEngine` is
|
|
524
|
-
// visible on `akm health` instead of requiring config archaeology.
|
|
525
|
-
const engines = {};
|
|
526
|
-
for (const [name, process] of Object.entries(plan.processes)) {
|
|
527
|
-
if (process.enabled && process.runner)
|
|
528
|
-
engines[name] = process.runner.engine;
|
|
529
|
-
}
|
|
530
|
-
if (plan.triageJudgment)
|
|
531
|
-
engines["triage.judgment"] = plan.triageJudgment.engine;
|
|
532
|
-
const engineList = Object.entries(engines)
|
|
533
|
-
.sort(([a], [b]) => a.localeCompare(b))
|
|
534
|
-
.map(([process, engine]) => `${process}: "${engine}"`)
|
|
535
|
-
.join(", ");
|
|
536
|
-
// #957: fail only when the strategy's model work would be a total no-op —
|
|
537
|
-
// every process the strategy actually enabled among the ones that call a
|
|
538
|
-
// model themselves (MODEL_CALLING_PROCESSES, any engine kind) ended up
|
|
539
|
-
// unavailable. A partial failure (some processes still have a working
|
|
540
|
-
// engine) stays a `warn`, matching #914's "a credential warn stays a warn"
|
|
541
|
-
// policy for the general per-engine probes; this is the strategy-scoped
|
|
542
|
-
// "is the whole run a no-op" question instead.
|
|
543
|
-
const modelProcessNames = [...MODEL_CALLING_PROCESSES];
|
|
544
|
-
const requiredModelProcessNames = modelProcessNames.filter((name) => plan.processes[name].enabled || plan.engineUnavailable.some((item) => item.process === name));
|
|
545
|
-
const availableModelProcessNames = modelProcessNames.filter((name) => plan.processes[name].enabled);
|
|
546
|
-
const allRequiredUnavailable = requiredModelProcessNames.length > 0 && availableModelProcessNames.length === 0;
|
|
547
|
-
// No engine configured at all (no unavailable item carries a resolved engine)
|
|
548
|
-
// is "not set up yet", not a broken credential: it keeps the unknown/warn
|
|
549
|
-
// result it had when the plan threw for it. Engine-free deterministic triage
|
|
550
|
-
// (#1143) now lets such a plan resolve, so this has to be explicit.
|
|
551
|
-
const noEngineConfigured = plan.engineUnavailable.length > 0 && plan.engineUnavailable.every((i) => !i.engine);
|
|
552
|
-
const explicitlyConfigured = config.defaults?.improveStrategy !== undefined || Object.keys(config.improve?.strategies ?? {}).length > 0;
|
|
553
|
-
const status = unavailableProcesses.length === 0
|
|
554
|
-
? "pass"
|
|
555
|
-
: allRequiredUnavailable
|
|
556
|
-
? noEngineConfigured
|
|
557
|
-
? explicitlyConfigured
|
|
558
|
-
? "warn"
|
|
559
|
-
: "unknown"
|
|
560
|
-
: "fail"
|
|
561
|
-
: "warn";
|
|
562
|
-
return {
|
|
563
|
-
check: {
|
|
564
|
-
name: "active-improve-strategy",
|
|
565
|
-
kind: "deterministic",
|
|
566
|
-
status,
|
|
567
|
-
confidence: "high",
|
|
568
|
-
message: unavailableProcesses.length === 0
|
|
569
|
-
? `Active improve strategy "${plan.strategy.name}" has available process engines${engineList ? ` (${engineList})` : ""}.`
|
|
570
|
-
: allRequiredUnavailable
|
|
571
|
-
? `Active improve strategy "${plan.strategy.name}" cannot run any LLM-backed process; the nightly run would be a no-op: ${unavailableProcesses.join(", ")}${engineList ? ` (engines: ${engineList})` : ""}.`
|
|
572
|
-
: `Active improve strategy "${plan.strategy.name}" has unavailable required credentials for: ${unavailableProcesses.join(", ")}${engineList ? ` (engines: ${engineList})` : ""}.`,
|
|
573
|
-
evidence: {
|
|
574
|
-
strategy: plan.strategy.name,
|
|
575
|
-
unavailableProcesses,
|
|
576
|
-
engines,
|
|
577
|
-
},
|
|
578
|
-
},
|
|
579
|
-
processEngines: Object.freeze({ ...engines }),
|
|
580
|
-
};
|
|
581
|
-
}
|
|
582
|
-
catch (error) {
|
|
583
|
-
const explicitlyConfigured = config.defaults?.improveStrategy !== undefined || Object.keys(config.improve?.strategies ?? {}).length > 0;
|
|
584
|
-
return {
|
|
585
|
-
check: {
|
|
586
|
-
name: "active-improve-strategy",
|
|
587
|
-
kind: "deterministic",
|
|
588
|
-
status: explicitlyConfigured ? "warn" : "unknown",
|
|
589
|
-
confidence: "high",
|
|
590
|
-
message: `Active improve strategy "${strategyName}" is unavailable: ${error instanceof Error ? error.message : String(error)}`,
|
|
591
|
-
evidence: { strategy: strategyName, unavailableProcesses: [] },
|
|
592
|
-
},
|
|
593
|
-
processEngines: {},
|
|
594
|
-
};
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
/** Plain-`HealthCheckResult` wrapper around {@link probeActiveImproveStrategy} for existing callers/tests. */
|
|
598
|
-
export function runActiveImproveStrategyProbe(deps = {}) {
|
|
599
|
-
return probeActiveImproveStrategy(deps).check;
|
|
600
|
-
}
|
|
601
|
-
/**
|
|
602
|
-
* #950: the `engine-last-used` advisory. Pure projection of context computed
|
|
603
|
-
* once in `health.ts` (`activeImproveStrategyEngines`, `engineLastUsed`,
|
|
604
|
-
* `improveRunsInLookbackWindow`) — no IO here, mirrors `thinking-control`.
|
|
605
|
-
*
|
|
606
|
-
* `unknown` (not a noisy `warn`) both when no engine is bound to an enabled
|
|
607
|
-
* process, AND when no improve run has been recorded (started) in the
|
|
608
|
-
* lookback window at all — a fresh install has never been given the chance
|
|
609
|
-
* to use its engines.
|
|
610
|
-
*/
|
|
611
|
-
function projectEngineLastUsedCheck(processEngineMap, lastUsed, improveRunsInLookbackWindow, lookbackDays) {
|
|
612
|
-
const engineProcesses = new Map();
|
|
613
|
-
for (const [process, engine] of Object.entries(processEngineMap)) {
|
|
614
|
-
const processes = engineProcesses.get(engine) ?? [];
|
|
615
|
-
processes.push(process);
|
|
616
|
-
engineProcesses.set(engine, processes);
|
|
617
|
-
}
|
|
618
|
-
const engines = [...engineProcesses.keys()].sort();
|
|
619
|
-
if (engines.length === 0) {
|
|
620
|
-
return {
|
|
621
|
-
name: "engine-last-used",
|
|
622
|
-
kind: "deterministic",
|
|
623
|
-
status: "unknown",
|
|
624
|
-
confidence: "high",
|
|
625
|
-
message: "No engine is bound to an enabled improve process.",
|
|
626
|
-
evidence: { engines: [] },
|
|
627
|
-
};
|
|
628
|
-
}
|
|
629
|
-
if (improveRunsInLookbackWindow === 0) {
|
|
630
|
-
return {
|
|
631
|
-
name: "engine-last-used",
|
|
632
|
-
kind: "deterministic",
|
|
633
|
-
status: "unknown",
|
|
634
|
-
confidence: "high",
|
|
635
|
-
message: `No improve runs in the last ${lookbackDays} days.`,
|
|
636
|
-
evidence: {
|
|
637
|
-
engines: engines.map((engine) => ({ engine, processes: (engineProcesses.get(engine) ?? []).sort() })),
|
|
638
|
-
},
|
|
639
|
-
};
|
|
640
|
-
}
|
|
641
|
-
const entries = engines.map((engine) => ({
|
|
642
|
-
engine,
|
|
643
|
-
processes: (engineProcesses.get(engine) ?? []).sort(),
|
|
644
|
-
lastUsedAt: lastUsed.get(engine)?.lastUsedAt ?? null,
|
|
645
|
-
}));
|
|
646
|
-
const idle = entries.filter((entry) => entry.lastUsedAt === null);
|
|
647
|
-
const status = idle.length > 0 ? "warn" : "pass";
|
|
648
|
-
const message = idle.length > 0
|
|
649
|
-
? idle
|
|
650
|
-
.map((entry) => {
|
|
651
|
-
const quoted = entry.processes.map((process) => `"${process}"`).join(", ");
|
|
652
|
-
const noun = entry.processes.length === 1 ? "process" : "processes";
|
|
653
|
-
return `Engine "${entry.engine}" is bound to ${noun} ${quoted} but has not been used in the last ${lookbackDays} days.`;
|
|
654
|
-
})
|
|
655
|
-
.join(" ")
|
|
656
|
-
: entries
|
|
657
|
-
.map((entry) => {
|
|
658
|
-
const process = lastUsed.get(entry.engine)?.process ?? entry.processes.join(", ");
|
|
659
|
-
return `Engine "${entry.engine}" last used by "${process}" at ${entry.lastUsedAt}.`;
|
|
660
|
-
})
|
|
661
|
-
.join(" ");
|
|
662
|
-
return {
|
|
663
|
-
name: "engine-last-used",
|
|
664
|
-
kind: "deterministic",
|
|
665
|
-
status,
|
|
666
|
-
confidence: "high",
|
|
667
|
-
message,
|
|
668
|
-
evidence: { engines: entries },
|
|
669
|
-
};
|
|
670
|
-
}
|
|
671
|
-
/**
|
|
672
|
-
* Validate the immutable installed model map and optional user overlay.
|
|
673
|
-
* Installed corruption is a package defect (fail); a bad optional user file
|
|
674
|
-
* (including an `engine`-backed profile referencing a missing/broken engine,
|
|
675
|
-
* once resolved against real `config.engines` — #946) is operator-fixable
|
|
676
|
-
* configuration (warn); absence is the normal state.
|
|
677
|
-
*/
|
|
678
|
-
export function runModelMapProbe(options = {}) {
|
|
679
|
-
let installedText;
|
|
680
|
-
try {
|
|
681
|
-
installedText = readInstalledModelMapText(options);
|
|
682
|
-
mergeModelMapLayers(parseModelMapLayer(installedText, "installed models.json"));
|
|
683
|
-
}
|
|
684
|
-
catch (error) {
|
|
685
|
-
return {
|
|
686
|
-
name: "model-map-files",
|
|
687
|
-
kind: "deterministic",
|
|
688
|
-
status: "fail",
|
|
689
|
-
confidence: "high",
|
|
690
|
-
message: `Installed models.json is invalid; this AKM installation cannot resolve model aliases: ${error instanceof Error ? error.message : String(error)}`,
|
|
691
|
-
evidence: { installedSource: "package asset" },
|
|
692
|
-
};
|
|
693
|
-
}
|
|
694
|
-
// Load config OUTSIDE the models.json try/catch below: a broken
|
|
695
|
-
// config.json must surface as a config problem reported by the config
|
|
696
|
-
// checks, never get misreported as a models.json warning carrying the
|
|
697
|
-
// config error's own text. When config fails to load, validate the model
|
|
698
|
-
// map shape-only (no `engine` resolution), matching pre-#946 behavior.
|
|
699
|
-
let engines;
|
|
700
|
-
try {
|
|
701
|
-
engines = (options.loadConfig?.() ?? loadConfig()).engines;
|
|
702
|
-
}
|
|
703
|
-
catch {
|
|
704
|
-
engines = undefined;
|
|
705
|
-
}
|
|
706
|
-
try {
|
|
707
|
-
const loaded = loadModelMap({ ...options, installedText, engines });
|
|
708
|
-
return {
|
|
709
|
-
name: "model-map-files",
|
|
710
|
-
kind: "deterministic",
|
|
711
|
-
status: "pass",
|
|
712
|
-
confidence: "high",
|
|
713
|
-
message: loaded.userStatus === "loaded"
|
|
714
|
-
? `Installed defaults and user models.json at ${loaded.userPath} are valid.`
|
|
715
|
-
: "Installed model defaults are valid; no optional user models.json is present.",
|
|
716
|
-
evidence: {
|
|
717
|
-
installedSource: "package asset",
|
|
718
|
-
userPath: loaded.userPath,
|
|
719
|
-
userStatus: loaded.userStatus,
|
|
720
|
-
aliases: Object.keys(loaded.map.aliases).sort(),
|
|
721
|
-
},
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
catch (error) {
|
|
725
|
-
const hint = error instanceof ConfigError ? error.hint() : undefined;
|
|
726
|
-
return {
|
|
727
|
-
name: "model-map-files",
|
|
728
|
-
kind: "deterministic",
|
|
729
|
-
status: "warn",
|
|
730
|
-
confidence: "high",
|
|
731
|
-
message: `${error instanceof Error ? error.message : String(error)}${hint ? ` ${hint}` : ""}`,
|
|
732
|
-
evidence: {
|
|
733
|
-
installedSource: "package asset",
|
|
734
|
-
userPath: userModelMapPath(options.env),
|
|
735
|
-
userStatus: "invalid",
|
|
736
|
-
},
|
|
737
|
-
};
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
/**
|
|
741
|
-
* Check model selections owned by configured engines against the common model
|
|
742
|
-
* map. Unknown identifiers are deliberate exact-model pass-throughs; only an
|
|
743
|
-
* alias known somewhere in the map but absent for the selected engine warns.
|
|
744
|
-
*/
|
|
745
|
-
export function runSelectedModelAliasesProbe(deps = {}) {
|
|
746
|
-
const config = deps.loadConfig?.() ?? loadConfig();
|
|
747
|
-
const definitions = executionEngineDefinitionsFromConfig(config);
|
|
748
|
-
const selected = Object.entries(definitions)
|
|
749
|
-
.sort(([left], [right]) => left.localeCompare(right))
|
|
750
|
-
.flatMap(([engine, definition]) => {
|
|
751
|
-
const model = definition.defaults?.model;
|
|
752
|
-
const modelMapKey = definition.modelMapKey ?? definition.selection.platform ?? definition.selection.name;
|
|
753
|
-
return typeof model === "string" ? [{ engine, alias: model, modelMapKey }] : [];
|
|
754
|
-
});
|
|
755
|
-
if (selected.length === 0) {
|
|
756
|
-
return {
|
|
757
|
-
name: "selected-model-aliases",
|
|
758
|
-
kind: "deterministic",
|
|
759
|
-
status: "unknown",
|
|
760
|
-
confidence: "high",
|
|
761
|
-
message: "No configured engines select a model.",
|
|
762
|
-
evidence: { checked: [], missing: [] },
|
|
763
|
-
};
|
|
764
|
-
}
|
|
765
|
-
let modelMap;
|
|
766
|
-
try {
|
|
767
|
-
modelMap = (deps.loadModelMap ?? loadModelMap)({
|
|
768
|
-
env: deps.env,
|
|
769
|
-
installedText: deps.installedText,
|
|
770
|
-
engines: config.engines,
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
catch {
|
|
774
|
-
return {
|
|
775
|
-
name: "selected-model-aliases",
|
|
776
|
-
kind: "deterministic",
|
|
777
|
-
status: "unknown",
|
|
778
|
-
confidence: "high",
|
|
779
|
-
message: "Configured model selections could not be checked because the model map is invalid.",
|
|
780
|
-
evidence: { checked: [], missing: [] },
|
|
781
|
-
};
|
|
782
|
-
}
|
|
783
|
-
const outcomes = selected.map(({ engine, alias, modelMapKey }) => {
|
|
784
|
-
try {
|
|
785
|
-
const resolution = resolveModelMapAlias(alias, modelMapKey, modelMap.map);
|
|
786
|
-
if (resolution.interpretation === "alias") {
|
|
787
|
-
return { kind: "alias", evidence: { engine, alias, modelMapKey } };
|
|
788
|
-
}
|
|
789
|
-
return resolution.unmappedForEngine
|
|
790
|
-
? { kind: "missing", evidence: { engine, alias, modelMapKey } }
|
|
791
|
-
: { kind: "exact" };
|
|
792
|
-
}
|
|
793
|
-
catch {
|
|
794
|
-
return { kind: "missing", evidence: { engine, alias, modelMapKey } };
|
|
795
|
-
}
|
|
796
|
-
});
|
|
797
|
-
const checked = outcomes.flatMap((outcome) => (outcome.kind === "exact" ? [] : [outcome.evidence]));
|
|
798
|
-
const missing = outcomes.flatMap((outcome) => (outcome.kind === "missing" ? [outcome.evidence] : []));
|
|
799
|
-
return {
|
|
800
|
-
name: "selected-model-aliases",
|
|
801
|
-
kind: "deterministic",
|
|
802
|
-
status: missing.length === 0 ? "pass" : "warn",
|
|
803
|
-
confidence: "high",
|
|
804
|
-
message: missing.length === 0
|
|
805
|
-
? `All ${selected.length} configured model selections resolve for their selected engines.`
|
|
806
|
-
: `${missing.length} of ${selected.length} configured model selections ${missing.length === 1 ? "has" : "have"} no mapping for ${missing.length === 1 ? "its" : "their"} selected engine${missing.length === 1 ? "" : "s"}.`,
|
|
807
|
-
evidence: { checked, missing },
|
|
808
|
-
};
|
|
809
|
-
}
|
|
810
11
|
/**
|
|
811
12
|
* `state-db-migrations` when the open itself failed: the migrations still
|
|
812
13
|
* pending after a failed apply, from a read-only listing that never applies
|
|
@@ -1004,37 +205,14 @@ export const HEALTH_CHECKS = [
|
|
|
1004
205
|
},
|
|
1005
206
|
},
|
|
1006
207
|
{
|
|
1007
|
-
name: "
|
|
1008
|
-
channel: "hard",
|
|
1009
|
-
run: (ctx) => ctx.engineProbes.defaultEngine,
|
|
1010
|
-
},
|
|
1011
|
-
{
|
|
1012
|
-
name: "model-map-files",
|
|
1013
|
-
channel: "hard",
|
|
1014
|
-
run: () => runModelMapProbe(),
|
|
1015
|
-
},
|
|
1016
|
-
{
|
|
1017
|
-
name: "selected-model-aliases",
|
|
208
|
+
name: "connections-and-harnesses",
|
|
1018
209
|
channel: "hard",
|
|
1019
|
-
run: () =>
|
|
210
|
+
run: (ctx) => ctx.connectionsAndHarnesses,
|
|
1020
211
|
},
|
|
1021
212
|
{
|
|
1022
|
-
name: "
|
|
213
|
+
name: "semantic-search",
|
|
1023
214
|
channel: "hard",
|
|
1024
|
-
run: (ctx) => ctx.
|
|
1025
|
-
},
|
|
1026
|
-
{
|
|
1027
|
-
name: "configured-engines",
|
|
1028
|
-
channel: "hard",
|
|
1029
|
-
run: (ctx) => ctx.engineProbes.configuredEngines,
|
|
1030
|
-
},
|
|
1031
|
-
{
|
|
1032
|
-
name: "active-improve-strategy",
|
|
1033
|
-
channel: "hard",
|
|
1034
|
-
// #950: projects the context field instead of recomputing, so
|
|
1035
|
-
// `engine-last-used` below can reuse the same process→engine map without
|
|
1036
|
-
// a second `runActiveImproveStrategyProbe()` call.
|
|
1037
|
-
run: (ctx) => ctx.activeImproveStrategy,
|
|
215
|
+
run: (ctx) => semanticSearchCheck(ctx.semanticSearch),
|
|
1038
216
|
},
|
|
1039
217
|
{
|
|
1040
218
|
// C2 (13-bus-factor): the cron task-failure rate was computed and rendered
|
|
@@ -1179,37 +357,20 @@ export const HEALTH_CHECKS = [
|
|
|
1179
357
|
};
|
|
1180
358
|
},
|
|
1181
359
|
},
|
|
1182
|
-
{
|
|
1183
|
-
// #949: advisory channel, but `kind: "deterministic"` (same as the
|
|
1184
|
-
// pre-existing task-fail-rate advisory) — a warn here DOES flip
|
|
1185
|
-
// AkmHealthResult.status to "warn" and akm health's exit code to
|
|
1186
|
-
// EXIT_HEALTH_WARN, because the overall-status computation ORs
|
|
1187
|
-
// deterministic warns across both hardChecks and advisories.
|
|
1188
|
-
name: "thinking-control",
|
|
1189
|
-
channel: "advisory",
|
|
1190
|
-
run: (ctx) => projectThinkingControlCheck(ctx.thinkingOffEngines, ctx.llmUsage, ctx.since),
|
|
1191
|
-
},
|
|
1192
360
|
{
|
|
1193
361
|
// #950: best-effort "installed vs latest release" advisory, gated behind
|
|
1194
|
-
// the same --probe/--no-probe flag as
|
|
1195
|
-
// in health.ts (network IO), projected here like
|
|
362
|
+
// the same --probe/--no-probe flag as endpoint reachability. Computed once
|
|
363
|
+
// in health.ts (network IO), projected here like connectionsAndHarnesses.
|
|
1196
364
|
name: "cli-version",
|
|
1197
365
|
channel: "advisory",
|
|
1198
366
|
run: (ctx) => ctx.versionDrift,
|
|
1199
367
|
},
|
|
1200
|
-
{
|
|
1201
|
-
// #950: advisory channel, `kind: "deterministic"` — same
|
|
1202
|
-
// exit-code-gating rationale as thinking-control above.
|
|
1203
|
-
name: "engine-last-used",
|
|
1204
|
-
channel: "advisory",
|
|
1205
|
-
run: (ctx) => projectEngineLastUsedCheck(ctx.activeImproveStrategyEngines, ctx.engineLastUsed, ctx.improveRunsInLookbackWindow, ENGINE_LAST_USED_LOOKBACK_DAYS),
|
|
1206
|
-
},
|
|
1207
368
|
{
|
|
1208
369
|
// #953: registered last — order is load-bearing (see the HEALTH_CHECKS
|
|
1209
370
|
// doc comment above). Best-effort scheduler-binary-drift advisory, gated
|
|
1210
|
-
// behind the same --probe/--no-probe flag as
|
|
371
|
+
// behind the same --probe/--no-probe flag as endpoint reachability and
|
|
1211
372
|
// cli-version. Computed once in health.ts (process-spawn IO), projected
|
|
1212
|
-
// here like versionDrift/
|
|
373
|
+
// here like versionDrift/connectionsAndHarnesses.
|
|
1213
374
|
name: "scheduler-binary",
|
|
1214
375
|
channel: "advisory",
|
|
1215
376
|
run: (ctx) => ctx.schedulerBinaryDrift,
|