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
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import fs from "node:fs";
12
12
  import { parse as yamlParse, stringify as yamlStringify } from "yaml";
13
- import { assembleAsset } from "./asset-serialize.js";
13
+ import { assembleAsset, serializeFrontmatter } from "./asset-serialize.js";
14
14
  /**
15
15
  * Parse YAML frontmatter from a Markdown (or similar) string.
16
16
  *
@@ -51,15 +51,11 @@ export function parseFrontmatter(raw) {
51
51
  };
52
52
  }
53
53
  /**
54
- * Normalize YAML-parsed values to match expected AKM frontmatter types.
54
+ * Normalize YAML dates to match expected AKM frontmatter types.
55
55
  *
56
- * Two conversions:
57
- * 1. `Date` → YYYY-MM-DD string: the yaml "core" schema parses bare date
56
+ * `Date` → YYYY-MM-DD string: the yaml "core" schema parses bare date
58
57
  * scalars like `2026-06-18` as JS Date instances. AKM frontmatter treats
59
58
  * `updated:` and similar fields as plain strings.
60
- * 2. `null` → `""`: the yaml library parses empty-value keys (`key:` with no
61
- * value) as `null`, but AKM callers historically received `""` from the
62
- * hand-rolled parser. Convert to preserve backward compatibility.
63
59
  */
64
60
  function normalizeYamlValues(value) {
65
61
  if (value instanceof Date) {
@@ -68,11 +64,9 @@ function normalizeYamlValues(value) {
68
64
  const d = String(value.getUTCDate()).padStart(2, "0");
69
65
  return `${y}-${m}-${d}`;
70
66
  }
71
- if (value === null)
72
- return "";
73
67
  if (Array.isArray(value))
74
68
  return value.map(normalizeYamlValues);
75
- if (typeof value === "object") {
69
+ if (value !== null && typeof value === "object") {
76
70
  return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, normalizeYamlValues(v)]));
77
71
  }
78
72
  return value;
@@ -118,15 +112,37 @@ function parseFrontmatterLenient(frontmatter) {
118
112
  * or `null` to skip the write entirely (e.g. for idempotent no-ops). The body
119
113
  * content is preserved from the parse.
120
114
  *
115
+ * A frontmatter mutation is a METADATA edit, not a content edit: when the file
116
+ * already has a frontmatter block, only that block is replaced and the body
117
+ * bytes are kept verbatim (routing through `assembleAsset` would strip the
118
+ * body's leading blank lines and force a trailing newline, silently reshaping
119
+ * assets whose writer used a different separator style). A file gaining its
120
+ * FIRST frontmatter block goes through the canonical `assembleAsset` shape.
121
+ *
121
122
  * @returns `true` if a write occurred, `false` if the mutator returned `null`.
122
123
  */
123
124
  export function mutateFrontmatter(filePath, mutator) {
124
125
  const raw = fs.readFileSync(filePath, "utf8");
125
126
  const parsed = parseFrontmatter(raw);
127
+ if (parsed.frontmatter?.trim()) {
128
+ let strict;
129
+ try {
130
+ strict = yamlParse(parsed.frontmatter);
131
+ }
132
+ catch {
133
+ throw new Error(`Cannot mutate malformed YAML frontmatter in ${filePath}.`);
134
+ }
135
+ if (strict === null || typeof strict !== "object" || Array.isArray(strict)) {
136
+ throw new Error(`Cannot mutate non-mapping YAML frontmatter in ${filePath}.`);
137
+ }
138
+ }
126
139
  const nextFrontmatter = mutator(parsed);
127
140
  if (nextFrontmatter === null)
128
141
  return false;
129
- fs.writeFileSync(filePath, assembleAsset(nextFrontmatter, parsed.content), "utf8");
142
+ const next = parsed.frontmatter !== null
143
+ ? `---\n${serializeFrontmatter(nextFrontmatter)}\n---\n${parsed.content}`
144
+ : assembleAsset(nextFrontmatter, parsed.content);
145
+ fs.writeFileSync(filePath, next, "utf8");
130
146
  return true;
131
147
  }
132
148
  export function parseFrontmatterBlock(raw) {
@@ -141,7 +157,7 @@ export function parseFrontmatterBlock(raw) {
141
157
  return {
142
158
  frontmatter,
143
159
  content,
144
- bodyStartLine: countLines(raw.slice(0, match[0].length - match[2].length)) + 1,
160
+ bodyStartLine: countLines(raw.slice(0, match[0].length - content.length)) + 1,
145
161
  };
146
162
  }
147
163
  // Empty frontmatter (---\n---): the content-bearing regex above requires at
@@ -2,6 +2,34 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import { parseFrontmatter } from "./frontmatter.js";
5
+ /** Stable GitHub-style selector for a Markdown heading. */
6
+ export function markdownHeadingSlug(heading) {
7
+ return heading
8
+ .trim()
9
+ .toLowerCase()
10
+ .replace(/<[^>]*>/g, "")
11
+ .replace(/[^\p{L}\p{N}\s_-]+/gu, "-")
12
+ .replace(/[\s_]+/g, "-")
13
+ .replace(/-+/g, "-")
14
+ .replace(/^-|-$/g, "");
15
+ }
16
+ export function markdownFragmentSlugs(content) {
17
+ return uniqueHeadingSlugs(parseMarkdownToc(content).headings).filter(Boolean);
18
+ }
19
+ function uniqueHeadingSlugs(headings) {
20
+ const used = new Set();
21
+ return headings.map((heading) => {
22
+ const base = markdownHeadingSlug(heading.text);
23
+ if (!base)
24
+ return "";
25
+ let slug = base;
26
+ let suffix = 0;
27
+ while (used.has(slug))
28
+ slug = `${base}-${++suffix}`;
29
+ used.add(slug);
30
+ return slug;
31
+ });
32
+ }
5
33
  // ── Parsing ─────────────────────────────────────────────────────────────────
6
34
  export function parseMarkdownToc(content) {
7
35
  const lines = content.split(/\r?\n/);
@@ -31,61 +59,22 @@ export function parseMarkdownToc(content) {
31
59
  // ── Extraction ──────────────────────────────────────────────────────────────
32
60
  export function extractSection(content, heading) {
33
61
  const lines = content.split(/\r?\n/);
34
- const target = heading.toLowerCase();
35
- let startIdx = -1;
36
- let startLevel = 0;
37
- for (let i = 0; i < lines.length; i++) {
38
- const match = lines[i].match(/^(#{1,6})\s+(.+)$/);
39
- if (!match)
40
- continue;
41
- const text = match[2].replace(/\s+#+\s*$/, "").trim();
42
- if (text.toLowerCase() === target && startIdx === -1) {
43
- startIdx = i;
44
- startLevel = match[1].length;
45
- }
46
- else if (startIdx !== -1 && match[1].length <= startLevel) {
47
- return {
48
- content: lines.slice(startIdx, i).join("\n"),
49
- startLine: startIdx + 1,
50
- endLine: i,
51
- };
52
- }
53
- }
54
- if (startIdx === -1)
62
+ const headings = parseMarkdownToc(content).headings;
63
+ const fragment = heading.trim();
64
+ const slugIndex = uniqueHeadingSlugs(headings).indexOf(fragment);
65
+ const exact = slugIndex < 0 ? headings.find((candidate) => candidate.text.toLowerCase() === fragment.toLowerCase()) : undefined;
66
+ const selected = slugIndex >= 0 ? headings[slugIndex] : exact;
67
+ if (!selected)
55
68
  return null;
69
+ const next = headings.find((candidate) => candidate.line > selected.line && candidate.level <= selected.level);
70
+ const startIdx = selected.line - 1;
71
+ const endIdx = next ? next.line - 1 : lines.length;
56
72
  return {
57
- content: lines.slice(startIdx).join("\n"),
58
- startLine: startIdx + 1,
59
- endLine: lines.length,
73
+ content: lines.slice(startIdx, endIdx).join("\n"),
74
+ startLine: selected.line,
75
+ endLine: endIdx,
60
76
  };
61
77
  }
62
- export function extractLineRange(content, start, end) {
63
- const lines = content.split(/\r?\n/);
64
- if (end < start)
65
- return "";
66
- const s = Math.max(1, Math.min(start, lines.length));
67
- const e = Math.min(end, lines.length);
68
- return lines.slice(s - 1, e).join("\n");
69
- }
70
- export function extractFrontmatterOnly(content) {
71
- const parsed = parseFrontmatter(content);
72
- return parsed.frontmatter;
73
- }
74
- // ── Formatting ──────────────────────────────────────────────────────────────
75
- export function formatToc(toc) {
76
- if (toc.headings.length === 0) {
77
- return `(no headings found — ${toc.totalLines} lines total)`;
78
- }
79
- const lineWidth = String(toc.totalLines).length;
80
- const parts = toc.headings.map((h) => {
81
- const lineNum = `L${String(h.line).padStart(lineWidth)}`;
82
- const indent = " ".repeat(h.level - 1);
83
- const prefix = "#".repeat(h.level);
84
- return `${lineNum} ${indent}${prefix} ${h.text}`;
85
- });
86
- parts.push(`\n${toc.totalLines} lines total`);
87
- return parts.join("\n");
88
- }
89
78
  // ── Fence stripping ──────────────────────────────────────────────────────────
90
79
  /**
91
80
  * Best-effort fence stripping. Strips `<think>` reasoning blocks emitted by
@@ -0,0 +1,274 @@
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
+ * Ref RESOLUTION layer — akm 0.9.0 Chunk-5 flip, stage F1 (ref-grammar decision
6
+ * D-R1 / D-R4).
7
+ *
8
+ * The 0.9.0 ref abstraction is `parse → resolve → serialize`:
9
+ * - parse — `parseBundleRef` (`asset-ref.ts`), pure syntax, no I/O.
10
+ * - resolve — {@link resolveRef} (this module): turn a maybe-short
11
+ * {@link BundleRef} into a fully-qualified {@link ResolvedRef}
12
+ * against an injected {@link RefContext}. This is the "the short
13
+ * form is input sugar" rule (§11.1) made structural: only a
14
+ * `ResolvedRef` ever crosses a storage boundary.
15
+ * - serialize — `bundleRefToString` (`asset-ref.ts`); serializing a
16
+ * `ResolvedRef` always emits the fully-qualified form.
17
+ *
18
+ * ── Cycle-safety (HARD constraint) ──
19
+ *
20
+ * This is a PURE LEAF. It imports only sibling leaves (`asset-ref`,
21
+ * `asset-placement`) and the `core/errors` sink — nothing from the indexer-db
22
+ * SCC and no `Database`/config handle. The resolution surface is INJECTED via
23
+ * {@link RefContext}; callers build the context from their own db handle /
24
+ * installation list and hand it in. Keeping the resolver free of I/O is what
25
+ * lets it stay out of every import cycle.
26
+ *
27
+ * ── Input-boundary parser (new-grammar only) ──
28
+ *
29
+ * {@link parseRefInput} parses a RAW user/CLI/API ref in the 0.9.0
30
+ * `[bundle//]conceptId` grammar and returns an {@link AssetRef} value object via
31
+ * the permanent D-R2 reverse table {@link typeNameFromConceptId}. Post-Chunk-8
32
+ * every durable ref reaching a reader is already the new grammar, so this is the
33
+ * ONE ref parser outside the frozen migrator — there is no stored-ref dual
34
+ * grammar to bridge any more.
35
+ */
36
+ import { NotFoundError, UsageError } from "../errors.js";
37
+ import { placementSpecFor, stashDirFor, typeForStashDir } from "./asset-placement.js";
38
+ import { isBundleSlug, parseBundleRef } from "./asset-ref.js";
39
+ /**
40
+ * Resolve a maybe-short input ref to a fully-qualified {@link ResolvedRef}
41
+ * against `ctx`, implementing D-R4 exactly:
42
+ *
43
+ * 1. Already-qualified input (`bundle//…`) → that bundle (passthrough). When
44
+ * `ctx.only` is set and disagrees, that is a not-found (the ref names a
45
+ * bundle the caller scoped out).
46
+ * 2. Short input, `only` set → resolve to `only` iff it contains the concept.
47
+ * 3. Short input, no `only` → `defaultBundle` if it contains the concept,
48
+ * otherwise the FIRST bundle (priority order) that contains it.
49
+ * 4. No match → {@link NotFoundError} naming the forms tried.
50
+ *
51
+ * The `#fragment` is carried through untouched.
52
+ */
53
+ export function resolveRef(input, ctx) {
54
+ const ref = typeof input === "string" ? parseBundleRef(input) : input;
55
+ const { conceptId, fragment } = ref;
56
+ // 1. Qualified passthrough — an explicit bundle prefix wins.
57
+ if (ref.bundle !== undefined) {
58
+ if (ctx.only !== undefined && ref.bundle !== ctx.only) {
59
+ throw notFound(conceptId, [`${ref.bundle}//${conceptId}`], ctx);
60
+ }
61
+ return { bundle: ref.bundle, conceptId, fragment };
62
+ }
63
+ // `only` scoping restricts the candidate set to a single bundle.
64
+ const candidates = ctx.only !== undefined ? ctx.bundles.filter((b) => b.id === ctx.only) : ctx.bundles;
65
+ // 2/3. defaultBundle wins over priority order for a short ref (but only when
66
+ // not `only`-scoped; an `only` request never falls back to the default).
67
+ if (ctx.only === undefined && ctx.defaultBundle !== undefined) {
68
+ const def = ctx.bundles.find((b) => b.id === ctx.defaultBundle);
69
+ if (def?.hasConcept(conceptId))
70
+ return { bundle: def.id, conceptId, fragment };
71
+ }
72
+ // First candidate (priority order) that contains the concept.
73
+ for (const b of candidates) {
74
+ if (b.hasConcept(conceptId))
75
+ return { bundle: b.id, conceptId, fragment };
76
+ }
77
+ throw notFound(conceptId, [conceptId], ctx);
78
+ }
79
+ function notFound(conceptId, triedForms, ctx) {
80
+ const scope = ctx.only !== undefined ? ` in bundle "${ctx.only}"` : "";
81
+ const forms = triedForms.map((f) => `"${f}"`).join(", ");
82
+ return new NotFoundError(`No bundle contains concept "${conceptId}"${scope} (tried ${forms}).`, "ASSET_NOT_FOUND");
83
+ }
84
+ /**
85
+ * D-R2 conceptId derivation from an asset `type`/`name` pair
86
+ * (`stashDirFor(type)/name`; bare name for a foreign type with no placement
87
+ * stash-subdir). Kept self-contained so {@link displayRef} — a PERMANENT display
88
+ * rule remains independent of input parsing.
89
+ *
90
+ * Exported (Chunk-8 WI-8.5c) as the ONE conceptId derivation the improve
91
+ * correlation sites (`eligibility.ts` candidate refs, `salience.ts`
92
+ * last-use lookup, `collapse-detector.ts` canary mint/score) share with the
93
+ * display rule — the permanent successor to the retired transient
94
+ * `legacyConceptId`.
95
+ */
96
+ export function conceptIdFromTypeName(type, name) {
97
+ const stashDir = stashDirFor(type);
98
+ return stashDir !== undefined ? `${stashDir}/${name}` : name;
99
+ }
100
+ /**
101
+ * Build the USER-FACING / envelope ref string for an indexed item, applying the
102
+ * Chunk-5 flip F4b output-spelling rule (orchestrator decision; ref-grammar
103
+ * decision D-R2 / D-R3). This is the ONE place the rule lives — every emission
104
+ * site calls it instead of hand-building a ref from an entry.
105
+ *
106
+ * The rule mirrors TODAY'S origin-qualification UX, transposed to the 0.9.0
107
+ * grammar:
108
+ *
109
+ * - An item in the **default/primary bundle** (`bundleId` undefined, or equal
110
+ * to `defaultBundleId`) emits the SHORT conceptId (`knowledge/http-caching`)
111
+ * — exactly where the pre-0.9.0 output emitted an un-qualified `type:name`.
112
+ * - Any other **non-default bundle** emits the fully-qualified
113
+ * `bundle//conceptId`. Post-Chunk-8 every bundle id is a legal slug (the
114
+ * config migration assigned each source its D-R5 slug bundle key), so this
115
+ * is always the new grammar — a non-slug registryId now displays under its
116
+ * derived slug bundle id, never the retired `origin//type:name` spelling.
117
+ */
118
+ export function displayRef(item, defaultBundleId) {
119
+ const conceptId = item.conceptId ?? conceptIdFromTypeName(item.type, item.name);
120
+ const { bundleId } = item;
121
+ // Default/primary bundle → SHORT conceptId (the flip).
122
+ if (bundleId === undefined || bundleId === defaultBundleId)
123
+ return conceptId;
124
+ // Non-default bundle → the new fully-qualified `bundle//conceptId` grammar.
125
+ return `${bundleId}//${conceptId}`;
126
+ }
127
+ /**
128
+ * Split a qualified conceptId (`<stash-subdir>/<name>`) into its asset
129
+ * `type`/`name`, or `undefined` when the leading segment is not a known stash
130
+ * subdir (a bare-name conceptId from a foreign type — no legacy predicate
131
+ * applies). The PERMANENT D-R2 reverse table: the input boundary uses it to map
132
+ * a new-grammar conceptId onto today's {@link AssetRef} shape. (The migrate home
133
+ * keeps a private transient copy for stored-ref parsing.)
134
+ */
135
+ export function typeNameFromConceptId(conceptId) {
136
+ const slash = conceptId.indexOf("/");
137
+ if (slash <= 0)
138
+ return undefined;
139
+ const type = typeForStashDir(conceptId.slice(0, slash));
140
+ if (type === undefined)
141
+ return undefined;
142
+ return { type, name: conceptId.slice(slash + 1) };
143
+ }
144
+ /**
145
+ * D11 — the opaque-adapter-conceptId fallback. `typeNameFromConceptId` only
146
+ * ever answers for the PLACEMENT_SPECS stash-resident subset (D-R2); a
147
+ * conceptId whose leading segment is NOT a registered placement stashDir is
148
+ * still perfectly legal DATA per D11 — an OKF item (`tables/customers`), a
149
+ * website page, a wiki pageKind, an adapter `instruction` doc, … — and the
150
+ * ref-consuming commands must accept it rather than treat "not an AKM
151
+ * placement dir" as "malformed ref". This function draws the line: it accepts
152
+ * any well-formed `<segment>/<rest>` conceptId (so the shape is still
153
+ * anchored — a bare no-slash name stays the caller's job to pre-qualify with a
154
+ * default type, the existing env/secret/`akm mv` "bare name" convenience), and
155
+ * REJECTS anything shaped like the retired `type:name` colon grammar (Q-02):
156
+ * a `:` in the leading segment is that grammar smuggled through a conceptId
157
+ * string (e.g. `script:db/migrate/run.sh`, `workflow:release/train`), not a
158
+ * real adapter directory name, so it is refused rather than silently
159
+ * reinterpreted as opaque data.
160
+ *
161
+ * `name` deliberately carries the FULL original conceptId, not just the tail.
162
+ * This is what makes the pair round-trip through the UNCHANGED
163
+ * {@link conceptIdFromTypeName} (`stashDirFor(type)/name`, bare `name` when
164
+ * `type` has no placement stashDir): since an opaque `type` never owns a
165
+ * placement stashDir, `conceptIdFromTypeName(type, name)` falls to its bare-
166
+ * `name` branch and returns `name` verbatim — the original conceptId,
167
+ * unchanged — instead of losing the leading segment. `type` itself carries
168
+ * the leading segment (informational/behavioral use: `.type === "lesson"`
169
+ * checks correctly miss for opaque data) UNLESS that segment happens to
170
+ * collide with a real PLACEMENT_SPECS type key that merely uses a different
171
+ * stashDir spelling (e.g. a foreign top-level dir literally named "skill",
172
+ * singular) — that pathological case would make `stashDirFor` succeed on the
173
+ * "type" and corrupt the round-trip, so it falls back to the full conceptId as
174
+ * `type` too (never a placement key, since a placement key never contains
175
+ * `/`).
176
+ *
177
+ * This intentionally does NOT collapse the KNOWN_TYPES/PLACEMENT_SPECS split:
178
+ * `typeNameFromConceptId` (PLACEMENT_SPECS only) is untouched, and an opaque
179
+ * `type` returned here is never a {@link KnownType} — it is a passthrough
180
+ * label, not a claim that AKM recognizes or owns the concept.
181
+ */
182
+ function opaqueRefParts(conceptId, allowRoot = false) {
183
+ const slash = conceptId.indexOf("/");
184
+ if (slash <= 0)
185
+ return allowRoot && !conceptId.includes(":") ? { type: conceptId, name: conceptId } : undefined;
186
+ const segment = conceptId.slice(0, slash);
187
+ if (segment.includes(":"))
188
+ return undefined; // retired `type:name` grammar, not opaque data (Q-02).
189
+ const type = placementSpecFor(segment) === undefined ? segment : conceptId;
190
+ return { type, name: conceptId };
191
+ }
192
+ /**
193
+ * Parse a RAW user / CLI / API ref string in the 0.9.0 `[bundle//]conceptId`
194
+ * grammar, returning it in today's {@link AssetRef} value-object shape
195
+ * (ref-grammar decision D-R1 / D-R4). All boundaries are NEW-GRAMMAR ONLY: a
196
+ * legacy `type:name` input now fails as an unknown-conceptId not-found. Post-
197
+ * Chunk-8 every durable ref is already the new grammar, so this parser also
198
+ * serves the (formerly dual-grammar) stored-ref readers.
199
+ *
200
+ * Mapping (new grammar → {@link AssetRef}):
201
+ * - `conceptId` → `type`/`name` via {@link typeNameFromConceptId} (the D-R2
202
+ * static stash-subdir table) when the leading segment is a known AKM
203
+ * placement stashDir, else via {@link opaqueRefParts} (D11 — the ref-parser
204
+ * seam accepts opaque adapter conceptIds, e.g. OKF items, website pages,
205
+ * wiki pageKinds, adapter `instruction` docs) when it is merely a well-
206
+ * formed but foreign `<segment>/<rest>` shape. A conceptId that is neither
207
+ * — no slash at all, or a retired colon-grammar shape smuggled through —
208
+ * has no type predicate: the same not-found outcome a genuine typo
209
+ * produces today.
210
+ * - `bundle` → `origin`. A new-grammar bundle slug is a registryId-shaped
211
+ * id by construction, so it flows straight into the legacy origin channel
212
+ * that `resolveSourcesForOrigin` matches on `registryId`. The SHORT form (no
213
+ * bundle) leaves `origin` undefined = search-all-sources.
214
+ * - `#fragment` → rejected. No input boundary consumes an export fragment.
215
+ */
216
+ export function parseRefInput(raw) {
217
+ const ref = parseBundleRef(raw);
218
+ if (ref.fragment !== undefined) {
219
+ throw new UsageError(`Export fragment "#${ref.fragment}" is not accepted here — drop it from "${raw.trim()}".`, "INVALID_FLAG_VALUE");
220
+ }
221
+ const parts = typeNameFromConceptId(ref.conceptId) ?? opaqueRefParts(ref.conceptId, ref.bundle !== undefined);
222
+ if (parts === undefined) {
223
+ throw new NotFoundError(`Unrecognized asset ref "${raw.trim()}": conceptId "${ref.conceptId}" has no known asset-type prefix.`, "ASSET_NOT_FOUND");
224
+ }
225
+ return { type: parts.type, name: parts.name, origin: ref.bundle };
226
+ }
227
+ /**
228
+ * Parse a CLI/API ref that MAY be qualified by a NON-slug origin — a registry
229
+ * ref (`github:owner/repo`, `npm:@scope/pkg`, `git:host/path`), a bare path, or
230
+ * a URL — as its `origin//conceptId` prefix. Such an origin carries `:`/`.`/`/`
231
+ * so it is not a legal bundle slug and the strict {@link parseRefInput} rejects
232
+ * it; but it is still a valid SOURCE origin that `resolveSourcesForOrigin`
233
+ * matches by registry-id / path and the remote-fetch fallback can install. The
234
+ * conceptId body is parsed under the strict new grammar; the raw origin is kept
235
+ * as-is — the symmetric input side of {@link displayRef}, which likewise keeps
236
+ * `origin//…` for exactly these non-slug origins (ref-grammar decision D-R5).
237
+ *
238
+ * A short ref (no origin) or a slug-origin ref is delegated verbatim to
239
+ * {@link parseRefInput}, so this is a safe superset for origin-accepting
240
+ * commands (`show`, `clone`, `graph`, `history`).
241
+ */
242
+ export function parseQualifiedRefInput(raw) {
243
+ const trimmed = raw.trim();
244
+ const boundary = trimmed.indexOf("//");
245
+ if (boundary > 0) {
246
+ const origin = trimmed.slice(0, boundary);
247
+ if (!isBundleSlug(origin)) {
248
+ return { ...parseRefInput(trimmed.slice(boundary + 2)), origin };
249
+ }
250
+ }
251
+ return parseRefInput(trimmed);
252
+ }
253
+ /**
254
+ * Does `raw` already read as a COMPLETE new-grammar asset ref, as opposed to a
255
+ * bare asset name that a boundary would prefix with a default type (the
256
+ * `env`/`secret`/`akm mv` "bare name" convenience)?
257
+ *
258
+ * True when `raw` is a `[bundle//]conceptId` whose conceptId leads with a KNOWN
259
+ * stash subdir ({@link typeNameFromConceptId} resolves it). A bare name like
260
+ * `prod` or `projectA/new-note` is neither — its leading segment maps to no
261
+ * type — so it stays a bare name for the caller to qualify.
262
+ */
263
+ export function isFullRefInput(raw) {
264
+ const trimmed = raw.trim();
265
+ if (!trimmed)
266
+ return false;
267
+ try {
268
+ const parsed = parseBundleRef(trimmed);
269
+ return parsed.bundle !== undefined || typeNameFromConceptId(parsed.conceptId) !== undefined;
270
+ }
271
+ catch {
272
+ return false;
273
+ }
274
+ }
@@ -7,7 +7,7 @@
7
7
  * A stash may carry an optional, human-authored `.meta/` directory at its
8
8
  * root holding orientation docs for the stash as a whole: purpose, key
9
9
  * assets, conventions, maintainer info. Because `.meta/` is a dot-directory,
10
- * the indexer's walker already skips it (see `src/indexer/walker.ts`), so
10
+ * the indexer's walker already skips it (see `src/indexer/walk/walker.ts`), so
11
11
  * these files never pollute the search corpus. They are surfaced on demand
12
12
  * via `akm show [<origin>//]meta[:<name>]`, which direct-reads the file
13
13
  * rather than going through the index.
@@ -54,7 +54,7 @@ export function parseMetaRef(ref) {
54
54
  }
55
55
  /**
56
56
  * Reject meta names that would escape the `.meta/` directory. Mirrors the
57
- * traversal guards in `parseAssetRef`'s `validateName`.
57
+ * traversal guards in the ref parser's `validateName`.
58
58
  */
59
59
  function assertSafeMetaName(name) {
60
60
  if (name.includes("\0")) {
@@ -0,0 +1,51 @@
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 path from "node:path";
6
+ import { isBundleSlug } from "./asset/asset-ref.js";
7
+ /** Deterministic, filesystem-safe bundle slug from a source path. */
8
+ export function slugForPath(sourcePath) {
9
+ const resolved = path.resolve(sourcePath);
10
+ const base = path
11
+ .basename(resolved)
12
+ .toLowerCase()
13
+ .replace(/[^a-z0-9]+/g, "-")
14
+ .replace(/^-+|-+$/g, "");
15
+ if (base.length > 0)
16
+ return base;
17
+ return `bundle-${shortHash(resolved)}`;
18
+ }
19
+ /** Derive one batch-unique bundle id. */
20
+ export function deriveBundleId(registryId, sourcePath, usedIds) {
21
+ const preferred = registryId && registryId.length > 0 && isBundleSlug(registryId) ? registryId : slugForPath(sourcePath);
22
+ const id = ensureUniqueId(preferred, sourcePath, usedIds);
23
+ usedIds.add(id);
24
+ return id;
25
+ }
26
+ /** Derive an ordered batch while reserving every explicit configured bundle id. */
27
+ export function deriveBundleIds(sources) {
28
+ const usedIds = new Set();
29
+ const reservedIds = new Set(sources.flatMap((source) => (source.registryId && isBundleSlug(source.registryId) ? [source.registryId] : [])));
30
+ return sources.map((source) => {
31
+ const id = source.registryId && isBundleSlug(source.registryId)
32
+ ? deriveBundleId(source.registryId, source.path, usedIds)
33
+ : deriveBundleId(undefined, source.path, new Set([...usedIds, ...reservedIds]));
34
+ usedIds.add(id);
35
+ return id;
36
+ });
37
+ }
38
+ function ensureUniqueId(preferred, sourcePath, used) {
39
+ if (!used.has(preferred))
40
+ return preferred;
41
+ const suffixed = `${preferred}-${shortHash(path.resolve(sourcePath))}`;
42
+ if (!used.has(suffixed))
43
+ return suffixed;
44
+ let n = 2;
45
+ while (used.has(`${suffixed}-${n}`))
46
+ n++;
47
+ return `${suffixed}-${n}`;
48
+ }
49
+ function shortHash(input) {
50
+ return crypto.createHash("sha256").update(input).digest("hex").slice(0, 8);
51
+ }