akm-cli 0.9.17-alpha.3 → 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 +731 -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 +361 -751
  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 -441
  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
@@ -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
+ }