akm-cli 0.7.0 → 0.7.2

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 (332) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/{src/cli.js → cli.js} +22 -8
  3. package/dist/{src/commands → commands}/installed-stashes.js +1 -1
  4. package/dist/{src/commands → commands}/source-add.js +1 -1
  5. package/dist/{src/core → core}/common.js +16 -1
  6. package/dist/{src/core → core}/config.js +5 -2
  7. package/dist/{src/indexer → indexer}/db-search.js +16 -1
  8. package/dist/{src/indexer → indexer}/graph-extraction.js +5 -3
  9. package/dist/{src/indexer → indexer}/indexer.js +27 -11
  10. package/dist/{src/indexer → indexer}/memory-inference.js +47 -58
  11. package/dist/{src/indexer → indexer}/search-source.js +1 -1
  12. package/dist/{src/llm → llm}/client.js +61 -1
  13. package/dist/{src/llm → llm}/embedder.js +8 -5
  14. package/dist/{src/llm → llm}/embedders/local.js +8 -2
  15. package/dist/{src/llm → llm}/embedders/remote.js +4 -2
  16. package/dist/{src/llm → llm}/graph-extract.js +4 -4
  17. package/dist/llm/memory-infer.js +114 -0
  18. package/dist/{src/llm → llm}/metadata-enhance.js +2 -2
  19. package/dist/{src/output → output}/cli-hints.js +2 -0
  20. package/dist/{src/setup → setup}/setup.js +30 -20
  21. package/dist/sources/providers/website.js +27 -0
  22. package/dist/{src/sources/providers/website.js → sources/website-ingest.js} +38 -51
  23. package/docs/README.md +7 -0
  24. package/docs/migration/release-notes/0.7.0.md +14 -0
  25. package/package.json +11 -8
  26. package/dist/src/llm/memory-infer.js +0 -86
  27. package/dist/tests/add-website-source.test.js +0 -119
  28. package/dist/tests/agent/agent-config-loader.test.js +0 -70
  29. package/dist/tests/agent/agent-config.test.js +0 -221
  30. package/dist/tests/agent/agent-detect.test.js +0 -100
  31. package/dist/tests/agent/agent-spawn.test.js +0 -234
  32. package/dist/tests/agent-output.test.js +0 -186
  33. package/dist/tests/architecture/agent-no-llm-sdk-guard.test.js +0 -103
  34. package/dist/tests/architecture/agent-spawn-seam.test.js +0 -193
  35. package/dist/tests/architecture/llm-stateless-seam.test.js +0 -112
  36. package/dist/tests/asset-ref.test.js +0 -192
  37. package/dist/tests/asset-registry.test.js +0 -103
  38. package/dist/tests/asset-spec.test.js +0 -241
  39. package/dist/tests/bench/attribution.test.js +0 -996
  40. package/dist/tests/bench/cleanup-sigint.test.js +0 -83
  41. package/dist/tests/bench/cleanup.js +0 -234
  42. package/dist/tests/bench/cleanup.test.js +0 -166
  43. package/dist/tests/bench/cli.js +0 -1018
  44. package/dist/tests/bench/cli.test.js +0 -445
  45. package/dist/tests/bench/compare.test.js +0 -556
  46. package/dist/tests/bench/corpus.js +0 -317
  47. package/dist/tests/bench/corpus.test.js +0 -258
  48. package/dist/tests/bench/doctor.js +0 -525
  49. package/dist/tests/bench/driver.js +0 -401
  50. package/dist/tests/bench/driver.test.js +0 -584
  51. package/dist/tests/bench/environment.js +0 -233
  52. package/dist/tests/bench/environment.test.js +0 -199
  53. package/dist/tests/bench/evolve-metrics.js +0 -179
  54. package/dist/tests/bench/evolve-metrics.test.js +0 -187
  55. package/dist/tests/bench/evolve.js +0 -647
  56. package/dist/tests/bench/evolve.test.js +0 -624
  57. package/dist/tests/bench/failure-modes.test.js +0 -349
  58. package/dist/tests/bench/feedback-integrity.test.js +0 -457
  59. package/dist/tests/bench/leakage.test.js +0 -228
  60. package/dist/tests/bench/learning-curve.test.js +0 -134
  61. package/dist/tests/bench/metrics.js +0 -2395
  62. package/dist/tests/bench/metrics.test.js +0 -1150
  63. package/dist/tests/bench/no-os-tmpdir-invariant.test.js +0 -43
  64. package/dist/tests/bench/opencode-config.js +0 -194
  65. package/dist/tests/bench/opencode-config.test.js +0 -370
  66. package/dist/tests/bench/report.js +0 -1885
  67. package/dist/tests/bench/report.test.js +0 -1038
  68. package/dist/tests/bench/run-config.js +0 -355
  69. package/dist/tests/bench/run-config.test.js +0 -298
  70. package/dist/tests/bench/run-curate-test.js +0 -32
  71. package/dist/tests/bench/run-failing-tasks.js +0 -56
  72. package/dist/tests/bench/run-full-bench.js +0 -51
  73. package/dist/tests/bench/run-items36-targeted.js +0 -69
  74. package/dist/tests/bench/run-nano-quick.js +0 -42
  75. package/dist/tests/bench/run-waveg-targeted.js +0 -62
  76. package/dist/tests/bench/runner.js +0 -699
  77. package/dist/tests/bench/runner.test.js +0 -958
  78. package/dist/tests/bench/search-bridge.test.js +0 -331
  79. package/dist/tests/bench/tmp.js +0 -131
  80. package/dist/tests/bench/trajectory.js +0 -116
  81. package/dist/tests/bench/trajectory.test.js +0 -127
  82. package/dist/tests/bench/verifier.js +0 -114
  83. package/dist/tests/bench/verifier.test.js +0 -118
  84. package/dist/tests/bench/workflow-evaluator.js +0 -557
  85. package/dist/tests/bench/workflow-evaluator.test.js +0 -421
  86. package/dist/tests/bench/workflow-spec.js +0 -345
  87. package/dist/tests/bench/workflow-spec.test.js +0 -363
  88. package/dist/tests/bench/workflow-trace.js +0 -472
  89. package/dist/tests/bench/workflow-trace.test.js +0 -254
  90. package/dist/tests/benchmark-search-quality.js +0 -536
  91. package/dist/tests/benchmark-suite.js +0 -1441
  92. package/dist/tests/capture-cli.test.js +0 -112
  93. package/dist/tests/cli-errors.test.js +0 -204
  94. package/dist/tests/commands/events.test.js +0 -370
  95. package/dist/tests/commands/history.test.js +0 -418
  96. package/dist/tests/commands/import.test.js +0 -103
  97. package/dist/tests/commands/proposal-cli.test.js +0 -209
  98. package/dist/tests/commands/reflect-propose-cli.test.js +0 -333
  99. package/dist/tests/commands/remember.test.js +0 -97
  100. package/dist/tests/commands/scope-flags.test.js +0 -300
  101. package/dist/tests/commands/search.test.js +0 -537
  102. package/dist/tests/commands/show-indexer-parity.test.js +0 -117
  103. package/dist/tests/commands/show.test.js +0 -294
  104. package/dist/tests/common.test.js +0 -266
  105. package/dist/tests/completions.test.js +0 -142
  106. package/dist/tests/config-cli.test.js +0 -193
  107. package/dist/tests/config-llm-features.test.js +0 -139
  108. package/dist/tests/config.test.js +0 -569
  109. package/dist/tests/contracts/migration-baseline.test.js +0 -43
  110. package/dist/tests/contracts/reflect-propose-envelope.test.js +0 -139
  111. package/dist/tests/contracts/spec-helpers.js +0 -46
  112. package/dist/tests/contracts/v1-spec-section-11-proposal-queue.test.js +0 -228
  113. package/dist/tests/contracts/v1-spec-section-12-agent-config.test.js +0 -56
  114. package/dist/tests/contracts/v1-spec-section-13-lesson-type.test.js +0 -34
  115. package/dist/tests/contracts/v1-spec-section-14-llm-features.test.js +0 -94
  116. package/dist/tests/contracts/v1-spec-section-4-1-asset-types.test.js +0 -39
  117. package/dist/tests/contracts/v1-spec-section-4-2-quality-rules.test.js +0 -44
  118. package/dist/tests/contracts/v1-spec-section-5-configuration.test.js +0 -47
  119. package/dist/tests/contracts/v1-spec-section-6-orchestration.test.js +0 -40
  120. package/dist/tests/contracts/v1-spec-section-7-module-layout.test.js +0 -58
  121. package/dist/tests/contracts/v1-spec-section-8-extension-points.test.js +0 -34
  122. package/dist/tests/contracts/v1-spec-section-9-4-cli-surface.test.js +0 -75
  123. package/dist/tests/contracts/v1-spec-section-9-7-llm-agent-boundary.test.js +0 -36
  124. package/dist/tests/core/write-source.test.js +0 -366
  125. package/dist/tests/curate-command.test.js +0 -87
  126. package/dist/tests/db-scoring.test.js +0 -201
  127. package/dist/tests/db.test.js +0 -654
  128. package/dist/tests/distill-cli-flag.test.js +0 -208
  129. package/dist/tests/distill.test.js +0 -515
  130. package/dist/tests/docker-install.test.js +0 -120
  131. package/dist/tests/e2e.test.js +0 -1419
  132. package/dist/tests/embedder.test.js +0 -340
  133. package/dist/tests/embedding-model-config.test.js +0 -379
  134. package/dist/tests/feedback-command.test.js +0 -172
  135. package/dist/tests/file-context.test.js +0 -552
  136. package/dist/tests/fixtures/scripts/git/summarize-diff.js +0 -9
  137. package/dist/tests/fixtures/scripts/lint/eslint-check.js +0 -7
  138. package/dist/tests/fixtures/stashes/load.js +0 -166
  139. package/dist/tests/fixtures/stashes/load.test.js +0 -97
  140. package/dist/tests/fixtures/stashes/ranking-baseline/scripts/mem0-search.js +0 -12
  141. package/dist/tests/frontmatter.test.js +0 -190
  142. package/dist/tests/fts-field-weighting.test.js +0 -254
  143. package/dist/tests/fuzzy-search.test.js +0 -230
  144. package/dist/tests/git-provider-clone.test.js +0 -45
  145. package/dist/tests/github.test.js +0 -161
  146. package/dist/tests/graph-boost-ranking.test.js +0 -305
  147. package/dist/tests/graph-extraction.test.js +0 -282
  148. package/dist/tests/helpers/usage-events.js +0 -8
  149. package/dist/tests/index-pass-llm.test.js +0 -161
  150. package/dist/tests/indexer.test.js +0 -570
  151. package/dist/tests/info-command.test.js +0 -166
  152. package/dist/tests/init.test.js +0 -69
  153. package/dist/tests/install-script.test.js +0 -246
  154. package/dist/tests/integration/agent-real-profile.test.js +0 -94
  155. package/dist/tests/issue-36-repro.test.js +0 -304
  156. package/dist/tests/issues-191-194.test.js +0 -160
  157. package/dist/tests/lesson-lint.test.js +0 -111
  158. package/dist/tests/llm-client.test.js +0 -115
  159. package/dist/tests/llm-feature-gate.test.js +0 -151
  160. package/dist/tests/llm.test.js +0 -139
  161. package/dist/tests/lockfile.test.js +0 -216
  162. package/dist/tests/manifest.test.js +0 -205
  163. package/dist/tests/markdown.test.js +0 -126
  164. package/dist/tests/matchers-unit.test.js +0 -189
  165. package/dist/tests/memory-inference.test.js +0 -299
  166. package/dist/tests/merge-scoring.test.js +0 -136
  167. package/dist/tests/metadata.test.js +0 -313
  168. package/dist/tests/migration-help.test.js +0 -89
  169. package/dist/tests/origin-resolve.test.js +0 -124
  170. package/dist/tests/output-baseline.test.js +0 -218
  171. package/dist/tests/output-shapes-unit.test.js +0 -478
  172. package/dist/tests/parallel-search.test.js +0 -272
  173. package/dist/tests/parameter-metadata.test.js +0 -365
  174. package/dist/tests/paths.test.js +0 -177
  175. package/dist/tests/progressive-disclosure.test.js +0 -280
  176. package/dist/tests/proposals.test.js +0 -279
  177. package/dist/tests/proposed-quality.test.js +0 -271
  178. package/dist/tests/provider-registry.test.js +0 -32
  179. package/dist/tests/ranking-regression.test.js +0 -548
  180. package/dist/tests/reflect-propose.test.js +0 -455
  181. package/dist/tests/registry-build-index.test.js +0 -394
  182. package/dist/tests/registry-cli.test.js +0 -290
  183. package/dist/tests/registry-index-v2.test.js +0 -430
  184. package/dist/tests/registry-install.test.js +0 -728
  185. package/dist/tests/registry-providers/parity.test.js +0 -189
  186. package/dist/tests/registry-providers/skills-sh.test.js +0 -309
  187. package/dist/tests/registry-providers/static-index.test.js +0 -238
  188. package/dist/tests/registry-resolve.test.js +0 -126
  189. package/dist/tests/registry-search.test.js +0 -923
  190. package/dist/tests/remember-frontmatter.test.js +0 -378
  191. package/dist/tests/remember-unit.test.js +0 -123
  192. package/dist/tests/ripgrep-install.test.js +0 -251
  193. package/dist/tests/ripgrep-resolve.test.js +0 -108
  194. package/dist/tests/ripgrep.test.js +0 -163
  195. package/dist/tests/save-command.test.js +0 -94
  196. package/dist/tests/save-trust-qa-fixes.test.js +0 -270
  197. package/dist/tests/scoring-pipeline.test.js +0 -648
  198. package/dist/tests/search-include-proposed-cli.test.js +0 -118
  199. package/dist/tests/self-update.test.js +0 -442
  200. package/dist/tests/semantic-search-e2e.test.js +0 -512
  201. package/dist/tests/semantic-status.test.js +0 -471
  202. package/dist/tests/setup-run.integration.js +0 -877
  203. package/dist/tests/setup-wizard.test.js +0 -198
  204. package/dist/tests/setup.test.js +0 -131
  205. package/dist/tests/source-add.test.js +0 -11
  206. package/dist/tests/source-clone.test.js +0 -254
  207. package/dist/tests/source-manage.test.js +0 -366
  208. package/dist/tests/source-providers/filesystem.test.js +0 -82
  209. package/dist/tests/source-providers/git.test.js +0 -252
  210. package/dist/tests/source-providers/website.test.js +0 -128
  211. package/dist/tests/source-qa-fixes.test.js +0 -286
  212. package/dist/tests/source-registry.test.js +0 -350
  213. package/dist/tests/source-resolve.test.js +0 -100
  214. package/dist/tests/source-source.test.js +0 -281
  215. package/dist/tests/source.test.js +0 -533
  216. package/dist/tests/tar-utils-scan.test.js +0 -73
  217. package/dist/tests/toggle-components.test.js +0 -73
  218. package/dist/tests/usage-telemetry.test.js +0 -265
  219. package/dist/tests/utility-scoring.test.js +0 -558
  220. package/dist/tests/vault-load-error.test.js +0 -78
  221. package/dist/tests/vault-qa-fixes.test.js +0 -194
  222. package/dist/tests/vault.test.js +0 -429
  223. package/dist/tests/vector-search.test.js +0 -608
  224. package/dist/tests/walker.test.js +0 -252
  225. package/dist/tests/wave2-cluster-bc.test.js +0 -228
  226. package/dist/tests/wave2-cluster-d.test.js +0 -180
  227. package/dist/tests/wave2-cluster-e.test.js +0 -179
  228. package/dist/tests/wiki-qa-fixes.test.js +0 -270
  229. package/dist/tests/wiki.test.js +0 -529
  230. package/dist/tests/workflow-cli.test.js +0 -271
  231. package/dist/tests/workflow-markdown.test.js +0 -171
  232. package/dist/tests/workflow-path-escape.test.js +0 -132
  233. package/dist/tests/workflow-qa-fixes.test.js +0 -395
  234. package/dist/tests/workflows/indexer-rejection.test.js +0 -213
  235. /package/dist/{src/commands → commands}/completions.js +0 -0
  236. /package/dist/{src/commands → commands}/config-cli.js +0 -0
  237. /package/dist/{src/commands → commands}/curate.js +0 -0
  238. /package/dist/{src/commands → commands}/distill.js +0 -0
  239. /package/dist/{src/commands → commands}/events.js +0 -0
  240. /package/dist/{src/commands → commands}/history.js +0 -0
  241. /package/dist/{src/commands → commands}/info.js +0 -0
  242. /package/dist/{src/commands → commands}/init.js +0 -0
  243. /package/dist/{src/commands → commands}/install-audit.js +0 -0
  244. /package/dist/{src/commands → commands}/migration-help.js +0 -0
  245. /package/dist/{src/commands → commands}/proposal.js +0 -0
  246. /package/dist/{src/commands → commands}/propose.js +0 -0
  247. /package/dist/{src/commands → commands}/reflect.js +0 -0
  248. /package/dist/{src/commands → commands}/registry-search.js +0 -0
  249. /package/dist/{src/commands → commands}/remember.js +0 -0
  250. /package/dist/{src/commands → commands}/search.js +0 -0
  251. /package/dist/{src/commands → commands}/self-update.js +0 -0
  252. /package/dist/{src/commands → commands}/show.js +0 -0
  253. /package/dist/{src/commands → commands}/source-clone.js +0 -0
  254. /package/dist/{src/commands → commands}/source-manage.js +0 -0
  255. /package/dist/{src/commands → commands}/vault.js +0 -0
  256. /package/dist/{src/core → core}/asset-ref.js +0 -0
  257. /package/dist/{src/core → core}/asset-registry.js +0 -0
  258. /package/dist/{src/core → core}/asset-spec.js +0 -0
  259. /package/dist/{src/core → core}/errors.js +0 -0
  260. /package/dist/{src/core → core}/events.js +0 -0
  261. /package/dist/{src/core → core}/frontmatter.js +0 -0
  262. /package/dist/{src/core → core}/lesson-lint.js +0 -0
  263. /package/dist/{src/core → core}/markdown.js +0 -0
  264. /package/dist/{src/core → core}/paths.js +0 -0
  265. /package/dist/{src/core → core}/proposals.js +0 -0
  266. /package/dist/{src/core → core}/warn.js +0 -0
  267. /package/dist/{src/core → core}/write-source.js +0 -0
  268. /package/dist/{src/indexer → indexer}/db.js +0 -0
  269. /package/dist/{src/indexer → indexer}/file-context.js +0 -0
  270. /package/dist/{src/indexer → indexer}/graph-boost.js +0 -0
  271. /package/dist/{src/indexer → indexer}/manifest.js +0 -0
  272. /package/dist/{src/indexer → indexer}/matchers.js +0 -0
  273. /package/dist/{src/indexer → indexer}/metadata.js +0 -0
  274. /package/dist/{src/indexer → indexer}/search-fields.js +0 -0
  275. /package/dist/{src/indexer → indexer}/semantic-status.js +0 -0
  276. /package/dist/{src/indexer → indexer}/usage-events.js +0 -0
  277. /package/dist/{src/indexer → indexer}/walker.js +0 -0
  278. /package/dist/{src/integrations → integrations}/agent/config.js +0 -0
  279. /package/dist/{src/integrations → integrations}/agent/detect.js +0 -0
  280. /package/dist/{src/integrations → integrations}/agent/index.js +0 -0
  281. /package/dist/{src/integrations → integrations}/agent/profiles.js +0 -0
  282. /package/dist/{src/integrations → integrations}/agent/prompts.js +0 -0
  283. /package/dist/{src/integrations → integrations}/agent/spawn.js +0 -0
  284. /package/dist/{src/integrations → integrations}/github.js +0 -0
  285. /package/dist/{src/integrations → integrations}/lockfile.js +0 -0
  286. /package/dist/{src/llm → llm}/embedders/cache.js +0 -0
  287. /package/dist/{src/llm → llm}/embedders/types.js +0 -0
  288. /package/dist/{src/llm → llm}/feature-gate.js +0 -0
  289. /package/dist/{src/llm → llm}/index-passes.js +0 -0
  290. /package/dist/{src/output → output}/context.js +0 -0
  291. /package/dist/{src/output → output}/renderers.js +0 -0
  292. /package/dist/{src/output → output}/shapes.js +0 -0
  293. /package/dist/{src/output → output}/text.js +0 -0
  294. /package/dist/{src/registry → registry}/build-index.js +0 -0
  295. /package/dist/{src/registry → registry}/create-provider-registry.js +0 -0
  296. /package/dist/{src/registry → registry}/factory.js +0 -0
  297. /package/dist/{src/registry → registry}/origin-resolve.js +0 -0
  298. /package/dist/{src/registry → registry}/providers/index.js +0 -0
  299. /package/dist/{src/registry → registry}/providers/skills-sh.js +0 -0
  300. /package/dist/{src/registry → registry}/providers/static-index.js +0 -0
  301. /package/dist/{src/registry → registry}/providers/types.js +0 -0
  302. /package/dist/{src/registry → registry}/resolve.js +0 -0
  303. /package/dist/{src/registry → registry}/types.js +0 -0
  304. /package/dist/{src/setup → setup}/detect.js +0 -0
  305. /package/dist/{src/setup → setup}/ripgrep-install.js +0 -0
  306. /package/dist/{src/setup → setup}/ripgrep-resolve.js +0 -0
  307. /package/dist/{src/setup → setup}/steps.js +0 -0
  308. /package/dist/{src/sources → sources}/include.js +0 -0
  309. /package/dist/{src/sources → sources}/provider-factory.js +0 -0
  310. /package/dist/{src/sources → sources}/provider.js +0 -0
  311. /package/dist/{src/sources → sources}/providers/filesystem.js +0 -0
  312. /package/dist/{src/sources → sources}/providers/git.js +0 -0
  313. /package/dist/{src/sources → sources}/providers/index.js +0 -0
  314. /package/dist/{src/sources → sources}/providers/install-types.js +0 -0
  315. /package/dist/{src/sources → sources}/providers/npm.js +0 -0
  316. /package/dist/{src/sources → sources}/providers/provider-utils.js +0 -0
  317. /package/dist/{src/sources → sources}/providers/sync-from-ref.js +0 -0
  318. /package/dist/{src/sources → sources}/providers/tar-utils.js +0 -0
  319. /package/dist/{src/sources → sources}/resolve.js +0 -0
  320. /package/dist/{src/sources → sources}/types.js +0 -0
  321. /package/dist/{src/templates → templates}/wiki-templates.js +0 -0
  322. /package/dist/{src/version.js → version.js} +0 -0
  323. /package/dist/{src/wiki → wiki}/wiki.js +0 -0
  324. /package/dist/{src/workflows → workflows}/authoring.js +0 -0
  325. /package/dist/{src/workflows → workflows}/cli.js +0 -0
  326. /package/dist/{src/workflows → workflows}/db.js +0 -0
  327. /package/dist/{src/workflows → workflows}/document-cache.js +0 -0
  328. /package/dist/{src/workflows → workflows}/parser.js +0 -0
  329. /package/dist/{src/workflows → workflows}/renderer.js +0 -0
  330. /package/dist/{src/workflows → workflows}/runs.js +0 -0
  331. /package/dist/{src/workflows → workflows}/schema.js +0 -0
  332. /package/dist/{src/workflows → workflows}/validator.js +0 -0
@@ -1,166 +0,0 @@
1
- /**
2
- * Shared fixture-stash loader for tests/*.test.ts and bench tasks.
3
- *
4
- * Each fixture lives at `tests/fixtures/stashes/<name>/` with a `MANIFEST.json`
5
- * and the standard akm stash layout. `loadFixtureStash(name)` copies the
6
- * fixture into a fresh tmp dir, sets `AKM_STASH_DIR`, runs `akm index`, and
7
- * returns the materialised path plus a cleanup function.
8
- *
9
- * See docs/technical/benchmark.md §5.5 for the contract.
10
- */
11
- import { createHash } from "node:crypto";
12
- import fs from "node:fs";
13
- import os from "node:os";
14
- import path from "node:path";
15
- const FIXTURES_ROOT = __dirname;
16
- const REPO_ROOT = path.resolve(FIXTURES_ROOT, "..", "..", "..");
17
- const CLI_ENTRY = path.join(REPO_ROOT, "src", "cli.ts");
18
- /**
19
- * List the fixture names available under `tests/fixtures/stashes/`.
20
- *
21
- * A directory is considered a fixture iff it contains a `MANIFEST.json`.
22
- * Returned names are sorted alphabetically.
23
- */
24
- export function listFixtures() {
25
- const entries = fs.readdirSync(FIXTURES_ROOT, { withFileTypes: true });
26
- const names = [];
27
- for (const entry of entries) {
28
- if (!entry.isDirectory())
29
- continue;
30
- const manifest = path.join(FIXTURES_ROOT, entry.name, "MANIFEST.json");
31
- if (fs.existsSync(manifest))
32
- names.push(entry.name);
33
- }
34
- names.sort();
35
- return names;
36
- }
37
- /**
38
- * Synchronous, deterministic SHA-256 hex of every file under the named
39
- * fixture. Hash input is `<relative-path>\0<file-bytes>\0` for each file in
40
- * sorted-relative-path order. Used by `bench compare` to refuse cross-fixture
41
- * diffs.
42
- *
43
- * Also exported as `computeFixtureContentHash` for callers that prefer the
44
- * `compute*` naming convention used by sibling helpers in `tests/bench/`
45
- * (see `computeTaskCorpusHash` in corpus.ts). The two names point at the
46
- * SAME implementation — there is exactly one fixture-content hash function
47
- * in this codebase, and `LoadedFixtureStash.contentHash` reuses it.
48
- */
49
- export function fixtureContentHash(name) {
50
- const root = fixtureSourceDir(name);
51
- const files = collectFilesSorted(root);
52
- const hash = createHash("sha256");
53
- for (const rel of files) {
54
- hash.update(rel);
55
- hash.update("\0");
56
- hash.update(fs.readFileSync(path.join(root, rel)));
57
- hash.update("\0");
58
- }
59
- return hash.digest("hex");
60
- }
61
- /**
62
- * Alias for `fixtureContentHash` matching the `compute*` naming used by
63
- * sibling helpers in `tests/bench/`. Reuses the SAME implementation —
64
- * defining a separate hash function for the same content would risk drift
65
- * between the report-stamping path and `LoadedFixtureStash.contentHash`.
66
- */
67
- export const computeFixtureContentHash = fixtureContentHash;
68
- /**
69
- * Copy the named fixture into a fresh tmp dir, set `AKM_STASH_DIR`, and run
70
- * `akm index` against it. Returns the tmp path plus a cleanup function that
71
- * restores the prior env value and recursively removes the tmp dir.
72
- *
73
- * Pass `{ skipIndex: true }` if the caller will build its own index and the
74
- * helper's `akm index` spawn would be wasted work.
75
- */
76
- export function loadFixtureStash(name, options = {}) {
77
- const sourceDir = fixtureSourceDir(name);
78
- const contentHash = fixtureContentHash(name);
79
- const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), `akm-fixture-${name}-`));
80
- const stashDir = path.join(tmpRoot, "stash");
81
- const cacheHome = path.join(tmpRoot, "cache");
82
- const configHome = path.join(tmpRoot, "config");
83
- copyDirRecursive(sourceDir, stashDir);
84
- fs.mkdirSync(cacheHome, { recursive: true });
85
- fs.mkdirSync(configHome, { recursive: true });
86
- const priorAkmStashDir = process.env.AKM_STASH_DIR;
87
- process.env.AKM_STASH_DIR = stashDir;
88
- if (!options.skipIndex) {
89
- // Use isolated XDG dirs for the index invocation so the helper never
90
- // touches the operator's real ~/.cache/akm or pulls in their configured
91
- // registries / sources. The shipped fixture is the only thing indexed.
92
- const result = Bun.spawnSync({
93
- cmd: ["bun", "run", CLI_ENTRY, "index"],
94
- cwd: stashDir,
95
- env: {
96
- ...process.env,
97
- AKM_STASH_DIR: stashDir,
98
- XDG_CACHE_HOME: cacheHome,
99
- XDG_CONFIG_HOME: configHome,
100
- },
101
- stdout: "pipe",
102
- stderr: "pipe",
103
- });
104
- if (result.exitCode !== 0) {
105
- // Restore env and clean up before throwing so the caller is not left
106
- // with a leaked tmp dir or mutated process state.
107
- if (priorAkmStashDir === undefined)
108
- delete process.env.AKM_STASH_DIR;
109
- else
110
- process.env.AKM_STASH_DIR = priorAkmStashDir;
111
- fs.rmSync(tmpRoot, { recursive: true, force: true });
112
- const stderr = result.stderr ? new TextDecoder().decode(result.stderr) : "";
113
- throw new Error(`akm index failed for fixture "${name}" (exit ${result.exitCode}): ${stderr}`);
114
- }
115
- }
116
- const cleanup = () => {
117
- if (priorAkmStashDir === undefined)
118
- delete process.env.AKM_STASH_DIR;
119
- else
120
- process.env.AKM_STASH_DIR = priorAkmStashDir;
121
- fs.rmSync(tmpRoot, { recursive: true, force: true });
122
- };
123
- return { stashDir, cleanup, contentHash, ...(!options.skipIndex ? { indexCacheHome: cacheHome } : {}) };
124
- }
125
- // ── Internals ───────────────────────────────────────────────────────────────
126
- function fixtureSourceDir(name) {
127
- if (!isSafeName(name)) {
128
- throw new Error(`invalid fixture name: ${JSON.stringify(name)}`);
129
- }
130
- const dir = path.join(FIXTURES_ROOT, name);
131
- if (!fs.existsSync(path.join(dir, "MANIFEST.json"))) {
132
- throw new Error(`fixture not found: ${name} (expected ${dir}/MANIFEST.json)`);
133
- }
134
- return dir;
135
- }
136
- function isSafeName(name) {
137
- return /^[a-zA-Z0-9._-]+$/.test(name);
138
- }
139
- function collectFilesSorted(root) {
140
- const out = [];
141
- const walk = (dir) => {
142
- const entries = fs.readdirSync(dir, { withFileTypes: true });
143
- for (const entry of entries) {
144
- const abs = path.join(dir, entry.name);
145
- if (entry.isDirectory())
146
- walk(abs);
147
- else if (entry.isFile())
148
- out.push(path.relative(root, abs));
149
- }
150
- };
151
- walk(root);
152
- out.sort();
153
- return out;
154
- }
155
- function copyDirRecursive(src, dest) {
156
- fs.mkdirSync(dest, { recursive: true });
157
- const entries = fs.readdirSync(src, { withFileTypes: true });
158
- for (const entry of entries) {
159
- const s = path.join(src, entry.name);
160
- const d = path.join(dest, entry.name);
161
- if (entry.isDirectory())
162
- copyDirRecursive(s, d);
163
- else if (entry.isFile())
164
- fs.copyFileSync(s, d);
165
- }
166
- }
@@ -1,97 +0,0 @@
1
- /**
2
- * Smoke tests for the shared fixture-stash loader.
3
- *
4
- * Validates that loadFixtureStash, fixtureContentHash, and listFixtures
5
- * behave as advertised in docs/technical/benchmark.md §5.5.
6
- */
7
- import { describe, expect, test } from "bun:test";
8
- import fs from "node:fs";
9
- import path from "node:path";
10
- import { computeFixtureContentHash, fixtureContentHash, listFixtures, loadFixtureStash } from "./load";
11
- describe("loadFixtureStash", () => {
12
- test("materialises the minimal fixture and cleanup removes it", () => {
13
- const priorAkmStashDir = process.env.AKM_STASH_DIR;
14
- const sentinel = "/tmp/some-prior-value";
15
- process.env.AKM_STASH_DIR = sentinel;
16
- const { stashDir, cleanup, contentHash } = loadFixtureStash("minimal");
17
- try {
18
- expect(fs.existsSync(stashDir)).toBe(true);
19
- expect(fs.statSync(stashDir).isDirectory()).toBe(true);
20
- // All five core asset directories from the minimal fixture.
21
- for (const sub of ["skills", "commands", "agents", "knowledge", "scripts"]) {
22
- expect(fs.existsSync(path.join(stashDir, sub))).toBe(true);
23
- }
24
- // Content hash is non-empty hex.
25
- expect(contentHash).toMatch(/^[0-9a-f]{64}$/);
26
- // The helper set AKM_STASH_DIR to the materialised path.
27
- expect(process.env.AKM_STASH_DIR).toBe(stashDir);
28
- // Default behaviour runs `akm index`, which writes the SQLite DB into
29
- // the helper's isolated XDG_CACHE_HOME (sibling of stashDir).
30
- const tmpRoot = path.dirname(stashDir);
31
- const dbPath = path.join(tmpRoot, "cache", "akm", "index.db");
32
- expect(fs.existsSync(dbPath)).toBe(true);
33
- }
34
- finally {
35
- cleanup();
36
- }
37
- // After cleanup, the tmp tree is gone and AKM_STASH_DIR is restored.
38
- expect(fs.existsSync(stashDir)).toBe(false);
39
- expect(process.env.AKM_STASH_DIR).toBe(sentinel);
40
- // Restore the test's own prior value rather than the synthetic sentinel.
41
- if (priorAkmStashDir === undefined)
42
- delete process.env.AKM_STASH_DIR;
43
- else
44
- process.env.AKM_STASH_DIR = priorAkmStashDir;
45
- });
46
- test("with { skipIndex: true } does not invoke akm index", () => {
47
- const priorAkmStashDir = process.env.AKM_STASH_DIR;
48
- const { stashDir, cleanup } = loadFixtureStash("minimal", { skipIndex: true });
49
- try {
50
- // The fixture is still materialised and AKM_STASH_DIR is still set.
51
- expect(fs.existsSync(stashDir)).toBe(true);
52
- expect(process.env.AKM_STASH_DIR).toBe(stashDir);
53
- // But the index DB the helper would otherwise have created in the
54
- // isolated XDG_CACHE_HOME is absent — proving no `akm index` ran.
55
- const tmpRoot = path.dirname(stashDir);
56
- const dbPath = path.join(tmpRoot, "cache", "akm", "index.db");
57
- expect(fs.existsSync(dbPath)).toBe(false);
58
- }
59
- finally {
60
- cleanup();
61
- }
62
- if (priorAkmStashDir === undefined)
63
- delete process.env.AKM_STASH_DIR;
64
- else
65
- process.env.AKM_STASH_DIR = priorAkmStashDir;
66
- });
67
- });
68
- describe("fixtureContentHash", () => {
69
- test("is deterministic for the same fixture", () => {
70
- const a = fixtureContentHash("minimal");
71
- const b = fixtureContentHash("minimal");
72
- expect(a).toBe(b);
73
- expect(a).toMatch(/^[0-9a-f]{64}$/);
74
- });
75
- test("computeFixtureContentHash is the same implementation (#250)", () => {
76
- // Critical addendum: there must be exactly one fixture-content hash
77
- // function. Two diverging hash implementations for the same content
78
- // would be a bug.
79
- expect(computeFixtureContentHash).toBe(fixtureContentHash);
80
- expect(computeFixtureContentHash("minimal")).toBe(fixtureContentHash("minimal"));
81
- });
82
- });
83
- describe("listFixtures", () => {
84
- test("returns all shipped fixtures, sorted", () => {
85
- const names = listFixtures();
86
- expect(names).toEqual([
87
- "az-cli",
88
- "docker-homelab",
89
- "drillbit",
90
- "inkwell",
91
- "minimal",
92
- "multi-domain",
93
- "noisy",
94
- "ranking-baseline",
95
- ]);
96
- });
97
- });
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env bun
2
- "use strict";
3
- /**
4
- * Search memories stored in mem0 for relevant context.
5
- *
6
- * @param {string} query - Search query to find relevant memories
7
- * @param {number} limit - Maximum number of results to return
8
- */
9
- const query = process.argv[2] ?? "";
10
- const limit = parseInt(process.argv[3] ?? "10", 10);
11
- console.log(`Searching mem0 for: ${query} (limit: ${limit})`);
12
- // mem0 search implementation would go here
@@ -1,190 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
- import { parseFrontmatter, parseFrontmatterBlock, parseYamlScalar, toStringOrUndefined } from "../src/core/frontmatter";
3
- // ── parseFrontmatter ────────────────────────────────────────────────────────
4
- describe("parseFrontmatter", () => {
5
- test("parses basic frontmatter with key-value pairs", () => {
6
- const raw = "---\ntitle: Hello\ndescription: A test\n---\nBody content\n";
7
- const result = parseFrontmatter(raw);
8
- expect(result.data.title).toBe("Hello");
9
- expect(result.data.description).toBe("A test");
10
- expect(result.content).toBe("Body content\n");
11
- expect(result.frontmatter).not.toBeNull();
12
- });
13
- test("returns empty data and full content when no frontmatter", () => {
14
- const raw = "Just some text\nNo frontmatter here\n";
15
- const result = parseFrontmatter(raw);
16
- expect(result.data).toEqual({});
17
- expect(result.content).toBe(raw);
18
- expect(result.frontmatter).toBeNull();
19
- expect(result.bodyStartLine).toBe(1);
20
- });
21
- test("parses boolean values", () => {
22
- const raw = "---\nenabled: true\ndisabled: false\n---\n";
23
- const result = parseFrontmatter(raw);
24
- expect(result.data.enabled).toBe(true);
25
- expect(result.data.disabled).toBe(false);
26
- });
27
- test("parses numeric values", () => {
28
- const raw = "---\ncount: 42\npi: 3.14\n---\n";
29
- const result = parseFrontmatter(raw);
30
- expect(result.data.count).toBe(42);
31
- expect(result.data.pi).toBe(3.14);
32
- });
33
- test("parses quoted string values", () => {
34
- const raw = "---\ntitle: \"Hello World\"\nsingle: 'test'\n---\n";
35
- const result = parseFrontmatter(raw);
36
- expect(result.data.title).toBe("Hello World");
37
- expect(result.data.single).toBe("test");
38
- });
39
- test("parses nested key-value pairs", () => {
40
- const raw = "---\npolicy:\n allow: Read,Glob\n deny: Write\n---\nBody\n";
41
- const result = parseFrontmatter(raw);
42
- expect(result.data.policy).toEqual({ allow: "Read,Glob", deny: "Write" });
43
- });
44
- test("handles empty frontmatter block", () => {
45
- const raw = "---\n\n---\nBody\n";
46
- const result = parseFrontmatter(raw);
47
- expect(result.data).toEqual({});
48
- expect(result.content).toBe("Body\n");
49
- });
50
- test("handles keys with hyphens", () => {
51
- const raw = "---\nmodel-hint: gpt-4\ntool-policy: allow\n---\n";
52
- const result = parseFrontmatter(raw);
53
- expect(result.data["model-hint"]).toBe("gpt-4");
54
- expect(result.data["tool-policy"]).toBe("allow");
55
- });
56
- test("handles empty value (starts nested object)", () => {
57
- const raw = "---\noptions:\n verbose: true\n---\n";
58
- const result = parseFrontmatter(raw);
59
- expect(result.data.options).toEqual({ verbose: true });
60
- });
61
- test("bodyStartLine is correct", () => {
62
- const raw = "---\ntitle: X\ndesc: Y\n---\nBody\n";
63
- const result = parseFrontmatter(raw);
64
- expect(result.bodyStartLine).toBe(5);
65
- });
66
- test("handles CRLF line endings", () => {
67
- const raw = "---\r\ntitle: Test\r\n---\r\nBody\r\n";
68
- const result = parseFrontmatter(raw);
69
- expect(result.data.title).toBe("Test");
70
- expect(result.content).toContain("Body");
71
- });
72
- // ── List / array support ───────────────────────────────────────────────────
73
- test("parses flow array (inline style)", () => {
74
- const raw = "---\ntags: [ops, networking, deploy]\n---\nBody\n";
75
- const result = parseFrontmatter(raw);
76
- expect(result.data.tags).toEqual(["ops", "networking", "deploy"]);
77
- });
78
- test("parses block-sequence (- item style)", () => {
79
- const raw = "---\ntags:\n- ops\n- networking\n- deploy\n---\nBody\n";
80
- const result = parseFrontmatter(raw);
81
- expect(result.data.tags).toEqual(["ops", "networking", "deploy"]);
82
- });
83
- test("parses block-sequence with 2-space indent", () => {
84
- const raw = "---\ntags:\n - ops\n - networking\n---\nBody\n";
85
- const result = parseFrontmatter(raw);
86
- expect(result.data.tags).toEqual(["ops", "networking"]);
87
- });
88
- test("parses block-sequence with scalar values (bool, number)", () => {
89
- const raw = "---\nvalues:\n- true\n- 42\n- hello\n---\n";
90
- const result = parseFrontmatter(raw);
91
- expect(result.data.values).toEqual([true, 42, "hello"]);
92
- });
93
- test("parses empty flow array", () => {
94
- const raw = "---\ntags: []\n---\n";
95
- const result = parseFrontmatter(raw);
96
- expect(result.data.tags).toEqual([]);
97
- });
98
- test("block sequence followed by another top-level key", () => {
99
- const raw = "---\ntags:\n- ops\n- networking\ndescription: A test\n---\nBody\n";
100
- const result = parseFrontmatter(raw);
101
- expect(result.data.tags).toEqual(["ops", "networking"]);
102
- expect(result.data.description).toBe("A test");
103
- });
104
- test("mixed styles: flow array and block sequence in same document", () => {
105
- const raw = "---\ntags: [ops, networking]\naliases:\n- op\n- net\ndescription: test\n---\n";
106
- const result = parseFrontmatter(raw);
107
- expect(result.data.tags).toEqual(["ops", "networking"]);
108
- expect(result.data.aliases).toEqual(["op", "net"]);
109
- expect(result.data.description).toBe("test");
110
- });
111
- test("empty value with no continuation becomes empty string (backward compat)", () => {
112
- const raw = "---\ntitle: Hello\nempty:\ndescription: test\n---\n";
113
- const result = parseFrontmatter(raw);
114
- expect(result.data.title).toBe("Hello");
115
- expect(result.data.empty).toBe("");
116
- expect(result.data.description).toBe("test");
117
- });
118
- test("single-item block sequence", () => {
119
- const raw = "---\ntags:\n- solo\n---\n";
120
- const result = parseFrontmatter(raw);
121
- expect(result.data.tags).toEqual(["solo"]);
122
- });
123
- });
124
- // ── parseFrontmatterBlock ───────────────────────────────────────────────────
125
- describe("parseFrontmatterBlock", () => {
126
- test("returns null for content without frontmatter delimiters", () => {
127
- expect(parseFrontmatterBlock("No frontmatter")).toBeNull();
128
- });
129
- test("returns null for content that doesn't start with ---", () => {
130
- expect(parseFrontmatterBlock("text\n---\nfoo\n---\n")).toBeNull();
131
- });
132
- test("extracts frontmatter and content correctly", () => {
133
- const result = parseFrontmatterBlock("---\nkey: val\n---\nbody\n");
134
- expect(result).not.toBeNull();
135
- expect(result?.frontmatter).toBe("key: val");
136
- expect(result?.content).toBe("body\n");
137
- });
138
- test("handles frontmatter without trailing content", () => {
139
- const result = parseFrontmatterBlock("---\nkey: val\n---\n");
140
- expect(result).not.toBeNull();
141
- expect(result?.frontmatter).toBe("key: val");
142
- expect(result?.content).toBe("");
143
- });
144
- });
145
- // ── parseYamlScalar ─────────────────────────────────────────────────────────
146
- describe("parseYamlScalar", () => {
147
- test("returns empty string for empty input", () => {
148
- expect(parseYamlScalar("")).toBe("");
149
- });
150
- test("returns boolean for true/false", () => {
151
- expect(parseYamlScalar("true")).toBe(true);
152
- expect(parseYamlScalar("false")).toBe(false);
153
- });
154
- test("returns number for numeric strings", () => {
155
- expect(parseYamlScalar("42")).toBe(42);
156
- expect(parseYamlScalar("3.14")).toBe(3.14);
157
- expect(parseYamlScalar("0")).toBe(0);
158
- expect(parseYamlScalar("-1")).toBe(-1);
159
- });
160
- test("strips quotes from quoted strings", () => {
161
- expect(parseYamlScalar('"hello"')).toBe("hello");
162
- expect(parseYamlScalar("'world'")).toBe("world");
163
- });
164
- test("returns plain string for unquoted non-boolean non-numeric", () => {
165
- expect(parseYamlScalar("hello")).toBe("hello");
166
- expect(parseYamlScalar("some-value")).toBe("some-value");
167
- });
168
- test("does not strip mismatched quotes", () => {
169
- expect(parseYamlScalar("\"hello'")).toBe("\"hello'");
170
- });
171
- });
172
- // ── toStringOrUndefined ─────────────────────────────────────────────────────
173
- describe("toStringOrUndefined", () => {
174
- test("returns string for non-empty string", () => {
175
- expect(toStringOrUndefined("hello")).toBe("hello");
176
- });
177
- test("returns undefined for empty string", () => {
178
- expect(toStringOrUndefined("")).toBeUndefined();
179
- });
180
- test("returns undefined for whitespace-only string", () => {
181
- expect(toStringOrUndefined(" ")).toBeUndefined();
182
- });
183
- test("returns undefined for non-string values", () => {
184
- expect(toStringOrUndefined(42)).toBeUndefined();
185
- expect(toStringOrUndefined(null)).toBeUndefined();
186
- expect(toStringOrUndefined(undefined)).toBeUndefined();
187
- expect(toStringOrUndefined(true)).toBeUndefined();
188
- expect(toStringOrUndefined({})).toBeUndefined();
189
- });
190
- });