akm-cli 0.9.16 → 0.9.17-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. package/CHANGELOG.md +2101 -0
  2. package/STABILITY.md +11 -10
  3. package/dist/akm +124 -193
  4. package/dist/akm-migrate +38 -19
  5. package/dist/assets/hints/cli-hints-full.md +6 -7
  6. package/dist/assets/improve-strategies/catchup.json +0 -3
  7. package/dist/assets/improve-strategies/consolidate.json +0 -1
  8. package/dist/assets/improve-strategies/default.json +1 -2
  9. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -2
  10. package/dist/assets/improve-strategies/quick.json +1 -2
  11. package/dist/assets/improve-strategies/reflect-distill.json +1 -2
  12. package/dist/assets/improve-strategies/thorough.json +0 -3
  13. package/dist/assets/prompts/consolidate-pair.md +20 -0
  14. package/dist/assets/prompts/consolidate-system.md +4 -11
  15. package/dist/assets/prompts/retrieval-relevance-judge.md +6 -0
  16. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +20 -20
  17. package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -2
  18. package/dist/assets/templates/html/health.html +3 -5
  19. package/dist/cli/retired-commands.js +1 -1
  20. package/dist/cli/shared.js +6 -2
  21. package/dist/cli/unknown-flags.js +24 -1
  22. package/dist/cli.js +68 -10
  23. package/dist/commands/agent/agent-dispatch.js +1 -1
  24. package/dist/commands/command/command-execution.js +24 -62
  25. package/dist/commands/feedback-cli.js +0 -1
  26. package/dist/commands/health/accept-rate.js +6 -0
  27. package/dist/commands/health/archive-usage.js +92 -0
  28. package/dist/commands/health/checks.js +83 -74
  29. package/dist/commands/health/config-skew.js +38 -0
  30. package/dist/commands/health/data-dir-usage.js +25 -13
  31. package/dist/commands/health/egress.js +54 -0
  32. package/dist/commands/health/html-report.js +1 -42
  33. package/dist/commands/health/improve-metrics.js +136 -591
  34. package/dist/commands/health/md-report.js +1 -6
  35. package/dist/commands/health/plugin-staleness.js +53 -3
  36. package/dist/commands/health/renderers.js +12 -4
  37. package/dist/commands/health/report-view-model.js +14 -120
  38. package/dist/commands/health/types-improve.js +4 -19
  39. package/dist/commands/health/windows.js +64 -74
  40. package/dist/commands/health.js +145 -143
  41. package/dist/commands/improve/consolidate/chunking.js +26 -117
  42. package/dist/commands/improve/consolidate/continuity-check.js +137 -0
  43. package/dist/commands/improve/consolidate/pair-pass.js +791 -0
  44. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  45. package/dist/commands/improve/consolidate.js +589 -1127
  46. package/dist/commands/improve/content-hash.js +16 -24
  47. package/dist/commands/improve/distill/content-repair.js +18 -100
  48. package/dist/commands/improve/distill-guards.js +20 -81
  49. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  50. package/dist/commands/improve/distill.js +608 -1041
  51. package/dist/commands/improve/eligibility.js +126 -390
  52. package/dist/commands/improve/execution.js +8 -10
  53. package/dist/commands/improve/extract-prompt.js +1 -2
  54. package/dist/commands/improve/extract.js +487 -1046
  55. package/dist/commands/improve/feedback-valence.js +0 -25
  56. package/dist/commands/improve/improve-cli.js +75 -169
  57. package/dist/commands/improve/improve-result-file.js +10 -66
  58. package/dist/commands/improve/improve-strategies.js +52 -4
  59. package/dist/commands/improve/improve-usage-report.js +18 -64
  60. package/dist/commands/improve/improve.js +480 -1074
  61. package/dist/commands/improve/ledger.js +119 -0
  62. package/dist/commands/improve/locks.js +2 -8
  63. package/dist/commands/improve/loop-stages.js +415 -1073
  64. package/dist/commands/improve/memory/derived-ref.js +12 -77
  65. package/dist/commands/improve/memory/memory-belief.js +16 -118
  66. package/dist/commands/improve/memory/memory-improve.js +266 -14
  67. package/dist/commands/improve/outcome-loop.js +28 -156
  68. package/dist/commands/improve/planner.js +5 -15
  69. package/dist/commands/improve/preparation.js +779 -2319
  70. package/dist/commands/improve/proactive-maintenance.js +34 -101
  71. package/dist/commands/improve/reflect-noise.js +104 -280
  72. package/dist/commands/improve/reflect.js +642 -1353
  73. package/dist/commands/improve/retrieval-gate.js +127 -0
  74. package/dist/commands/improve/retrieval-scope.js +92 -0
  75. package/dist/commands/improve/salience.js +41 -240
  76. package/dist/commands/improve/session-asset.js +19 -100
  77. package/dist/commands/improve/stage.js +322 -0
  78. package/dist/commands/lint/base-linter.js +37 -15
  79. package/dist/commands/proposal/drain.js +261 -578
  80. package/dist/commands/proposal/proposal-cli.js +19 -20
  81. package/dist/commands/proposal/proposal-types.js +31 -24
  82. package/dist/commands/proposal/proposal.js +38 -8
  83. package/dist/commands/proposal/propose.js +134 -160
  84. package/dist/commands/proposal/repository.js +1097 -1394
  85. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  86. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  87. package/dist/commands/proposal/validators/proposals.js +22 -89
  88. package/dist/commands/read/curate.js +105 -462
  89. package/dist/commands/read/knowledge.js +3 -2
  90. package/dist/commands/read/search-cli.js +16 -33
  91. package/dist/commands/read/search.js +17 -23
  92. package/dist/commands/read/show.js +57 -108
  93. package/dist/commands/sources/bundle-cli.js +25 -2
  94. package/dist/commands/sources/bundle-config-ops.js +4 -0
  95. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  96. package/dist/commands/sources/info.js +127 -29
  97. package/dist/commands/sources/installed-stashes.js +197 -746
  98. package/dist/commands/sources/schema-repair.js +98 -129
  99. package/dist/commands/sources/source-add.js +62 -12
  100. package/dist/commands/sources/source-manage.js +9 -2
  101. package/dist/commands/sources/stash-cli.js +24 -4
  102. package/dist/commands/tasks/explain.js +10 -13
  103. package/dist/commands/tasks/tasks-cli.js +12 -13
  104. package/dist/commands/tasks/tasks.js +350 -936
  105. package/dist/commands/tasks/validate.js +26 -24
  106. package/dist/commands/workflow/plan.js +22 -29
  107. package/dist/commands/workflow-cli.js +4 -4
  108. package/dist/core/adapter/adapters/akm-adapter.js +2 -1
  109. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  110. package/dist/core/adapter/adapters/akm-metadata.js +42 -12
  111. package/dist/core/adapter/adapters/akm-task-adapter.js +29 -8
  112. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  113. package/dist/core/adapter/execution-source.js +17 -29
  114. package/dist/core/asset/asset-placement.js +4 -13
  115. package/dist/core/asset/frontmatter.js +106 -1
  116. package/dist/core/asset/resolve-ref.js +1 -1
  117. package/dist/core/bundle-id.js +42 -5
  118. package/dist/core/bundle-rename.js +285 -0
  119. package/dist/core/config/config-io.js +1 -2
  120. package/dist/core/config/config-schema.js +9 -34
  121. package/dist/core/config/config-walker.js +1 -1
  122. package/dist/core/config/config.js +184 -111
  123. package/dist/core/config/engine-semantics.js +0 -2
  124. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  125. package/dist/core/config/schema/embedding.js +20 -5
  126. package/dist/core/config/schema/engines.js +5 -0
  127. package/dist/core/config/schema/execution.js +1 -1
  128. package/dist/core/config/schema/experimental.js +1 -1
  129. package/dist/core/config/schema/improve-processes.js +54 -125
  130. package/dist/core/config/schema/improve.js +4 -42
  131. package/dist/core/config/schema/index-config.js +9 -48
  132. package/dist/core/config/schema/scheduler.js +12 -12
  133. package/dist/core/config/schema/search.js +6 -22
  134. package/dist/core/env-secret-ref.js +0 -1
  135. package/dist/core/errors.js +8 -9
  136. package/dist/core/file-change.js +13 -5
  137. package/dist/core/file-lock.js +76 -173
  138. package/dist/core/improve-result.js +35 -7
  139. package/dist/core/improve-types.js +0 -1
  140. package/dist/core/logs-db.js +2 -2
  141. package/dist/core/loopback.js +7 -12
  142. package/dist/core/non-task-input.js +20 -0
  143. package/dist/core/parse.js +13 -16
  144. package/dist/core/paths.js +0 -24
  145. package/dist/core/redaction.js +109 -2
  146. package/dist/core/run-lock.js +2 -5
  147. package/dist/core/spawn-env.js +1 -1
  148. package/dist/core/state/migrations.js +123 -61
  149. package/dist/core/state-db-scope.js +2 -4
  150. package/dist/core/state-db.js +126 -692
  151. package/dist/core/time.js +0 -20
  152. package/dist/core/type-presentation.js +1 -9
  153. package/dist/core/write-source.js +294 -1005
  154. package/dist/execution/input-contract.js +1 -1
  155. package/dist/execution/resolved-request.js +135 -689
  156. package/dist/execution/source.js +63 -257
  157. package/dist/execution/target-ref.js +1 -1
  158. package/dist/indexer/bundle-identity-guard.js +2 -2
  159. package/dist/indexer/db/llm-cache.js +2 -2
  160. package/dist/indexer/ensure-index.js +77 -73
  161. package/dist/indexer/index-rebuild-lock.js +3 -11
  162. package/dist/indexer/index-writer-lock.js +8 -17
  163. package/dist/indexer/index-written-assets.js +141 -154
  164. package/dist/indexer/indexer.js +400 -1124
  165. package/dist/indexer/links/declared-links.js +90 -0
  166. package/dist/indexer/materialize-embeddings.js +60 -397
  167. package/dist/indexer/passes/memory-inference.js +96 -90
  168. package/dist/indexer/passes/metadata.js +132 -219
  169. package/dist/indexer/read-preflight.js +0 -7
  170. package/dist/indexer/scan/doc-to-entry.js +2 -3
  171. package/dist/indexer/scan/drain-dir.js +1 -1
  172. package/dist/indexer/search/db-search.js +190 -590
  173. package/dist/indexer/search/fts-query.js +30 -41
  174. package/dist/indexer/search/ranking.js +28 -154
  175. package/dist/indexer/search/search-attribution.js +12 -32
  176. package/dist/indexer/search/search-fields.js +11 -15
  177. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  178. package/dist/indexer/search/search-source.js +1 -4
  179. package/dist/indexer/usage/usage-events.js +36 -7
  180. package/dist/indexer/walk/walker.js +3 -4
  181. package/dist/integrations/agent/engine-fallback.js +23 -40
  182. package/dist/integrations/agent/engine-resolution.js +93 -183
  183. package/dist/integrations/agent/execution.js +507 -0
  184. package/dist/integrations/agent/model-map.js +28 -156
  185. package/dist/integrations/agent/request-lowering.js +66 -141
  186. package/dist/integrations/agent/runner-dispatch.js +143 -321
  187. package/dist/integrations/agent/runner.js +54 -14
  188. package/dist/integrations/lockfile.js +53 -101
  189. package/dist/llm/client.js +18 -6
  190. package/dist/llm/embedders/deterministic.js +2 -3
  191. package/dist/llm/embedders/profile.js +71 -0
  192. package/dist/llm/embedders/remote.js +11 -17
  193. package/dist/llm/feature-gate.js +0 -8
  194. package/dist/llm/index-passes.js +3 -5
  195. package/dist/llm/memory-infer.js +1 -2
  196. package/dist/llm/structured-call.js +5 -24
  197. package/dist/output/generic-render.js +23 -11
  198. package/dist/output/html-render.js +13 -10
  199. package/dist/output/render-registry.js +3 -32
  200. package/dist/output/shapes/helpers.js +25 -38
  201. package/dist/output/shapes/passthrough.js +1 -9
  202. package/dist/{indexer/graph/graph-types.js → output/text/bundle-rename.js} +4 -1
  203. package/dist/output/text/command-format.js +69 -31
  204. package/dist/output/text/helpers.js +1 -1
  205. package/dist/output/text/migrate.js +5 -14
  206. package/dist/output/text/proposal-format.js +48 -3
  207. package/dist/output/text/show-format.js +13 -17
  208. package/dist/output/text/workflow-format.js +0 -32
  209. package/dist/output/text.js +2 -0
  210. package/dist/registry/factory.js +4 -19
  211. package/dist/registry/network.js +66 -220
  212. package/dist/registry/providers/index.js +0 -2
  213. package/dist/registry/providers/skills-sh.js +3 -14
  214. package/dist/registry/providers/static-index.js +24 -26
  215. package/dist/registry/resolve.js +55 -131
  216. package/dist/scripts/akm-migrate-node.js +42948 -92369
  217. package/dist/scripts/akm-migrate.js +42935 -92354
  218. package/dist/setup/registry-stash-loader.js +4 -13
  219. package/dist/setup/semantic-assets.js +3 -44
  220. package/dist/setup/setup.js +1 -1
  221. package/dist/setup/steps/connection.js +5 -6
  222. package/dist/setup/steps/platforms.js +2 -2
  223. package/dist/setup/steps/tasks.js +25 -15
  224. package/dist/sources/provider-factory.js +17 -18
  225. package/dist/sources/providers/filesystem.js +2 -3
  226. package/dist/sources/providers/git-install.js +7 -1
  227. package/dist/sources/providers/git-provider.js +0 -3
  228. package/dist/sources/providers/git-stash.js +83 -21
  229. package/dist/sources/providers/npm.js +2 -4
  230. package/dist/sources/providers/provider-utils.js +5 -10
  231. package/dist/sources/providers/website.js +0 -2
  232. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  233. package/dist/sources/website-url.js +2 -2
  234. package/dist/storage/database.js +9 -35
  235. package/dist/storage/repositories/improve-ledger-repository.js +209 -0
  236. package/dist/storage/repositories/index-connection.js +39 -72
  237. package/dist/storage/repositories/index-entries-repository.js +131 -129
  238. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  239. package/dist/storage/repositories/index-entry-schema.js +101 -268
  240. package/dist/storage/repositories/index-fts-repository.js +86 -256
  241. package/dist/storage/repositories/index-links-repository.js +143 -0
  242. package/dist/storage/repositories/index-llm-cache-repository.js +7 -9
  243. package/dist/storage/repositories/index-meta-repository.js +6 -4
  244. package/dist/storage/repositories/index-schema.js +257 -325
  245. package/dist/storage/repositories/index-utility-repository.js +8 -29
  246. package/dist/storage/repositories/index-vec-repository.js +133 -414
  247. package/dist/storage/repositories/outcome-repository.js +2 -1
  248. package/dist/storage/repositories/proposals-repository.js +104 -1
  249. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  250. package/dist/storage/repositories/salience-repository.js +1 -19
  251. package/dist/storage/repositories/task-history-repository.js +26 -4
  252. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  253. package/dist/storage/sqlite-migrations.js +136 -0
  254. package/dist/storage/sqlite-pragmas.js +11 -9
  255. package/dist/storage/sqlite-transaction.js +170 -0
  256. package/dist/storage/state-db-integrity.js +130 -0
  257. package/dist/tasks/activation-config.js +134 -62
  258. package/dist/tasks/backends/cron.js +191 -302
  259. package/dist/tasks/backends/exec-utils.js +2 -5
  260. package/dist/tasks/backends/launchd.js +141 -748
  261. package/dist/tasks/backends/schtasks.js +119 -623
  262. package/dist/tasks/prepare/prepare-support.js +5 -15
  263. package/dist/tasks/prepare/prepare.js +0 -2
  264. package/dist/tasks/resolve-akm-bin.js +20 -79
  265. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  266. package/dist/tasks/run/load-task.js +1 -1
  267. package/dist/tasks/scheduler-binding.js +20 -238
  268. package/dist/tasks/scheduler-invocation.js +136 -244
  269. package/dist/tasks/scheduler-lock.js +53 -0
  270. package/dist/tasks/scheduler-sync.js +368 -679
  271. package/dist/tasks/source/parse-task-source.js +55 -9
  272. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  273. package/dist/tasks/source/task-to-v4.js +464 -88
  274. package/dist/workflows/authoring/authoring.js +3 -12
  275. package/dist/workflows/compile.js +211 -0
  276. package/dist/workflows/concurrency-policy.js +13 -74
  277. package/dist/workflows/exec/child-invocation.js +3 -17
  278. package/dist/workflows/exec/child-workflow.js +32 -141
  279. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  280. package/dist/workflows/exec/environment.js +98 -0
  281. package/dist/workflows/exec/exec-unit.js +33 -140
  282. package/dist/workflows/exec/frozen-judge.js +7 -59
  283. package/dist/workflows/exec/native-executor.js +82 -341
  284. package/dist/workflows/exec/param-secrets.js +29 -47
  285. package/dist/workflows/exec/run-workflow.js +154 -387
  286. package/dist/workflows/exec/scheduler.js +9 -36
  287. package/dist/workflows/exec/step-work.js +127 -430
  288. package/dist/workflows/exec/unit-dispatch.js +11 -63
  289. package/dist/workflows/exec/unit-writer.js +8 -52
  290. package/dist/workflows/exec/worktree.js +39 -273
  291. package/dist/workflows/freeze/child-output-references.js +4 -15
  292. package/dist/workflows/freeze/environment.js +99 -92
  293. package/dist/workflows/freeze/freeze.js +172 -0
  294. package/dist/workflows/freeze/step-values.js +19 -21
  295. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  296. package/dist/workflows/freeze/targets/command.js +10 -33
  297. package/dist/workflows/freeze/targets/script.js +5 -12
  298. package/dist/workflows/freeze/targets/shell.js +3 -6
  299. package/dist/workflows/freeze/targets/task.js +25 -80
  300. package/dist/workflows/freeze/task-bindings.js +20 -67
  301. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  302. package/dist/workflows/ir/params.js +6 -51
  303. package/dist/workflows/ir/plan-hash.js +2 -34
  304. package/dist/workflows/parser.js +140 -43
  305. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  306. package/dist/workflows/renderer.js +36 -69
  307. package/dist/workflows/resource-limits.js +12 -120
  308. package/dist/workflows/runtime/agent-identity.js +8 -40
  309. package/dist/workflows/runtime/run-outputs.js +3 -6
  310. package/dist/workflows/runtime/run-plan.js +316 -0
  311. package/dist/workflows/runtime/runs.js +48 -200
  312. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  313. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  314. package/dist/workflows/validate-summary.js +2 -7
  315. package/docs/integration/bundling-akm.md +49 -42
  316. package/docs/migration/README.md +1 -0
  317. package/docs/migration/release-notes/0.9.17.md +43 -0
  318. package/docs/migration/v0.9.1-to-v0.9.2.md +23 -7
  319. package/docs/reference/cli.md +232 -135
  320. package/docs/reference/configuration.md +71 -57
  321. package/docs/reference/data-and-telemetry.md +20 -21
  322. package/docs/reference/tasks.md +105 -39
  323. package/docs/reference/workflow-schema.md +14 -18
  324. package/docs/reference/workflows.md +6 -9
  325. package/package.json +1 -1
  326. package/schemas/akm-config.json +115 -738
  327. package/schemas/akm-workflow.json +1 -0
  328. package/dist/assets/improve-strategies/graph-refresh.json +0 -15
  329. package/dist/assets/prompts/contradiction-judge.md +0 -33
  330. package/dist/assets/prompts/graph-extract-system.md +0 -1
  331. package/dist/assets/prompts/graph-extract-user-prompt.md +0 -35
  332. package/dist/assets/prompts/metadata-enhance-system.md +0 -1
  333. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +0 -4
  334. package/dist/commands/health/advisories.js +0 -150
  335. package/dist/commands/health/metrics.js +0 -329
  336. package/dist/commands/health/surfaces.js +0 -102
  337. package/dist/commands/improve/anti-collapse.js +0 -83
  338. package/dist/commands/improve/collapse-detector.js +0 -432
  339. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  340. package/dist/commands/improve/consolidate/merge.js +0 -149
  341. package/dist/commands/improve/distill/promote-memory.js +0 -291
  342. package/dist/commands/improve/distill/quality-gate.js +0 -337
  343. package/dist/commands/improve/eval-cases.js +0 -52
  344. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  345. package/dist/commands/improve/proposal-envelope.js +0 -31
  346. package/dist/commands/improve/run-context.js +0 -123
  347. package/dist/commands/improve/shared.js +0 -31
  348. package/dist/commands/improve/source-identity.js +0 -28
  349. package/dist/commands/improve/triage.js +0 -96
  350. package/dist/commands/proposal/drain-policies.js +0 -151
  351. package/dist/commands/sources/update-transaction.js +0 -220
  352. package/dist/core/action-contributors.js +0 -28
  353. package/dist/core/config/config-version-shim.js +0 -101
  354. package/dist/core/fs-txn.js +0 -405
  355. package/dist/core/lexical-score.js +0 -25
  356. package/dist/core/maintenance-barrier.js +0 -167
  357. package/dist/execution/executable-identity.js +0 -105
  358. package/dist/execution/guarded-source.js +0 -427
  359. package/dist/indexer/db/graph-db.js +0 -444
  360. package/dist/indexer/graph/graph-boost.js +0 -427
  361. package/dist/indexer/graph/graph-dedup.js +0 -95
  362. package/dist/indexer/graph/graph-extraction.js +0 -1108
  363. package/dist/indexer/search/name-match.js +0 -35
  364. package/dist/indexer/search/ranking-contributors.js +0 -515
  365. package/dist/indexer/search/ranking-types.js +0 -4
  366. package/dist/indexer/walk/project-context.js +0 -192
  367. package/dist/integrations/agent/execution-cascade.js +0 -566
  368. package/dist/integrations/agent/execution-definitions.js +0 -202
  369. package/dist/integrations/agent/execution-lowering.js +0 -841
  370. package/dist/integrations/agent/execution-preparation.js +0 -98
  371. package/dist/integrations/agent/inline-execution.js +0 -74
  372. package/dist/llm/graph-extract.js +0 -728
  373. package/dist/llm/metadata-enhance.js +0 -96
  374. package/dist/registry/create-provider-registry.js +0 -29
  375. package/dist/registry/pinned-request-helper.js +0 -247
  376. package/dist/registry/pinned-transport.js +0 -717
  377. package/dist/sources/providers/index.js +0 -14
  378. package/dist/storage/engines/sqlite-migrations.js +0 -271
  379. package/dist/storage/repositories/canaries-repository.js +0 -107
  380. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  381. package/dist/storage/repositories/registry-cache.js +0 -113
  382. package/dist/tasks/scheduler-sync-preview.js +0 -52
  383. package/dist/tasks/source/task-to-v3.js +0 -507
  384. package/dist/workflows/freeze/resolve-steps.js +0 -86
  385. package/dist/workflows/freeze/source-freeze.js +0 -64
  386. package/dist/workflows/ir/compile.js +0 -321
  387. package/dist/workflows/ir/environment-v4.js +0 -330
  388. package/dist/workflows/ir/freeze-v4.js +0 -153
  389. package/dist/workflows/ir/schema-v4.js +0 -745
  390. package/dist/workflows/ir/schema.js +0 -354
  391. package/dist/workflows/program/schema.js +0 -77
  392. package/dist/workflows/runtime/checkin.js +0 -57
  393. package/dist/workflows/runtime/plan-classifier.js +0 -196
  394. package/dist/workflows/runtime/unit-checkin.js +0 -45
  395. package/dist/workflows/runtime/unit-phases.js +0 -20
  396. package/dist/workflows/schema.js +0 -4
  397. package/dist/workflows/source-ir/compile.js +0 -200
  398. package/dist/workflows/source-ir/program.js +0 -50
  399. package/dist/workflows/source-ir/result.js +0 -26
  400. package/dist/workflows/source-ir/schema.js +0 -786
  401. package/dist/workflows/source-ir/triggers.js +0 -79
  402. package/dist/workflows/source-ir/uses.js +0 -40
  403. package/dist/workflows/validator.js +0 -60
@@ -0,0 +1,127 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * The retrieval regression gate (#722): a reflect rewrite of an existing asset
6
+ * must not grade lower on the queries that actually retrieved it.
7
+ *
8
+ * Measured before it was built: of 60 accepted reflect rewrites judged against
9
+ * their own queries, 14 graded lower (23%, 95% CI 14–35%) and 12 higher. The
10
+ * old and new content are graded one query at a time, blind, with the
11
+ * retrieval-eval judge's prompt (kappa 0.83 against human grades) and its
12
+ * document shape: type, ref, name, description and the first 1,500 characters
13
+ * of the body.
14
+ */
15
+ import relevanceJudgePrompt from "../../assets/prompts/retrieval-relevance-judge.md" with { type: "text" };
16
+ import { parseFrontmatter } from "../../core/asset/frontmatter.js";
17
+ import { parseRefInput } from "../../core/asset/resolve-ref.js";
18
+ import { nonTaskInput } from "../../core/non-task-input.js";
19
+ import { parseEmbeddedJsonResponse } from "../../core/parse.js";
20
+ import { listRetrievalQueries } from "../../indexer/usage/usage-events.js";
21
+ import { readLedgerDb, stripBundle } from "./ledger.js";
22
+ import { callStage } from "./stage.js";
23
+ /** Queries graded per rewrite, as measured. */
24
+ const MAX_QUERIES = 5;
25
+ /** The retrieval suite treats a longer input as a paste, not a query; the measurement did the same. */
26
+ const MAX_QUERY_CHARS = 2000;
27
+ /** The judge sees this much of the body, as in the retrieval eval. */
28
+ const MAX_DOC_CHARS = 1500;
29
+ const GRADE_SCHEMA = {
30
+ type: "object",
31
+ required: ["grade", "reason"],
32
+ additionalProperties: false,
33
+ properties: { grade: { type: "integer", minimum: 0, maximum: 3 }, reason: { type: "string" } },
34
+ };
35
+ /** Up to five distinct task queries, in the given order, whitespace collapsed. */
36
+ export function usableRetrievalQueries(raw) {
37
+ const out = [];
38
+ for (const text of raw) {
39
+ const query = text.replace(/\s+/g, " ").trim();
40
+ if (!query || query.length > MAX_QUERY_CHARS || nonTaskInput(query) || out.includes(query))
41
+ continue;
42
+ out.push(query);
43
+ if (out.length === MAX_QUERIES)
44
+ break;
45
+ }
46
+ return out;
47
+ }
48
+ /** The asset's own retrieval queries from the usage log (none when state.db cannot be read). */
49
+ export function loadRetrievalQueries(access, ref) {
50
+ try {
51
+ return usableRetrievalQueries(readLedgerDb(access, (db) => listRetrievalQueries(db, stripBundle(ref))) ?? []);
52
+ }
53
+ catch {
54
+ return [];
55
+ }
56
+ }
57
+ function judgeDocument(ref, raw) {
58
+ const conceptId = stripBundle(ref);
59
+ const parsed = parseRefInput(conceptId);
60
+ const { data, content } = parseFrontmatter(raw);
61
+ const text = content
62
+ .replace(/\n{3,}/g, "\n\n")
63
+ .trim()
64
+ .slice(0, MAX_DOC_CHARS);
65
+ const name = typeof data.name === "string" && data.name ? data.name : parsed.name;
66
+ const description = typeof data.description === "string" ? data.description : "";
67
+ return [
68
+ "Candidate asset:",
69
+ `Type: ${parsed.type}`,
70
+ `Ref: ${conceptId}`,
71
+ `Name: ${name}`,
72
+ `Description: ${description}`,
73
+ "",
74
+ "Content:",
75
+ text,
76
+ ].join("\n");
77
+ }
78
+ /**
79
+ * Grade `before` and `after` on each query; refuse the rewrite when the new
80
+ * content's mean grade is lower. Fails closed, like the quality judge: a grade
81
+ * that cannot be obtained refuses the rewrite.
82
+ */
83
+ export async function runRetrievalRegressionGate(args) {
84
+ if (args.queries.length === 0)
85
+ return { pass: true, queries: 0, reason: "no retrieval queries to compare on" };
86
+ const documents = { old: judgeDocument(args.ref, args.before), new: judgeDocument(args.ref, args.after) };
87
+ const totals = { old: 0, new: 0 };
88
+ for (const query of args.queries) {
89
+ for (const version of ["old", "new"]) {
90
+ const outcome = await callStage({
91
+ feature: "proposal_quality_gate",
92
+ runner: args.runner,
93
+ system: relevanceJudgePrompt.trim(),
94
+ prompt: `Query: ${query}\n\n${documents[version]}`,
95
+ request: {
96
+ enableThinking: false,
97
+ temperature: 0,
98
+ responseSchema: GRADE_SCHEMA,
99
+ ...(args.timeoutMs !== undefined ? { timeoutMs: args.timeoutMs } : {}),
100
+ ...(args.signal ? { signal: args.signal } : {}),
101
+ ...(args.chat ? { chat: args.chat } : {}),
102
+ },
103
+ ...(args.onNotices ? { onNotices: args.onNotices } : {}),
104
+ });
105
+ const grade = outcome.ok ? parseEmbeddedJsonResponse(outcome.raw)?.grade : undefined;
106
+ if (typeof grade !== "number" || !Number.isInteger(grade) || grade < 0 || grade > 3) {
107
+ return {
108
+ pass: false,
109
+ queries: args.queries.length,
110
+ reason: `retrieval check could not grade the ${version} content${outcome.ok ? "" : ` (${outcome.reason})`}`,
111
+ };
112
+ }
113
+ totals[version] += grade;
114
+ }
115
+ }
116
+ const oldMean = totals.old / args.queries.length;
117
+ const newMean = totals.new / args.queries.length;
118
+ const pass = newMean >= oldMean;
119
+ const grades = `${oldMean.toFixed(2)} -> ${newMean.toFixed(2)} over ${args.queries.length} retrieval ${args.queries.length === 1 ? "query" : "queries"}`;
120
+ return {
121
+ pass,
122
+ queries: args.queries.length,
123
+ oldMean,
124
+ newMean,
125
+ reason: pass ? `retrieval grade ${grades}` : `retrieval regression: grade ${grades}`,
126
+ };
127
+ }
@@ -0,0 +1,92 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * What improve may rework (#986): an asset that retrieval returned inside the
6
+ * usage window, or newly captured material no improve stage has processed.
7
+ *
8
+ * Fresh feedback and an explicit `--scope <ref>` are usage evidence of their
9
+ * own, so the signal-delta and scope lanes need no check. The fallback lanes
10
+ * (proactive maintenance, high salience) and consolidation pick assets
11
+ * without such evidence, so they pick only inside this scope.
12
+ */
13
+ import fs from "node:fs";
14
+ import { daysToMs } from "../../core/common.js";
15
+ import { warn } from "../../core/warn.js";
16
+ import { listUsedEntryRefs, USAGE_EVENT_RETENTION_DAYS } from "../../indexer/usage/usage-events.js";
17
+ import { listImproveLedgerRows } from "../../storage/repositories/improve-ledger-repository.js";
18
+ import { listProposalRefSources } from "../../storage/repositories/proposals-repository.js";
19
+ import { PAIR_PASS_LEDGER_SOURCE, readLedgerDb, stripBundle } from "./ledger.js";
20
+ /**
21
+ * Ledger and proposal sources that bring material in. Every other source is an
22
+ * improve stage reworking an asset (reflect, distill, consolidate, schema repair).
23
+ */
24
+ const CAPTURE_SOURCES = new Set(["extract", "propose", "remember", "import"]);
25
+ /**
26
+ * Load the scope from state.db. The window is the usage log's retention: the
27
+ * log keeps nothing older, and anything shorter would drop assets read less
28
+ * often than the window. A `.derived` hit counts for its parent memory, whose
29
+ * facts it carries. `undefined` (every asset eligible, as before #986) only
30
+ * when state.db cannot be read.
31
+ */
32
+ export function loadRetrievalScope(access, stashDir) {
33
+ const sinceMs = Date.now() - daysToMs(USAGE_EVENT_RETENTION_DAYS);
34
+ const used = new Set();
35
+ const processed = new Set();
36
+ try {
37
+ readLedgerDb(access, (db) => {
38
+ for (const entryRef of listUsedEntryRefs(db, new Date(sinceMs).toISOString())) {
39
+ const conceptId = stripBundle(entryRef);
40
+ used.add(conceptId);
41
+ if (conceptId.endsWith(".derived"))
42
+ used.add(conceptId.slice(0, -".derived".length));
43
+ }
44
+ if (!stashDir)
45
+ return;
46
+ // Blocker 1 (second review round): a pair-pass ledger row must NOT mark
47
+ // an asset "processed" — unlike every other stage, the pair pass judges
48
+ // material against its NEIGHBOURS, not on its own merits, so its own
49
+ // attempt is not usage evidence the fallback lanes (proactive,
50
+ // high-salience) or promotion retries should be starved by. Left in
51
+ // the ledger for the pair pass's OWN eligibility
52
+ // (selectInitiators reads content_hash directly, never this scope).
53
+ // Proposal rows are untouched: a MINTED retire proposal is real
54
+ // evidence something happened to the asset.
55
+ for (const row of listImproveLedgerRows(db, stashDir)) {
56
+ if (row.source === PAIR_PASS_LEDGER_SOURCE)
57
+ continue;
58
+ if (!CAPTURE_SOURCES.has(row.source))
59
+ processed.add(stripBundle(row.ref));
60
+ }
61
+ for (const row of listProposalRefSources(db, stashDir)) {
62
+ if (!CAPTURE_SOURCES.has(row.source))
63
+ processed.add(stripBundle(row.ref));
64
+ }
65
+ });
66
+ }
67
+ catch (error) {
68
+ warn(`[improve] usage history unreadable, so every asset stays eligible: ${error instanceof Error ? error.message : String(error)}`);
69
+ return undefined;
70
+ }
71
+ return { used, processed, sinceMs };
72
+ }
73
+ /**
74
+ * Whether improve may rework `ref` (whose file is `filePath`) under `scope`. An
75
+ * unprocessed asset whose file cannot be read is left to the disk check that
76
+ * follows, which reports it as missing.
77
+ */
78
+ export function isInRetrievalScope(scope, ref, filePath) {
79
+ if (!scope)
80
+ return true;
81
+ const conceptId = stripBundle(ref);
82
+ if (scope.used.has(conceptId))
83
+ return true;
84
+ if (scope.processed.has(conceptId))
85
+ return false;
86
+ try {
87
+ return filePath === undefined || fs.statSync(filePath).mtimeMs >= scope.sinceMs;
88
+ }
89
+ catch {
90
+ return true;
91
+ }
92
+ }
@@ -4,71 +4,25 @@
4
4
  import { getAllEntries } from "../../storage/repositories/index-entries-repository.js";
5
5
  import { getUtilityScoresByIds } from "../../storage/repositories/index-utility-repository.js";
6
6
  import { WARM_START_CAP } from "./outcome-loop.js";
7
- // ── One day in ms ─────────────────────────────────────────────────────────────
8
7
  const DAY_MS = 86_400_000;
9
- // ── Recency decay half-life (mirrors the proactive-maintenance prototype) ─────
10
8
  const RECENCY_HALFLIFE_DAYS = 21;
11
- // ── Recency-floor half-life (R4 — SHY-style continuous downscaling) ──────────
12
- //
13
- // The recency floor itself decays on this (much longer) half-life so an
14
- // unreviewed-forever asset keeps drifting down instead of parking at the 0.1
15
- // floor. This replaces the deleted homeostatic demotion pass (which was
16
- // default-off and self-undoing — every salience recompute clobbered it);
17
- // folding the decay into the always-applied recency term makes it persist by
18
- // construction. At 180 days the floor halves; a 1-year-stale asset sits at
19
- // ~0.025 instead of 0.1.
9
+ /**
10
+ * The recency floor itself halves every 180 days, so an asset nobody uses keeps
11
+ * drifting down instead of parking at the floor.
12
+ */
20
13
  const RECENCY_FLOOR_HALFLIFE_DAYS = 180;
21
- // Absolute epsilon under the decaying floor. Keeps the frequency term ordinal
22
- // for assets whose last-use timestamp is unknown (utility_scores has no
23
- // last_used_at) — without it their retrieval salience collapses to exactly 0
24
- // and frequency ordering is lost for maintenance selection.
14
+ /** Keeps frequency ordinal for assets whose last use is unknown. */
25
15
  const RECENCY_EPSILON = 0.01;
26
- // ── Size proxy floor (avoids log10(0)) ────────────────────────────────────────
27
16
  const SIZE_FLOOR_BYTES = 200;
28
- // ── Projection weights ────────────────────────────────────────────────────────
29
- //
30
- // These constants are the DEFAULT ranking weights (R1 loop closure). Operators
31
- // can opt back out to the WS-1 parity weights (w_e=0.30, w_r=0.70, w_o=0) via
32
- // `improve.salience.outcomeWeightEnabled: false`.
33
- //
34
- // WS-2 split (w_e=0.25, w_o=0.15, w_r=0.60, sum = 1.0):
35
- // [exp] Expert recommendation: encoding should be moderate so a type-importance
36
- // stub does not completely dominate; retrieval should be strong since it directly
37
- // measures use; outcome provides a quality signal proportional to usefulness.
38
- //
39
- // Re-tune via the Part-V measurement protocol if the throughput/quality gate
40
- // shows regression after enabling the outcome weight.
41
- export const W_ENCODING = 0.25; // WS-2 target encoding weight (w_e)
42
- export const W_OUTCOME = 0.15; // WS-2 target outcome weight (w_o)
43
- export const W_RETRIEVAL = 0.6; // WS-2 target retrieval weight (w_r)
44
- // Compile-time guard: weights must sum to 1.0 (±ε). The TS initializer runs
45
- // at module load, not build time, so this acts as a startup assertion.
46
- if (Math.abs(W_ENCODING + W_OUTCOME + W_RETRIEVAL - 1.0) > 1e-9) {
47
- throw new Error(`salience.ts: W_ENCODING + W_OUTCOME + W_RETRIEVAL must equal 1.0 (got ${W_ENCODING + W_OUTCOME + W_RETRIEVAL})`);
48
- }
49
- // ── WS-1 parity weights ───────────────────────────────────────────────────────
50
- //
51
- // These constants reflect the WS-1 parity weights used when the operator
52
- // explicitly opts out (`outcomeWeightEnabled: false`). They preserve the
53
- // WS-1 two-way split (w_e=0.30, w_r=0.70) with w_o=0 so outcome does not
54
- // affect rankScore in the opt-out mode.
55
- //
56
- // Named here (rather than inline literals in the else branch) so a future
57
- // re-tune has a single source of truth and the sum-to-1 guard below catches
58
- // any accidental mis-edit.
59
- export const W_ENCODING_PARITY = 0.3; // WS-1 parity encoding weight
60
- export const W_OUTCOME_PARITY = 0; // WS-1 parity outcome weight (0 = disabled)
61
- export const W_RETRIEVAL_PARITY = 0.7; // WS-1 parity retrieval weight
62
- // Startup guard: parity triple must also sum to 1.0 (±ε).
63
- if (Math.abs(W_ENCODING_PARITY + W_OUTCOME_PARITY + W_RETRIEVAL_PARITY - 1.0) > 1e-9) {
64
- throw new Error(`salience.ts: W_ENCODING_PARITY + W_OUTCOME_PARITY + W_RETRIEVAL_PARITY must equal 1.0 (got ${W_ENCODING_PARITY + W_OUTCOME_PARITY + W_RETRIEVAL_PARITY})`);
65
- }
66
- // ── Type-importance fallback weights (#608 landed) ────────────────────────────
67
- //
68
- // The real encoding salience estimator is `scoreEncodingSalience` in
69
- // `encoding-salience.ts` (#608). These weights are the fallback used when
70
- // `SalienceInputs.encodingSalience` is absent (pre-#608 assets without a
71
- // frontmatter `salience:` field or a state.db row seeded by distill).
17
+ /** Default weights: the outcome term is on (opt out with `improve.salience.outcomeWeightEnabled: false`). */
18
+ export const W_ENCODING = 0.25;
19
+ export const W_OUTCOME = 0.15;
20
+ export const W_RETRIEVAL = 0.6;
21
+ /** Weights with the outcome term off. */
22
+ export const W_ENCODING_PARITY = 0.3;
23
+ export const W_OUTCOME_PARITY = 0;
24
+ export const W_RETRIEVAL_PARITY = 0.7;
25
+ /** Encoding salience by type, for assets with no content-derived score yet. */
72
26
  export const DEFAULT_TYPE_ENCODING_WEIGHTS = Object.freeze({
73
27
  skill: 0.9,
74
28
  agent: 0.9,
@@ -79,218 +33,65 @@ export const DEFAULT_TYPE_ENCODING_WEIGHTS = Object.freeze({
79
33
  script: 0.6,
80
34
  memory: 0.5,
81
35
  });
82
- /** Default encoding salience for types not in the table above. */
83
36
  export const DEFAULT_ENCODING_SALIENCE = 0.5;
84
- // ── Core computation ─────────────────────────────────────────────────────────
85
- /**
86
- * Compute the salience vector for one asset.
87
- *
88
- * Pure function — no I/O. All inputs are pre-fetched by the caller.
89
- */
37
+ const clamp01 = (value) => Math.min(1, Math.max(0, value));
38
+ /** The salience vector for one asset (pure). */
90
39
  export function computeSalience(inputs) {
91
40
  const now = inputs.now ?? Date.now();
92
- // ── Encoding salience ────────────────────────────────────────────────────────
93
- //
94
- // When `inputs.encodingSalience` is provided (computed by `scoreEncodingSalience`
95
- // in encoding-salience.ts at extract/distill time, #608), use it directly.
96
- // Fall back to the type-importance stub only when the caller has not yet
97
- // computed a content-based score (e.g. on older assets before the first
98
- // staleness refresh runs).
99
41
  const encodingSource = inputs.encodingSalience !== undefined ? "content" : "type-stub";
100
42
  const encoding = inputs.encodingSalience !== undefined
101
- ? Math.min(1, Math.max(0, inputs.encodingSalience))
43
+ ? clamp01(inputs.encodingSalience)
102
44
  : (DEFAULT_TYPE_ENCODING_WEIGHTS[inputs.type] ?? DEFAULT_ENCODING_SALIENCE);
103
- // ── Outcome salience (WS-2 active) ────────────────────────────────────────
104
- //
105
- // When `inputs.outcomeSalience` is provided (WS-2 has populated asset_outcome
106
- // for this ref), use it directly — it has already been normalised by
107
- // `outcomeScoreToSalience` in outcome-loop.ts (value in [DIVERSITY_FLOOR, 1]).
108
- //
109
- // When absent (new asset, no WS-2 row yet): fall back to the warm-start seed
110
- // from `utilityScore` clipped to [0, WARM_START_CAP], matching the seed
111
- // value that `updateAssetOutcome` writes on first row creation. This ensures
112
- // `outcomeSalience` is non-zero at launch for assets with utility history
113
- // (avoiding the starvation problem described in the plan §WS-2 warm start).
114
- let outcome;
115
- if (inputs.outcomeSalience !== undefined) {
116
- // Direct pass-through — caller already normalised via outcomeScoreToSalience.
117
- outcome = Math.min(1, Math.max(0, inputs.outcomeSalience));
118
- }
119
- else {
120
- // Warm-start fallback: clip utility to [0, WARM_START_CAP] so the
121
- // outcomeSalience term contributes a modest non-zero baseline.
122
- outcome = Math.min(WARM_START_CAP, Math.max(0, inputs.utilityScore ?? 0));
123
- }
124
- // ── Retrieval salience ─────────────────────────────────────────────────────
125
- //
126
- // Formula: log(1 + freq) × recencyDecay
127
- // log(1+freq): sub-linear frequency term (same as proactive-maintenance prototype).
128
- // recencyDecay: max(ε, 0.1·0.5^(useAgeDays/180) + 0.5^(useAgeDays/21)) —
129
- // the fast term halves every 21 days; the 0.1 floor itself halves every
130
- // 180 days (R4: SHY-style continuous downscaling — an unreviewed-forever
131
- // asset keeps drifting down instead of parking at the floor). The ε=0.01
132
- // epsilon keeps the frequency term ordinal for unknown-last-use assets.
133
- // lastUseMs=0/undefined → useAgeDays=9999 → recencyDecay=ε.
134
- //
135
- // The recency term is MANDATORY (plan requirement §WS-1 step 2). Without it
136
- // retrievalSalience degenerates to a non-decaying frequency count. This
137
- // always-applied decay replaces the deleted homeostatic demotion pass.
45
+ // Without an outcome row, utility (capped) seeds the outcome term — the same
46
+ // seed the first outcome row gets — so it is not zero at launch.
47
+ const outcome = inputs.outcomeSalience !== undefined
48
+ ? clamp01(inputs.outcomeSalience)
49
+ : Math.min(WARM_START_CAP, Math.max(0, inputs.utilityScore ?? 0));
50
+ // log(1 + freq) × recency, where recency halves every 21 days above a floor
51
+ // that itself halves every 180 days; soft-capped to [0, 1).
138
52
  const lastUseMs = inputs.lastUseMs ?? 0;
139
53
  const useAgeDays = lastUseMs > 0 ? (now - lastUseMs) / DAY_MS : 9999;
140
54
  const recencyDecay = Math.max(RECENCY_EPSILON, 0.1 * 0.5 ** (useAgeDays / RECENCY_FLOOR_HALFLIFE_DAYS) + 0.5 ** (useAgeDays / RECENCY_HALFLIFE_DAYS));
141
55
  const rawRetrieval = Math.log(1 + inputs.retrievalFreq) * recencyDecay;
142
- // ── Size penalty ─────────────────────────────────────────────────────────────
143
- // 1/log10(size): larger assets are slightly deprioritized (same as proactive prototype).
144
- const sizeProxy = Math.max(SIZE_FLOOR_BYTES, inputs.sizeBytes ?? 0);
145
- const sizePenalty = 1 / Math.log10(sizeProxy);
146
- // ── Projection → rankScore ────────────────────────────────────────────────
147
- //
148
- // Raw projection may be > 1 (log retrieval terms can exceed 1 for high freq + fresh use).
149
- // Normalize by the theoretical maximum of the retrieval component:
150
- // max retrievalRaw = log(1 + Infinity) × (0.1 + 1.0) = Infinity, so we
151
- // cap instead — rankScore is clamped to [0,1] after applying the size penalty.
152
- //
153
- // Normalization approach: we scale the combined linear sum to [0,1] by clamping,
154
- // after applying the size penalty. The encoding term is already in [0,1]; the
155
- // retrieval term is open-ended but bounded in practice by log(1+N)×1.1 where N
156
- // is the retrieval count. We normalize `retrieval` to [0,1] using a soft cap:
157
- // retrieval_normalized = rawRetrieval / (rawRetrieval + 1)
158
- // which asymptotes to 1 and equals 0.5 at rawRetrieval=1. This is the same
159
- // formula used for MemRL utility updates.
160
56
  const retrieval = rawRetrieval / (rawRetrieval + 1);
161
- // ── Weight selection (R1 — outcome loop closed by default) ───────────────
162
- //
163
- // When `outcomeWeightEnabled` is true/absent (DEFAULT ON since the G2
164
- // saturation cap landed): use WS-2 weights (w_e=0.25, w_o=0.15, w_r=0.60)
165
- // so the prediction-error outcome signal actually shapes rankScore — this
166
- // is the R1 loop-closure.
167
- //
168
- // When `outcomeWeightEnabled` is explicitly false (operator opt-out via
169
- // `improve.salience.outcomeWeightEnabled: false`): fall back to the WS-1
170
- // parity weights (w_e=0.30, w_r=0.70, w_o=0). The `outcome` sub-score is
171
- // still computed and stored for observability in that mode.
172
- let we;
173
- let wo;
174
- let wr;
175
- if (inputs.outcomeWeightEnabled !== false) {
176
- // WS-2 active (default): three-way split.
177
- we = W_ENCODING; // 0.25
178
- wo = W_OUTCOME; // 0.15
179
- wr = W_RETRIEVAL; // 0.60
180
- }
181
- else {
182
- // WS-1 parity (opt-out): w_o=0, redistribute to WS-1 proportions.
183
- // Original WS-1 split was w_e=0.30, w_r=0.70.
184
- we = W_ENCODING_PARITY;
185
- wo = W_OUTCOME_PARITY;
186
- wr = W_RETRIEVAL_PARITY;
187
- }
188
- const rawRankScore = (we * encoding + wo * outcome + wr * retrieval) * sizePenalty;
189
- const rankScore = Math.min(1, Math.max(0, rawRankScore));
57
+ // Larger assets rank slightly lower.
58
+ const sizePenalty = 1 / Math.log10(Math.max(SIZE_FLOOR_BYTES, inputs.sizeBytes ?? 0));
59
+ const [we, wo, wr] = inputs.outcomeWeightEnabled !== false
60
+ ? [W_ENCODING, W_OUTCOME, W_RETRIEVAL]
61
+ : [W_ENCODING_PARITY, W_OUTCOME_PARITY, W_RETRIEVAL_PARITY];
62
+ const rankScore = clamp01((we * encoding + wo * outcome + wr * retrieval) * sizePenalty);
190
63
  return { encoding, outcome, retrieval, rankScore, encodingSource };
191
64
  }
192
- // ── state.db persistence ─────────────────────────────────────────────────────
193
- //
194
- // The three sub-scores live in state.db::asset_salience. Raw SQL now lives in
195
- // storage/repositories/salience-repository.ts (#672 part 2) — extracted
196
- // verbatim, only relocated behind the repository boundary. Re-exported here so
197
- // existing importers of this module resolve unchanged. Migrations live in
198
- // state-db.ts (migration 009).
199
- export { getAllRankScores, getAssetSalience, getConsecutiveNoOps, recordNoOp, resetConsecutiveNoOps, upsertAssetSalience, } from "../../storage/repositories/salience-repository.js";
200
- /**
201
- * Does this row carry a genuine content-derived `encoding_salience` (#644)?
202
- *
203
- * Unknown provenance is not treated as content-derived.
204
- */
65
+ export { getAssetSalience, getConsecutiveNoOps, recordNoOp, resetConsecutiveNoOps, upsertAssetSalience, } from "../../storage/repositories/salience-repository.js";
66
+ /** Whether a stored row's encoding salience is content-derived (unknown provenance is not). */
205
67
  export function isContentEncodingRow(row) {
206
68
  return row.encoding_source === "content";
207
69
  }
208
- // ── Consolidation-selection dampener constants ────────────────────────────────
209
- //
210
- // Assets with consecutive_no_ops >= THRESHOLD are deprioritised in the
211
- // SELECTION ORDER only. The persisted rank_score is intentionally left
212
- // unchanged so stable assets remain fully retrievable by other callers.
213
- //
214
- // Tuning guidance:
215
- // THRESHOLD — how many consecutive no-op runs before dampening kicks in.
216
- // 3 means "skipped three times in a row", which signals the
217
- // LLM consistently has nothing to say about this asset.
218
- // FACTOR — multiplicative penalty on the effective selection score.
219
- // 0.5 halves the apparent score so a dampened asset sorts
220
- // after any peer with >= half its rankScore.
221
- export const SALIENCE_NO_OP_DAMPEN_THRESHOLD = 3;
222
- export const SALIENCE_NO_OP_DAMPEN_FACTOR = 0.5;
223
- /**
224
- * Emit the forgetting-safety rank-change distribution report.
225
- *
226
- * Compares the provided `newRanks` (Map<ref, position (1-indexed)>) against
227
- * the provided `oldRanks` and flags refs that were in the old top-200 but
228
- * are now below position 500 as "forgetting candidates".
229
- *
230
- * Caller is responsible for computing old/new rank positions before and after
231
- * the WS-1 formula cutover. Called once at cutover, not every run.
232
- *
233
- * @param oldRanks - Map<ref, 1-indexed rank position> under the OLD formula.
234
- * @param newRanks - Map<ref, 1-indexed rank position> under the NEW formula.
235
- * @param oldTopN - Assets in old top-N to guard (default: 200).
236
- * @param forgettingThreshold - New rank position below which a fall is flagged (default: 500).
237
- */
238
- export function buildRankChangeReport(oldRanks, newRanks, oldTopN = 200, forgettingThreshold = 500) {
239
- const allChanges = [];
240
- const forgettingCandidates = [];
241
- for (const [ref, oldRank] of oldRanks) {
242
- const newRank = newRanks.get(ref);
243
- if (newRank === undefined)
244
- continue; // ref not in new ranking
245
- const rankDelta = newRank - oldRank; // positive = fell in rank
246
- allChanges.push({ ref, oldRank, newRank, rankDelta });
247
- if (oldRank <= oldTopN && newRank > forgettingThreshold) {
248
- forgettingCandidates.push({ ref, oldRank, newRank, rankDelta });
249
- }
250
- }
251
- // Sort by magnitude of rank drop (most dramatic first).
252
- forgettingCandidates.sort((a, b) => b.rankDelta - a.rankDelta);
253
- return { forgettingCandidates, allChanges };
254
- }
255
- // ── Last-use timestamp lookup helper ─────────────────────────────────────────
256
- //
257
- // Wraps the index DB query to retrieve the last-retrieval timestamp per ref,
258
- // so callers do not need to import the raw db helpers directly. Returns a Map
259
- // keyed by the same ref strings passed in.
260
- //
261
- // Source: `utility_scores.last_used_at` (ISO-8601 string) joined to entries
262
- // via entry_id. WS-2 may later supersede this with `asset_outcome.last_retrieved_at`.
263
70
  /**
264
- * Build a Map<ref, lastUseMs> from the index database's utility_scores table.
265
- *
266
- * Returns only refs that have a non-null `last_used_at`. Refs absent from the
267
- * map should be treated as never retrieved (lastUseMs = 0).
268
- *
269
- * @param indexDb - An open read-capable index database connection.
270
- * @param candidates - Planned refs carrying their canonical durable item_ref.
71
+ * Consolidation selection only: an asset whose last three runs were no-ops
72
+ * sorts at half its score. The stored rank is untouched.
271
73
  */
74
+ export const SALIENCE_NO_OP_DAMPEN_THRESHOLD = 3;
75
+ export const SALIENCE_NO_OP_DAMPEN_FACTOR = 0.5;
76
+ /** `ref → last retrieval (ms)` from the index's utility scores; absent means never retrieved. */
272
77
  export function getLastUseMsByRef(indexDb, candidates) {
273
78
  const result = new Map();
274
79
  if (candidates.length === 0)
275
80
  return result;
276
81
  const refByItemRef = new Map(candidates.flatMap((candidate) => (candidate.itemRef ? [[candidate.itemRef, candidate.ref]] : [])));
277
- const allEntries = getAllEntries(indexDb);
278
82
  const idToRef = new Map();
279
- for (const indexed of allEntries) {
83
+ for (const indexed of getAllEntries(indexDb)) {
280
84
  const ref = refByItemRef.get(indexed.itemRef);
281
85
  if (ref)
282
86
  idToRef.set(indexed.id, ref);
283
87
  }
284
- const ids = [...idToRef.keys()];
285
- if (ids.length === 0)
88
+ if (idToRef.size === 0)
286
89
  return result;
287
- const { global: scores } = getUtilityScoresByIds(indexDb, ids);
90
+ const scores = getUtilityScoresByIds(indexDb, [...idToRef.keys()]);
288
91
  for (const [id, row] of scores) {
289
92
  const ref = idToRef.get(id);
290
- if (!ref)
291
- continue;
292
93
  const lastUsedAt = row.lastUsedAt;
293
- if (!lastUsedAt)
94
+ if (!ref || !lastUsedAt)
294
95
  continue;
295
96
  const ms = typeof lastUsedAt === "number" ? lastUsedAt : Date.parse(lastUsedAt);
296
97
  if (ms > 0)