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
@@ -3,100 +3,102 @@
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
6
- import { resolveStashDir } from "../../core/common.js";
7
- import { getSources, loadConfig } from "../../core/config/config.js";
6
+ import { isSourceWriteActivated } from "../../core/activation-policy.js";
7
+ import { isWithin, resolveStashDir } from "../../core/common.js";
8
+ import { bundleComponentConfig, bundlesToSourceEntries, getSources, loadConfig } from "../../core/config/config.js";
9
+ import { resolveGitContentRoot, resolveWritable } from "../../core/write-source.js";
10
+ import { lockContentRootFor } from "../../integrations/lockfile.js";
8
11
  import { resolveSourceProviderFactory } from "../../sources/provider-factory.js";
9
12
  // Eager side-effect imports so all built-in source providers self-register
10
13
  // before resolveEntryContentDir() runs.
11
14
  import "../../sources/providers/index.js";
12
15
  import { warn } from "../../core/warn.js";
13
- // Legacy "context-hub" / "github" type aliases are normalized to "git" at
14
- // config-load time (see src/config.ts), so this set only contains the canonical
15
- // type.
16
- const GIT_STASH_TYPES = new Set(["git"]);
17
16
  // ── Resolution ──────────────────────────────────────────────────────────────
18
17
  /**
19
18
  * Build the ordered list of stash sources, walking every configured stash
20
19
  * once. Iteration order:
21
20
  *
22
- * 1. The primary stash directory (the entry marked `primary: true`, or the
23
- * legacy top-level `stashDir`). Always emitted, even when the directory
24
- * does not yet exist on disk, so callers can use it as the clone target.
25
- * 2. Each entry in `config.sources[]` (in declared order), excluding the
26
- * one already emitted as the primary.
27
- * 3. Each entry in `config.installed[]` (registry-managed stashes).
21
+ * 1. An explicit argument or `AKM_BUNDLE_DIR`, when present.
22
+ * 2. The configured `defaultBundle`, after component-root validation.
23
+ * 3. Remaining configured bundles in installation-priority order.
28
24
  *
29
25
  * Replaces the previous four-pass loop that walked `stashes[]` separately
30
- * for each provider kind. Disabled entries (`enabled: false`) and entries
31
- * whose disk path doesn't exist are filtered after deduplication.
26
+ * for each provider kind. Disabled entries (`enabled: false`) are filtered
27
+ * after deduplication. Missing configured roots remain in the result so the
28
+ * indexer can classify their scan as incomplete instead of mistaking them for
29
+ * removed sources.
32
30
  */
33
31
  export function resolveSourceEntries(overrideStashDir, existingConfig) {
34
- const stashDir = overrideStashDir ?? resolveStashDir();
35
32
  const config = existingConfig ?? loadConfig();
36
- // Primary stash is always writable.
37
- const sources = [{ path: stashDir, writable: true }];
38
- const seen = new Set([path.resolve(stashDir)]);
39
- const addSource = (dir, registryId, wikiName, writable) => {
33
+ const configuredEntries = bundlesToSourceEntries(config) ?? [];
34
+ const envOverride = process.env.AKM_BUNDLE_DIR?.trim();
35
+ const implicitStashDir = overrideStashDir !== undefined
36
+ ? path.resolve(overrideStashDir)
37
+ : envOverride
38
+ ? resolveStashDir()
39
+ : config.defaultBundle
40
+ ? undefined
41
+ : resolveStashDir();
42
+ // Explicit and environment overrides stay first. Without either override,
43
+ // the configured default enters through the validated loop below.
44
+ const sources = implicitStashDir ? [{ path: implicitStashDir, writable: true }] : [];
45
+ const seen = new Set(implicitStashDir ? [implicitStashDir] : []);
46
+ const addSource = (dir, registryId, writable, type, adapterId, unresolved = false) => {
40
47
  const resolved = path.resolve(dir);
41
48
  if (seen.has(resolved)) {
42
49
  // Already in the source list — typically the primary stash injected at
43
50
  // sources[0] before this loop. Enrich that entry with whatever metadata
44
- // the matching config source carries so `--source <config-name>` can
51
+ // the matching config source carries so `--from <config-name>` can
45
52
  // find it via registryId. Without this, the primary stash entry stays
46
53
  // identity-less and a user-named primary source ("name": "my-stash")
47
54
  // would validate but match zero entries when filtering.
48
55
  const existing = sources.find((s) => s.path === resolved);
49
- if (existing) {
50
- if (registryId && !existing.registryId)
56
+ if (existing && existing.type === undefined) {
57
+ if (registryId)
51
58
  existing.registryId = registryId;
52
- if (wikiName && !existing.wikiName)
53
- existing.wikiName = wikiName;
54
- if (writable && !existing.writable)
55
- existing.writable = true;
59
+ existing.type = type;
60
+ existing.writable = writable;
61
+ existing.adapterId = adapterId;
56
62
  }
63
+ if (existing && unresolved)
64
+ existing.unresolved = true;
57
65
  return;
58
66
  }
59
67
  seen.add(resolved);
60
68
  if (isSuspiciousStashRoot(dir)) {
61
69
  warn(`Warning: stash root "${dir}" appears to be a system directory. This may be unintentional.`);
62
70
  }
63
- if (isValidDirectory(dir)) {
64
- sources.push({
65
- path: resolved,
66
- ...(registryId ? { registryId } : {}),
67
- ...(wikiName ? { wikiName } : {}),
68
- ...(writable ? { writable: true } : {}),
69
- });
70
- }
71
- };
72
- // (1) + (2) Single pass over declared stashes — primary first if present,
73
- // then the rest in declared order. The primary's directory is already
74
- // injected as `sources[0]` above, so we only need to dedupe the source set.
75
- const stashes = getSources(config);
76
- const primaryIdx = stashes.findIndex((entry) => entry.primary === true);
77
- const ordered = [];
78
- if (primaryIdx >= 0) {
79
- ordered.push(stashes[primaryIdx]);
80
- stashes.forEach((entry, i) => {
81
- if (i !== primaryIdx)
82
- ordered.push(entry);
71
+ sources.push({
72
+ path: resolved,
73
+ ...(registryId ? { registryId } : {}),
74
+ writable,
75
+ type,
76
+ ...(adapterId ? { adapterId } : {}),
77
+ ...(unresolved ? { unresolved: true } : {}),
83
78
  });
84
- }
85
- else {
86
- ordered.push(...stashes);
87
- }
88
- for (const entry of ordered) {
79
+ };
80
+ // 0.9.0 shape (spec §10.1 / D-R5): resolve from `bundles` + `defaultBundle`.
81
+ // `bundlesToSourceEntries` returns the configured default first, then map
82
+ // insertion order. Each entry is validated before insertion so a component
83
+ // root can never escape its provider's materialized content root.
84
+ for (const entry of configuredEntries) {
89
85
  if (entry.enabled === false)
90
86
  continue;
91
- const dir = resolveEntryContentDir(entry);
92
- if (dir == null)
87
+ const component = bundleComponentConfig(config.bundles?.[entry.name ?? ""]);
88
+ const contentRoot = resolveEntryContentDir(entry);
89
+ if (contentRoot == null) {
90
+ const unresolvedPath = path.join(implicitStashDir ?? process.cwd(), ".akm", "unresolved-sources", entry.name ?? entry.type);
91
+ addSource(unresolvedPath, entry.name, component?.writable ?? resolveWritable(entry), entry.type, component?.adapter, true);
93
92
  continue;
94
- addSource(dir, entry.name, entry.wikiName, entry.writable === true);
95
- }
96
- // (3) Installed stashes (registry-managed). Always last.
97
- // Only installed entries explicitly marked writable: true are considered writable.
98
- for (const entry of config.installed ?? []) {
99
- addSource(entry.stashRoot, entry.id, entry.wikiName, entry.writable === true);
93
+ }
94
+ const dir = path.resolve(contentRoot, component?.root ?? ".");
95
+ if (!isWithin(dir, contentRoot)) {
96
+ warn(`Warning: component root "${component?.root}" escapes bundle "${entry.name}"; skipping source.`);
97
+ const unresolvedPath = path.join(contentRoot, ".akm", "unresolved-sources", entry.name ?? entry.type);
98
+ addSource(unresolvedPath, entry.name, component?.writable ?? resolveWritable(entry), entry.type, component?.adapter, true);
99
+ continue;
100
+ }
101
+ addSource(dir, entry.name, component?.writable ?? resolveWritable(entry), entry.type, component?.adapter);
100
102
  }
101
103
  return sources;
102
104
  }
@@ -116,7 +118,19 @@ export function resolveSourceEntries(overrideStashDir, existingConfig) {
116
118
  * That convention is part of the akm content layout, not a provider concern,
117
119
  * so it stays here.
118
120
  */
119
- function resolveEntryContentDir(entry) {
121
+ export function resolveEntryContentDir(entry) {
122
+ // §10.2 (WI-8.5) desired/resolved split: a git/npm bundle's desired config
123
+ // carries only the source LOCATOR, not the materialized cache root — the
124
+ // resolved root lives in the lock (`localRoot`). Resolve from there first via
125
+ // the SHARED lock-first resolver (the same one write-source consults, so reads
126
+ // and writes agree on where content is); the localRoot is the already-walkable
127
+ // content root (installed sources are extracted to their content dir), so no
128
+ // content/-subdir step is applied. Fall back to the provider path logic when no
129
+ // lock entry exists (e.g. a git bundle migrated from a `sources[]` url, whose
130
+ // provider re-derives the mirror path).
131
+ const localRoot = lockContentRootFor(entry.name, entry.type);
132
+ if (localRoot != null)
133
+ return localRoot;
120
134
  const factory = resolveSourceProviderFactory(entry.type);
121
135
  if (!factory)
122
136
  return undefined;
@@ -140,9 +154,8 @@ function resolveEntryContentDir(entry) {
140
154
  // layout puts indexable files under `<repo>/content/`, so the walker needs
141
155
  // that subdirectory. This is a content-layout convention, not a provider
142
156
  // capability — keep it here.
143
- if (GIT_STASH_TYPES.has(entry.type)) {
144
- const contentDir = path.join(dir, "content");
145
- return isValidDirectory(contentDir) ? contentDir : dir;
157
+ if (entry.type === "git") {
158
+ return resolveGitContentRoot(dir);
146
159
  }
147
160
  return dir;
148
161
  }
@@ -154,15 +167,10 @@ export function resolveAllStashDirs(overrideStashDir) {
154
167
  }
155
168
  /**
156
169
  * Return the resolved absolute paths of all writable stash sources.
157
- *
158
- * The primary stash is always writable. Filesystem/git sources that have
159
- * `writable: true` in config are also included. Registry-cached sources
160
- * (installed without `writable: true`) are excluded because they are
161
- * overwritten on `akm update` and must never be mutated.
162
170
  */
163
171
  export function getWritableStashDirs(overrideStashDir, existingConfig) {
164
172
  return resolveSourceEntries(overrideStashDir, existingConfig)
165
- .filter((s) => s.writable === true)
173
+ .filter((s) => isSourceWriteActivated(s))
166
174
  .map((s) => s.path);
167
175
  }
168
176
  /**
@@ -197,45 +205,22 @@ export function getPrimarySource(sources) {
197
205
  }
198
206
  // ── Editability ─────────────────────────────────────────────────────────────
199
207
  /**
200
- * Determine whether a file is safe to edit in place.
201
- *
202
- * The only files that are NOT editable are those inside a cache directory
203
- * managed by the package manager (`installed[].cacheDir`). These
204
- * will be overwritten by `akm update` without warning.
205
- *
206
- * Everything else — working stash, additional stashes, local project dirs — is
207
- * the user's domain to manage.
208
+ * Determine whether AKM policy allows modifying this exact file in place.
209
+ * Ownership is resolved by longest source-root match and unknown ownership
210
+ * fails closed. Resolved sources already carry canonical `resolveWritable()`
211
+ * semantics; editability is never persisted in the index.
208
212
  */
209
- export function isEditable(filePath, config) {
210
- const cfg = config ?? loadConfig();
211
- const resolved = path.resolve(filePath);
212
- const cacheManaged = cfg.installed ?? [];
213
- const isWin = process.platform === "win32";
214
- for (const entry of cacheManaged) {
215
- // Local sources reference original paths — always editable
216
- if (entry.source === "local")
217
- continue;
218
- const cacheRoot = path.resolve(entry.cacheDir);
219
- if (isWin) {
220
- // Windows paths are case-insensitive — normalize both sides
221
- if (resolved.toLowerCase().startsWith(cacheRoot.toLowerCase() + path.sep))
222
- return false;
223
- }
224
- else {
225
- if (resolved.startsWith(cacheRoot + path.sep))
226
- return false;
227
- }
228
- }
229
- return true;
213
+ export function isEditable(filePath, config, sources) {
214
+ const resolvedSources = sources ?? resolveSourceEntries(undefined, config ?? loadConfig());
215
+ return findSourceForPath(filePath, resolvedSources)?.writable === true;
230
216
  }
231
217
  /**
232
218
  * Build an actionable hint for the agent when a file is not editable.
233
219
  * Callers must check `isEditable()` before calling — this function
234
220
  * unconditionally returns the hint string.
235
221
  */
236
- export function buildEditHint(_filePath, assetType, assetName, origin) {
237
- const ref = origin ? `${origin}//${assetType}:${assetName}` : `${assetType}:${assetName}`;
238
- return `This asset is managed by akm and may be overwritten on update. To edit, run: akm clone ${ref}`;
222
+ export function buildEditHint(ref) {
223
+ return `This asset is read-only under current AKM source policy. To make an editable copy, run: akm clone ${ref}`;
239
224
  }
240
225
  // ── Validation ──────────────────────────────────────────────────────────────
241
226
  const SUSPICIOUS_ROOTS = new Set(["/", "/etc", "/bin", "/sbin", "/usr", "/var", "/tmp", "/dev", "/proc", "/sys"]);
@@ -252,33 +237,53 @@ function isSuspiciousStashRoot(dir) {
252
237
  }
253
238
  return false;
254
239
  }
255
- // ── Helpers ─────────────────────────────────────────────────────────────────
256
- function isValidDirectory(dir) {
257
- try {
258
- return fs.statSync(dir).isDirectory();
259
- }
260
- catch {
261
- return false;
262
- }
263
- }
264
240
  // ── Stash cache integration ─────────────────────────────────────────────────
265
241
  /**
266
242
  * Ensure all cache-backed stash providers are refreshed so their cache
267
243
  * directories exist on disk. Must be called (async) before
268
244
  * `resolveSourceEntries()` so the content directories pass the
269
245
  * `isValidDirectory()` check.
246
+ *
247
+ * `materialize` (default `true`) is the query-time safety valve (spec §14.3 /
248
+ * D11): the sanctioned materialization callers (`akm index`, source
249
+ * add/update/sync, improve's blocking preflight) pass it truthy and clone/pull/
250
+ * fetch as needed. A READ command's inline auto-index passes `materialize:
251
+ * false` — network is FORBIDDEN at query time, so instead of `sync()` we only
252
+ * check whether each cache-backed source is already materialized: a present
253
+ * cache is served as-is (last-known-good; no TTL pull either), while an absent
254
+ * or partially-staged cache makes that source UNAVAILABLE for the read and is
255
+ * skipped with one warning naming the remedy. The rest of the command still
256
+ * resolves.
270
257
  */
271
258
  export async function ensureSourceCaches(config, options) {
272
259
  const cfg = config ?? loadConfig();
273
260
  const force = options?.force === true;
261
+ const materialize = options?.materialize !== false;
274
262
  // Polymorphic refresh: walk every enabled source through its registered
275
263
  // provider and call `sync()`. Every cache-backed kind (git, website, npm)
276
264
  // refreshes the same way — a bad source warns and is skipped without
277
265
  // aborting the others. The git content/-subdir layout convention stays in
278
- // resolveEntryContentDir.
266
+ // resolveEntryContentDir. NEW shape reads `bundles`; old shape reads sources[].
267
+ //
268
+ // DISTINCTION (deliberately NOT lock-first): refresh derives the PROVIDER's
269
+ // own cache path to git-pull/re-materialize INTO — that derived path is where
270
+ // content ENDS UP; the lock's `localRoot` merely records the result. So this
271
+ // path correctly uses the provider, not the shared `lockContentRootFor`
272
+ // resolver that reads/writes use to agree on where content already IS.
279
273
  for (const entry of getSources(cfg)) {
280
274
  if (entry.enabled === false)
281
275
  continue;
276
+ const lockedRoot = lockContentRootFor(entry.name, entry.type);
277
+ if (lockedRoot) {
278
+ if (!isMaterializedDir(lockedRoot)) {
279
+ warn(`Warning: managed source "${entry.name}" is missing its locked materialization at ${lockedRoot}; ` +
280
+ `run \`akm bundle update ${entry.name}\` to restore it.`);
281
+ }
282
+ // Managed installs are refreshed only by add/update. Hydrating the URL-
283
+ // derived provider cache here would create a second checkout while reads
284
+ // and writes continue using the lock root.
285
+ continue;
286
+ }
282
287
  const factory = resolveSourceProviderFactory(entry.type);
283
288
  if (!factory)
284
289
  continue;
@@ -292,6 +297,12 @@ export async function ensureSourceCaches(config, options) {
292
297
  }
293
298
  if (!provider.sync)
294
299
  continue;
300
+ if (!materialize) {
301
+ // READ path: never clone/pull/fetch. Serve an already-materialized cache
302
+ // as last-known-good; skip an absent/partial one with a single warning.
303
+ warnIfSourceUnavailableForRead(entry, provider.name);
304
+ continue;
305
+ }
295
306
  try {
296
307
  await provider.sync({ force });
297
308
  }
@@ -300,3 +311,38 @@ export async function ensureSourceCaches(config, options) {
300
311
  }
301
312
  }
302
313
  }
314
+ /**
315
+ * True when `dir` holds already-materialized content: it exists, is a
316
+ * directory, and is non-empty. A non-existent path or an empty leftover /
317
+ * partial staging dir reads as NOT materialized so the read skips it rather
318
+ * than walking a hollow cache.
319
+ */
320
+ function isMaterializedDir(dir) {
321
+ try {
322
+ if (!fs.statSync(dir).isDirectory())
323
+ return false;
324
+ return fs.readdirSync(dir).length > 0;
325
+ }
326
+ catch {
327
+ return false;
328
+ }
329
+ }
330
+ /**
331
+ * On a read-path auto-index, warn (once per source) that a cache-backed source
332
+ * is not materialized locally and is being skipped — naming the remedy. Uses
333
+ * the SAME lock-first content-root resolution the walker uses, so an installed
334
+ * source whose content lives at its lock `localRoot` counts as materialized.
335
+ */
336
+ function warnIfSourceUnavailableForRead(entry, providerName) {
337
+ let dir;
338
+ try {
339
+ dir = resolveEntryContentDir(entry);
340
+ }
341
+ catch {
342
+ dir = undefined;
343
+ }
344
+ if (dir && isMaterializedDir(dir))
345
+ return;
346
+ warn(`Warning: source "${providerName}" is not materialized locally; skipping it for this read. ` +
347
+ "Run `akm index` (or `akm bundle update`) to fetch it.");
348
+ }
@@ -11,7 +11,10 @@ export function deriveSemanticProviderFingerprint(embedding) {
11
11
  return `deterministic:${DETERMINISTIC_EMBED_MODEL_ID}`;
12
12
  }
13
13
  if (embedding?.endpoint) {
14
- return `remote:${embedding.endpoint}|${embedding.model}|${embedding.dimension ?? "default"}`;
14
+ // Fingerprint keys on vector identity only (model + dimension). The endpoint
15
+ // is transport/routing and has no bearing on vector compatibility, so moving
16
+ // the same model+dimension to a different host must not force a full re-embed.
17
+ return `remote:${embedding.model}|${embedding.dimension ?? "default"}`;
15
18
  }
16
19
  return `local:${embedding?.localModel ?? DEFAULT_LOCAL_MODEL}`;
17
20
  }
@@ -1,6 +1,14 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ const USAGE_EVENT_SOURCES = new Set(["user", "improve", "task", "audit", "unknown"]);
5
+ /** Resolve subprocess provenance without treating an invalid value as user demand. */
6
+ export function resolveUsageEventSource(env = process.env) {
7
+ const raw = env.AKM_EVENT_SOURCE;
8
+ if (raw === undefined || raw === "")
9
+ return "user";
10
+ return USAGE_EVENT_SOURCES.has(raw) ? raw : "unknown";
11
+ }
4
12
  // ── Schema ──────────────────────────────────────────────────────────────────
5
13
  export function ensureUsageEventsSchema(db) {
6
14
  db.exec(`
@@ -29,41 +37,13 @@ export function ensureUsageEventsSchema(db) {
29
37
  export function insertUsageEvent(db, event) {
30
38
  try {
31
39
  db.prepare(`INSERT INTO usage_events (event_type, query, entry_id, entry_ref, signal, metadata, source)
32
- VALUES (?, ?, ?, ?, ?, ?, ?)`).run(event.event_type, event.query ?? null, event.entry_id ?? null, event.entry_ref ?? null, event.signal ?? null, event.metadata ?? null, event.source ?? "user");
40
+ VALUES (?, ?, ?, ?, ?, ?, ?)`).run(event.event_type, event.query ?? null, event.entry_id ?? null, event.entry_ref ?? null, event.signal ?? null, event.metadata ?? null, event.source ?? "unknown");
33
41
  }
34
42
  catch {
35
43
  /* fire-and-forget: silently ignore errors */
36
44
  }
37
45
  }
38
46
  // ── Query ────────────────────────────────────────────────────────────────────
39
- /**
40
- * Retrieve usage events, optionally filtered by event_type and/or entry_ref.
41
- */
42
- export function getUsageEvents(db, filters) {
43
- const conditions = [];
44
- const params = [];
45
- if (filters?.event_type) {
46
- conditions.push("event_type = ?");
47
- params.push(filters.event_type);
48
- }
49
- if (filters?.entry_ref) {
50
- conditions.push("entry_ref = ?");
51
- params.push(filters.entry_ref);
52
- }
53
- if (filters?.source) {
54
- conditions.push("source = ?");
55
- params.push(filters.source);
56
- }
57
- if (filters?.since) {
58
- conditions.push("created_at >= ?");
59
- params.push(filters.since);
60
- }
61
- const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
62
- const sql = `SELECT id, event_type, query, entry_id, entry_ref, signal, metadata, source, created_at
63
- FROM usage_events ${where}
64
- ORDER BY id ASC`;
65
- return db.prepare(sql).all(...params);
66
- }
67
47
  /**
68
48
  * Aggregate positive/negative feedback counts for a single entry.
69
49
  *
@@ -78,7 +58,7 @@ export function countFeedbackSignals(db, entryId) {
78
58
  SUM(CASE WHEN signal = 'positive' THEN 1 ELSE 0 END) AS pos,
79
59
  SUM(CASE WHEN signal = 'negative' THEN 1 ELSE 0 END) AS neg
80
60
  FROM usage_events
81
- WHERE event_type = 'feedback' AND entry_id = ?`)
61
+ WHERE event_type = 'feedback' AND entry_id = ? AND source = 'user'`)
82
62
  .get(entryId);
83
63
  return { pos: counts?.pos ?? 0, neg: counts?.neg ?? 0 };
84
64
  }
@@ -67,8 +67,6 @@ export function buildFileContext(stashRoot, absPath) {
67
67
  };
68
68
  }
69
69
  // ── Registry ─────────────────────────────────────────────────────────────────
70
- /** Ordered list of registered matchers. Later registrations win ties. */
71
- const matchers = [];
72
70
  /** Renderer lookup by name. */
73
71
  const renderers = new Map();
74
72
  /**
@@ -77,21 +75,12 @@ const renderers = new Map();
77
75
  * Delegates to the single `initIndexer()` composition root (see
78
76
  * `src/indexer/init.ts`). Imported dynamically to keep this a lazy gate and to
79
77
  * avoid a static import cycle (init -> renderers -> file-context). Called on
80
- * first use of runMatchers/getRenderer/getAllRenderers; idempotent.
78
+ * first use of getRenderer/getAllRenderers; idempotent.
81
79
  */
82
80
  async function ensureBuiltinsRegistered() {
83
81
  const { initIndexer } = await import("../init.js");
84
82
  await initIndexer();
85
83
  }
86
- /**
87
- * Register an AssetMatcher.
88
- *
89
- * Matchers are evaluated in registration order. When two matchers produce
90
- * the same specificity score, the one registered later wins.
91
- */
92
- export function registerMatcher(matcher) {
93
- matchers.push(matcher);
94
- }
95
84
  /**
96
85
  * Register an AssetRenderer.
97
86
  *
@@ -114,47 +103,16 @@ export async function getAllRenderers() {
114
103
  await ensureBuiltinsRegistered();
115
104
  return Array.from(renderers.values());
116
105
  }
117
- /**
118
- * Run every registered matcher against a FileContext and return the
119
- * highest-specificity result.
120
- *
121
- * Resolution rules:
122
- * 1. Every matcher is invoked; null returns are discarded.
123
- * 2. Results are ranked by specificity (descending).
124
- * 3. Ties are broken by registration order: the matcher registered later wins
125
- * (this lets user-registered matchers override built-in ones).
126
- * 4. Returns null when no matcher claims the file.
127
- */
128
- export async function runMatchers(ctx) {
129
- await ensureBuiltinsRegistered();
130
- // Collect (result, registrationIndex) pairs from all matchers.
131
- const hits = [];
132
- for (let i = 0; i < matchers.length; i++) {
133
- const result = matchers[i](ctx);
134
- if (result !== null) {
135
- hits.push({ result, index: i });
136
- }
137
- }
138
- if (hits.length === 0)
139
- return null;
140
- // Sort by specificity descending, then by registration index descending (later wins ties).
141
- hits.sort((a, b) => {
142
- const specDiff = b.result.specificity - a.result.specificity;
143
- if (specDiff !== 0)
144
- return specDiff;
145
- return b.index - a.index;
146
- });
147
- return hits[0].result;
148
- }
149
106
  /**
150
107
  * Build a RenderContext by merging a FileContext with its winning MatchResult
151
108
  * and the list of stash search paths.
152
109
  */
153
- export function buildRenderContext(ctx, match, stashDirs, origin) {
110
+ export function buildRenderContext(ctx, match, stashDirs, origin, defaultBundle) {
154
111
  return {
155
112
  ...ctx,
156
113
  matchResult: match,
157
114
  stashDirs,
158
115
  origin,
116
+ defaultBundle,
159
117
  };
160
118
  }