akm-cli 0.9.16 → 0.9.17-alpha.10

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 (403) hide show
  1. package/CHANGELOG.md +2101 -0
  2. package/STABILITY.md +11 -10
  3. package/dist/akm +124 -193
  4. package/dist/akm-migrate +38 -19
  5. package/dist/assets/hints/cli-hints-full.md +6 -7
  6. package/dist/assets/improve-strategies/catchup.json +0 -3
  7. package/dist/assets/improve-strategies/consolidate.json +0 -1
  8. package/dist/assets/improve-strategies/default.json +1 -2
  9. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -2
  10. package/dist/assets/improve-strategies/quick.json +1 -2
  11. package/dist/assets/improve-strategies/reflect-distill.json +1 -2
  12. package/dist/assets/improve-strategies/thorough.json +0 -3
  13. package/dist/assets/prompts/consolidate-pair.md +20 -0
  14. package/dist/assets/prompts/consolidate-system.md +4 -11
  15. package/dist/assets/prompts/retrieval-relevance-judge.md +6 -0
  16. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +20 -20
  17. package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -2
  18. package/dist/assets/templates/html/health.html +3 -5
  19. package/dist/cli/retired-commands.js +1 -1
  20. package/dist/cli/shared.js +6 -2
  21. package/dist/cli/unknown-flags.js +24 -1
  22. package/dist/cli.js +68 -10
  23. package/dist/commands/agent/agent-dispatch.js +1 -1
  24. package/dist/commands/command/command-execution.js +24 -62
  25. package/dist/commands/feedback-cli.js +0 -1
  26. package/dist/commands/health/accept-rate.js +6 -0
  27. package/dist/commands/health/archive-usage.js +92 -0
  28. package/dist/commands/health/checks.js +83 -74
  29. package/dist/commands/health/config-skew.js +38 -0
  30. package/dist/commands/health/data-dir-usage.js +25 -13
  31. package/dist/commands/health/egress.js +54 -0
  32. package/dist/commands/health/html-report.js +1 -42
  33. package/dist/commands/health/improve-metrics.js +136 -591
  34. package/dist/commands/health/md-report.js +1 -6
  35. package/dist/commands/health/plugin-staleness.js +53 -3
  36. package/dist/commands/health/renderers.js +12 -4
  37. package/dist/commands/health/report-view-model.js +14 -120
  38. package/dist/commands/health/types-improve.js +4 -19
  39. package/dist/commands/health/windows.js +64 -74
  40. package/dist/commands/health.js +145 -143
  41. package/dist/commands/improve/consolidate/chunking.js +26 -117
  42. package/dist/commands/improve/consolidate/continuity-check.js +137 -0
  43. package/dist/commands/improve/consolidate/pair-pass.js +791 -0
  44. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  45. package/dist/commands/improve/consolidate.js +589 -1127
  46. package/dist/commands/improve/content-hash.js +16 -24
  47. package/dist/commands/improve/distill/content-repair.js +18 -100
  48. package/dist/commands/improve/distill-guards.js +20 -81
  49. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  50. package/dist/commands/improve/distill.js +608 -1041
  51. package/dist/commands/improve/eligibility.js +126 -390
  52. package/dist/commands/improve/execution.js +8 -10
  53. package/dist/commands/improve/extract-prompt.js +1 -2
  54. package/dist/commands/improve/extract.js +487 -1046
  55. package/dist/commands/improve/feedback-valence.js +0 -25
  56. package/dist/commands/improve/improve-cli.js +75 -169
  57. package/dist/commands/improve/improve-result-file.js +10 -66
  58. package/dist/commands/improve/improve-strategies.js +52 -4
  59. package/dist/commands/improve/improve-usage-report.js +18 -64
  60. package/dist/commands/improve/improve.js +480 -1074
  61. package/dist/commands/improve/ledger.js +119 -0
  62. package/dist/commands/improve/locks.js +2 -8
  63. package/dist/commands/improve/loop-stages.js +415 -1073
  64. package/dist/commands/improve/memory/derived-ref.js +12 -77
  65. package/dist/commands/improve/memory/memory-belief.js +16 -118
  66. package/dist/commands/improve/memory/memory-improve.js +266 -14
  67. package/dist/commands/improve/outcome-loop.js +28 -156
  68. package/dist/commands/improve/planner.js +5 -15
  69. package/dist/commands/improve/preparation.js +779 -2319
  70. package/dist/commands/improve/proactive-maintenance.js +34 -101
  71. package/dist/commands/improve/reflect-noise.js +104 -280
  72. package/dist/commands/improve/reflect.js +642 -1353
  73. package/dist/commands/improve/retrieval-gate.js +127 -0
  74. package/dist/commands/improve/retrieval-scope.js +92 -0
  75. package/dist/commands/improve/salience.js +41 -240
  76. package/dist/commands/improve/session-asset.js +19 -100
  77. package/dist/commands/improve/stage.js +322 -0
  78. package/dist/commands/lint/base-linter.js +37 -15
  79. package/dist/commands/proposal/drain.js +261 -578
  80. package/dist/commands/proposal/proposal-cli.js +19 -20
  81. package/dist/commands/proposal/proposal-types.js +31 -24
  82. package/dist/commands/proposal/proposal.js +38 -8
  83. package/dist/commands/proposal/propose.js +134 -160
  84. package/dist/commands/proposal/repository.js +1097 -1394
  85. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  86. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  87. package/dist/commands/proposal/validators/proposals.js +22 -89
  88. package/dist/commands/read/curate.js +105 -462
  89. package/dist/commands/read/knowledge.js +3 -2
  90. package/dist/commands/read/search-cli.js +16 -33
  91. package/dist/commands/read/search.js +17 -23
  92. package/dist/commands/read/show.js +57 -108
  93. package/dist/commands/sources/bundle-cli.js +25 -2
  94. package/dist/commands/sources/bundle-config-ops.js +4 -0
  95. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  96. package/dist/commands/sources/info.js +127 -29
  97. package/dist/commands/sources/installed-stashes.js +197 -746
  98. package/dist/commands/sources/schema-repair.js +98 -129
  99. package/dist/commands/sources/source-add.js +62 -12
  100. package/dist/commands/sources/source-manage.js +9 -2
  101. package/dist/commands/sources/stash-cli.js +24 -4
  102. package/dist/commands/tasks/explain.js +10 -13
  103. package/dist/commands/tasks/tasks-cli.js +12 -13
  104. package/dist/commands/tasks/tasks.js +350 -936
  105. package/dist/commands/tasks/validate.js +26 -24
  106. package/dist/commands/workflow/plan.js +22 -29
  107. package/dist/commands/workflow-cli.js +4 -4
  108. package/dist/core/adapter/adapters/akm-adapter.js +2 -1
  109. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  110. package/dist/core/adapter/adapters/akm-metadata.js +42 -12
  111. package/dist/core/adapter/adapters/akm-task-adapter.js +29 -8
  112. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  113. package/dist/core/adapter/execution-source.js +17 -29
  114. package/dist/core/asset/asset-placement.js +4 -13
  115. package/dist/core/asset/frontmatter.js +106 -1
  116. package/dist/core/asset/resolve-ref.js +1 -1
  117. package/dist/core/bundle-id.js +42 -5
  118. package/dist/core/bundle-rename.js +285 -0
  119. package/dist/core/config/config-io.js +1 -2
  120. package/dist/core/config/config-schema.js +9 -34
  121. package/dist/core/config/config-walker.js +1 -1
  122. package/dist/core/config/config.js +184 -111
  123. package/dist/core/config/engine-semantics.js +0 -2
  124. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  125. package/dist/core/config/schema/embedding.js +20 -5
  126. package/dist/core/config/schema/engines.js +5 -0
  127. package/dist/core/config/schema/execution.js +1 -1
  128. package/dist/core/config/schema/experimental.js +1 -1
  129. package/dist/core/config/schema/improve-processes.js +54 -125
  130. package/dist/core/config/schema/improve.js +4 -42
  131. package/dist/core/config/schema/index-config.js +9 -48
  132. package/dist/core/config/schema/scheduler.js +12 -12
  133. package/dist/core/config/schema/search.js +6 -22
  134. package/dist/core/env-secret-ref.js +0 -1
  135. package/dist/core/errors.js +8 -9
  136. package/dist/core/file-change.js +13 -5
  137. package/dist/core/file-lock.js +76 -173
  138. package/dist/core/improve-result.js +35 -7
  139. package/dist/core/improve-types.js +0 -1
  140. package/dist/core/logs-db.js +2 -2
  141. package/dist/core/loopback.js +7 -12
  142. package/dist/core/non-task-input.js +20 -0
  143. package/dist/core/parse.js +13 -16
  144. package/dist/core/paths.js +0 -24
  145. package/dist/core/redaction.js +109 -2
  146. package/dist/core/run-lock.js +2 -5
  147. package/dist/core/spawn-env.js +1 -1
  148. package/dist/core/state/migrations.js +123 -61
  149. package/dist/core/state-db-scope.js +2 -4
  150. package/dist/core/state-db.js +126 -692
  151. package/dist/core/time.js +0 -20
  152. package/dist/core/type-presentation.js +1 -9
  153. package/dist/core/write-source.js +294 -1005
  154. package/dist/execution/input-contract.js +1 -1
  155. package/dist/execution/resolved-request.js +135 -689
  156. package/dist/execution/source.js +63 -257
  157. package/dist/execution/target-ref.js +1 -1
  158. package/dist/indexer/bundle-identity-guard.js +2 -2
  159. package/dist/indexer/db/llm-cache.js +2 -2
  160. package/dist/indexer/ensure-index.js +77 -73
  161. package/dist/indexer/index-rebuild-lock.js +3 -11
  162. package/dist/indexer/index-writer-lock.js +8 -17
  163. package/dist/indexer/index-written-assets.js +141 -154
  164. package/dist/indexer/indexer.js +400 -1124
  165. package/dist/indexer/links/declared-links.js +90 -0
  166. package/dist/indexer/materialize-embeddings.js +60 -397
  167. package/dist/indexer/passes/memory-inference.js +96 -90
  168. package/dist/indexer/passes/metadata.js +132 -219
  169. package/dist/indexer/read-preflight.js +0 -7
  170. package/dist/indexer/scan/doc-to-entry.js +2 -3
  171. package/dist/indexer/scan/drain-dir.js +1 -1
  172. package/dist/indexer/search/db-search.js +190 -590
  173. package/dist/indexer/search/fts-query.js +30 -41
  174. package/dist/indexer/search/ranking.js +28 -154
  175. package/dist/indexer/search/search-attribution.js +12 -32
  176. package/dist/indexer/search/search-fields.js +11 -15
  177. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  178. package/dist/indexer/search/search-source.js +1 -4
  179. package/dist/indexer/usage/usage-events.js +36 -7
  180. package/dist/indexer/walk/walker.js +3 -4
  181. package/dist/integrations/agent/engine-fallback.js +23 -40
  182. package/dist/integrations/agent/engine-resolution.js +93 -183
  183. package/dist/integrations/agent/execution.js +507 -0
  184. package/dist/integrations/agent/model-map.js +28 -156
  185. package/dist/integrations/agent/request-lowering.js +66 -141
  186. package/dist/integrations/agent/runner-dispatch.js +143 -321
  187. package/dist/integrations/agent/runner.js +54 -14
  188. package/dist/integrations/lockfile.js +53 -101
  189. package/dist/llm/client.js +18 -6
  190. package/dist/llm/embedders/deterministic.js +2 -3
  191. package/dist/llm/embedders/profile.js +71 -0
  192. package/dist/llm/embedders/remote.js +11 -17
  193. package/dist/llm/feature-gate.js +0 -8
  194. package/dist/llm/index-passes.js +3 -5
  195. package/dist/llm/memory-infer.js +1 -2
  196. package/dist/llm/structured-call.js +5 -24
  197. package/dist/output/generic-render.js +23 -11
  198. package/dist/output/html-render.js +13 -10
  199. package/dist/output/render-registry.js +3 -32
  200. package/dist/output/shapes/helpers.js +25 -38
  201. package/dist/output/shapes/passthrough.js +1 -9
  202. package/dist/{indexer/graph/graph-types.js → output/text/bundle-rename.js} +4 -1
  203. package/dist/output/text/command-format.js +69 -31
  204. package/dist/output/text/helpers.js +1 -1
  205. package/dist/output/text/migrate.js +5 -14
  206. package/dist/output/text/proposal-format.js +48 -3
  207. package/dist/output/text/show-format.js +13 -17
  208. package/dist/output/text/workflow-format.js +0 -32
  209. package/dist/output/text.js +2 -0
  210. package/dist/registry/factory.js +4 -19
  211. package/dist/registry/network.js +66 -220
  212. package/dist/registry/providers/index.js +0 -2
  213. package/dist/registry/providers/skills-sh.js +3 -14
  214. package/dist/registry/providers/static-index.js +24 -26
  215. package/dist/registry/resolve.js +55 -131
  216. package/dist/scripts/akm-migrate-node.js +42948 -92369
  217. package/dist/scripts/akm-migrate.js +42935 -92354
  218. package/dist/setup/registry-stash-loader.js +4 -13
  219. package/dist/setup/semantic-assets.js +3 -44
  220. package/dist/setup/setup.js +1 -1
  221. package/dist/setup/steps/connection.js +5 -6
  222. package/dist/setup/steps/platforms.js +2 -2
  223. package/dist/setup/steps/tasks.js +25 -15
  224. package/dist/sources/provider-factory.js +17 -18
  225. package/dist/sources/providers/filesystem.js +2 -3
  226. package/dist/sources/providers/git-install.js +7 -1
  227. package/dist/sources/providers/git-provider.js +0 -3
  228. package/dist/sources/providers/git-stash.js +83 -21
  229. package/dist/sources/providers/npm.js +2 -4
  230. package/dist/sources/providers/provider-utils.js +5 -10
  231. package/dist/sources/providers/website.js +0 -2
  232. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  233. package/dist/sources/website-url.js +2 -2
  234. package/dist/storage/database.js +9 -35
  235. package/dist/storage/repositories/improve-ledger-repository.js +209 -0
  236. package/dist/storage/repositories/index-connection.js +39 -72
  237. package/dist/storage/repositories/index-entries-repository.js +131 -129
  238. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  239. package/dist/storage/repositories/index-entry-schema.js +101 -268
  240. package/dist/storage/repositories/index-fts-repository.js +86 -256
  241. package/dist/storage/repositories/index-links-repository.js +143 -0
  242. package/dist/storage/repositories/index-llm-cache-repository.js +7 -9
  243. package/dist/storage/repositories/index-meta-repository.js +6 -4
  244. package/dist/storage/repositories/index-schema.js +257 -325
  245. package/dist/storage/repositories/index-utility-repository.js +8 -29
  246. package/dist/storage/repositories/index-vec-repository.js +133 -414
  247. package/dist/storage/repositories/outcome-repository.js +2 -1
  248. package/dist/storage/repositories/proposals-repository.js +104 -1
  249. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  250. package/dist/storage/repositories/salience-repository.js +1 -19
  251. package/dist/storage/repositories/task-history-repository.js +26 -4
  252. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  253. package/dist/storage/sqlite-migrations.js +136 -0
  254. package/dist/storage/sqlite-pragmas.js +11 -9
  255. package/dist/storage/sqlite-transaction.js +170 -0
  256. package/dist/storage/state-db-integrity.js +130 -0
  257. package/dist/tasks/activation-config.js +134 -62
  258. package/dist/tasks/backends/cron.js +191 -302
  259. package/dist/tasks/backends/exec-utils.js +2 -5
  260. package/dist/tasks/backends/launchd.js +141 -748
  261. package/dist/tasks/backends/schtasks.js +119 -623
  262. package/dist/tasks/prepare/prepare-support.js +5 -15
  263. package/dist/tasks/prepare/prepare.js +0 -2
  264. package/dist/tasks/resolve-akm-bin.js +20 -79
  265. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  266. package/dist/tasks/run/load-task.js +1 -1
  267. package/dist/tasks/scheduler-binding.js +20 -238
  268. package/dist/tasks/scheduler-invocation.js +136 -244
  269. package/dist/tasks/scheduler-lock.js +53 -0
  270. package/dist/tasks/scheduler-sync.js +368 -679
  271. package/dist/tasks/source/parse-task-source.js +55 -9
  272. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  273. package/dist/tasks/source/task-to-v4.js +464 -88
  274. package/dist/workflows/authoring/authoring.js +3 -12
  275. package/dist/workflows/compile.js +211 -0
  276. package/dist/workflows/concurrency-policy.js +13 -74
  277. package/dist/workflows/exec/child-invocation.js +3 -17
  278. package/dist/workflows/exec/child-workflow.js +32 -141
  279. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  280. package/dist/workflows/exec/environment.js +98 -0
  281. package/dist/workflows/exec/exec-unit.js +33 -140
  282. package/dist/workflows/exec/frozen-judge.js +7 -59
  283. package/dist/workflows/exec/native-executor.js +82 -341
  284. package/dist/workflows/exec/param-secrets.js +29 -47
  285. package/dist/workflows/exec/run-workflow.js +154 -387
  286. package/dist/workflows/exec/scheduler.js +9 -36
  287. package/dist/workflows/exec/step-work.js +127 -430
  288. package/dist/workflows/exec/unit-dispatch.js +11 -63
  289. package/dist/workflows/exec/unit-writer.js +8 -52
  290. package/dist/workflows/exec/worktree.js +39 -273
  291. package/dist/workflows/freeze/child-output-references.js +4 -15
  292. package/dist/workflows/freeze/environment.js +99 -92
  293. package/dist/workflows/freeze/freeze.js +172 -0
  294. package/dist/workflows/freeze/step-values.js +19 -21
  295. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  296. package/dist/workflows/freeze/targets/command.js +10 -33
  297. package/dist/workflows/freeze/targets/script.js +5 -12
  298. package/dist/workflows/freeze/targets/shell.js +3 -6
  299. package/dist/workflows/freeze/targets/task.js +25 -80
  300. package/dist/workflows/freeze/task-bindings.js +20 -67
  301. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  302. package/dist/workflows/ir/params.js +6 -51
  303. package/dist/workflows/ir/plan-hash.js +2 -34
  304. package/dist/workflows/parser.js +140 -43
  305. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  306. package/dist/workflows/renderer.js +36 -69
  307. package/dist/workflows/resource-limits.js +12 -120
  308. package/dist/workflows/runtime/agent-identity.js +8 -40
  309. package/dist/workflows/runtime/run-outputs.js +3 -6
  310. package/dist/workflows/runtime/run-plan.js +316 -0
  311. package/dist/workflows/runtime/runs.js +48 -200
  312. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  313. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  314. package/dist/workflows/validate-summary.js +2 -7
  315. package/docs/integration/bundling-akm.md +49 -42
  316. package/docs/migration/README.md +1 -0
  317. package/docs/migration/release-notes/0.9.17.md +43 -0
  318. package/docs/migration/v0.9.1-to-v0.9.2.md +23 -7
  319. package/docs/reference/cli.md +232 -135
  320. package/docs/reference/configuration.md +71 -57
  321. package/docs/reference/data-and-telemetry.md +20 -21
  322. package/docs/reference/tasks.md +105 -39
  323. package/docs/reference/workflow-schema.md +14 -18
  324. package/docs/reference/workflows.md +6 -9
  325. package/package.json +1 -1
  326. package/schemas/akm-config.json +115 -738
  327. package/schemas/akm-workflow.json +1 -0
  328. package/dist/assets/improve-strategies/graph-refresh.json +0 -15
  329. package/dist/assets/prompts/contradiction-judge.md +0 -33
  330. package/dist/assets/prompts/graph-extract-system.md +0 -1
  331. package/dist/assets/prompts/graph-extract-user-prompt.md +0 -35
  332. package/dist/assets/prompts/metadata-enhance-system.md +0 -1
  333. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +0 -4
  334. package/dist/commands/health/advisories.js +0 -150
  335. package/dist/commands/health/metrics.js +0 -329
  336. package/dist/commands/health/surfaces.js +0 -102
  337. package/dist/commands/improve/anti-collapse.js +0 -83
  338. package/dist/commands/improve/collapse-detector.js +0 -432
  339. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  340. package/dist/commands/improve/consolidate/merge.js +0 -149
  341. package/dist/commands/improve/distill/promote-memory.js +0 -291
  342. package/dist/commands/improve/distill/quality-gate.js +0 -337
  343. package/dist/commands/improve/eval-cases.js +0 -52
  344. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  345. package/dist/commands/improve/proposal-envelope.js +0 -31
  346. package/dist/commands/improve/run-context.js +0 -123
  347. package/dist/commands/improve/shared.js +0 -31
  348. package/dist/commands/improve/source-identity.js +0 -28
  349. package/dist/commands/improve/triage.js +0 -96
  350. package/dist/commands/proposal/drain-policies.js +0 -151
  351. package/dist/commands/sources/update-transaction.js +0 -220
  352. package/dist/core/action-contributors.js +0 -28
  353. package/dist/core/config/config-version-shim.js +0 -101
  354. package/dist/core/fs-txn.js +0 -405
  355. package/dist/core/lexical-score.js +0 -25
  356. package/dist/core/maintenance-barrier.js +0 -167
  357. package/dist/execution/executable-identity.js +0 -105
  358. package/dist/execution/guarded-source.js +0 -427
  359. package/dist/indexer/db/graph-db.js +0 -444
  360. package/dist/indexer/graph/graph-boost.js +0 -427
  361. package/dist/indexer/graph/graph-dedup.js +0 -95
  362. package/dist/indexer/graph/graph-extraction.js +0 -1108
  363. package/dist/indexer/search/name-match.js +0 -35
  364. package/dist/indexer/search/ranking-contributors.js +0 -515
  365. package/dist/indexer/search/ranking-types.js +0 -4
  366. package/dist/indexer/walk/project-context.js +0 -192
  367. package/dist/integrations/agent/execution-cascade.js +0 -566
  368. package/dist/integrations/agent/execution-definitions.js +0 -202
  369. package/dist/integrations/agent/execution-lowering.js +0 -841
  370. package/dist/integrations/agent/execution-preparation.js +0 -98
  371. package/dist/integrations/agent/inline-execution.js +0 -74
  372. package/dist/llm/graph-extract.js +0 -728
  373. package/dist/llm/metadata-enhance.js +0 -96
  374. package/dist/registry/create-provider-registry.js +0 -29
  375. package/dist/registry/pinned-request-helper.js +0 -247
  376. package/dist/registry/pinned-transport.js +0 -717
  377. package/dist/sources/providers/index.js +0 -14
  378. package/dist/storage/engines/sqlite-migrations.js +0 -271
  379. package/dist/storage/repositories/canaries-repository.js +0 -107
  380. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  381. package/dist/storage/repositories/registry-cache.js +0 -113
  382. package/dist/tasks/scheduler-sync-preview.js +0 -52
  383. package/dist/tasks/source/task-to-v3.js +0 -507
  384. package/dist/workflows/freeze/resolve-steps.js +0 -86
  385. package/dist/workflows/freeze/source-freeze.js +0 -64
  386. package/dist/workflows/ir/compile.js +0 -321
  387. package/dist/workflows/ir/environment-v4.js +0 -330
  388. package/dist/workflows/ir/freeze-v4.js +0 -153
  389. package/dist/workflows/ir/schema-v4.js +0 -745
  390. package/dist/workflows/ir/schema.js +0 -354
  391. package/dist/workflows/program/schema.js +0 -77
  392. package/dist/workflows/runtime/checkin.js +0 -57
  393. package/dist/workflows/runtime/plan-classifier.js +0 -196
  394. package/dist/workflows/runtime/unit-checkin.js +0 -45
  395. package/dist/workflows/runtime/unit-phases.js +0 -20
  396. package/dist/workflows/schema.js +0 -4
  397. package/dist/workflows/source-ir/compile.js +0 -200
  398. package/dist/workflows/source-ir/program.js +0 -50
  399. package/dist/workflows/source-ir/result.js +0 -26
  400. package/dist/workflows/source-ir/schema.js +0 -786
  401. package/dist/workflows/source-ir/triggers.js +0 -79
  402. package/dist/workflows/source-ir/uses.js +0 -40
  403. package/dist/workflows/validator.js +0 -60
@@ -23,7 +23,8 @@
23
23
  * This file is intentionally NOT an adapter/DI/ports-and-adapters layer. It is
24
24
  * a plain module: a structural type plus a factory function. The handle it
25
25
  * returns is the real underlying driver instance (so e.g. `sqlite-vec`'s
26
- * `load(db)` receives the genuine driver handle and works unchanged).
26
+ * `load(db)`, used to drop the retired `entries_vec` table, receives the
27
+ * genuine driver handle and works unchanged).
27
28
  *
28
29
  * @module storage/database
29
30
  */
@@ -35,39 +36,13 @@ const isBun = !!process.versions?.bun;
35
36
  // Bun built-in, unresolvable on Node) nor `better-sqlite3` (an optional native
36
37
  // dep, possibly absent under Bun) is statically imported.
37
38
  const nodeRequire = createRequire(import.meta.url);
38
- // bun:sqlite — Bun built-in, no native build. Cannot run on Node.
39
- const bunSqliteProvider = {
40
- name: "bun:sqlite",
41
- supported: () => isBun,
42
- open: openBunDatabase,
43
- };
44
- // better-sqlite3 — native Node driver. Cannot run on Bun (oven-sh/bun#4290).
45
- const nodeSqliteProvider = {
46
- name: "better-sqlite3",
47
- supported: () => !isBun,
48
- open: openNodeDatabase,
49
- };
50
39
  /**
51
- * Ordered provider registry. The factory selects the first supported provider.
52
- * A future Postgres provider is appended here — and only here. Both SQLite
53
- * engines are kept as distinct providers (not collapsed) because no single
54
- * SQLite driver runs on both Bun and Node today.
55
- */
56
- const PROVIDERS = [bunSqliteProvider, nodeSqliteProvider];
57
- /** Select the provider for the current runtime. */
58
- function selectProvider() {
59
- const provider = PROVIDERS.find((p) => p.supported());
60
- if (!provider) {
61
- throw new Error(`No storage provider supports the current runtime (${isBun ? "Bun" : "Node"}).`);
62
- }
63
- return provider;
64
- }
65
- /**
66
- * Open a SQLite database handle at `path` via the active {@link StorageProvider}.
67
- * Returns a handle conforming to the structural {@link Database} type.
40
+ * Open a SQLite database handle at `path` on the current runtime's driver
41
+ * (`bun:sqlite` on Bun, `better-sqlite3` on Node). Returns a handle conforming
42
+ * to the structural {@link Database} type.
68
43
  */
69
44
  export function openDatabase(path, opts) {
70
- return selectProvider().open(path, opts);
45
+ return isBun ? openBunDatabase(path, opts) : openNodeDatabase(path, opts);
71
46
  }
72
47
  /**
73
48
  * {@link openDatabase} with a finalize-on-close guard (issue #720).
@@ -90,7 +65,7 @@ export function openDatabase(path, opts) {
90
65
  * force-finalizing under them changes behavior they were built on.
91
66
  */
92
67
  export function openDatabaseFinalizing(path, opts) {
93
- const db = selectProvider().open(path, opts);
68
+ const db = openDatabase(path, opts);
94
69
  const tracked = new Set();
95
70
  const origPrepare = db.prepare.bind(db);
96
71
  const origClose = db.close.bind(db);
@@ -251,9 +226,8 @@ function openNodeDatabase(path, opts) {
251
226
  // bun:sqlite also provides db.run(). Normalize the latter at the provider
252
227
  // boundary so callers and maintenance wrappers can rely on one contract.
253
228
  run: (sql, ...params) => db.prepare(sql).run(...params),
254
- // sqlite-vec's load(db) calls db.loadExtension(). Without forwarding it the
255
- // extension could never load on Node, so the vector fast path was dead
256
- // across the entire npm distribution even when sqlite-vec was installed.
229
+ // sqlite-vec's load(db) calls db.loadExtension(); without forwarding it the
230
+ // extension could never load on Node.
257
231
  loadExtension: db.loadExtension.bind(db),
258
232
  transaction: db.transaction.bind(db),
259
233
  get inTransaction() {
@@ -0,0 +1,209 @@
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
+ export const IMPROVE_LEDGER_OUTCOMES = [
5
+ "proposed",
6
+ "accepted",
7
+ "rejected",
8
+ "quality_rejected",
9
+ "review_needed",
10
+ "expired",
11
+ "unchanged",
12
+ "failed",
13
+ "judged_no_action",
14
+ ];
15
+ const MS_PER_DAY = 86_400_000;
16
+ const DETAIL_MAX_CHARS = 500;
17
+ /**
18
+ * Post-rejection windows by source: reflect 14 d, distill 30 d, every other
19
+ * source 7 d — the constants the rejection backoff always used.
20
+ */
21
+ export const LEDGER_REJECTION_WINDOW_DAYS = Object.freeze({
22
+ reflect: 14,
23
+ distill: 30,
24
+ });
25
+ export const LEDGER_DEFAULT_REJECTION_WINDOW_DAYS = 7;
26
+ /** A proposal nobody reviewed inside the retention window: short grace, not a rejection backoff. */
27
+ export const LEDGER_EXPIRED_GRACE_DAYS = 1;
28
+ /** Revisit cadence for a ref the stage looked at and had nothing to do (or is still pending). */
29
+ export const LEDGER_REVISIT_CADENCE_DAYS = 7;
30
+ /**
31
+ * The consolidate pair pass's own ledger source (alpha.9): kept apart from
32
+ * the promote pass's `consolidate` rows so the two candidate-selection
33
+ * cadences never collide on the same `(stash, ref, source)` key. Its
34
+ * eligibility is entirely content-driven (`content_hash` above, compared by
35
+ * `selectInitiators` in `src/commands/improve/consolidate/pair-pass.ts`) —
36
+ * {@link windowDays} below gives it no `next_eligible_at` timer at all, so a
37
+ * row never "expires" on its own; only a content change makes the ref
38
+ * eligible again.
39
+ */
40
+ export const PAIR_PASS_LEDGER_SOURCE = "consolidate-pair";
41
+ /**
42
+ * Outcomes whose window a fresh signal on the asset (new feedback, a content
43
+ * change) cannot lift. Every other window is a revisit cadence that a signal
44
+ * newer than `last_attempt_at` lifts.
45
+ */
46
+ export const LEDGER_HARD_OUTCOMES = new Set([
47
+ "rejected",
48
+ "quality_rejected",
49
+ "expired",
50
+ ]);
51
+ function windowDays(source, outcome) {
52
+ // The pair pass's own eligibility never reads next_eligible_at (it compares
53
+ // content_hash instead — selectInitiators in pair-pass.ts) — recording a
54
+ // window here would be a number nothing enforces, so every row it writes
55
+ // stays "eligible now" regardless of outcome.
56
+ if (source === PAIR_PASS_LEDGER_SOURCE)
57
+ return null;
58
+ switch (outcome) {
59
+ case "rejected":
60
+ case "quality_rejected":
61
+ return LEDGER_REJECTION_WINDOW_DAYS[source] ?? LEDGER_DEFAULT_REJECTION_WINDOW_DAYS;
62
+ case "expired":
63
+ return LEDGER_EXPIRED_GRACE_DAYS;
64
+ case "unchanged":
65
+ case "judged_no_action":
66
+ case "proposed":
67
+ case "review_needed":
68
+ return LEDGER_REVISIT_CADENCE_DAYS;
69
+ case "accepted":
70
+ case "failed":
71
+ return null;
72
+ }
73
+ }
74
+ /**
75
+ * The single cadence function: when a `(source, outcome)` recorded at
76
+ * `fromIso` becomes eligible again, or `null` for "immediately".
77
+ */
78
+ export function nextEligibleAt(source, outcome, fromIso) {
79
+ const from = Date.parse(fromIso);
80
+ if (!Number.isFinite(from))
81
+ return null;
82
+ const days = windowDays(source, outcome);
83
+ return days === null ? null : new Date(from + days * MS_PER_DAY).toISOString();
84
+ }
85
+ /**
86
+ * Whether the ledger blocks another attempt on this row at `nowIso`.
87
+ * `signalSinceIso` is the newest signal on the asset (feedback, content
88
+ * change); a signal newer than the last attempt lifts a soft window but never
89
+ * a hard one ({@link LEDGER_HARD_OUTCOMES}).
90
+ */
91
+ export function isLedgerBlocked(row, nowIso, signalSinceIso) {
92
+ if (!row?.nextEligibleAt)
93
+ return false;
94
+ if (row.nextEligibleAt <= nowIso)
95
+ return false;
96
+ if (LEDGER_HARD_OUTCOMES.has(row.outcome))
97
+ return true;
98
+ return !(signalSinceIso !== undefined && signalSinceIso > row.lastAttemptAt);
99
+ }
100
+ function toRow(row) {
101
+ return {
102
+ stashDir: row.stash_dir,
103
+ ref: row.ref,
104
+ source: row.source,
105
+ lastAttemptAt: row.last_attempt_at,
106
+ // Tolerate an outcome a newer release may add: it still carries a window.
107
+ outcome: row.outcome,
108
+ nextEligibleAt: row.next_eligible_at,
109
+ proposalId: row.proposal_id,
110
+ detail: row.detail,
111
+ contentHash: row.content_hash,
112
+ };
113
+ }
114
+ function trimDetail(detail) {
115
+ if (detail === undefined)
116
+ return null;
117
+ const trimmed = detail.trim();
118
+ if (trimmed.length === 0)
119
+ return null;
120
+ return trimmed.length > DETAIL_MAX_CHARS ? `${trimmed.slice(0, DETAIL_MAX_CHARS - 1)}…` : trimmed;
121
+ }
122
+ /** Record an attempt on `(stashDir, ref, source)`: upsert the row and its cadence. */
123
+ export function recordImproveLedger(db, input) {
124
+ const row = {
125
+ stashDir: input.stashDir,
126
+ ref: input.ref,
127
+ source: input.source,
128
+ lastAttemptAt: input.at,
129
+ outcome: input.outcome,
130
+ nextEligibleAt: nextEligibleAt(input.source, input.outcome, input.at),
131
+ proposalId: input.proposalId ?? null,
132
+ detail: trimDetail(input.detail),
133
+ contentHash: input.contentHash ?? null,
134
+ };
135
+ db.prepare(`INSERT INTO improve_ledger
136
+ (stash_dir, ref, source, last_attempt_at, outcome, next_eligible_at, proposal_id, detail, content_hash)
137
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
138
+ ON CONFLICT(stash_dir, ref, source) DO UPDATE SET
139
+ last_attempt_at = excluded.last_attempt_at,
140
+ outcome = excluded.outcome,
141
+ next_eligible_at = excluded.next_eligible_at,
142
+ proposal_id = excluded.proposal_id,
143
+ detail = excluded.detail,
144
+ content_hash = excluded.content_hash`).run(row.stashDir, row.ref, row.source, row.lastAttemptAt, row.outcome, row.nextEligibleAt, row.proposalId, row.detail, row.contentHash);
145
+ return row;
146
+ }
147
+ /**
148
+ * Record a decision (accept / reject / expire / revert) on the proposal a row
149
+ * was minted for. The row is found by `proposal_id` — the proposal's ref may
150
+ * differ from the ledger key (a distill proposal for `lessons/x` is keyed by
151
+ * its input `memories/x`) — and `last_attempt_at` is kept: the window starts
152
+ * at the decision, the attempt happened when it happened. A proposal no row
153
+ * knows (minted before the ledger existed) gets a row keyed by its own ref.
154
+ */
155
+ export function recordImproveLedgerDecision(db, input) {
156
+ const changes = db
157
+ .prepare(`UPDATE improve_ledger
158
+ SET outcome = ?, next_eligible_at = ?, detail = ?
159
+ WHERE stash_dir = ? AND proposal_id = ?`)
160
+ .run(input.outcome, nextEligibleAt(input.source, input.outcome, input.at), trimDetail(input.detail), input.stashDir, input.proposalId).changes;
161
+ if (Number(changes) > 0)
162
+ return;
163
+ recordImproveLedger(db, {
164
+ stashDir: input.stashDir,
165
+ ref: input.ref,
166
+ source: input.source,
167
+ outcome: input.outcome,
168
+ at: input.at,
169
+ proposalId: input.proposalId,
170
+ ...(input.detail !== undefined ? { detail: input.detail } : {}),
171
+ });
172
+ }
173
+ /**
174
+ * Should-fix 6 (second review round): a read-only or dry-run open never
175
+ * migrates, so it can land on a state.db from before migration 029 added
176
+ * `content_hash` — reading it there threw "no such column", which
177
+ * `loadRetrievalScope`'s own catch then reported as "usage history
178
+ * unreadable", making the WHOLE scope `undefined` (every asset eligible) on
179
+ * every read-only/dry-run call against an as-yet-unmigrated database. A
180
+ * per-connection cache, since a real `Database` handle's schema does not
181
+ * change mid-lifetime and this is checked on every ledger read.
182
+ */
183
+ const hasContentHashColumnCache = new WeakMap();
184
+ function hasContentHashColumn(db) {
185
+ const cached = hasContentHashColumnCache.get(db);
186
+ if (cached !== undefined)
187
+ return cached;
188
+ const has = db.prepare("PRAGMA table_info(improve_ledger)").all().some((c) => c.name === "content_hash");
189
+ hasContentHashColumnCache.set(db, has);
190
+ return has;
191
+ }
192
+ export function getImproveLedgerRow(db, stashDir, ref, source) {
193
+ const withHash = hasContentHashColumn(db);
194
+ const row = db
195
+ .prepare(`SELECT stash_dir, ref, source, last_attempt_at, outcome, next_eligible_at, proposal_id, detail${withHash ? ", content_hash" : ""}
196
+ FROM improve_ledger WHERE stash_dir = ? AND ref = ? AND source = ?`)
197
+ .get(stashDir, ref, source);
198
+ return row ? toRow(withHash ? row : { ...row, content_hash: null }) : undefined;
199
+ }
200
+ /** Every row for one stash, optionally narrowed to `sources`. */
201
+ export function listImproveLedgerRows(db, stashDir, sources) {
202
+ const withHash = hasContentHashColumn(db);
203
+ const sourceFilter = sources && sources.length > 0 ? ` AND source IN (${sources.map(() => "?").join(", ")})` : "";
204
+ const rows = db
205
+ .prepare(`SELECT stash_dir, ref, source, last_attempt_at, outcome, next_eligible_at, proposal_id, detail${withHash ? ", content_hash" : ""}
206
+ FROM improve_ledger WHERE stash_dir = ?${sourceFilter} ORDER BY ref ASC, source ASC`)
207
+ .all(stashDir, ...(sources && sources.length > 0 ? sources : []));
208
+ return rows.map((row) => toRow(withHash ? row : { ...row, content_hash: null }));
209
+ }
@@ -4,14 +4,13 @@
4
4
  /**
5
5
  * `index.db` connection lifecycle for the storage layer.
6
6
  *
7
- * Opens/closes the index database, arming the sqlite-vec extension and (for the
8
- * managed open path) running `ensureSchema`. This module lives BELOW the
9
- * indexer, so the storage loan helpers (`index-db.ts`, `registry-cache.ts`)
7
+ * Opens/closes the index database, running `ensureSchema` on the managed
8
+ * (writable) open path. This module lives BELOW the
9
+ * indexer, so the storage loan helpers (`index-db.ts`, `registry-index-cache-repository.ts`)
10
10
  * import their opener from a sibling here instead of reaching up into the
11
11
  * indexer — inverting the old storage→indexer arrow.
12
12
  */
13
13
  import fs from "node:fs";
14
- import { createRequire } from "node:module";
15
14
  import { ConfigError } from "../../core/errors.js";
16
15
  import { classifyPathAccess, describeInaccessiblePath } from "../../core/path-access.js";
17
16
  import { getDbPath } from "../../core/paths.js";
@@ -20,9 +19,8 @@ import { openDatabase } from "../database.js";
20
19
  import { openManagedDatabase } from "../managed-db.js";
21
20
  import { SQLITE_BUSY_TIMEOUT_MS } from "../sqlite-pragmas.js";
22
21
  import { openSqliteReadSnapshot, SqliteReadSnapshotUnavailableError } from "../sqlite-read-snapshot.js";
23
- import { CANONICAL_INDEX_DB_VERSION, classifyIndexGeneration, isCanonicalIndexGeneration } from "./index-entry-schema.js";
24
- import { ensureSchema } from "./index-schema.js";
25
- import { loadVecExtension, warnIfVecMissing } from "./index-vec-repository.js";
22
+ import { CANONICAL_INDEX_DB_VERSION } from "./index-entry-schema.js";
23
+ import { ensureSchema, newerIndexLayoutError } from "./index-schema.js";
26
24
  /**
27
25
  * Whether `error` is SQLite reporting on-disk corruption (`SQLITE_CORRUPT`,
28
26
  * "database disk image is malformed") rather than a permission, lock, or
@@ -41,21 +39,11 @@ export function openIndexDatabase(dbPath, options) {
41
39
  const spec = {
42
40
  path: resolvedPath,
43
41
  init: (db) => {
44
- // Try to load sqlite-vec extension
45
- loadVecExtension(db);
46
42
  // Source update uses this narrow lifecycle seam to ATTACH state.db and
47
43
  // open its coordinator-owned outer transaction before ensureSchema or
48
44
  // any indexer write can mutate the live generation.
49
45
  options?.beforeSchema?.(db);
50
- // Dim resolution: explicit option wins; otherwise consult the on-disk
51
- // config so unparameterised opens (registry providers, graph helpers,
52
- // ad-hoc CLI subcommands) honour the operator-declared dimension. Only if
53
- // both are absent do we fall through to the no-clobber path, which keeps
54
- // ensureSchema from touching `index_meta.embeddingDim` at all.
55
- const resolvedDim = options?.embeddingDim ?? resolveConfiguredEmbeddingDim();
56
- ensureSchema(db, resolvedDim);
57
- // Warn once at init if using JS fallback with many entries
58
- warnIfVecMissing(db, { once: true });
46
+ ensureSchema(db);
59
47
  },
60
48
  };
61
49
  try {
@@ -66,10 +54,9 @@ export function openIndexDatabase(dbPath, options) {
66
54
  // (see src/core/state-db.ts's "Why a separate database from index.db"
67
55
  // note) — so real on-disk corruption is recovered by deleting the file
68
56
  // and rebuilding, not by surfacing a raw SQLITE_CORRUPT to the caller or
69
- // quietly falling through to an unreadable index. This mirrors the
70
- // existing stale-version-marker rebuild below, one layer further down
71
- // (that path opens fine and rewrites tables in place; corruption prevents
72
- // even opening, so the file itself has to go first).
57
+ // quietly falling through to an unreadable index (#865). This is the ONE
58
+ // from-scratch rebuild: an older layout is migrated in place by
59
+ // ensureSchema, never dropped.
73
60
  if (!isCorruptionError(error))
74
61
  throw error;
75
62
  warn(`Index database is corrupt at ${resolvedPath} — rebuilding.`);
@@ -85,34 +72,9 @@ export function openIndexDatabase(dbPath, options) {
85
72
  return openManagedDatabase(spec);
86
73
  }
87
74
  }
88
- /**
89
- * Read the operator-configured embedding dimension from the on-disk config.
90
- * Returns `undefined` when no config file is present, when the config has
91
- * no `embedding.dimension` set, or when reading the config throws (e.g.
92
- * inside isolated test fixtures with no XDG home). Failure is silent on
93
- * purpose — every openDatabase() call would otherwise have to handle a
94
- * config-not-found error path, and the fallback (no-clobber semantics) is
95
- * already correct.
96
- */
97
- function resolveConfiguredEmbeddingDim() {
98
- try {
99
- const esmRequire = createRequire(import.meta.url);
100
- const { loadConfig } = esmRequire("../../core/config/config");
101
- const dim = loadConfig().embedding?.dimension;
102
- if (typeof dim === "number" && Number.isInteger(dim) && dim > 0 && dim <= 4096) {
103
- return dim;
104
- }
105
- return undefined;
106
- }
107
- catch {
108
- return undefined;
109
- }
110
- }
111
75
  export function openExistingDatabase(dbPath) {
112
- // Existing-DB callers do not mutate schema or embedding metadata on open.
113
- // They do validate the exact current derived generation before returning a
114
- // handle, so no current reader can accidentally serve a populated legacy
115
- // table and fail later on its first canonical-column query.
76
+ // Existing-DB callers do not mutate schema or embedding metadata on open;
77
+ // they serve an older layout as-is and refuse a newer one (see checkIndexLayout).
116
78
  //
117
79
  // "Existing" is load-bearing: a missing file throws instead of being
118
80
  // created. Create-on-open used to leave a schema-less index.db behind (a
@@ -126,15 +88,9 @@ export function openExistingDatabase(dbPath) {
126
88
  if (classifyPathAccess(resolvedPath).access === "absent") {
127
89
  throw new Error(`Index database not found at ${resolvedPath}. Run 'akm index' to build it.`);
128
90
  }
129
- const db = openManagedDatabase({
130
- path: resolvedPath,
131
- init: (db) => {
132
- loadVecExtension(db);
133
- },
134
- create: false,
135
- });
91
+ const db = openManagedDatabase({ path: resolvedPath, create: false });
136
92
  try {
137
- assertCanonicalIndexGeneration(db, resolvedPath);
93
+ checkIndexLayout(db, resolvedPath);
138
94
  return db;
139
95
  }
140
96
  catch (error) {
@@ -143,21 +99,29 @@ export function openExistingDatabase(dbPath) {
143
99
  }
144
100
  }
145
101
  /**
146
- * Read callers must never receive a known-incompatible derived index. The
147
- * writable opener owns rebuilding an older generation; a reader can only
148
- * report the one action that is safe for the direction of the mismatch.
102
+ * A reader serves an older layout as-is (the FTS readers understand both
103
+ * layouts, and a missing table degrades at the caller — keyword-only search,
104
+ * an inline rebuild, or a "run akm index" notice) and names it once per
105
+ * process; the next writable open migrates it in place. A newer layout is
106
+ * refused, naming the upgrade ({@link newerIndexLayoutError}).
149
107
  */
150
- function assertCanonicalIndexGeneration(db, resolvedPath) {
151
- if (isCanonicalIndexGeneration(db))
108
+ function checkIndexLayout(db, resolvedPath) {
109
+ let stored;
110
+ try {
111
+ const row = db.prepare("SELECT value FROM index_meta WHERE key = 'version'").get();
112
+ if (!row)
113
+ return;
114
+ stored = Number(row.value);
115
+ }
116
+ catch {
152
117
  return;
153
- const classification = classifyIndexGeneration(db);
154
- const stored = classification.storedVersion ?? "unknown";
155
- if (classification.status === "newer") {
156
- throw new ConfigError(`Index database at ${resolvedPath} was built by a newer akm (stored generation ${stored}; ` +
157
- `this binary understands ${CANONICAL_INDEX_DB_VERSION}). Upgrade akm to use this index.`, "INDEX_SCHEMA_INCOMPATIBLE", "Upgrade akm to a version that understands this index generation.");
158
118
  }
159
- throw new ConfigError(`Index database at ${resolvedPath} is not usable with this akm's derived schema (stored generation ${stored}; ` +
160
- `this binary understands ${CANONICAL_INDEX_DB_VERSION}). Run 'akm index' to rebuild it.`, "INDEX_SCHEMA_INCOMPATIBLE", "Run `akm index` to rebuild the derived index from the currently materialized sources.");
119
+ if (!Number.isFinite(stored) || stored === CANONICAL_INDEX_DB_VERSION)
120
+ return;
121
+ if (stored > CANONICAL_INDEX_DB_VERSION)
122
+ throw newerIndexLayoutError(stored, resolvedPath);
123
+ warnOnce(`index-db-layout:${resolvedPath}`, `Index database at ${resolvedPath} uses an older layout (${stored}; this akm writes ${CANONICAL_INDEX_DB_VERSION}). ` +
124
+ "Serving it as-is; the next 'akm index' migrates it in place.");
161
125
  }
162
126
  /**
163
127
  * Refuse to treat an UNREADABLE index as a missing one (#791).
@@ -216,10 +180,13 @@ export function openReadonlyExistingDatabase(dbPath, options) {
216
180
  // never block — but in the DELETE/TRUNCATE modes the network-FS fallback and
217
181
  // AKM_SQLITE_JOURNAL_MODE can select, a concurrent writer makes every read
218
182
  // fail instantly with SQLITE_BUSY. busy_timeout is legal on a read-only
219
- // connection, so apply just that one.
183
+ // connection, so apply just that one. `busyTimeoutMs` defaults to the
184
+ // shared 30s constant; a caller that must never sit behind another akm
185
+ // process's write lock for long (e.g. `akm info`) can pass a much shorter
186
+ // bound instead.
220
187
  try {
221
- db.exec(`PRAGMA busy_timeout = ${SQLITE_BUSY_TIMEOUT_MS}`);
222
- assertCanonicalIndexGeneration(db, resolvedPath);
188
+ db.exec(`PRAGMA busy_timeout = ${options?.busyTimeoutMs ?? SQLITE_BUSY_TIMEOUT_MS}`);
189
+ checkIndexLayout(db, resolvedPath);
223
190
  return db;
224
191
  }
225
192
  catch (error) {