akm-cli 0.9.17-alpha.3 → 0.9.17-alpha.5

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 (346) hide show
  1. package/CHANGELOG.md +760 -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/lint/base-linter.js +19 -5
  53. package/dist/commands/proposal/drain.js +251 -644
  54. package/dist/commands/proposal/proposal-cli.js +3 -18
  55. package/dist/commands/proposal/proposal-types.js +20 -41
  56. package/dist/commands/proposal/proposal.js +1 -2
  57. package/dist/commands/proposal/propose.js +134 -160
  58. package/dist/commands/proposal/repository.js +502 -1487
  59. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  60. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  61. package/dist/commands/proposal/validators/proposals.js +13 -89
  62. package/dist/commands/read/curate.js +63 -413
  63. package/dist/commands/read/search-cli.js +16 -33
  64. package/dist/commands/read/search.js +17 -23
  65. package/dist/commands/read/show.js +2 -13
  66. package/dist/commands/sources/bundle-cli.js +25 -2
  67. package/dist/commands/sources/bundle-config-ops.js +4 -0
  68. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  69. package/dist/commands/sources/info.js +2 -11
  70. package/dist/commands/sources/installed-stashes.js +197 -746
  71. package/dist/commands/sources/schema-repair.js +98 -129
  72. package/dist/commands/sources/source-add.js +62 -12
  73. package/dist/commands/sources/source-manage.js +9 -2
  74. package/dist/commands/sources/stash-cli.js +1 -1
  75. package/dist/commands/tasks/explain.js +10 -13
  76. package/dist/commands/tasks/tasks-cli.js +9 -8
  77. package/dist/commands/tasks/tasks.js +326 -930
  78. package/dist/commands/tasks/validate.js +42 -21
  79. package/dist/commands/workflow/plan.js +22 -29
  80. package/dist/commands/workflow-cli.js +4 -4
  81. package/dist/core/adapter/adapters/akm-adapter.js +0 -1
  82. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  83. package/dist/core/adapter/adapters/akm-metadata.js +11 -12
  84. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  85. package/dist/core/adapter/execution-source.js +17 -29
  86. package/dist/core/asset/asset-placement.js +4 -13
  87. package/dist/core/asset/resolve-ref.js +1 -1
  88. package/dist/core/bundle-id.js +42 -5
  89. package/dist/core/bundle-rename.js +291 -0
  90. package/dist/core/config/config-io.js +1 -2
  91. package/dist/core/config/config-schema.js +1 -33
  92. package/dist/core/config/config-walker.js +1 -1
  93. package/dist/core/config/config.js +163 -68
  94. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  95. package/dist/core/config/schema/embedding.js +20 -5
  96. package/dist/core/config/schema/engines.js +5 -0
  97. package/dist/core/config/schema/execution.js +1 -1
  98. package/dist/core/config/schema/experimental.js +1 -1
  99. package/dist/core/config/schema/improve-processes.js +21 -95
  100. package/dist/core/config/schema/improve.js +4 -42
  101. package/dist/core/config/schema/scheduler.js +12 -12
  102. package/dist/core/config/schema/search.js +6 -22
  103. package/dist/core/env-secret-ref.js +0 -1
  104. package/dist/core/errors.js +8 -9
  105. package/dist/core/file-lock.js +76 -173
  106. package/dist/core/logs-db.js +2 -2
  107. package/dist/core/paths.js +0 -27
  108. package/dist/core/redaction.js +109 -2
  109. package/dist/core/run-lock.js +2 -5
  110. package/dist/core/spawn-env.js +1 -1
  111. package/dist/core/state/migrations.js +108 -61
  112. package/dist/core/state-db-scope.js +2 -4
  113. package/dist/core/state-db.js +126 -692
  114. package/dist/core/type-presentation.js +1 -9
  115. package/dist/core/write-source.js +293 -1012
  116. package/dist/execution/input-contract.js +1 -1
  117. package/dist/execution/resolved-request.js +135 -689
  118. package/dist/execution/source.js +63 -257
  119. package/dist/execution/target-ref.js +1 -1
  120. package/dist/indexer/bundle-identity-guard.js +2 -2
  121. package/dist/indexer/db/graph-db.js +106 -46
  122. package/dist/indexer/ensure-index.js +44 -85
  123. package/dist/indexer/graph/graph-extraction.js +340 -562
  124. package/dist/indexer/graph/graph-related.js +130 -0
  125. package/dist/indexer/index-rebuild-lock.js +3 -11
  126. package/dist/indexer/index-writer-lock.js +8 -17
  127. package/dist/indexer/index-written-assets.js +139 -151
  128. package/dist/indexer/indexer.js +524 -846
  129. package/dist/indexer/materialize-embeddings.js +60 -397
  130. package/dist/indexer/passes/memory-inference.js +81 -90
  131. package/dist/indexer/passes/metadata.js +132 -200
  132. package/dist/indexer/read-preflight.js +0 -7
  133. package/dist/indexer/scan/doc-to-entry.js +1 -3
  134. package/dist/indexer/scan/drain-dir.js +1 -1
  135. package/dist/indexer/search/db-search.js +181 -590
  136. package/dist/indexer/search/fts-query.js +30 -41
  137. package/dist/indexer/search/ranking.js +28 -154
  138. package/dist/indexer/search/search-attribution.js +12 -32
  139. package/dist/indexer/search/search-fields.js +11 -15
  140. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  141. package/dist/indexer/search/search-source.js +1 -4
  142. package/dist/indexer/usage/usage-events.js +2 -7
  143. package/dist/integrations/agent/engine-fallback.js +23 -40
  144. package/dist/integrations/agent/engine-resolution.js +93 -183
  145. package/dist/integrations/agent/execution.js +507 -0
  146. package/dist/integrations/agent/model-map.js +28 -156
  147. package/dist/integrations/agent/request-lowering.js +66 -141
  148. package/dist/integrations/agent/runner-dispatch.js +143 -321
  149. package/dist/integrations/agent/runner.js +54 -14
  150. package/dist/integrations/lockfile.js +53 -101
  151. package/dist/llm/embedders/deterministic.js +2 -3
  152. package/dist/llm/embedders/profile.js +71 -0
  153. package/dist/llm/embedders/remote.js +10 -15
  154. package/dist/llm/graph-extract.js +3 -12
  155. package/dist/llm/index-passes.js +3 -5
  156. package/dist/llm/memory-infer.js +1 -2
  157. package/dist/llm/metadata-enhance.js +1 -2
  158. package/dist/llm/structured-call.js +5 -24
  159. package/dist/output/generic-render.js +23 -11
  160. package/dist/output/html-render.js +13 -10
  161. package/dist/output/render-registry.js +3 -32
  162. package/dist/output/shapes/helpers.js +2 -34
  163. package/dist/output/shapes/passthrough.js +1 -9
  164. package/dist/{indexer/search/ranking-types.js → output/text/bundle-rename.js} +4 -1
  165. package/dist/output/text/command-format.js +60 -23
  166. package/dist/output/text/helpers.js +1 -1
  167. package/dist/output/text/migrate.js +5 -14
  168. package/dist/output/text/proposal-format.js +1 -2
  169. package/dist/output/text/workflow-format.js +0 -32
  170. package/dist/output/text.js +2 -0
  171. package/dist/registry/factory.js +4 -19
  172. package/dist/registry/network.js +66 -220
  173. package/dist/registry/providers/index.js +0 -2
  174. package/dist/registry/providers/skills-sh.js +3 -14
  175. package/dist/registry/providers/static-index.js +24 -26
  176. package/dist/registry/resolve.js +55 -131
  177. package/dist/scripts/akm-migrate-node.js +43940 -93320
  178. package/dist/scripts/akm-migrate.js +43700 -93078
  179. package/dist/setup/registry-stash-loader.js +4 -13
  180. package/dist/setup/semantic-assets.js +3 -44
  181. package/dist/setup/setup.js +1 -1
  182. package/dist/setup/steps/tasks.js +25 -15
  183. package/dist/sources/provider-factory.js +17 -18
  184. package/dist/sources/providers/filesystem.js +2 -3
  185. package/dist/sources/providers/git-install.js +7 -1
  186. package/dist/sources/providers/git-provider.js +0 -3
  187. package/dist/sources/providers/git-stash.js +0 -17
  188. package/dist/sources/providers/npm.js +2 -4
  189. package/dist/sources/providers/provider-utils.js +5 -10
  190. package/dist/sources/providers/website.js +0 -2
  191. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  192. package/dist/sources/website-url.js +2 -2
  193. package/dist/storage/database.js +9 -35
  194. package/dist/storage/repositories/improve-ledger-repository.js +168 -0
  195. package/dist/storage/repositories/index-connection.js +34 -70
  196. package/dist/storage/repositories/index-entries-repository.js +69 -111
  197. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  198. package/dist/storage/repositories/index-entry-schema.js +83 -269
  199. package/dist/storage/repositories/index-fts-repository.js +86 -256
  200. package/dist/storage/repositories/index-llm-cache-repository.js +17 -0
  201. package/dist/storage/repositories/index-meta-repository.js +6 -4
  202. package/dist/storage/repositories/index-schema.js +192 -220
  203. package/dist/storage/repositories/index-utility-repository.js +8 -29
  204. package/dist/storage/repositories/index-vec-repository.js +133 -414
  205. package/dist/storage/repositories/outcome-repository.js +2 -1
  206. package/dist/storage/repositories/proposals-repository.js +35 -0
  207. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  208. package/dist/storage/repositories/task-history-repository.js +26 -4
  209. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  210. package/dist/storage/sqlite-migrations.js +136 -0
  211. package/dist/storage/sqlite-pragmas.js +11 -9
  212. package/dist/storage/sqlite-transaction.js +170 -0
  213. package/dist/storage/state-db-integrity.js +34 -27
  214. package/dist/tasks/activation-config.js +134 -62
  215. package/dist/tasks/backends/cron.js +129 -277
  216. package/dist/tasks/backends/exec-utils.js +2 -5
  217. package/dist/tasks/backends/launchd.js +125 -745
  218. package/dist/tasks/backends/schtasks.js +101 -620
  219. package/dist/tasks/prepare/prepare-support.js +5 -15
  220. package/dist/tasks/prepare/prepare.js +0 -2
  221. package/dist/tasks/resolve-akm-bin.js +20 -79
  222. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  223. package/dist/tasks/scheduler-binding.js +18 -238
  224. package/dist/tasks/scheduler-invocation.js +52 -52
  225. package/dist/tasks/scheduler-lock.js +53 -0
  226. package/dist/tasks/scheduler-sync.js +361 -751
  227. package/dist/tasks/source/parse-task-source.js +160 -10
  228. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  229. package/dist/tasks/source/task-to-v4.js +2 -2
  230. package/dist/workflows/authoring/authoring.js +3 -12
  231. package/dist/workflows/compile.js +211 -0
  232. package/dist/workflows/concurrency-policy.js +13 -74
  233. package/dist/workflows/exec/child-invocation.js +3 -17
  234. package/dist/workflows/exec/child-workflow.js +32 -141
  235. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  236. package/dist/workflows/exec/environment.js +98 -0
  237. package/dist/workflows/exec/exec-unit.js +33 -140
  238. package/dist/workflows/exec/frozen-judge.js +7 -59
  239. package/dist/workflows/exec/native-executor.js +82 -341
  240. package/dist/workflows/exec/param-secrets.js +29 -47
  241. package/dist/workflows/exec/run-workflow.js +154 -387
  242. package/dist/workflows/exec/scheduler.js +9 -36
  243. package/dist/workflows/exec/step-work.js +127 -430
  244. package/dist/workflows/exec/unit-dispatch.js +11 -63
  245. package/dist/workflows/exec/unit-writer.js +8 -52
  246. package/dist/workflows/exec/worktree.js +39 -273
  247. package/dist/workflows/freeze/child-output-references.js +4 -15
  248. package/dist/workflows/freeze/environment.js +99 -92
  249. package/dist/workflows/freeze/freeze.js +172 -0
  250. package/dist/workflows/freeze/step-values.js +19 -21
  251. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  252. package/dist/workflows/freeze/targets/command.js +10 -33
  253. package/dist/workflows/freeze/targets/script.js +5 -12
  254. package/dist/workflows/freeze/targets/shell.js +3 -6
  255. package/dist/workflows/freeze/targets/task.js +25 -80
  256. package/dist/workflows/freeze/task-bindings.js +20 -67
  257. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  258. package/dist/workflows/ir/params.js +6 -51
  259. package/dist/workflows/ir/plan-hash.js +2 -34
  260. package/dist/workflows/parser.js +140 -43
  261. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  262. package/dist/workflows/renderer.js +36 -69
  263. package/dist/workflows/resource-limits.js +12 -120
  264. package/dist/workflows/runtime/agent-identity.js +8 -40
  265. package/dist/workflows/runtime/run-outputs.js +3 -6
  266. package/dist/workflows/runtime/run-plan.js +316 -0
  267. package/dist/workflows/runtime/runs.js +48 -200
  268. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  269. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  270. package/dist/workflows/validate-summary.js +2 -7
  271. package/docs/integration/bundling-akm.md +49 -42
  272. package/docs/migration/README.md +1 -0
  273. package/docs/migration/release-notes/0.9.17.md +41 -0
  274. package/docs/migration/v0.9.1-to-v0.9.2.md +19 -7
  275. package/docs/reference/cli.md +182 -125
  276. package/docs/reference/configuration.md +49 -56
  277. package/docs/reference/data-and-telemetry.md +19 -20
  278. package/docs/reference/tasks.md +86 -38
  279. package/docs/reference/workflow-schema.md +14 -18
  280. package/docs/reference/workflows.md +6 -9
  281. package/package.json +1 -1
  282. package/schemas/akm-config.json +87 -406
  283. package/dist/commands/health/advisories.js +0 -150
  284. package/dist/commands/health/metrics.js +0 -329
  285. package/dist/commands/health/surfaces.js +0 -102
  286. package/dist/commands/improve/anti-collapse.js +0 -83
  287. package/dist/commands/improve/collapse-detector.js +0 -432
  288. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  289. package/dist/commands/improve/consolidate/merge.js +0 -146
  290. package/dist/commands/improve/distill/promote-memory.js +0 -329
  291. package/dist/commands/improve/distill/quality-gate.js +0 -500
  292. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  293. package/dist/commands/improve/proposal-envelope.js +0 -31
  294. package/dist/commands/improve/run-context.js +0 -123
  295. package/dist/commands/improve/shared.js +0 -21
  296. package/dist/commands/improve/source-identity.js +0 -28
  297. package/dist/commands/improve/triage.js +0 -96
  298. package/dist/commands/proposal/drain-policies.js +0 -151
  299. package/dist/commands/sources/update-transaction.js +0 -220
  300. package/dist/core/action-contributors.js +0 -28
  301. package/dist/core/config/config-version-shim.js +0 -101
  302. package/dist/core/config/retired-experimental-keys-shim.js +0 -62
  303. package/dist/core/fs-txn.js +0 -405
  304. package/dist/core/lexical-score.js +0 -25
  305. package/dist/core/maintenance-barrier.js +0 -167
  306. package/dist/execution/executable-identity.js +0 -105
  307. package/dist/execution/guarded-source.js +0 -441
  308. package/dist/indexer/graph/graph-boost.js +0 -427
  309. package/dist/indexer/graph/graph-dedup.js +0 -95
  310. package/dist/indexer/search/name-match.js +0 -35
  311. package/dist/indexer/search/ranking-contributors.js +0 -515
  312. package/dist/indexer/walk/project-context.js +0 -192
  313. package/dist/integrations/agent/execution-cascade.js +0 -566
  314. package/dist/integrations/agent/execution-definitions.js +0 -202
  315. package/dist/integrations/agent/execution-lowering.js +0 -841
  316. package/dist/integrations/agent/execution-preparation.js +0 -98
  317. package/dist/integrations/agent/inline-execution.js +0 -74
  318. package/dist/registry/create-provider-registry.js +0 -29
  319. package/dist/registry/pinned-request-helper.js +0 -247
  320. package/dist/registry/pinned-transport.js +0 -717
  321. package/dist/sources/providers/index.js +0 -14
  322. package/dist/storage/engines/sqlite-migrations.js +0 -271
  323. package/dist/storage/repositories/canaries-repository.js +0 -107
  324. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  325. package/dist/storage/repositories/registry-cache.js +0 -113
  326. package/dist/tasks/scheduler-sync-preview.js +0 -52
  327. package/dist/workflows/freeze/resolve-steps.js +0 -86
  328. package/dist/workflows/freeze/source-freeze.js +0 -64
  329. package/dist/workflows/ir/compile.js +0 -321
  330. package/dist/workflows/ir/environment-v4.js +0 -330
  331. package/dist/workflows/ir/freeze-v4.js +0 -153
  332. package/dist/workflows/ir/schema-v4.js +0 -745
  333. package/dist/workflows/ir/schema.js +0 -354
  334. package/dist/workflows/program/schema.js +0 -78
  335. package/dist/workflows/runtime/checkin.js +0 -57
  336. package/dist/workflows/runtime/plan-classifier.js +0 -196
  337. package/dist/workflows/runtime/unit-checkin.js +0 -45
  338. package/dist/workflows/runtime/unit-phases.js +0 -20
  339. package/dist/workflows/schema.js +0 -4
  340. package/dist/workflows/source-ir/compile.js +0 -200
  341. package/dist/workflows/source-ir/program.js +0 -50
  342. package/dist/workflows/source-ir/result.js +0 -26
  343. package/dist/workflows/source-ir/schema.js +0 -786
  344. package/dist/workflows/source-ir/triggers.js +0 -79
  345. package/dist/workflows/source-ir/uses.js +0 -40
  346. package/dist/workflows/validator.js +0 -60
@@ -2,17 +2,26 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
- * The single canonical contract for the derived `entries` generation.
5
+ * The derived `entries` layout: DDL plus the layout marker.
6
6
  *
7
- * `index.db` is regenerable, so callers compare one normalized PRAGMA
8
- * fingerprint and discard any generation that differs. This module owns both
9
- * the DDL and its expected fingerprint so schema creation, writable opens,
10
- * serving preflights, and read-only evaluator tooling cannot drift into
11
- * separate definitions of "current".
7
+ * `index_meta.version` is a layout marker. An older layout is never refused:
8
+ * readers serve what is there, and the writable opener (`ensureSchema`,
9
+ * `index-schema.ts`) brings it up to date in place — added and dropped
10
+ * columns, retired tables dropped, a one-time full-text rebuild — without
11
+ * touching embeddings, utility scores, graph rows, or the LLM enrichment
12
+ * cache. A newer layout is refused, naming the upgrade.
12
13
  */
13
- // v23 adds an isolated fragment FTS population. v22 is the last shipped
14
- // generation and is intentionally rebuilt rather than migrated in place.
15
- export const CANONICAL_INDEX_DB_VERSION = 23;
14
+ // 25: vectors live only in `embeddings`; the sqlite-vec mirror `entries_vec`
15
+ // is dropped (`dropVecMirror`, index-schema.ts), and so is the fragment FTS
16
+ // table `entry_fragments_fts`, which search no longer reads. `entries` keeps
17
+ // a hash of each entry's embedding input (`embed_hash`) instead of the text
18
+ // (`search_text`); the text is derived from `document_json` when embedding.
19
+ // 24: the FTS5 tables are contentless (`content=''`) — the indexed text lives
20
+ // once, in `entries` / `entry_fragments`, and FTS rows are keyed by rowid only.
21
+ // 23 and earlier stored a second copy of every indexed field in FTS5's own
22
+ // content shadow tables. `ensureFtsLayout` (index-schema.ts) rebuilds the FTS
23
+ // tables from the stored entries when it finds the older layout.
24
+ export const CANONICAL_INDEX_DB_VERSION = 25;
16
25
  export const CANONICAL_ENTRY_SCHEMA_SQL = `
17
26
  CREATE TABLE IF NOT EXISTS entries (
18
27
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -25,8 +34,8 @@ export const CANONICAL_ENTRY_SCHEMA_SQL = `
25
34
  file_path TEXT NOT NULL,
26
35
  content_hash TEXT,
27
36
  document_json TEXT NOT NULL,
28
- search_text TEXT NOT NULL,
29
- derived_from TEXT
37
+ derived_from TEXT,
38
+ embed_hash TEXT
30
39
  );
31
40
 
32
41
  CREATE INDEX IF NOT EXISTS idx_entries_bundle ON entries(bundle_id);
@@ -34,279 +43,84 @@ export const CANONICAL_ENTRY_SCHEMA_SQL = `
34
43
  CREATE INDEX IF NOT EXISTS idx_entries_file_path ON entries(file_path);
35
44
  CREATE INDEX IF NOT EXISTS idx_entries_derived_from ON entries(derived_from);
36
45
 
37
- -- Keep parent metadata and body fragments in separate FTS populations.
38
- -- Combining them changes parent-document IDF and conjunction semantics.
39
- CREATE VIRTUAL TABLE IF NOT EXISTS entries_fts USING fts5(
40
- entry_id UNINDEXED,
41
- name,
42
- description,
43
- tags,
44
- hints,
45
- content,
46
- tokenize='porter unicode61'
47
- );
48
-
49
46
  CREATE TABLE IF NOT EXISTS entry_fragments (
50
47
  entry_id INTEGER PRIMARY KEY REFERENCES entries(id) ON DELETE CASCADE,
51
48
  safe_markdown TEXT NOT NULL
52
49
  );
53
-
54
- CREATE VIRTUAL TABLE IF NOT EXISTS entry_fragments_fts USING fts5(
55
- entry_id UNINDEXED,
56
- fragment_id UNINDEXED,
57
- fragment_ordinal UNINDEXED,
58
- content,
59
- tokenize='porter unicode61'
60
- );
61
50
  `;
62
- const CANONICAL_ENTRY_SCHEMA_FINGERPRINT = {
63
- tableSql: "CREATE TABLE entries ( id INTEGER PRIMARY KEY AUTOINCREMENT, item_ref TEXT NOT NULL UNIQUE, bundle_id TEXT NOT NULL, component_id TEXT NOT NULL, concept_id TEXT NOT NULL, adapter_id TEXT NOT NULL, type TEXT NOT NULL, file_path TEXT NOT NULL, content_hash TEXT, document_json TEXT NOT NULL, search_text TEXT NOT NULL, derived_from TEXT )",
64
- sqliteSequenceTable: true,
65
- sqliteSequenceValid: true,
66
- columns: [
67
- { cid: 0, name: "id", type: "INTEGER", notNull: 0, defaultValue: null, primaryKeyPosition: 1, hidden: 0 },
68
- {
69
- cid: 1,
70
- name: "item_ref",
71
- type: "TEXT",
72
- notNull: 1,
73
- defaultValue: null,
74
- primaryKeyPosition: 0,
75
- hidden: 0,
76
- },
77
- {
78
- cid: 2,
79
- name: "bundle_id",
80
- type: "TEXT",
81
- notNull: 1,
82
- defaultValue: null,
83
- primaryKeyPosition: 0,
84
- hidden: 0,
85
- },
86
- {
87
- cid: 3,
88
- name: "component_id",
89
- type: "TEXT",
90
- notNull: 1,
91
- defaultValue: null,
92
- primaryKeyPosition: 0,
93
- hidden: 0,
94
- },
95
- {
96
- cid: 4,
97
- name: "concept_id",
98
- type: "TEXT",
99
- notNull: 1,
100
- defaultValue: null,
101
- primaryKeyPosition: 0,
102
- hidden: 0,
103
- },
104
- {
105
- cid: 5,
106
- name: "adapter_id",
107
- type: "TEXT",
108
- notNull: 1,
109
- defaultValue: null,
110
- primaryKeyPosition: 0,
111
- hidden: 0,
112
- },
113
- { cid: 6, name: "type", type: "TEXT", notNull: 1, defaultValue: null, primaryKeyPosition: 0, hidden: 0 },
114
- {
115
- cid: 7,
116
- name: "file_path",
117
- type: "TEXT",
118
- notNull: 1,
119
- defaultValue: null,
120
- primaryKeyPosition: 0,
121
- hidden: 0,
122
- },
123
- {
124
- cid: 8,
125
- name: "content_hash",
126
- type: "TEXT",
127
- notNull: 0,
128
- defaultValue: null,
129
- primaryKeyPosition: 0,
130
- hidden: 0,
131
- },
132
- {
133
- cid: 9,
134
- name: "document_json",
135
- type: "TEXT",
136
- notNull: 1,
137
- defaultValue: null,
138
- primaryKeyPosition: 0,
139
- hidden: 0,
140
- },
141
- {
142
- cid: 10,
143
- name: "search_text",
144
- type: "TEXT",
145
- notNull: 1,
146
- defaultValue: null,
147
- primaryKeyPosition: 0,
148
- hidden: 0,
149
- },
150
- {
151
- cid: 11,
152
- name: "derived_from",
153
- type: "TEXT",
154
- notNull: 0,
155
- defaultValue: null,
156
- primaryKeyPosition: 0,
157
- hidden: 0,
158
- },
159
- ],
160
- indexes: [
161
- {
162
- name: "idx_entries_bundle",
163
- unique: 0,
164
- origin: "c",
165
- partial: 0,
166
- columns: [
167
- { sequence: 0, cid: 2, name: "bundle_id", descending: 0, collation: "BINARY", key: 1 },
168
- { sequence: 1, cid: -1, name: null, descending: 0, collation: "BINARY", key: 0 },
169
- ],
170
- },
171
- {
172
- name: "idx_entries_derived_from",
173
- unique: 0,
174
- origin: "c",
175
- partial: 0,
176
- columns: [
177
- { sequence: 0, cid: 11, name: "derived_from", descending: 0, collation: "BINARY", key: 1 },
178
- { sequence: 1, cid: -1, name: null, descending: 0, collation: "BINARY", key: 0 },
179
- ],
180
- },
181
- {
182
- name: "idx_entries_file_path",
183
- unique: 0,
184
- origin: "c",
185
- partial: 0,
186
- columns: [
187
- { sequence: 0, cid: 7, name: "file_path", descending: 0, collation: "BINARY", key: 1 },
188
- { sequence: 1, cid: -1, name: null, descending: 0, collation: "BINARY", key: 0 },
189
- ],
190
- },
191
- {
192
- name: "idx_entries_type",
193
- unique: 0,
194
- origin: "c",
195
- partial: 0,
196
- columns: [
197
- { sequence: 0, cid: 6, name: "type", descending: 0, collation: "BINARY", key: 1 },
198
- { sequence: 1, cid: -1, name: null, descending: 0, collation: "BINARY", key: 0 },
199
- ],
200
- },
201
- {
202
- name: "sqlite_autoindex_entries_1",
203
- unique: 1,
204
- origin: "u",
205
- partial: 0,
206
- columns: [
207
- { sequence: 0, cid: 1, name: "item_ref", descending: 0, collation: "BINARY", key: 1 },
208
- { sequence: 1, cid: -1, name: null, descending: 0, collation: "BINARY", key: 0 },
209
- ],
210
- },
211
- ],
212
- searchSurfaces: {
213
- entriesFtsSql: "CREATE VIRTUAL TABLE entries_fts USING fts5( entry_id UNINDEXED, name, description, tags, hints, content, tokenize='porter unicode61' )",
214
- fragmentSourceSql: "CREATE TABLE entry_fragments ( entry_id INTEGER PRIMARY KEY REFERENCES entries(id) ON DELETE CASCADE, safe_markdown TEXT NOT NULL )",
215
- fragmentsFtsSql: "CREATE VIRTUAL TABLE entry_fragments_fts USING fts5( entry_id UNINDEXED, fragment_id UNINDEXED, fragment_ordinal UNINDEXED, content, tokenize='porter unicode61' )",
216
- },
217
- };
51
+ // The FTS table is contentless: FTS5 keeps only the inverted index, and a row
52
+ // is addressed by its rowid (`entries_fts.rowid = entries.id`, see
53
+ // index-fts-repository.ts). `contentless_delete=1` lets a row be deleted by
54
+ // rowid alone — an external-content table would instead need the exact text
55
+ // originally indexed, which is derived in JS from `document_json`
56
+ // (`buildSearchFields`) and would corrupt the index the first time that
57
+ // derivation changed. The UNINDEXED columns store nothing and read back NULL;
58
+ // they stay declared so the insert statements and the readers'
59
+ // `COALESCE(f.entry_id, f.rowid)` joins are valid against both this layout
60
+ // and the content-bearing one older releases wrote — which is also the
61
+ // layout written when the linked SQLite predates `contentless_delete` (3.43,
62
+ // e.g. the macOS 13 system library Bun links there).
63
+ const CONTENTLESS_OPTIONS = "content='', contentless_delete=1,";
64
+ export function entriesFtsDdl(contentless) {
65
+ return `
66
+ CREATE VIRTUAL TABLE IF NOT EXISTS entries_fts USING fts5(
67
+ entry_id UNINDEXED, name, description, tags, hints, content,
68
+ ${contentless ? CONTENTLESS_OPTIONS : ""} tokenize='porter unicode61'
69
+ );`;
70
+ }
71
+ /** Whether the linked SQLite's FTS5 supports `contentless_delete` (3.43.0+). */
72
+ export function supportsContentlessDelete(db) {
73
+ const version = db.prepare("SELECT sqlite_version() AS version").get().version;
74
+ const [major = 0, minor = 0] = version.split(".").map(Number);
75
+ return major > 3 || (major === 3 && minor >= 43);
76
+ }
218
77
  function sqlString(value) {
219
78
  return `'${value.replaceAll("'", "''")}'`;
220
79
  }
221
- function normalizeSchemaSql(value) {
222
- if (value == null)
223
- return null;
224
- return value.replace(/\s+/g, " ").trim();
225
- }
226
- function readNamedTableSql(db, name) {
80
+ export function readTableSql(db, name) {
227
81
  const row = db.prepare(`SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ${sqlString(name)}`).get();
228
- return normalizeSchemaSql(row?.sql);
229
- }
230
- export function readEntrySchemaFingerprint(db) {
231
- const sqliteSequenceTable = db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'sqlite_sequence'").get() !=
232
- null;
233
- const maxId = Number(db.prepare("SELECT COALESCE(MAX(id), 0) AS maxId FROM entries").get().maxId);
234
- const sequenceRow = sqliteSequenceTable
235
- ? db.prepare("SELECT seq FROM sqlite_sequence WHERE name = 'entries'").get()
236
- : undefined;
237
- const sqliteSequenceValid = sqliteSequenceTable &&
238
- (maxId === 0 ? sequenceRow == null || Number(sequenceRow.seq) >= 0 : Number(sequenceRow?.seq) >= maxId);
239
- const columns = db.prepare("PRAGMA table_xinfo(entries)").all().map((column) => ({
240
- cid: Number(column.cid),
241
- name: column.name,
242
- type: column.type.trim().toUpperCase(),
243
- notNull: Number(column.notnull),
244
- defaultValue: column.dflt_value === null ? null : String(column.dflt_value),
245
- primaryKeyPosition: Number(column.pk),
246
- hidden: Number(column.hidden),
247
- }));
248
- const indexes = db.prepare("PRAGMA index_list(entries)").all()
249
- .map((index) => ({
250
- name: index.name,
251
- unique: Number(index.unique),
252
- origin: index.origin,
253
- partial: Number(index.partial),
254
- columns: db.prepare(`PRAGMA index_xinfo(${sqlString(index.name)})`).all()
255
- .sort((left, right) => Number(left.seqno) - Number(right.seqno))
256
- .map((column) => ({
257
- sequence: Number(column.seqno),
258
- cid: Number(column.cid),
259
- name: column.name,
260
- descending: Number(column.desc),
261
- collation: column.coll,
262
- key: Number(column.key),
263
- })),
264
- }))
265
- .sort((left, right) => left.name.localeCompare(right.name));
266
- return {
267
- tableSql: readNamedTableSql(db, "entries"),
268
- sqliteSequenceTable,
269
- sqliteSequenceValid,
270
- columns,
271
- indexes,
272
- searchSurfaces: {
273
- entriesFtsSql: readNamedTableSql(db, "entries_fts"),
274
- fragmentSourceSql: readNamedTableSql(db, "entry_fragments"),
275
- fragmentsFtsSql: readNamedTableSql(db, "entry_fragments_fts"),
276
- },
277
- };
82
+ return row?.sql ?? null;
278
83
  }
279
- export function hasCanonicalEntrySchema(db) {
280
- try {
281
- return JSON.stringify(readEntrySchemaFingerprint(db)) === JSON.stringify(CANONICAL_ENTRY_SCHEMA_FINGERPRINT);
282
- }
283
- catch {
284
- return false;
285
- }
84
+ export function tableExists(db, name) {
85
+ return readTableSql(db, name) !== null;
286
86
  }
287
- export function classifyIndexGeneration(db) {
288
- let storedVersion;
289
- try {
290
- const row = db.prepare("SELECT value FROM index_meta WHERE key = 'version'").get();
291
- storedVersion = row?.value;
292
- }
293
- catch {
294
- storedVersion = undefined;
295
- }
296
- if (storedVersion === String(CANONICAL_INDEX_DB_VERSION) && hasCanonicalEntrySchema(db)) {
297
- return { status: "canonical", storedVersion };
298
- }
299
- const storedNumeric = storedVersion === undefined ? undefined : Number(storedVersion);
300
- if (storedNumeric !== undefined && Number.isFinite(storedNumeric) && storedNumeric > CANONICAL_INDEX_DB_VERSION) {
301
- return { status: "newer", storedVersion };
302
- }
303
- return { status: "older", storedVersion };
87
+ /**
88
+ * Columns this release's readers need in `entries` (layout 21+). The writable
89
+ * opener adds `embed_hash` to an older table, so it is not required here.
90
+ */
91
+ const REQUIRED_ENTRY_COLUMNS = [
92
+ "id",
93
+ "item_ref",
94
+ "bundle_id",
95
+ "component_id",
96
+ "concept_id",
97
+ "adapter_id",
98
+ "type",
99
+ "file_path",
100
+ "content_hash",
101
+ "document_json",
102
+ "derived_from",
103
+ ];
104
+ /** Required `entries` columns the table lacks; every column when there is no `entries` table. */
105
+ export function missingEntryColumns(db) {
106
+ const present = new Set(db.prepare("PRAGMA table_info(entries)").all().map((c) => c.name));
107
+ return REQUIRED_ENTRY_COLUMNS.filter((column) => !present.has(column));
304
108
  }
305
- export function isCanonicalIndexGeneration(db) {
109
+ /**
110
+ * Whether an index database has an `entries` table this release can read. A
111
+ * fresh or empty file has none; an index older than layout 21 has one keyed
112
+ * by columns this release no longer reads, and serves nothing until the next
113
+ * `akm index` recreates it.
114
+ */
115
+ export function hasCurrentEntriesTable(db) {
306
116
  try {
307
- return classifyIndexGeneration(db).status === "canonical";
117
+ return missingEntryColumns(db).length === 0;
308
118
  }
309
119
  catch {
310
120
  return false;
311
121
  }
312
122
  }
123
+ /** True when an FTS5 table's DDL declares the contentless layout this release writes. */
124
+ export function isContentlessFtsDdl(sql) {
125
+ return sql !== null && /content\s*=\s*''/.test(sql);
126
+ }