akm-cli 0.9.0-rc.1 → 0.9.0-rc.13

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 (587) hide show
  1. package/CHANGELOG.md +1190 -52
  2. package/README.md +62 -37
  3. package/SECURITY.md +46 -31
  4. package/dist/akm +162 -38
  5. package/dist/akm-migrate +44 -0
  6. package/dist/assets/backends/schtasks-template.xml +2 -1
  7. package/dist/assets/hints/cli-hints-full.md +268 -118
  8. package/dist/assets/hints/cli-hints-short.md +87 -24
  9. package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
  10. package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
  11. package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
  12. package/dist/assets/improve-strategies/frequent.json +15 -0
  13. package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
  14. package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
  15. package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
  16. package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
  17. package/dist/assets/improve-strategies/reflect-distill.json +30 -0
  18. package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
  19. package/dist/assets/prompts/consolidate-system.md +5 -5
  20. package/dist/assets/prompts/extract-session.md +2 -6
  21. package/dist/assets/prompts/memory-infer-user.md +2 -3
  22. package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
  23. package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
  24. package/dist/assets/prompts/reflect-output-repair.md +3 -0
  25. package/dist/assets/stash-skeleton/README.md +38 -10
  26. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
  27. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
  28. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
  29. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
  30. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
  38. package/dist/assets/tasks/core/extract.yml +3 -2
  39. package/dist/assets/tasks/core/improve.yml +2 -1
  40. package/dist/assets/tasks/core/index-refresh.yml +1 -0
  41. package/dist/assets/tasks/core/sync.yml +1 -0
  42. package/dist/assets/tasks/core/version-check.yml +2 -1
  43. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  44. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  45. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  46. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  47. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  48. package/dist/assets/templates/html/health.html +5 -4
  49. package/dist/assets/workflows/workflow-template.md +31 -15
  50. package/dist/cli/invocation.js +279 -0
  51. package/dist/cli/parse-args.js +5 -90
  52. package/dist/cli/retired-commands.js +78 -0
  53. package/dist/cli/shared.js +158 -48
  54. package/dist/cli-node.mjs +2 -1
  55. package/dist/cli.js +747 -293
  56. package/dist/commands/agent/agent-dispatch.js +19 -18
  57. package/dist/commands/agent/agent-support.js +0 -24
  58. package/dist/commands/agent/contribute-cli.js +43 -97
  59. package/dist/commands/completions.js +80 -23
  60. package/dist/commands/config-cli.js +44 -281
  61. package/dist/commands/env/env-binding.js +13 -9
  62. package/dist/commands/env/env-cli.js +76 -159
  63. package/dist/commands/env/env.js +12 -163
  64. package/dist/commands/env/marker-path.js +6 -0
  65. package/dist/commands/env/secret-cli.js +45 -61
  66. package/dist/commands/env/secret.js +32 -62
  67. package/dist/commands/feedback-cli.js +179 -85
  68. package/dist/commands/health/accept-rate.js +58 -0
  69. package/dist/commands/health/advisories.js +7 -8
  70. package/dist/commands/health/checks.js +279 -94
  71. package/dist/commands/health/html-report.js +197 -578
  72. package/dist/commands/health/improve-metrics.js +277 -246
  73. package/dist/commands/health/llm-usage.js +19 -19
  74. package/dist/commands/health/md-report.js +16 -7
  75. package/dist/commands/health/metrics.js +67 -32
  76. package/dist/commands/health/renderers.js +47 -0
  77. package/dist/commands/health/report-view-model.js +508 -0
  78. package/dist/commands/health/stash-exposure.js +1 -1
  79. package/dist/commands/health/surfaces.js +16 -56
  80. package/dist/commands/health/task-runs.js +3 -67
  81. package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
  82. package/dist/commands/health/types-improve.js +29 -0
  83. package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
  84. package/dist/commands/health/types-result.js +7 -0
  85. package/dist/commands/health/types-runs.js +4 -0
  86. package/dist/commands/health/types-session-log.js +4 -0
  87. package/dist/commands/health/types-windows.js +4 -0
  88. package/dist/commands/health/types.js +26 -21
  89. package/dist/commands/health/windows.js +2 -3
  90. package/dist/commands/health.js +296 -167
  91. package/dist/commands/improve/anti-collapse.js +5 -5
  92. package/dist/commands/improve/autonomy-gate.js +68 -0
  93. package/dist/commands/improve/collapse-detector.js +65 -52
  94. package/dist/commands/improve/consolidate/chunking.js +9 -7
  95. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  96. package/dist/commands/improve/consolidate/merge.js +4 -0
  97. package/dist/commands/improve/consolidate.js +454 -1354
  98. package/dist/commands/improve/content-hash.js +39 -0
  99. package/dist/commands/improve/distill/content-repair.js +4 -10
  100. package/dist/commands/improve/distill/promote-memory.js +89 -64
  101. package/dist/commands/improve/distill/quality-gate.js +118 -42
  102. package/dist/commands/improve/distill-guards.js +1 -1
  103. package/dist/commands/improve/distill-promotion-policy.js +33 -888
  104. package/dist/commands/improve/distill.js +607 -363
  105. package/dist/commands/improve/eligibility.js +165 -79
  106. package/dist/commands/improve/extract-cli.js +35 -126
  107. package/dist/commands/improve/extract-prompt.js +6 -35
  108. package/dist/commands/improve/extract.js +640 -391
  109. package/dist/commands/improve/feedback-valence.js +2 -12
  110. package/dist/commands/improve/improve-cli.js +134 -135
  111. package/dist/commands/improve/improve-result-file.js +30 -50
  112. package/dist/commands/improve/improve-run-types.js +4 -0
  113. package/dist/commands/improve/improve-strategies.js +135 -0
  114. package/dist/commands/improve/improve.js +904 -701
  115. package/dist/commands/improve/locks.js +64 -111
  116. package/dist/commands/improve/loop-stages.js +1110 -923
  117. package/dist/commands/improve/memory/derived-ref.js +124 -0
  118. package/dist/commands/improve/memory/memory-belief.js +79 -7
  119. package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
  120. package/dist/commands/improve/memory/memory-improve.js +25 -37
  121. package/dist/commands/improve/outcome-loop.js +25 -88
  122. package/dist/commands/improve/preparation.js +1034 -813
  123. package/dist/commands/improve/proactive-maintenance.js +34 -9
  124. package/dist/commands/improve/proposal-envelope.js +31 -0
  125. package/dist/commands/improve/reflect.js +983 -794
  126. package/dist/commands/improve/run-context.js +119 -0
  127. package/dist/commands/improve/salience.js +24 -127
  128. package/dist/commands/improve/session-asset.js +7 -3
  129. package/dist/commands/improve/shared.js +14 -34
  130. package/dist/commands/improve/source-identity.js +28 -0
  131. package/dist/commands/improve/triage.js +20 -17
  132. package/dist/commands/lint/base-linter.js +340 -313
  133. package/dist/commands/lint/env-key-rules.js +31 -47
  134. package/dist/commands/lint/index.js +185 -30
  135. package/dist/commands/{events.js → log.js} +28 -38
  136. package/dist/commands/migrate-cli.js +54 -0
  137. package/dist/commands/migration-tool.js +55 -0
  138. package/dist/commands/observability-cli.js +70 -208
  139. package/dist/commands/proposal/diff-format.js +50 -0
  140. package/dist/commands/proposal/drain-policies.js +0 -6
  141. package/dist/commands/proposal/drain.js +91 -40
  142. package/dist/commands/proposal/proposal-cli.js +134 -132
  143. package/dist/commands/proposal/proposal-types.js +56 -0
  144. package/dist/commands/proposal/proposal.js +83 -65
  145. package/dist/commands/proposal/propose-cli.js +88 -0
  146. package/dist/commands/proposal/propose.js +105 -88
  147. package/dist/commands/proposal/repository.js +1303 -278
  148. package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
  149. package/dist/commands/proposal/validators/proposal-validators.js +61 -12
  150. package/dist/commands/proposal/validators/proposals.js +6 -8
  151. package/dist/commands/read/curate.js +78 -73
  152. package/dist/commands/read/knowledge.js +510 -13
  153. package/dist/commands/read/registry-search.js +2 -2
  154. package/dist/commands/read/remember-cli.js +84 -15
  155. package/dist/commands/read/search-cli.js +203 -96
  156. package/dist/commands/read/search.js +126 -94
  157. package/dist/commands/read/show.js +226 -250
  158. package/dist/commands/registry-cli.js +34 -60
  159. package/dist/commands/remember.js +18 -57
  160. package/dist/commands/sources/add-cli.js +104 -49
  161. package/dist/commands/sources/bundle-cli.js +166 -0
  162. package/dist/commands/sources/bundle-config-ops.js +63 -0
  163. package/dist/commands/sources/info.js +27 -15
  164. package/dist/commands/sources/init.js +30 -40
  165. package/dist/commands/sources/installed-stashes.js +469 -172
  166. package/dist/commands/sources/schema-repair.js +10 -9
  167. package/dist/commands/sources/self-update.js +182 -121
  168. package/dist/commands/sources/source-add.js +169 -178
  169. package/dist/commands/sources/source-clone.js +144 -41
  170. package/dist/commands/sources/source-manage.js +94 -59
  171. package/dist/commands/sources/sources-cli.js +64 -205
  172. package/dist/commands/sources/stash-cli.js +91 -54
  173. package/dist/commands/sources/stash-skeleton.js +1 -1
  174. package/dist/commands/tasks/tasks-cli.js +106 -104
  175. package/dist/commands/tasks/tasks.js +445 -262
  176. package/dist/commands/workflow-cli.js +75 -228
  177. package/dist/core/action-contributors.js +1 -1
  178. package/dist/core/activation-policy.js +49 -0
  179. package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
  180. package/dist/core/adapter/adapters/akm-adapter.js +528 -0
  181. package/dist/core/adapter/adapters/akm-lint.js +392 -0
  182. package/dist/core/adapter/adapters/akm-metadata.js +387 -0
  183. package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
  184. package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
  185. package/dist/core/adapter/adapters/claude-adapter.js +61 -0
  186. package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
  187. package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
  188. package/dist/core/adapter/adapters/index.js +80 -0
  189. package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
  190. package/dist/core/adapter/adapters/okf-adapter.js +391 -0
  191. package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
  192. package/dist/core/adapter/adapters/shared.js +286 -0
  193. package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
  194. package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
  195. package/dist/core/adapter/bundle-adapter.js +4 -0
  196. package/dist/core/adapter/detect-adapter.js +17 -0
  197. package/dist/core/adapter/recognize-match.js +44 -0
  198. package/dist/core/adapter/registry.js +56 -0
  199. package/dist/core/adapter/types.js +4 -0
  200. package/dist/core/asset/akm-markdown.js +30 -0
  201. package/dist/core/asset/asset-placement.js +243 -0
  202. package/dist/core/asset/asset-ref.js +110 -79
  203. package/dist/core/asset/asset-serialize.js +20 -0
  204. package/dist/core/asset/frontmatter.js +28 -12
  205. package/dist/core/asset/markdown.js +40 -51
  206. package/dist/core/asset/resolve-ref.js +274 -0
  207. package/dist/core/asset/stash-meta.js +2 -2
  208. package/dist/core/bundle-id.js +51 -0
  209. package/dist/core/common.js +281 -86
  210. package/dist/core/config/config-io.js +42 -128
  211. package/dist/core/config/config-schema.js +233 -855
  212. package/dist/core/config/config-sources.js +162 -39
  213. package/dist/core/config/config-types.js +16 -11
  214. package/dist/core/config/config-version.js +29 -0
  215. package/dist/core/config/config-walker.js +126 -37
  216. package/dist/core/config/config.js +154 -331
  217. package/dist/core/config/deep-merge.js +41 -0
  218. package/dist/core/config/engine-semantics.js +28 -0
  219. package/dist/core/config/experimental.js +21 -0
  220. package/dist/core/config/schema/embedding.js +38 -0
  221. package/dist/core/config/schema/engines.js +116 -0
  222. package/dist/core/config/schema/experimental.js +47 -0
  223. package/dist/core/config/schema/feedback.js +31 -0
  224. package/dist/core/config/schema/improve-processes.js +389 -0
  225. package/dist/core/config/schema/improve.js +94 -0
  226. package/dist/core/config/schema/index-config.js +176 -0
  227. package/dist/core/config/schema/output.js +18 -0
  228. package/dist/core/config/schema/primitives.js +94 -0
  229. package/dist/core/config/schema/search.js +30 -0
  230. package/dist/core/config/schema/setup.js +18 -0
  231. package/dist/core/config/schema/sources-bundles.js +169 -0
  232. package/dist/core/config/schema/workflow.js +29 -0
  233. package/dist/core/env-secret-ref.js +155 -20
  234. package/dist/core/errors.js +17 -15
  235. package/dist/core/events-types.js +4 -0
  236. package/dist/core/events.js +46 -128
  237. package/dist/core/extra-params.js +62 -0
  238. package/dist/core/file-change.js +17 -0
  239. package/dist/core/file-lock.js +202 -57
  240. package/dist/core/fs-txn.js +392 -0
  241. package/dist/core/git-message.js +59 -0
  242. package/dist/core/improve-result.js +167 -0
  243. package/dist/core/lesson-lint.js +1 -17
  244. package/dist/core/logs-db.js +1 -1
  245. package/dist/core/maintenance-barrier.js +135 -0
  246. package/dist/core/migration-operation.js +44 -0
  247. package/dist/core/mutation-target.js +78 -0
  248. package/dist/core/paths.js +22 -25
  249. package/dist/core/platform.js +10 -0
  250. package/dist/core/recognition-util.js +128 -0
  251. package/dist/core/redaction.js +392 -0
  252. package/dist/core/standards/resolve-standards-context.js +36 -65
  253. package/dist/core/standards/resolve-stash-standards.js +2 -2
  254. package/dist/core/standards/resolve-type-conventions.js +5 -5
  255. package/dist/core/state/migrations.js +242 -11
  256. package/dist/core/state-db.js +98 -10
  257. package/dist/core/structured.js +1 -1
  258. package/dist/core/subprocess.js +303 -0
  259. package/dist/core/text-truncation.js +9 -5
  260. package/dist/core/time.js +20 -0
  261. package/dist/core/type-presentation.js +130 -0
  262. package/dist/core/warn.js +0 -3
  263. package/dist/core/write-source.js +834 -118
  264. package/dist/indexer/bundle-identity-guard.js +92 -0
  265. package/dist/indexer/db/graph-db.js +1 -25
  266. package/dist/indexer/db/llm-cache.js +1 -1
  267. package/dist/indexer/ensure-index.js +30 -9
  268. package/dist/indexer/graph/graph-boost.js +9 -30
  269. package/dist/indexer/graph/graph-extraction.js +41 -27
  270. package/dist/indexer/graph/graph-types.js +4 -0
  271. package/dist/indexer/index-writer-lock.js +93 -49
  272. package/dist/indexer/index-written-assets.js +100 -53
  273. package/dist/indexer/indexer.js +746 -329
  274. package/dist/indexer/init.js +18 -25
  275. package/dist/indexer/installations.js +142 -0
  276. package/dist/indexer/passes/dir-staleness.js +18 -10
  277. package/dist/indexer/passes/memory-inference.js +25 -15
  278. package/dist/indexer/passes/metadata.js +412 -243
  279. package/dist/indexer/scan/doc-to-entry.js +160 -0
  280. package/dist/indexer/scan/drain-dir.js +134 -0
  281. package/dist/indexer/search/db-search.js +292 -108
  282. package/dist/indexer/search/fts-query.js +64 -0
  283. package/dist/indexer/search/ranking-contributors.js +145 -25
  284. package/dist/indexer/search/ranking-types.js +4 -0
  285. package/dist/indexer/search/ranking.js +28 -71
  286. package/dist/indexer/search/search-attribution.js +67 -0
  287. package/dist/indexer/search/search-fields.js +18 -3
  288. package/dist/indexer/search/search-hit-enrichers.js +30 -40
  289. package/dist/indexer/search/search-source.js +157 -111
  290. package/dist/indexer/search/semantic-status.js +4 -1
  291. package/dist/indexer/usage/usage-events.js +10 -30
  292. package/dist/indexer/walk/file-context.js +3 -45
  293. package/dist/indexer/walk/matchers.js +42 -73
  294. package/dist/indexer/walk/path-resolver.js +11 -5
  295. package/dist/indexer/walk/walker.js +42 -14
  296. package/dist/integrations/agent/builder-shared.js +7 -0
  297. package/dist/integrations/agent/builders.js +5 -58
  298. package/dist/integrations/agent/config.js +3 -143
  299. package/dist/integrations/agent/detect.js +17 -2
  300. package/dist/integrations/agent/engine-resolution.js +231 -0
  301. package/dist/integrations/agent/index.js +1 -2
  302. package/dist/integrations/agent/model-aliases.js +8 -3
  303. package/dist/integrations/agent/profiles.js +6 -99
  304. package/dist/integrations/agent/prompts.js +46 -18
  305. package/dist/integrations/agent/runner-dispatch.js +78 -13
  306. package/dist/integrations/agent/runner.js +76 -208
  307. package/dist/integrations/agent/spawn.js +48 -279
  308. package/dist/integrations/harnesses/aider/agent-builder.js +9 -8
  309. package/dist/integrations/harnesses/aider/index.js +2 -12
  310. package/dist/integrations/harnesses/amazonq/agent-builder.js +10 -16
  311. package/dist/integrations/harnesses/amazonq/index.js +3 -17
  312. package/dist/integrations/harnesses/claude/agent-builder.js +2 -3
  313. package/dist/integrations/harnesses/claude/config-import.js +1 -3
  314. package/dist/integrations/harnesses/claude/index.js +1 -14
  315. package/dist/integrations/harnesses/claude/session-log.js +27 -75
  316. package/dist/integrations/harnesses/codex/agent-builder.js +8 -7
  317. package/dist/integrations/harnesses/codex/index.js +2 -13
  318. package/dist/integrations/harnesses/copilot/agent-builder.js +9 -9
  319. package/dist/integrations/harnesses/copilot/index.js +1 -13
  320. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -9
  321. package/dist/integrations/harnesses/gemini/index.js +1 -13
  322. package/dist/integrations/harnesses/ids.js +24 -0
  323. package/dist/integrations/harnesses/index.js +31 -33
  324. package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
  325. package/dist/integrations/harnesses/opencode/config-import.js +1 -3
  326. package/dist/integrations/harnesses/opencode/index.js +1 -18
  327. package/dist/integrations/harnesses/opencode/session-log.js +67 -125
  328. package/dist/integrations/harnesses/opencode-sdk/harness.js +3 -17
  329. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +274 -191
  330. package/dist/integrations/harnesses/openhands/agent-builder.js +12 -10
  331. package/dist/integrations/harnesses/openhands/index.js +2 -12
  332. package/dist/integrations/harnesses/pi/agent-builder.js +11 -18
  333. package/dist/integrations/harnesses/pi/index.js +3 -16
  334. package/dist/integrations/harnesses/shared.js +17 -0
  335. package/dist/integrations/harnesses/types.js +38 -34
  336. package/dist/integrations/lockfile.js +211 -24
  337. package/dist/integrations/session-logs/index.js +24 -40
  338. package/dist/integrations/session-logs/provider-base.js +113 -0
  339. package/dist/llm/client.js +182 -110
  340. package/dist/llm/embedders/deterministic.js +2 -2
  341. package/dist/llm/embedders/remote.js +21 -9
  342. package/dist/llm/feature-gate.js +17 -57
  343. package/dist/llm/graph-extract.js +12 -13
  344. package/dist/llm/index-passes.js +8 -42
  345. package/dist/llm/memory-infer.js +144 -1
  346. package/dist/llm/metadata-enhance.js +45 -30
  347. package/dist/llm/structured-call.js +16 -8
  348. package/dist/llm/usage-persist.js +30 -5
  349. package/dist/llm/usage-telemetry.js +59 -6
  350. package/dist/output/cli-hints.js +1 -2
  351. package/dist/output/command-registry.js +27 -0
  352. package/dist/output/context.js +22 -7
  353. package/dist/output/format-exempt.js +80 -0
  354. package/dist/output/generic-render.js +251 -0
  355. package/dist/output/html-render.js +11 -16
  356. package/dist/output/render-registry.js +57 -0
  357. package/dist/output/renderers.js +15 -281
  358. package/dist/output/shapes/curate.js +10 -1
  359. package/dist/output/shapes/events.js +12 -7
  360. package/dist/output/shapes/helpers.js +58 -84
  361. package/dist/output/shapes/passthrough.js +8 -40
  362. package/dist/output/shapes/proposal/producer.js +15 -7
  363. package/dist/output/shapes/registry.js +12 -6
  364. package/dist/output/shapes.js +0 -9
  365. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  366. package/dist/output/text/bundle-show.js +7 -0
  367. package/dist/output/text/command-format.js +562 -0
  368. package/dist/output/text/env.js +1 -3
  369. package/dist/output/text/events.js +8 -7
  370. package/dist/output/text/helpers.js +15 -1375
  371. package/dist/output/text/proposal/producer.js +4 -2
  372. package/dist/output/text/proposal-format.js +202 -0
  373. package/dist/output/text/registry-commands.js +1 -2
  374. package/dist/output/text/registry.js +12 -6
  375. package/dist/output/text/show-directives.js +117 -0
  376. package/dist/output/text/show-format.js +103 -0
  377. package/dist/output/text/sync.js +5 -0
  378. package/dist/output/text/workflow-format.js +332 -0
  379. package/dist/output/text/workflow.js +1 -2
  380. package/dist/output/text.js +10 -19
  381. package/dist/registry/factory.js +4 -6
  382. package/dist/registry/origin-resolve.js +16 -27
  383. package/dist/registry/providers/skills-sh.js +3 -3
  384. package/dist/registry/providers/static-index.js +15 -25
  385. package/dist/registry/resolve.js +43 -94
  386. package/dist/registry/semver.js +43 -0
  387. package/dist/runtime.js +81 -12
  388. package/dist/scripts/akm-migrate.js +35529 -0
  389. package/dist/setup/detect.js +5 -7
  390. package/dist/setup/detected-engines.js +136 -0
  391. package/dist/setup/engine-config.js +100 -0
  392. package/dist/setup/registry-stash-loader.js +3 -3
  393. package/dist/setup/semantic-assets.js +12 -9
  394. package/dist/setup/setup.js +444 -208
  395. package/dist/setup/steps/connection-shared.js +120 -0
  396. package/dist/setup/steps/connection.js +108 -305
  397. package/dist/setup/steps/platforms.js +13 -12
  398. package/dist/setup/steps/semantic.js +15 -3
  399. package/dist/setup/steps/sources.js +21 -15
  400. package/dist/setup/steps/stashdir.js +6 -4
  401. package/dist/setup/steps/tasks.js +236 -119
  402. package/dist/setup/steps.js +3 -2
  403. package/dist/sources/freshness.js +39 -0
  404. package/dist/sources/provider-factory.js +11 -17
  405. package/dist/sources/providers/filesystem.js +2 -3
  406. package/dist/sources/providers/git-install.js +278 -34
  407. package/dist/sources/providers/git-provider.js +54 -56
  408. package/dist/sources/providers/git-stash.js +420 -91
  409. package/dist/sources/providers/git.js +2 -2
  410. package/dist/sources/providers/npm.js +16 -19
  411. package/dist/sources/providers/provider-utils.js +47 -22
  412. package/dist/sources/providers/sync-from-ref.js +3 -9
  413. package/dist/sources/providers/website.js +2 -2
  414. package/dist/sources/resolve.js +11 -10
  415. package/dist/sources/snapshot-fetchers/types.js +4 -0
  416. package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
  417. package/dist/storage/database.js +60 -4
  418. package/dist/storage/engines/sqlite-migrations.js +156 -5
  419. package/dist/storage/locations.js +1 -2
  420. package/dist/storage/repositories/canaries-repository.js +1 -1
  421. package/dist/storage/repositories/events-repository.js +51 -11
  422. package/dist/storage/repositories/improve-runs-repository.js +6 -32
  423. package/dist/storage/repositories/index-connection.js +79 -0
  424. package/dist/storage/repositories/index-db.js +4 -3
  425. package/dist/storage/repositories/index-entries-repository.js +863 -0
  426. package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
  427. package/dist/storage/repositories/index-entry-types.js +4 -0
  428. package/dist/storage/repositories/index-fts-repository.js +167 -0
  429. package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
  430. package/dist/storage/repositories/index-meta-repository.js +49 -0
  431. package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
  432. package/dist/storage/repositories/index-sql.js +12 -0
  433. package/dist/storage/repositories/index-utility-repository.js +356 -0
  434. package/dist/storage/repositories/index-vec-repository.js +250 -0
  435. package/dist/storage/repositories/outcome-repository.js +119 -0
  436. package/dist/storage/repositories/proposals-repository.js +317 -75
  437. package/dist/storage/repositories/registry-cache.js +1 -1
  438. package/dist/storage/repositories/salience-repository.js +172 -0
  439. package/dist/storage/repositories/task-history-repository.js +110 -3
  440. package/dist/storage/repositories/workflow-runs-repository.js +68 -35
  441. package/dist/tasks/backends/cron.js +169 -46
  442. package/dist/tasks/backends/exec-utils.js +76 -3
  443. package/dist/tasks/backends/index.js +6 -9
  444. package/dist/tasks/backends/launchd.js +292 -55
  445. package/dist/tasks/backends/schtasks.js +557 -70
  446. package/dist/tasks/backends/types.js +4 -0
  447. package/dist/tasks/command-executable.js +93 -0
  448. package/dist/tasks/embedded.js +56 -38
  449. package/dist/tasks/parser.js +156 -64
  450. package/dist/tasks/resolve-akm-bin.js +144 -51
  451. package/dist/tasks/runner.js +377 -209
  452. package/dist/tasks/schedule.js +108 -19
  453. package/dist/tasks/scheduler-invocation.js +296 -0
  454. package/dist/tasks/schema.js +1 -1
  455. package/dist/tasks/task-id.js +35 -0
  456. package/dist/tasks/validator.js +30 -16
  457. package/dist/workflows/authoring/authoring.js +96 -148
  458. package/dist/workflows/authoring/scope-key.js +1 -1
  459. package/dist/workflows/cli.js +0 -20
  460. package/dist/workflows/concurrency-policy.js +15 -0
  461. package/dist/workflows/exec/brief.js +25 -59
  462. package/dist/workflows/exec/frozen-judge.js +47 -0
  463. package/dist/workflows/exec/native-executor.js +157 -94
  464. package/dist/workflows/exec/report.js +365 -200
  465. package/dist/workflows/exec/run-workflow.js +46 -40
  466. package/dist/workflows/exec/scheduler.js +12 -41
  467. package/dist/workflows/exec/step-work.js +239 -205
  468. package/dist/workflows/exec/workflow-engine-gate.js +67 -0
  469. package/dist/workflows/ir/compile.js +141 -283
  470. package/dist/workflows/ir/freeze.js +233 -0
  471. package/dist/workflows/ir/plan-hash.js +40 -5
  472. package/dist/workflows/ir/schema.js +537 -1
  473. package/dist/workflows/parser.js +878 -306
  474. package/dist/workflows/program/expressions.js +20 -208
  475. package/dist/workflows/program/schema.js +7 -10
  476. package/dist/workflows/renderer.js +99 -121
  477. package/dist/workflows/resource-limits.js +22 -0
  478. package/dist/workflows/runtime/checkin.js +1 -1
  479. package/dist/workflows/runtime/plan-classifier.js +131 -0
  480. package/dist/workflows/runtime/runs.js +200 -113
  481. package/dist/workflows/runtime/unit-checkin.js +1 -1
  482. package/dist/workflows/runtime/unit-phases.js +20 -0
  483. package/dist/workflows/runtime/workflow-asset-loader.js +235 -97
  484. package/dist/workflows/schema.js +1 -11
  485. package/dist/workflows/validate-summary.js +4 -26
  486. package/dist/workflows/validator.js +52 -30
  487. package/docs/README.md +42 -78
  488. package/docs/migration/README.md +8 -0
  489. package/docs/migration/release-notes/0.6.0.md +1 -1
  490. package/docs/migration/release-notes/0.7.0.md +9 -8
  491. package/docs/migration/release-notes/0.9.0.md +158 -14
  492. package/docs/migration/v0.7-to-v0.8.md +46 -47
  493. package/docs/migration/v0.8-to-v0.9.md +844 -0
  494. package/docs/reference/README.md +12 -0
  495. package/docs/reference/data-and-telemetry.md +333 -0
  496. package/package.json +21 -17
  497. package/schemas/akm-asset-envelope.json +93 -0
  498. package/schemas/akm-config.json +4636 -0
  499. package/schemas/akm-task.json +87 -0
  500. package/{dist/schemas → schemas}/akm-workflow.json +127 -82
  501. package/dist/akm-migrate-storage +0 -38
  502. package/dist/assets/help/help-accept.md +0 -12
  503. package/dist/assets/help/help-improve.md +0 -84
  504. package/dist/assets/help/help-proposals.md +0 -17
  505. package/dist/assets/help/help-propose.md +0 -17
  506. package/dist/assets/help/help-reject.md +0 -11
  507. package/dist/assets/profiles/frequent.json +0 -13
  508. package/dist/assets/profiles/recombine-only.json +0 -21
  509. package/dist/assets/profiles/reflect-distill.json +0 -30
  510. package/dist/assets/profiles/synthesize.json +0 -15
  511. package/dist/assets/prompts/procedural-system.md +0 -44
  512. package/dist/assets/prompts/recombine-system.md +0 -40
  513. package/dist/assets/prompts/staleness-detect-system.md +0 -6
  514. package/dist/assets/tasks/core/backup.yml +0 -4
  515. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  516. package/dist/assets/templates/html/default.html +0 -78
  517. package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
  518. package/dist/assets/wiki/index-template.md +0 -12
  519. package/dist/assets/wiki/ingest-workflow-template.md +0 -83
  520. package/dist/assets/wiki/log-template.md +0 -8
  521. package/dist/assets/wiki/schema-template.md +0 -61
  522. package/dist/cli/config-migrate.js +0 -150
  523. package/dist/cli/config-validate.js +0 -39
  524. package/dist/commands/graph/graph-cli.js +0 -124
  525. package/dist/commands/graph/graph.js +0 -487
  526. package/dist/commands/improve/calibration.js +0 -161
  527. package/dist/commands/improve/dedup.js +0 -482
  528. package/dist/commands/improve/extract-watch.js +0 -140
  529. package/dist/commands/improve/hot-probation.js +0 -45
  530. package/dist/commands/improve/improve-auto-accept.js +0 -276
  531. package/dist/commands/improve/improve-profiles.js +0 -168
  532. package/dist/commands/improve/procedural.js +0 -398
  533. package/dist/commands/improve/recombine.js +0 -818
  534. package/dist/commands/improve/schema-similarity-gate.js +0 -168
  535. package/dist/commands/lint/agent-linter.js +0 -44
  536. package/dist/commands/lint/command-linter.js +0 -44
  537. package/dist/commands/lint/default-linter.js +0 -16
  538. package/dist/commands/lint/fact-linter.js +0 -39
  539. package/dist/commands/lint/knowledge-linter.js +0 -16
  540. package/dist/commands/lint/memory-linter.js +0 -61
  541. package/dist/commands/lint/registry.js +0 -41
  542. package/dist/commands/lint/skill-linter.js +0 -45
  543. package/dist/commands/lint/task-linter.js +0 -50
  544. package/dist/commands/lint/workflow-linter.js +0 -81
  545. package/dist/commands/proposal/legacy-import.js +0 -115
  546. package/dist/commands/sources/history.js +0 -196
  547. package/dist/commands/tasks/default-tasks.js +0 -186
  548. package/dist/commands/wiki-cli.js +0 -292
  549. package/dist/core/asset/asset-registry.js +0 -76
  550. package/dist/core/asset/asset-spec.js +0 -316
  551. package/dist/core/config/config-migration.js +0 -602
  552. package/dist/core/deep-merge.js +0 -38
  553. package/dist/core/eval/rank-metrics.js +0 -113
  554. package/dist/core/ripgrep/install.js +0 -163
  555. package/dist/core/ripgrep/resolve.js +0 -81
  556. package/dist/indexer/db/db.js +0 -1414
  557. package/dist/indexer/manifest.js +0 -170
  558. package/dist/indexer/passes/metadata-contributors.js +0 -31
  559. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
  560. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -25
  561. package/dist/llm/call-ai.js +0 -62
  562. package/dist/llm/memory-infer-impl.js +0 -138
  563. package/dist/output/shapes/distill.js +0 -14
  564. package/dist/output/shapes/history.js +0 -11
  565. package/dist/output/text/distill.js +0 -6
  566. package/dist/output/text/enable-disable.js +0 -8
  567. package/dist/output/text/history.js +0 -6
  568. package/dist/output/text/wiki.js +0 -16
  569. package/dist/registry/build-index.js +0 -386
  570. package/dist/schemas/akm-config.json +0 -14225
  571. package/dist/scripts/migrate-storage.js +0 -13169
  572. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -10169
  573. package/dist/scripts/migrations/v16-to-v17.js +0 -141
  574. package/dist/setup/legacy-config.js +0 -106
  575. package/dist/storage/repositories/consolidation-repository.js +0 -38
  576. package/dist/storage/repositories/recombine-repository.js +0 -213
  577. package/dist/wiki/wiki-templates.js +0 -15
  578. package/dist/wiki/wiki.js +0 -1012
  579. package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
  580. package/dist/workflows/db.js +0 -350
  581. package/dist/workflows/exec/watch.js +0 -116
  582. package/dist/workflows/program/parser.js +0 -760
  583. package/dist/workflows/program/project.js +0 -105
  584. package/docs/data-and-telemetry.md +0 -227
  585. package/docs/migration/release-notes/0.9.0-beta.60.md +0 -19
  586. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
  587. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
@@ -0,0 +1,59 @@
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
+ * Leaf util for sanitizing git commit messages.
6
+ *
7
+ * Split out of `core/write-source.ts` so that `sources/providers/git-stash.ts`
8
+ * (which `core/write-source.ts` imports `getCachePaths`/`listGitChangedPaths`/
9
+ * `parseGitRepoUrl`/`saveGitStash` from, via the `sources/providers/git`
10
+ * barrel, by value) does not need to import back into `write-source.ts` just
11
+ * for this helper — that back-edge was a 3-file static-graph cycle
12
+ * (write-source.ts → git.ts → git-stash.ts → write-source.ts; chunk 9 WI-9.8
13
+ * KILL 6 sever). Callers import `sanitizeCommitMessage` directly so
14
+ * the dependency graph stays acyclic.
15
+ */
16
+ /**
17
+ * Maximum length of a sanitized git commit message. Git itself imposes no
18
+ * fixed limit, but message strings come from refs and `--message` flags that
19
+ * can be supplied by users or upstream config. A 4096-char clamp keeps audit
20
+ * trails readable and prevents pathological payloads from bloating the log
21
+ * stream a downstream consumer parses.
22
+ */
23
+ const COMMIT_MESSAGE_MAX_LENGTH = 4096;
24
+ /**
25
+ * Sanitize a string before passing it as `git commit -m <message>`.
26
+ *
27
+ * Defenses, in order:
28
+ * 1. Strip NUL bytes (`\0`) — git rejects them anyway, but we never want
29
+ * them in argv.
30
+ * 2. Replace any CR/LF (`\r`, `\n`) and other ASCII control chars with a
31
+ * single space. This collapses newline-injection attempts that would
32
+ * otherwise turn a single-line commit subject into a forged trailer
33
+ * block.
34
+ * 3. Collapse runs of whitespace into a single space and trim.
35
+ * 4. Clamp to {@link COMMIT_MESSAGE_MAX_LENGTH} characters.
36
+ *
37
+ * If the result is empty after sanitization the caller should substitute a
38
+ * default — this helper returns `""` rather than throwing because not every
39
+ * callsite has a sensible "invalid input" exit code, and "empty" is a
40
+ * recoverable signal.
41
+ */
42
+ export function sanitizeCommitMessage(input) {
43
+ if (typeof input !== "string")
44
+ return "";
45
+ // 1. Strip NULs outright.
46
+ let out = input.replace(/\0/g, "");
47
+ // 2. Replace CR/LF + other C0 control characters (0x00-0x1F, 0x7F) with a
48
+ // space. Tab (0x09) is included intentionally — commit subjects should
49
+ // be a single visual line.
50
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: intentional sanitization
51
+ out = out.replace(/[\x00-\x1F\x7F]/g, " ");
52
+ // 3. Collapse whitespace runs and trim.
53
+ out = out.replace(/\s+/g, " ").trim();
54
+ // 4. Clamp length.
55
+ if (out.length > COMMIT_MESSAGE_MAX_LENGTH) {
56
+ out = out.slice(0, COMMIT_MESSAGE_MAX_LENGTH).trimEnd();
57
+ }
58
+ return out;
59
+ }
@@ -0,0 +1,167 @@
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
+ const COMMON_FIELDS = [
5
+ "schemaVersion",
6
+ "ok",
7
+ "scope",
8
+ "dryRun",
9
+ "skipped",
10
+ "guidance",
11
+ "memorySummary",
12
+ "memoryCleanup",
13
+ "cyclesRun",
14
+ "plannedRefs",
15
+ "actions",
16
+ "distillSkipped",
17
+ "validationFailures",
18
+ "schemaRepairs",
19
+ "consolidation",
20
+ "extract",
21
+ "lintSummary",
22
+ "memoryIndexHealth",
23
+ "coverageGaps",
24
+ "evalCasesWritten",
25
+ "deadUrls",
26
+ "reflectsWithErrorContext",
27
+ "memoryInference",
28
+ "graphExtraction",
29
+ "memoryInferenceDurationMs",
30
+ "graphExtractionDurationMs",
31
+ "orphansPurged",
32
+ "proposalsExpired",
33
+ "reflectCooldownActions",
34
+ "reflectSkippedActions",
35
+ "reflectGuardRejectedActions",
36
+ "gateAutoAcceptedCount",
37
+ "gateAutoAcceptFailedCount",
38
+ "triage",
39
+ "proactiveMaintenance",
40
+ "cycleMetrics",
41
+ "runId",
42
+ "sync",
43
+ "terminated",
44
+ ];
45
+ const V2_FIELDS = new Set([...COMMON_FIELDS, "strategy", "strategyFilteredRefs"]);
46
+ function fail(message) {
47
+ throw new Error(`invalid improve-result envelope: ${message}`);
48
+ }
49
+ function isRecord(value) {
50
+ return typeof value === "object" && value !== null && !Array.isArray(value);
51
+ }
52
+ function requireExactFields(value, allowed) {
53
+ const unknown = Object.keys(value).filter((key) => !allowed.has(key));
54
+ if (unknown.length > 0)
55
+ fail(`unknown field${unknown.length === 1 ? "" : "s"}: ${unknown.sort().join(", ")}`);
56
+ }
57
+ function validateCommon(value) {
58
+ if (typeof value.ok !== "boolean")
59
+ fail("ok must be a boolean");
60
+ if (typeof value.dryRun !== "boolean")
61
+ fail("dryRun must be a boolean");
62
+ if (!Array.isArray(value.plannedRefs))
63
+ fail("plannedRefs must be an array");
64
+ if (!isRecord(value.scope))
65
+ fail("scope must be an object");
66
+ requireExactFields(value.scope, new Set(["mode", "value"]));
67
+ if (value.scope.mode !== "all" && value.scope.mode !== "type" && value.scope.mode !== "ref") {
68
+ fail('scope.mode must be "all", "type", or "ref"');
69
+ }
70
+ if (value.scope.value !== undefined && typeof value.scope.value !== "string") {
71
+ fail("scope.value must be a string when present");
72
+ }
73
+ if (!isRecord(value.memorySummary))
74
+ fail("memorySummary must be an object");
75
+ requireExactFields(value.memorySummary, new Set(["eligible", "derived"]));
76
+ if (typeof value.memorySummary.eligible !== "number" || typeof value.memorySummary.derived !== "number") {
77
+ fail("memorySummary.eligible and memorySummary.derived must be numbers");
78
+ }
79
+ for (const field of [
80
+ "actions",
81
+ "validationFailures",
82
+ "schemaRepairs",
83
+ "extract",
84
+ "coverageGaps",
85
+ "deadUrls",
86
+ ]) {
87
+ if (value[field] !== undefined && !Array.isArray(value[field]))
88
+ fail(`${field} must be an array`);
89
+ }
90
+ for (const field of [
91
+ "cyclesRun",
92
+ "evalCasesWritten",
93
+ "reflectsWithErrorContext",
94
+ "memoryInferenceDurationMs",
95
+ "graphExtractionDurationMs",
96
+ "orphansPurged",
97
+ "proposalsExpired",
98
+ "reflectCooldownActions",
99
+ "reflectSkippedActions",
100
+ "reflectGuardRejectedActions",
101
+ "gateAutoAcceptedCount",
102
+ "gateAutoAcceptFailedCount",
103
+ ]) {
104
+ if (value[field] !== undefined && typeof value[field] !== "number")
105
+ fail(`${field} must be a number`);
106
+ }
107
+ for (const field of ["guidance", "runId"]) {
108
+ if (value[field] !== undefined && typeof value[field] !== "string")
109
+ fail(`${field} must be a string`);
110
+ }
111
+ for (const field of [
112
+ "skipped",
113
+ "memoryCleanup",
114
+ "distillSkipped",
115
+ "consolidation",
116
+ "lintSummary",
117
+ "memoryIndexHealth",
118
+ "memoryInference",
119
+ "graphExtraction",
120
+ "triage",
121
+ "proactiveMaintenance",
122
+ "cycleMetrics",
123
+ "sync",
124
+ "terminated",
125
+ ]) {
126
+ if (value[field] !== undefined && !isRecord(value[field]))
127
+ fail(`${field} must be an object`);
128
+ }
129
+ if (isRecord(value.terminated)) {
130
+ requireExactFields(value.terminated, new Set(["reason", "at", "errorMessage"]));
131
+ if (typeof value.terminated.reason !== "string" || typeof value.terminated.at !== "string") {
132
+ fail("terminated.reason and terminated.at must be strings");
133
+ }
134
+ if (value.terminated.errorMessage !== undefined && typeof value.terminated.errorMessage !== "string") {
135
+ fail("terminated.errorMessage must be a string when present");
136
+ }
137
+ }
138
+ }
139
+ /** Decode the persisted public result contract. */
140
+ export function decodeImproveResult(input) {
141
+ let parsed = input;
142
+ if (typeof input === "string") {
143
+ try {
144
+ parsed = JSON.parse(input);
145
+ }
146
+ catch {
147
+ fail("not valid JSON");
148
+ }
149
+ }
150
+ if (!isRecord(parsed))
151
+ fail("root must be an object");
152
+ if (parsed.schemaVersion === 2) {
153
+ requireExactFields(parsed, V2_FIELDS);
154
+ validateCommon(parsed);
155
+ if (typeof parsed.strategy !== "string" || parsed.strategy.length === 0) {
156
+ fail("strategy must be a non-empty string");
157
+ }
158
+ if (parsed.strategyFilteredRefs !== undefined && !Array.isArray(parsed.strategyFilteredRefs)) {
159
+ fail("strategyFilteredRefs must be an array");
160
+ }
161
+ return {
162
+ envelope: parsed,
163
+ strategy: parsed.strategy,
164
+ };
165
+ }
166
+ fail(`unsupported schemaVersion: ${String(parsed.schemaVersion)}`);
167
+ }
@@ -13,9 +13,7 @@
13
13
  *
14
14
  * Lint produces structured findings rather than throwing so callers can
15
15
  * batch-validate (e.g. `akm proposal accept` over a queue) and surface every
16
- * violation in a single pass. A strict wrapper (`assertLessonValid`) throws
17
- * a `UsageError` for call sites that want a fail-fast contract — most
18
- * notably the proposal-accept path described in v1 spec §13.1.
16
+ * violation in a single pass.
19
17
  *
20
18
  * The lint is intentionally side-effect free and does not import the indexer
21
19
  * or filesystem walker; it operates on a single file path + raw string. This
@@ -24,7 +22,6 @@
24
22
  */
25
23
  import fs from "node:fs";
26
24
  import { parseFrontmatter } from "./asset/frontmatter.js";
27
- import { UsageError } from "./errors.js";
28
25
  function isNonEmptyString(value) {
29
26
  return typeof value === "string" && value.trim().length > 0;
30
27
  }
@@ -74,16 +71,3 @@ export function lintLessonFile(filePath) {
74
71
  const raw = fs.readFileSync(filePath, "utf8");
75
72
  return lintLessonContent(raw, filePath);
76
73
  }
77
- /**
78
- * Strict variant: throws a `UsageError` if any finding is present. The thrown
79
- * error carries the full set of findings on its message and a hint pointing
80
- * at v1 spec §13. The first finding's `field` becomes the error's primary
81
- * field for callers that want to highlight the first violation.
82
- */
83
- export function assertLessonValid(filePath) {
84
- const report = lintLessonFile(filePath);
85
- if (report.findings.length === 0)
86
- return;
87
- const message = report.findings.map((f) => f.message).join("\n");
88
- throw new UsageError(message, "MISSING_REQUIRED_ARGUMENT", "Lessons require non-empty `description` and `when_to_use` frontmatter fields. See v1 spec §13.");
89
- }
@@ -9,7 +9,7 @@
9
9
  * The strategic direction (stop scattering data across files/folders) means
10
10
  * every NEW log consumer queries this database; the per-run text file written
11
11
  * by the task runner is retained only as a transitional tail for humans —
12
- * see docs/technical/logs-audit.md for the full producer audit.
12
+ * per the #579 logs audit of every producer.
13
13
  *
14
14
  * ## Why a separate database from state.db
15
15
  *
@@ -0,0 +1,135 @@
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 { AsyncLocalStorage } from "node:async_hooks";
5
+ import { randomUUID } from "node:crypto";
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ import { ConfigError } from "./errors.js";
9
+ import { createLockPayload, probeLock, reclaimStaleLock, releaseLock, tryAcquireLockSync } from "./file-lock.js";
10
+ import { getMaintenanceBarrierPath } from "./paths.js";
11
+ const heldBarrierContext = new AsyncLocalStorage();
12
+ /**
13
+ * Serialize restore with the short critical section that creates every
14
+ * long-lived AKM lock or workflow lease. The long operation keeps its own
15
+ * lock/lease; this barrier is released immediately after acquisition.
16
+ */
17
+ export function tryAcquireMaintenanceBarrier() {
18
+ const lockPath = getMaintenanceBarrierPath();
19
+ fs.mkdirSync(path.dirname(lockPath), { recursive: true });
20
+ for (let attempt = 0; attempt < 2; attempt += 1) {
21
+ const ownership = tryAcquireLockSync(lockPath, createLockPayload({ purpose: "maintenance-start" }));
22
+ if (ownership) {
23
+ return () => releaseLock(ownership);
24
+ }
25
+ const probe = probeLock(lockPath);
26
+ if (probe.state !== "stale" || !reclaimStaleLock(lockPath, probe))
27
+ return undefined;
28
+ }
29
+ return undefined;
30
+ }
31
+ export function acquireMaintenanceBarrier() {
32
+ const release = tryAcquireMaintenanceBarrier();
33
+ if (release)
34
+ return release;
35
+ throw new ConfigError(`AKM maintenance is in progress (barrier ${getMaintenanceBarrierPath()}); retry after it completes.`, "INVALID_CONFIG_FILE");
36
+ }
37
+ export function withMaintenanceStartBarrier(run) {
38
+ if (heldBarrierContext.getStore()?.active)
39
+ return run();
40
+ const release = acquireMaintenanceBarrier();
41
+ const ownership = { active: true };
42
+ try {
43
+ return heldBarrierContext.run(ownership, run);
44
+ }
45
+ finally {
46
+ ownership.active = false;
47
+ release();
48
+ }
49
+ }
50
+ /** Run while holding the start barrier, or return undefined when it is busy. */
51
+ export function tryWithMaintenanceStartBarrier(run) {
52
+ if (heldBarrierContext.getStore()?.active)
53
+ return run();
54
+ const release = tryAcquireMaintenanceBarrier();
55
+ if (!release)
56
+ return undefined;
57
+ const ownership = { active: true };
58
+ try {
59
+ return heldBarrierContext.run(ownership, run);
60
+ }
61
+ finally {
62
+ ownership.active = false;
63
+ release();
64
+ }
65
+ }
66
+ async function acquireMaintenanceBarrierAsync() {
67
+ const deadline = Date.now() + 5_000;
68
+ while (true) {
69
+ const release = tryAcquireMaintenanceBarrier();
70
+ if (release)
71
+ return release;
72
+ if (Date.now() >= deadline)
73
+ return acquireMaintenanceBarrier();
74
+ await new Promise((resolve) => setTimeout(resolve, 5));
75
+ }
76
+ }
77
+ export async function withMaintenanceStartBarrierAsync(run) {
78
+ if (heldBarrierContext.getStore()?.active)
79
+ return run();
80
+ const release = await acquireMaintenanceBarrierAsync();
81
+ const ownership = { active: true };
82
+ try {
83
+ return await heldBarrierContext.run(ownership, run);
84
+ }
85
+ finally {
86
+ ownership.active = false;
87
+ release();
88
+ }
89
+ }
90
+ function withMaintenanceStartBarrierSyncWait(run) {
91
+ if (heldBarrierContext.getStore()?.active)
92
+ return run();
93
+ const deadline = Date.now() + 5_000;
94
+ let release = tryAcquireMaintenanceBarrier();
95
+ while (!release && Date.now() < deadline) {
96
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 5);
97
+ release = tryAcquireMaintenanceBarrier();
98
+ }
99
+ if (!release)
100
+ release = acquireMaintenanceBarrier();
101
+ const ownership = { active: true };
102
+ try {
103
+ return heldBarrierContext.run(ownership, run);
104
+ }
105
+ finally {
106
+ ownership.active = false;
107
+ release();
108
+ }
109
+ }
110
+ /** Register a long-lived operation atomically with restore's blocker scan. */
111
+ export async function acquireMaintenanceActivity(name) {
112
+ return withMaintenanceStartBarrierAsync(async () => {
113
+ const directory = path.join(path.dirname(getMaintenanceBarrierPath()), "maintenance-activities");
114
+ fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
115
+ const lockPath = path.join(directory, `${name}-${process.pid}-${randomUUID()}.lock`);
116
+ const ownership = tryAcquireLockSync(lockPath, createLockPayload({ purpose: name }));
117
+ if (!ownership) {
118
+ throw new ConfigError(`Could not register AKM maintenance activity at ${lockPath}.`, "INVALID_CONFIG_FILE");
119
+ }
120
+ return () => releaseLock(ownership);
121
+ });
122
+ }
123
+ /** Synchronous activity registration for synchronous database handle lifetimes. */
124
+ export function acquireMaintenanceActivitySync(name) {
125
+ return withMaintenanceStartBarrierSyncWait(() => {
126
+ const directory = path.join(path.dirname(getMaintenanceBarrierPath()), "maintenance-activities");
127
+ fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
128
+ const lockPath = path.join(directory, `${name}-${process.pid}-${randomUUID()}.lock`);
129
+ const ownership = tryAcquireLockSync(lockPath, createLockPayload({ purpose: name }));
130
+ if (!ownership) {
131
+ throw new ConfigError(`Could not register AKM maintenance activity at ${lockPath}.`, "INVALID_CONFIG_FILE");
132
+ }
133
+ return () => releaseLock(ownership);
134
+ });
135
+ }
@@ -0,0 +1,44 @@
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 crypto from "node:crypto";
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+ import { ConfigError } from "./errors.js";
8
+ import { getConfigPath, getDataDir } from "./paths.js";
9
+ let afterPendingCheckHook;
10
+ /** TEST-ONLY: run once after a clear pending-operation check. */
11
+ export function _setAfterPendingOperationCheckHookForTests(hook) {
12
+ afterPendingCheckHook = hook;
13
+ }
14
+ function installationId() {
15
+ return crypto
16
+ .createHash("sha256")
17
+ .update(path.resolve(path.dirname(getConfigPath())))
18
+ .update("\0")
19
+ .update(path.resolve(getDataDir()))
20
+ .digest("hex")
21
+ .slice(0, 24);
22
+ }
23
+ export function getMigrationOperationRoot() {
24
+ return path.join(getDataDir(), "backups", "migrations", installationId());
25
+ }
26
+ export function getMigrationRestoreJournalPath() {
27
+ return path.join(getMigrationOperationRoot(), "restore-active.json");
28
+ }
29
+ export function getMigrationApplyJournalPath() {
30
+ return path.join(getMigrationOperationRoot(), "apply-active.json");
31
+ }
32
+ export function assertNoPendingMigrationOperation() {
33
+ for (const [kind, journalPath] of [
34
+ ["restore", getMigrationRestoreJournalPath()],
35
+ ["migration apply", getMigrationApplyJournalPath()],
36
+ ]) {
37
+ if (fs.existsSync(journalPath)) {
38
+ throw new ConfigError(`AKM ${kind} recovery is pending at ${journalPath}; refusing canonical config/database access until recovery completes.`, "INVALID_CONFIG_FILE");
39
+ }
40
+ }
41
+ const hook = afterPendingCheckHook;
42
+ afterPendingCheckHook = undefined;
43
+ hook?.();
44
+ }
@@ -0,0 +1,78 @@
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 path from "node:path";
5
+ import { deriveInstallations } from "../indexer/installations.js";
6
+ import { resolveSourceEntries } from "../indexer/search/search-source.js";
7
+ import { displayRef } from "./asset/resolve-ref.js";
8
+ import { UsageError } from "./errors.js";
9
+ import { prepareWriteTargetForMutation, resolveWorkingStashTarget, resolveWriteTarget, } from "./write-source.js";
10
+ function canonicalSources(config) {
11
+ const sources = resolveSourceEntries(undefined, config);
12
+ const installations = deriveInstallations(sources);
13
+ return sources.flatMap((source, index) => {
14
+ const bundleId = installations[index]?.id;
15
+ return bundleId ? [{ bundleId, source }] : [];
16
+ });
17
+ }
18
+ function targetForCanonicalSource(config, canonical, options) {
19
+ const target = canonical.source.registryId
20
+ ? resolveWriteTarget(config, canonical.source.registryId, options)
21
+ : resolveWorkingStashTarget(config, options);
22
+ if (path.resolve(target.source.path) !== path.resolve(canonical.source.path)) {
23
+ throw new UsageError(`Bundle "${canonical.bundleId}" no longer resolves to its indexed source root.`);
24
+ }
25
+ return target;
26
+ }
27
+ /** Resolve the canonical bundle id currently assigned to a write target. */
28
+ export function canonicalBundleIdForTarget(config, target) {
29
+ return (canonicalSources(config).find((candidate) => path.resolve(candidate.source.path) === path.resolve(target.source.path))?.bundleId ?? target.source.name);
30
+ }
31
+ /** Resolve a canonical bundle qualifier to its writable target without preparing a Git boundary. */
32
+ export function resolveBundleWriteTarget(config, bundleId, options = {}) {
33
+ const canonical = canonicalSources(config).find((candidate) => candidate.bundleId === bundleId);
34
+ if (!canonical) {
35
+ throw new UsageError(`Bundle "${bundleId}" is not configured.`, "INVALID_FLAG_VALUE");
36
+ }
37
+ const target = targetForCanonicalSource(config, canonical, options);
38
+ return { ...target, source: { ...target.source, name: canonical.bundleId } };
39
+ }
40
+ function resolveExplicitMutationTarget(config, explicitTarget, options) {
41
+ try {
42
+ return resolveWriteTarget(config, explicitTarget, options);
43
+ }
44
+ catch (error) {
45
+ try {
46
+ return resolveBundleWriteTarget(config, explicitTarget, options);
47
+ }
48
+ catch {
49
+ throw error;
50
+ }
51
+ }
52
+ }
53
+ /** Reconcile a qualified mutation ref with `--target`, then resolve the write destination. */
54
+ export function resolveMutationTarget(config, ref, explicitTarget, options = {}) {
55
+ const writeOptions = { requireWritable: options.requireWritable };
56
+ const qualifiedTarget = ref.origin ? resolveBundleWriteTarget(config, ref.origin, writeOptions) : undefined;
57
+ const explicitResolved = explicitTarget
58
+ ? resolveExplicitMutationTarget(config, explicitTarget, writeOptions)
59
+ : undefined;
60
+ if (qualifiedTarget &&
61
+ explicitResolved &&
62
+ path.resolve(qualifiedTarget.source.path) !== path.resolve(explicitResolved.source.path)) {
63
+ throw new UsageError(`Qualified ref bundle "${ref.origin}" conflicts with --target "${explicitTarget}".`, "INVALID_FLAG_VALUE", `Drop --target or select the same bundle.`);
64
+ }
65
+ let target = qualifiedTarget ?? explicitResolved ?? resolveWriteTarget(config, undefined, writeOptions);
66
+ const bundleId = ref.origin ?? canonicalBundleIdForTarget(config, target);
67
+ target = prepareWriteTargetForMutation({ ...target, source: { ...target.source, name: bundleId } }, { allowedAdapters: options.allowedAdapters });
68
+ const stableRef = { ...ref, origin: bundleId };
69
+ const defaultBundle = defaultBundleForTarget(config);
70
+ return {
71
+ target,
72
+ ref: stableRef,
73
+ displayRef: displayRef({ type: stableRef.type, name: stableRef.name, bundleId: stableRef.origin }, defaultBundle),
74
+ };
75
+ }
76
+ export function defaultBundleForTarget(config) {
77
+ return config.defaultBundle;
78
+ }
@@ -10,8 +10,8 @@
10
10
  */
11
11
  import os from "node:os";
12
12
  import path from "node:path";
13
- import { IS_WINDOWS } from "./common.js";
14
13
  import { ConfigError } from "./errors.js";
14
+ import { IS_WINDOWS } from "./platform.js";
15
15
  /**
16
16
  * Returns true when the current process appears to be running under
17
17
  * `bun test` (either via the BUN_TEST sentinel Bun sets on the test
@@ -30,10 +30,10 @@ function isUnderBunTest(env) {
30
30
  * Returns true when the given path is in a directory family the OS may
31
31
  * reap (or that the user has clearly designated as a sandbox by virtue
32
32
  * of placing it under `/tmp` or a macOS per-user temp dir). Used to
33
- * decide whether `AKM_STASH_DIR=$tmpdir` should also isolate config +
33
+ * decide whether `AKM_BUNDLE_DIR=$tmpdir` should also isolate config +
34
34
  * cache writes (so a test harness's `akm setup --yes --dir .` cannot
35
35
  * silently clobber the user's `~/.config/akm/config.json`). See
36
- * `docs/technical/incidents/2026-05-23-setup-clobbers-user-config.md`
36
+ * the 2026-05-23 setup-clobbers-user-config incident
37
37
  * for the incident that motivated this.
38
38
  *
39
39
  * Both `/var/folders/*` and `/private/var/folders/*` are matched because
@@ -67,7 +67,7 @@ export function getConfigDir(env = process.env, platform = process.platform) {
67
67
  return override;
68
68
  // Explicit XDG override wins next — tests and operators that pre-arrange
69
69
  // an isolated config dir via XDG_CONFIG_HOME (or %APPDATA% on Windows)
70
- // must be honored as set, so the AKM_STASH_DIR transient-isolation rule
70
+ // must be honored as set, so the AKM_BUNDLE_DIR transient-isolation rule
71
71
  // below does not silently move config away from where they pointed it.
72
72
  if (platform === "win32") {
73
73
  const appData = env.APPDATA?.trim();
@@ -79,16 +79,16 @@ export function getConfigDir(env = process.env, platform = process.platform) {
79
79
  if (xdgConfigHome)
80
80
  return path.join(xdgConfigHome, "akm");
81
81
  }
82
- // Isolation safety: when AKM_STASH_DIR points at a transient/sandbox path
82
+ // Isolation safety: when AKM_BUNDLE_DIR points at a transient/sandbox path
83
83
  // (/tmp, /var/tmp, /private/var/folders) AND no explicit config dir
84
- // override is set, route config writes into `${AKM_STASH_DIR}/.akm`
84
+ // override is set, route config writes into `${AKM_BUNDLE_DIR}/.akm`
85
85
  // instead of the user's host ~/.config/akm. This prevents the documented
86
86
  // isolation pattern
87
- // AKM_DATA_DIR=/tmp/x AKM_STASH_DIR=/tmp/x akm setup --yes --dir .
87
+ // AKM_DATA_DIR=/tmp/x AKM_BUNDLE_DIR=/tmp/x akm setup --yes --dir .
88
88
  // from silently clobbering the host config. See
89
- // docs/technical/incidents/2026-05-23-setup-clobbers-user-config.md for the incident.
90
- // Daily users with a persistent AKM_STASH_DIR=~/my-stash are unaffected.
91
- const stashOverride = env.AKM_STASH_DIR?.trim();
89
+ // the 2026-05-23 setup-clobbers-user-config incident.
90
+ // Daily users with a persistent AKM_BUNDLE_DIR=~/my-stash are unaffected.
91
+ const stashOverride = env.AKM_BUNDLE_DIR?.trim();
92
92
  if (stashOverride && isTransientStashPath(stashOverride)) {
93
93
  return path.join(stashOverride, ".akm");
94
94
  }
@@ -122,7 +122,7 @@ export function getCacheDir(env = process.env) {
122
122
  // Explicit XDG/platform overrides win before the transient-stash isolation
123
123
  // rule below — tests and operators that pre-arrange XDG_CACHE_HOME (or
124
124
  // %LOCALAPPDATA% / %USERPROFILE% / %APPDATA% on Windows) must be honored
125
- // as set, so the AKM_STASH_DIR transient rule does not silently move cache
125
+ // as set, so the AKM_BUNDLE_DIR transient rule does not silently move cache
126
126
  // writes away from where they pointed them.
127
127
  if (IS_WINDOWS) {
128
128
  const localAppData = env.LOCALAPPDATA?.trim();
@@ -145,12 +145,12 @@ export function getCacheDir(env = process.env) {
145
145
  if (xdgCacheHome)
146
146
  return path.join(xdgCacheHome, "akm");
147
147
  }
148
- // Isolation safety (mirrors getConfigDir): when AKM_STASH_DIR points at a
148
+ // Isolation safety (mirrors getConfigDir): when AKM_BUNDLE_DIR points at a
149
149
  // transient path AND no explicit cache override is set, route cache writes
150
- // into `${AKM_STASH_DIR}/.akm/cache` so that config backups, registry-index
150
+ // into `${AKM_BUNDLE_DIR}/.akm/cache` so that config backups, registry-index
151
151
  // cache, and other regenerable artifacts do not pollute the user's host
152
152
  // ~/.cache/akm directory.
153
- const stashOverride = env.AKM_STASH_DIR?.trim();
153
+ const stashOverride = env.AKM_BUNDLE_DIR?.trim();
154
154
  if (stashOverride && isTransientStashPath(stashOverride)) {
155
155
  return path.join(stashOverride, ".akm", "cache");
156
156
  }
@@ -184,7 +184,7 @@ export function getDataDir(env = process.env, platform = process.platform) {
184
184
  // user's real $XDG_DATA_HOME / ~/.local/share/akm under any condition.
185
185
  // Any test that needs a data dir must point it at a mktemp-d directory
186
186
  // via XDG_DATA_HOME (or AKM_DATA_DIR). The previous carve-out that only
187
- // fired when AKM_STASH_DIR was set was a loophole: tests calling
187
+ // fired when AKM_BUNDLE_DIR was set was a loophole: tests calling
188
188
  // openDatabase() or getDbPath() without overriding any env var silently
189
189
  // wrote into ~/.local/share/akm/index.db (observed: 4,183-row
190
190
  // registry-cache pollution). Item 5 of the 0.8.x critical-review plan.
@@ -218,16 +218,16 @@ export function getDbPath(env = process.env) {
218
218
  export function getIndexWriterLockPath() {
219
219
  return path.join(getDataDir(), "index.db.write.lock");
220
220
  }
221
- export function getWorkflowDbPath() {
222
- return path.join(getDataDir(), "workflow.db");
221
+ export function getMaintenanceBarrierPath() {
222
+ return path.join(getDataDir(), "maintenance.barrier.lock");
223
223
  }
224
224
  /** Path to the state.db file in $DATA. */
225
225
  export function getStateDbPathInDataDir() {
226
226
  return path.join(getDataDir(), "state.db");
227
227
  }
228
- /** Path for the task history directory in $DATA. */
229
- export function getTaskHistoryStateDir() {
230
- return path.join(getDataDir(), "tasks", "history");
228
+ /** Content-addressed scheduler runtime descriptors. */
229
+ export function getTaskContextDir(env = process.env) {
230
+ return path.join(getDataDir(env), "tasks", "context");
231
231
  }
232
232
  /** Path to the akm.lock file in $DATA. */
233
233
  export function getLockfilePath() {
@@ -246,9 +246,6 @@ export function getRegistryCacheDir() {
246
246
  export function getRegistryIndexCacheDir() {
247
247
  return path.join(getCacheDir(), "registry-index");
248
248
  }
249
- export function getBinDir() {
250
- return path.join(getCacheDir(), "bin");
251
- }
252
249
  // ── Scheduled-task runtime directories (logs + history) ──────────────────────
253
250
  export function getTaskLogDir() {
254
251
  return path.join(getCacheDir(), "tasks", "logs");
@@ -258,7 +255,7 @@ export function getTaskHistoryDir() {
258
255
  }
259
256
  // ── Default stash directory ──────────────────────────────────────────────────
260
257
  export function getDefaultStashDir(env = process.env) {
261
- const override = env.AKM_STASH_DIR?.trim();
258
+ const override = env.AKM_BUNDLE_DIR?.trim();
262
259
  if (override)
263
260
  return override;
264
261
  if (IS_WINDOWS) {
@@ -269,7 +266,7 @@ export function getDefaultStashDir(env = process.env) {
269
266
  }
270
267
  const home = env.HOME?.trim();
271
268
  if (!home) {
272
- throw new ConfigError("Unable to determine default stash directory. Set HOME.", "STASH_DIR_NOT_FOUND");
269
+ throw new ConfigError("Unable to determine default bundle directory. Set HOME.", "STASH_DIR_NOT_FOUND");
273
270
  }
274
271
  return path.join(home, "akm");
275
272
  }