akm-cli 0.9.17-alpha.2 → 0.9.17-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/CHANGELOG.md +756 -0
  2. package/dist/akm +94 -196
  3. package/dist/cli/shared.js +6 -2
  4. package/dist/cli.js +22 -9
  5. package/dist/commands/agent/agent-dispatch.js +1 -1
  6. package/dist/commands/command/command-execution.js +24 -62
  7. package/dist/commands/feedback-cli.js +0 -1
  8. package/dist/commands/health/accept-rate.js +2 -2
  9. package/dist/commands/health/checks.js +30 -75
  10. package/dist/commands/health/config-skew.js +38 -0
  11. package/dist/commands/health/egress.js +54 -0
  12. package/dist/commands/health/html-report.js +0 -38
  13. package/dist/commands/health/improve-metrics.js +123 -562
  14. package/dist/commands/health/plugin-staleness.js +53 -3
  15. package/dist/commands/health/renderers.js +12 -4
  16. package/dist/commands/health/report-view-model.js +11 -106
  17. package/dist/commands/health/types-improve.js +4 -19
  18. package/dist/commands/health/windows.js +64 -73
  19. package/dist/commands/health.js +122 -143
  20. package/dist/commands/improve/consolidate/chunking.js +25 -100
  21. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  22. package/dist/commands/improve/consolidate.js +538 -1075
  23. package/dist/commands/improve/content-hash.js +16 -24
  24. package/dist/commands/improve/distill/content-repair.js +18 -100
  25. package/dist/commands/improve/distill-guards.js +20 -81
  26. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  27. package/dist/commands/improve/distill.js +608 -1075
  28. package/dist/commands/improve/eligibility.js +126 -400
  29. package/dist/commands/improve/execution.js +3 -5
  30. package/dist/commands/improve/extract.js +487 -1046
  31. package/dist/commands/improve/feedback-valence.js +0 -25
  32. package/dist/commands/improve/improve-cli.js +29 -166
  33. package/dist/commands/improve/improve-result-file.js +10 -66
  34. package/dist/commands/improve/improve-strategies.js +12 -7
  35. package/dist/commands/improve/improve-usage-report.js +18 -64
  36. package/dist/commands/improve/improve.js +443 -1063
  37. package/dist/commands/improve/ledger.js +114 -0
  38. package/dist/commands/improve/locks.js +2 -8
  39. package/dist/commands/improve/loop-stages.js +459 -1172
  40. package/dist/commands/improve/memory/derived-ref.js +12 -77
  41. package/dist/commands/improve/memory/memory-belief.js +14 -118
  42. package/dist/commands/improve/memory/memory-improve.js +4 -3
  43. package/dist/commands/improve/outcome-loop.js +28 -156
  44. package/dist/commands/improve/planner.js +5 -10
  45. package/dist/commands/improve/preparation.js +851 -2339
  46. package/dist/commands/improve/proactive-maintenance.js +34 -101
  47. package/dist/commands/improve/reflect-noise.js +104 -280
  48. package/dist/commands/improve/reflect.js +621 -1367
  49. package/dist/commands/improve/salience.js +46 -232
  50. package/dist/commands/improve/session-asset.js +19 -100
  51. package/dist/commands/improve/stage.js +323 -0
  52. package/dist/commands/proposal/drain.js +251 -644
  53. package/dist/commands/proposal/proposal-cli.js +3 -18
  54. package/dist/commands/proposal/proposal-types.js +20 -41
  55. package/dist/commands/proposal/proposal.js +1 -2
  56. package/dist/commands/proposal/propose.js +134 -160
  57. package/dist/commands/proposal/repository.js +502 -1487
  58. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  59. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  60. package/dist/commands/proposal/validators/proposals.js +13 -89
  61. package/dist/commands/read/curate.js +63 -413
  62. package/dist/commands/read/search-cli.js +16 -33
  63. package/dist/commands/read/search.js +17 -23
  64. package/dist/commands/read/show.js +2 -13
  65. package/dist/commands/sources/bundle-cli.js +25 -2
  66. package/dist/commands/sources/bundle-config-ops.js +7 -0
  67. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  68. package/dist/commands/sources/info.js +2 -11
  69. package/dist/commands/sources/installed-stashes.js +197 -746
  70. package/dist/commands/sources/schema-repair.js +98 -129
  71. package/dist/commands/sources/source-add.js +62 -12
  72. package/dist/commands/sources/stash-cli.js +1 -1
  73. package/dist/commands/tasks/explain.js +10 -13
  74. package/dist/commands/tasks/tasks-cli.js +9 -8
  75. package/dist/commands/tasks/tasks.js +326 -930
  76. package/dist/commands/tasks/validate.js +42 -21
  77. package/dist/commands/workflow/plan.js +22 -29
  78. package/dist/commands/workflow-cli.js +4 -4
  79. package/dist/core/adapter/adapters/akm-adapter.js +0 -1
  80. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  81. package/dist/core/adapter/adapters/akm-metadata.js +11 -12
  82. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  83. package/dist/core/adapter/execution-source.js +17 -29
  84. package/dist/core/asset/resolve-ref.js +1 -1
  85. package/dist/core/bundle-id.js +42 -5
  86. package/dist/core/bundle-rename.js +291 -0
  87. package/dist/core/config/config-io.js +1 -2
  88. package/dist/core/config/config-schema.js +1 -33
  89. package/dist/core/config/config-walker.js +1 -1
  90. package/dist/core/config/config.js +163 -68
  91. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  92. package/dist/core/config/schema/embedding.js +20 -5
  93. package/dist/core/config/schema/engines.js +5 -0
  94. package/dist/core/config/schema/execution.js +1 -1
  95. package/dist/core/config/schema/experimental.js +1 -1
  96. package/dist/core/config/schema/improve-processes.js +21 -95
  97. package/dist/core/config/schema/improve.js +4 -42
  98. package/dist/core/config/schema/scheduler.js +12 -12
  99. package/dist/core/config/schema/search.js +6 -22
  100. package/dist/core/env-secret-ref.js +0 -1
  101. package/dist/core/errors.js +8 -9
  102. package/dist/core/file-lock.js +76 -173
  103. package/dist/core/logs-db.js +2 -2
  104. package/dist/core/paths.js +0 -27
  105. package/dist/core/redaction.js +109 -2
  106. package/dist/core/run-lock.js +2 -5
  107. package/dist/core/spawn-env.js +1 -1
  108. package/dist/core/state/migrations.js +108 -61
  109. package/dist/core/state-db-scope.js +2 -4
  110. package/dist/core/state-db.js +126 -692
  111. package/dist/core/type-presentation.js +1 -9
  112. package/dist/core/write-source.js +293 -1012
  113. package/dist/execution/input-contract.js +1 -1
  114. package/dist/execution/resolved-request.js +135 -689
  115. package/dist/execution/source.js +63 -257
  116. package/dist/execution/target-ref.js +1 -1
  117. package/dist/indexer/bundle-identity-guard.js +2 -2
  118. package/dist/indexer/db/graph-db.js +106 -46
  119. package/dist/indexer/ensure-index.js +44 -85
  120. package/dist/indexer/graph/graph-extraction.js +340 -562
  121. package/dist/indexer/graph/graph-related.js +130 -0
  122. package/dist/indexer/index-rebuild-lock.js +3 -11
  123. package/dist/indexer/index-writer-lock.js +8 -17
  124. package/dist/indexer/index-written-assets.js +139 -151
  125. package/dist/indexer/indexer.js +524 -846
  126. package/dist/indexer/materialize-embeddings.js +60 -397
  127. package/dist/indexer/passes/memory-inference.js +81 -90
  128. package/dist/indexer/passes/metadata.js +132 -200
  129. package/dist/indexer/read-preflight.js +0 -7
  130. package/dist/indexer/scan/doc-to-entry.js +1 -3
  131. package/dist/indexer/scan/drain-dir.js +1 -1
  132. package/dist/indexer/search/db-search.js +181 -590
  133. package/dist/indexer/search/fts-query.js +30 -41
  134. package/dist/indexer/search/ranking.js +28 -154
  135. package/dist/indexer/search/search-attribution.js +12 -32
  136. package/dist/indexer/search/search-fields.js +11 -15
  137. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  138. package/dist/indexer/search/search-source.js +1 -4
  139. package/dist/indexer/usage/usage-events.js +2 -7
  140. package/dist/integrations/agent/engine-fallback.js +23 -40
  141. package/dist/integrations/agent/engine-resolution.js +93 -183
  142. package/dist/integrations/agent/execution.js +507 -0
  143. package/dist/integrations/agent/model-map.js +28 -156
  144. package/dist/integrations/agent/request-lowering.js +66 -141
  145. package/dist/integrations/agent/runner-dispatch.js +143 -321
  146. package/dist/integrations/agent/runner.js +54 -14
  147. package/dist/integrations/lockfile.js +53 -101
  148. package/dist/llm/embedders/deterministic.js +2 -3
  149. package/dist/llm/embedders/profile.js +71 -0
  150. package/dist/llm/embedders/remote.js +10 -15
  151. package/dist/llm/graph-extract.js +3 -12
  152. package/dist/llm/index-passes.js +3 -5
  153. package/dist/llm/memory-infer.js +1 -2
  154. package/dist/llm/metadata-enhance.js +1 -2
  155. package/dist/llm/structured-call.js +5 -24
  156. package/dist/output/generic-render.js +23 -11
  157. package/dist/output/html-render.js +13 -10
  158. package/dist/output/render-registry.js +3 -32
  159. package/dist/output/shapes/helpers.js +2 -34
  160. package/dist/output/shapes/passthrough.js +1 -9
  161. package/dist/{indexer/search/ranking-types.js → output/text/bundle-rename.js} +4 -1
  162. package/dist/output/text/command-format.js +60 -23
  163. package/dist/output/text/helpers.js +1 -1
  164. package/dist/output/text/migrate.js +5 -14
  165. package/dist/output/text/proposal-format.js +1 -2
  166. package/dist/output/text/workflow-format.js +0 -32
  167. package/dist/output/text.js +2 -0
  168. package/dist/registry/factory.js +4 -19
  169. package/dist/registry/network.js +66 -220
  170. package/dist/registry/providers/index.js +0 -2
  171. package/dist/registry/providers/skills-sh.js +3 -14
  172. package/dist/registry/providers/static-index.js +24 -26
  173. package/dist/registry/resolve.js +55 -131
  174. package/dist/scripts/akm-migrate-node.js +43937 -93313
  175. package/dist/scripts/akm-migrate.js +43697 -93071
  176. package/dist/setup/registry-stash-loader.js +4 -13
  177. package/dist/setup/semantic-assets.js +3 -44
  178. package/dist/setup/setup.js +1 -1
  179. package/dist/setup/steps/tasks.js +25 -15
  180. package/dist/sources/provider-factory.js +17 -18
  181. package/dist/sources/providers/filesystem.js +2 -3
  182. package/dist/sources/providers/git-install.js +7 -1
  183. package/dist/sources/providers/git-provider.js +0 -3
  184. package/dist/sources/providers/git-stash.js +0 -17
  185. package/dist/sources/providers/npm.js +2 -4
  186. package/dist/sources/providers/provider-utils.js +5 -10
  187. package/dist/sources/providers/website.js +0 -2
  188. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  189. package/dist/sources/website-url.js +2 -2
  190. package/dist/storage/database.js +9 -35
  191. package/dist/storage/repositories/improve-ledger-repository.js +168 -0
  192. package/dist/storage/repositories/index-connection.js +34 -70
  193. package/dist/storage/repositories/index-entries-repository.js +69 -111
  194. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  195. package/dist/storage/repositories/index-entry-schema.js +83 -269
  196. package/dist/storage/repositories/index-fts-repository.js +86 -256
  197. package/dist/storage/repositories/index-llm-cache-repository.js +17 -0
  198. package/dist/storage/repositories/index-meta-repository.js +6 -4
  199. package/dist/storage/repositories/index-schema.js +192 -220
  200. package/dist/storage/repositories/index-utility-repository.js +8 -29
  201. package/dist/storage/repositories/index-vec-repository.js +133 -414
  202. package/dist/storage/repositories/outcome-repository.js +2 -1
  203. package/dist/storage/repositories/proposals-repository.js +35 -0
  204. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  205. package/dist/storage/repositories/task-history-repository.js +26 -4
  206. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  207. package/dist/storage/sqlite-migrations.js +136 -0
  208. package/dist/storage/sqlite-pragmas.js +11 -9
  209. package/dist/storage/sqlite-transaction.js +170 -0
  210. package/dist/storage/state-db-integrity.js +34 -27
  211. package/dist/tasks/activation-config.js +134 -62
  212. package/dist/tasks/backends/cron.js +129 -277
  213. package/dist/tasks/backends/exec-utils.js +2 -5
  214. package/dist/tasks/backends/launchd.js +125 -745
  215. package/dist/tasks/backends/schtasks.js +101 -620
  216. package/dist/tasks/prepare/prepare-support.js +5 -15
  217. package/dist/tasks/prepare/prepare.js +0 -2
  218. package/dist/tasks/resolve-akm-bin.js +20 -79
  219. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  220. package/dist/tasks/scheduler-binding.js +18 -238
  221. package/dist/tasks/scheduler-invocation.js +52 -52
  222. package/dist/tasks/scheduler-lock.js +53 -0
  223. package/dist/tasks/scheduler-sync.js +363 -679
  224. package/dist/tasks/source/parse-task-source.js +160 -10
  225. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  226. package/dist/tasks/source/task-to-v4.js +2 -2
  227. package/dist/workflows/authoring/authoring.js +3 -12
  228. package/dist/workflows/compile.js +211 -0
  229. package/dist/workflows/concurrency-policy.js +13 -74
  230. package/dist/workflows/exec/child-invocation.js +3 -17
  231. package/dist/workflows/exec/child-workflow.js +32 -141
  232. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  233. package/dist/workflows/exec/environment.js +98 -0
  234. package/dist/workflows/exec/exec-unit.js +33 -140
  235. package/dist/workflows/exec/frozen-judge.js +7 -59
  236. package/dist/workflows/exec/native-executor.js +82 -341
  237. package/dist/workflows/exec/param-secrets.js +29 -47
  238. package/dist/workflows/exec/run-workflow.js +154 -387
  239. package/dist/workflows/exec/scheduler.js +9 -36
  240. package/dist/workflows/exec/step-work.js +127 -430
  241. package/dist/workflows/exec/unit-dispatch.js +11 -63
  242. package/dist/workflows/exec/unit-writer.js +8 -52
  243. package/dist/workflows/exec/worktree.js +39 -273
  244. package/dist/workflows/freeze/child-output-references.js +4 -15
  245. package/dist/workflows/freeze/environment.js +99 -92
  246. package/dist/workflows/freeze/freeze.js +172 -0
  247. package/dist/workflows/freeze/step-values.js +19 -21
  248. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  249. package/dist/workflows/freeze/targets/command.js +10 -33
  250. package/dist/workflows/freeze/targets/script.js +5 -12
  251. package/dist/workflows/freeze/targets/shell.js +3 -6
  252. package/dist/workflows/freeze/targets/task.js +25 -80
  253. package/dist/workflows/freeze/task-bindings.js +20 -67
  254. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  255. package/dist/workflows/ir/params.js +6 -51
  256. package/dist/workflows/ir/plan-hash.js +2 -34
  257. package/dist/workflows/parser.js +140 -43
  258. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  259. package/dist/workflows/renderer.js +36 -69
  260. package/dist/workflows/resource-limits.js +12 -120
  261. package/dist/workflows/runtime/agent-identity.js +8 -40
  262. package/dist/workflows/runtime/run-outputs.js +3 -6
  263. package/dist/workflows/runtime/run-plan.js +316 -0
  264. package/dist/workflows/runtime/runs.js +48 -200
  265. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  266. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  267. package/dist/workflows/validate-summary.js +2 -7
  268. package/docs/integration/bundling-akm.md +49 -42
  269. package/docs/migration/README.md +1 -0
  270. package/docs/migration/release-notes/0.9.17.md +41 -0
  271. package/docs/migration/v0.9.1-to-v0.9.2.md +19 -7
  272. package/docs/reference/cli.md +182 -125
  273. package/docs/reference/configuration.md +49 -56
  274. package/docs/reference/data-and-telemetry.md +19 -20
  275. package/docs/reference/tasks.md +86 -38
  276. package/docs/reference/workflow-schema.md +14 -18
  277. package/docs/reference/workflows.md +6 -9
  278. package/package.json +1 -1
  279. package/schemas/akm-config.json +87 -406
  280. package/dist/commands/health/advisories.js +0 -150
  281. package/dist/commands/health/metrics.js +0 -329
  282. package/dist/commands/health/surfaces.js +0 -102
  283. package/dist/commands/improve/anti-collapse.js +0 -83
  284. package/dist/commands/improve/collapse-detector.js +0 -432
  285. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  286. package/dist/commands/improve/consolidate/merge.js +0 -146
  287. package/dist/commands/improve/distill/promote-memory.js +0 -329
  288. package/dist/commands/improve/distill/quality-gate.js +0 -500
  289. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  290. package/dist/commands/improve/proposal-envelope.js +0 -31
  291. package/dist/commands/improve/run-context.js +0 -123
  292. package/dist/commands/improve/shared.js +0 -21
  293. package/dist/commands/improve/source-identity.js +0 -28
  294. package/dist/commands/improve/triage.js +0 -96
  295. package/dist/commands/proposal/drain-policies.js +0 -151
  296. package/dist/commands/sources/update-transaction.js +0 -220
  297. package/dist/core/action-contributors.js +0 -28
  298. package/dist/core/config/config-version-shim.js +0 -101
  299. package/dist/core/config/retired-experimental-keys-shim.js +0 -62
  300. package/dist/core/fs-txn.js +0 -405
  301. package/dist/core/lexical-score.js +0 -25
  302. package/dist/core/maintenance-barrier.js +0 -167
  303. package/dist/execution/executable-identity.js +0 -105
  304. package/dist/execution/guarded-source.js +0 -427
  305. package/dist/indexer/graph/graph-boost.js +0 -427
  306. package/dist/indexer/graph/graph-dedup.js +0 -95
  307. package/dist/indexer/search/name-match.js +0 -35
  308. package/dist/indexer/search/ranking-contributors.js +0 -515
  309. package/dist/indexer/walk/project-context.js +0 -192
  310. package/dist/integrations/agent/execution-cascade.js +0 -566
  311. package/dist/integrations/agent/execution-definitions.js +0 -202
  312. package/dist/integrations/agent/execution-lowering.js +0 -841
  313. package/dist/integrations/agent/execution-preparation.js +0 -98
  314. package/dist/integrations/agent/inline-execution.js +0 -74
  315. package/dist/registry/create-provider-registry.js +0 -29
  316. package/dist/registry/pinned-request-helper.js +0 -247
  317. package/dist/registry/pinned-transport.js +0 -717
  318. package/dist/sources/providers/index.js +0 -14
  319. package/dist/storage/engines/sqlite-migrations.js +0 -271
  320. package/dist/storage/repositories/canaries-repository.js +0 -107
  321. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  322. package/dist/storage/repositories/registry-cache.js +0 -113
  323. package/dist/tasks/scheduler-sync-preview.js +0 -52
  324. package/dist/workflows/freeze/resolve-steps.js +0 -86
  325. package/dist/workflows/freeze/source-freeze.js +0 -64
  326. package/dist/workflows/ir/compile.js +0 -321
  327. package/dist/workflows/ir/environment-v4.js +0 -330
  328. package/dist/workflows/ir/freeze-v4.js +0 -153
  329. package/dist/workflows/ir/schema-v4.js +0 -745
  330. package/dist/workflows/ir/schema.js +0 -354
  331. package/dist/workflows/program/schema.js +0 -78
  332. package/dist/workflows/runtime/checkin.js +0 -57
  333. package/dist/workflows/runtime/plan-classifier.js +0 -196
  334. package/dist/workflows/runtime/unit-checkin.js +0 -45
  335. package/dist/workflows/runtime/unit-phases.js +0 -20
  336. package/dist/workflows/schema.js +0 -4
  337. package/dist/workflows/source-ir/compile.js +0 -200
  338. package/dist/workflows/source-ir/program.js +0 -50
  339. package/dist/workflows/source-ir/result.js +0 -26
  340. package/dist/workflows/source-ir/schema.js +0 -786
  341. package/dist/workflows/source-ir/triggers.js +0 -79
  342. package/dist/workflows/source-ir/uses.js +0 -40
  343. package/dist/workflows/validator.js +0 -60
@@ -1,151 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /**
5
- * Built-in deterministic triage policy presets (Proposal-Queue Triage, §3.1).
6
- *
7
- * These are the *only* "rule schema" we ship. Custom needs are served by the
8
- * single `--policy <path>` escape hatch, which zod-validates an external policy
9
- * file — not by a config-embedded rule engine (see §9, rejected alternatives).
10
- *
11
- * | preset | accepts | rejects | leaves pending |
12
- * |------------------|-----------------------------------------------------------|-------------|----------------------------------------------------|
13
- * | `personal-stash` | extract (real content); reflect ≤80 lines; consolidate | empty diffs | consolidate mid-band, distill dups, contradictions |
14
- * | `conservative` | small extract + consolidate only | empty diffs | everything else |
15
- * | `manual` | nothing | empty diffs | everything else |
16
- */
17
- import fs from "node:fs";
18
- import { z } from "zod";
19
- import { UsageError } from "../../core/errors.js";
20
- import { warnOnce } from "../../core/warn.js";
21
- import { PROPOSAL_SOURCES } from "./repository.js";
22
- // Valid `generator` values for a drain rule are exactly the canonical proposal
23
- // `source` values (see {@link PROPOSAL_SOURCES} in src/commands/proposal/repository.ts). The
24
- // engine matches rules via `policy.accept.find(r => r.generator === proposal.source)`,
25
- // so a generator that is not a real source can never match — it would be a
26
- // silent permanent no-op. Validate against the closed set to surface typos.
27
- const GeneratorSchema = z.enum(PROPOSAL_SOURCES, {
28
- errorMap: () => ({
29
- message: `must be one of the known proposal sources: ${PROPOSAL_SOURCES.join(", ")}`,
30
- }),
31
- });
32
- // ---------------------------------------------------------------------------
33
- // Built-in presets
34
- // ---------------------------------------------------------------------------
35
- /**
36
- * `personal-stash` encodes the deterministic core of today's hand-rolled
37
- * rubric (the editable `contradicted` memory). It is shipped as a preset, never
38
- * hardcoded policy: edit a copy via `--policy <path>` to tune it.
39
- */
40
- export const PERSONAL_STASH = {
41
- name: "personal-stash",
42
- accept: [
43
- // Extract proposals carry freshly-pulled real content — accept when present,
44
- // but cap the diff for parity with reflect(80)/consolidate(200): an
45
- // arbitrarily large extract should not auto-promote with zero LLM calls.
46
- { generator: "extract", minContentLines: 1, maxDiffLines: 200 },
47
- // Reflect refinements: accept small ones; larger refinements defer to review.
48
- { generator: "reflect", maxDiffLines: 80 },
49
- // Consolidate within the diff band; mid-band lands in `defer` below.
50
- { generator: "consolidate", maxDiffLines: 200 },
51
- ],
52
- rejectEmpty: true,
53
- // Mid-band consolidate, distill duplicates, and contradiction escalations are
54
- // the irreducibly-semantic tail — deferred to the (Phase 3) judgment tier.
55
- defer: ["consolidate", "distill"],
56
- };
57
- /** `conservative` accepts only small, low-risk extract + consolidate proposals. */
58
- export const CONSERVATIVE = {
59
- name: "conservative",
60
- accept: [
61
- { generator: "extract", maxDiffLines: 80, minContentLines: 1 },
62
- { generator: "consolidate", maxDiffLines: 80 },
63
- ],
64
- rejectEmpty: true,
65
- defer: [],
66
- };
67
- /** `manual` accepts nothing; it only clears empty diffs. */
68
- export const MANUAL = {
69
- name: "manual",
70
- accept: [],
71
- rejectEmpty: true,
72
- defer: [],
73
- };
74
- const BUILTIN_POLICIES = {
75
- "personal-stash": PERSONAL_STASH,
76
- conservative: CONSERVATIVE,
77
- manual: MANUAL,
78
- };
79
- /** Names of the built-in presets, for help text and validation messages. */
80
- export const BUILTIN_POLICY_NAMES = Object.keys(BUILTIN_POLICIES);
81
- // ---------------------------------------------------------------------------
82
- // Custom policy file schema (`--policy <path>`)
83
- // ---------------------------------------------------------------------------
84
- const DrainAcceptRuleSchema = z
85
- .object({
86
- generator: GeneratorSchema,
87
- maxDiffLines: z.number().int().positive().optional(),
88
- minContentLines: z.number().int().nonnegative().optional(),
89
- requireType: z.string().optional(),
90
- })
91
- .passthrough();
92
- const DrainPolicySchema = z
93
- .object({
94
- name: z.string().min(1),
95
- accept: z.array(DrainAcceptRuleSchema),
96
- rejectEmpty: z.boolean(),
97
- defer: z.array(GeneratorSchema),
98
- })
99
- .passthrough();
100
- function warnIgnoredPolicyKeys(filePath, label, raw, knownKeys) {
101
- if (!raw || typeof raw !== "object" || Array.isArray(raw))
102
- return;
103
- const extra = Object.keys(raw).filter((key) => !knownKeys.includes(key));
104
- if (extra.length === 0)
105
- return;
106
- warnOnce(`drain-policy-ignored-keys:${filePath}:${label}:${extra.join(",")}`, `[proposal] Policy file "${filePath}" has ${label} field(s) akm does not recognize and ignores: ${extra.join(", ")}. Check for a typo, or the file may be written for a newer akm version.`);
107
- }
108
- const DRAIN_POLICY_KNOWN_KEYS = Object.keys(DrainPolicySchema.shape);
109
- const DRAIN_ACCEPT_RULE_KNOWN_KEYS = Object.keys(DrainAcceptRuleSchema.shape);
110
- /**
111
- * Resolve a `--policy <preset|path>` argument into a {@link DrainPolicy}.
112
- *
113
- * - A bare preset name (`personal-stash` / `conservative` / `manual`) returns
114
- * the matching built-in.
115
- * - Anything else is treated as a filesystem path to a JSON policy file, which
116
- * is read and zod-validated.
117
- *
118
- * Throws a {@link UsageError} on an unknown preset, a missing file, or a file
119
- * that fails schema validation.
120
- */
121
- export function resolveDrainPolicy(arg) {
122
- const value = (arg ?? "personal-stash").trim();
123
- const builtin = BUILTIN_POLICIES[value];
124
- if (builtin)
125
- return builtin;
126
- // Treat as a path to a custom policy file.
127
- if (!fs.existsSync(value)) {
128
- throw new UsageError(`Unknown policy "${value}". Use a built-in preset (${BUILTIN_POLICY_NAMES.join(", ")}) or a path to a policy file.`, "INVALID_FLAG_VALUE");
129
- }
130
- let parsed;
131
- try {
132
- parsed = JSON.parse(fs.readFileSync(value, "utf8"));
133
- }
134
- catch (err) {
135
- throw new UsageError(`Could not parse policy file "${value}": ${err instanceof Error ? err.message : String(err)}`, "INVALID_FLAG_VALUE");
136
- }
137
- const validated = DrainPolicySchema.safeParse(parsed);
138
- if (!validated.success) {
139
- throw new UsageError(`Invalid policy file "${value}": ${validated.error.issues.map((i) => `${i.path.join(".") || "<root>"}: ${i.message}`).join("; ")}`, "INVALID_FLAG_VALUE");
140
- }
141
- warnIgnoredPolicyKeys(value, "top-level", parsed, DRAIN_POLICY_KNOWN_KEYS);
142
- if (parsed &&
143
- typeof parsed === "object" &&
144
- !Array.isArray(parsed) &&
145
- Array.isArray(parsed.accept)) {
146
- parsed.accept.forEach((rule, index) => {
147
- warnIgnoredPolicyKeys(value, `accept[${index}]`, rule, DRAIN_ACCEPT_RULE_KNOWN_KEYS);
148
- });
149
- }
150
- return validated.data;
151
- }
@@ -1,220 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { randomBytes } from "node:crypto";
5
- import fs from "node:fs";
6
- import path from "node:path";
7
- import { ConfigError } from "../../core/errors.js";
8
- import { warn } from "../../core/warn.js";
9
- import { runGit } from "../../sources/providers/git.js";
10
- import { assertNoIgnoredPathOverwrite } from "../../sources/providers/git-install.js";
11
- export function prepareDirectoryPublication(stagedRoot, liveRoot) {
12
- const backupRoot = `${liveRoot}.akm-update-backup-${randomBytes(6).toString("hex")}`;
13
- let published = false;
14
- let hadLiveRoot = false;
15
- return {
16
- publish() {
17
- if (published)
18
- throw new ConfigError(`Update content at ${liveRoot} was already published.`);
19
- hadLiveRoot = fs.existsSync(liveRoot);
20
- fs.mkdirSync(path.dirname(liveRoot), { recursive: true });
21
- if (hadLiveRoot)
22
- fs.renameSync(liveRoot, backupRoot);
23
- try {
24
- fs.renameSync(stagedRoot, liveRoot);
25
- published = true;
26
- }
27
- catch (error) {
28
- if (hadLiveRoot && fs.existsSync(backupRoot))
29
- fs.renameSync(backupRoot, liveRoot);
30
- throw error;
31
- }
32
- },
33
- rollback() {
34
- if (!published)
35
- return;
36
- const failedRoot = `${liveRoot}.akm-update-failed-${randomBytes(6).toString("hex")}`;
37
- if (fs.existsSync(liveRoot))
38
- fs.renameSync(liveRoot, failedRoot);
39
- try {
40
- if (hadLiveRoot && fs.existsSync(backupRoot))
41
- fs.renameSync(backupRoot, liveRoot);
42
- }
43
- catch (error) {
44
- // The prior generation could not be restored. Put the published
45
- // candidate back at the live path so resolution never sees a missing
46
- // root, then surface the rollback failure loudly.
47
- try {
48
- if (!fs.existsSync(liveRoot) && fs.existsSync(failedRoot))
49
- fs.renameSync(failedRoot, liveRoot);
50
- }
51
- catch {
52
- // Preserve the original restoration failure; both paths remain for
53
- // manual recovery when even the defensive rename cannot complete.
54
- }
55
- published = false;
56
- throw error;
57
- }
58
- try {
59
- fs.rmSync(failedRoot, { recursive: true, force: true });
60
- }
61
- catch (error) {
62
- warn(`[akm bundle update] restored ${liveRoot}, but could not remove failed candidate ${failedRoot}: ${error instanceof Error ? error.message : String(error)}`);
63
- }
64
- published = false;
65
- },
66
- commit() {
67
- if (hadLiveRoot) {
68
- try {
69
- fs.rmSync(backupRoot, { recursive: true, force: true });
70
- }
71
- catch (error) {
72
- warn(`[akm bundle update] update committed, but could not remove backup ${backupRoot}: ${error instanceof Error ? error.message : String(error)}`);
73
- }
74
- }
75
- published = false;
76
- },
77
- };
78
- }
79
- function gitOutput(repoDir, args, description) {
80
- const result = runGit(["-C", repoDir, ...args], { timeout: 120_000 });
81
- if (result.status !== 0) {
82
- throw new ConfigError(`${description}: ${result.stderr.trim() || result.stdout.trim() || "git failed"}`);
83
- }
84
- return result.stdout.trim();
85
- }
86
- function assertGitCheckoutGeneration(repoDir, expectedHead, phase) {
87
- const actualHead = gitOutput(repoDir, ["rev-parse", "HEAD"], `Cannot read writable Git HEAD at ${repoDir}`);
88
- if (actualHead !== expectedHead) {
89
- throw new ConfigError(`Writable Git checkout at ${repoDir} changed after the update was audited (${phase}: expected ${expectedHead}, found ${actualHead}); refusing to overwrite the live commit.`);
90
- }
91
- const status = gitOutput(repoDir, ["status", "--porcelain=v1", "--untracked-files=all", "--ignore-submodules=none"], `Cannot inspect writable Git checkout at ${repoDir}`);
92
- if (status) {
93
- throw new ConfigError(`Writable Git checkout at ${repoDir} changed after the update was audited (${phase}: working tree is no longer clean); refusing to overwrite live files.`);
94
- }
95
- }
96
- function assertNoGitlinks(repoDir, targetHead) {
97
- const tree = gitOutput(repoDir, ["ls-tree", "-r", "-z", targetHead], `Cannot inspect audited Git tree ${targetHead} at ${repoDir}`);
98
- const gitlink = tree.split("\0").find((entry) => entry.startsWith("160000 "));
99
- if (gitlink) {
100
- const targetPath = gitlink.slice(gitlink.indexOf("\t") + 1);
101
- throw new ConfigError(`Writable Git target contains unaudited submodule/gitlink ${targetPath}; refusing to materialize it.`);
102
- }
103
- }
104
- function copyWorktree(source, destination) {
105
- fs.mkdirSync(destination, { recursive: true, mode: 0o700 });
106
- for (const entry of fs.readdirSync(source, { withFileTypes: true })) {
107
- if (entry.name === ".git")
108
- continue;
109
- fs.cpSync(path.join(source, entry.name), path.join(destination, entry.name), {
110
- recursive: true,
111
- preserveTimestamps: true,
112
- });
113
- }
114
- }
115
- function clearWorktree(repoDir) {
116
- for (const entry of fs.readdirSync(repoDir, { withFileTypes: true })) {
117
- if (entry.name === ".git")
118
- continue;
119
- fs.rmSync(path.join(repoDir, entry.name), { recursive: true, force: true });
120
- }
121
- }
122
- /**
123
- * Publish the exact audited commit into a writable checkout without replacing
124
- * the checkout directory. The expected-old-HEAD and clean-tree fence runs
125
- * under the caller's asset mutation lease immediately before the fast-forward.
126
- */
127
- export function prepareWritableGitPublication(opts) {
128
- let published = false;
129
- let rollbackParent;
130
- let rollbackWorktree;
131
- const discardRollback = () => {
132
- if (!rollbackParent)
133
- return;
134
- cleanupStagingParent(rollbackParent);
135
- rollbackParent = undefined;
136
- rollbackWorktree = undefined;
137
- };
138
- const restore = () => {
139
- if (!rollbackWorktree)
140
- return;
141
- const actualHead = gitOutput(opts.liveRepo, ["rev-parse", "HEAD"], `Cannot read writable Git rollback HEAD`);
142
- if (actualHead !== opts.expectedOldHead && actualHead !== opts.auditedTargetHead) {
143
- throw new ConfigError(`Writable Git checkout ${opts.liveRepo} advanced concurrently to ${actualHead}; refusing to overwrite that commit during rollback.`);
144
- }
145
- gitOutput(opts.liveRepo, ["reset", "--hard", opts.expectedOldHead], `Cannot restore writable Git checkout ${opts.liveRepo} to ${opts.expectedOldHead}`);
146
- clearWorktree(opts.liveRepo);
147
- copyWorktree(rollbackWorktree, opts.liveRepo);
148
- assertGitCheckoutGeneration(opts.liveRepo, opts.expectedOldHead, "rollback verification");
149
- published = false;
150
- discardRollback();
151
- };
152
- return {
153
- publish() {
154
- if (published)
155
- throw new ConfigError(`Writable Git update at ${opts.liveRepo} was already published.`);
156
- assertGitCheckoutGeneration(opts.liveRepo, opts.expectedOldHead, "pre-publish fence");
157
- assertGitCheckoutGeneration(opts.stagedRepo, opts.auditedTargetHead, "staged audit fence");
158
- const ancestor = runGit([
159
- "-C",
160
- opts.stagedRepo,
161
- "merge-base",
162
- "--is-ancestor",
163
- opts.expectedOldHead,
164
- opts.auditedTargetHead,
165
- ]);
166
- if (ancestor.status !== 0) {
167
- throw new ConfigError(`Audited Git target ${opts.auditedTargetHead} is not a fast-forward of live HEAD ${opts.expectedOldHead}; refusing writable update.`);
168
- }
169
- assertNoGitlinks(opts.stagedRepo, opts.auditedTargetHead);
170
- gitOutput(opts.liveRepo, ["fetch", "--no-tags", opts.stagedRepo, opts.auditedTargetHead], `Cannot import audited Git target ${opts.auditedTargetHead} into ${opts.liveRepo}`);
171
- // A non-cooperating local Git command may have committed while fetch ran.
172
- assertGitCheckoutGeneration(opts.liveRepo, opts.expectedOldHead, "post-fetch fence");
173
- assertNoIgnoredPathOverwrite(opts.liveRepo, opts.auditedTargetHead);
174
- rollbackParent = createStagingParent(path.dirname(opts.liveRepo));
175
- rollbackWorktree = path.join(rollbackParent, "worktree");
176
- try {
177
- copyWorktree(opts.liveRepo, rollbackWorktree);
178
- }
179
- catch (error) {
180
- discardRollback();
181
- throw error;
182
- }
183
- try {
184
- gitOutput(opts.liveRepo, ["merge", "--ff-only", "--no-overwrite-ignore", opts.auditedTargetHead], `Cannot fast-forward writable Git checkout ${opts.liveRepo}`);
185
- published = true;
186
- assertGitCheckoutGeneration(opts.liveRepo, opts.auditedTargetHead, "post-materialization fence");
187
- }
188
- catch (error) {
189
- try {
190
- restore();
191
- }
192
- catch (restoreError) {
193
- throw new ConfigError(`Writable Git publication failed and its worktree could not be restored: ${restoreError instanceof Error ? restoreError.message : String(restoreError)}`);
194
- }
195
- throw error;
196
- }
197
- },
198
- rollback() {
199
- if (!published)
200
- return;
201
- restore();
202
- },
203
- commit() {
204
- published = false;
205
- discardRollback();
206
- },
207
- };
208
- }
209
- export function createStagingParent(parent) {
210
- fs.mkdirSync(parent, { recursive: true, mode: 0o700 });
211
- return fs.mkdtempSync(path.join(parent, ".akm-update-stage-"));
212
- }
213
- export function cleanupStagingParent(stagingParent) {
214
- try {
215
- fs.rmSync(stagingParent, { recursive: true, force: true });
216
- }
217
- catch (error) {
218
- warn(`[akm bundle update] could not remove staging directory ${stagingParent}: ${error instanceof Error ? error.message : String(error)}`);
219
- }
220
- }
@@ -1,28 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { defaultRendererRegistry } from "./type-presentation.js";
5
- function registryActionContributor(registry) {
6
- return {
7
- name: "registry-action-contributor",
8
- appliesTo(ctx) {
9
- return registry.actionBuilderFor(ctx.type) !== undefined;
10
- },
11
- buildAction(ctx) {
12
- return registry.actionBuilderFor(ctx.type)?.(ctx.ref);
13
- },
14
- };
15
- }
16
- export function defaultActionContributors(registry = defaultRendererRegistry) {
17
- return [registryActionContributor(registry)];
18
- }
19
- export function buildActionFromContributors(ctx, contributors = defaultActionContributors()) {
20
- for (const contributor of contributors) {
21
- if (!contributor.appliesTo(ctx))
22
- continue;
23
- const action = contributor.buildAction(ctx);
24
- if (action !== undefined)
25
- return action;
26
- }
27
- return undefined;
28
- }
@@ -1,101 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /**
5
- * The `configVersion` read shim (#863).
6
- *
7
- * `configVersion` used to be a hard `z.literal(CURRENT_CONFIG_VERSION)` gate:
8
- * every value other than the exact current string threw
9
- * `UNSUPPORTED_CONFIG_VERSION` for every command, since every akm invocation
10
- * loads config first. That is the same shape of break #858/#859 (proposal
11
- * rows), the `task_history` `metadataVersion` gate, and the task-source v2/v3
12
- * gate each caused in 0.9.x — a version gate with no read shim — except
13
- * `configVersion`'s blast radius is the whole CLI rather than one subsystem.
14
- *
15
- * This module mirrors the in-tree template for that fix,
16
- * `src/tasks/source/parse-task-source.ts`'s v2/v3 -> v4 shim: a known-old
17
- * version routes through a pure, in-memory upgrade function to the current
18
- * shape, with a one-line stderr deprecation warning; the result is never
19
- * written back to disk (the on-disk rewrite already happens for free — every
20
- * `saveConfig`/`mutateConfig` write forces `configVersion` to
21
- * {@link CURRENT_CONFIG_VERSION}, so the very next `akm config set` or any
22
- * other mutating command silences the warning permanently). A version that is
23
- * neither current nor a known old version — including anything NEWER than
24
- * current — still fails closed with `UNSUPPORTED_CONFIG_VERSION`:
25
- * forward-incompatibility is a real hazard (an older binary must not guess at
26
- * a newer, unknown shape) and this shim does not soften that.
27
- *
28
- * IMPORTANT — as of this writing, `"0.9.0"` is the only `configVersion` akm
29
- * has ever shipped; there is no real prior release to shim. `"0.0.1"` below
30
- * is a SYNTHETIC placeholder entry that exists solely to stand up and
31
- * exercise this mechanism — the known-versions list, the dispatch table, the
32
- * warn-once-and-upgrade behavior, the fail-closed behavior for anything
33
- * else — before a real bump ever needs it (see
34
- * `tests/integration/config-version-shim.test.ts` and the
35
- * `previous-release-corpus.test.ts` fixture). When the first genuine
36
- * `configVersion` bump ships, add its real old shape as its own entry the
37
- * same way and delete the synthetic `"0.0.1"` entry (and this paragraph) in
38
- * the same change.
39
- */
40
- import { ConfigError } from "../errors.js";
41
- import { warn } from "../warn.js";
42
- import { CURRENT_CONFIG_VERSION } from "./schema/primitives.js";
43
- /**
44
- * Every `configVersion` this binary can still READ, other than
45
- * {@link CURRENT_CONFIG_VERSION} itself — each with an in-memory upgrade
46
- * function in {@link CONFIG_VERSION_UPGRADES}. Anything not in this list (and
47
- * not equal to current) fails closed.
48
- */
49
- export const KNOWN_OLD_CONFIG_VERSIONS = ["0.0.1"];
50
- function isKnownOldConfigVersion(value) {
51
- return typeof value === "string" && KNOWN_OLD_CONFIG_VERSIONS.includes(value);
52
- }
53
- /**
54
- * SYNTHETIC 0.0.1 -> 0.9.0 upgrade (placeholder — see module doc). Per this
55
- * placeholder, 0.0.1 kept the default LLM engine name at the config root as
56
- * `defaultEngine`; 0.9.0 moved it under `defaults.llmEngine`. Pure function:
57
- * takes the raw parsed JSON object, returns a new raw object with the 0.9.0
58
- * shape. Never touches disk.
59
- */
60
- function upgradeFrom080(raw) {
61
- const { defaultEngine, defaults, ...rest } = raw;
62
- if (typeof defaultEngine !== "string" || defaultEngine.length === 0) {
63
- return { ...rest, ...(defaults !== undefined ? { defaults } : {}), configVersion: CURRENT_CONFIG_VERSION };
64
- }
65
- const existingDefaults = defaults !== null && typeof defaults === "object" ? defaults : {};
66
- return {
67
- ...rest,
68
- configVersion: CURRENT_CONFIG_VERSION,
69
- // An explicit `defaults.llmEngine` already present in the raw 0.0.1
70
- // document (should never happen for a real 0.0.1 file, but a malformed
71
- // one is possible) wins over the root-level field being migrated in.
72
- defaults: { llmEngine: defaultEngine, ...existingDefaults },
73
- };
74
- }
75
- const CONFIG_VERSION_UPGRADES = {
76
- "0.0.1": upgradeFrom080,
77
- };
78
- function unsupportedConfigVersionError(rawVersion, sourcePath) {
79
- const where = sourcePath ? ` at ${sourcePath}` : "";
80
- const supported = [CURRENT_CONFIG_VERSION, ...KNOWN_OLD_CONFIG_VERSIONS].map((v) => `"${v}"`).join(", ");
81
- return new ConfigError(`Unsupported configVersion${where}: got ${JSON.stringify(rawVersion)}, expected one of ${supported}.`, "UNSUPPORTED_CONFIG_VERSION", "Recreate engines and improve.strategies manually for AKM 0.9.0; profile-based configuration is not translated automatically.");
82
- }
83
- /**
84
- * Route a raw parsed config object through the version shim before schema
85
- * validation. Returns a raw object whose `configVersion` is
86
- * {@link CURRENT_CONFIG_VERSION} — either unchanged (already current),
87
- * in-memory-upgraded (a known old version, with a one-line stderr warning),
88
- * or this throws `UNSUPPORTED_CONFIG_VERSION` (unknown, newer, missing, or
89
- * malformed).
90
- */
91
- export function upgradeConfigVersion(raw, sourcePath) {
92
- const version = raw.configVersion;
93
- if (version === CURRENT_CONFIG_VERSION)
94
- return raw;
95
- if (isKnownOldConfigVersion(version)) {
96
- const upgraded = CONFIG_VERSION_UPGRADES[version](raw);
97
- warn(`Config${sourcePath ? ` at ${sourcePath}` : ""} uses configVersion "${version}" — auto-upgraded to ${CURRENT_CONFIG_VERSION} in memory; the next config write (e.g. \`akm config set\`) persists this and silences the warning.`);
98
- return upgraded;
99
- }
100
- throw unsupportedConfigVersionError(version, sourcePath);
101
- }
@@ -1,62 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /**
5
- * `experimental.*` retired-key shim.
6
- *
7
- * `ExperimentalConfigSchema` (`./schema/experimental.ts`) moved from
8
- * `.passthrough()` to `.strict()` in 0.9.16 (`cc6152e02`) so a typo in an
9
- * authority flag (e.g. `improveAutonomyy`) fails loudly instead of silently
10
- * doing nothing. `workflowEngine` was removed from that block earlier, in
11
- * `e0655d13c`, but 0.9.15's passthrough still accepted it — so a real config
12
- * written by 0.9.15 can carry `experimental.workflowEngine` and now fails
13
- * every command with `Invalid config: experimental: Unrecognized key(s)`.
14
- *
15
- * Per AGENTS.md "Reading persisted data": a reader tolerates what older
16
- * releases wrote, converts in memory, warns once, and leaves the on-disk
17
- * rewrite to `akm migrate apply`. This mirrors `./legacy-source-shape-shim.ts`
18
- * exactly — strip the retired key(s) before schema validation, warn once
19
- * naming the key and the migrate command — rather than reintroducing
20
- * `.passthrough()`, which would also let a live key typo through silently.
21
- */
22
- import { isRecord } from "../common.js";
23
- import { warnOnce } from "../warn.js";
24
- /**
25
- * Every `experimental.*` key `ExperimentalConfigSchema` has ever retired.
26
- * `workflowEngine` (removed in `e0655d13c`) is the only one so far — kept as
27
- * a list because the shim and `akm migrate apply`
28
- * (`scripts/akm-migrate/migrate/config-retired-experimental-keys.ts`) share
29
- * it.
30
- */
31
- export const RETIRED_EXPERIMENTAL_KEYS = ["workflowEngine"];
32
- /**
33
- * Which `RETIRED_EXPERIMENTAL_KEYS` are present in a raw config's
34
- * `experimental` section. Returns `[]` when `raw.experimental` is missing or
35
- * not a record. Shared by `stripRetiredExperimentalKeys` below and by
36
- * `akm migrate apply`'s on-disk counterpart
37
- * (`scripts/akm-migrate/migrate/config-retired-experimental-keys.ts`).
38
- */
39
- export function retiredExperimentalKeysIn(raw) {
40
- const experimental = raw.experimental;
41
- if (!isRecord(experimental))
42
- return [];
43
- return RETIRED_EXPERIMENTAL_KEYS.filter((key) => key in experimental);
44
- }
45
- /**
46
- * Drop retired `experimental.*` keys from a raw parsed config object before
47
- * schema validation, warning once per source when any were present. Live
48
- * keys (including an unrecognized one, e.g. a typo) are left untouched for
49
- * `ExperimentalConfigSchema.strict()` to reject as before.
50
- */
51
- export function stripRetiredExperimentalKeys(raw, sourcePath) {
52
- const present = retiredExperimentalKeysIn(raw);
53
- if (present.length === 0)
54
- return raw;
55
- const original = raw.experimental;
56
- const experimental = { ...original };
57
- for (const key of present)
58
- delete experimental[key];
59
- const where = sourcePath ? ` at ${sourcePath}` : "";
60
- warnOnce(`config:retired-experimental-key${sourcePath ? `:${sourcePath}` : ""}`, `Config${where} uses the retired experimental key(s) ${present.join(", ")} — ignored in memory. Run \`akm migrate apply\` to remove ${present.length === 1 ? "it" : "them"} from the config file and silence this warning.`);
61
- return { ...raw, experimental };
62
- }