akm-cli 0.9.1 → 0.9.2-alpha.2

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.
Files changed (350) hide show
  1. package/CHANGELOG.md +103 -28
  2. package/README.md +3 -1
  3. package/SECURITY.md +1 -1
  4. package/STABILITY.md +1 -1
  5. package/dist/akm +2 -2
  6. package/dist/akm-migrate +2 -2
  7. package/dist/assets/hints/cli-hints-full.md +14 -9
  8. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -1
  9. package/dist/assets/improve-strategies/reflect-distill.json +1 -1
  10. package/dist/assets/models.json +35 -0
  11. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +3 -4
  12. package/dist/assets/stash-skeleton/facts/conventions/organization.md +1 -3
  13. package/dist/assets/tasks/core/extract.yml +6 -5
  14. package/dist/assets/tasks/core/improve.yml +6 -5
  15. package/dist/assets/tasks/core/index-refresh.yml +6 -5
  16. package/dist/assets/tasks/core/sync.yml +6 -5
  17. package/dist/assets/tasks/core/version-check.yml +6 -5
  18. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +6 -5
  19. package/dist/assets/tasks/improve/akm-improve-catchup.yml +6 -5
  20. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +6 -5
  21. package/dist/assets/tasks/improve/akm-improve-frequent.yml +6 -5
  22. package/dist/assets/tasks/improve/akm-improve-nightly.yml +6 -5
  23. package/dist/cli/confirm.js +2 -2
  24. package/dist/cli/parse-args.js +3 -24
  25. package/dist/cli/retired-commands.js +1 -1
  26. package/dist/cli/shared.js +2 -2
  27. package/dist/cli.js +11 -9
  28. package/dist/commands/agent/agent-dispatch.js +55 -89
  29. package/dist/commands/agent/contribute-cli.js +12 -45
  30. package/dist/commands/command/builtin-action.js +32 -0
  31. package/dist/commands/command/command-cli.js +99 -0
  32. package/dist/commands/command/command-execution.js +308 -0
  33. package/dist/commands/command/execution-source-loader.js +176 -0
  34. package/dist/commands/command/portable-template.js +60 -0
  35. package/dist/commands/config-cli.js +10 -4
  36. package/dist/commands/env/env.js +4 -2
  37. package/dist/commands/feedback-cli.js +1 -1
  38. package/dist/commands/health/checks.js +241 -29
  39. package/dist/commands/health/html-report.js +0 -14
  40. package/dist/commands/health/report-view-model.js +0 -1
  41. package/dist/commands/health/surfaces.js +6 -7
  42. package/dist/commands/health/types.js +0 -2
  43. package/dist/commands/health.js +63 -18
  44. package/dist/commands/improve/collapse-detector.js +5 -6
  45. package/dist/commands/improve/consolidate.js +251 -214
  46. package/dist/commands/improve/distill/promote-memory.js +71 -34
  47. package/dist/commands/improve/distill/quality-gate.js +17 -5
  48. package/dist/commands/improve/distill.js +232 -155
  49. package/dist/commands/improve/eligibility.js +112 -79
  50. package/dist/commands/improve/execution.js +57 -0
  51. package/dist/commands/improve/extract-cli.js +5 -5
  52. package/dist/commands/improve/extract-prompt.js +64 -22
  53. package/dist/commands/improve/extract.js +608 -360
  54. package/dist/commands/improve/improve-strategies.js +43 -14
  55. package/dist/commands/improve/improve.js +249 -29
  56. package/dist/commands/improve/loop-stages.js +11 -17
  57. package/dist/commands/improve/memory/memory-contradiction-detect.js +90 -66
  58. package/dist/commands/improve/outcome-loop.js +22 -38
  59. package/dist/commands/improve/planner.js +134 -0
  60. package/dist/commands/improve/preparation.js +730 -409
  61. package/dist/commands/improve/reflect.js +386 -223
  62. package/dist/commands/improve/run-context.js +3 -4
  63. package/dist/commands/improve/salience.js +6 -58
  64. package/dist/commands/improve/session-asset.js +12 -12
  65. package/dist/commands/lint/index.js +101 -29
  66. package/dist/commands/migrate-cli.js +11 -69
  67. package/dist/commands/migration-tool.js +6 -9
  68. package/dist/commands/models-cli.js +27 -0
  69. package/dist/commands/proposal/drain.js +258 -186
  70. package/dist/commands/proposal/proposal-cli.js +32 -10
  71. package/dist/commands/proposal/proposal.js +2 -5
  72. package/dist/commands/proposal/propose.js +192 -172
  73. package/dist/commands/proposal/repository.js +54 -91
  74. package/dist/commands/proposal/validators/proposal-validators.js +9 -7
  75. package/dist/commands/read/curate.js +53 -22
  76. package/dist/commands/read/registry-search.js +25 -9
  77. package/dist/commands/read/remember-cli.js +14 -2
  78. package/dist/commands/read/search.js +10 -4
  79. package/dist/commands/read/show.js +139 -153
  80. package/dist/commands/registry-cli.js +16 -7
  81. package/dist/commands/remember.js +33 -18
  82. package/dist/commands/sources/add-cli.js +19 -178
  83. package/dist/commands/sources/bundle-cli.js +15 -3
  84. package/dist/commands/sources/dangerous-env-audit.js +135 -0
  85. package/dist/commands/sources/info.js +2 -1
  86. package/dist/commands/sources/installed-stashes.js +901 -177
  87. package/dist/commands/sources/schema-repair.js +174 -95
  88. package/dist/commands/sources/self-update.js +30 -74
  89. package/dist/commands/sources/source-add.js +3 -5
  90. package/dist/commands/sources/sources-cli.js +2 -15
  91. package/dist/commands/sources/update-transaction.js +220 -0
  92. package/dist/commands/tasks/tasks-cli.js +3 -3
  93. package/dist/commands/tasks/tasks.js +736 -317
  94. package/dist/commands/workflow-cli.js +2 -2
  95. package/dist/core/adapter/adapters/agent-skills-adapter.js +3 -0
  96. package/dist/core/adapter/adapters/akm-adapter.js +85 -35
  97. package/dist/core/adapter/adapters/akm-lint.js +54 -39
  98. package/dist/core/adapter/adapters/akm-metadata.js +45 -45
  99. package/dist/core/adapter/adapters/akm-task-adapter.js +32 -49
  100. package/dist/core/adapter/adapters/akm-workflow-adapter.js +38 -23
  101. package/dist/core/adapter/adapters/dotenv-adapter.js +30 -1
  102. package/dist/core/adapter/adapters/generic-files-adapter.js +11 -0
  103. package/dist/core/adapter/adapters/index.js +0 -9
  104. package/dist/core/adapter/adapters/llm-wiki-adapter.js +4 -0
  105. package/dist/core/adapter/adapters/okf-adapter.js +4 -0
  106. package/dist/core/adapter/adapters/opencode-adapter.js +5 -8
  107. package/dist/core/adapter/adapters/tool-dir-shared.js +63 -6
  108. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -0
  109. package/dist/core/adapter/execution-source.js +308 -0
  110. package/dist/core/adapter/recognize-match.js +36 -13
  111. package/dist/core/adapter/registry.js +0 -9
  112. package/dist/core/asset/stash-meta.js +94 -4
  113. package/dist/core/common.js +6 -11
  114. package/dist/core/config/config-io.js +3 -3
  115. package/dist/core/config/config-schema.js +18 -40
  116. package/dist/core/config/config-sources.js +11 -21
  117. package/dist/core/config/config-walker.js +31 -13
  118. package/dist/core/config/config.js +23 -26
  119. package/dist/core/config/schema/engines.js +8 -7
  120. package/dist/core/config/schema/improve-processes.js +29 -5
  121. package/dist/core/config/schema/index-config.js +0 -27
  122. package/dist/core/config/schema/primitives.js +1 -23
  123. package/dist/core/config/schema/sources-bundles.js +13 -16
  124. package/dist/core/errors.js +2 -0
  125. package/dist/core/events.js +68 -32
  126. package/dist/core/extra-params.js +1 -0
  127. package/dist/core/improve-result.js +315 -0
  128. package/dist/core/lesson-lint.js +0 -6
  129. package/dist/core/maintenance-barrier.js +4 -4
  130. package/dist/core/network-policy.js +152 -0
  131. package/dist/core/paths.js +1 -1
  132. package/dist/core/recognition-util.js +4 -4
  133. package/dist/core/registry-url.js +456 -0
  134. package/dist/core/state/migrations.js +161 -47
  135. package/dist/core/state-db.js +453 -80
  136. package/dist/core/system-error.js +32 -0
  137. package/dist/core/time.js +2 -12
  138. package/dist/core/write-source.js +0 -18
  139. package/dist/execution/directory-identity.js +52 -0
  140. package/dist/execution/executable-identity.js +107 -0
  141. package/dist/execution/guarded-source.js +398 -0
  142. package/dist/execution/json.js +95 -0
  143. package/dist/{commands/health/types-session-log.js → execution/limits.js} +2 -1
  144. package/dist/execution/record.js +55 -0
  145. package/dist/execution/resolved-request.js +730 -0
  146. package/dist/execution/source.js +320 -0
  147. package/dist/indexer/bundle-identity-guard.js +5 -4
  148. package/dist/indexer/db/graph-db.js +33 -0
  149. package/dist/indexer/graph/graph-boost.js +3 -4
  150. package/dist/indexer/graph/graph-extraction.js +562 -373
  151. package/dist/indexer/index-written-assets.js +78 -39
  152. package/dist/indexer/indexer.js +471 -432
  153. package/dist/indexer/installations.js +6 -0
  154. package/dist/indexer/lookup/adapter-concept-owner.js +283 -0
  155. package/dist/indexer/materialize-embeddings.js +155 -0
  156. package/dist/indexer/passes/memory-inference.js +227 -174
  157. package/dist/indexer/passes/metadata.js +263 -118
  158. package/dist/indexer/scan/doc-to-entry.js +7 -10
  159. package/dist/indexer/scan/drain-dir.js +51 -23
  160. package/dist/indexer/search/db-search.js +156 -50
  161. package/dist/indexer/search/fts-query.js +40 -40
  162. package/dist/indexer/search/ranking.js +36 -1
  163. package/dist/indexer/search/search-attribution.js +3 -1
  164. package/dist/indexer/search/search-fields.js +23 -14
  165. package/dist/indexer/search/search-hit-enrichers.js +1 -1
  166. package/dist/indexer/search/search-source.js +7 -16
  167. package/dist/indexer/search/semantic-status.js +10 -1
  168. package/dist/indexer/usage/show-usage.js +105 -0
  169. package/dist/indexer/usage/usage-events.js +7 -2
  170. package/dist/indexer/walk/matchers.js +40 -10
  171. package/dist/indexer/walk/path-resolver.js +5 -2
  172. package/dist/indexer/walk/walker.js +20 -2
  173. package/dist/integrations/agent/builder-shared.js +3 -6
  174. package/dist/integrations/agent/conversation-fallback.js +16 -0
  175. package/dist/integrations/agent/engine-resolution.js +87 -87
  176. package/dist/integrations/agent/execution-cascade.js +566 -0
  177. package/dist/integrations/agent/execution-definitions.js +211 -0
  178. package/dist/integrations/agent/execution-lowering.js +811 -0
  179. package/dist/integrations/agent/execution-preparation.js +67 -0
  180. package/dist/integrations/agent/index.js +0 -2
  181. package/dist/integrations/agent/inline-execution.js +74 -0
  182. package/dist/integrations/agent/model-map.js +515 -0
  183. package/dist/integrations/agent/persona-fallback.js +30 -0
  184. package/dist/integrations/agent/request-lowering.js +186 -0
  185. package/dist/integrations/agent/runner-dispatch.js +230 -37
  186. package/dist/integrations/agent/runner.js +12 -83
  187. package/dist/integrations/harnesses/aider/agent-builder.js +8 -0
  188. package/dist/integrations/harnesses/aider/index.js +0 -1
  189. package/dist/integrations/harnesses/amazonq/agent-builder.js +8 -0
  190. package/dist/integrations/harnesses/amazonq/index.js +0 -1
  191. package/dist/integrations/harnesses/claude/agent-builder.js +14 -1
  192. package/dist/integrations/harnesses/claude/index.js +1 -5
  193. package/dist/integrations/harnesses/claude/session-log.js +3 -33
  194. package/dist/integrations/harnesses/codex/agent-builder.js +8 -0
  195. package/dist/integrations/harnesses/codex/index.js +0 -1
  196. package/dist/integrations/harnesses/copilot/agent-builder.js +8 -0
  197. package/dist/integrations/harnesses/copilot/index.js +0 -1
  198. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -0
  199. package/dist/integrations/harnesses/gemini/index.js +0 -1
  200. package/dist/integrations/harnesses/index.js +4 -44
  201. package/dist/integrations/harnesses/opencode/agent-builder.js +16 -9
  202. package/dist/integrations/harnesses/opencode/index.js +0 -2
  203. package/dist/integrations/harnesses/opencode/session-log.js +14 -204
  204. package/dist/integrations/harnesses/opencode-sdk/harness.js +12 -1
  205. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +40 -42
  206. package/dist/integrations/harnesses/openhands/agent-builder.js +8 -0
  207. package/dist/integrations/harnesses/openhands/index.js +0 -1
  208. package/dist/integrations/harnesses/pi/agent-builder.js +8 -0
  209. package/dist/integrations/harnesses/pi/index.js +0 -1
  210. package/dist/integrations/harnesses/shared.js +0 -1
  211. package/dist/integrations/harnesses/types.js +1 -3
  212. package/dist/integrations/lockfile.js +82 -79
  213. package/dist/integrations/session-logs/index.js +6 -17
  214. package/dist/integrations/session-logs/provider-base.js +1 -29
  215. package/dist/llm/client.js +10 -5
  216. package/dist/llm/embedder.js +6 -7
  217. package/dist/llm/embedders/local.js +37 -88
  218. package/dist/llm/embedders/types.js +1 -1
  219. package/dist/llm/graph-extract.js +75 -50
  220. package/dist/llm/index-passes.js +43 -5
  221. package/dist/llm/memory-infer.js +8 -6
  222. package/dist/llm/metadata-enhance.js +5 -3
  223. package/dist/llm/structured-call.js +122 -25
  224. package/dist/output/format-exempt.js +1 -1
  225. package/dist/output/render-registry.js +0 -16
  226. package/dist/output/renderers.js +12 -7
  227. package/dist/output/shapes/curate.js +1 -0
  228. package/dist/output/shapes/helpers.js +10 -2
  229. package/dist/output/shapes/passthrough.js +2 -0
  230. package/dist/output/text/command-format.js +31 -33
  231. package/dist/output/text/health-format.js +1 -29
  232. package/dist/output/text/migrate.js +6 -56
  233. package/dist/output/text/proposal-format.js +16 -1
  234. package/dist/output/text/workflow-format.js +16 -0
  235. package/dist/registry/network.js +279 -0
  236. package/dist/registry/pinned-request-helper.js +247 -0
  237. package/dist/registry/pinned-transport.js +717 -0
  238. package/dist/registry/providers/skills-sh.js +18 -6
  239. package/dist/registry/providers/static-index.js +20 -7
  240. package/dist/registry/resolve.js +53 -28
  241. package/dist/scripts/akm-migrate-node.js +19334 -52269
  242. package/dist/scripts/akm-migrate.js +19270 -51612
  243. package/dist/setup/registry-stash-loader.js +64 -20
  244. package/dist/setup/semantic-assets.js +9 -34
  245. package/dist/setup/setup.js +12 -30
  246. package/dist/setup/source-identity.js +17 -0
  247. package/dist/setup/steps/sources.js +36 -15
  248. package/dist/setup/steps/tasks.js +39 -11
  249. package/dist/sources/providers/git-provider.js +3 -3
  250. package/dist/sources/providers/npm.js +2 -2
  251. package/dist/sources/providers/provider-utils.js +4 -3
  252. package/dist/sources/providers/website.js +11 -7
  253. package/dist/sources/snapshot-fetchers/host-guard.js +9 -136
  254. package/dist/sources/snapshot-fetchers/website-ingest.js +25 -109
  255. package/dist/sources/website-url.js +73 -0
  256. package/dist/storage/engines/sqlite-migrations.js +81 -26
  257. package/dist/storage/managed-db.js +27 -24
  258. package/dist/storage/repositories/events-repository.js +3 -0
  259. package/dist/storage/repositories/index-connection.js +42 -10
  260. package/dist/storage/repositories/index-entries-repository.js +203 -229
  261. package/dist/storage/repositories/index-entry-mapper.js +8 -12
  262. package/dist/storage/repositories/index-entry-schema.js +255 -0
  263. package/dist/storage/repositories/index-fts-repository.js +64 -71
  264. package/dist/storage/repositories/index-llm-cache-repository.js +8 -13
  265. package/dist/storage/repositories/index-meta-repository.js +0 -11
  266. package/dist/storage/repositories/index-schema.js +74 -350
  267. package/dist/storage/repositories/index-utility-repository.js +12 -17
  268. package/dist/storage/repositories/index-vec-repository.js +56 -7
  269. package/dist/storage/repositories/proposals-repository.js +4 -127
  270. package/dist/storage/repositories/registry-cache.js +2 -1
  271. package/dist/storage/repositories/task-history-repository.js +20 -40
  272. package/dist/storage/repositories/workflow-runs-repository.js +228 -129
  273. package/dist/storage/sqlite-read-snapshot.js +148 -0
  274. package/dist/tasks/backends/cron.js +170 -42
  275. package/dist/tasks/backends/index.js +1 -1
  276. package/dist/tasks/backends/launchd.js +787 -202
  277. package/dist/tasks/backends/schtasks.js +282 -83
  278. package/dist/tasks/embedded.js +7 -7
  279. package/dist/tasks/frozen-script.js +50 -0
  280. package/dist/tasks/resolve-akm-bin.js +5 -1
  281. package/dist/tasks/runner.js +239 -251
  282. package/dist/tasks/runtime-v3.js +281 -0
  283. package/dist/tasks/scheduler-binding.js +272 -0
  284. package/dist/tasks/scheduler-invocation.js +57 -43
  285. package/dist/tasks/scheduler-sync.js +654 -0
  286. package/dist/tasks/source-v3.js +752 -0
  287. package/dist/tasks/standalone-script-entry.js +5 -0
  288. package/dist/tasks/task-id.js +29 -0
  289. package/dist/workflows/authoring/authoring.js +15 -32
  290. package/dist/workflows/exec/dispatch-redaction.js +14 -8
  291. package/dist/workflows/exec/exec-unit.js +7 -28
  292. package/dist/workflows/exec/frozen-judge.js +57 -89
  293. package/dist/workflows/exec/lowering-notices.js +23 -0
  294. package/dist/workflows/exec/native-executor.js +301 -458
  295. package/dist/workflows/exec/param-secrets.js +4 -3
  296. package/dist/workflows/exec/run-workflow.js +26 -32
  297. package/dist/workflows/exec/step-work.js +105 -109
  298. package/dist/workflows/exec/unit-dispatch.js +103 -27
  299. package/dist/workflows/exec/unit-writer.js +3 -3
  300. package/dist/workflows/exec/worktree.js +2 -2
  301. package/dist/workflows/ir/compile.js +86 -72
  302. package/dist/workflows/ir/environment-v4.js +328 -0
  303. package/dist/workflows/ir/freeze-v4.js +122 -0
  304. package/dist/workflows/ir/plan-hash.js +13 -7
  305. package/dist/workflows/ir/schema-v4.js +525 -0
  306. package/dist/workflows/ir/schema.js +25 -284
  307. package/dist/workflows/ir/source-freeze-v4.js +506 -0
  308. package/dist/workflows/parser.js +27 -24
  309. package/dist/workflows/program/schema.js +1 -2
  310. package/dist/workflows/renderer.js +42 -29
  311. package/dist/workflows/resource-limits.js +4 -5
  312. package/dist/workflows/runtime/agent-identity.js +11 -13
  313. package/dist/workflows/runtime/plan-classifier.js +8 -8
  314. package/dist/workflows/runtime/runs.js +27 -43
  315. package/dist/workflows/runtime/workflow-asset-loader.js +45 -205
  316. package/dist/workflows/source-files.js +373 -0
  317. package/dist/workflows/source-ir/compile.js +196 -0
  318. package/dist/workflows/source-ir/github-yaml.js +577 -0
  319. package/dist/workflows/source-ir/ordering.js +38 -0
  320. package/dist/workflows/source-ir/program.js +50 -0
  321. package/dist/workflows/source-ir/result.js +26 -0
  322. package/dist/workflows/source-ir/schema.js +772 -0
  323. package/dist/workflows/source-ir/semantics.js +242 -0
  324. package/dist/workflows/source-ir/uses.js +14 -0
  325. package/docs/README.md +2 -0
  326. package/docs/migration/README.md +3 -1
  327. package/docs/migration/release-notes/0.9.2.md +55 -0
  328. package/docs/migration/release-notes/README.md +5 -0
  329. package/docs/migration/v0.8-to-v0.9.md +76 -1077
  330. package/docs/migration/v0.9.0-troubleshooting.md +104 -516
  331. package/docs/migration/v0.9.1-to-v0.9.2.md +150 -0
  332. package/docs/reference/README.md +1 -0
  333. package/docs/reference/cli.md +230 -98
  334. package/docs/reference/configuration.md +159 -36
  335. package/docs/reference/data-and-telemetry.md +19 -1
  336. package/docs/reference/supported-formats.md +23 -3
  337. package/docs/reference/tasks.md +182 -0
  338. package/docs/reference/workflow-schema.md +91 -40
  339. package/docs/reference/workflows.md +33 -6
  340. package/package.json +10 -6
  341. package/schemas/akm-config.json +372 -224
  342. package/schemas/akm-task.json +324 -80
  343. package/schemas/akm-workflow.json +6 -9
  344. package/dist/core/migration-operation.js +0 -75
  345. package/dist/integrations/agent/model-aliases.js +0 -74
  346. package/dist/tasks/parser.js +0 -380
  347. package/dist/tasks/schema.js +0 -123
  348. package/dist/tasks/validator.js +0 -80
  349. package/dist/workflows/ir/freeze.js +0 -320
  350. package/dist/workflows/runtime/document-cache.js +0 -13
@@ -25,12 +25,10 @@
25
25
  * - Top-level uses `.passthrough()` so unknown future keys round-trip intact on
26
26
  * read; `sanitizeConfigForWrite` decides what to persist.
27
27
  * - Most nested sub-objects use `.catch(undefined)` so malformed entries are
28
- * silently dropped (matches the legacy parser's warn-and-ignore semantics for
29
- * field-level shape errors keeps cold-start working when a user has a
30
- * typo in their config).
31
- * - Two exceptions (hard-rejected): openviking source type and legacy
32
- * `stashes[]` key. Both have explicit migration paths; silently dropping
33
- * would mask user data loss.
28
+ * silently dropped to keep cold-start working when a user has a field-level
29
+ * typo in an optional section.
30
+ * - Unsupported top-level source shapes and provider kinds are hard-rejected;
31
+ * silently dropping them would mask user data loss.
34
32
  * - UNKNOWN-KEY POLICY: object schemas use passthrough (unknown keys are
35
33
  * preserved and ignored, NOT rejected). akm runs across multiple installed
36
34
  * versions sharing one config.json; a newer version writes keys an older
@@ -51,7 +49,7 @@ import { FeedbackConfigSchema } from "./schema/feedback.js";
51
49
  import { ImproveConfigSchema } from "./schema/improve.js";
52
50
  import { IndexConfigSchema } from "./schema/index-config.js";
53
51
  import { OutputConfigSchema } from "./schema/output.js";
54
- import { CURRENT_CONFIG_VERSION, engineName, GlobalModelAliasesSchema, nonEmptyString, nonNegativeNumber, } from "./schema/primitives.js";
52
+ import { CURRENT_CONFIG_VERSION, engineName, nonEmptyString, nonNegativeNumber } from "./schema/primitives.js";
55
53
  import { SearchConfigSchema } from "./schema/search.js";
56
54
  import { SetupConfigSchema } from "./schema/setup.js";
57
55
  import { BundlesConfigSchema, RegistryConfigEntrySchema } from "./schema/sources-bundles.js";
@@ -85,33 +83,21 @@ export const DefaultsSchema = z
85
83
  * with cross-field refinements (`.superRefine()`).
86
84
  *
87
85
  * 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.
86
+ * the removed parser's warn-and-drop tolerance was a source of silent
87
+ * configuration loss. There is no pre-schema compatibility transform.
91
88
  */
92
89
  export const AkmConfigShape = {
93
90
  configVersion: z.literal(CURRENT_CONFIG_VERSION),
94
91
  engines: EnginesSchema.optional(),
95
92
  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
93
  semanticSearchMode: z.enum(["off", "auto"]).default("off"),
106
94
  embedding: EmbeddingConnectionConfigSchema.optional(),
107
95
  index: IndexConfigSchema.optional(),
108
96
  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).
97
+ // `bundles` + `defaultBundle` are the only source configuration shape. The
98
+ // retired `stashDir`/`sources[]`/`installed[]` keys are rejected at load;
99
+ // there is no runtime config translator. `defaultBundle` names the primary
100
+ // bundle used for short-ref resolution.
115
101
  bundles: BundlesConfigSchema.optional(),
116
102
  defaultBundle: nonEmptyString.optional(),
117
103
  output: OutputConfigSchema.optional(),
@@ -128,17 +114,14 @@ export const AkmConfigShape = {
128
114
  };
129
115
  export const AkmConfigBaseSchema = z.object(AkmConfigShape).passthrough();
130
116
  /**
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.
117
+ * Per-key overrides for unsupported pre-cutover source shapes.
135
118
  */
136
119
  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`.",
120
+ stashDir: "stashDir is not supported; configure `bundles`, or use `akm config path --all` / `akm info` to inspect current paths.",
138
121
  };
139
122
  export const AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) => {
140
123
  const raw = config;
141
- for (const key of ["profiles", "llm", "agent", "features", "stashes"]) {
124
+ for (const key of ["profiles", "llm", "agent", "features", "stashes", "modelAliases"]) {
142
125
  if (key in raw) {
143
126
  ctx.addIssue({
144
127
  code: z.ZodIssueCode.custom,
@@ -157,19 +140,14 @@ export const AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) =>
157
140
  message: "bindings is not supported in 0.9.0 (Tier B); it is neither emitted nor accepted",
158
141
  });
159
142
  }
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.
143
+ // Only the current source shape enters the runtime. There is no config
144
+ // compatibility path; `bundles` + `defaultBundle` fully supersede these keys.
166
145
  for (const key of ["stashDir", "sources", "installed"]) {
167
146
  if (key in raw && raw[key] !== undefined) {
168
147
  ctx.addIssue({
169
148
  code: z.ZodIssueCode.custom,
170
149
  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`,
150
+ message: RETIRED_SOURCE_SHAPE_KEY_MESSAGES[key] ?? `${key} is not supported; configure the current bundles shape`,
173
151
  });
174
152
  }
175
153
  }
@@ -295,7 +273,7 @@ export const AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) =>
295
273
  }
296
274
  }
297
275
  const judgmentEngine = processConfig.judgment?.engine;
298
- if (judgmentEngine) {
276
+ if (processConfig.judgment?.enabled === true && judgmentEngine) {
299
277
  const engine = config.engines?.[judgmentEngine];
300
278
  if (!engine) {
301
279
  ctx.addIssue({
@@ -2,9 +2,8 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
- * Runtime helpers that derive {@link ConfiguredSource} values from the
6
- * persisted {@link SourceConfigEntry} / {@link InstalledBundle} shapes
7
- * in an {@link AkmConfig}.
5
+ * Runtime helpers that derive provider-ready and {@link ConfiguredSource}
6
+ * values from the current bundle map in an {@link AkmConfig}.
8
7
  */
9
8
  import { createHash } from "node:crypto";
10
9
  import path from "node:path";
@@ -20,15 +19,9 @@ export function bundleComponentConfig(bundle) {
20
19
  return components[0];
21
20
  }
22
21
  /**
23
- * Convert a `bundles` map (0.9.0 config-shape cutover, spec §10.1 / D-R5) into
24
- * the ordered {@link SourceConfigEntry} list the transitional runtime source
25
- * resolvers already consume `defaultBundle` first (primary), then map
26
- * insertion order (preserving today's installation-priority semantics, on which
27
- * D-R4 short-ref resolution depends). Each entry's `name` IS its bundle key, so
28
- * `deriveInstallations` re-derives the exact same installation id (D-R5 rule 1).
29
- *
30
- * Returns `undefined` for an old-shape config (no `bundles`), so callers fall
31
- * back to the pre-cutover `stashDir`/`sources[]`/`installed[]` resolution.
22
+ * Convert the current `bundles` map into its ordered provider projection:
23
+ * `defaultBundle` first, then map insertion order. Each entry's `name` is its
24
+ * bundle key. Returns `undefined` when no bundles map is configured.
32
25
  */
33
26
  /**
34
27
  * The resolved primary stash path — the `defaultBundle`'s filesystem `path`
@@ -83,9 +76,7 @@ export function bundleEntryToSourceEntry(key, bundle, isPrimary = false) {
83
76
  return { type: "git", url: normalizeInstalledGitRef("", bundle.git), ...base };
84
77
  }
85
78
  if (bundle.website && typeof bundle.website.url === "string") {
86
- // All non-`url` website-descriptor keys (maxPages/refresh/maxDepth + any
87
- // passthrough provider options) round-trip back to the runtime entry's
88
- // `options` bag, mirroring the pre-cutover `sources[].options` shape.
79
+ // All non-`url` website-descriptor keys become provider options.
89
80
  const { url, ...rest } = bundle.website;
90
81
  return {
91
82
  type: "website",
@@ -144,9 +135,9 @@ function normalizeInstalledGitRef(source, ref) {
144
135
  return requestedRef ? `${cloneUrl}/tree/${requestedRef}` : cloneUrl;
145
136
  }
146
137
  /**
147
- * Synthesize a stable identifier when a {@link SourceConfigEntry} omits its
148
- * `name`. Uses a short hash of the discriminating fields so two equivalent
149
- * entries collapse to the same generated name.
138
+ * Produce a stable internal identifier for a provider projection. Current
139
+ * bundle-derived entries always carry `name`; the hash protects manually
140
+ * constructed internal values.
150
141
  */
151
142
  function deriveBundleName(entry) {
152
143
  if (entry.name)
@@ -160,7 +151,7 @@ function deriveBundleName(entry) {
160
151
  return `${entry.type}-${hash}`;
161
152
  }
162
153
  /**
163
- * Convert a persisted {@link SourceConfigEntry} into the runtime
154
+ * Convert a provider-ready {@link SourceConfigEntry} into the runtime
164
155
  * {@link SourceSpec} discriminated union. Returns `undefined` when the entry
165
156
  * is missing the fields its provider type requires (e.g. a `filesystem`
166
157
  * entry with no `path`); callers should drop or warn for those.
@@ -189,8 +180,7 @@ export function parseSourceSpec(entry) {
189
180
  * Build the full ordered list of runtime {@link ConfiguredSource} values from a
190
181
  * loaded {@link AkmConfig}, resolved from `bundles` + `defaultBundle` (spec
191
182
  * §10.1): the `defaultBundle` (primary) first, then map insertion order. The
192
- * retired `stashDir`/`sources[]`/`installed[]` trio is no longer read here — a
193
- * pre-cutover config is normalized to bundles by the migrator before it loads.
183
+ * retired `stashDir`/`sources[]`/`installed[]` trio is never read or normalized.
194
184
  *
195
185
  * Entries with `enabled: false` are still emitted — callers decide whether to
196
186
  * honour the flag. Entries that fail {@link parseSourceSpec} drop silently.
@@ -180,11 +180,26 @@ export function configSet(config, dotted, raw) {
180
180
  if (!schema && !symbolicApiKey) {
181
181
  throw new UsageError(`Unknown config key: ${dotted}`, "INVALID_FLAG_VALUE", unknownKeyHint(dotted));
182
182
  }
183
- const value = path[0] === "engines" && path.length === 2
184
- ? parseObjectPatch(raw, dotted)
185
- : symbolicApiKey
186
- ? raw
187
- : coerceForSchema(schema, raw, dotted);
183
+ const judgmentObjectPath = isTriageJudgmentPath(path);
184
+ const value = judgmentObjectPath && raw === "null"
185
+ ? undefined
186
+ : path[0] === "engines" && path.length === 2
187
+ ? parseObjectPatch(raw, dotted)
188
+ : symbolicApiKey
189
+ ? raw
190
+ : coerceForSchema(schema, raw, dotted);
191
+ const existing = path.reduce((value, key) => {
192
+ if (value && typeof value === "object")
193
+ return value[key];
194
+ return undefined;
195
+ }, config);
196
+ // The judgment leaf supplies `enabled: true` when the field is omitted.
197
+ // Merge a JSON object patch with the existing value before that current
198
+ // schema transform,
199
+ // otherwise the synthesized default can overwrite an explicit false.
200
+ const candidate = judgmentObjectPath && isPlainObject(value)
201
+ ? deepMergeConfig(isPlainObject(existing) ? existing : {}, value)
202
+ : value;
188
203
  // Validate the coerced value against the leaf schema. This catches enum
189
204
  // mismatches, out-of-range numbers, schema-level shape errors (writable
190
205
  // npm/website sources via .superRefine, strict-mode unknown keys in nested
@@ -195,7 +210,7 @@ export function configSet(config, dotted, raw) {
195
210
  ? /^\$[A-Za-z_][A-Za-z0-9_]*$|^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/.test(raw)
196
211
  ? { success: true, data: value }
197
212
  : { success: false, error: { issues: [{ path: [], message: `apiKey must be $VAR or \${VAR}` }] } }
198
- : schema.safeParse(value);
213
+ : schema.safeParse(candidate);
199
214
  if (!parsed.success) {
200
215
  const lines = parsed.error.issues
201
216
  .map((i) => {
@@ -205,11 +220,6 @@ export function configSet(config, dotted, raw) {
205
220
  .join("\n");
206
221
  throw new UsageError(`Invalid value for ${dotted}:\n${lines}`, "INVALID_FLAG_VALUE");
207
222
  }
208
- const existing = path.reduce((value, key) => {
209
- if (value && typeof value === "object")
210
- return value[key];
211
- return undefined;
212
- }, config);
213
223
  const next = setPath(config, path, isPlainObject(existing) && isPlainObject(parsed.data) ? deepMergeConfig(existing, parsed.data) : parsed.data);
214
224
  // Targeted invariant: defaultWriteTarget must point at a configured bundle
215
225
  // (#464.a). Whole-config validation happens at save time; this check fires
@@ -223,6 +233,14 @@ export function configSet(config, dotted, raw) {
223
233
  }
224
234
  return next;
225
235
  }
236
+ function isTriageJudgmentPath(path) {
237
+ return (path.length === 6 &&
238
+ path[0] === "improve" &&
239
+ path[1] === "strategies" &&
240
+ path[3] === "processes" &&
241
+ path[4] === "triage" &&
242
+ path[5] === "judgment");
243
+ }
226
244
  /**
227
245
  * Unset the value at the dotted path. Removes the leaf key (and prunes empty
228
246
  * parent objects if they become empty). Returns a new config object.
@@ -411,8 +429,8 @@ function unsetPath(config, path) {
411
429
  */
412
430
  const RETIRED_KEY_HINTS = {
413
431
  stashDir: "stashDir was removed in 0.9; get the stash path from `akm config path --all` or `akm info`.",
414
- sources: "sources was replaced by bundles in 0.9; run `akm-migrate apply` on a pre-0.9 config to convert it.",
415
- installed: "installed was replaced by bundles in 0.9; run `akm-migrate apply` on a pre-0.9 config to convert it.",
432
+ sources: "sources is not supported; configure `bundles` instead.",
433
+ installed: "installed is not supported; configure `bundles` instead.",
416
434
  wikiName: "the wiki subsystem was removed in 0.9; wikis are ordinary knowledge assets now — see `akm import`.",
417
435
  wiki: "the wiki subsystem was removed in 0.9; wikis are ordinary knowledge assets now — see `akm import`.",
418
436
  llm: "llm was replaced by named engines configuration in 0.9; configure `engines` instead.",
@@ -4,19 +4,11 @@
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
6
6
  import { ConfigError } from "../errors.js";
7
- import { assertNoPendingMigrationOperation } from "../migration-operation.js";
8
7
  import { acquireConfigLock, backupExistingConfig, parseConfigText, readConfigText, withConfigLock, writeConfigAtomic, } from "./config-io.js";
9
8
  import { AkmConfigSchema, CURRENT_CONFIG_VERSION } from "./config-schema.js";
10
9
  import { bundlesToSourceEntries } from "./config-sources.js";
11
10
  import { deepMergeConfig } from "./deep-merge.js";
12
11
  export { stripJsonComments } from "./config-io.js";
13
- // requireLlmConfig / getDefaultLlmConfig moved to
14
- // integrations/agent/engine-resolution.ts (WI-9.8 KILL 3, D.3 edge A) — they
15
- // called that module's materializeLlmConnection/resolveLlmEngineUse, and that
16
- // module imported LlmConnectionConfig back from this file, closing a 2-file
17
- // cycle that also fused config.ts into the harness/agent-runtime SCC. This
18
- // file can no longer re-export them (a re-export is still a graph edge to
19
- // engine-resolution.ts) — import them from there directly.
20
12
  import { getConfigPath } from "../paths.js";
21
13
  import { warn } from "../warn.js";
22
14
  // Canonical harness-id source of truth (#565) — runtime value re-export.
@@ -74,7 +66,6 @@ export function resetConfigCache() {
74
66
  cachedConfig = undefined;
75
67
  }
76
68
  export function loadUserConfig() {
77
- assertNoPendingMigrationOperation();
78
69
  const configPath = getConfigPath();
79
70
  let stat;
80
71
  try {
@@ -124,6 +115,24 @@ export function loadUserConfig() {
124
115
  };
125
116
  return finalConfig;
126
117
  }
118
+ /**
119
+ * Acquire the existing config-write sentinel and read a fresh validated
120
+ * generation while keeping the sentinel held. Source update uses this to
121
+ * fence an audited bundle descriptor through publication: a cooperating
122
+ * config writer can commit either before this snapshot or after the update,
123
+ * never between the final generation check and index commit.
124
+ */
125
+ export function acquireConfigReadFence() {
126
+ const release = acquireConfigLock();
127
+ try {
128
+ cachedConfig = undefined;
129
+ return { config: loadUserConfig(), release };
130
+ }
131
+ catch (error) {
132
+ release();
133
+ throw error;
134
+ }
135
+ }
127
136
  /**
128
137
  * Parse raw config text and validate via Zod.
129
138
  * ({@link AkmConfigSchema}). Returns the merged-with-defaults AkmConfig.
@@ -153,11 +162,9 @@ export function parseAndValidateConfigText(text, sourcePath) {
153
162
  /**
154
163
  * The configured stash sources as an ordered {@link SourceConfigEntry} list.
155
164
  *
156
- * 0.9.0 (spec §10.1): the retired `stashDir`/`sources[]`/`installed[]` trio is
157
- * gone — every source is a `bundles.<slug>` entry. This derives the unified
158
- * source list from `bundles` (defaultBundle first, then map order), so callers
159
- * that iterated `sources[]` keep working over the new shape. Returns `[]` when
160
- * no bundles are configured.
165
+ * Every source is a `bundles.<slug>` entry. This derives the provider-ready
166
+ * source list from `bundles` (defaultBundle first, then map order). Returns
167
+ * `[]` when no bundles are configured.
161
168
  */
162
169
  export function getSources(config) {
163
170
  return bundlesToSourceEntries(config) ?? [];
@@ -181,13 +188,11 @@ export function saveConfig(config) {
181
188
  saveConfigReal(currentConfig);
182
189
  }
183
190
  function saveConfigReal(config) {
184
- assertNoPendingMigrationOperation();
185
191
  cachedConfig = undefined;
186
192
  const configPath = getConfigPath();
187
193
  const dir = path.dirname(configPath);
188
194
  fs.mkdirSync(dir, { recursive: true });
189
195
  withConfigLock(() => {
190
- assertNoPendingMigrationOperation();
191
196
  const validated = validateCompleteConfig(config);
192
197
  backupExistingConfig(configPath);
193
198
  writeConfigAtomic(configPath, sanitizeConfigForWrite(validated));
@@ -206,11 +211,9 @@ export function validateCompleteConfig(config) {
206
211
  * ordinary backup, and atomic write.
207
212
  */
208
213
  export function mutateConfig(mutate, options) {
209
- assertNoPendingMigrationOperation();
210
214
  cachedConfig = undefined;
211
215
  const configPath = getConfigPath();
212
216
  return withConfigLock(() => {
213
- assertNoPendingMigrationOperation();
214
217
  const text = readConfigText(configPath);
215
218
  if (text === undefined && options?.absentNoop) {
216
219
  return { config: { ...DEFAULT_CONFIG }, written: false };
@@ -233,12 +236,10 @@ export function mutateConfig(mutate, options) {
233
236
  * its stash, while preventing another config writer from racing the final save.
234
237
  */
235
238
  export async function mutateConfigWithPrecommit(mutate, precommit) {
236
- assertNoPendingMigrationOperation();
237
239
  cachedConfig = undefined;
238
240
  const configPath = getConfigPath();
239
241
  const release = acquireConfigLock();
240
242
  try {
241
- assertNoPendingMigrationOperation();
242
243
  const text = readConfigText(configPath);
243
244
  const current = text === undefined ? { ...DEFAULT_CONFIG } : parseAndValidateConfigText(text, configPath);
244
245
  const mutated = mutate(current);
@@ -346,12 +347,8 @@ export function resolveSecret(value) {
346
347
  * filtering out the reserved feature-section keys so callers don't mistake
347
348
  * `metadataEnhance` for a pass.
348
349
  */
349
- /**
350
- * Reserved well-known keys on IndexConfig that are NOT per-pass entries.
351
- * `indexBodyOpening` (stash-conventions SPEC-8) is a boolean feature flag, not
352
- * a pass section.
353
- */
354
- const INDEX_RESERVED_KEYS = new Set(["metadataEnhance", "indexBodyOpening"]);
350
+ /** Reserved well-known keys on IndexConfig that are NOT per-pass entries. */
351
+ const INDEX_RESERVED_KEYS = new Set(["metadataEnhance"]);
355
352
  export function getIndexPassConfig(config, passName) {
356
353
  if (!config)
357
354
  return undefined;
@@ -15,7 +15,7 @@ import { z } from "zod";
15
15
  // a config-schema ↔ config-types type cycle that collapses inference.
16
16
  import { HARNESS_AGENT_DISPATCH_IDS, VALID_HARNESS_IDS } from "../../../integrations/harnesses/ids.js";
17
17
  import { WORKFLOW_MAX_TIMEOUT_MS } from "../../../workflows/resource-limits.js";
18
- import { chatCompletionsEndpoint, ENV_REFERENCE_PATTERN, ExtraParamsSchema, engineName, LlmCapabilitiesSchema, ModelAliasMapSchema, nonEmptyString, positiveInt, } from "./primitives.js";
18
+ import { chatCompletionsEndpoint, ENV_REFERENCE_PATTERN, ExtraParamsSchema, engineName, LlmCapabilitiesSchema, nonEmptyString, positiveInt, } from "./primitives.js";
19
19
  /**
20
20
  * Engine-config timeouts share the workflow ceiling.
21
21
  *
@@ -29,11 +29,9 @@ const timeoutMsField = z.union([positiveInt.max(WORKFLOW_MAX_TIMEOUT_MS), z.null
29
29
  // ── Connection configs (LLM) ────────────────────────────────────────────────
30
30
  /**
31
31
  * OpenAI-compatible connection fields shared by named LLM engines and bounded
32
- * internal call helpers. `model` is required at schema level partial entries
33
- * created by `akm config set llm.endpoint <url>` (where model is left absent)
34
- * are normalized to `model: ""` *before* Zod sees them by the load-time
35
- * pre-Zod migrator hook, so this strict shape gates CLI writes without
36
- * breaking legacy load-time partial configs.
32
+ * internal call helpers. `model` is required at schema level: current loads and
33
+ * CLI writes reject a partial named engine rather than normalizing it through a
34
+ * pre-schema compatibility transform.
37
35
  */
38
36
  export const LlmConnectionConfigSchema = z
39
37
  .object({
@@ -49,6 +47,7 @@ export const LlmConnectionConfigSchema = z
49
47
  extraParams: ExtraParamsSchema.optional(),
50
48
  contextLength: positiveInt.optional(),
51
49
  enableThinking: z.boolean().optional(),
50
+ reasoningEffort: nonEmptyString.optional(),
52
51
  })
53
52
  .passthrough();
54
53
  export const LlmProfileConfigSchema = LlmConnectionConfigSchema.extend({
@@ -73,6 +72,7 @@ const LlmEngineSchema = z
73
72
  extraParams: ExtraParamsSchema.optional(),
74
73
  contextLength: positiveInt.optional(),
75
74
  enableThinking: z.boolean().optional(),
75
+ reasoningEffort: nonEmptyString.optional(),
76
76
  })
77
77
  .passthrough()
78
78
  .superRefine((value, ctx) => {
@@ -92,7 +92,6 @@ const AgentEngineSchema = z
92
92
  workspace: nonEmptyString.optional(),
93
93
  model: nonEmptyString.optional(),
94
94
  timeoutMs: timeoutMsField,
95
- modelAliases: ModelAliasMapSchema.optional(),
96
95
  llmEngine: engineName.optional(),
97
96
  })
98
97
  .passthrough()
@@ -108,6 +107,8 @@ const AgentEngineSchema = z
108
107
  "extraParams",
109
108
  "contextLength",
110
109
  "enableThinking",
110
+ "reasoningEffort",
111
+ "modelAliases",
111
112
  ]) {
112
113
  if (key in value)
113
114
  ctx.addIssue({ code: z.ZodIssueCode.custom, path: [key], message: `${key} is not valid on an agent engine` });
@@ -100,15 +100,32 @@ const extractTriageGateField = z
100
100
  })
101
101
  .passthrough()
102
102
  .optional();
103
- /** Triage process: LLM-as-judge triage-apply decision engine override. */
104
- const triageJudgmentField = z
103
+ const triageJudgmentErrorMap = (issue, ctx) => {
104
+ if (issue.code === z.ZodIssueCode.unrecognized_keys) {
105
+ const retired = issue.keys.find((key) => key === "mode" || key === "profile");
106
+ if (retired)
107
+ return { message: `${retired} is retired; use engine` };
108
+ }
109
+ return { message: ctx.defaultError };
110
+ };
111
+ // Judgment is an explicit opt-in surface, so invocation typos must fail closed.
112
+ // Keep the shared override schema lenient for ordinary cross-version config
113
+ // compatibility, while making this nested surface strict. `extraParams`
114
+ // remains the intentional arbitrary provider-parameter escape hatch.
115
+ const triageJudgmentLlmOverridesField = LlmInvocationOverridesSchema.strict();
116
+ const triageJudgmentObjectField = z
105
117
  .object({
118
+ enabled: z.boolean().optional(),
106
119
  engine: engineName.optional(),
107
120
  model: nonEmptyString.optional(),
108
121
  timeoutMs: z.union([positiveInt, z.null()]).optional(),
109
- llm: LlmInvocationOverridesSchema.optional(),
110
- })
111
- .passthrough()
122
+ llm: triageJudgmentLlmOverridesField.optional(),
123
+ }, { errorMap: triageJudgmentErrorMap })
124
+ .strict();
125
+ /** Triage process: explicit LLM-as-judge enablement and execution overrides. */
126
+ const triageJudgmentField = z
127
+ .union([z.boolean(), triageJudgmentObjectField])
128
+ .transform((value) => typeof value === "boolean" ? { enabled: value } : { ...value, enabled: value.enabled ?? true })
112
129
  .optional();
113
130
  /**
114
131
  * WS-3b: Anti-collapse guards (step 8). Prevents the consolidation pipeline
@@ -256,6 +273,13 @@ function checkRetiredProcessKeys(value, ctx) {
256
273
  ctx.addIssue({ code: z.ZodIssueCode.custom, path: [key], message: `${key} is retired; use engine` });
257
274
  }
258
275
  }
276
+ if ("judgement" in value) {
277
+ ctx.addIssue({
278
+ code: z.ZodIssueCode.custom,
279
+ path: ["judgement"],
280
+ message: "judgement is not a valid key; use judgment",
281
+ });
282
+ }
259
283
  const judgment = value.judgment;
260
284
  if (judgment) {
261
285
  for (const key of ["mode", "profile"]) {
@@ -99,14 +99,6 @@ const IndexDefaultsSchema = z
99
99
  * Index config is a union of reserved feature sections and per-pass entries.
100
100
  * Passthrough so per-pass entries (keyed by arbitrary pass names like `graph`,
101
101
  * `enrichment`) can live next to the reserved keys.
102
- *
103
- * Reserved scalar key `indexBodyOpening` (stash-conventions SPEC-8, default
104
- * false): when true, the metadata pass captures the first prose paragraph of
105
- * each markdown asset body into `entry.bodyOpening`, which folds into the
106
- * lowest-weight `content` FTS column and the embedding text. It is a boolean,
107
- * not a per-pass object — the preprocess below exempts it from the
108
- * object-shape check so it never routes into the per-pass catchall.
109
- *
110
102
  * The outer preprocess emits the legacy parser's actionable error messages
111
103
  * for the two most common type-shape mistakes:
112
104
  * - An array at the `index` block.
@@ -136,17 +128,6 @@ const IndexConfigRuntimeSchema = z.preprocess((raw, ctx) => {
136
128
  });
137
129
  return raw;
138
130
  }
139
- if (passName === "indexBodyOpening") {
140
- if (typeof value !== "boolean") {
141
- ctx.addIssue({
142
- code: z.ZodIssueCode.custom,
143
- message: "Invalid `index.indexBodyOpening`: expected a boolean (true to index the first body paragraph " +
144
- `of markdown assets into search). Got ${Array.isArray(value) ? "array" : typeof value}.`,
145
- });
146
- return raw;
147
- }
148
- continue;
149
- }
150
131
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
151
132
  ctx.addIssue({
152
133
  code: z.ZodIssueCode.custom,
@@ -160,14 +141,6 @@ const IndexConfigRuntimeSchema = z.preprocess((raw, ctx) => {
160
141
  .object({
161
142
  defaults: IndexDefaultsSchema.optional(),
162
143
  metadataEnhance: MetadataEnhanceSchema.optional(),
163
- indexBodyOpening: z
164
- .boolean()
165
- .optional()
166
- .describe("Index the first prose paragraph of each markdown asset body (capped at 280 chars) into the " +
167
- "lowest-weight `content` search column and the embedding text (default false). Secret/env files " +
168
- "and session-kind memories are never captured. Toggling the flag changes indexed text: run " +
169
- "`akm index --full` afterwards to re-extract every entry and regenerate embeddings, and re-mint " +
170
- "collapse-detector canary baselines via `bun scripts/refresh-canary-set.ts --refresh`."),
171
144
  })
172
145
  .catchall(IndexPassConfigSchema));
173
146
  // The runtime catchall correctly validates arbitrary pass objects, but its
@@ -53,29 +53,6 @@ export const ExtraParamsSchema = z.record(z.unknown()).superRefine((value, ctx)
53
53
  ctx.addIssue({ code: z.ZodIssueCode.custom, path: issue.path, message: issue.message });
54
54
  }
55
55
  });
56
- function normalizeAliasKeys(raw, ctx) {
57
- if (!raw || typeof raw !== "object" || Array.isArray(raw))
58
- return raw;
59
- const normalized = {};
60
- const originalByKey = new Map();
61
- for (const [key, value] of Object.entries(raw)) {
62
- const lower = key.toLowerCase();
63
- const previous = originalByKey.get(lower);
64
- if (previous !== undefined) {
65
- ctx.addIssue({
66
- code: z.ZodIssueCode.custom,
67
- path: [key],
68
- message: `alias collides case-insensitively with ${previous}`,
69
- });
70
- continue;
71
- }
72
- originalByKey.set(lower, key);
73
- normalized[lower] = value;
74
- }
75
- return normalized;
76
- }
77
- export const ModelAliasMapSchema = z.preprocess((raw, ctx) => normalizeAliasKeys(raw, ctx), z.record(z.string().min(1), z.string().min(1)));
78
- export const GlobalModelAliasesSchema = z.preprocess((raw, ctx) => normalizeAliasKeys(raw, ctx), z.record(z.string().min(1), z.record(z.string().min(1), z.string().min(1))));
79
56
  // ── Shared connection/invocation building blocks ────────────────────────────
80
57
  export const LlmCapabilitiesSchema = z
81
58
  .object({
@@ -90,5 +67,6 @@ export const LlmInvocationOverridesSchema = z
90
67
  extraParams: ExtraParamsSchema.optional(),
91
68
  contextLength: positiveInt.optional(),
92
69
  enableThinking: z.boolean().optional(),
70
+ reasoningEffort: nonEmptyString.optional(),
93
71
  })
94
72
  .passthrough();