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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/CHANGELOG.md +756 -0
  2. package/dist/akm +94 -196
  3. package/dist/cli/shared.js +6 -2
  4. package/dist/cli.js +22 -9
  5. package/dist/commands/agent/agent-dispatch.js +1 -1
  6. package/dist/commands/command/command-execution.js +24 -62
  7. package/dist/commands/feedback-cli.js +0 -1
  8. package/dist/commands/health/accept-rate.js +2 -2
  9. package/dist/commands/health/checks.js +30 -75
  10. package/dist/commands/health/config-skew.js +38 -0
  11. package/dist/commands/health/egress.js +54 -0
  12. package/dist/commands/health/html-report.js +0 -38
  13. package/dist/commands/health/improve-metrics.js +123 -562
  14. package/dist/commands/health/plugin-staleness.js +53 -3
  15. package/dist/commands/health/renderers.js +12 -4
  16. package/dist/commands/health/report-view-model.js +11 -106
  17. package/dist/commands/health/types-improve.js +4 -19
  18. package/dist/commands/health/windows.js +64 -73
  19. package/dist/commands/health.js +122 -143
  20. package/dist/commands/improve/consolidate/chunking.js +25 -100
  21. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  22. package/dist/commands/improve/consolidate.js +538 -1075
  23. package/dist/commands/improve/content-hash.js +16 -24
  24. package/dist/commands/improve/distill/content-repair.js +18 -100
  25. package/dist/commands/improve/distill-guards.js +20 -81
  26. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  27. package/dist/commands/improve/distill.js +608 -1075
  28. package/dist/commands/improve/eligibility.js +126 -400
  29. package/dist/commands/improve/execution.js +3 -5
  30. package/dist/commands/improve/extract.js +487 -1046
  31. package/dist/commands/improve/feedback-valence.js +0 -25
  32. package/dist/commands/improve/improve-cli.js +29 -166
  33. package/dist/commands/improve/improve-result-file.js +10 -66
  34. package/dist/commands/improve/improve-strategies.js +12 -7
  35. package/dist/commands/improve/improve-usage-report.js +18 -64
  36. package/dist/commands/improve/improve.js +443 -1063
  37. package/dist/commands/improve/ledger.js +114 -0
  38. package/dist/commands/improve/locks.js +2 -8
  39. package/dist/commands/improve/loop-stages.js +459 -1172
  40. package/dist/commands/improve/memory/derived-ref.js +12 -77
  41. package/dist/commands/improve/memory/memory-belief.js +14 -118
  42. package/dist/commands/improve/memory/memory-improve.js +4 -3
  43. package/dist/commands/improve/outcome-loop.js +28 -156
  44. package/dist/commands/improve/planner.js +5 -10
  45. package/dist/commands/improve/preparation.js +851 -2339
  46. package/dist/commands/improve/proactive-maintenance.js +34 -101
  47. package/dist/commands/improve/reflect-noise.js +104 -280
  48. package/dist/commands/improve/reflect.js +621 -1367
  49. package/dist/commands/improve/salience.js +46 -232
  50. package/dist/commands/improve/session-asset.js +19 -100
  51. package/dist/commands/improve/stage.js +323 -0
  52. package/dist/commands/proposal/drain.js +251 -644
  53. package/dist/commands/proposal/proposal-cli.js +3 -18
  54. package/dist/commands/proposal/proposal-types.js +20 -41
  55. package/dist/commands/proposal/proposal.js +1 -2
  56. package/dist/commands/proposal/propose.js +134 -160
  57. package/dist/commands/proposal/repository.js +502 -1487
  58. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  59. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  60. package/dist/commands/proposal/validators/proposals.js +13 -89
  61. package/dist/commands/read/curate.js +63 -413
  62. package/dist/commands/read/search-cli.js +16 -33
  63. package/dist/commands/read/search.js +17 -23
  64. package/dist/commands/read/show.js +2 -13
  65. package/dist/commands/sources/bundle-cli.js +25 -2
  66. package/dist/commands/sources/bundle-config-ops.js +7 -0
  67. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  68. package/dist/commands/sources/info.js +2 -11
  69. package/dist/commands/sources/installed-stashes.js +197 -746
  70. package/dist/commands/sources/schema-repair.js +98 -129
  71. package/dist/commands/sources/source-add.js +62 -12
  72. package/dist/commands/sources/stash-cli.js +1 -1
  73. package/dist/commands/tasks/explain.js +10 -13
  74. package/dist/commands/tasks/tasks-cli.js +9 -8
  75. package/dist/commands/tasks/tasks.js +326 -930
  76. package/dist/commands/tasks/validate.js +42 -21
  77. package/dist/commands/workflow/plan.js +22 -29
  78. package/dist/commands/workflow-cli.js +4 -4
  79. package/dist/core/adapter/adapters/akm-adapter.js +0 -1
  80. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  81. package/dist/core/adapter/adapters/akm-metadata.js +11 -12
  82. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  83. package/dist/core/adapter/execution-source.js +17 -29
  84. package/dist/core/asset/resolve-ref.js +1 -1
  85. package/dist/core/bundle-id.js +42 -5
  86. package/dist/core/bundle-rename.js +291 -0
  87. package/dist/core/config/config-io.js +1 -2
  88. package/dist/core/config/config-schema.js +1 -33
  89. package/dist/core/config/config-walker.js +1 -1
  90. package/dist/core/config/config.js +163 -68
  91. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  92. package/dist/core/config/schema/embedding.js +20 -5
  93. package/dist/core/config/schema/engines.js +5 -0
  94. package/dist/core/config/schema/execution.js +1 -1
  95. package/dist/core/config/schema/experimental.js +1 -1
  96. package/dist/core/config/schema/improve-processes.js +21 -95
  97. package/dist/core/config/schema/improve.js +4 -42
  98. package/dist/core/config/schema/scheduler.js +12 -12
  99. package/dist/core/config/schema/search.js +6 -22
  100. package/dist/core/env-secret-ref.js +0 -1
  101. package/dist/core/errors.js +8 -9
  102. package/dist/core/file-lock.js +76 -173
  103. package/dist/core/logs-db.js +2 -2
  104. package/dist/core/paths.js +0 -27
  105. package/dist/core/redaction.js +109 -2
  106. package/dist/core/run-lock.js +2 -5
  107. package/dist/core/spawn-env.js +1 -1
  108. package/dist/core/state/migrations.js +108 -61
  109. package/dist/core/state-db-scope.js +2 -4
  110. package/dist/core/state-db.js +126 -692
  111. package/dist/core/type-presentation.js +1 -9
  112. package/dist/core/write-source.js +293 -1012
  113. package/dist/execution/input-contract.js +1 -1
  114. package/dist/execution/resolved-request.js +135 -689
  115. package/dist/execution/source.js +63 -257
  116. package/dist/execution/target-ref.js +1 -1
  117. package/dist/indexer/bundle-identity-guard.js +2 -2
  118. package/dist/indexer/db/graph-db.js +106 -46
  119. package/dist/indexer/ensure-index.js +44 -85
  120. package/dist/indexer/graph/graph-extraction.js +340 -562
  121. package/dist/indexer/graph/graph-related.js +130 -0
  122. package/dist/indexer/index-rebuild-lock.js +3 -11
  123. package/dist/indexer/index-writer-lock.js +8 -17
  124. package/dist/indexer/index-written-assets.js +139 -151
  125. package/dist/indexer/indexer.js +524 -846
  126. package/dist/indexer/materialize-embeddings.js +60 -397
  127. package/dist/indexer/passes/memory-inference.js +81 -90
  128. package/dist/indexer/passes/metadata.js +132 -200
  129. package/dist/indexer/read-preflight.js +0 -7
  130. package/dist/indexer/scan/doc-to-entry.js +1 -3
  131. package/dist/indexer/scan/drain-dir.js +1 -1
  132. package/dist/indexer/search/db-search.js +181 -590
  133. package/dist/indexer/search/fts-query.js +30 -41
  134. package/dist/indexer/search/ranking.js +28 -154
  135. package/dist/indexer/search/search-attribution.js +12 -32
  136. package/dist/indexer/search/search-fields.js +11 -15
  137. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  138. package/dist/indexer/search/search-source.js +1 -4
  139. package/dist/indexer/usage/usage-events.js +2 -7
  140. package/dist/integrations/agent/engine-fallback.js +23 -40
  141. package/dist/integrations/agent/engine-resolution.js +93 -183
  142. package/dist/integrations/agent/execution.js +507 -0
  143. package/dist/integrations/agent/model-map.js +28 -156
  144. package/dist/integrations/agent/request-lowering.js +66 -141
  145. package/dist/integrations/agent/runner-dispatch.js +143 -321
  146. package/dist/integrations/agent/runner.js +54 -14
  147. package/dist/integrations/lockfile.js +53 -101
  148. package/dist/llm/embedders/deterministic.js +2 -3
  149. package/dist/llm/embedders/profile.js +71 -0
  150. package/dist/llm/embedders/remote.js +10 -15
  151. package/dist/llm/graph-extract.js +3 -12
  152. package/dist/llm/index-passes.js +3 -5
  153. package/dist/llm/memory-infer.js +1 -2
  154. package/dist/llm/metadata-enhance.js +1 -2
  155. package/dist/llm/structured-call.js +5 -24
  156. package/dist/output/generic-render.js +23 -11
  157. package/dist/output/html-render.js +13 -10
  158. package/dist/output/render-registry.js +3 -32
  159. package/dist/output/shapes/helpers.js +2 -34
  160. package/dist/output/shapes/passthrough.js +1 -9
  161. package/dist/{indexer/search/ranking-types.js → output/text/bundle-rename.js} +4 -1
  162. package/dist/output/text/command-format.js +60 -23
  163. package/dist/output/text/helpers.js +1 -1
  164. package/dist/output/text/migrate.js +5 -14
  165. package/dist/output/text/proposal-format.js +1 -2
  166. package/dist/output/text/workflow-format.js +0 -32
  167. package/dist/output/text.js +2 -0
  168. package/dist/registry/factory.js +4 -19
  169. package/dist/registry/network.js +66 -220
  170. package/dist/registry/providers/index.js +0 -2
  171. package/dist/registry/providers/skills-sh.js +3 -14
  172. package/dist/registry/providers/static-index.js +24 -26
  173. package/dist/registry/resolve.js +55 -131
  174. package/dist/scripts/akm-migrate-node.js +43937 -93313
  175. package/dist/scripts/akm-migrate.js +43697 -93071
  176. package/dist/setup/registry-stash-loader.js +4 -13
  177. package/dist/setup/semantic-assets.js +3 -44
  178. package/dist/setup/setup.js +1 -1
  179. package/dist/setup/steps/tasks.js +25 -15
  180. package/dist/sources/provider-factory.js +17 -18
  181. package/dist/sources/providers/filesystem.js +2 -3
  182. package/dist/sources/providers/git-install.js +7 -1
  183. package/dist/sources/providers/git-provider.js +0 -3
  184. package/dist/sources/providers/git-stash.js +0 -17
  185. package/dist/sources/providers/npm.js +2 -4
  186. package/dist/sources/providers/provider-utils.js +5 -10
  187. package/dist/sources/providers/website.js +0 -2
  188. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  189. package/dist/sources/website-url.js +2 -2
  190. package/dist/storage/database.js +9 -35
  191. package/dist/storage/repositories/improve-ledger-repository.js +168 -0
  192. package/dist/storage/repositories/index-connection.js +34 -70
  193. package/dist/storage/repositories/index-entries-repository.js +69 -111
  194. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  195. package/dist/storage/repositories/index-entry-schema.js +83 -269
  196. package/dist/storage/repositories/index-fts-repository.js +86 -256
  197. package/dist/storage/repositories/index-llm-cache-repository.js +17 -0
  198. package/dist/storage/repositories/index-meta-repository.js +6 -4
  199. package/dist/storage/repositories/index-schema.js +192 -220
  200. package/dist/storage/repositories/index-utility-repository.js +8 -29
  201. package/dist/storage/repositories/index-vec-repository.js +133 -414
  202. package/dist/storage/repositories/outcome-repository.js +2 -1
  203. package/dist/storage/repositories/proposals-repository.js +35 -0
  204. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  205. package/dist/storage/repositories/task-history-repository.js +26 -4
  206. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  207. package/dist/storage/sqlite-migrations.js +136 -0
  208. package/dist/storage/sqlite-pragmas.js +11 -9
  209. package/dist/storage/sqlite-transaction.js +170 -0
  210. package/dist/storage/state-db-integrity.js +34 -27
  211. package/dist/tasks/activation-config.js +134 -62
  212. package/dist/tasks/backends/cron.js +129 -277
  213. package/dist/tasks/backends/exec-utils.js +2 -5
  214. package/dist/tasks/backends/launchd.js +125 -745
  215. package/dist/tasks/backends/schtasks.js +101 -620
  216. package/dist/tasks/prepare/prepare-support.js +5 -15
  217. package/dist/tasks/prepare/prepare.js +0 -2
  218. package/dist/tasks/resolve-akm-bin.js +20 -79
  219. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  220. package/dist/tasks/scheduler-binding.js +18 -238
  221. package/dist/tasks/scheduler-invocation.js +52 -52
  222. package/dist/tasks/scheduler-lock.js +53 -0
  223. package/dist/tasks/scheduler-sync.js +363 -679
  224. package/dist/tasks/source/parse-task-source.js +160 -10
  225. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  226. package/dist/tasks/source/task-to-v4.js +2 -2
  227. package/dist/workflows/authoring/authoring.js +3 -12
  228. package/dist/workflows/compile.js +211 -0
  229. package/dist/workflows/concurrency-policy.js +13 -74
  230. package/dist/workflows/exec/child-invocation.js +3 -17
  231. package/dist/workflows/exec/child-workflow.js +32 -141
  232. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  233. package/dist/workflows/exec/environment.js +98 -0
  234. package/dist/workflows/exec/exec-unit.js +33 -140
  235. package/dist/workflows/exec/frozen-judge.js +7 -59
  236. package/dist/workflows/exec/native-executor.js +82 -341
  237. package/dist/workflows/exec/param-secrets.js +29 -47
  238. package/dist/workflows/exec/run-workflow.js +154 -387
  239. package/dist/workflows/exec/scheduler.js +9 -36
  240. package/dist/workflows/exec/step-work.js +127 -430
  241. package/dist/workflows/exec/unit-dispatch.js +11 -63
  242. package/dist/workflows/exec/unit-writer.js +8 -52
  243. package/dist/workflows/exec/worktree.js +39 -273
  244. package/dist/workflows/freeze/child-output-references.js +4 -15
  245. package/dist/workflows/freeze/environment.js +99 -92
  246. package/dist/workflows/freeze/freeze.js +172 -0
  247. package/dist/workflows/freeze/step-values.js +19 -21
  248. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  249. package/dist/workflows/freeze/targets/command.js +10 -33
  250. package/dist/workflows/freeze/targets/script.js +5 -12
  251. package/dist/workflows/freeze/targets/shell.js +3 -6
  252. package/dist/workflows/freeze/targets/task.js +25 -80
  253. package/dist/workflows/freeze/task-bindings.js +20 -67
  254. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  255. package/dist/workflows/ir/params.js +6 -51
  256. package/dist/workflows/ir/plan-hash.js +2 -34
  257. package/dist/workflows/parser.js +140 -43
  258. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  259. package/dist/workflows/renderer.js +36 -69
  260. package/dist/workflows/resource-limits.js +12 -120
  261. package/dist/workflows/runtime/agent-identity.js +8 -40
  262. package/dist/workflows/runtime/run-outputs.js +3 -6
  263. package/dist/workflows/runtime/run-plan.js +316 -0
  264. package/dist/workflows/runtime/runs.js +48 -200
  265. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  266. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  267. package/dist/workflows/validate-summary.js +2 -7
  268. package/docs/integration/bundling-akm.md +49 -42
  269. package/docs/migration/README.md +1 -0
  270. package/docs/migration/release-notes/0.9.17.md +41 -0
  271. package/docs/migration/v0.9.1-to-v0.9.2.md +19 -7
  272. package/docs/reference/cli.md +182 -125
  273. package/docs/reference/configuration.md +49 -56
  274. package/docs/reference/data-and-telemetry.md +19 -20
  275. package/docs/reference/tasks.md +86 -38
  276. package/docs/reference/workflow-schema.md +14 -18
  277. package/docs/reference/workflows.md +6 -9
  278. package/package.json +1 -1
  279. package/schemas/akm-config.json +87 -406
  280. package/dist/commands/health/advisories.js +0 -150
  281. package/dist/commands/health/metrics.js +0 -329
  282. package/dist/commands/health/surfaces.js +0 -102
  283. package/dist/commands/improve/anti-collapse.js +0 -83
  284. package/dist/commands/improve/collapse-detector.js +0 -432
  285. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  286. package/dist/commands/improve/consolidate/merge.js +0 -146
  287. package/dist/commands/improve/distill/promote-memory.js +0 -329
  288. package/dist/commands/improve/distill/quality-gate.js +0 -500
  289. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  290. package/dist/commands/improve/proposal-envelope.js +0 -31
  291. package/dist/commands/improve/run-context.js +0 -123
  292. package/dist/commands/improve/shared.js +0 -21
  293. package/dist/commands/improve/source-identity.js +0 -28
  294. package/dist/commands/improve/triage.js +0 -96
  295. package/dist/commands/proposal/drain-policies.js +0 -151
  296. package/dist/commands/sources/update-transaction.js +0 -220
  297. package/dist/core/action-contributors.js +0 -28
  298. package/dist/core/config/config-version-shim.js +0 -101
  299. package/dist/core/config/retired-experimental-keys-shim.js +0 -62
  300. package/dist/core/fs-txn.js +0 -405
  301. package/dist/core/lexical-score.js +0 -25
  302. package/dist/core/maintenance-barrier.js +0 -167
  303. package/dist/execution/executable-identity.js +0 -105
  304. package/dist/execution/guarded-source.js +0 -427
  305. package/dist/indexer/graph/graph-boost.js +0 -427
  306. package/dist/indexer/graph/graph-dedup.js +0 -95
  307. package/dist/indexer/search/name-match.js +0 -35
  308. package/dist/indexer/search/ranking-contributors.js +0 -515
  309. package/dist/indexer/walk/project-context.js +0 -192
  310. package/dist/integrations/agent/execution-cascade.js +0 -566
  311. package/dist/integrations/agent/execution-definitions.js +0 -202
  312. package/dist/integrations/agent/execution-lowering.js +0 -841
  313. package/dist/integrations/agent/execution-preparation.js +0 -98
  314. package/dist/integrations/agent/inline-execution.js +0 -74
  315. package/dist/registry/create-provider-registry.js +0 -29
  316. package/dist/registry/pinned-request-helper.js +0 -247
  317. package/dist/registry/pinned-transport.js +0 -717
  318. package/dist/sources/providers/index.js +0 -14
  319. package/dist/storage/engines/sqlite-migrations.js +0 -271
  320. package/dist/storage/repositories/canaries-repository.js +0 -107
  321. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  322. package/dist/storage/repositories/registry-cache.js +0 -113
  323. package/dist/tasks/scheduler-sync-preview.js +0 -52
  324. package/dist/workflows/freeze/resolve-steps.js +0 -86
  325. package/dist/workflows/freeze/source-freeze.js +0 -64
  326. package/dist/workflows/ir/compile.js +0 -321
  327. package/dist/workflows/ir/environment-v4.js +0 -330
  328. package/dist/workflows/ir/freeze-v4.js +0 -153
  329. package/dist/workflows/ir/schema-v4.js +0 -745
  330. package/dist/workflows/ir/schema.js +0 -354
  331. package/dist/workflows/program/schema.js +0 -78
  332. package/dist/workflows/runtime/checkin.js +0 -57
  333. package/dist/workflows/runtime/plan-classifier.js +0 -196
  334. package/dist/workflows/runtime/unit-checkin.js +0 -45
  335. package/dist/workflows/runtime/unit-phases.js +0 -20
  336. package/dist/workflows/schema.js +0 -4
  337. package/dist/workflows/source-ir/compile.js +0 -200
  338. package/dist/workflows/source-ir/program.js +0 -50
  339. package/dist/workflows/source-ir/result.js +0 -26
  340. package/dist/workflows/source-ir/schema.js +0 -786
  341. package/dist/workflows/source-ir/triggers.js +0 -79
  342. package/dist/workflows/source-ir/uses.js +0 -40
  343. package/dist/workflows/validator.js +0 -60
@@ -1,515 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { isKnownType } from "../../core/recognition-util.js";
5
- import { computeGraphBoost } from "../graph/graph-boost.js";
6
- import { lexicalNameTokens, structuralNamePhraseMatch, structuralNameTokenMatch } from "./name-match.js";
7
- import { attachSearchHitAttribution } from "./search-attribution.js";
8
- /**
9
- * Chunk 1.5 (D1.5-5) — retyped from `Record<string, number>` to a FULL
10
- * `Record<KnownType, number>`. Only 8/14 types carried an entry before this
11
- * chunk (`env`, `secret`, `wiki`, `lesson`, `task`, `session` silently fell
12
- * through to the `?? 0` fallback at the sole consumer,
13
- * {@link typeRankingContributor}). The 6 additions below are explicit `0`
14
- * entries — behavior-preserving (they already defaulted to `0`), but now
15
- * compile-time-exhaustive: adding a new `KNOWN_TYPE` forces an explicit
16
- * boost decision instead of silently defaulting.
17
- */
18
- export const TYPE_BOOST = {
19
- skill: 0.4,
20
- command: 0.35,
21
- workflow: 0.35,
22
- agent: 0.3,
23
- script: 0.2,
24
- knowledge: 0.22,
25
- // Facts are authoritative, durable declarations about the stash — rank them
26
- // alongside knowledge so they surface reliably when relevant.
27
- fact: 0.22,
28
- // Instruction files (CLAUDE.md / AGENTS.md) are project instructions read
29
- // like knowledge (maintainer resolution 2026-07) — rank them alongside
30
- // knowledge so they surface reliably when relevant.
31
- instruction: 0.22,
32
- memory: -0.02,
33
- // Chunk 1.5: previously-absent entries, all defaulted to 0 pre-chunk —
34
- // explicit now, unchanged in effect.
35
- env: 0,
36
- secret: 0,
37
- lesson: 0,
38
- task: 0,
39
- session: 0,
40
- };
41
- /**
42
- * Open-string accessor over {@link TYPE_BOOST} (plan §2.3 "ranking
43
- * accessor"). Foreign/unknown types (outside `KNOWN_TYPES`) fall back to `0`
44
- * — identical to the old `TYPE_BOOST[item.entry.type] ?? 0` behavior on a
45
- * loosely-typed `Record<string, number>`, now expressed safely over the
46
- * exhaustive `Record<KnownType, number>`.
47
- */
48
- export function typeBoostFor(type) {
49
- return isKnownType(type) ? TYPE_BOOST[type] : 0;
50
- }
51
- const MAX_BOOST_SUM = 3.0;
52
- const UTILITY_WEIGHT = 0.5;
53
- const UTILITY_MAX_BOOST = 1.5;
54
- /**
55
- * R2 / #692 — weight of the improve loop's `asset_salience.rank_score`.
56
- * rank_score ∈ [0,1] → boost ∈ [1, 1.2]. Bounded well below the utility boost
57
- * so the composed signal would refine, never dominate, lexical/semantic
58
- * relevance.
59
- *
60
- * As of #692 this is NOT wired into default user-facing ranking — see
61
- * {@link salienceRankingContributor}'s doc comment. Kept exported (with the
62
- * contributor) for a future gated experiment; do not reintroduce it into
63
- * {@link defaultUtilityRankingContributors} without a measured
64
- * curate-golden-bench delta and an explicit config gate.
65
- */
66
- export const SALIENCE_WEIGHT = 0.2;
67
- export const SALIENCE_MAX_BOOST = 1.2;
68
- /**
69
- * Phase 2A / Rec 5: default recency half-life (days) used when no
70
- * `utilityDecayConfig` is supplied to the ranking pipeline. Matches the
71
- * pre-2A hardcoded `RECENCY_DECAY_DAYS = 30` constant — the formula is
72
- * default-safe and collapses to `exp(-days / 30)` when no overrides apply.
73
- */
74
- const DEFAULT_RECENCY_HALF_LIFE_DAYS = 30;
75
- /**
76
- * Cap on the effective half-life after applying the feedback stability
77
- * boost — prevents indefinite half-life inflation for memories with many
78
- * positive feedback events. `effectiveHalfLife = min(halfLife * boost^count, halfLife * 4)`.
79
- */
80
- const FEEDBACK_HALF_LIFE_CAP_MULTIPLIER = 4;
81
- function beliefStateBoost(item) {
82
- const entry = item.entry;
83
- // 03: belief-state penalties/boosts apply to ANY flagged entry (memory OR
84
- // knowledge), so contradicted/superseded KNOWLEDGE is demoted from results
85
- // just like flagged memories. Entries without a belief state fall through to
86
- // the `return 0` below (default-safe — no effect on unflagged assets).
87
- // Phase 1A: `asserted` and `deprecated` are first-class states.
88
- // `asserted` carries stronger user-explicit authority than `active`.
89
- // `deprecated` is a frozen historical state — penalized but milder than `superseded`.
90
- if (entry.beliefState === "contradicted")
91
- return -0.45;
92
- if (entry.beliefState === "superseded")
93
- return -0.25;
94
- if (entry.beliefState === "archived")
95
- return -0.6;
96
- if (entry.beliefState === "deprecated")
97
- return -0.15;
98
- if (entry.beliefState === "asserted")
99
- return 0.08;
100
- if (entry.beliefState === "active")
101
- return 0.06;
102
- return 0;
103
- }
104
- /**
105
- * Post-boost score ceilings for the demoting belief states (SPEC-5,
106
- * stash-conventions-code-spec.md — corrections demotion).
107
- *
108
- * Why the additive {@link beliefStateBoost} penalties alone are not enough:
109
- * keyword base scores have a bounded lexical floor (`normalizeFtsScores`),
110
- * while the boost sum then MULTIPLIES the base (`score *= 1 + boostSum`,
111
- * {@link applyScoreContributors}). A superseded incumbent can still earn
112
- * enough independent boosts to outrank its own correction, so additive
113
- * penalties alone cannot guarantee the corrections pattern's point ("so the
114
- * ranker demotes the stale version instead of letting it outrank your fix").
115
- *
116
- * The ceilings guarantee the demotion while keeping flagged entries VISIBLE:
117
- * un-demoted keyword hits floor at a 0.3 base, so any un-demoted hit outranks
118
- * a ceilinged one; demoted entries still list (belief FILTERING stays a
119
- * separate opt-in axis, `--belief`), and scores already below a ceiling keep
120
- * their relative ordering. Ceiling order mirrors the additive-penalty
121
- * severity order pinned in tests/integration/belief-state-phase1a.test.ts:
122
- * deprecated (mildest) > superseded > contradicted > archived.
123
- */
124
- const BELIEF_STATE_SCORE_CEILINGS = {
125
- deprecated: 0.28,
126
- superseded: 0.25,
127
- contradicted: 0.2,
128
- archived: 0.15,
129
- };
130
- /**
131
- * Clamp a ranked entry's FINAL score (after every additive and utility boost)
132
- * to its demoting belief state's ceiling. No-op for `asserted`/`active`/unset
133
- * entries. Applied once per item at the end of `applyRankingRules` so sort
134
- * order and displayed scores stay consistent (single scoring pipeline).
135
- *
136
- * When the ceiling clamps, the pre-clamp score is recorded as
137
- * `preCeilingScore` so db-search's semantic-only `minScore` floor can judge
138
- * the hit by what it would have scored WITHOUT the demotion — a ceiling below
139
- * the floor (archived 0.15 < default minScore 0.2) must demote a hit to last
140
- * place, never silently drop it from the results.
141
- */
142
- export function applyBeliefStateScoreCeiling(item) {
143
- const state = item.entry.beliefState;
144
- const ceiling = state !== undefined ? BELIEF_STATE_SCORE_CEILINGS[state] : undefined;
145
- if (ceiling !== undefined && item.score > ceiling) {
146
- item.preCeilingScore = item.score;
147
- item.score = ceiling;
148
- }
149
- }
150
- const exactNameRankingContributor = {
151
- name: "exact-name-ranking",
152
- appliesTo: () => true,
153
- adjust(item, ctx) {
154
- const entry = item.entry;
155
- const nameLower = entry.name.toLowerCase();
156
- const rawNameBase = nameLower.split("/").pop() ?? nameLower;
157
- const nameBase = entry.type === "memory" && rawNameBase.endsWith(".derived")
158
- ? rawNameBase.slice(0, -".derived".length)
159
- : rawNameBase;
160
- if (nameBase === ctx.queryLower || nameLower === ctx.queryLower) {
161
- return 2.0;
162
- }
163
- const nameTokens = lexicalNameTokens(nameBase);
164
- if (structuralNamePhraseMatch(nameTokens, ctx.queryTokens))
165
- return 1.0;
166
- const matchCount = ctx.queryTokens.filter((qt) => nameTokens.some((nt) => structuralNameTokenMatch(nt, qt))).length;
167
- return matchCount > 0 ? Math.min(0.9, matchCount * 0.3) : 0;
168
- },
169
- };
170
- const typeRankingContributor = {
171
- name: "type-ranking",
172
- appliesTo: () => true,
173
- adjust(item) {
174
- return typeBoostFor(item.entry.type);
175
- },
176
- };
177
- const beliefStateRankingContributor = {
178
- name: "belief-state-ranking",
179
- appliesTo(item) {
180
- // Fire for any entry that carries a belief state, regardless of type — so
181
- // contradicted/superseded knowledge is demoted, not just memories. The
182
- // `.derived`-twin `derivedBoost` (±0.12/−0.08) is deleted (03-R3): it made
183
- // stale flag-free twins outrank their corrected base memory; belief-state
184
- // demotion is the principled signal, not the twin-name heuristic.
185
- return item.entry.beliefState !== undefined;
186
- },
187
- adjust(item) {
188
- return beliefStateBoost(item);
189
- },
190
- };
191
- const tagRankingContributor = {
192
- name: "tag-ranking",
193
- appliesTo(item) {
194
- return Array.isArray(item.entry.tags) && item.entry.tags.length > 0;
195
- },
196
- adjust(item, ctx) {
197
- let tagBoost = 0;
198
- for (const tag of item.entry.tags ?? []) {
199
- if (ctx.queryTokens.some((token) => tag.toLowerCase() === token))
200
- tagBoost += 0.15;
201
- }
202
- return Math.min(0.3, tagBoost);
203
- },
204
- };
205
- const searchHintRankingContributor = {
206
- name: "search-hint-ranking",
207
- appliesTo(item) {
208
- return Array.isArray(item.entry.searchHints) && item.entry.searchHints.length > 0;
209
- },
210
- adjust(item, ctx) {
211
- let hintBoost = 0;
212
- for (const hint of item.entry.searchHints ?? []) {
213
- const hintLower = hint.toLowerCase();
214
- for (const token of ctx.queryTokens) {
215
- if (hintLower.includes(token)) {
216
- hintBoost += 0.12;
217
- break;
218
- }
219
- }
220
- }
221
- return Math.min(0.24, hintBoost);
222
- },
223
- };
224
- const aliasRankingContributor = {
225
- name: "alias-ranking",
226
- appliesTo(item) {
227
- return Array.isArray(item.entry.aliases) && item.entry.aliases.length > 0;
228
- },
229
- adjust(item, ctx) {
230
- let boost = 0;
231
- for (const alias of item.entry.aliases ?? []) {
232
- const aliasLower = alias.toLowerCase();
233
- if (aliasLower === ctx.queryLower) {
234
- boost += 1.5;
235
- break;
236
- }
237
- if (ctx.queryTokens.some((token) => aliasLower.includes(token)))
238
- boost += 0.3;
239
- }
240
- return boost;
241
- },
242
- };
243
- const descriptionRankingContributor = {
244
- name: "description-ranking",
245
- appliesTo(item) {
246
- // A relaxed FTS query admits an OR pool. Awarding a flat +0.1 merely
247
- // because of a partial description coincidence double-counts a weak
248
- // signal and can outrank materially stronger BM25 body evidence. The FTS
249
- // score already accounts for descriptions; retain this secondary boost
250
- // only for conjunctive candidates.
251
- return (item.lexicalMatch !== "relaxed" && typeof item.entry.description === "string" && item.entry.description.length > 0);
252
- },
253
- adjust(item, ctx) {
254
- const descLower = item.entry.description?.toLowerCase() ?? "";
255
- const descMatchCount = ctx.queryTokens.filter((token) => descLower.includes(token)).length;
256
- if (descMatchCount === ctx.queryTokens.length && ctx.queryTokens.length > 1)
257
- return 0.25;
258
- if (descMatchCount > 0)
259
- return 0.1;
260
- return 0;
261
- },
262
- };
263
- const metadataRankingContributor = {
264
- name: "metadata-ranking",
265
- appliesTo: () => true,
266
- adjust(item) {
267
- let boost = item.entry.quality === "curated" ? 0.05 : 0;
268
- if (typeof item.entry.confidence === "number") {
269
- boost += Math.min(0.05, Math.max(0, item.entry.confidence) * 0.05);
270
- }
271
- return boost;
272
- },
273
- };
274
- const graphRankingContributor = {
275
- name: "graph-ranking",
276
- appliesTo(_item, ctx) {
277
- return ctx.graphContext !== null;
278
- },
279
- adjust(item, ctx) {
280
- return ctx.graphContext ? computeGraphBoost(ctx.graphContext, item.filePath) : 0;
281
- },
282
- applied(item, ctx, contribution) {
283
- if (!ctx.graphContext || contribution <= 0)
284
- return;
285
- const graphNode = ctx.graphContext.nodesByPath.get(item.filePath);
286
- attachSearchHitAttribution(item, {
287
- graphExtraction: {
288
- boost: contribution,
289
- ...(graphNode?.bodyHash ? { bodyHash: graphNode.bodyHash } : {}),
290
- ...((graphNode?.extractionRunId ?? ctx.graphContext.graph.telemetry?.extractionRunId)
291
- ? { extractionRunId: graphNode?.extractionRunId ?? ctx.graphContext.graph.telemetry?.extractionRunId }
292
- : {}),
293
- },
294
- });
295
- },
296
- };
297
- /**
298
- * Capture-mode boost — Phase 1B / Rec 7.
299
- *
300
- * Memories captured via the hot path (`akm remember`) get a modest additive
301
- * boost so they outrank otherwise-equal background-derived memories. Memories
302
- * without `captureMode` return 0.
303
- */
304
- const captureModeRankingContributor = {
305
- name: "capture-mode-ranking",
306
- appliesTo(item) {
307
- return item.entry.type === "memory" && item.entry.captureMode === "hot";
308
- },
309
- adjust() {
310
- return 0.2;
311
- },
312
- };
313
- /**
314
- * Lesson strength boost — Phase 7A / Advantage D4b.
315
- *
316
- * Each ref that has credited a lesson via `akm feedback --applied-to` adds
317
- * 0.06 to the boost (capped at 0.3 ≈ five credits). Lessons without a
318
- * `lessonStrength` array (or a number) return 0.
319
- */
320
- const lessonStrengthContributor = {
321
- name: "lesson-strength-ranking",
322
- appliesTo(item) {
323
- return (item.entry.type === "lesson" && typeof item.entry.lessonStrength === "number" && item.entry.lessonStrength > 0);
324
- },
325
- adjust(item) {
326
- const strength = item.entry.lessonStrength ?? 0;
327
- return Math.min(0.3, 0.06 * strength);
328
- },
329
- };
330
- /**
331
- * Pinned-fact boost.
332
- *
333
- * Facts marked `pinned: true` form the small always-injected "core context"
334
- * (see docs/architecture/specs/fact-asset-type.md). The fact metadata contributor records
335
- * a `pinned` search hint; here we give those facts a modest additive boost so
336
- * the core outranks ordinary facts on otherwise-equal queries. Capped small so
337
- * it cannot overpower an exact-name match.
338
- */
339
- const pinnedFactRankingContributor = {
340
- name: "pinned-fact-ranking",
341
- appliesTo(item) {
342
- return item.entry.type === "fact" && (item.entry.searchHints?.includes("pinned") ?? false);
343
- },
344
- adjust() {
345
- return 0.15;
346
- },
347
- };
348
- /**
349
- * Blend ratio for scoped vs. global utility signals.
350
- *
351
- * When a scoped row exists: `effectiveUtility = scoped * 0.7 + global * 0.3`
352
- * This ensures the in-project signal strongly dominates while the global
353
- * cold-start signal still helps when scoped history is sparse.
354
- */
355
- const SCOPED_UTILITY_BLEND_SCOPED = 0.7;
356
- const SCOPED_UTILITY_BLEND_GLOBAL = 1 - SCOPED_UTILITY_BLEND_SCOPED;
357
- const utilityRankingContributor = {
358
- name: "utility-ranking",
359
- appliesTo(item, ctx) {
360
- const utilScore = ctx.utilityScores.get(item.id);
361
- const scopedScore = ctx.scopedUtilityScores?.get(item.id);
362
- return Boolean((utilScore && utilScore.utility > 0) || (scopedScore && scopedScore.utility > 0));
363
- },
364
- apply(item, ctx) {
365
- const utilScore = ctx.utilityScores.get(item.id);
366
- const scopedScore = ctx.scopedUtilityScores?.get(item.id);
367
- // Determine effective utility: prefer scoped when present, blend with global.
368
- const globalUtility = utilScore?.utility ?? 0;
369
- const scopedUtility = scopedScore?.utility ?? 0;
370
- const effectiveUtility = scopedUtility > 0
371
- ? scopedUtility * SCOPED_UTILITY_BLEND_SCOPED + globalUtility * SCOPED_UTILITY_BLEND_GLOBAL
372
- : globalUtility;
373
- if (effectiveUtility <= 0)
374
- return;
375
- // Recency decay: use the global lastUsedAt for the decay factor (it's an
376
- // ISO string with full resolution), falling back to scoped lastUsedAt (ms).
377
- let recencyFactor = 1;
378
- const lastUsedRaw = utilScore?.lastUsedAt ?? (scopedScore ? new Date(scopedScore.lastUsedAt).toISOString() : undefined);
379
- if (lastUsedRaw) {
380
- const lastUsedMs = new Date(lastUsedRaw).getTime();
381
- const daysSinceLastUse = Number.isNaN(lastUsedMs)
382
- ? Infinity
383
- : Math.max(0, (Date.now() - lastUsedMs) / (1000 * 60 * 60 * 24));
384
- // Phase 2A / Rec 5: configurable forgetting curve with optional
385
- // feedback-stability boost. Absent config + absent positive feedback
386
- // collapses to `exp(-days / 30)` — pre-2A default-safe.
387
- const halfLifeDays = ctx.utilityDecayConfig?.halfLifeDays ?? DEFAULT_RECENCY_HALF_LIFE_DAYS;
388
- const stabilityBoost = ctx.utilityDecayConfig?.feedbackStabilityBoost ?? 1.5;
389
- const positiveCount = ctx.positiveFeedbackCounts?.get(item.id) ?? 0;
390
- // `boost^count` is 1 when count is 0 OR when boost is 1.0, so neither
391
- // a missing feedback count nor a "no boost" config widens the half-life.
392
- let stabilizedHalfLife = halfLifeDays * stabilityBoost ** positiveCount;
393
- stabilizedHalfLife = Math.min(stabilizedHalfLife, halfLifeDays * FEEDBACK_HALF_LIFE_CAP_MULTIPLIER);
394
- // Defensive: half-life must stay positive to avoid div-by-zero / Infinity.
395
- const safeHalfLife = Math.max(0.0001, stabilizedHalfLife);
396
- recencyFactor = Math.exp(-daysSinceLastUse / safeHalfLife);
397
- }
398
- const rawBoost = 1 + effectiveUtility * recencyFactor * UTILITY_WEIGHT;
399
- item.score *= Math.min(rawBoost, UTILITY_MAX_BOOST);
400
- item.utilityBoosted = true;
401
- },
402
- };
403
- /**
404
- * Project-context boost.
405
- *
406
- * Auto-boosts assets whose name, tags, aliases, or search hints contain tokens
407
- * derived from the current working directory's project name. For example, when
408
- * running `akm search` from the `akm` git repo, assets tagged `akm` or named
409
- * `akm-*` receive an additive boost.
410
- *
411
- * The boost is capped at 0.5 so it can never overpower an exact-name match
412
- * (which contributes 2.0). Each matching token adds 0.2 up to the cap.
413
- *
414
- * Skipped entirely when `projectContext` is absent or has no tokens (e.g.
415
- * when running from home dir, /tmp, or when disabled via
416
- * `--no-project-context`).
417
- */
418
- const projectContextRankingContributor = {
419
- name: "project-context-ranking",
420
- appliesTo(_item, ctx) {
421
- return ctx.projectContext != null && ctx.projectContext.tokens.size > 0;
422
- },
423
- adjust(item, ctx) {
424
- if (!ctx.projectContext)
425
- return 0;
426
- const fields = [
427
- item.entry.name ?? "",
428
- ...(item.entry.tags ?? []),
429
- ...(item.entry.aliases ?? []),
430
- ...(item.entry.searchHints ?? []),
431
- ].map((s) => s.toLowerCase());
432
- let hits = 0;
433
- for (const token of ctx.projectContext.tokens) {
434
- if (fields.some((f) => f.includes(token)))
435
- hits++;
436
- }
437
- return Math.min(0.5, hits * 0.2);
438
- },
439
- };
440
- export const defaultRankingContributors = [
441
- exactNameRankingContributor,
442
- typeRankingContributor,
443
- beliefStateRankingContributor,
444
- tagRankingContributor,
445
- searchHintRankingContributor,
446
- aliasRankingContributor,
447
- descriptionRankingContributor,
448
- metadataRankingContributor,
449
- graphRankingContributor,
450
- captureModeRankingContributor,
451
- lessonStrengthContributor,
452
- pinnedFactRankingContributor,
453
- projectContextRankingContributor,
454
- ];
455
- /**
456
- * R2 — the improve loop's salience core, as a bounded multiplicative ranking
457
- * boost. `asset_salience.rank_score` (encoding + outcome + retrieval
458
- * projection, maintained every improve run) otherwise drives only improve's
459
- * INTERNAL maintenance selection.
460
- *
461
- * **#692 — NOT in {@link defaultUtilityRankingContributors}.** Removed from
462
- * default user-facing ranking (search/curate): the boost was
463
- * retrieval-dominated (`w_r = 0.60` in salience.ts, with no source filter, so
464
- * it double-counted the same `usage_events` the utility EMA contributor
465
- * already reinforces), warm-started non-zero with no outcome evidence, had
466
- * zero pack coverage (favoring only self-generated personal assets), and
467
- * measured as noise on live data (max observed multiplier ×1.071). Removing
468
- * its default state.db load also deleted a confirmed hot-path defect — see
469
- * the now-deleted `loadSalienceRankScores` in `ranking.ts` git history.
470
- *
471
- * `rank_score` itself is UNCHANGED as improve's internal selection signal.
472
- * This contributor, and its weight/cap constants, stay exported so a FUTURE
473
- * gated experiment (config-gated, outcome-gated) can wire it back in
474
- * explicitly — see `RankEntriesOptions.salienceRankScores`'s doc comment in
475
- * `ranking.ts`. Reachable today only via explicit contributor-list injection
476
- * (tests / eval harnesses calling `applyUtilityContributors` directly with a
477
- * list that includes it) — never through `applyRankingRules` / `akm search` /
478
- * `akm curate`.
479
- */
480
- export const salienceRankingContributor = {
481
- name: "salience-ranking",
482
- appliesTo(item, ctx) {
483
- const rank = ctx.salienceRankScores?.get(item.id);
484
- return rank !== undefined && rank > 0;
485
- },
486
- apply(item, ctx) {
487
- const rank = ctx.salienceRankScores?.get(item.id) ?? 0;
488
- const rawBoost = 1 + Math.min(1, Math.max(0, rank)) * SALIENCE_WEIGHT;
489
- item.score *= Math.min(rawBoost, SALIENCE_MAX_BOOST);
490
- },
491
- };
492
- // #692 — salienceRankingContributor deliberately excluded; see its doc
493
- // comment. Do not add it back here without a config gate + a measured
494
- // curate-golden-bench delta justifying it.
495
- export const defaultUtilityRankingContributors = [utilityRankingContributor];
496
- export function applyScoreContributors(item, ctx, contributors = defaultRankingContributors) {
497
- let boostSum = 0;
498
- for (const contributor of contributors) {
499
- if (!contributor.appliesTo(item, ctx))
500
- continue;
501
- const cappedBefore = Math.min(boostSum, MAX_BOOST_SUM);
502
- boostSum += contributor.adjust(item, ctx);
503
- // Attribution receives only the share admitted by the common boost cap,
504
- // never a raw contributor value that scoring discarded.
505
- contributor.applied?.(item, ctx, Math.min(boostSum, MAX_BOOST_SUM) - cappedBefore);
506
- }
507
- item.score *= 1 + Math.min(boostSum, MAX_BOOST_SUM);
508
- }
509
- export function applyUtilityContributors(item, ctx, contributors = defaultUtilityRankingContributors) {
510
- for (const contributor of contributors) {
511
- if (!contributor.appliesTo(item, ctx))
512
- continue;
513
- contributor.apply(item, ctx);
514
- }
515
- }