akm-cli 0.9.17-alpha.2 → 0.9.17-alpha.4
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 +756 -0
- package/dist/akm +94 -196
- package/dist/cli/shared.js +6 -2
- package/dist/cli.js +22 -9
- package/dist/commands/agent/agent-dispatch.js +1 -1
- package/dist/commands/command/command-execution.js +24 -62
- package/dist/commands/feedback-cli.js +0 -1
- package/dist/commands/health/accept-rate.js +2 -2
- package/dist/commands/health/checks.js +30 -75
- package/dist/commands/health/config-skew.js +38 -0
- package/dist/commands/health/egress.js +54 -0
- package/dist/commands/health/html-report.js +0 -38
- package/dist/commands/health/improve-metrics.js +123 -562
- package/dist/commands/health/plugin-staleness.js +53 -3
- package/dist/commands/health/renderers.js +12 -4
- package/dist/commands/health/report-view-model.js +11 -106
- package/dist/commands/health/types-improve.js +4 -19
- package/dist/commands/health/windows.js +64 -73
- package/dist/commands/health.js +122 -143
- package/dist/commands/improve/consolidate/chunking.js +25 -100
- package/dist/commands/improve/consolidate/sanitize.js +54 -149
- package/dist/commands/improve/consolidate.js +538 -1075
- package/dist/commands/improve/content-hash.js +16 -24
- package/dist/commands/improve/distill/content-repair.js +18 -100
- package/dist/commands/improve/distill-guards.js +20 -81
- package/dist/commands/improve/distill-promotion-policy.js +23 -243
- package/dist/commands/improve/distill.js +608 -1075
- package/dist/commands/improve/eligibility.js +126 -400
- package/dist/commands/improve/execution.js +3 -5
- package/dist/commands/improve/extract.js +487 -1046
- package/dist/commands/improve/feedback-valence.js +0 -25
- package/dist/commands/improve/improve-cli.js +29 -166
- package/dist/commands/improve/improve-result-file.js +10 -66
- package/dist/commands/improve/improve-strategies.js +12 -7
- package/dist/commands/improve/improve-usage-report.js +18 -64
- package/dist/commands/improve/improve.js +443 -1063
- package/dist/commands/improve/ledger.js +114 -0
- package/dist/commands/improve/locks.js +2 -8
- package/dist/commands/improve/loop-stages.js +459 -1172
- package/dist/commands/improve/memory/derived-ref.js +12 -77
- package/dist/commands/improve/memory/memory-belief.js +14 -118
- package/dist/commands/improve/memory/memory-improve.js +4 -3
- package/dist/commands/improve/outcome-loop.js +28 -156
- package/dist/commands/improve/planner.js +5 -10
- package/dist/commands/improve/preparation.js +851 -2339
- package/dist/commands/improve/proactive-maintenance.js +34 -101
- package/dist/commands/improve/reflect-noise.js +104 -280
- package/dist/commands/improve/reflect.js +621 -1367
- package/dist/commands/improve/salience.js +46 -232
- package/dist/commands/improve/session-asset.js +19 -100
- package/dist/commands/improve/stage.js +323 -0
- package/dist/commands/proposal/drain.js +251 -644
- package/dist/commands/proposal/proposal-cli.js +3 -18
- package/dist/commands/proposal/proposal-types.js +20 -41
- package/dist/commands/proposal/proposal.js +1 -2
- package/dist/commands/proposal/propose.js +134 -160
- package/dist/commands/proposal/repository.js +502 -1487
- package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
- package/dist/commands/proposal/validators/proposal-validators.js +1 -1
- package/dist/commands/proposal/validators/proposals.js +13 -89
- package/dist/commands/read/curate.js +63 -413
- package/dist/commands/read/search-cli.js +16 -33
- package/dist/commands/read/search.js +17 -23
- package/dist/commands/read/show.js +2 -13
- package/dist/commands/sources/bundle-cli.js +25 -2
- package/dist/commands/sources/bundle-config-ops.js +7 -0
- package/dist/commands/sources/dangerous-env-audit.js +1 -2
- package/dist/commands/sources/info.js +2 -11
- package/dist/commands/sources/installed-stashes.js +197 -746
- package/dist/commands/sources/schema-repair.js +98 -129
- package/dist/commands/sources/source-add.js +62 -12
- package/dist/commands/sources/stash-cli.js +1 -1
- package/dist/commands/tasks/explain.js +10 -13
- package/dist/commands/tasks/tasks-cli.js +9 -8
- package/dist/commands/tasks/tasks.js +326 -930
- package/dist/commands/tasks/validate.js +42 -21
- package/dist/commands/workflow/plan.js +22 -29
- package/dist/commands/workflow-cli.js +4 -4
- package/dist/core/adapter/adapters/akm-adapter.js +0 -1
- package/dist/core/adapter/adapters/akm-lint.js +2 -3
- package/dist/core/adapter/adapters/akm-metadata.js +11 -12
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
- package/dist/core/adapter/execution-source.js +17 -29
- package/dist/core/asset/resolve-ref.js +1 -1
- package/dist/core/bundle-id.js +42 -5
- package/dist/core/bundle-rename.js +291 -0
- package/dist/core/config/config-io.js +1 -2
- package/dist/core/config/config-schema.js +1 -33
- package/dist/core/config/config-walker.js +1 -1
- package/dist/core/config/config.js +163 -68
- package/dist/core/config/legacy-source-shape-shim.js +38 -9
- package/dist/core/config/schema/embedding.js +20 -5
- package/dist/core/config/schema/engines.js +5 -0
- package/dist/core/config/schema/execution.js +1 -1
- package/dist/core/config/schema/experimental.js +1 -1
- package/dist/core/config/schema/improve-processes.js +21 -95
- package/dist/core/config/schema/improve.js +4 -42
- package/dist/core/config/schema/scheduler.js +12 -12
- package/dist/core/config/schema/search.js +6 -22
- package/dist/core/env-secret-ref.js +0 -1
- package/dist/core/errors.js +8 -9
- package/dist/core/file-lock.js +76 -173
- package/dist/core/logs-db.js +2 -2
- package/dist/core/paths.js +0 -27
- package/dist/core/redaction.js +109 -2
- package/dist/core/run-lock.js +2 -5
- package/dist/core/spawn-env.js +1 -1
- package/dist/core/state/migrations.js +108 -61
- package/dist/core/state-db-scope.js +2 -4
- package/dist/core/state-db.js +126 -692
- package/dist/core/type-presentation.js +1 -9
- package/dist/core/write-source.js +293 -1012
- package/dist/execution/input-contract.js +1 -1
- package/dist/execution/resolved-request.js +135 -689
- package/dist/execution/source.js +63 -257
- package/dist/execution/target-ref.js +1 -1
- package/dist/indexer/bundle-identity-guard.js +2 -2
- package/dist/indexer/db/graph-db.js +106 -46
- package/dist/indexer/ensure-index.js +44 -85
- package/dist/indexer/graph/graph-extraction.js +340 -562
- package/dist/indexer/graph/graph-related.js +130 -0
- package/dist/indexer/index-rebuild-lock.js +3 -11
- package/dist/indexer/index-writer-lock.js +8 -17
- package/dist/indexer/index-written-assets.js +139 -151
- package/dist/indexer/indexer.js +524 -846
- package/dist/indexer/materialize-embeddings.js +60 -397
- package/dist/indexer/passes/memory-inference.js +81 -90
- package/dist/indexer/passes/metadata.js +132 -200
- package/dist/indexer/read-preflight.js +0 -7
- package/dist/indexer/scan/doc-to-entry.js +1 -3
- package/dist/indexer/scan/drain-dir.js +1 -1
- package/dist/indexer/search/db-search.js +181 -590
- package/dist/indexer/search/fts-query.js +30 -41
- package/dist/indexer/search/ranking.js +28 -154
- package/dist/indexer/search/search-attribution.js +12 -32
- package/dist/indexer/search/search-fields.js +11 -15
- package/dist/indexer/search/search-hit-enrichers.js +54 -85
- package/dist/indexer/search/search-source.js +1 -4
- package/dist/indexer/usage/usage-events.js +2 -7
- package/dist/integrations/agent/engine-fallback.js +23 -40
- package/dist/integrations/agent/engine-resolution.js +93 -183
- package/dist/integrations/agent/execution.js +507 -0
- package/dist/integrations/agent/model-map.js +28 -156
- package/dist/integrations/agent/request-lowering.js +66 -141
- package/dist/integrations/agent/runner-dispatch.js +143 -321
- package/dist/integrations/agent/runner.js +54 -14
- package/dist/integrations/lockfile.js +53 -101
- package/dist/llm/embedders/deterministic.js +2 -3
- package/dist/llm/embedders/profile.js +71 -0
- package/dist/llm/embedders/remote.js +10 -15
- package/dist/llm/graph-extract.js +3 -12
- package/dist/llm/index-passes.js +3 -5
- package/dist/llm/memory-infer.js +1 -2
- package/dist/llm/metadata-enhance.js +1 -2
- package/dist/llm/structured-call.js +5 -24
- package/dist/output/generic-render.js +23 -11
- package/dist/output/html-render.js +13 -10
- package/dist/output/render-registry.js +3 -32
- package/dist/output/shapes/helpers.js +2 -34
- package/dist/output/shapes/passthrough.js +1 -9
- package/dist/{indexer/search/ranking-types.js → output/text/bundle-rename.js} +4 -1
- package/dist/output/text/command-format.js +60 -23
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/migrate.js +5 -14
- package/dist/output/text/proposal-format.js +1 -2
- package/dist/output/text/workflow-format.js +0 -32
- package/dist/output/text.js +2 -0
- package/dist/registry/factory.js +4 -19
- package/dist/registry/network.js +66 -220
- package/dist/registry/providers/index.js +0 -2
- package/dist/registry/providers/skills-sh.js +3 -14
- package/dist/registry/providers/static-index.js +24 -26
- package/dist/registry/resolve.js +55 -131
- package/dist/scripts/akm-migrate-node.js +43937 -93313
- package/dist/scripts/akm-migrate.js +43697 -93071
- package/dist/setup/registry-stash-loader.js +4 -13
- package/dist/setup/semantic-assets.js +3 -44
- package/dist/setup/setup.js +1 -1
- package/dist/setup/steps/tasks.js +25 -15
- package/dist/sources/provider-factory.js +17 -18
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +7 -1
- package/dist/sources/providers/git-provider.js +0 -3
- package/dist/sources/providers/git-stash.js +0 -17
- package/dist/sources/providers/npm.js +2 -4
- package/dist/sources/providers/provider-utils.js +5 -10
- package/dist/sources/providers/website.js +0 -2
- package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
- package/dist/sources/website-url.js +2 -2
- package/dist/storage/database.js +9 -35
- package/dist/storage/repositories/improve-ledger-repository.js +168 -0
- package/dist/storage/repositories/index-connection.js +34 -70
- package/dist/storage/repositories/index-entries-repository.js +69 -111
- package/dist/storage/repositories/index-entry-mapper.js +1 -2
- package/dist/storage/repositories/index-entry-schema.js +83 -269
- package/dist/storage/repositories/index-fts-repository.js +86 -256
- package/dist/storage/repositories/index-llm-cache-repository.js +17 -0
- package/dist/storage/repositories/index-meta-repository.js +6 -4
- package/dist/storage/repositories/index-schema.js +192 -220
- package/dist/storage/repositories/index-utility-repository.js +8 -29
- package/dist/storage/repositories/index-vec-repository.js +133 -414
- package/dist/storage/repositories/outcome-repository.js +2 -1
- package/dist/storage/repositories/proposals-repository.js +35 -0
- package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
- package/dist/storage/repositories/task-history-repository.js +26 -4
- package/dist/storage/repositories/workflow-runs-repository.js +53 -244
- package/dist/storage/sqlite-migrations.js +136 -0
- package/dist/storage/sqlite-pragmas.js +11 -9
- package/dist/storage/sqlite-transaction.js +170 -0
- package/dist/storage/state-db-integrity.js +34 -27
- package/dist/tasks/activation-config.js +134 -62
- package/dist/tasks/backends/cron.js +129 -277
- package/dist/tasks/backends/exec-utils.js +2 -5
- package/dist/tasks/backends/launchd.js +125 -745
- package/dist/tasks/backends/schtasks.js +101 -620
- package/dist/tasks/prepare/prepare-support.js +5 -15
- package/dist/tasks/prepare/prepare.js +0 -2
- package/dist/tasks/resolve-akm-bin.js +20 -79
- package/dist/tasks/run/attempt-lifecycle.js +0 -1
- package/dist/tasks/scheduler-binding.js +18 -238
- package/dist/tasks/scheduler-invocation.js +52 -52
- package/dist/tasks/scheduler-lock.js +53 -0
- package/dist/tasks/scheduler-sync.js +363 -679
- package/dist/tasks/source/parse-task-source.js +160 -10
- package/dist/tasks/source/task-source-v3-frozen.js +3 -4
- package/dist/tasks/source/task-to-v4.js +2 -2
- package/dist/workflows/authoring/authoring.js +3 -12
- package/dist/workflows/compile.js +211 -0
- package/dist/workflows/concurrency-policy.js +13 -74
- package/dist/workflows/exec/child-invocation.js +3 -17
- package/dist/workflows/exec/child-workflow.js +32 -141
- package/dist/workflows/exec/dispatch-redaction.js +13 -53
- package/dist/workflows/exec/environment.js +98 -0
- package/dist/workflows/exec/exec-unit.js +33 -140
- package/dist/workflows/exec/frozen-judge.js +7 -59
- package/dist/workflows/exec/native-executor.js +82 -341
- package/dist/workflows/exec/param-secrets.js +29 -47
- package/dist/workflows/exec/run-workflow.js +154 -387
- package/dist/workflows/exec/scheduler.js +9 -36
- package/dist/workflows/exec/step-work.js +127 -430
- package/dist/workflows/exec/unit-dispatch.js +11 -63
- package/dist/workflows/exec/unit-writer.js +8 -52
- package/dist/workflows/exec/worktree.js +39 -273
- package/dist/workflows/freeze/child-output-references.js +4 -15
- package/dist/workflows/freeze/environment.js +99 -92
- package/dist/workflows/freeze/freeze.js +172 -0
- package/dist/workflows/freeze/step-values.js +19 -21
- package/dist/workflows/freeze/targets/child-workflow.js +23 -92
- package/dist/workflows/freeze/targets/command.js +10 -33
- package/dist/workflows/freeze/targets/script.js +5 -12
- package/dist/workflows/freeze/targets/shell.js +3 -6
- package/dist/workflows/freeze/targets/task.js +25 -80
- package/dist/workflows/freeze/task-bindings.js +20 -67
- package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
- package/dist/workflows/ir/params.js +6 -51
- package/dist/workflows/ir/plan-hash.js +2 -34
- package/dist/workflows/parser.js +140 -43
- package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
- package/dist/workflows/renderer.js +36 -69
- package/dist/workflows/resource-limits.js +12 -120
- package/dist/workflows/runtime/agent-identity.js +8 -40
- package/dist/workflows/runtime/run-outputs.js +3 -6
- package/dist/workflows/runtime/run-plan.js +316 -0
- package/dist/workflows/runtime/runs.js +48 -200
- package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
- package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
- package/dist/workflows/validate-summary.js +2 -7
- package/docs/integration/bundling-akm.md +49 -42
- package/docs/migration/README.md +1 -0
- package/docs/migration/release-notes/0.9.17.md +41 -0
- package/docs/migration/v0.9.1-to-v0.9.2.md +19 -7
- package/docs/reference/cli.md +182 -125
- package/docs/reference/configuration.md +49 -56
- package/docs/reference/data-and-telemetry.md +19 -20
- package/docs/reference/tasks.md +86 -38
- package/docs/reference/workflow-schema.md +14 -18
- package/docs/reference/workflows.md +6 -9
- package/package.json +1 -1
- package/schemas/akm-config.json +87 -406
- package/dist/commands/health/advisories.js +0 -150
- package/dist/commands/health/metrics.js +0 -329
- package/dist/commands/health/surfaces.js +0 -102
- package/dist/commands/improve/anti-collapse.js +0 -83
- package/dist/commands/improve/collapse-detector.js +0 -432
- package/dist/commands/improve/consolidate/eligibility.js +0 -48
- package/dist/commands/improve/consolidate/merge.js +0 -146
- package/dist/commands/improve/distill/promote-memory.js +0 -329
- package/dist/commands/improve/distill/quality-gate.js +0 -500
- package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
- package/dist/commands/improve/proposal-envelope.js +0 -31
- package/dist/commands/improve/run-context.js +0 -123
- package/dist/commands/improve/shared.js +0 -21
- package/dist/commands/improve/source-identity.js +0 -28
- package/dist/commands/improve/triage.js +0 -96
- package/dist/commands/proposal/drain-policies.js +0 -151
- package/dist/commands/sources/update-transaction.js +0 -220
- package/dist/core/action-contributors.js +0 -28
- package/dist/core/config/config-version-shim.js +0 -101
- package/dist/core/config/retired-experimental-keys-shim.js +0 -62
- package/dist/core/fs-txn.js +0 -405
- package/dist/core/lexical-score.js +0 -25
- package/dist/core/maintenance-barrier.js +0 -167
- package/dist/execution/executable-identity.js +0 -105
- package/dist/execution/guarded-source.js +0 -427
- package/dist/indexer/graph/graph-boost.js +0 -427
- package/dist/indexer/graph/graph-dedup.js +0 -95
- package/dist/indexer/search/name-match.js +0 -35
- package/dist/indexer/search/ranking-contributors.js +0 -515
- package/dist/indexer/walk/project-context.js +0 -192
- package/dist/integrations/agent/execution-cascade.js +0 -566
- package/dist/integrations/agent/execution-definitions.js +0 -202
- package/dist/integrations/agent/execution-lowering.js +0 -841
- package/dist/integrations/agent/execution-preparation.js +0 -98
- package/dist/integrations/agent/inline-execution.js +0 -74
- package/dist/registry/create-provider-registry.js +0 -29
- package/dist/registry/pinned-request-helper.js +0 -247
- package/dist/registry/pinned-transport.js +0 -717
- package/dist/sources/providers/index.js +0 -14
- package/dist/storage/engines/sqlite-migrations.js +0 -271
- package/dist/storage/repositories/canaries-repository.js +0 -107
- package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
- package/dist/storage/repositories/registry-cache.js +0 -113
- package/dist/tasks/scheduler-sync-preview.js +0 -52
- package/dist/workflows/freeze/resolve-steps.js +0 -86
- package/dist/workflows/freeze/source-freeze.js +0 -64
- package/dist/workflows/ir/compile.js +0 -321
- package/dist/workflows/ir/environment-v4.js +0 -330
- package/dist/workflows/ir/freeze-v4.js +0 -153
- package/dist/workflows/ir/schema-v4.js +0 -745
- package/dist/workflows/ir/schema.js +0 -354
- package/dist/workflows/program/schema.js +0 -78
- package/dist/workflows/runtime/checkin.js +0 -57
- package/dist/workflows/runtime/plan-classifier.js +0 -196
- package/dist/workflows/runtime/unit-checkin.js +0 -45
- package/dist/workflows/runtime/unit-phases.js +0 -20
- package/dist/workflows/schema.js +0 -4
- package/dist/workflows/source-ir/compile.js +0 -200
- package/dist/workflows/source-ir/program.js +0 -50
- package/dist/workflows/source-ir/result.js +0 -26
- package/dist/workflows/source-ir/schema.js +0 -786
- package/dist/workflows/source-ir/triggers.js +0 -79
- package/dist/workflows/source-ir/uses.js +0 -40
- package/dist/workflows/validator.js +0 -60
|
@@ -5,18 +5,18 @@ import fs from "node:fs";
|
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { isDeepStrictEqual } from "node:util";
|
|
8
|
-
import { isBundleSlug } from "../asset/asset-ref.js";
|
|
9
|
-
import {
|
|
8
|
+
import { isBundleSlug, parseBundleRef } from "../asset/asset-ref.js";
|
|
9
|
+
import { deriveBundleId } from "../bundle-id.js";
|
|
10
|
+
import { isRecord, resolveStashDir } from "../common.js";
|
|
10
11
|
import { ConfigError } from "../errors.js";
|
|
11
12
|
import { liftLegacyEngineExtraParams } from "../extra-params.js";
|
|
12
13
|
import { formatRegistryLabel, hasRegistryUrlCredentials } from "../registry-url.js";
|
|
13
14
|
import { acquireConfigLock, backupExistingConfig, parseConfigText, readConfigText, withConfigLock, writeConfigAtomic, } from "./config-io.js";
|
|
14
|
-
import { AkmConfigSchema, CURRENT_CONFIG_VERSION
|
|
15
|
-
import { bundleComponentConfig, bundleContentRoot, bundleContentRoots, bundlesToSourceEntries } from "./config-sources.js";
|
|
16
|
-
import {
|
|
15
|
+
import { AkmConfigSchema, CURRENT_CONFIG_VERSION } from "./config-schema.js";
|
|
16
|
+
import { bundleComponentConfig, bundleContentRoot, bundleContentRoots, bundleSourceId, bundlesToSourceEntries, filesystemBundleSourceId, isBundleEnabled, } from "./config-sources.js";
|
|
17
|
+
import { resolveSchemaAt } from "./config-walker.js";
|
|
17
18
|
import { deepMergeConfig, isPlainObject } from "./deep-merge.js";
|
|
18
19
|
import { migrateLegacySourceShape } from "./legacy-source-shape-shim.js";
|
|
19
|
-
import { stripRetiredExperimentalKeys } from "./retired-experimental-keys-shim.js";
|
|
20
20
|
import { isApiKeyReference, SECRET_STORE_REFERENCE_PATTERN } from "./schema/primitives.js";
|
|
21
21
|
export { stripJsonComments } from "./config-io.js";
|
|
22
22
|
import { getConfigPath } from "../paths.js";
|
|
@@ -125,40 +125,38 @@ export function loadUserConfig() {
|
|
|
125
125
|
};
|
|
126
126
|
return finalConfig;
|
|
127
127
|
}
|
|
128
|
-
/**
|
|
129
|
-
* Acquire the existing config-write sentinel and read a fresh validated
|
|
130
|
-
* generation while keeping the sentinel held. Source update uses this to
|
|
131
|
-
* fence an audited bundle descriptor through publication: a cooperating
|
|
132
|
-
* config writer can commit either before this snapshot or after the update,
|
|
133
|
-
* never between the final generation check and index commit.
|
|
134
|
-
*/
|
|
135
|
-
export function acquireConfigReadFence() {
|
|
136
|
-
const release = acquireConfigLock();
|
|
137
|
-
try {
|
|
138
|
-
cachedConfig = undefined;
|
|
139
|
-
return { config: loadUserConfig(), release };
|
|
140
|
-
}
|
|
141
|
-
catch (error) {
|
|
142
|
-
release();
|
|
143
|
-
throw error;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
128
|
/**
|
|
147
129
|
* Run the per-file config pipeline every raw config object goes through
|
|
148
130
|
* before it is either validated (the local/top-level file) or merged in as
|
|
149
|
-
* an `extends` base: JSONC parse already done by the caller, then
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
131
|
+
* an `extends` base: JSONC parse already done by the caller, then the
|
|
132
|
+
* `configVersion` read ({@link readConfigVersion}), then the legacy
|
|
133
|
+
* `stashDir`/`sources[]`/`installed[]` shim, then the legacy `extraParams`
|
|
134
|
+
* lift (#852). Unknown keys are not an error: the schema drops them in
|
|
135
|
+
* memory. Shared by {@link parseAndValidateConfigText} (the local file) and
|
|
136
|
+
* {@link resolveExtendsChain} (each base in the chain) so a fleet-shared base
|
|
137
|
+
* config can carry its own `configVersion` / legacy shape independently of
|
|
138
|
+
* the file that extends it.
|
|
156
139
|
*/
|
|
157
140
|
function runConfigFilePipeline(text, sourcePath) {
|
|
158
|
-
const versioned =
|
|
141
|
+
const versioned = readConfigVersion(parseConfigText(text, sourcePath), sourcePath);
|
|
159
142
|
const parsedRaw = migrateLegacySourceShape(versioned, sourcePath);
|
|
160
|
-
|
|
161
|
-
|
|
143
|
+
return liftExtraParamsOrThrow(parsedRaw, sourcePath);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* `configVersion` is read, never gated on. `"0.9.0"` is the only value akm
|
|
147
|
+
* has ever shipped, and a document without the field is that same document.
|
|
148
|
+
* Any other value is named once and the file is read as the current shape
|
|
149
|
+
* anyway; every ordinary config write and `akm migrate apply`'s `configFile`
|
|
150
|
+
* step then persist `"0.9.0"`.
|
|
151
|
+
*/
|
|
152
|
+
function readConfigVersion(raw, sourcePath) {
|
|
153
|
+
const version = raw.configVersion;
|
|
154
|
+
if (version === CURRENT_CONFIG_VERSION)
|
|
155
|
+
return raw;
|
|
156
|
+
if (version !== undefined) {
|
|
157
|
+
warnOnce(`config:config-version${sourcePath ? `:${sourcePath}` : ""}`, `${sourcePath ?? "config.json"} declares configVersion ${JSON.stringify(version)}; this release reads it as ${CURRENT_CONFIG_VERSION}.`);
|
|
158
|
+
}
|
|
159
|
+
return { ...raw, configVersion: CURRENT_CONFIG_VERSION };
|
|
162
160
|
}
|
|
163
161
|
/**
|
|
164
162
|
* #852 (following #815): a config still using legacy `extraParams` keys —
|
|
@@ -195,49 +193,62 @@ function liftExtraParamsOrThrow(parsedRaw, sourcePath) {
|
|
|
195
193
|
* keeps around, instead of only getting the final merged `AkmConfig` back.
|
|
196
194
|
*/
|
|
197
195
|
function buildEffectiveConfig(liftedLocalRaw, sourcePath) {
|
|
198
|
-
warnUnknownTopLevelConfigKeys(liftedLocalRaw, sourcePath);
|
|
199
196
|
const withExtends = resolveExtendsChain(liftedLocalRaw, sourcePath);
|
|
200
197
|
const where = sourcePath ? ` at ${sourcePath}` : "";
|
|
198
|
+
warnUnknownConfigKeys(liftedLocalRaw, sourcePath);
|
|
201
199
|
const parsed = AkmConfigSchema.safeParse(withExtends);
|
|
202
200
|
if (!parsed.success) {
|
|
203
201
|
const lines = parsed.error.issues.map((i) => ` - ${i.path.join(".") || "(root)"}: ${i.message}`).join("\n");
|
|
204
|
-
|
|
205
|
-
throw new ConfigError(`Invalid config${where}:\n${lines}`, "INVALID_CONFIG_FILE", needsSchedulerMigration
|
|
206
|
-
? "Run `akm migrate apply` to bind existing scheduler grants to their source."
|
|
207
|
-
: undefined);
|
|
202
|
+
throw new ConfigError(`Invalid config${where}:\n${lines}`, "INVALID_CONFIG_FILE");
|
|
208
203
|
}
|
|
209
204
|
const merged = deepMergeConfig(DEFAULT_CONFIG, parsed.data);
|
|
210
205
|
const finalResult = AkmConfigSchema.safeParse(merged);
|
|
211
206
|
if (!finalResult.success) {
|
|
212
207
|
const lines = finalResult.error.issues.map((i) => ` - ${i.path.join(".") || "(root)"}: ${i.message}`).join("\n");
|
|
213
|
-
|
|
214
|
-
throw new ConfigError(`Invalid merged config${sourcePath ? ` at ${sourcePath}` : ""}:\n${lines}`, "INVALID_CONFIG_FILE", needsSchedulerMigration
|
|
215
|
-
? "Run `akm migrate apply` to bind existing scheduler grants to their source."
|
|
216
|
-
: undefined);
|
|
208
|
+
throw new ConfigError(`Invalid merged config${sourcePath ? ` at ${sourcePath}` : ""}:\n${lines}`, "INVALID_CONFIG_FILE");
|
|
217
209
|
}
|
|
218
210
|
assertUniquePhysicalBundleRoots(finalResult.data, sourcePath);
|
|
219
211
|
return finalResult.data;
|
|
220
212
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
function warnUnknownTopLevelConfigKeys(raw, sourcePath) {
|
|
235
|
-
const known = new Set(listTopLevelConfigKeys());
|
|
236
|
-
for (const key of Object.keys(raw).sort()) {
|
|
237
|
-
if (known.has(key) || RETIRED_TOP_LEVEL_CONFIG_KEYS.has(key))
|
|
213
|
+
/**
|
|
214
|
+
* Every dotted key in `raw` the schema does not know, at any depth (arrays
|
|
215
|
+
* are not descended). Unknown keys are never an error: they are a typo, or a
|
|
216
|
+
* key another release used. Reads keep them (they round-trip through
|
|
217
|
+
* ordinary writes, so a newer release's settings survive a downgrade);
|
|
218
|
+
* `akm migrate apply` drops them.
|
|
219
|
+
*/
|
|
220
|
+
export function unknownConfigKeyPaths(root, node = root, prefix = []) {
|
|
221
|
+
const found = [];
|
|
222
|
+
for (const key of Object.keys(node).sort()) {
|
|
223
|
+
const keyPath = [...prefix, key];
|
|
224
|
+
if (resolveSchemaAt(keyPath, root) === undefined) {
|
|
225
|
+
found.push(keyPath);
|
|
238
226
|
continue;
|
|
239
|
-
|
|
227
|
+
}
|
|
228
|
+
const value = node[key];
|
|
229
|
+
if (isPlainConfigObject(value))
|
|
230
|
+
found.push(...unknownConfigKeyPaths(root, value, keyPath));
|
|
231
|
+
}
|
|
232
|
+
return found;
|
|
233
|
+
}
|
|
234
|
+
function warnUnknownConfigKeys(raw, sourcePath) {
|
|
235
|
+
for (const keyPath of unknownConfigKeyPaths(raw)) {
|
|
236
|
+
const dotted = keyPath.join(".");
|
|
237
|
+
warnOnce(`config:unknown-key:${sourcePath ?? "inline"}:${dotted}`, `Unknown config key ${JSON.stringify(dotted)}${sourcePath ? ` at ${sourcePath}` : ""} has no defined akm behavior and is ignored. Check the spelling; a key retired by this release or added by a newer one is dropped by \`akm migrate apply\`.`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function deleteConfigPath(node, keyPath) {
|
|
241
|
+
let cursor = node;
|
|
242
|
+
for (const segment of keyPath.slice(0, -1)) {
|
|
243
|
+
if (!isPlainConfigObject(cursor))
|
|
244
|
+
return;
|
|
245
|
+
cursor = cursor[segment];
|
|
240
246
|
}
|
|
247
|
+
if (isPlainConfigObject(cursor))
|
|
248
|
+
delete cursor[keyPath[keyPath.length - 1]];
|
|
249
|
+
}
|
|
250
|
+
function isPlainConfigObject(value) {
|
|
251
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
241
252
|
}
|
|
242
253
|
function assertUniquePhysicalBundleRoots(config, sourcePath) {
|
|
243
254
|
const owners = new Map();
|
|
@@ -253,11 +264,10 @@ function assertUniquePhysicalBundleRoots(config, sourcePath) {
|
|
|
253
264
|
* Parse raw config text and validate via Zod.
|
|
254
265
|
* ({@link AkmConfigSchema}). Returns the merged-with-defaults AkmConfig.
|
|
255
266
|
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
* deep-merged underneath before validation — see {@link resolveExtendsChain}.
|
|
267
|
+
* `configVersion` is read as the current version whatever it says (see
|
|
268
|
+
* {@link readConfigVersion}). When the config sets `extends` (#945), its
|
|
269
|
+
* resolved chain is deep-merged underneath before validation — see
|
|
270
|
+
* {@link resolveExtendsChain}.
|
|
261
271
|
*/
|
|
262
272
|
export function parseAndValidateConfigText(text, sourcePath) {
|
|
263
273
|
const liftedConfig = runConfigFilePipeline(text, sourcePath);
|
|
@@ -290,7 +300,7 @@ function collectExtendsLayers(localRaw, configPath) {
|
|
|
290
300
|
}
|
|
291
301
|
visited.add(resolvedPath);
|
|
292
302
|
const baseRaw = runConfigFilePipeline(text, resolvedPath);
|
|
293
|
-
|
|
303
|
+
warnUnknownConfigKeys(baseRaw, resolvedPath);
|
|
294
304
|
layers.push({ ref, raw: baseRaw });
|
|
295
305
|
current = baseRaw;
|
|
296
306
|
currentPath = resolvedPath;
|
|
@@ -666,6 +676,36 @@ function configWriteBody(localRaw, current, next, persistTopLevelKeys = []) {
|
|
|
666
676
|
}
|
|
667
677
|
return ordered;
|
|
668
678
|
}
|
|
679
|
+
/**
|
|
680
|
+
* The migrator's one config step. The reader already tolerates every shape
|
|
681
|
+
* akm has written (`configVersion` read as current, legacy source layout,
|
|
682
|
+
* `extraParams` lift, unknown keys dropped); this writes that current shape back to
|
|
683
|
+
* `config.json` — the same body `mutateConfig` writes — so the tolerance
|
|
684
|
+
* becomes durable. Reports without writing unless `apply` is set.
|
|
685
|
+
*/
|
|
686
|
+
export function normalizeConfigFile(configPath, options) {
|
|
687
|
+
return withConfigLock(() => {
|
|
688
|
+
const text = readConfigText(configPath);
|
|
689
|
+
if (text === undefined)
|
|
690
|
+
return { keys: [], changed: false, applied: false };
|
|
691
|
+
const raw = parseConfigText(text, configPath);
|
|
692
|
+
const localRaw = runConfigFilePipeline(text, configPath);
|
|
693
|
+
const current = buildEffectiveConfig(localRaw, configPath);
|
|
694
|
+
const next = validateCompleteConfig({ ...current, configVersion: CURRENT_CONFIG_VERSION });
|
|
695
|
+
const body = withSchedulerOnDisk(configWriteBody(localRaw, current, next), next);
|
|
696
|
+
for (const keyPath of unknownConfigKeyPaths(body))
|
|
697
|
+
deleteConfigPath(body, keyPath);
|
|
698
|
+
const keys = [...new Set([...Object.keys(raw), ...Object.keys(body)])]
|
|
699
|
+
.filter((key) => JSON.stringify(raw[key]) !== JSON.stringify(body[key]))
|
|
700
|
+
.sort();
|
|
701
|
+
if (keys.length === 0 || !options.apply)
|
|
702
|
+
return { keys, changed: keys.length > 0, applied: false };
|
|
703
|
+
const backup = backupExistingConfig(configPath);
|
|
704
|
+
writeConfigAtomic(configPath, body);
|
|
705
|
+
cachedConfig = undefined;
|
|
706
|
+
return { keys, changed: true, applied: true, ...(backup ? { backupPath: backup.timestamped } : {}) };
|
|
707
|
+
});
|
|
708
|
+
}
|
|
669
709
|
/**
|
|
670
710
|
* Mutate config under one fail-closed lock spanning read, merge, validation,
|
|
671
711
|
* ordinary backup, and atomic write.
|
|
@@ -719,6 +759,61 @@ export async function mutateConfigWithPrecommit(mutate, precommit, options) {
|
|
|
719
759
|
release();
|
|
720
760
|
}
|
|
721
761
|
}
|
|
762
|
+
const UNBOUND_SCHEDULER_SOURCE_ID = `sha256:${"0".repeat(64)}`;
|
|
763
|
+
/**
|
|
764
|
+
* The source identity 0.9.16 bound a scheduler grant to: the configured
|
|
765
|
+
* bundle's source id, or the implicit `AKM_BUNDLE_DIR` stash's. `undefined`
|
|
766
|
+
* when the bundle is not active on this host.
|
|
767
|
+
*/
|
|
768
|
+
export function schedulerSourceIdFor(config, bundleId) {
|
|
769
|
+
if (isBundleEnabled(config, bundleId))
|
|
770
|
+
return bundleSourceId(config, bundleId);
|
|
771
|
+
if (config.bundles?.[bundleId] !== undefined || !process.env.AKM_BUNDLE_DIR?.trim())
|
|
772
|
+
return undefined;
|
|
773
|
+
try {
|
|
774
|
+
const root = resolveStashDir();
|
|
775
|
+
const implicitId = deriveBundleId(undefined, root, new Set(Object.keys(config.bundles ?? {})));
|
|
776
|
+
return implicitId === bundleId ? filesystemBundleSourceId(root) : undefined;
|
|
777
|
+
}
|
|
778
|
+
catch {
|
|
779
|
+
return undefined;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* `scheduler.enabled` is a list of refs in memory but is written in the
|
|
784
|
+
* `{kind, ref, sourceId}` shape 0.9.16 reads, so that release still runs
|
|
785
|
+
* against a config this one wrote (the upgrade rehearsal's read-back). This
|
|
786
|
+
* release reads either shape; the object form can go once no supported
|
|
787
|
+
* release is strict about it.
|
|
788
|
+
*/
|
|
789
|
+
function schedulerEnabledOnDisk(config) {
|
|
790
|
+
const enabled = config.scheduler?.enabled;
|
|
791
|
+
if (enabled === undefined)
|
|
792
|
+
return undefined;
|
|
793
|
+
return enabled.map((ref) => {
|
|
794
|
+
let bundle;
|
|
795
|
+
let conceptId = "";
|
|
796
|
+
try {
|
|
797
|
+
const parsed = parseBundleRef(ref);
|
|
798
|
+
bundle = parsed.bundle;
|
|
799
|
+
conceptId = parsed.conceptId;
|
|
800
|
+
}
|
|
801
|
+
catch {
|
|
802
|
+
return ref;
|
|
803
|
+
}
|
|
804
|
+
return {
|
|
805
|
+
kind: conceptId.startsWith("workflows/") ? "workflow" : "task",
|
|
806
|
+
ref,
|
|
807
|
+
sourceId: (bundle !== undefined ? schedulerSourceIdFor(config, bundle) : undefined) ?? UNBOUND_SCHEDULER_SOURCE_ID,
|
|
808
|
+
};
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
function withSchedulerOnDisk(body, config) {
|
|
812
|
+
const onDisk = schedulerEnabledOnDisk(config);
|
|
813
|
+
if (onDisk === undefined || !isPlainConfigObject(body.scheduler))
|
|
814
|
+
return body;
|
|
815
|
+
return { ...body, scheduler: { ...body.scheduler, enabled: onDisk } };
|
|
816
|
+
}
|
|
722
817
|
/**
|
|
723
818
|
* Strip literal apiKey fields before writing config to disk.
|
|
724
819
|
* API keys are expected to come from environment variables
|
|
@@ -783,7 +878,7 @@ export function sanitizeConfigForWrite(config) {
|
|
|
783
878
|
warn(`Config sanitizer dropped registry entr${droppedRegistries.length === 1 ? "y" : "ies"} with URL credentials before writing to disk:\n - ${droppedRegistries.join("\n - ")}\n\nRegistry URLs must be credential-free; configure a credential-free HTTPS endpoint.`);
|
|
784
879
|
}
|
|
785
880
|
}
|
|
786
|
-
return sanitized;
|
|
881
|
+
return withSchedulerOnDisk(sanitized, config);
|
|
787
882
|
}
|
|
788
883
|
export function updateConfig(partial) {
|
|
789
884
|
return mutateConfig((current) => deepMergeConfig(current, partial)).config;
|
|
@@ -55,20 +55,29 @@ function filesystemLocator(bundle) {
|
|
|
55
55
|
return undefined;
|
|
56
56
|
return path.resolve(bundle.path);
|
|
57
57
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Pure legacy `stashDir`/`sources[]`/`installed` -> `bundles`/`defaultBundle`
|
|
60
|
+
* conversion. Triggers on key *presence* (not on the value being usable), so
|
|
61
|
+
* an unusable value — `stashDir: ""`, `sources: []` — is still removed along
|
|
62
|
+
* with the rest of the legacy shape; only a usable `stashDir` or `sources[]`
|
|
63
|
+
* entry is actually folded into `bundles`. Never warns — see
|
|
64
|
+
* {@link migrateLegacySourceShape} for the warn-once wrapper callers use.
|
|
65
|
+
*/
|
|
66
|
+
export function convertLegacySourceShape(raw) {
|
|
67
|
+
const hasStashDir = "stashDir" in raw;
|
|
68
|
+
const hasSources = "sources" in raw;
|
|
61
69
|
const hasInstalled = "installed" in raw && raw.installed !== undefined;
|
|
62
70
|
if (!hasStashDir && !hasSources && !hasInstalled)
|
|
63
|
-
return raw;
|
|
71
|
+
return { config: raw, converted: [] };
|
|
64
72
|
const { stashDir: _stashDir, sources: _sources, installed: _installed, ...rest } = raw;
|
|
65
73
|
const bundles = isPlainRecord(rest.bundles) ? { ...rest.bundles } : {};
|
|
66
74
|
let defaultBundle = typeof rest.defaultBundle === "string" ? rest.defaultBundle : undefined;
|
|
67
|
-
|
|
75
|
+
const usableStashDir = typeof raw.stashDir === "string" && raw.stashDir.trim().length > 0;
|
|
76
|
+
if (usableStashDir) {
|
|
68
77
|
bundles.stash = { path: raw.stashDir, writable: true };
|
|
69
78
|
defaultBundle ??= "stash";
|
|
70
79
|
}
|
|
71
|
-
if (
|
|
80
|
+
if (Array.isArray(raw.sources)) {
|
|
72
81
|
raw.sources.forEach((entry, index) => {
|
|
73
82
|
const converted = bundleFromLegacySource(entry, index);
|
|
74
83
|
if (!converted)
|
|
@@ -81,8 +90,28 @@ export function migrateLegacySourceShape(raw, sourcePath) {
|
|
|
81
90
|
defaultBundle ??= key;
|
|
82
91
|
});
|
|
83
92
|
}
|
|
84
|
-
const
|
|
93
|
+
const converted = [hasStashDir && "stashDir", hasSources && "sources", hasInstalled && "installed"].filter((key) => typeof key === "string");
|
|
94
|
+
// Only add a `bundles` key when there is something to say: either a
|
|
95
|
+
// legacy entry actually converted into one, or the config already had a
|
|
96
|
+
// `bundles` map (preserved as-is). An unusable `stashDir: ""` / `sources: []`
|
|
97
|
+
// with no pre-existing `bundles` should just disappear, not leave behind
|
|
98
|
+
// an empty `bundles: {}`.
|
|
99
|
+
const hasBundles = Object.keys(bundles).length > 0 || isPlainRecord(rest.bundles);
|
|
100
|
+
return {
|
|
101
|
+
config: { ...rest, ...(hasBundles ? { bundles } : {}), ...(defaultBundle !== undefined ? { defaultBundle } : {}) },
|
|
102
|
+
converted,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Warn-once wrapper around {@link convertLegacySourceShape} for the
|
|
107
|
+
* in-memory read path: converts the legacy shape and, when it removed
|
|
108
|
+
* anything, warns once that `akm migrate apply` will persist the rewrite.
|
|
109
|
+
*/
|
|
110
|
+
export function migrateLegacySourceShape(raw, sourcePath) {
|
|
111
|
+
const { config, converted } = convertLegacySourceShape(raw);
|
|
112
|
+
if (converted.length === 0)
|
|
113
|
+
return config;
|
|
85
114
|
const where = sourcePath ? ` at ${sourcePath}` : "";
|
|
86
|
-
warnOnce(`legacy-source-shape${sourcePath ? `:${sourcePath}` : ""}`, `Config${where} uses the retired ${
|
|
87
|
-
return
|
|
115
|
+
warnOnce(`legacy-source-shape${sourcePath ? `:${sourcePath}` : ""}`, `Config${where} uses the retired ${converted.join("/")} shape — auto-migrated in memory to \`bundles\`/\`defaultBundle\`. Run \`akm migrate apply\` to rewrite the config file and silence this warning.`);
|
|
116
|
+
return config;
|
|
88
117
|
}
|
|
@@ -27,11 +27,7 @@ export const EmbeddingConnectionConfigSchema = z
|
|
|
27
27
|
endpoint: z.string().optional(),
|
|
28
28
|
model: z.string().optional(),
|
|
29
29
|
apiKey: symbolicOrWarnApiKey("embedding.apiKey").optional(),
|
|
30
|
-
|
|
31
|
-
// storage/repositories/index-schema.ts) so an out-of-range dimension
|
|
32
|
-
// fails at config validation with a clear message instead of crashing
|
|
33
|
-
// `akm index` when ensureSchema rejects it (§24.2 "Semantic" gate).
|
|
34
|
-
dimension: positiveInt.max(4096).optional(),
|
|
30
|
+
dimension: positiveInt.optional(),
|
|
35
31
|
localModel: z.string().min(1).optional(),
|
|
36
32
|
/**
|
|
37
33
|
* Per-document token cap applied BEFORE batching (default 512,
|
|
@@ -68,6 +64,25 @@ export const EmbeddingConnectionConfigSchema = z
|
|
|
68
64
|
* no retry — every batch that hit it was silently dropped (#954).
|
|
69
65
|
*/
|
|
70
66
|
timeoutMs: positiveInt.optional(),
|
|
67
|
+
/**
|
|
68
|
+
* How long search waits for the query embedding (default 3000,
|
|
69
|
+
* `DEFAULT_QUERY_EMBED_TIMEOUT_MS` in `src/indexer/search/db-search.ts`).
|
|
70
|
+
* On expiry the search is served by keyword ranking alone, with a warning.
|
|
71
|
+
*/
|
|
72
|
+
queryTimeoutMs: positiveInt.optional(),
|
|
73
|
+
/**
|
|
74
|
+
* Text sent to the model around a search query, `{text}` marking the
|
|
75
|
+
* query (a template without it is a prefix). Overrides the preset matched
|
|
76
|
+
* on the model name (`src/llm/embedders/profile.ts`); `""` sends the query
|
|
77
|
+
* as is.
|
|
78
|
+
*/
|
|
79
|
+
queryTemplate: z.string().optional(),
|
|
80
|
+
/**
|
|
81
|
+
* Text sent to the model around each document at index time, as
|
|
82
|
+
* `queryTemplate`. Part of the embedding fingerprint: changing it
|
|
83
|
+
* re-embeds the index.
|
|
84
|
+
*/
|
|
85
|
+
documentTemplate: z.string().optional(),
|
|
71
86
|
/**
|
|
72
87
|
* Overrides the fixed in-flight request window (#954, added after field
|
|
73
88
|
* evidence from multi-slot local servers). Bounded 1-16. Unset keeps
|
|
@@ -77,6 +77,11 @@ const LlmEngineSchema = z
|
|
|
77
77
|
maxTokens: positiveInt.optional(),
|
|
78
78
|
timeoutMs: timeoutMsField,
|
|
79
79
|
concurrency: positiveInt.optional(),
|
|
80
|
+
// Same user-settable override LlmConnectionConfigSchema declares above; a
|
|
81
|
+
// named `kind: "llm"` engine is validated by THIS object, so without the
|
|
82
|
+
// field here the unknown-key walk reported a live setting as unknown and
|
|
83
|
+
// `akm migrate apply` dropped it from config.json.
|
|
84
|
+
supportsJsonSchema: z.boolean().optional(),
|
|
80
85
|
extraParams: ExtraParamsSchema.optional(),
|
|
81
86
|
contextLength: positiveInt.optional(),
|
|
82
87
|
enableThinking: z.boolean().optional(),
|
|
@@ -64,8 +64,6 @@ const processLimitField = positiveInt.optional();
|
|
|
64
64
|
* `reflect` process (proposal-side quality gate; see reflect.ts).
|
|
65
65
|
*/
|
|
66
66
|
const qualityGateField = z.object({ enabled: z.boolean().optional() }).passthrough().optional();
|
|
67
|
-
/** Consolidate process: gate for the M-1 (#367) contradiction-detection pass. */
|
|
68
|
-
const contradictionDetectionField = z.object({ enabled: z.boolean().optional() }).passthrough().optional();
|
|
69
67
|
/**
|
|
70
68
|
* WS-3b: CLS (Complementary Learning System) interleaving (step 9).
|
|
71
69
|
* distill/memoryInference prompts include embedding-retrieved existing adjacent
|
|
@@ -109,19 +107,10 @@ const extractTriageGateField = z
|
|
|
109
107
|
})
|
|
110
108
|
.passthrough()
|
|
111
109
|
.optional();
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return { message: `${retired} is retired; use engine` };
|
|
117
|
-
}
|
|
118
|
-
return { message: ctx.defaultError };
|
|
119
|
-
};
|
|
120
|
-
// Judgment is an explicit opt-in surface, so invocation typos must fail closed.
|
|
121
|
-
// Keep the shared override schema lenient for ordinary cross-version config
|
|
122
|
-
// compatibility, while making this nested surface strict. `extraParams`
|
|
123
|
-
// remains the intentional arbitrary provider-parameter escape hatch.
|
|
124
|
-
const triageJudgmentLlmOverridesField = LlmInvocationOverridesSchema.strict();
|
|
110
|
+
// Unknown keys pass through here like every other nested surface (the loader
|
|
111
|
+
// names them once); `extraParams` remains the arbitrary provider-parameter
|
|
112
|
+
// escape hatch.
|
|
113
|
+
const triageJudgmentLlmOverridesField = LlmInvocationOverridesSchema.passthrough();
|
|
125
114
|
const triageJudgmentObjectField = z
|
|
126
115
|
.object({
|
|
127
116
|
enabled: z.boolean().optional(),
|
|
@@ -129,41 +118,26 @@ const triageJudgmentObjectField = z
|
|
|
129
118
|
model: nonEmptyString.optional(),
|
|
130
119
|
timeoutMs: z.union([positiveInt, z.null()]).optional(),
|
|
131
120
|
llm: triageJudgmentLlmOverridesField.optional(),
|
|
132
|
-
}
|
|
133
|
-
.
|
|
121
|
+
})
|
|
122
|
+
.passthrough();
|
|
134
123
|
/** Triage process: explicit LLM-as-judge enablement and execution overrides. */
|
|
135
124
|
const triageJudgmentField = z
|
|
136
125
|
.union([z.boolean(), triageJudgmentObjectField])
|
|
137
126
|
.transform((value) => typeof value === "boolean" ? { enabled: value } : { ...value, enabled: value.enabled ?? true })
|
|
138
127
|
.optional();
|
|
139
128
|
/**
|
|
140
|
-
* WS-3b: Anti-collapse
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* decorative/inert knob. `false` skips the merge-information-floor
|
|
148
|
-
* measurement entirely (no counting, no warning) for every merge;
|
|
149
|
-
* true/absent (default) measures it on every merge. The MEASUREMENT's
|
|
150
|
-
* outcome is advisory in v1: a failing merge is counted
|
|
151
|
-
* (`merge_floor_violations`) and warned but never refused (promotion path:
|
|
152
|
-
* docs/architecture/specs/improve-collapse-churn-detector-design.md §7). In short:
|
|
153
|
-
* this field gates whether the check runs at all (a real code path), not
|
|
154
|
-
* whether a merge is allowed.
|
|
155
|
-
* - minSpecificityRetention: distinct-token retention floor for merges (default 0.6).
|
|
156
|
-
* (WS-3b step 0a `homeostaticDemotion` was removed — R4. Continuous decay is
|
|
157
|
-
* now part of the always-applied salience recency term.)
|
|
129
|
+
* WS-3b: Anti-collapse guard (step 8), consolidate process only: a small
|
|
130
|
+
* random (non-similarity-driven) fraction of the pool is mixed into the
|
|
131
|
+
* clustered order so consolidation is not purely rich-get-richer. Default ON
|
|
132
|
+
* (opt out via `enabled: false`); `randomClusterFraction` defaults to 0.05.
|
|
133
|
+
* The retired merge guards (`maxGeneration`, `lexicalDiversityCheck`,
|
|
134
|
+
* `mergeInformationFloor`, `minSpecificityRetention`) never refused a merge
|
|
135
|
+
* and are tolerated as unknown keys.
|
|
158
136
|
*/
|
|
159
137
|
const antiCollapseField = z
|
|
160
138
|
.object({
|
|
161
139
|
enabled: z.boolean().optional(),
|
|
162
|
-
maxGeneration: z.number().int().min(1).optional(),
|
|
163
|
-
lexicalDiversityCheck: z.boolean().optional(),
|
|
164
140
|
randomClusterFraction: z.number().min(0).max(1).optional(),
|
|
165
|
-
mergeInformationFloor: z.boolean().optional(),
|
|
166
|
-
minSpecificityRetention: z.number().min(0).max(1).optional(),
|
|
167
141
|
})
|
|
168
142
|
.passthrough()
|
|
169
143
|
.optional();
|
|
@@ -202,7 +176,6 @@ const CONSOLIDATE_PROCESS_FIELDS = {
|
|
|
202
176
|
// accumulates; this value is only used on the very first run. Default 30s.
|
|
203
177
|
p90ChunkSecondsDefault: z.number().finite().positive().optional(),
|
|
204
178
|
antiCollapse: antiCollapseField,
|
|
205
|
-
contradictionDetection: contradictionDetectionField,
|
|
206
179
|
};
|
|
207
180
|
const MEMORY_INFERENCE_PROCESS_FIELDS = {
|
|
208
181
|
// Minimum pending memory count to run the pass.
|
|
@@ -261,10 +234,7 @@ const EXTRACT_PROCESS_FIELDS = {
|
|
|
261
234
|
};
|
|
262
235
|
const TRIAGE_PROCESS_FIELDS = {
|
|
263
236
|
applyMode: z.enum(["queue", "promote"]).optional(),
|
|
264
|
-
policy: z.string().min(1).optional(),
|
|
265
237
|
maxAcceptsPerRun: positiveInt.optional(),
|
|
266
|
-
maxDiffLines: positiveInt.optional(),
|
|
267
|
-
rejectEmpty: z.boolean().optional(),
|
|
268
238
|
judgment: triageJudgmentField,
|
|
269
239
|
};
|
|
270
240
|
/** proactiveMaintenance process fields (Layer 2). */
|
|
@@ -276,38 +246,6 @@ const PROACTIVE_MAINTENANCE_PROCESS_FIELDS = {
|
|
|
276
246
|
maxPerRun: positiveInt.optional(),
|
|
277
247
|
limit: processLimitField,
|
|
278
248
|
};
|
|
279
|
-
/**
|
|
280
|
-
* Shared cross-process superRefine: rejects the retired `mode`/`profile`
|
|
281
|
-
* knobs (top-level and inside a `judgment` sub-object) in favour of `engine`.
|
|
282
|
-
* Applied identically to every per-process schema and to the wide
|
|
283
|
-
* ImproveProcessConfigSchema.
|
|
284
|
-
*/
|
|
285
|
-
function checkRetiredProcessKeys(value, ctx) {
|
|
286
|
-
for (const key of ["mode", "profile"]) {
|
|
287
|
-
if (key in value) {
|
|
288
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, path: [key], message: `${key} is retired; use engine` });
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
if ("judgement" in value) {
|
|
292
|
-
ctx.addIssue({
|
|
293
|
-
code: z.ZodIssueCode.custom,
|
|
294
|
-
path: ["judgement"],
|
|
295
|
-
message: "judgement is not a valid key; use judgment",
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
const judgment = value.judgment;
|
|
299
|
-
if (judgment) {
|
|
300
|
-
for (const key of ["mode", "profile"]) {
|
|
301
|
-
if (key in judgment) {
|
|
302
|
-
ctx.addIssue({
|
|
303
|
-
code: z.ZodIssueCode.custom,
|
|
304
|
-
path: ["judgment", key],
|
|
305
|
-
message: `${key} is retired; use engine`,
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
249
|
/** distill/consolidate are memory-only and never read `excludeRefPrefixes` (reflect only, R12). */
|
|
312
250
|
function rejectExcludeRefPrefixesOutsideReflect(value, ctx) {
|
|
313
251
|
if ("excludeRefPrefixes" in value) {
|
|
@@ -330,55 +268,43 @@ export const ImproveProcessConfigSchema = z
|
|
|
330
268
|
...TRIAGE_PROCESS_FIELDS,
|
|
331
269
|
...PROACTIVE_MAINTENANCE_PROCESS_FIELDS,
|
|
332
270
|
})
|
|
333
|
-
.passthrough()
|
|
334
|
-
.superRefine(checkRetiredProcessKeys);
|
|
271
|
+
.passthrough();
|
|
335
272
|
/** `processes.reflect` — narrow per-process schema (WI-9.6). */
|
|
336
273
|
export const ReflectProcessConfigSchema = z
|
|
337
274
|
.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...REFLECT_PROCESS_FIELDS })
|
|
338
|
-
.passthrough()
|
|
339
|
-
.superRefine(checkRetiredProcessKeys);
|
|
275
|
+
.passthrough();
|
|
340
276
|
/** `processes.distill` — narrow per-process schema (WI-9.6). */
|
|
341
277
|
export const DistillProcessConfigSchema = z
|
|
342
278
|
.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...DISTILL_PROCESS_FIELDS })
|
|
343
279
|
.passthrough()
|
|
344
|
-
.superRefine(checkRetiredProcessKeys)
|
|
345
280
|
.superRefine(rejectExcludeRefPrefixesOutsideReflect);
|
|
346
281
|
/** `processes.consolidate` — narrow per-process schema (WI-9.6). */
|
|
347
282
|
export const ConsolidateProcessConfigSchema = z
|
|
348
283
|
.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...CONSOLIDATE_PROCESS_FIELDS })
|
|
349
284
|
.passthrough()
|
|
350
|
-
.superRefine(checkRetiredProcessKeys)
|
|
351
285
|
.superRefine(rejectExcludeRefPrefixesOutsideReflect);
|
|
352
286
|
/** `processes.memoryInference` — narrow per-process schema (WI-9.6). */
|
|
353
287
|
export const MemoryInferenceProcessConfigSchema = z
|
|
354
288
|
.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...MEMORY_INFERENCE_PROCESS_FIELDS })
|
|
355
|
-
.passthrough()
|
|
356
|
-
.superRefine(checkRetiredProcessKeys);
|
|
289
|
+
.passthrough();
|
|
357
290
|
/** `processes.graphExtraction` — narrow per-process schema (WI-9.6). */
|
|
358
291
|
export const GraphExtractionProcessConfigSchema = z
|
|
359
292
|
.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...GRAPH_EXTRACTION_PROCESS_FIELDS })
|
|
360
|
-
.passthrough()
|
|
361
|
-
.superRefine(checkRetiredProcessKeys);
|
|
293
|
+
.passthrough();
|
|
362
294
|
/** `processes.extract` — narrow per-process schema (WI-9.6). */
|
|
363
295
|
export const ExtractProcessConfigSchema = z
|
|
364
296
|
.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...EXTRACT_PROCESS_FIELDS })
|
|
365
|
-
.passthrough()
|
|
366
|
-
.superRefine(checkRetiredProcessKeys);
|
|
297
|
+
.passthrough();
|
|
367
298
|
/** `processes.validation` — narrow per-process schema (WI-9.6); no extra fields beyond the shared base. */
|
|
368
|
-
export const ValidationProcessConfigSchema = z
|
|
369
|
-
.object({ ...IMPROVE_PROCESS_BASE_FIELDS })
|
|
370
|
-
.passthrough()
|
|
371
|
-
.superRefine(checkRetiredProcessKeys);
|
|
299
|
+
export const ValidationProcessConfigSchema = z.object({ ...IMPROVE_PROCESS_BASE_FIELDS }).passthrough();
|
|
372
300
|
/** `processes.triage` — narrow per-process schema (WI-9.6). */
|
|
373
301
|
export const TriageProcessConfigSchema = z
|
|
374
302
|
.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...TRIAGE_PROCESS_FIELDS })
|
|
375
|
-
.passthrough()
|
|
376
|
-
.superRefine(checkRetiredProcessKeys);
|
|
303
|
+
.passthrough();
|
|
377
304
|
/** `processes.proactiveMaintenance` — narrow per-process schema (WI-9.6). */
|
|
378
305
|
export const ProactiveMaintenanceProcessConfigSchema = z
|
|
379
306
|
.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...PROACTIVE_MAINTENANCE_PROCESS_FIELDS })
|
|
380
|
-
.passthrough()
|
|
381
|
-
.superRefine(checkRetiredProcessKeys);
|
|
307
|
+
.passthrough();
|
|
382
308
|
const ImproveProfileProcessesSchema = z
|
|
383
309
|
.object({
|
|
384
310
|
reflect: ReflectProcessConfigSchema.optional(),
|