akm-cli 0.9.0-rc.0 → 0.9.0-rc.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1283 -22
- package/README.md +62 -37
- package/SECURITY.md +46 -31
- package/dist/akm +162 -38
- package/dist/akm-migrate +44 -0
- package/dist/assets/backends/schtasks-template.xml +2 -1
- package/dist/assets/hints/cli-hints-full.md +268 -118
- package/dist/assets/hints/cli-hints-short.md +87 -24
- package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
- package/dist/assets/improve-strategies/frequent.json +15 -0
- package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
- package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
- package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
- package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
- package/dist/assets/improve-strategies/reflect-distill.json +30 -0
- package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +5 -5
- package/dist/assets/prompts/extract-session.md +2 -6
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
- package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
- package/dist/assets/prompts/reflect-output-repair.md +3 -0
- package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
- package/dist/assets/stash-skeleton/README.md +38 -10
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
- package/dist/assets/tasks/core/extract.yml +3 -2
- package/dist/assets/tasks/core/improve.yml +2 -1
- package/dist/assets/tasks/core/index-refresh.yml +1 -0
- package/dist/assets/tasks/core/sync.yml +1 -0
- package/dist/assets/tasks/core/version-check.yml +2 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
- package/dist/assets/templates/html/health.html +5 -4
- package/dist/assets/workflows/workflow-template.md +31 -15
- package/dist/cli/invocation.js +279 -0
- package/dist/cli/parse-args.js +5 -90
- package/dist/cli/retired-commands.js +78 -0
- package/dist/cli/shared.js +158 -48
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +747 -293
- package/dist/commands/agent/agent-dispatch.js +19 -18
- package/dist/commands/agent/agent-support.js +0 -24
- package/dist/commands/agent/contribute-cli.js +43 -97
- package/dist/commands/completions.js +80 -23
- package/dist/commands/config-cli.js +44 -281
- package/dist/commands/env/env-binding.js +99 -0
- package/dist/commands/env/env-cli.js +84 -224
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +45 -61
- package/dist/commands/env/secret.js +32 -62
- package/dist/commands/feedback-cli.js +179 -85
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +7 -8
- package/dist/commands/health/checks.js +279 -94
- package/dist/commands/health/html-report.js +197 -578
- package/dist/commands/health/improve-metrics.js +277 -246
- package/dist/commands/health/llm-usage.js +19 -19
- package/dist/commands/health/md-report.js +16 -7
- package/dist/commands/health/metrics.js +67 -32
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +508 -0
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +16 -56
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
- package/dist/commands/health/types-improve.js +29 -0
- package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
- package/dist/commands/health/types-result.js +7 -0
- package/dist/commands/health/types-runs.js +4 -0
- package/dist/commands/health/types-session-log.js +4 -0
- package/dist/commands/health/types-windows.js +4 -0
- package/dist/commands/health/types.js +26 -21
- package/dist/commands/health/windows.js +2 -3
- package/dist/commands/health.js +296 -167
- package/dist/commands/improve/anti-collapse.js +5 -5
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +65 -52
- package/dist/commands/improve/consolidate/chunking.js +9 -7
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +454 -1354
- package/dist/commands/improve/content-hash.js +39 -0
- package/dist/commands/improve/distill/content-repair.js +4 -10
- package/dist/commands/improve/distill/promote-memory.js +89 -64
- package/dist/commands/improve/distill/quality-gate.js +118 -42
- package/dist/commands/improve/distill-guards.js +1 -1
- package/dist/commands/improve/distill-promotion-policy.js +33 -888
- package/dist/commands/improve/distill.js +607 -363
- package/dist/commands/improve/eligibility.js +165 -79
- package/dist/commands/improve/extract-cli.js +35 -126
- package/dist/commands/improve/extract-prompt.js +6 -35
- package/dist/commands/improve/extract.js +640 -391
- package/dist/commands/improve/feedback-valence.js +2 -12
- package/dist/commands/improve/improve-cli.js +134 -135
- package/dist/commands/improve/improve-result-file.js +30 -50
- package/dist/commands/improve/improve-run-types.js +4 -0
- package/dist/commands/improve/improve-strategies.js +135 -0
- package/dist/commands/improve/improve.js +904 -701
- package/dist/commands/improve/locks.js +64 -111
- package/dist/commands/improve/loop-stages.js +1110 -923
- package/dist/commands/improve/memory/derived-ref.js +124 -0
- package/dist/commands/improve/memory/memory-belief.js +79 -7
- package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
- package/dist/commands/improve/memory/memory-improve.js +25 -37
- package/dist/commands/improve/outcome-loop.js +25 -88
- package/dist/commands/improve/preparation.js +1034 -813
- package/dist/commands/improve/proactive-maintenance.js +34 -9
- package/dist/commands/improve/proposal-envelope.js +31 -0
- package/dist/commands/improve/reflect.js +983 -794
- package/dist/commands/improve/run-context.js +119 -0
- package/dist/commands/improve/salience.js +24 -127
- package/dist/commands/improve/session-asset.js +7 -3
- package/dist/commands/improve/shared.js +14 -34
- package/dist/commands/improve/source-identity.js +28 -0
- package/dist/commands/improve/triage.js +20 -17
- package/dist/commands/lint/base-linter.js +340 -313
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +185 -30
- package/dist/commands/{events.js → log.js} +28 -38
- package/dist/commands/migrate-cli.js +54 -0
- package/dist/commands/migration-tool.js +55 -0
- package/dist/commands/observability-cli.js +70 -208
- package/dist/commands/proposal/diff-format.js +50 -0
- package/dist/commands/proposal/drain-policies.js +0 -6
- package/dist/commands/proposal/drain.js +91 -40
- package/dist/commands/proposal/proposal-cli.js +134 -132
- package/dist/commands/proposal/proposal-types.js +56 -0
- package/dist/commands/proposal/proposal.js +83 -65
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +105 -88
- package/dist/commands/proposal/repository.js +1303 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
- package/dist/commands/proposal/validators/proposal-validators.js +61 -12
- package/dist/commands/proposal/validators/proposals.js +6 -8
- package/dist/commands/read/curate.js +78 -73
- package/dist/commands/read/knowledge.js +510 -13
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +84 -15
- package/dist/commands/read/search-cli.js +203 -96
- package/dist/commands/read/search.js +126 -94
- package/dist/commands/read/show.js +226 -250
- package/dist/commands/registry-cli.js +34 -60
- package/dist/commands/remember.js +18 -57
- package/dist/commands/sources/add-cli.js +104 -49
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +63 -0
- package/dist/commands/sources/info.js +27 -15
- package/dist/commands/sources/init.js +30 -40
- package/dist/commands/sources/installed-stashes.js +469 -172
- package/dist/commands/sources/migration-help.js +7 -4
- package/dist/commands/sources/schema-repair.js +10 -9
- package/dist/commands/sources/self-update.js +182 -121
- package/dist/commands/sources/source-add.js +169 -178
- package/dist/commands/sources/source-clone.js +144 -41
- package/dist/commands/sources/source-manage.js +94 -59
- package/dist/commands/sources/sources-cli.js +64 -205
- package/dist/commands/sources/stash-cli.js +91 -54
- package/dist/commands/sources/stash-skeleton.js +1 -1
- package/dist/commands/tasks/tasks-cli.js +106 -104
- package/dist/commands/tasks/tasks.js +445 -262
- package/dist/commands/workflow-cli.js +232 -121
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/activation-policy.js +49 -0
- package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
- package/dist/core/adapter/adapters/akm-adapter.js +528 -0
- package/dist/core/adapter/adapters/akm-lint.js +392 -0
- package/dist/core/adapter/adapters/akm-metadata.js +387 -0
- package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
- package/dist/core/adapter/adapters/claude-adapter.js +61 -0
- package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
- package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
- package/dist/core/adapter/adapters/index.js +80 -0
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
- package/dist/core/adapter/adapters/okf-adapter.js +391 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
- package/dist/core/adapter/adapters/shared.js +286 -0
- package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
- package/dist/core/adapter/bundle-adapter.js +4 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +44 -0
- package/dist/core/adapter/registry.js +56 -0
- package/dist/core/adapter/types.js +4 -0
- package/dist/core/asset/akm-markdown.js +30 -0
- package/dist/core/asset/asset-placement.js +243 -0
- package/dist/core/asset/asset-ref.js +110 -79
- package/dist/core/asset/asset-serialize.js +20 -0
- package/dist/core/asset/frontmatter.js +28 -12
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +274 -0
- package/dist/core/asset/stash-meta.js +2 -2
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +281 -86
- package/dist/core/config/config-io.js +42 -128
- package/dist/core/config/config-schema.js +233 -834
- package/dist/core/config/config-sources.js +162 -39
- package/dist/core/config/config-types.js +16 -11
- package/dist/core/config/config-version.js +29 -0
- package/dist/core/config/config-walker.js +126 -37
- package/dist/core/config/config.js +154 -331
- package/dist/core/config/deep-merge.js +41 -0
- package/dist/core/config/engine-semantics.js +28 -0
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +38 -0
- package/dist/core/config/schema/engines.js +116 -0
- package/dist/core/config/schema/experimental.js +47 -0
- package/dist/core/config/schema/feedback.js +31 -0
- package/dist/core/config/schema/improve-processes.js +389 -0
- package/dist/core/config/schema/improve.js +94 -0
- package/dist/core/config/schema/index-config.js +176 -0
- package/dist/core/config/schema/output.js +18 -0
- package/dist/core/config/schema/primitives.js +94 -0
- package/dist/core/config/schema/search.js +30 -0
- package/dist/core/config/schema/setup.js +18 -0
- package/dist/core/config/schema/sources-bundles.js +169 -0
- package/dist/core/config/schema/workflow.js +29 -0
- package/dist/core/env-secret-ref.js +155 -20
- package/dist/core/errors.js +17 -15
- package/dist/core/events-types.js +4 -0
- package/dist/core/events.js +46 -128
- package/dist/core/extra-params.js +62 -0
- package/dist/core/file-change.js +17 -0
- package/dist/core/file-lock.js +202 -57
- package/dist/core/fs-txn.js +392 -0
- package/dist/core/git-message.js +59 -0
- package/dist/core/improve-result.js +167 -0
- package/dist/core/json-schema.js +142 -0
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +1 -1
- package/dist/core/maintenance-barrier.js +135 -0
- package/dist/core/migration-operation.js +44 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/paths.js +22 -25
- package/dist/core/platform.js +10 -0
- package/dist/core/recognition-util.js +128 -0
- package/dist/core/redaction.js +392 -0
- package/dist/core/standards/resolve-standards-context.js +36 -65
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +5 -5
- package/dist/core/state/migrations.js +242 -11
- package/dist/core/state-db.js +98 -10
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +303 -0
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/time.js +20 -0
- package/dist/core/type-presentation.js +130 -0
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +834 -118
- package/dist/indexer/bundle-identity-guard.js +92 -0
- package/dist/indexer/db/graph-db.js +1 -25
- package/dist/indexer/db/llm-cache.js +1 -1
- package/dist/indexer/ensure-index.js +30 -9
- package/dist/indexer/graph/graph-boost.js +9 -30
- package/dist/indexer/graph/graph-extraction.js +41 -27
- package/dist/indexer/graph/graph-types.js +4 -0
- package/dist/indexer/index-writer-lock.js +93 -49
- package/dist/indexer/index-written-assets.js +100 -53
- package/dist/indexer/indexer.js +746 -329
- package/dist/indexer/init.js +18 -25
- package/dist/indexer/installations.js +142 -0
- package/dist/indexer/passes/dir-staleness.js +18 -10
- package/dist/indexer/passes/memory-inference.js +25 -15
- package/dist/indexer/passes/metadata.js +412 -243
- package/dist/indexer/scan/doc-to-entry.js +160 -0
- package/dist/indexer/scan/drain-dir.js +134 -0
- package/dist/indexer/search/db-search.js +292 -108
- package/dist/indexer/search/fts-query.js +64 -0
- package/dist/indexer/search/ranking-contributors.js +145 -25
- package/dist/indexer/search/ranking-types.js +4 -0
- package/dist/indexer/search/ranking.js +28 -71
- package/dist/indexer/search/search-attribution.js +67 -0
- package/dist/indexer/search/search-fields.js +18 -3
- package/dist/indexer/search/search-hit-enrichers.js +30 -40
- package/dist/indexer/search/search-source.js +157 -111
- package/dist/indexer/search/semantic-status.js +4 -1
- package/dist/indexer/usage/usage-events.js +10 -30
- package/dist/indexer/walk/file-context.js +3 -45
- package/dist/indexer/walk/matchers.js +42 -34
- package/dist/indexer/walk/path-resolver.js +11 -5
- package/dist/indexer/walk/walker.js +42 -14
- package/dist/integrations/agent/builder-shared.js +7 -0
- package/dist/integrations/agent/builders.js +5 -56
- package/dist/integrations/agent/config.js +3 -143
- package/dist/integrations/agent/detect.js +17 -2
- package/dist/integrations/agent/engine-resolution.js +231 -0
- package/dist/integrations/agent/index.js +1 -2
- package/dist/integrations/agent/model-aliases.js +16 -2
- package/dist/integrations/agent/profiles.js +36 -62
- package/dist/integrations/agent/prompts.js +46 -18
- package/dist/integrations/agent/runner-dispatch.js +93 -4
- package/dist/integrations/agent/runner.js +76 -208
- package/dist/integrations/agent/spawn.js +88 -196
- package/dist/integrations/harnesses/aider/agent-builder.js +114 -0
- package/dist/integrations/harnesses/aider/index.js +48 -0
- package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
- package/dist/integrations/harnesses/amazonq/agent-builder.js +147 -0
- package/dist/integrations/harnesses/amazonq/index.js +45 -0
- package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
- package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
- package/dist/integrations/harnesses/claude/config-import.js +1 -3
- package/dist/integrations/harnesses/claude/index.js +24 -35
- package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
- package/dist/integrations/harnesses/claude/session-log.js +27 -75
- package/dist/integrations/harnesses/codex/agent-builder.js +138 -0
- package/dist/integrations/harnesses/codex/index.js +52 -0
- package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
- package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
- package/dist/integrations/harnesses/copilot/index.js +48 -0
- package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
- package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
- package/dist/integrations/harnesses/gemini/index.js +48 -0
- package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
- package/dist/integrations/harnesses/ids.js +24 -0
- package/dist/integrations/harnesses/index.js +54 -34
- package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
- package/dist/integrations/harnesses/opencode/config-import.js +1 -3
- package/dist/integrations/harnesses/opencode/index.js +14 -32
- package/dist/integrations/harnesses/opencode/session-log.js +67 -125
- package/dist/integrations/harnesses/opencode-sdk/harness.js +51 -0
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
- package/dist/integrations/harnesses/openhands/agent-builder.js +128 -0
- package/dist/integrations/harnesses/openhands/index.js +48 -0
- package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
- package/dist/integrations/harnesses/pi/agent-builder.js +97 -0
- package/dist/integrations/harnesses/pi/index.js +45 -0
- package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
- package/dist/integrations/harnesses/shared.js +17 -0
- package/dist/integrations/harnesses/types.js +43 -32
- package/dist/integrations/lockfile.js +211 -24
- package/dist/integrations/session-logs/index.js +36 -39
- package/dist/integrations/session-logs/provider-base.js +113 -0
- package/dist/llm/client.js +182 -110
- package/dist/llm/embedders/deterministic.js +2 -2
- package/dist/llm/embedders/remote.js +21 -9
- package/dist/llm/feature-gate.js +17 -57
- package/dist/llm/graph-extract.js +12 -13
- package/dist/llm/index-passes.js +8 -42
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +45 -30
- package/dist/llm/structured-call.js +16 -8
- package/dist/llm/usage-persist.js +30 -5
- package/dist/llm/usage-telemetry.js +59 -6
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/command-registry.js +27 -0
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +251 -0
- package/dist/output/html-render.js +11 -16
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -279
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +58 -84
- package/dist/output/shapes/passthrough.js +11 -39
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes/registry.js +12 -6
- package/dist/output/shapes.js +0 -9
- package/dist/output/text/{init.js → bundle-create.js} +3 -1
- package/dist/output/text/bundle-show.js +7 -0
- package/dist/output/text/command-format.js +562 -0
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/helpers.js +15 -1164
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +202 -0
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/registry.js +12 -6
- package/dist/output/text/show-directives.js +117 -0
- package/dist/output/text/show-format.js +103 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +332 -0
- package/dist/output/text/workflow.js +3 -2
- package/dist/output/text.js +10 -19
- package/dist/registry/factory.js +4 -6
- package/dist/registry/origin-resolve.js +16 -27
- package/dist/registry/providers/skills-sh.js +3 -3
- package/dist/registry/providers/static-index.js +15 -25
- package/dist/registry/resolve.js +43 -94
- package/dist/registry/semver.js +43 -0
- package/dist/runtime.js +81 -12
- package/dist/scripts/akm-migrate.js +35529 -0
- package/dist/setup/detect.js +5 -7
- package/dist/setup/detected-engines.js +136 -0
- package/dist/setup/engine-config.js +100 -0
- package/dist/setup/registry-stash-loader.js +3 -3
- package/dist/setup/semantic-assets.js +12 -9
- package/dist/setup/setup.js +444 -208
- package/dist/setup/steps/connection-shared.js +120 -0
- package/dist/setup/steps/connection.js +108 -305
- package/dist/setup/steps/platforms.js +13 -12
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +21 -15
- package/dist/setup/steps/stashdir.js +6 -4
- package/dist/setup/steps/tasks.js +236 -119
- package/dist/setup/steps.js +3 -2
- package/dist/sources/freshness.js +39 -0
- package/dist/sources/provider-factory.js +11 -17
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +278 -34
- package/dist/sources/providers/git-provider.js +54 -56
- package/dist/sources/providers/git-stash.js +420 -91
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +47 -22
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +11 -10
- package/dist/sources/snapshot-fetchers/types.js +4 -0
- package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
- package/dist/storage/database.js +60 -4
- package/dist/storage/engines/sqlite-migrations.js +156 -5
- package/dist/storage/locations.js +1 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +51 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -32
- package/dist/storage/repositories/index-connection.js +79 -0
- package/dist/storage/repositories/index-db.js +4 -3
- package/dist/storage/repositories/index-entries-repository.js +863 -0
- package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
- package/dist/storage/repositories/index-entry-types.js +4 -0
- package/dist/storage/repositories/index-fts-repository.js +167 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
- package/dist/storage/repositories/index-meta-repository.js +49 -0
- package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
- package/dist/storage/repositories/index-sql.js +12 -0
- package/dist/storage/repositories/index-utility-repository.js +356 -0
- package/dist/storage/repositories/index-vec-repository.js +250 -0
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +317 -75
- package/dist/storage/repositories/registry-cache.js +1 -1
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +110 -3
- package/dist/storage/repositories/workflow-runs-repository.js +240 -19
- package/dist/tasks/backends/cron.js +169 -46
- package/dist/tasks/backends/exec-utils.js +76 -3
- package/dist/tasks/backends/index.js +6 -9
- package/dist/tasks/backends/launchd.js +292 -55
- package/dist/tasks/backends/schtasks.js +557 -70
- package/dist/tasks/backends/types.js +4 -0
- package/dist/tasks/command-executable.js +93 -0
- package/dist/tasks/embedded.js +56 -38
- package/dist/tasks/parser.js +156 -64
- package/dist/tasks/resolve-akm-bin.js +144 -51
- package/dist/tasks/runner.js +377 -209
- package/dist/tasks/schedule.js +108 -19
- package/dist/tasks/scheduler-invocation.js +296 -0
- package/dist/tasks/schema.js +1 -1
- package/dist/tasks/task-id.js +35 -0
- package/dist/tasks/validator.js +30 -16
- package/dist/text-import-hook.mjs +1 -1
- package/dist/workflows/authoring/authoring.js +104 -43
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/cli.js +0 -16
- package/dist/workflows/concurrency-policy.js +15 -0
- package/dist/workflows/exec/brief.js +450 -0
- package/dist/workflows/exec/frozen-judge.js +47 -0
- package/dist/workflows/exec/native-executor.js +1038 -0
- package/dist/workflows/exec/param-secrets.js +115 -0
- package/dist/workflows/exec/report.js +1460 -0
- package/dist/workflows/exec/run-workflow.js +602 -0
- package/dist/workflows/exec/scheduler.js +71 -0
- package/dist/workflows/exec/step-work.js +1190 -0
- package/dist/workflows/exec/unit-writer.js +23 -0
- package/dist/workflows/exec/workflow-engine-gate.js +67 -0
- package/dist/workflows/exec/worktree.js +171 -0
- package/dist/workflows/ir/compile.js +246 -0
- package/dist/workflows/ir/freeze.js +233 -0
- package/dist/workflows/ir/params.js +54 -0
- package/dist/workflows/ir/plan-hash.js +68 -0
- package/dist/workflows/ir/schema.js +540 -0
- package/dist/workflows/parser.js +878 -304
- package/dist/workflows/program/expressions.js +181 -0
- package/dist/workflows/program/schema.js +51 -0
- package/dist/workflows/renderer.js +100 -45
- package/dist/workflows/resource-limits.js +22 -0
- package/dist/workflows/runtime/agent-identity.js +59 -14
- package/dist/workflows/runtime/checkin.js +1 -1
- package/dist/workflows/runtime/plan-classifier.js +131 -0
- package/dist/workflows/runtime/runs.js +376 -119
- package/dist/workflows/runtime/unit-checkin.js +45 -0
- package/dist/workflows/runtime/unit-phases.js +20 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +241 -40
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +2 -3
- package/dist/workflows/validator.js +52 -30
- package/docs/README.md +42 -78
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +9 -8
- package/docs/migration/release-notes/0.9.0.md +158 -14
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +844 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/data-and-telemetry.md +333 -0
- package/package.json +21 -17
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +4636 -0
- package/schemas/akm-task.json +87 -0
- package/schemas/akm-workflow.json +373 -0
- package/dist/akm-migrate-storage +0 -38
- package/dist/assets/help/help-accept.md +0 -12
- package/dist/assets/help/help-improve.md +0 -84
- package/dist/assets/help/help-proposals.md +0 -17
- package/dist/assets/help/help-propose.md +0 -17
- package/dist/assets/help/help-reject.md +0 -11
- package/dist/assets/profiles/frequent.json +0 -13
- package/dist/assets/profiles/recombine-only.json +0 -21
- package/dist/assets/profiles/reflect-distill.json +0 -30
- package/dist/assets/profiles/synthesize.json +0 -15
- package/dist/assets/prompts/procedural-system.md +0 -44
- package/dist/assets/prompts/recombine-system.md +0 -40
- package/dist/assets/prompts/staleness-detect-system.md +0 -6
- package/dist/assets/tasks/core/backup.yml +0 -4
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/assets/templates/html/default.html +0 -78
- package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
- package/dist/assets/wiki/index-template.md +0 -12
- package/dist/assets/wiki/ingest-workflow-template.md +0 -83
- package/dist/assets/wiki/log-template.md +0 -8
- package/dist/assets/wiki/schema-template.md +0 -61
- package/dist/cli/config-migrate.js +0 -150
- package/dist/cli/config-validate.js +0 -39
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -487
- package/dist/commands/improve/calibration.js +0 -161
- package/dist/commands/improve/dedup.js +0 -482
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/improve/hot-probation.js +0 -45
- package/dist/commands/improve/improve-auto-accept.js +0 -276
- package/dist/commands/improve/improve-profiles.js +0 -168
- package/dist/commands/improve/procedural.js +0 -398
- package/dist/commands/improve/recombine.js +0 -818
- package/dist/commands/improve/schema-similarity-gate.js +0 -168
- package/dist/commands/lint/agent-linter.js +0 -44
- package/dist/commands/lint/command-linter.js +0 -44
- package/dist/commands/lint/default-linter.js +0 -16
- package/dist/commands/lint/fact-linter.js +0 -39
- package/dist/commands/lint/knowledge-linter.js +0 -16
- package/dist/commands/lint/memory-linter.js +0 -61
- package/dist/commands/lint/registry.js +0 -41
- package/dist/commands/lint/skill-linter.js +0 -45
- package/dist/commands/lint/task-linter.js +0 -50
- package/dist/commands/lint/workflow-linter.js +0 -81
- package/dist/commands/proposal/legacy-import.js +0 -115
- package/dist/commands/sources/history.js +0 -196
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/commands/wiki-cli.js +0 -292
- package/dist/core/asset/asset-registry.js +0 -76
- package/dist/core/asset/asset-spec.js +0 -259
- package/dist/core/config/config-migration.js +0 -602
- package/dist/core/deep-merge.js +0 -38
- package/dist/core/eval/rank-metrics.js +0 -113
- package/dist/core/ripgrep/install.js +0 -163
- package/dist/core/ripgrep/resolve.js +0 -81
- package/dist/indexer/db/db.js +0 -1413
- package/dist/indexer/manifest.js +0 -170
- package/dist/indexer/passes/metadata-contributors.js +0 -31
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -49
- package/dist/llm/call-ai.js +0 -62
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/output/shapes/distill.js +0 -14
- package/dist/output/shapes/history.js +0 -11
- package/dist/output/text/distill.js +0 -6
- package/dist/output/text/enable-disable.js +0 -8
- package/dist/output/text/history.js +0 -6
- package/dist/output/text/wiki.js +0 -16
- package/dist/registry/build-index.js +0 -386
- package/dist/scripts/migrate-storage.js +0 -19108
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -9411
- package/dist/scripts/migrations/v16-to-v17.js +0 -141
- package/dist/setup/legacy-config.js +0 -106
- package/dist/storage/repositories/consolidation-repository.js +0 -38
- package/dist/storage/repositories/recombine-repository.js +0 -213
- package/dist/wiki/wiki-templates.js +0 -15
- package/dist/wiki/wiki.js +0 -1012
- package/dist/workflows/db.js +0 -215
- package/docs/data-and-telemetry.md +0 -226
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
|
@@ -4,6 +4,15 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* Zod schema for AkmConfig — the single source of truth for the on-disk shape.
|
|
6
6
|
*
|
|
7
|
+
* ASSEMBLY BARREL: the individual section schemas live under `./schema/*` (one
|
|
8
|
+
* cohesive module per config area — engines, embedding, improve, sources/
|
|
9
|
+
* bundles, index, search, output, feedback, workflow, setup, plus shared
|
|
10
|
+
* `primitives`). This file assembles them into the top-level {@link AkmConfigShape}
|
|
11
|
+
* / {@link AkmConfigSchema}, owns the cross-field {@link AkmConfigSchema.superRefine},
|
|
12
|
+
* and RE-EXPORTS every section schema so all existing `./config-schema` imports
|
|
13
|
+
* keep working unchanged. The decomposition is a pure structural refactor — the
|
|
14
|
+
* generated `schemas/akm-config.json` is byte-identical.
|
|
15
|
+
*
|
|
7
16
|
* Two responsibilities:
|
|
8
17
|
* 1. **Validate + transform** the raw JSON-parsed config object into the runtime
|
|
9
18
|
* `AkmConfig` shape consumed by the rest of the codebase. Replaces the
|
|
@@ -34,891 +43,281 @@
|
|
|
34
43
|
* enforced at save time via `superRefine` on the top-level schema.
|
|
35
44
|
*/
|
|
36
45
|
import { z } from "zod";
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
export
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
];
|
|
67
|
-
// ── Connection configs (LLM / embedding) ────────────────────────────────────
|
|
68
|
-
const LlmCapabilitiesSchema = z
|
|
46
|
+
import { BUILTIN_IMPROVE_STRATEGY_NAMES, IMPROVE_PROCESS_ENGINE_CAPABILITIES } from "./engine-semantics.js";
|
|
47
|
+
import { EmbeddingConnectionConfigSchema } from "./schema/embedding.js";
|
|
48
|
+
import { EnginesSchema } from "./schema/engines.js";
|
|
49
|
+
import { ExperimentalConfigSchema } from "./schema/experimental.js";
|
|
50
|
+
import { FeedbackConfigSchema } from "./schema/feedback.js";
|
|
51
|
+
import { ImproveConfigSchema } from "./schema/improve.js";
|
|
52
|
+
import { IndexConfigSchema } from "./schema/index-config.js";
|
|
53
|
+
import { OutputConfigSchema } from "./schema/output.js";
|
|
54
|
+
import { CURRENT_CONFIG_VERSION, engineName, GlobalModelAliasesSchema, nonEmptyString, nonNegativeNumber, } from "./schema/primitives.js";
|
|
55
|
+
import { SearchConfigSchema } from "./schema/search.js";
|
|
56
|
+
import { SetupConfigSchema } from "./schema/setup.js";
|
|
57
|
+
import { BundlesConfigSchema, RegistryConfigEntrySchema } from "./schema/sources-bundles.js";
|
|
58
|
+
import { WorkflowConfigSchema } from "./schema/workflow.js";
|
|
59
|
+
// ── Section re-exports (keep every `./config-schema` import path working) ────
|
|
60
|
+
export { EmbeddingConnectionConfigSchema } from "./schema/embedding.js";
|
|
61
|
+
export { EngineConfigSchema, EnginesSchema, LlmConnectionConfigSchema, LlmProfileConfigSchema } from "./schema/engines.js";
|
|
62
|
+
export { ExperimentalConfigSchema } from "./schema/experimental.js";
|
|
63
|
+
export { FEEDBACK_FAILURE_MODES, FeedbackConfigSchema } from "./schema/feedback.js";
|
|
64
|
+
export { ImproveConfigSchema } from "./schema/improve.js";
|
|
65
|
+
export { ConsolidateProcessConfigSchema, DistillProcessConfigSchema, ExtractProcessConfigSchema, GraphExtractionProcessConfigSchema, ImproveProcessConfigSchema, ImproveProfileConfigSchema, MemoryInferenceProcessConfigSchema, ProactiveMaintenanceProcessConfigSchema, ReflectProcessConfigSchema, TriageProcessConfigSchema, ValidationProcessConfigSchema, } from "./schema/improve-processes.js";
|
|
66
|
+
export { IndexConfigSchema, IndexPassConfigSchema } from "./schema/index-config.js";
|
|
67
|
+
export { OutputConfigSchema } from "./schema/output.js";
|
|
68
|
+
export { CURRENT_CONFIG_VERSION, LlmInvocationOverridesSchema } from "./schema/primitives.js";
|
|
69
|
+
export { SearchConfigSchema } from "./schema/search.js";
|
|
70
|
+
export { SetupConfigSchema } from "./schema/setup.js";
|
|
71
|
+
export { BundleConfigEntrySchema, BundlesConfigSchema, RegistryConfigEntrySchema, SourceConfigEntrySchema, } from "./schema/sources-bundles.js";
|
|
72
|
+
export { WorkflowConfigSchema } from "./schema/workflow.js";
|
|
73
|
+
// ── Defaults ───────────────────────────────────────────────────────────────
|
|
74
|
+
export const DefaultsSchema = z
|
|
69
75
|
.object({
|
|
70
|
-
|
|
76
|
+
engine: engineName.optional(),
|
|
77
|
+
llmEngine: engineName.optional(),
|
|
78
|
+
improveStrategy: engineName.optional(),
|
|
71
79
|
})
|
|
72
80
|
.passthrough();
|
|
81
|
+
// ── Top-level AkmConfig ────────────────────────────────────────────────────
|
|
73
82
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
83
|
+
* Base object schema used both as the top-level shape and as the source of
|
|
84
|
+
* truth for {@link listTopLevelConfigKeys}. {@link AkmConfigSchema} wraps this
|
|
85
|
+
* with cross-field refinements (`.superRefine()`).
|
|
86
|
+
*
|
|
87
|
+
* All fields validate loudly — typos and shape errors throw at load time. The
|
|
88
|
+
* legacy parser's warn-and-drop tolerance was a frequent source of silent
|
|
89
|
+
* configuration loss; the migration module ({@link migrateConfigShape}) handles
|
|
90
|
+
* one-time 0.7→0.8 input transforms before the schema sees the value.
|
|
80
91
|
*/
|
|
81
|
-
export const
|
|
82
|
-
.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
model:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
.
|
|
92
|
+
export const AkmConfigShape = {
|
|
93
|
+
configVersion: z.literal(CURRENT_CONFIG_VERSION),
|
|
94
|
+
engines: EnginesSchema.optional(),
|
|
95
|
+
defaults: DefaultsSchema.optional(),
|
|
96
|
+
// Global model-alias tiers: alias → platform → exact model string, with a
|
|
97
|
+
// reserved `"*"` platform key as fallback. Lets workflows/callers name a
|
|
98
|
+
// semantic tier ("fast", "deep") that resolves per-harness at dispatch
|
|
99
|
+
// time. Values are literal model strings, never other aliases (one
|
|
100
|
+
// resolution level). Platform keys match the platform string a command
|
|
101
|
+
// builder resolves against ("claude", "opencode", "opencode-sdk", or a
|
|
102
|
+
// custom profile's name for the default builder) — unknown keys are inert.
|
|
103
|
+
// Precedence: profile modelAliases > this table > built-in aliases.
|
|
104
|
+
modelAliases: GlobalModelAliasesSchema.optional(),
|
|
105
|
+
semanticSearchMode: z.enum(["off", "auto"]).default("off"),
|
|
106
|
+
embedding: EmbeddingConnectionConfigSchema.optional(),
|
|
107
|
+
index: IndexConfigSchema.optional(),
|
|
108
|
+
registries: z.array(RegistryConfigEntrySchema).optional(),
|
|
109
|
+
// 0.9.0 config-shape cutover (spec §10.1 / D-R5). `bundles` + `defaultBundle`
|
|
110
|
+
// are the ONLY source shape — the retired `stashDir`/`sources[]`/`installed[]`
|
|
111
|
+
// trio is hard-rejected at load (see the top-level superRefine). The migrator
|
|
112
|
+
// ({@link migrateConfigSourcesToBundles}) converts a pre-cutover config to this
|
|
113
|
+
// shape before validation. `defaultBundle` names the primary bundle (spec
|
|
114
|
+
// §11.1 short-ref resolution / D-R4).
|
|
115
|
+
bundles: BundlesConfigSchema.optional(),
|
|
116
|
+
defaultBundle: nonEmptyString.optional(),
|
|
117
|
+
output: OutputConfigSchema.optional(),
|
|
118
|
+
defaultWriteTarget: nonEmptyString.optional(),
|
|
119
|
+
search: SearchConfigSchema.optional(),
|
|
120
|
+
feedback: FeedbackConfigSchema.optional(),
|
|
121
|
+
archiveRetentionDays: nonNegativeNumber.optional(),
|
|
122
|
+
improve: ImproveConfigSchema.optional(),
|
|
123
|
+
workflow: WorkflowConfigSchema.optional(),
|
|
124
|
+
setup: SetupConfigSchema.optional(),
|
|
125
|
+
// D8 — explicit opt-ins for behaviour outside the stability contract. Every
|
|
126
|
+
// key defaults to OFF; see `src/core/config/experimental.ts` for the readers.
|
|
127
|
+
experimental: ExperimentalConfigSchema.optional(),
|
|
128
|
+
};
|
|
129
|
+
export const AkmConfigBaseSchema = z.object(AkmConfigShape).passthrough();
|
|
106
130
|
/**
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* Consumers route via `hasRemoteEndpoint()` which checks for an http(s)
|
|
113
|
-
* endpoint — absent fields take the local path naturally, no sentinels needed.
|
|
131
|
+
* Per-key overrides for the retired `stashDir`/`sources`/`installed` source-
|
|
132
|
+
* shape rejection below. Keys without an entry fall back to the shared
|
|
133
|
+
* "retired pre-cutover source shape" message, which already names the
|
|
134
|
+
* replacement (bundles) and the migration command.
|
|
114
135
|
*/
|
|
115
|
-
|
|
116
|
-
.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
})
|
|
129
|
-
.passthrough();
|
|
130
|
-
// ── Agent profiles ──────────────────────────────────────────────────────────
|
|
131
|
-
// Derives from the canonical VALID_HARNESS_IDS (#565) so the Zod gate cannot
|
|
132
|
-
// drift from the TS union / parse check / setup detection.
|
|
133
|
-
const AgentPlatformSchema = z.enum(VALID_HARNESS_IDS);
|
|
134
|
-
export const AgentProfileConfigSchema = z
|
|
135
|
-
.object({
|
|
136
|
-
platform: AgentPlatformSchema,
|
|
137
|
-
bin: z.string().min(1).optional(),
|
|
138
|
-
args: z.array(z.string()).optional(),
|
|
139
|
-
workspace: z.string().min(1).optional(),
|
|
140
|
-
model: z.string().min(1).optional(),
|
|
141
|
-
// Per-call timeout (ms) used when a command does not pass an explicit
|
|
142
|
-
// timeout (e.g. `akm wiki ingest` without `--timeout-ms`). null = no
|
|
143
|
-
// timeout. Honored by resolveAgentProfile (integrations/agent/config.ts).
|
|
144
|
-
timeoutMs: z.union([positiveInt, z.null()]).optional(),
|
|
145
|
-
// Per-profile model aliases: lowercase alias → exact model string for
|
|
146
|
-
// this profile's CLI. Highest-precedence tier in resolveModel
|
|
147
|
-
// (integrations/agent/model-aliases.ts) — beats the config-root
|
|
148
|
-
// `modelAliases` table and the built-in opus/sonnet/haiku entries.
|
|
149
|
-
modelAliases: z.record(z.string().min(1), z.string().min(1)).optional(),
|
|
150
|
-
})
|
|
151
|
-
.passthrough();
|
|
152
|
-
// ── Improve profile / process ──────────────────────────────────────────────
|
|
153
|
-
export const ImproveProcessConfigSchema = z
|
|
154
|
-
.object({
|
|
155
|
-
enabled: z.boolean().optional(),
|
|
156
|
-
mode: z.enum(["llm", "agent", "sdk"]).optional(),
|
|
157
|
-
profile: z.string().min(1).optional(),
|
|
158
|
-
timeoutMs: z.union([positiveInt, z.null()]).optional(),
|
|
159
|
-
allowedTypes: z.array(z.string().min(1)).optional(),
|
|
160
|
-
// Consolidate process: minimum eligible-memory pool size below which the
|
|
161
|
-
// consolidation pass skips entirely (emits `pool_below_min_size`). 0 disables
|
|
162
|
-
// the guard. Only meaningful on the `consolidate` process. Default 500.
|
|
163
|
-
minPoolSize: z.number().int().min(0).optional(),
|
|
164
|
-
// Consolidate process: deterministic near-duplicate dedup pre-pass (#617).
|
|
165
|
-
// A cheap, no-LLM fast path that collapses obvious duplicates (`.derived`
|
|
166
|
-
// origin pairs + content twins) before the LLM consolidation. Default OFF
|
|
167
|
-
// — when absent the consolidate pass behaves byte-identically to today.
|
|
168
|
-
// `cosineThreshold` is a strict floor in [0, 1] (default 0.97) for the
|
|
169
|
-
// optional embedding-similarity match; exact normalized content-hash
|
|
170
|
-
// equality always collapses regardless of the threshold. Only meaningful
|
|
171
|
-
// on the `consolidate` process.
|
|
172
|
-
dedup: z
|
|
173
|
-
.object({
|
|
174
|
-
enabled: z.boolean().optional(),
|
|
175
|
-
cosineThreshold: z.number().min(0).max(1).optional(),
|
|
176
|
-
// WS-3a: maximum pool size for the O(n²) cosine-similarity twin compare.
|
|
177
|
-
// Only the first `cosineCandidateLimit` memories are cosine-compared;
|
|
178
|
-
// exact-hash matches still run over the full pool. Default 500. Raise
|
|
179
|
-
// with care — cost is O(n²).
|
|
180
|
-
cosineCandidateLimit: z.number().int().positive().optional(),
|
|
181
|
-
})
|
|
182
|
-
.passthrough()
|
|
183
|
-
.optional(),
|
|
184
|
-
// Consolidate process: judged-state cache (#581). When enabled, a memory
|
|
185
|
-
// whose current content hash equals its cached judged hash is SKIPPED from
|
|
186
|
-
// the LLM pool (judged-unchanged → no re-judge), letting one run sweep the
|
|
187
|
-
// whole corpus at O(changed/new) cost instead of narrowing to a recent
|
|
188
|
-
// time-window slice. Default OFF — when absent the consolidate pass behaves
|
|
189
|
-
// byte-identically to today (the incrementalSince path is unaffected). Only
|
|
190
|
-
// meaningful on the `consolidate` process.
|
|
191
|
-
judgedCache: z.object({ enabled: z.boolean().optional() }).passthrough().optional(),
|
|
192
|
-
// Distill process: LLM-as-judge lesson quality gate. Default ON (R3);
|
|
193
|
-
// fail-open — judge failure/timeout/parse errors pass through. Set
|
|
194
|
-
// `enabled: false` on the distill process to opt out.
|
|
195
|
-
qualityGate: z.object({ enabled: z.boolean().optional() }).passthrough().optional(),
|
|
196
|
-
contradictionDetection: z.object({ enabled: z.boolean().optional() }).passthrough().optional(),
|
|
197
|
-
// Extract process config (only meaningful for extract process)
|
|
198
|
-
defaultSince: z.string().min(1).optional(),
|
|
199
|
-
maxTotalChars: positiveInt.optional(),
|
|
200
|
-
// Extract process: minimum raw session size (pre-filter inputCount) below
|
|
201
|
-
// which the extract LLM call is skipped (#595/#596). 0 disables the gate.
|
|
202
|
-
// Absent = default 10 (skip only truly empty sessions). Only meaningful
|
|
203
|
-
// on the `extract` process.
|
|
204
|
-
minContentChars: z.number().int().min(0).optional(),
|
|
205
|
-
maxChunkSize: z.number().int().min(1).max(50).optional(),
|
|
206
|
-
// Consolidate process: narrow candidate pool to memories modified within
|
|
207
|
-
// this duration window plus their graph neighbours. Only meaningful on
|
|
208
|
-
// the `consolidate` process. Absent = full-pool sweep.
|
|
209
|
-
incrementalSince: z.string().optional(),
|
|
210
|
-
// Consolidate process: hard cap on memories processed per pass.
|
|
211
|
-
// Reflect/distill: max refs processed (same as profile-level `limit`).
|
|
212
|
-
limit: positiveInt.optional(),
|
|
213
|
-
// Consolidate process: graph neighbours per changed memory during
|
|
214
|
-
// incremental consolidation. Default 5. Only meaningful with incrementalSince.
|
|
215
|
-
neighborsPerChanged: z.number().int().min(1).optional(),
|
|
216
|
-
// Distill process: skip distill entirely when reflect produced zero planned refs.
|
|
217
|
-
requirePlannedRefs: z.boolean().optional(),
|
|
218
|
-
// proactiveMaintenance process (Layer 2): staleness gate + rotation cooldown
|
|
219
|
-
// in days (default 30). Only meaningful on `proactiveMaintenance`.
|
|
220
|
-
dueDays: z.number().int().min(0).optional(),
|
|
221
|
-
// proactiveMaintenance process: top-N bound per run (default 25). Alias for
|
|
222
|
-
// `limit`; `maxPerRun` wins when both are set.
|
|
223
|
-
maxPerRun: positiveInt.optional(),
|
|
224
|
-
// graphExtraction process (#624 P2): when set, rank eligible files by
|
|
225
|
-
// utility_scores DESC and process only the top-N per run (incremental
|
|
226
|
-
// high-signal-first sweep). Unset = process all eligible (current
|
|
227
|
-
// behavior). Only meaningful on `graphExtraction`.
|
|
228
|
-
topN: positiveInt.optional(),
|
|
229
|
-
// graphExtraction process: full-corpus scan. When true, graph extraction
|
|
230
|
-
// runs on ALL stash files instead of only files touched by actionable refs
|
|
231
|
-
// in the current run. Used by the `graph-refresh` built-in profile / a
|
|
232
|
-
// scheduled weekly task. Only meaningful on `graphExtraction`.
|
|
233
|
-
fullScan: z.boolean().optional(),
|
|
234
|
-
// #626 — extract process: pre-LLM heuristic triage gate. When enabled, a
|
|
235
|
-
// deterministic scorer decides BEFORE the extraction LLM call whether a
|
|
236
|
-
// session carries enough signal to be worth extracting; low-signal sessions
|
|
237
|
-
// are skipped at zero LLM cost. Default OFF. Only meaningful on `extract`.
|
|
238
|
-
// `minScore` is the minimum total heuristic score to PASS (default 2).
|
|
239
|
-
triage: z
|
|
240
|
-
.object({
|
|
241
|
-
enabled: z.boolean().optional(),
|
|
242
|
-
minScore: z.number().min(0).optional(),
|
|
243
|
-
})
|
|
244
|
-
.passthrough()
|
|
245
|
-
.optional(),
|
|
246
|
-
// MemoryInference process: minimum pending memory count to run the pass.
|
|
247
|
-
minPendingCount: z.number().int().min(0).optional(),
|
|
248
|
-
// Extract process: minimum number of new (unseen, in-window) candidate
|
|
249
|
-
// sessions below which the extract pass skips entirely (emits an
|
|
250
|
-
// `improve_skipped` event with `reason: "below_min_new_sessions"`). 0
|
|
251
|
-
// disables the guard. Only meaningful on the `extract` process. Default 0
|
|
252
|
-
// (disabled) so existing behaviour is preserved; only opted-in profiles set it.
|
|
253
|
-
minNewSessions: z.number().int().min(0).optional(),
|
|
254
|
-
// Extract process: cap on NEW sessions processed (LLM-called) per run; the
|
|
255
|
-
// rest roll to the next run (still unseen). 0 disables. Absent = default 25.
|
|
256
|
-
maxSessionsPerRun: z.number().int().min(0).optional(),
|
|
257
|
-
// #561 — index agent sessions as a searchable `session` asset (extract
|
|
258
|
-
// process). Absent = on-when-an-LLM-is-available (fail-open when offline).
|
|
259
|
-
// COST: when on, each processed session makes a SECOND LLM call (the session
|
|
260
|
-
// summary) on top of the extraction call — i.e. ~2 LLM calls/session. Set to
|
|
261
|
-
// false to halve per-session extract cost at the price of unsearchable
|
|
262
|
-
// sessions. (Unchanged/skip sessions still cost zero — the content-hash
|
|
263
|
-
// ledger gates both calls upstream.)
|
|
264
|
-
indexSessions: z.boolean().optional(),
|
|
265
|
-
// #561 — minimum session duration in minutes for session indexing. 0
|
|
266
|
-
// disables the gate. Absent = default 5. Only meaningful on `extract`.
|
|
267
|
-
minSessionDuration: z.number().min(0).optional(),
|
|
268
|
-
// Consolidate process: fallback p90 wall-clock time per consolidation chunk
|
|
269
|
-
// in seconds, used for cold-start budget estimation when no telemetry
|
|
270
|
-
// history exists. The actual p90 is derived from observed run durations
|
|
271
|
-
// once sufficient history accumulates; this value is only used on the very
|
|
272
|
-
// first run. Default 30 s. Only meaningful on the `consolidate` process.
|
|
273
|
-
p90ChunkSecondsDefault: z.number().finite().positive().optional(),
|
|
274
|
-
// (WS-3b step 0a `homeostaticDemotion` was removed — R4. The key is
|
|
275
|
-
// tolerated via passthrough if an old config still carries it; continuous
|
|
276
|
-
// decay is now part of the always-applied salience recency term.)
|
|
277
|
-
// WS-3b: Schema-similarity gate (step 0b). At intake, if a new candidate's
|
|
278
|
-
// body embedding is within epsilon of an existing derived-layer lesson/knowledge
|
|
279
|
-
// node, mark it schema-consistent and lower its priority. Default ON for
|
|
280
|
-
// the `extract` process since R3 (fail-open; set `enabled: false` to opt out).
|
|
281
|
-
// Only meaningful on the `consolidate` and `extract` processes.
|
|
282
|
-
schemaSimilarity: z
|
|
283
|
-
.object({
|
|
284
|
-
enabled: z.boolean().optional(),
|
|
285
|
-
// Epsilon: cosine similarity threshold above which a candidate is schema-consistent
|
|
286
|
-
// (default 0.85 — looser than dedup's 0.97 since we want to catch conceptual overlap).
|
|
287
|
-
epsilon: z.number().min(0).max(1).optional(),
|
|
288
|
-
// Multiplicative factor applied to candidate confidence when schema-consistent.
|
|
289
|
-
// Default 0.5 — halves the confidence so schema-consistent candidates are less likely
|
|
290
|
-
// to pass the quality gate and create redundant stash entries.
|
|
291
|
-
confidencePenalty: z.number().min(0).max(1).optional(),
|
|
292
|
-
})
|
|
293
|
-
.passthrough()
|
|
294
|
-
.optional(),
|
|
295
|
-
// WS-3b: Hot-probation intake buffer (step 0c, #604). New system-generated
|
|
296
|
-
// extractions enter captureMode: hot-probation and spend ONE consolidation
|
|
297
|
-
// cycle in probation. Dedup + quality second-pass runs before promotion.
|
|
298
|
-
// Default OFF. Only meaningful on the `extract` process.
|
|
299
|
-
hotProbation: z
|
|
300
|
-
.object({
|
|
301
|
-
enabled: z.boolean().optional(),
|
|
302
|
-
})
|
|
303
|
-
.passthrough()
|
|
304
|
-
.optional(),
|
|
305
|
-
// WS-3b: Anti-collapse guards (step 8). Prevents the consolidation pipeline
|
|
306
|
-
// from collapsing too aggressively and losing diversity.
|
|
307
|
-
// - maxGeneration: refuse to merge two assets both above this generation (default 2).
|
|
308
|
-
// - lexicalDiversityCheck: low n-gram diversity ⇒ raise merge threshold.
|
|
309
|
-
// - randomClusterFraction: occasional random (non-similar) cluster in pool (default 0.05).
|
|
310
|
-
// - mergeInformationFloor: measure that merges keep provenance + specificity
|
|
311
|
-
// (R5 §4.2; ADVISORY in v1 — counted, never refused).
|
|
312
|
-
// - minSpecificityRetention: distinct-token retention floor for merges (default 0.6).
|
|
313
|
-
// Default ON since R5 (opt out via enabled: false). Only meaningful on the
|
|
314
|
-
// `consolidate` process.
|
|
315
|
-
antiCollapse: z
|
|
316
|
-
.object({
|
|
317
|
-
enabled: z.boolean().optional(),
|
|
318
|
-
maxGeneration: z.number().int().min(1).optional(),
|
|
319
|
-
lexicalDiversityCheck: z.boolean().optional(),
|
|
320
|
-
randomClusterFraction: z.number().min(0).max(1).optional(),
|
|
321
|
-
mergeInformationFloor: z.boolean().optional(),
|
|
322
|
-
minSpecificityRetention: z.number().min(0).max(1).optional(),
|
|
323
|
-
})
|
|
324
|
-
.passthrough()
|
|
325
|
-
.optional(),
|
|
326
|
-
// WS-3b: CLS (Complementary Learning System) interleaving (step 9).
|
|
327
|
-
// distill/memoryInference prompts include embedding-retrieved existing adjacent
|
|
328
|
-
// lessons/knowledge to prevent catastrophic interference with prior generalizations.
|
|
329
|
-
// Default OFF. Only meaningful on `distill` and `memoryInference` processes.
|
|
330
|
-
cls: z
|
|
331
|
-
.object({
|
|
332
|
-
enabled: z.boolean().optional(),
|
|
333
|
-
// Number of adjacent lessons/knowledge to include in prompts (default 3).
|
|
334
|
-
adjacentCount: z.number().int().min(1).optional(),
|
|
335
|
-
})
|
|
336
|
-
.passthrough()
|
|
337
|
-
.optional(),
|
|
338
|
-
// WS-3b: Distill→source fidelity check (step 10). After a distill proposal,
|
|
339
|
-
// check it against its cited source memories; a contradiction flag forces
|
|
340
|
-
// human review. Default OFF. Only meaningful on `distill` process.
|
|
341
|
-
fidelityCheck: z
|
|
342
|
-
.object({
|
|
343
|
-
enabled: z.boolean().optional(),
|
|
344
|
-
})
|
|
345
|
-
.passthrough()
|
|
346
|
-
.optional(),
|
|
347
|
-
// #609 — recombine process: minimum related-memory cluster size before an
|
|
348
|
-
// LLM generalization call. Default 3. Only meaningful on `recombine`.
|
|
349
|
-
minClusterSize: z.number().int().min(2).optional(),
|
|
350
|
-
// #609 — recombine process: hard cap on clusters processed per run (one
|
|
351
|
-
// bounded LLM call each). Default 5. Only meaningful on `recombine`.
|
|
352
|
-
maxClustersPerRun: positiveInt.optional(),
|
|
353
|
-
// #632 — recombine process: max members a cluster may contain before it is
|
|
354
|
-
// SKIPPED (drops bland over-broad buckets). When set, largest-first ranking
|
|
355
|
-
// no longer starves tighter clusters. Default UNSET = no cap. Only
|
|
356
|
-
// meaningful on `recombine`.
|
|
357
|
-
maxClusterSize: positiveInt.optional(),
|
|
358
|
-
// #632 — recombine process: tag values that must never form a tag cluster
|
|
359
|
-
// (generic project-wide tags). Default UNSET/[]. Only meaningful on
|
|
360
|
-
// `recombine`.
|
|
361
|
-
excludeTags: z.array(z.string().min(1)).optional(),
|
|
362
|
-
// #632 — recombine process: entity_norm values that must never form an
|
|
363
|
-
// entity cluster (user counterpart to the built-in generic-entity filter).
|
|
364
|
-
// Default UNSET/[]. Only meaningful on `recombine`.
|
|
365
|
-
excludeEntities: z.array(z.string().min(1)).optional(),
|
|
366
|
-
// #609 — recombine process: relatedness signal used to form clusters
|
|
367
|
-
// (tags | graph | both). Clustering is by relatedness, never embedding
|
|
368
|
-
// similarity. Default "both" (#632). Only meaningful on `recombine`.
|
|
369
|
-
relatednessSource: z.enum(["tags", "graph", "both"]).optional(),
|
|
370
|
-
// #609 — recombine process: consecutive re-inductions required before a
|
|
371
|
-
// hypothesis is promoted to a lesson. Default 2. Only meaningful on
|
|
372
|
-
// `recombine`.
|
|
373
|
-
confirmThreshold: z.number().int().min(1).optional(),
|
|
374
|
-
// #615 — procedural process: minimum number of distinct assets sharing the
|
|
375
|
-
// same successful normalized ordered-action sequence before it is compiled
|
|
376
|
-
// into a workflow proposal. Default 3. Only meaningful on `procedural`.
|
|
377
|
-
minRecurrence: z.number().int().min(2).optional(),
|
|
378
|
-
// #615 — procedural process: hard cap on workflow proposals emitted per run
|
|
379
|
-
// (one bounded LLM call each). Default 3. Only meaningful on `procedural`.
|
|
380
|
-
maxProposalsPerRun: positiveInt.optional(),
|
|
381
|
-
// #615 — procedural process: asset type a compiled sequence is emitted as.
|
|
382
|
-
// Reserved; v1 always emits "workflow". Only meaningful on `procedural`.
|
|
383
|
-
emitAs: z.enum(["workflow", "skill"]).optional(),
|
|
384
|
-
// #639 — semantic value-floor filter for the `reflect` process. When
|
|
385
|
-
// enabled, proposals classified as "low-value" by the deterministic noise
|
|
386
|
-
// gate are deferred. DEFAULT OFF (absent / { enabled: false } = pre-#639
|
|
387
|
-
// byte-identical behaviour). Only meaningful on the `reflect` process.
|
|
388
|
-
lowValueFilter: z.object({ enabled: z.boolean().optional() }).passthrough().optional(),
|
|
389
|
-
// #641 — procedural-aware floor for the `extract` process triage gate.
|
|
390
|
-
// When true, a session must have markers>=1 OR editCommit>=0.5 to pass, even
|
|
391
|
-
// if score>=minScore. DEFAULT OFF (absent/false = pre-#641 byte-identical).
|
|
392
|
-
// Only meaningful on the `extract` process when triage is also enabled.
|
|
393
|
-
proceduralAwareFloor: z.boolean().optional(),
|
|
394
|
-
// Triage process config (only meaningful for the `triage` process)
|
|
395
|
-
applyMode: z.enum(["queue", "promote"]).optional(),
|
|
396
|
-
policy: z.string().min(1).optional(),
|
|
397
|
-
maxAcceptsPerRun: positiveInt.optional(),
|
|
398
|
-
maxDiffLines: positiveInt.optional(),
|
|
399
|
-
rejectEmpty: z.boolean().optional(),
|
|
400
|
-
judgment: z
|
|
401
|
-
.object({
|
|
402
|
-
mode: z.enum(["llm", "agent", "sdk"]).optional(),
|
|
403
|
-
profile: z.string().min(1).optional(),
|
|
404
|
-
timeoutMs: z.union([positiveInt, z.null()]).optional(),
|
|
405
|
-
})
|
|
406
|
-
.passthrough()
|
|
407
|
-
.optional(),
|
|
408
|
-
})
|
|
409
|
-
.passthrough();
|
|
410
|
-
const ImproveProfileProcessesSchema = z
|
|
411
|
-
.object({
|
|
412
|
-
reflect: ImproveProcessConfigSchema.optional(),
|
|
413
|
-
distill: ImproveProcessConfigSchema.optional(),
|
|
414
|
-
consolidate: ImproveProcessConfigSchema.optional(),
|
|
415
|
-
memoryInference: ImproveProcessConfigSchema.optional(),
|
|
416
|
-
graphExtraction: ImproveProcessConfigSchema.optional(),
|
|
417
|
-
extract: ImproveProcessConfigSchema.optional(),
|
|
418
|
-
validation: ImproveProcessConfigSchema.optional(),
|
|
419
|
-
triage: ImproveProcessConfigSchema.optional(),
|
|
420
|
-
proactiveMaintenance: ImproveProcessConfigSchema.optional(),
|
|
421
|
-
recombine: ImproveProcessConfigSchema.optional(),
|
|
422
|
-
procedural: ImproveProcessConfigSchema.optional(),
|
|
423
|
-
})
|
|
424
|
-
.passthrough()
|
|
425
|
-
.superRefine((val, ctx) => {
|
|
426
|
-
// 0.8.0 removed the duplicated `feedbackDistillation` process key — it was
|
|
427
|
-
// a thin wrapper around `processes.distill.enabled`. Keep the migration
|
|
428
|
-
// hint so a stale config gets an actionable message rather than silently
|
|
429
|
-
// doing nothing. All OTHER unknown process keys are tolerated (passthrough)
|
|
430
|
-
// — see the unknown-key policy in this file's header. Hard-rejecting them
|
|
431
|
-
// turned benign cross-version skew into INVALID_CONFIG_FILE failures.
|
|
432
|
-
if ("feedbackDistillation" in val) {
|
|
433
|
-
ctx.addIssue({
|
|
434
|
-
code: z.ZodIssueCode.custom,
|
|
435
|
-
message: "feedbackDistillation was removed in 0.8.0 — use processes.distill.enabled instead. " +
|
|
436
|
-
"It now controls both the orchestration gate and the LLM-call gate.",
|
|
437
|
-
});
|
|
136
|
+
const RETIRED_SOURCE_SHAPE_KEY_MESSAGES = {
|
|
137
|
+
stashDir: "stashDir is retired in 0.9; the stash path now comes from `bundles`. Run `akm-migrate apply` to convert a pre-0.9 config, or see `akm config path --all` / `akm info`.",
|
|
138
|
+
};
|
|
139
|
+
export const AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) => {
|
|
140
|
+
const raw = config;
|
|
141
|
+
for (const key of ["profiles", "llm", "agent", "features", "stashes"]) {
|
|
142
|
+
if (key in raw) {
|
|
143
|
+
ctx.addIssue({
|
|
144
|
+
code: z.ZodIssueCode.custom,
|
|
145
|
+
path: [key],
|
|
146
|
+
message: `${key} is retired in 0.9; configure engines and improve.strategies instead`,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
438
149
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
.
|
|
442
|
-
|
|
443
|
-
processes: ImproveProfileProcessesSchema.optional(),
|
|
444
|
-
autoAccept: nonNegativeNumber.optional(),
|
|
445
|
-
limit: positiveInt.optional(),
|
|
446
|
-
// #616 — bounded multi-cycle phasing. Number of prep->loop->post-loop
|
|
447
|
-
// cycles per run. positiveInt forbids 0/negative. DEFAULT 1 => byte-identical
|
|
448
|
-
// single-pass behavior.
|
|
449
|
-
maxCycles: positiveInt.optional(),
|
|
450
|
-
// #614 — symmetric valence weighting in the eligibility sort. When true,
|
|
451
|
-
// the attention term becomes |valence| MAGNITUDE so BOTH strong positive
|
|
452
|
-
// and strong negative feedback drive attention (utility stays dominant) and
|
|
453
|
-
// strong-signed assets are routed to a fix/reinforce lane. DEFAULT OFF —
|
|
454
|
-
// false/absent preserves the legacy negative-only ranking byte-for-byte.
|
|
455
|
-
symmetricValence: z.boolean().optional(),
|
|
456
|
-
sync: z
|
|
457
|
-
.object({
|
|
458
|
-
enabled: z.boolean().optional(),
|
|
459
|
-
push: z.boolean().optional(),
|
|
460
|
-
message: z.string().min(1).optional(),
|
|
461
|
-
})
|
|
462
|
-
.passthrough()
|
|
463
|
-
.optional(),
|
|
464
|
-
})
|
|
465
|
-
.passthrough();
|
|
466
|
-
// ── Profiles / defaults ────────────────────────────────────────────────────
|
|
467
|
-
export const ProfilesSchema = z
|
|
468
|
-
.object({
|
|
469
|
-
llm: z.record(z.string(), LlmProfileConfigSchema).optional(),
|
|
470
|
-
agent: z.record(z.string(), AgentProfileConfigSchema).optional(),
|
|
471
|
-
improve: z.record(z.string(), ImproveProfileConfigSchema).optional(),
|
|
472
|
-
})
|
|
473
|
-
.passthrough();
|
|
474
|
-
export const DefaultsSchema = z
|
|
475
|
-
.object({
|
|
476
|
-
llm: z.string().min(1).optional(),
|
|
477
|
-
agent: z.string().min(1).optional(),
|
|
478
|
-
improve: z.string().min(1).optional(),
|
|
479
|
-
})
|
|
480
|
-
.passthrough();
|
|
481
|
-
// ── Sources / registries / installed ────────────────────────────────────────
|
|
482
|
-
const SourceConfigEntryOptionsSchema = z
|
|
483
|
-
.object({
|
|
484
|
-
/**
|
|
485
|
-
* @deprecated 0.9.0 (issue #507). Retired per-asset push-on-commit. Kept so
|
|
486
|
-
* old configs still parse; its intent maps onto the batch push gate and
|
|
487
|
-
* encountering it emits a one-time deprecation warning.
|
|
488
|
-
*/
|
|
489
|
-
pushOnCommit: z.boolean().optional(),
|
|
490
|
-
})
|
|
491
|
-
.passthrough();
|
|
492
|
-
export const SourceConfigEntrySchema = z
|
|
493
|
-
.object({
|
|
494
|
-
type: nonEmptyString,
|
|
495
|
-
path: z.string().min(1).optional(),
|
|
496
|
-
url: z.string().min(1).optional(),
|
|
497
|
-
name: z.string().min(1).optional(),
|
|
498
|
-
enabled: z.boolean().optional(),
|
|
499
|
-
writable: z.boolean().optional(),
|
|
500
|
-
primary: z.boolean().optional(),
|
|
501
|
-
options: SourceConfigEntryOptionsSchema.optional(),
|
|
502
|
-
wikiName: z.string().min(1).optional(),
|
|
503
|
-
})
|
|
504
|
-
.passthrough()
|
|
505
|
-
.superRefine((entry, ctx) => {
|
|
506
|
-
if (entry.writable === true && (entry.type === "website" || entry.type === "npm")) {
|
|
150
|
+
// `bindings` (spec §10.1) is Tier B — never emitted, never accepted. The
|
|
151
|
+
// top-level schema is `.passthrough()`, so without this it would round-trip
|
|
152
|
+
// silently; reject it loudly so a stray/hand-written bindings block is caught.
|
|
153
|
+
if ("bindings" in raw) {
|
|
507
154
|
ctx.addIssue({
|
|
508
155
|
code: z.ZodIssueCode.custom,
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
").",
|
|
156
|
+
path: ["bindings"],
|
|
157
|
+
message: "bindings is not supported in 0.9.0 (Tier B); it is neither emitted nor accepted",
|
|
512
158
|
});
|
|
513
159
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
.
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
stashRoot: nonEmptyString,
|
|
532
|
-
cacheDir: nonEmptyString,
|
|
533
|
-
installedAt: nonEmptyString,
|
|
534
|
-
writable: z.boolean().optional(),
|
|
535
|
-
resolvedVersion: z.string().min(1).optional(),
|
|
536
|
-
resolvedRevision: z.string().min(1).optional(),
|
|
537
|
-
wikiName: z.string().min(1).optional(),
|
|
538
|
-
})
|
|
539
|
-
.passthrough()
|
|
540
|
-
.superRefine((entry, ctx) => {
|
|
541
|
-
if (entry.writable === true && entry.source !== "git" && entry.source !== "filesystem") {
|
|
160
|
+
// 0.9.0 config-shape cutover (spec §10.1): the retired `stashDir`/`sources`/
|
|
161
|
+
// `installed` trio is HARD-REJECTED at load whenever present — `bundles` +
|
|
162
|
+
// `defaultBundle` fully supersede it. A pre-cutover config never loads through
|
|
163
|
+
// this validated path; the migrator ({@link migrateConfigSourcesToBundles})
|
|
164
|
+
// normalizes old→bundles BEFORE validation, and `inspectConfig` classifies an
|
|
165
|
+
// old-shape-alone config "old" (migration-eligible) via that same normalize.
|
|
166
|
+
for (const key of ["stashDir", "sources", "installed"]) {
|
|
167
|
+
if (key in raw && raw[key] !== undefined) {
|
|
168
|
+
ctx.addIssue({
|
|
169
|
+
code: z.ZodIssueCode.custom,
|
|
170
|
+
path: [key],
|
|
171
|
+
message: RETIRED_SOURCE_SHAPE_KEY_MESSAGES[key] ??
|
|
172
|
+
`${key} is the retired pre-cutover source shape; run \`akm-migrate apply\` to convert it to bundles`,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if ("writable" in raw) {
|
|
542
177
|
ctx.addIssue({
|
|
543
178
|
code: z.ZodIssueCode.custom,
|
|
544
|
-
|
|
179
|
+
path: ["writable"],
|
|
180
|
+
message: "top-level writable is not supported; configure bundles.<id>.writable instead",
|
|
545
181
|
});
|
|
546
182
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
.object({
|
|
551
|
-
format: z.enum(["json", "yaml", "text"]).optional(),
|
|
552
|
-
detail: z.enum(["brief", "normal", "full"]).optional(),
|
|
553
|
-
})
|
|
554
|
-
.passthrough();
|
|
555
|
-
// ── Search ──────────────────────────────────────────────────────────────────
|
|
556
|
-
const SearchGraphBoostSchema = z
|
|
557
|
-
.object({
|
|
558
|
-
directBoostPerEntity: nonNegativeNumber.optional(),
|
|
559
|
-
directBoostCap: nonNegativeNumber.optional(),
|
|
560
|
-
hopBoostPerEntity: nonNegativeNumber.optional(),
|
|
561
|
-
hopBoostCap: nonNegativeNumber.optional(),
|
|
562
|
-
/** Hard-capped at 3; values > 3 hard-error so users see the typo. */
|
|
563
|
-
maxHops: positiveInt.max(3).optional(),
|
|
564
|
-
confidenceMode: z.enum(["off", "blend", "multiply"]).default("blend").optional(),
|
|
565
|
-
/** Range [0, 1]; values > 1 hard-error (no silent clamp). */
|
|
566
|
-
confidenceWeight: z.number().finite().min(0).max(1).default(0.2).optional(),
|
|
567
|
-
})
|
|
568
|
-
.passthrough();
|
|
569
|
-
export const SearchConfigSchema = z
|
|
570
|
-
.object({
|
|
571
|
-
minScore: nonNegativeNumber.optional(),
|
|
572
|
-
defaultExcludeTypes: z.array(nonEmptyString).optional(),
|
|
573
|
-
graphBoost: SearchGraphBoostSchema.optional(),
|
|
574
|
-
})
|
|
575
|
-
.passthrough();
|
|
576
|
-
// ── Feedback ────────────────────────────────────────────────────────────────
|
|
577
|
-
export const FeedbackConfigSchema = z
|
|
578
|
-
.object({
|
|
579
|
-
requireReason: z.boolean().optional(),
|
|
580
|
-
allowedFailureModes: z.array(nonEmptyString).optional(),
|
|
581
|
-
})
|
|
582
|
-
.passthrough();
|
|
583
|
-
// ── Improve top-level (utility decay, event retention) ─────────────────────
|
|
584
|
-
const ImproveUtilityDecaySchema = z
|
|
585
|
-
.object({
|
|
586
|
-
halfLifeDays: z.number().finite().min(0.1).optional(),
|
|
587
|
-
feedbackStabilityBoost: z.number().finite().min(1).optional(),
|
|
588
|
-
})
|
|
589
|
-
.passthrough();
|
|
590
|
-
// #612 / WS-4 — auto-accept gate calibration + bounded, opt-in per-phase
|
|
591
|
-
// threshold auto-tune. DEFAULT OFF: when absent (or `autoTune: false`) no
|
|
592
|
-
// tuning occurs, so the gate behaves byte-identically to today.
|
|
593
|
-
// WS-4 adds: per-phase persistence (state.db) + auto-tune ceiling default 85.
|
|
594
|
-
const ImproveCalibrationSchema = z
|
|
595
|
-
.object({
|
|
596
|
-
/** Master switch for the bounded threshold auto-tune. Default false (parity). */
|
|
597
|
-
autoTune: z.boolean().optional(),
|
|
598
|
-
/** Lower bound (0-100) the tuned threshold may never drop below. */
|
|
599
|
-
minThreshold: z.number().int().min(0).max(100).optional(),
|
|
600
|
-
/**
|
|
601
|
-
* Upper bound (0-100) the tuned threshold may never rise above.
|
|
602
|
-
* WS-4 default: 85 (prevents gate converging to pure exploitation).
|
|
603
|
-
*/
|
|
604
|
-
maxThreshold: z.number().int().min(0).max(100).optional(),
|
|
605
|
-
/** Maximum adjustment magnitude (points) applied in one tune step. */
|
|
606
|
-
maxStep: positiveInt.optional(),
|
|
607
|
-
/** Minimum acted-on sample count required before any adjustment. */
|
|
608
|
-
minSamples: nonNegativeNumber.optional(),
|
|
609
|
-
/** Target realized accept rate in [0, 1]. Default 0.9. */
|
|
610
|
-
targetAcceptRate: z.number().finite().min(0).max(1).optional(),
|
|
611
|
-
})
|
|
612
|
-
.passthrough();
|
|
613
|
-
// WS-4 — exploration budget: a fixed fraction of proposals accepted per run
|
|
614
|
-
// regardless of confidence. DEFAULT OFF.
|
|
615
|
-
const ImproveExplorationSchema = z
|
|
616
|
-
.object({
|
|
617
|
-
/**
|
|
618
|
-
* Enable the exploration budget lane. Default false (parity).
|
|
619
|
-
* When true, a fraction of proposals are accepted regardless of confidence.
|
|
620
|
-
*/
|
|
621
|
-
enabled: z.boolean().optional(),
|
|
622
|
-
/**
|
|
623
|
-
* Fraction of proposals per run to accept as exploration [0, 1].
|
|
624
|
-
* Default 0.05 (5%). Clamped to [0, 1] at read time.
|
|
625
|
-
*/
|
|
626
|
-
budgetFraction: z.number().finite().min(0).max(1).optional(),
|
|
627
|
-
})
|
|
628
|
-
.passthrough();
|
|
629
|
-
const ImproveSalienceSchema = z
|
|
630
|
-
.object({
|
|
631
|
-
/**
|
|
632
|
-
* WS-2 Part-V gate: enable the outcome-weight term in the salience projection.
|
|
633
|
-
* Default false (parity — WS-1 weights w_e=0.30, w_r=0.70 until Part-V confirms
|
|
634
|
-
* no regression). Set to true after running scripts/akm-eval + health report.
|
|
635
|
-
*/
|
|
636
|
-
outcomeWeightEnabled: z.boolean().optional(),
|
|
637
|
-
/**
|
|
638
|
-
* Minimum encoding salience score [0, 1] for a zero-feedback asset to be
|
|
639
|
-
* admitted to the high-salience improve lane (#608).
|
|
640
|
-
* Default 0.75. Set to 1.0 to disable the lane entirely.
|
|
641
|
-
*/
|
|
642
|
-
salienceThreshold: z.number().min(0).max(1).optional(),
|
|
643
|
-
/**
|
|
644
|
-
* Per-run additive replay budget (#610). Up to this many top-salience refs are
|
|
645
|
-
* revisited even with no reactive signal and regardless of cooldown. Additive
|
|
646
|
-
* on top of --limit. Default 0 = no replay.
|
|
647
|
-
*/
|
|
648
|
-
replayBudget: z.number().int().min(0).optional(),
|
|
649
|
-
})
|
|
650
|
-
.passthrough();
|
|
651
|
-
// R5 — longitudinal collapse/churn detector (observe-only in v1; deterministic,
|
|
652
|
-
// fail-open, runs only on cycles where consolidate/recombine did work).
|
|
653
|
-
// Default ON; opt out via `improve.collapseDetector.enabled: false`.
|
|
654
|
-
// See docs/design/improve-collapse-churn-detector-design.md.
|
|
655
|
-
const ImproveCollapseDetectorSchema = z
|
|
656
|
-
.object({
|
|
657
|
-
enabled: z.boolean().optional(),
|
|
658
|
-
// Canary set size minted on first run (owner-approved 30–50 range; default 40).
|
|
659
|
-
canaryCount: z.number().int().min(3).max(200).optional(),
|
|
660
|
-
// Top-K cutoff for canary recall/nDCG (default 10).
|
|
661
|
-
k: z.number().int().min(1).max(100).optional(),
|
|
662
|
-
// Trend window in qualifying cycles (default 5).
|
|
663
|
-
windowCycles: z.number().int().min(2).max(50).optional(),
|
|
664
|
-
// Absolute mean-recall drop vs window median that fires collapse (default 0.15).
|
|
665
|
-
recallDropThreshold: z.number().min(0).max(1).optional(),
|
|
666
|
-
// distinct-content-ratio decline over the window that fires collapse (default 0.05).
|
|
667
|
-
entropyDropThreshold: z.number().min(0).max(1).optional(),
|
|
668
|
-
// Accepted-action volume over the window below which churn never fires (default 25).
|
|
669
|
-
churnMinAcceptedActions: z.number().int().min(1).optional(),
|
|
670
|
-
// improve_cycle_metrics retention (default 365 days, owner-approved).
|
|
671
|
-
retentionDays: z.number().int().min(1).optional(),
|
|
672
|
-
})
|
|
673
|
-
.passthrough();
|
|
674
|
-
export const ImproveConfigSchema = z
|
|
675
|
-
.object({
|
|
676
|
-
utilityDecay: ImproveUtilityDecaySchema.optional(),
|
|
677
|
-
eventRetentionDays: nonNegativeNumber.optional(),
|
|
678
|
-
calibration: ImproveCalibrationSchema.optional(),
|
|
679
|
-
exploration: ImproveExplorationSchema.optional(),
|
|
680
|
-
salience: ImproveSalienceSchema.optional(),
|
|
681
|
-
collapseDetector: ImproveCollapseDetectorSchema.optional(),
|
|
682
|
-
})
|
|
683
|
-
.passthrough();
|
|
684
|
-
// ── Index / per-pass ────────────────────────────────────────────────────────
|
|
685
|
-
const GRAPH_EXTRACTION_INCLUDE_TYPES_ALLOWED = [
|
|
686
|
-
"memory",
|
|
687
|
-
"knowledge",
|
|
688
|
-
"skill",
|
|
689
|
-
"command",
|
|
690
|
-
"agent",
|
|
691
|
-
"workflow",
|
|
692
|
-
"lesson",
|
|
693
|
-
"task",
|
|
694
|
-
"wiki",
|
|
695
|
-
"fact",
|
|
696
|
-
];
|
|
697
|
-
const INDEX_PASS_PROVIDER_KEYS = new Set([
|
|
698
|
-
"endpoint",
|
|
699
|
-
"model",
|
|
700
|
-
"provider",
|
|
701
|
-
"apiKey",
|
|
702
|
-
"baseUrl",
|
|
703
|
-
"temperature",
|
|
704
|
-
"maxTokens",
|
|
705
|
-
"capabilities",
|
|
706
|
-
]);
|
|
707
|
-
const INDEX_PASS_KNOWN_KEYS = new Set([
|
|
708
|
-
"llm",
|
|
709
|
-
"graphExtractionBatchSize",
|
|
710
|
-
"graphExtractionIncludeTypes",
|
|
711
|
-
"memoryInferenceBatchSize",
|
|
712
|
-
"lazyGraphExtraction",
|
|
713
|
-
]);
|
|
714
|
-
/**
|
|
715
|
-
* Per-pass `index.<pass>` entry. Uses preprocess + manual validation so we can
|
|
716
|
-
* emit the legacy parser's targeted error messages ("Duplicate LLM provider
|
|
717
|
-
* configuration", "Unknown key `index.<pass>.<key>`", "expected a boolean")
|
|
718
|
-
* instead of Zod's generic `Unrecognized key` / `Expected boolean, received
|
|
719
|
-
* string` strings — keeps `akm` startup errors actionable.
|
|
720
|
-
*/
|
|
721
|
-
export const IndexPassConfigSchema = z.preprocess((raw, ctx) => {
|
|
722
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
723
|
-
return raw; // let z.object below produce the type error
|
|
724
|
-
}
|
|
725
|
-
const obj = raw;
|
|
726
|
-
for (const key of Object.keys(obj)) {
|
|
727
|
-
if (INDEX_PASS_PROVIDER_KEYS.has(key)) {
|
|
183
|
+
// `defaultBundle`, when present, must name a configured bundle.
|
|
184
|
+
if (config.defaultBundle !== undefined) {
|
|
185
|
+
if (config.bundles === undefined) {
|
|
728
186
|
ctx.addIssue({
|
|
729
187
|
code: z.ZodIssueCode.custom,
|
|
730
|
-
|
|
731
|
-
|
|
188
|
+
path: ["defaultBundle"],
|
|
189
|
+
message: "defaultBundle requires a bundles map",
|
|
732
190
|
});
|
|
733
|
-
return raw;
|
|
734
191
|
}
|
|
735
|
-
if (!
|
|
192
|
+
else if (!(config.defaultBundle in config.bundles)) {
|
|
736
193
|
ctx.addIssue({
|
|
737
194
|
code: z.ZodIssueCode.custom,
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
"`memoryInferenceBatchSize`, and `lazyGraphExtraction`.",
|
|
195
|
+
path: ["defaultBundle"],
|
|
196
|
+
message: `defaultBundle "${config.defaultBundle}" does not name a configured bundle`,
|
|
741
197
|
});
|
|
742
|
-
return raw;
|
|
743
198
|
}
|
|
744
199
|
}
|
|
745
|
-
|
|
200
|
+
for (const key of ["llm", "agent", "improve"]) {
|
|
201
|
+
if (config.defaults && key in config.defaults) {
|
|
202
|
+
ctx.addIssue({
|
|
203
|
+
code: z.ZodIssueCode.custom,
|
|
204
|
+
path: ["defaults", key],
|
|
205
|
+
message: `defaults.${key} is retired in 0.9`,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
for (const [name, engine] of Object.entries(config.engines ?? {})) {
|
|
210
|
+
if (engine.kind === "agent" && engine.llmEngine) {
|
|
211
|
+
const fallback = config.engines?.[engine.llmEngine];
|
|
212
|
+
if (!fallback || fallback.kind !== "llm") {
|
|
213
|
+
ctx.addIssue({
|
|
214
|
+
code: z.ZodIssueCode.custom,
|
|
215
|
+
path: ["engines", name, "llmEngine"],
|
|
216
|
+
message: "llmEngine must name an LLM engine",
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const defaultEngine = config.defaults?.engine;
|
|
222
|
+
if (defaultEngine && !config.engines?.[defaultEngine]) {
|
|
746
223
|
ctx.addIssue({
|
|
747
224
|
code: z.ZodIssueCode.custom,
|
|
748
|
-
|
|
225
|
+
path: ["defaults", "engine"],
|
|
226
|
+
message: "engine does not name a configured engine",
|
|
749
227
|
});
|
|
750
|
-
return raw;
|
|
751
228
|
}
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
.object({
|
|
755
|
-
llm: z.boolean().optional(),
|
|
756
|
-
graphExtractionBatchSize: positiveInt.optional(),
|
|
757
|
-
graphExtractionIncludeTypes: z.array(z.enum(GRAPH_EXTRACTION_INCLUDE_TYPES_ALLOWED)).nonempty().optional(),
|
|
758
|
-
memoryInferenceBatchSize: positiveInt.optional(),
|
|
759
|
-
lazyGraphExtraction: z.boolean().optional(),
|
|
760
|
-
})
|
|
761
|
-
.passthrough());
|
|
762
|
-
const MetadataEnhanceSchema = z.object({ enabled: z.boolean().optional() }).passthrough();
|
|
763
|
-
/**
|
|
764
|
-
* RETIRED (meta-review 10-Q3): the staleness-detect pass was deleted; nothing
|
|
765
|
-
* reads this section anymore. The key stays TOLERATED here so configs that
|
|
766
|
-
* still carry `index.stalenessDetection` (written by 0.8.x migrations) do not
|
|
767
|
-
* fail validation — deleting the key would route it into the per-pass
|
|
768
|
-
* catchall, which rejects its `enabled`/`thresholdDays` fields.
|
|
769
|
-
*/
|
|
770
|
-
const StalenessDetectionSchema = z
|
|
771
|
-
.object({
|
|
772
|
-
enabled: z.boolean().optional(),
|
|
773
|
-
thresholdDays: positiveInt.optional(),
|
|
774
|
-
})
|
|
775
|
-
.passthrough();
|
|
776
|
-
/**
|
|
777
|
-
* Index config is a union of reserved feature sections and per-pass entries.
|
|
778
|
-
* Passthrough so per-pass entries (keyed by arbitrary pass names like `graph`,
|
|
779
|
-
* `enrichment`) can live next to the reserved keys.
|
|
780
|
-
*
|
|
781
|
-
* The outer preprocess emits the legacy parser's actionable error messages
|
|
782
|
-
* for the two most common type-shape mistakes:
|
|
783
|
-
* - An array at the `index` block.
|
|
784
|
-
* - A non-object at `index.<passName>`.
|
|
785
|
-
* Inner field validation (graphExtractionIncludeTypes enum, llm boolean,
|
|
786
|
-
* provider-key rejection) is delegated to {@link IndexPassConfigSchema}.
|
|
787
|
-
*/
|
|
788
|
-
export const IndexConfigSchema = z.preprocess((raw, ctx) => {
|
|
789
|
-
if (raw === undefined || raw === null)
|
|
790
|
-
return raw;
|
|
791
|
-
if (Array.isArray(raw)) {
|
|
229
|
+
const defaultLlm = config.defaults?.llmEngine;
|
|
230
|
+
if (defaultLlm && config.engines?.[defaultLlm]?.kind !== "llm") {
|
|
792
231
|
ctx.addIssue({
|
|
793
232
|
code: z.ZodIssueCode.custom,
|
|
794
|
-
|
|
233
|
+
path: ["defaults", "llmEngine"],
|
|
234
|
+
message: "llmEngine must name an LLM engine",
|
|
795
235
|
});
|
|
796
|
-
return raw;
|
|
797
236
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
const
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
}
|
|
237
|
+
const defaultStrategy = config.defaults?.improveStrategy;
|
|
238
|
+
if (defaultStrategy &&
|
|
239
|
+
!BUILTIN_IMPROVE_STRATEGY_NAMES.includes(defaultStrategy) &&
|
|
240
|
+
!config.improve?.strategies?.[defaultStrategy]) {
|
|
241
|
+
ctx.addIssue({
|
|
242
|
+
code: z.ZodIssueCode.custom,
|
|
243
|
+
path: ["defaults", "improveStrategy"],
|
|
244
|
+
message: "improveStrategy does not name a built-in or configured strategy",
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
for (const [strategyName, strategy] of Object.entries(config.improve?.strategies ?? {})) {
|
|
248
|
+
const strategyEngine = strategy.engine;
|
|
249
|
+
if (strategyEngine) {
|
|
250
|
+
const engine = config.engines?.[strategyEngine];
|
|
251
|
+
if (!engine || engine.kind !== "llm") {
|
|
252
|
+
ctx.addIssue({
|
|
253
|
+
code: z.ZodIssueCode.custom,
|
|
254
|
+
path: ["improve", "strategies", strategyName, "engine"],
|
|
255
|
+
message: engine ? "strategy engine must be an LLM engine" : "engine does not name a configured engine",
|
|
256
|
+
});
|
|
818
257
|
}
|
|
819
|
-
|
|
258
|
+
}
|
|
259
|
+
for (const [processName, process] of Object.entries(strategy.processes ?? {})) {
|
|
260
|
+
const processConfig = process;
|
|
261
|
+
const capability = IMPROVE_PROCESS_ENGINE_CAPABILITIES[processName];
|
|
262
|
+
if (processConfig.engine && capability === null) {
|
|
820
263
|
ctx.addIssue({
|
|
821
264
|
code: z.ZodIssueCode.custom,
|
|
822
|
-
|
|
265
|
+
path: ["improve", "strategies", strategyName, "processes", processName, "engine"],
|
|
266
|
+
message: `${processName} does not dispatch an engine`,
|
|
823
267
|
});
|
|
824
|
-
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
const processEngine = processConfig.engine ?? strategyEngine;
|
|
271
|
+
if (processEngine && capability === "llm") {
|
|
272
|
+
const engine = config.engines?.[processEngine];
|
|
273
|
+
if (!engine || engine.kind !== "llm") {
|
|
274
|
+
ctx.addIssue({
|
|
275
|
+
code: z.ZodIssueCode.custom,
|
|
276
|
+
path: ["improve", "strategies", strategyName, "processes", processName, "engine"],
|
|
277
|
+
message: engine ? `${processName} requires an LLM engine` : "engine does not name a configured engine",
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
else if (processConfig.engine && capability === "runner" && !config.engines?.[processConfig.engine]) {
|
|
282
|
+
ctx.addIssue({
|
|
283
|
+
code: z.ZodIssueCode.custom,
|
|
284
|
+
path: ["improve", "strategies", strategyName, "processes", processName, "engine"],
|
|
285
|
+
message: "engine does not name a configured engine",
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
const judgmentEngine = processConfig.judgment?.engine;
|
|
290
|
+
if (judgmentEngine) {
|
|
291
|
+
const engine = config.engines?.[judgmentEngine];
|
|
292
|
+
if (!engine) {
|
|
293
|
+
ctx.addIssue({
|
|
294
|
+
code: z.ZodIssueCode.custom,
|
|
295
|
+
path: ["improve", "strategies", strategyName, "processes", processName, "judgment", "engine"],
|
|
296
|
+
message: "engine does not name a configured engine",
|
|
297
|
+
});
|
|
298
|
+
}
|
|
825
299
|
}
|
|
826
300
|
}
|
|
827
301
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
stalenessDetection: StalenessDetectionSchema.optional(),
|
|
833
|
-
})
|
|
834
|
-
.catchall(IndexPassConfigSchema));
|
|
835
|
-
// ── Setup-derived recommendations ──────────────────────────────────────────
|
|
836
|
-
/**
|
|
837
|
-
* Cron-style schedule hints derived by `akm setup --reset-recommended`.
|
|
838
|
-
*
|
|
839
|
-
* These record the *recommended* cadence for the improve and index background
|
|
840
|
-
* tasks. They are advisory metadata persisted into config so the value
|
|
841
|
-
* survives a re-run; actual task scheduling lives in the tasks subsystem.
|
|
842
|
-
*/
|
|
843
|
-
export const SetupTaskSchedulesSchema = z
|
|
844
|
-
.object({
|
|
845
|
-
improve: z.string().min(1).optional(),
|
|
846
|
-
index: z.string().min(1).optional(),
|
|
847
|
-
})
|
|
848
|
-
.passthrough();
|
|
849
|
-
export const SetupConfigSchema = z
|
|
850
|
-
.object({
|
|
851
|
-
taskSchedules: SetupTaskSchedulesSchema.optional(),
|
|
852
|
-
})
|
|
853
|
-
.passthrough();
|
|
854
|
-
// ── Top-level AkmConfig ────────────────────────────────────────────────────
|
|
855
|
-
/**
|
|
856
|
-
* Base object schema used both as the top-level shape and as the source of
|
|
857
|
-
* truth for {@link listTopLevelConfigKeys}. {@link AkmConfigSchema} wraps this
|
|
858
|
-
* with cross-field refinements (`.superRefine()`).
|
|
859
|
-
*
|
|
860
|
-
* All fields validate loudly — typos and shape errors throw at load time. The
|
|
861
|
-
* legacy parser's warn-and-drop tolerance was a frequent source of silent
|
|
862
|
-
* configuration loss; the migration module ({@link migrateConfigShape}) handles
|
|
863
|
-
* one-time 0.7→0.8 input transforms before the schema sees the value.
|
|
864
|
-
*/
|
|
865
|
-
export const AkmConfigShape = {
|
|
866
|
-
configVersion: z.union([z.string().min(1), z.number()]).optional(),
|
|
867
|
-
profiles: ProfilesSchema.optional(),
|
|
868
|
-
defaults: DefaultsSchema.optional(),
|
|
869
|
-
// Global model-alias tiers: alias → platform → exact model string, with a
|
|
870
|
-
// reserved `"*"` platform key as fallback. Lets workflows/callers name a
|
|
871
|
-
// semantic tier ("fast", "deep") that resolves per-harness at dispatch
|
|
872
|
-
// time. Values are literal model strings, never other aliases (one
|
|
873
|
-
// resolution level). Platform keys match the platform string a command
|
|
874
|
-
// builder resolves against ("claude", "opencode", "opencode-sdk", or a
|
|
875
|
-
// custom profile's name for the default builder) — unknown keys are inert.
|
|
876
|
-
// Precedence: profile modelAliases > this table > built-in aliases.
|
|
877
|
-
modelAliases: z.record(z.string().min(1), z.record(z.string().min(1), z.string().min(1))).optional(),
|
|
878
|
-
stashDir: nonEmptyString.optional(),
|
|
879
|
-
semanticSearchMode: z.enum(["off", "auto"]).default("auto"),
|
|
880
|
-
embedding: EmbeddingConnectionConfigSchema.optional(),
|
|
881
|
-
index: IndexConfigSchema.optional(),
|
|
882
|
-
// The `installed[]` shape is OWNED by the registry (`InstalledStashEntry`):
|
|
883
|
-
// its `source` is the 4-value `InstallKind` produced by the registry ref
|
|
884
|
-
// parser, and installed entries never carry the extra passthrough keys. The
|
|
885
|
-
// schema still validates entries at runtime, but its OUTPUT type is pinned to
|
|
886
|
-
// the domain type so config consumers get the registry `InstalledStashEntry`
|
|
887
|
-
// (not a looser schema-local mirror) — the single-source-of-truth boundary.
|
|
888
|
-
installed: z.array(InstalledStashEntrySchema).optional(),
|
|
889
|
-
registries: z.array(RegistryConfigEntrySchema).optional(),
|
|
890
|
-
sources: z.array(SourceConfigEntrySchema).optional(),
|
|
891
|
-
output: OutputConfigSchema.optional(),
|
|
892
|
-
writable: z.boolean().optional(),
|
|
893
|
-
defaultWriteTarget: nonEmptyString.optional(),
|
|
894
|
-
search: SearchConfigSchema.optional(),
|
|
895
|
-
feedback: FeedbackConfigSchema.optional(),
|
|
896
|
-
archiveRetentionDays: nonNegativeNumber.optional(),
|
|
897
|
-
improve: ImproveConfigSchema.optional(),
|
|
898
|
-
setup: SetupConfigSchema.optional(),
|
|
899
|
-
};
|
|
900
|
-
export const AkmConfigBaseSchema = z.object(AkmConfigShape).passthrough();
|
|
901
|
-
export const AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) => {
|
|
902
|
-
// #464.a: defaultWriteTarget must name a configured source when sources
|
|
903
|
-
// are present. With no sources configured, error out instead of silently
|
|
904
|
-
// accepting (no implicit "first writable" fallback — see locked decision 3).
|
|
302
|
+
// #464.a: defaultWriteTarget must name a configured source. 0.9.0 (spec
|
|
303
|
+
// §10.1): sources are `bundles` keys, so it must name a bundle. With no
|
|
304
|
+
// bundles configured, error out instead of silently accepting (no implicit
|
|
305
|
+
// "first writable" fallback — see locked decision 3).
|
|
905
306
|
if (config.defaultWriteTarget !== undefined) {
|
|
906
|
-
const knownNames = (config.
|
|
907
|
-
.map((s) => s.name)
|
|
908
|
-
.filter((n) => typeof n === "string" && n.length > 0);
|
|
307
|
+
const knownNames = Object.keys(config.bundles ?? {});
|
|
909
308
|
if (knownNames.length === 0) {
|
|
910
309
|
ctx.addIssue({
|
|
911
310
|
code: z.ZodIssueCode.custom,
|
|
912
311
|
path: ["defaultWriteTarget"],
|
|
913
|
-
message: `defaultWriteTarget "${config.defaultWriteTarget}" cannot be resolved: no
|
|
914
|
-
"Add at least one entry to `
|
|
312
|
+
message: `defaultWriteTarget "${config.defaultWriteTarget}" cannot be resolved: no bundles configured. ` +
|
|
313
|
+
"Add at least one entry to `bundles` first.",
|
|
915
314
|
});
|
|
916
315
|
}
|
|
917
316
|
else if (!knownNames.includes(config.defaultWriteTarget)) {
|
|
918
317
|
ctx.addIssue({
|
|
919
318
|
code: z.ZodIssueCode.custom,
|
|
920
319
|
path: ["defaultWriteTarget"],
|
|
921
|
-
message: `defaultWriteTarget "${config.defaultWriteTarget}" does not match any configured
|
|
320
|
+
message: `defaultWriteTarget "${config.defaultWriteTarget}" does not match any configured bundle: ${knownNames.map((n) => `"${n}"`).join(", ")}.`,
|
|
922
321
|
});
|
|
923
322
|
}
|
|
924
323
|
}
|