akm-cli 0.9.1 → 0.9.2-alpha.1

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 (341) hide show
  1. package/CHANGELOG.md +88 -0
  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/tasks/core/extract.yml +6 -5
  12. package/dist/assets/tasks/core/improve.yml +6 -5
  13. package/dist/assets/tasks/core/index-refresh.yml +6 -5
  14. package/dist/assets/tasks/core/sync.yml +6 -5
  15. package/dist/assets/tasks/core/version-check.yml +6 -5
  16. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +6 -5
  17. package/dist/assets/tasks/improve/akm-improve-catchup.yml +6 -5
  18. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +6 -5
  19. package/dist/assets/tasks/improve/akm-improve-frequent.yml +6 -5
  20. package/dist/assets/tasks/improve/akm-improve-nightly.yml +6 -5
  21. package/dist/cli/confirm.js +2 -2
  22. package/dist/cli/parse-args.js +3 -24
  23. package/dist/cli/retired-commands.js +1 -1
  24. package/dist/cli/shared.js +2 -2
  25. package/dist/cli.js +11 -9
  26. package/dist/commands/agent/agent-dispatch.js +55 -89
  27. package/dist/commands/agent/contribute-cli.js +12 -45
  28. package/dist/commands/command/builtin-action.js +32 -0
  29. package/dist/commands/command/command-cli.js +99 -0
  30. package/dist/commands/command/command-execution.js +308 -0
  31. package/dist/commands/command/execution-source-loader.js +176 -0
  32. package/dist/commands/command/portable-template.js +60 -0
  33. package/dist/commands/config-cli.js +10 -4
  34. package/dist/commands/env/env.js +4 -2
  35. package/dist/commands/feedback-cli.js +1 -1
  36. package/dist/commands/health/checks.js +241 -29
  37. package/dist/commands/health/html-report.js +0 -14
  38. package/dist/commands/health/report-view-model.js +0 -1
  39. package/dist/commands/health/surfaces.js +6 -7
  40. package/dist/commands/health/types.js +0 -2
  41. package/dist/commands/health.js +63 -18
  42. package/dist/commands/improve/collapse-detector.js +2 -2
  43. package/dist/commands/improve/consolidate.js +251 -214
  44. package/dist/commands/improve/distill/promote-memory.js +71 -34
  45. package/dist/commands/improve/distill/quality-gate.js +17 -5
  46. package/dist/commands/improve/distill.js +232 -155
  47. package/dist/commands/improve/eligibility.js +112 -79
  48. package/dist/commands/improve/execution.js +57 -0
  49. package/dist/commands/improve/extract-cli.js +5 -5
  50. package/dist/commands/improve/extract.js +521 -342
  51. package/dist/commands/improve/improve-strategies.js +43 -14
  52. package/dist/commands/improve/improve.js +249 -29
  53. package/dist/commands/improve/loop-stages.js +11 -17
  54. package/dist/commands/improve/memory/memory-contradiction-detect.js +90 -66
  55. package/dist/commands/improve/outcome-loop.js +22 -38
  56. package/dist/commands/improve/planner.js +134 -0
  57. package/dist/commands/improve/preparation.js +730 -409
  58. package/dist/commands/improve/reflect.js +386 -223
  59. package/dist/commands/improve/run-context.js +3 -4
  60. package/dist/commands/improve/salience.js +6 -58
  61. package/dist/commands/improve/session-asset.js +12 -12
  62. package/dist/commands/lint/index.js +101 -29
  63. package/dist/commands/migrate-cli.js +11 -69
  64. package/dist/commands/migration-tool.js +6 -9
  65. package/dist/commands/models-cli.js +27 -0
  66. package/dist/commands/proposal/drain.js +258 -186
  67. package/dist/commands/proposal/proposal-cli.js +32 -10
  68. package/dist/commands/proposal/proposal.js +2 -5
  69. package/dist/commands/proposal/propose.js +192 -172
  70. package/dist/commands/proposal/repository.js +54 -91
  71. package/dist/commands/proposal/validators/proposal-validators.js +9 -7
  72. package/dist/commands/read/curate.js +10 -0
  73. package/dist/commands/read/registry-search.js +25 -9
  74. package/dist/commands/read/remember-cli.js +14 -2
  75. package/dist/commands/read/search.js +10 -4
  76. package/dist/commands/read/show.js +139 -153
  77. package/dist/commands/registry-cli.js +16 -7
  78. package/dist/commands/remember.js +33 -18
  79. package/dist/commands/sources/add-cli.js +19 -178
  80. package/dist/commands/sources/bundle-cli.js +15 -3
  81. package/dist/commands/sources/dangerous-env-audit.js +135 -0
  82. package/dist/commands/sources/info.js +2 -1
  83. package/dist/commands/sources/installed-stashes.js +835 -152
  84. package/dist/commands/sources/schema-repair.js +174 -95
  85. package/dist/commands/sources/self-update.js +30 -74
  86. package/dist/commands/sources/source-add.js +3 -5
  87. package/dist/commands/sources/sources-cli.js +2 -15
  88. package/dist/commands/sources/update-transaction.js +220 -0
  89. package/dist/commands/tasks/tasks-cli.js +3 -3
  90. package/dist/commands/tasks/tasks.js +736 -317
  91. package/dist/commands/workflow-cli.js +2 -2
  92. package/dist/core/adapter/adapters/agent-skills-adapter.js +3 -0
  93. package/dist/core/adapter/adapters/akm-adapter.js +83 -34
  94. package/dist/core/adapter/adapters/akm-lint.js +54 -39
  95. package/dist/core/adapter/adapters/akm-metadata.js +45 -45
  96. package/dist/core/adapter/adapters/akm-task-adapter.js +32 -49
  97. package/dist/core/adapter/adapters/akm-workflow-adapter.js +38 -23
  98. package/dist/core/adapter/adapters/dotenv-adapter.js +30 -1
  99. package/dist/core/adapter/adapters/generic-files-adapter.js +11 -0
  100. package/dist/core/adapter/adapters/index.js +0 -9
  101. package/dist/core/adapter/adapters/llm-wiki-adapter.js +4 -0
  102. package/dist/core/adapter/adapters/okf-adapter.js +4 -0
  103. package/dist/core/adapter/adapters/opencode-adapter.js +5 -8
  104. package/dist/core/adapter/adapters/tool-dir-shared.js +63 -6
  105. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -0
  106. package/dist/core/adapter/execution-source.js +308 -0
  107. package/dist/core/adapter/recognize-match.js +36 -13
  108. package/dist/core/adapter/registry.js +0 -9
  109. package/dist/core/asset/stash-meta.js +94 -4
  110. package/dist/core/common.js +6 -11
  111. package/dist/core/config/config-io.js +3 -3
  112. package/dist/core/config/config-schema.js +18 -40
  113. package/dist/core/config/config-sources.js +11 -21
  114. package/dist/core/config/config-walker.js +31 -13
  115. package/dist/core/config/config.js +21 -20
  116. package/dist/core/config/schema/engines.js +8 -7
  117. package/dist/core/config/schema/improve-processes.js +29 -5
  118. package/dist/core/config/schema/primitives.js +1 -23
  119. package/dist/core/config/schema/sources-bundles.js +13 -16
  120. package/dist/core/errors.js +2 -0
  121. package/dist/core/events.js +68 -32
  122. package/dist/core/extra-params.js +1 -0
  123. package/dist/core/improve-result.js +315 -0
  124. package/dist/core/lesson-lint.js +0 -6
  125. package/dist/core/maintenance-barrier.js +4 -4
  126. package/dist/core/network-policy.js +152 -0
  127. package/dist/core/paths.js +1 -1
  128. package/dist/core/recognition-util.js +4 -4
  129. package/dist/core/registry-url.js +456 -0
  130. package/dist/core/state/migrations.js +161 -47
  131. package/dist/core/state-db.js +453 -80
  132. package/dist/core/system-error.js +32 -0
  133. package/dist/core/time.js +2 -12
  134. package/dist/core/write-source.js +0 -18
  135. package/dist/execution/directory-identity.js +52 -0
  136. package/dist/execution/executable-identity.js +107 -0
  137. package/dist/execution/guarded-source.js +398 -0
  138. package/dist/execution/json.js +95 -0
  139. package/dist/{commands/health/types-session-log.js → execution/limits.js} +2 -1
  140. package/dist/execution/record.js +55 -0
  141. package/dist/execution/resolved-request.js +730 -0
  142. package/dist/execution/source.js +320 -0
  143. package/dist/indexer/bundle-identity-guard.js +5 -4
  144. package/dist/indexer/db/graph-db.js +33 -0
  145. package/dist/indexer/graph/graph-boost.js +3 -4
  146. package/dist/indexer/graph/graph-extraction.js +562 -373
  147. package/dist/indexer/index-written-assets.js +65 -34
  148. package/dist/indexer/indexer.js +443 -222
  149. package/dist/indexer/installations.js +6 -0
  150. package/dist/indexer/lookup/adapter-concept-owner.js +283 -0
  151. package/dist/indexer/passes/memory-inference.js +227 -174
  152. package/dist/indexer/scan/doc-to-entry.js +7 -9
  153. package/dist/indexer/scan/drain-dir.js +51 -23
  154. package/dist/indexer/search/db-search.js +98 -22
  155. package/dist/indexer/search/search-fields.js +1 -1
  156. package/dist/indexer/search/search-hit-enrichers.js +1 -1
  157. package/dist/indexer/search/search-source.js +7 -16
  158. package/dist/indexer/search/semantic-status.js +10 -1
  159. package/dist/indexer/usage/show-usage.js +105 -0
  160. package/dist/indexer/usage/usage-events.js +7 -2
  161. package/dist/indexer/walk/matchers.js +40 -10
  162. package/dist/indexer/walk/path-resolver.js +5 -2
  163. package/dist/indexer/walk/walker.js +20 -2
  164. package/dist/integrations/agent/builder-shared.js +3 -6
  165. package/dist/integrations/agent/conversation-fallback.js +16 -0
  166. package/dist/integrations/agent/engine-resolution.js +87 -87
  167. package/dist/integrations/agent/execution-cascade.js +566 -0
  168. package/dist/integrations/agent/execution-definitions.js +211 -0
  169. package/dist/integrations/agent/execution-lowering.js +811 -0
  170. package/dist/integrations/agent/execution-preparation.js +67 -0
  171. package/dist/integrations/agent/index.js +0 -2
  172. package/dist/integrations/agent/inline-execution.js +74 -0
  173. package/dist/integrations/agent/model-map.js +515 -0
  174. package/dist/integrations/agent/persona-fallback.js +30 -0
  175. package/dist/integrations/agent/request-lowering.js +186 -0
  176. package/dist/integrations/agent/runner-dispatch.js +230 -37
  177. package/dist/integrations/agent/runner.js +12 -83
  178. package/dist/integrations/harnesses/aider/agent-builder.js +8 -0
  179. package/dist/integrations/harnesses/aider/index.js +0 -1
  180. package/dist/integrations/harnesses/amazonq/agent-builder.js +8 -0
  181. package/dist/integrations/harnesses/amazonq/index.js +0 -1
  182. package/dist/integrations/harnesses/claude/agent-builder.js +14 -1
  183. package/dist/integrations/harnesses/claude/index.js +1 -5
  184. package/dist/integrations/harnesses/claude/session-log.js +3 -33
  185. package/dist/integrations/harnesses/codex/agent-builder.js +8 -0
  186. package/dist/integrations/harnesses/codex/index.js +0 -1
  187. package/dist/integrations/harnesses/copilot/agent-builder.js +8 -0
  188. package/dist/integrations/harnesses/copilot/index.js +0 -1
  189. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -0
  190. package/dist/integrations/harnesses/gemini/index.js +0 -1
  191. package/dist/integrations/harnesses/index.js +4 -44
  192. package/dist/integrations/harnesses/opencode/agent-builder.js +16 -9
  193. package/dist/integrations/harnesses/opencode/index.js +0 -2
  194. package/dist/integrations/harnesses/opencode/session-log.js +14 -204
  195. package/dist/integrations/harnesses/opencode-sdk/harness.js +12 -1
  196. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +40 -42
  197. package/dist/integrations/harnesses/openhands/agent-builder.js +8 -0
  198. package/dist/integrations/harnesses/openhands/index.js +0 -1
  199. package/dist/integrations/harnesses/pi/agent-builder.js +8 -0
  200. package/dist/integrations/harnesses/pi/index.js +0 -1
  201. package/dist/integrations/harnesses/shared.js +0 -1
  202. package/dist/integrations/harnesses/types.js +1 -3
  203. package/dist/integrations/lockfile.js +82 -79
  204. package/dist/integrations/session-logs/index.js +6 -17
  205. package/dist/integrations/session-logs/provider-base.js +1 -29
  206. package/dist/llm/client.js +10 -5
  207. package/dist/llm/embedder.js +6 -7
  208. package/dist/llm/embedders/local.js +37 -88
  209. package/dist/llm/embedders/types.js +1 -1
  210. package/dist/llm/graph-extract.js +75 -50
  211. package/dist/llm/index-passes.js +43 -5
  212. package/dist/llm/memory-infer.js +8 -6
  213. package/dist/llm/metadata-enhance.js +5 -3
  214. package/dist/llm/structured-call.js +122 -25
  215. package/dist/output/format-exempt.js +1 -1
  216. package/dist/output/render-registry.js +0 -16
  217. package/dist/output/renderers.js +12 -7
  218. package/dist/output/shapes/curate.js +1 -0
  219. package/dist/output/shapes/helpers.js +10 -2
  220. package/dist/output/shapes/passthrough.js +2 -0
  221. package/dist/output/text/command-format.js +28 -32
  222. package/dist/output/text/health-format.js +1 -29
  223. package/dist/output/text/migrate.js +6 -56
  224. package/dist/output/text/proposal-format.js +16 -1
  225. package/dist/output/text/workflow-format.js +16 -0
  226. package/dist/registry/network.js +279 -0
  227. package/dist/registry/pinned-request-helper.js +247 -0
  228. package/dist/registry/pinned-transport.js +717 -0
  229. package/dist/registry/providers/skills-sh.js +18 -6
  230. package/dist/registry/providers/static-index.js +20 -7
  231. package/dist/registry/resolve.js +53 -28
  232. package/dist/scripts/akm-migrate-node.js +19122 -52218
  233. package/dist/scripts/akm-migrate.js +19064 -51567
  234. package/dist/setup/registry-stash-loader.js +64 -20
  235. package/dist/setup/semantic-assets.js +9 -34
  236. package/dist/setup/setup.js +12 -30
  237. package/dist/setup/source-identity.js +17 -0
  238. package/dist/setup/steps/sources.js +36 -15
  239. package/dist/setup/steps/tasks.js +39 -11
  240. package/dist/sources/providers/git-provider.js +3 -3
  241. package/dist/sources/providers/npm.js +2 -2
  242. package/dist/sources/providers/provider-utils.js +4 -3
  243. package/dist/sources/providers/website.js +11 -7
  244. package/dist/sources/snapshot-fetchers/host-guard.js +9 -136
  245. package/dist/sources/snapshot-fetchers/website-ingest.js +25 -109
  246. package/dist/sources/website-url.js +73 -0
  247. package/dist/storage/engines/sqlite-migrations.js +81 -26
  248. package/dist/storage/managed-db.js +27 -24
  249. package/dist/storage/repositories/events-repository.js +3 -0
  250. package/dist/storage/repositories/index-connection.js +42 -10
  251. package/dist/storage/repositories/index-entries-repository.js +167 -207
  252. package/dist/storage/repositories/index-entry-mapper.js +8 -12
  253. package/dist/storage/repositories/index-entry-schema.js +255 -0
  254. package/dist/storage/repositories/index-fts-repository.js +10 -10
  255. package/dist/storage/repositories/index-llm-cache-repository.js +8 -13
  256. package/dist/storage/repositories/index-meta-repository.js +0 -11
  257. package/dist/storage/repositories/index-schema.js +71 -342
  258. package/dist/storage/repositories/index-utility-repository.js +12 -17
  259. package/dist/storage/repositories/index-vec-repository.js +1 -1
  260. package/dist/storage/repositories/proposals-repository.js +4 -127
  261. package/dist/storage/repositories/registry-cache.js +2 -1
  262. package/dist/storage/repositories/task-history-repository.js +20 -40
  263. package/dist/storage/repositories/workflow-runs-repository.js +228 -129
  264. package/dist/storage/sqlite-read-snapshot.js +148 -0
  265. package/dist/tasks/backends/cron.js +170 -42
  266. package/dist/tasks/backends/index.js +1 -1
  267. package/dist/tasks/backends/launchd.js +787 -202
  268. package/dist/tasks/backends/schtasks.js +282 -83
  269. package/dist/tasks/embedded.js +7 -7
  270. package/dist/tasks/frozen-script.js +50 -0
  271. package/dist/tasks/resolve-akm-bin.js +5 -1
  272. package/dist/tasks/runner.js +239 -251
  273. package/dist/tasks/runtime-v3.js +281 -0
  274. package/dist/tasks/scheduler-binding.js +272 -0
  275. package/dist/tasks/scheduler-invocation.js +57 -43
  276. package/dist/tasks/scheduler-sync.js +654 -0
  277. package/dist/tasks/source-v3.js +752 -0
  278. package/dist/tasks/standalone-script-entry.js +5 -0
  279. package/dist/tasks/task-id.js +29 -0
  280. package/dist/workflows/authoring/authoring.js +15 -32
  281. package/dist/workflows/exec/dispatch-redaction.js +14 -8
  282. package/dist/workflows/exec/exec-unit.js +7 -28
  283. package/dist/workflows/exec/frozen-judge.js +57 -89
  284. package/dist/workflows/exec/lowering-notices.js +23 -0
  285. package/dist/workflows/exec/native-executor.js +301 -458
  286. package/dist/workflows/exec/param-secrets.js +4 -3
  287. package/dist/workflows/exec/run-workflow.js +26 -32
  288. package/dist/workflows/exec/step-work.js +105 -109
  289. package/dist/workflows/exec/unit-dispatch.js +103 -27
  290. package/dist/workflows/exec/unit-writer.js +3 -3
  291. package/dist/workflows/exec/worktree.js +2 -2
  292. package/dist/workflows/ir/compile.js +86 -72
  293. package/dist/workflows/ir/environment-v4.js +328 -0
  294. package/dist/workflows/ir/freeze-v4.js +122 -0
  295. package/dist/workflows/ir/plan-hash.js +13 -7
  296. package/dist/workflows/ir/schema-v4.js +525 -0
  297. package/dist/workflows/ir/schema.js +25 -284
  298. package/dist/workflows/ir/source-freeze-v4.js +506 -0
  299. package/dist/workflows/parser.js +27 -24
  300. package/dist/workflows/program/schema.js +1 -2
  301. package/dist/workflows/renderer.js +42 -29
  302. package/dist/workflows/resource-limits.js +4 -5
  303. package/dist/workflows/runtime/agent-identity.js +11 -13
  304. package/dist/workflows/runtime/plan-classifier.js +8 -8
  305. package/dist/workflows/runtime/runs.js +27 -43
  306. package/dist/workflows/runtime/workflow-asset-loader.js +45 -205
  307. package/dist/workflows/source-files.js +373 -0
  308. package/dist/workflows/source-ir/compile.js +196 -0
  309. package/dist/workflows/source-ir/github-yaml.js +577 -0
  310. package/dist/workflows/source-ir/ordering.js +38 -0
  311. package/dist/workflows/source-ir/program.js +50 -0
  312. package/dist/workflows/source-ir/result.js +26 -0
  313. package/dist/workflows/source-ir/schema.js +772 -0
  314. package/dist/workflows/source-ir/semantics.js +242 -0
  315. package/dist/workflows/source-ir/uses.js +14 -0
  316. package/docs/README.md +2 -0
  317. package/docs/migration/README.md +3 -1
  318. package/docs/migration/release-notes/0.9.2.md +55 -0
  319. package/docs/migration/release-notes/README.md +5 -0
  320. package/docs/migration/v0.8-to-v0.9.md +76 -1077
  321. package/docs/migration/v0.9.0-troubleshooting.md +104 -516
  322. package/docs/migration/v0.9.1-to-v0.9.2.md +150 -0
  323. package/docs/reference/README.md +1 -0
  324. package/docs/reference/cli.md +230 -98
  325. package/docs/reference/configuration.md +153 -27
  326. package/docs/reference/data-and-telemetry.md +19 -1
  327. package/docs/reference/supported-formats.md +23 -3
  328. package/docs/reference/tasks.md +182 -0
  329. package/docs/reference/workflow-schema.md +91 -40
  330. package/docs/reference/workflows.md +33 -6
  331. package/package.json +10 -6
  332. package/schemas/akm-config.json +372 -216
  333. package/schemas/akm-task.json +324 -80
  334. package/schemas/akm-workflow.json +6 -9
  335. package/dist/core/migration-operation.js +0 -75
  336. package/dist/integrations/agent/model-aliases.js +0 -74
  337. package/dist/tasks/parser.js +0 -380
  338. package/dist/tasks/schema.js +0 -123
  339. package/dist/tasks/validator.js +0 -80
  340. package/dist/workflows/ir/freeze.js +0 -320
  341. 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);
@@ -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"]) {
@@ -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();
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { z } from "zod";
10
10
  import { isBundleSlug } from "../../asset/asset-ref.js";
11
+ import { hasRegistryUrlCredentials, REGISTRY_CREDENTIALS_UNSUPPORTED } from "../../registry-url.js";
11
12
  import { httpUrl, nonEmptyString, positiveInt } from "./primitives.js";
12
13
  // ── Sources / registries / installed ────────────────────────────────────────
13
14
  const SourceConfigEntryOptionsSchema = z.record(z.unknown());
@@ -49,7 +50,11 @@ export const SourceConfigEntrySchema = z
49
50
  });
50
51
  export const RegistryConfigEntrySchema = z
51
52
  .object({
52
- url: httpUrl,
53
+ url: httpUrl.superRefine((value, ctx) => {
54
+ if (hasRegistryUrlCredentials(value)) {
55
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: REGISTRY_CREDENTIALS_UNSUPPORTED });
56
+ }
57
+ }),
53
58
  name: z.string().min(1).optional(),
54
59
  enabled: z.boolean().optional(),
55
60
  provider: z.string().min(1).optional(),
@@ -58,9 +63,8 @@ export const RegistryConfigEntrySchema = z
58
63
  .passthrough();
59
64
  // ── Bundles (0.9.0 config-shape cutover, spec §10.1 / D-R5) ─────────────────
60
65
  //
61
- // `bundles` + `defaultBundle` are the 0.9.0 desired-configuration shape that
62
- // supersedes the pre-cutover `stashDir` / `sources[]` / `installed[]` trio. Each
63
- // bundle entry carries ONE source descriptor (`path` | `git` | `website` | `npm`
66
+ // `bundles` + `defaultBundle` are the desired-configuration shape. Each bundle
67
+ // entry carries ONE source descriptor (`path` | `git` | `website` | `npm`
64
68
  // — mirroring today's source types), an optional `writable`, an optional
65
69
  // `registryId` locator (the original registry install id, preserved verbatim so
66
70
  // a non-slug-legal id like `github:owner/repo` is not lost when its slug-legal
@@ -69,10 +73,7 @@ export const RegistryConfigEntrySchema = z
69
73
  // machinery). The map KEY is the workspace bundle slug (spec §11.1 charset: no
70
74
  // `/`, `:`, `.`, `#`, whitespace), validated with {@link isBundleSlug}.
71
75
  //
72
- // The config migrator ({@link migrateConfigSourcesToBundles}) emits these keyed
73
- // by exactly what `deriveInstallations` derives today (D-R5). `bindings` (spec
74
- // §10.1) is Tier B and is NEVER accepted here (the top-level superRefine rejects
75
- // it) — it is not part of the 0.9.0 config-shape cutover.
76
+ // `bindings` is not accepted here; the top-level schema rejects it.
76
77
  /** Website source descriptor for a bundle entry (spec §10.1). */
77
78
  const BundleWebsiteDescriptorSchema = z
78
79
  .object({
@@ -110,15 +111,11 @@ export const BundleConfigEntrySchema = z
110
111
  npm: z.string().min(1).optional(),
111
112
  writable: z.boolean().optional(),
112
113
  // Opt a bundle out of indexing, search, refresh, and write targeting
113
- // without deleting it. Carried over from the pre-cutover `sources[].enabled`
114
- // flag, which the runtime still honors on the derived source entry
115
- // (`write-source.ts`, `search-source.ts`); without it here, migrating a
116
- // disabled source would silently reactivate it.
114
+ // without deleting it. The runtime honors the derived value in write and
115
+ // search source selection.
117
116
  enabled: z.boolean().optional(),
118
- // The original registry install id when the bundle KEY was slug-derived from
119
- // it (e.g. registryId `github:owner/repo` → key `repo`). Preserved so the
120
- // source locator survives the config-shape migration (D-R5). Absent when the
121
- // bundle key already equals the source's stable id.
117
+ // The registry install id when the bundle key was slug-derived from it
118
+ // (e.g. registryId `github:owner/repo` → key `repo`).
122
119
  registryId: z.string().min(1).optional(),
123
120
  components: z.record(z.string().min(1), BundleComponentConfigSchema).optional(),
124
121
  })
@@ -10,12 +10,14 @@ const CONFIG_HINTS = {
10
10
  STASH_DIR_NOT_A_DIRECTORY: "The configured default bundle path exists but isn't a directory. Update it to point at a folder.",
11
11
  STASH_DIR_UNREADABLE: "Check the path exists and your user has read permission, or update the default bundle path.",
12
12
  DATA_DIR_UNREADABLE: "The data directory is not readable by the user running akm. Check its owner and mode, or point AKM_DATA_DIR / XDG_DATA_HOME somewhere this user owns.",
13
+ INDEX_SCHEMA_INCOMPATIBLE: "Run `akm index --full` to rebuild the derived index from the currently materialized sources.",
13
14
  EMBEDDING_NOT_CONFIGURED: 'Run `akm config set embedding \'{"endpoint":"...","model":"..."}\'` to enable embeddings.',
14
15
  LLM_NOT_CONFIGURED: 'Run `akm setup` or configure an `engines` entry with `kind: "llm"`, then select it with `defaults.llmEngine`.',
15
16
  TEST_ISOLATION_MISSING: "Under bun test, when AKM_BUNDLE_DIR is set you MUST also set XDG_DATA_HOME (or AKM_DATA_DIR) and XDG_STATE_HOME (or AKM_STATE_DIR) to temp directories so the test does not touch the developer's real ~/.local/share/akm or ~/.local/state/akm.",
16
17
  SETUP_TMP_STASH_REFUSED: "Use a persistent directory, or set AKM_FORCE_SETUP_TMP_STASH=1 to opt in to a sandboxed setup (setup also pre-sets AKM_BUNDLE_DIR so config and cache writes auto-isolate into $stashDir/.akm/ — host config is preserved).",
17
18
  UNSAFE_STASH_DIR: "Choose a path inside your home directory (e.g. ~/akm) or another empty workspace. The bundle directory cannot be the filesystem root, your home directory itself, or a sensitive system path like /etc, /var, ~/.config, or ~/.ssh.",
18
19
  UNKNOWN_IMPROVE_STRATEGY: "Pass one of the listed strategy names to `--strategy`, or define it under `improve.strategies`. Names are case-sensitive.",
20
+ EXECUTION_NOT_AUTHORIZED: "Change the selected tools or update the machine/user execution policy, then retry.",
19
21
  };
20
22
  /** Default hint for each UsageError code. */
21
23
  const USAGE_HINTS = {