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,251 +0,0 @@
1
- import { afterEach, describe, expect, test } from "bun:test";
2
- import { spawnSync } from "node:child_process";
3
- import fs from "node:fs";
4
- import os from "node:os";
5
- import path from "node:path";
6
- // We test the module by importing and mocking its dependencies.
7
- // Since ensureRg calls spawnSync and resolveRg, we mock at the module level.
8
- // ── Helpers ─────────────────────────────────────────────────────────────────
9
- let tmpDirs = [];
10
- function makeTmpDir() {
11
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), "akm-rg-install-test-"));
12
- tmpDirs.push(dir);
13
- return dir;
14
- }
15
- function makeToolchainDir() {
16
- const dir = makeTmpDir();
17
- fs.writeFileSync(path.join(dir, "curl"), '#!/bin/sh\nout=\'\'\nwhile [ $# -gt 0 ]; do\n if [ "$1" = "-o" ]; then\n out=$2\n shift 2\n continue\n fi\n shift\ndone\n/bin/cp "$FAKE_CURL_SOURCE" "$out"\n');
18
- fs.chmodSync(path.join(dir, "curl"), 0o755);
19
- fs.symlinkSync("/usr/bin/tar", path.join(dir, "tar"));
20
- fs.symlinkSync("/usr/bin/gzip", path.join(dir, "gzip"));
21
- return dir;
22
- }
23
- function makeFailingCurlDir() {
24
- const dir = makeTmpDir();
25
- fs.writeFileSync(path.join(dir, "curl"), "#!/bin/sh\necho 'fake curl failure' >&2\nexit 1\n");
26
- fs.chmodSync(path.join(dir, "curl"), 0o755);
27
- return dir;
28
- }
29
- function makeRipgrepTarball() {
30
- const root = makeTmpDir();
31
- const packageDir = path.join(root, "ripgrep-14.1.1-x86_64-unknown-linux-musl");
32
- fs.mkdirSync(packageDir, { recursive: true });
33
- fs.writeFileSync(path.join(packageDir, "rg"), "#!/bin/sh\necho 'ripgrep 14.1.1'\n");
34
- fs.chmodSync(path.join(packageDir, "rg"), 0o755);
35
- const tarballPath = path.join(root, "ripgrep.tar.gz");
36
- const result = spawnSync("tar", ["czf", tarballPath, "-C", root, path.basename(packageDir)], { encoding: "utf8" });
37
- if (result.status !== 0) {
38
- throw new Error(result.stderr || result.error?.message || "Failed to create ripgrep tarball");
39
- }
40
- return tarballPath;
41
- }
42
- afterEach(() => {
43
- for (const dir of tmpDirs) {
44
- fs.rmSync(dir, { recursive: true, force: true });
45
- }
46
- tmpDirs = [];
47
- });
48
- // ── ensureRg – already available ────────────────────────────────────────────
49
- describe("ensureRg", () => {
50
- test("returns existing rg when already available in binDir", async () => {
51
- // Create a fake rg binary so resolveRg finds it
52
- const binDir = makeTmpDir();
53
- const rgPath = path.join(binDir, "rg");
54
- fs.writeFileSync(rgPath, "#!/bin/sh\necho 'ripgrep 14.1.1'\n");
55
- fs.chmodSync(rgPath, 0o755);
56
- // We need to isolate PATH so only our binDir is searched
57
- const origPath = process.env.PATH;
58
- const origXdgCache = process.env.XDG_CACHE_HOME;
59
- const origHome = process.env.HOME;
60
- process.env.PATH = "";
61
- process.env.XDG_CACHE_HOME = makeTmpDir();
62
- try {
63
- const { ensureRg } = await import("../src/setup/ripgrep-install");
64
- const result = ensureRg(binDir);
65
- expect(result.rgPath).toBe(rgPath);
66
- expect(result.installed).toBe(false);
67
- }
68
- finally {
69
- process.env.PATH = origPath;
70
- if (origXdgCache === undefined)
71
- delete process.env.XDG_CACHE_HOME;
72
- else
73
- process.env.XDG_CACHE_HOME = origXdgCache;
74
- if (origHome === undefined)
75
- delete process.env.HOME;
76
- else
77
- process.env.HOME = origHome;
78
- }
79
- });
80
- });
81
- // ── getRgPlatformTarget (tested via ensureRg behavior) ──────────────────────
82
- describe("platform detection", () => {
83
- // We can test this indirectly: ensureRg will throw for unsupported platforms
84
- // We test current platform should be supported (we're running on linux/x64 or similar)
85
- test("current platform is recognized (does not throw unsupported)", async () => {
86
- const binDir = makeTmpDir();
87
- const origPath = process.env.PATH;
88
- const origXdgCache = process.env.XDG_CACHE_HOME;
89
- process.env.PATH = makeFailingCurlDir();
90
- process.env.XDG_CACHE_HOME = makeTmpDir();
91
- try {
92
- const { ensureRg } = await import("../src/setup/ripgrep-install");
93
- // This will try to actually download, so we expect a network error or curl error,
94
- // NOT an "Unsupported platform" error.
95
- try {
96
- ensureRg(binDir);
97
- }
98
- catch (err) {
99
- const message = err.message;
100
- // Should NOT be the unsupported platform error
101
- expect(message).not.toContain("Unsupported platform");
102
- // It should be a download/extraction error since we're not actually downloading
103
- expect(message.includes("Failed to download") ||
104
- message.includes("Failed to extract") ||
105
- message.includes("not found at")).toBe(true);
106
- }
107
- }
108
- finally {
109
- process.env.PATH = origPath;
110
- if (origXdgCache === undefined)
111
- delete process.env.XDG_CACHE_HOME;
112
- else
113
- process.env.XDG_CACHE_HOME = origXdgCache;
114
- }
115
- });
116
- });
117
- // ── getRgVersion (tested via ensureRg result) ───────────────────────────────
118
- describe("getRgVersion", () => {
119
- test("extracts version from rg binary output", async () => {
120
- const binDir = makeTmpDir();
121
- const rgPath = path.join(binDir, "rg");
122
- // Create a script that mimics rg --version output
123
- fs.writeFileSync(rgPath, '#!/bin/sh\necho "ripgrep 14.1.1 (rev abc123)"\n');
124
- fs.chmodSync(rgPath, 0o755);
125
- const origPath = process.env.PATH;
126
- const origXdgCache = process.env.XDG_CACHE_HOME;
127
- process.env.PATH = "";
128
- process.env.XDG_CACHE_HOME = makeTmpDir();
129
- try {
130
- const { ensureRg } = await import("../src/setup/ripgrep-install");
131
- const result = ensureRg(binDir);
132
- expect(result.version).toBe("14.1.1");
133
- expect(result.installed).toBe(false);
134
- }
135
- finally {
136
- process.env.PATH = origPath;
137
- if (origXdgCache === undefined)
138
- delete process.env.XDG_CACHE_HOME;
139
- else
140
- process.env.XDG_CACHE_HOME = origXdgCache;
141
- }
142
- });
143
- test("returns 'unknown' when rg binary does not output version format", async () => {
144
- const binDir = makeTmpDir();
145
- const rgPath = path.join(binDir, "rg");
146
- fs.writeFileSync(rgPath, '#!/bin/sh\necho "something else"\n');
147
- fs.chmodSync(rgPath, 0o755);
148
- const origPath = process.env.PATH;
149
- const origXdgCache = process.env.XDG_CACHE_HOME;
150
- process.env.PATH = "";
151
- process.env.XDG_CACHE_HOME = makeTmpDir();
152
- try {
153
- const { ensureRg } = await import("../src/setup/ripgrep-install");
154
- const result = ensureRg(binDir);
155
- expect(result.version).toBe("unknown");
156
- }
157
- finally {
158
- process.env.PATH = origPath;
159
- if (origXdgCache === undefined)
160
- delete process.env.XDG_CACHE_HOME;
161
- else
162
- process.env.XDG_CACHE_HOME = origXdgCache;
163
- }
164
- });
165
- });
166
- // ── EnsureRgResult shape ────────────────────────────────────────────────────
167
- describe("EnsureRgResult", () => {
168
- test("result has correct shape for existing binary", async () => {
169
- const binDir = makeTmpDir();
170
- const rgPath = path.join(binDir, "rg");
171
- fs.writeFileSync(rgPath, '#!/bin/sh\necho "ripgrep 14.0.0"\n');
172
- fs.chmodSync(rgPath, 0o755);
173
- const origPath = process.env.PATH;
174
- const origXdgCache = process.env.XDG_CACHE_HOME;
175
- process.env.PATH = "";
176
- process.env.XDG_CACHE_HOME = makeTmpDir();
177
- try {
178
- const { ensureRg } = await import("../src/setup/ripgrep-install");
179
- const result = ensureRg(binDir);
180
- expect(typeof result.rgPath).toBe("string");
181
- expect(typeof result.installed).toBe("boolean");
182
- expect(typeof result.version).toBe("string");
183
- }
184
- finally {
185
- process.env.PATH = origPath;
186
- if (origXdgCache === undefined)
187
- delete process.env.XDG_CACHE_HOME;
188
- else
189
- process.env.XDG_CACHE_HOME = origXdgCache;
190
- }
191
- });
192
- });
193
- // ── Download error handling ─────────────────────────────────────────────────
194
- describe("download error handling", () => {
195
- test("creates binDir if it does not exist", async () => {
196
- const parentDir = makeTmpDir();
197
- const binDir = path.join(parentDir, "nested", "bin");
198
- const rgPath = path.join(binDir, "rg");
199
- // Pre-create an rg binary so ensureRg finds it and doesn't try to download
200
- fs.mkdirSync(binDir, { recursive: true });
201
- fs.writeFileSync(rgPath, '#!/bin/sh\necho "ripgrep 14.1.1"\n');
202
- fs.chmodSync(rgPath, 0o755);
203
- const origPath = process.env.PATH;
204
- const origXdgCache = process.env.XDG_CACHE_HOME;
205
- process.env.PATH = "";
206
- process.env.XDG_CACHE_HOME = makeTmpDir();
207
- try {
208
- const { ensureRg } = await import("../src/setup/ripgrep-install");
209
- const result = ensureRg(binDir);
210
- expect(result.rgPath).toBe(rgPath);
211
- expect(result.installed).toBe(false);
212
- }
213
- finally {
214
- process.env.PATH = origPath;
215
- if (origXdgCache === undefined)
216
- delete process.env.XDG_CACHE_HOME;
217
- else
218
- process.env.XDG_CACHE_HOME = origXdgCache;
219
- }
220
- });
221
- test("ensureRg returns installed=true when it installs a new binary", async () => {
222
- const binDir = makeTmpDir();
223
- const origPath = process.env.PATH;
224
- const origXdgCache = process.env.XDG_CACHE_HOME;
225
- const origFakeCurlSource = process.env.FAKE_CURL_SOURCE;
226
- process.env.XDG_CACHE_HOME = makeTmpDir();
227
- process.env.FAKE_CURL_SOURCE = makeRipgrepTarball();
228
- process.env.PATH = makeToolchainDir();
229
- try {
230
- const { ensureRg } = await import("../src/setup/ripgrep-install");
231
- const rgInBin = path.join(binDir, "rg");
232
- if (fs.existsSync(rgInBin))
233
- fs.unlinkSync(rgInBin);
234
- const result = ensureRg(binDir);
235
- expect(result.installed).toBe(true);
236
- expect(result.version).toBe("14.1.1");
237
- expect(fs.existsSync(result.rgPath)).toBe(true);
238
- }
239
- finally {
240
- process.env.PATH = origPath;
241
- if (origXdgCache === undefined)
242
- delete process.env.XDG_CACHE_HOME;
243
- else
244
- process.env.XDG_CACHE_HOME = origXdgCache;
245
- if (origFakeCurlSource === undefined)
246
- delete process.env.FAKE_CURL_SOURCE;
247
- else
248
- process.env.FAKE_CURL_SOURCE = origFakeCurlSource;
249
- }
250
- });
251
- });
@@ -1,108 +0,0 @@
1
- import { afterAll, afterEach, describe, expect, test } from "bun:test";
2
- import fs from "node:fs";
3
- import os from "node:os";
4
- import path from "node:path";
5
- import { isRgAvailable, resolveRg } from "../src/setup/ripgrep-resolve";
6
- // ── Helpers ─────────────────────────────────────────────────────────────────
7
- const tempDirs = [];
8
- function makeTempDir() {
9
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), "akm-rg-"));
10
- tempDirs.push(dir);
11
- return dir;
12
- }
13
- afterAll(() => {
14
- for (const dir of tempDirs) {
15
- fs.rmSync(dir, { recursive: true, force: true });
16
- }
17
- });
18
- const origPath = process.env.PATH;
19
- const origXdgCacheHome = process.env.XDG_CACHE_HOME;
20
- const origHome = process.env.HOME;
21
- afterEach(() => {
22
- if (origPath === undefined) {
23
- delete process.env.PATH;
24
- }
25
- else {
26
- process.env.PATH = origPath;
27
- }
28
- if (origXdgCacheHome === undefined) {
29
- delete process.env.XDG_CACHE_HOME;
30
- }
31
- else {
32
- process.env.XDG_CACHE_HOME = origXdgCacheHome;
33
- }
34
- if (origHome === undefined) {
35
- delete process.env.HOME;
36
- }
37
- else {
38
- process.env.HOME = origHome;
39
- }
40
- });
41
- /** Isolate cache so getBinDir() never finds a real rg binary. */
42
- function isolateCache() {
43
- process.env.XDG_CACHE_HOME = makeTempDir();
44
- }
45
- // ── resolveRg ───────────────────────────────────────────────────────────────
46
- describe("resolveRg", () => {
47
- test("finds rg in provided bin directory", () => {
48
- const binDir = makeTempDir();
49
- const rgPath = path.join(binDir, "rg");
50
- fs.writeFileSync(rgPath, "#!/bin/sh\necho rg\n");
51
- fs.chmodSync(rgPath, 0o755);
52
- const result = resolveRg(binDir);
53
- expect(result).toBe(rgPath);
54
- });
55
- test("falls back to system PATH", () => {
56
- const fakeBinDir = makeTempDir();
57
- const fakeRg = path.join(fakeBinDir, "rg");
58
- fs.writeFileSync(fakeRg, "#!/bin/sh\necho rg\n");
59
- fs.chmodSync(fakeRg, 0o755);
60
- // Put our fake bin dir at the front of PATH
61
- process.env.PATH = `${fakeBinDir}${path.delimiter}${origPath}`;
62
- // No bin dir provided -- should find from PATH
63
- const result = resolveRg();
64
- expect(result).toBeTruthy();
65
- });
66
- test("returns null when not found anywhere", () => {
67
- const emptyDir = makeTempDir();
68
- process.env.PATH = "";
69
- isolateCache();
70
- const result = resolveRg(emptyDir);
71
- expect(result).toBeNull();
72
- });
73
- test("skips non-executable file in bin dir", () => {
74
- const binDir = makeTempDir();
75
- // Create an rg file that is NOT executable
76
- const rgPath = path.join(binDir, "rg");
77
- fs.writeFileSync(rgPath, "not executable");
78
- fs.chmodSync(rgPath, 0o644);
79
- process.env.PATH = "";
80
- isolateCache();
81
- const result = resolveRg(binDir);
82
- expect(result).toBeNull();
83
- });
84
- });
85
- // ── isRgAvailable ───────────────────────────────────────────────────────────
86
- describe("isRgAvailable", () => {
87
- test("returns true when resolveRg finds a binary", () => {
88
- const binDir = makeTempDir();
89
- const rgPath = path.join(binDir, "rg");
90
- fs.writeFileSync(rgPath, "#!/bin/sh\necho rg\n");
91
- fs.chmodSync(rgPath, 0o755);
92
- expect(isRgAvailable(binDir)).toBe(true);
93
- });
94
- test("returns false when resolveRg finds nothing", () => {
95
- const emptyDir = makeTempDir();
96
- process.env.PATH = "";
97
- isolateCache();
98
- expect(isRgAvailable(emptyDir)).toBe(false);
99
- });
100
- test("boolean result matches resolveRg truthiness", () => {
101
- const binDir = makeTempDir();
102
- process.env.PATH = "";
103
- isolateCache();
104
- const resolved = resolveRg(binDir);
105
- const available = isRgAvailable(binDir);
106
- expect(available).toBe(resolved !== null);
107
- });
108
- });
@@ -1,163 +0,0 @@
1
- import { afterAll, expect, test } from "bun:test";
2
- import fs from "node:fs";
3
- import os from "node:os";
4
- import path from "node:path";
5
- import { isRgAvailable, resolveRg } from "../src/setup/ripgrep-resolve";
6
- const createdTmpDirs = [];
7
- function expectDefined(value) {
8
- expect(value).toBeDefined();
9
- if (value === undefined || value === null) {
10
- throw new Error("Expected value to be defined");
11
- }
12
- return value;
13
- }
14
- function tmpDir() {
15
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), "akm-rg-"));
16
- createdTmpDirs.push(dir);
17
- return dir;
18
- }
19
- afterAll(() => {
20
- for (const dir of createdTmpDirs) {
21
- fs.rmSync(dir, { recursive: true, force: true });
22
- }
23
- });
24
- function writeFile(filePath, content = "") {
25
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
26
- fs.writeFileSync(filePath, content);
27
- }
28
- // ── resolveRg ───────────────────────────────────────────────────────────────
29
- test("resolveRg finds system ripgrep on PATH", () => {
30
- const originalPath = process.env.PATH;
31
- const stashDir = tmpDir();
32
- const binDir = path.join(stashDir, "bin");
33
- fs.mkdirSync(binDir, { recursive: true });
34
- // Create a fake rg binary on PATH so the test does not depend on the host environment
35
- const rgName = process.platform === "win32" ? "rg.cmd" : "rg";
36
- const fakeRg = path.join(binDir, rgName);
37
- const scriptContent = process.platform === "win32" ? "@echo off\r\necho fake rg\r\n" : "#!/bin/sh\necho fake rg\n";
38
- fs.writeFileSync(fakeRg, scriptContent);
39
- try {
40
- // Make sure the fake rg is executable where that concept applies
41
- if (process.platform !== "win32") {
42
- fs.chmodSync(fakeRg, 0o755);
43
- }
44
- }
45
- catch {
46
- // Ignore chmod errors on platforms/filesystems that do not support it
47
- }
48
- // Prepend the fake rg directory to PATH for this test only
49
- process.env.PATH = binDir + path.delimiter + (originalPath ?? "");
50
- try {
51
- const rg = resolveRg();
52
- expect(expectDefined(rg)).toContain("rg");
53
- }
54
- finally {
55
- process.env.PATH = originalPath;
56
- }
57
- });
58
- test("resolveRg finds rg in provided bin directory", () => {
59
- const binDir = tmpDir();
60
- // Create a fake rg binary
61
- const fakeRg = path.join(binDir, "rg");
62
- fs.writeFileSync(fakeRg, "#!/bin/sh\necho fake rg\n");
63
- fs.chmodSync(fakeRg, 0o755);
64
- const rg = resolveRg(binDir);
65
- expect(rg).toBe(fakeRg);
66
- });
67
- test("resolveRg skips non-executable files in bin dir", () => {
68
- const binDir = tmpDir();
69
- // Create a non-executable rg file
70
- const fakeRg = path.join(binDir, "rg");
71
- fs.writeFileSync(fakeRg, "not executable");
72
- fs.chmodSync(fakeRg, 0o644);
73
- const rg = resolveRg(binDir);
74
- // Should fall through to system PATH
75
- expect(rg).not.toBe(fakeRg);
76
- });
77
- // ── isRgAvailable ───────────────────────────────────────────────────────────
78
- test("isRgAvailable returns true when rg is on PATH", () => {
79
- const originalPath = process.env.PATH;
80
- const stashDir = tmpDir();
81
- const binDir = path.join(stashDir, "bin");
82
- fs.mkdirSync(binDir, { recursive: true });
83
- const rgName = process.platform === "win32" ? "rg.cmd" : "rg";
84
- const fakeRg = path.join(binDir, rgName);
85
- const scriptContent = process.platform === "win32" ? "@echo off\r\necho fake rg\r\n" : "#!/bin/sh\necho fake rg\n";
86
- fs.writeFileSync(fakeRg, scriptContent);
87
- if (process.platform !== "win32") {
88
- fs.chmodSync(fakeRg, 0o755);
89
- }
90
- process.env.PATH = binDir + path.delimiter + (originalPath ?? "");
91
- try {
92
- expect(isRgAvailable()).toBe(true);
93
- }
94
- finally {
95
- process.env.PATH = originalPath;
96
- }
97
- });
98
- // ── Integration: indexed search pipeline ────────────────────────────────────
99
- test("search pipeline returns ranked results when index exists", async () => {
100
- const stashDir = tmpDir();
101
- for (const sub of ["scripts", "skills", "commands", "agents"]) {
102
- fs.mkdirSync(path.join(stashDir, sub), { recursive: true });
103
- }
104
- // Create scripts with .stash.json metadata
105
- writeFile(path.join(stashDir, "scripts", "docker", "build.sh"), "#!/bin/bash\necho build\n");
106
- writeFile(path.join(stashDir, "scripts", "docker", ".stash.json"), JSON.stringify({
107
- entries: [
108
- {
109
- name: "docker-build",
110
- type: "script",
111
- description: "build docker images",
112
- tags: ["docker", "container"],
113
- filename: "build.sh",
114
- },
115
- ],
116
- }));
117
- writeFile(path.join(stashDir, "scripts", "git", "diff.sh"), "#!/bin/bash\necho diff\n");
118
- writeFile(path.join(stashDir, "scripts", "git", ".stash.json"), JSON.stringify({
119
- entries: [
120
- {
121
- name: "git-diff",
122
- type: "script",
123
- description: "summarize git changes",
124
- tags: ["git", "diff"],
125
- filename: "diff.sh",
126
- },
127
- ],
128
- }));
129
- // Isolation: ensure index cache and config are written to temp directories
130
- const oldXdgCacheHome = process.env.XDG_CACHE_HOME;
131
- const oldXdgConfigHome = process.env.XDG_CONFIG_HOME;
132
- const oldAkmStashDir = process.env.AKM_STASH_DIR;
133
- const tempCacheDir = tmpDir();
134
- const tempConfigDir = tmpDir();
135
- process.env.XDG_CACHE_HOME = tempCacheDir;
136
- process.env.XDG_CONFIG_HOME = tempConfigDir;
137
- try {
138
- // Build index
139
- process.env.AKM_STASH_DIR = stashDir;
140
- const { akmIndex } = await import("../src/indexer/indexer");
141
- await akmIndex({ stashDir });
142
- // Search — TF-IDF should rank docker-related results first
143
- const { akmSearch } = await import("../src/commands/search");
144
- const result = await akmSearch({ query: "docker", type: "any" });
145
- expect(result.hits.length).toBeGreaterThan(0);
146
- // Docker-related result should be ranked first
147
- expect(result.hits[0].name).toContain("docker");
148
- }
149
- finally {
150
- if (oldXdgCacheHome === undefined)
151
- delete process.env.XDG_CACHE_HOME;
152
- else
153
- process.env.XDG_CACHE_HOME = oldXdgCacheHome;
154
- if (oldXdgConfigHome === undefined)
155
- delete process.env.XDG_CONFIG_HOME;
156
- else
157
- process.env.XDG_CONFIG_HOME = oldXdgConfigHome;
158
- if (oldAkmStashDir === undefined)
159
- delete process.env.AKM_STASH_DIR;
160
- else
161
- process.env.AKM_STASH_DIR = oldAkmStashDir;
162
- }
163
- });
@@ -1,94 +0,0 @@
1
- import { afterEach, describe, expect, test } from "bun:test";
2
- import { spawnSync } from "node:child_process";
3
- import fs from "node:fs";
4
- import os from "node:os";
5
- import path from "node:path";
6
- const CLI = path.join(__dirname, "..", "src", "cli.ts");
7
- const tempDirs = [];
8
- function makeTempDir(prefix) {
9
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
10
- tempDirs.push(dir);
11
- return dir;
12
- }
13
- afterEach(() => {
14
- for (const dir of tempDirs.splice(0)) {
15
- fs.rmSync(dir, { recursive: true, force: true });
16
- }
17
- });
18
- function runCli(args, stashDir) {
19
- const xdgCache = makeTempDir("akm-save-cache-");
20
- const xdgConfig = makeTempDir("akm-save-cfg-");
21
- return spawnSync("bun", [CLI, ...args], {
22
- encoding: "utf8",
23
- timeout: 30_000,
24
- env: {
25
- ...process.env,
26
- AKM_STASH_DIR: stashDir,
27
- XDG_CACHE_HOME: xdgCache,
28
- XDG_CONFIG_HOME: xdgConfig,
29
- },
30
- });
31
- }
32
- function parseSaveOutput(stdout) {
33
- return JSON.parse(stdout.trim());
34
- }
35
- /** Initialise a bare git repo in `dir` so akm save can commit. */
36
- function initGitRepo(dir) {
37
- fs.mkdirSync(dir, { recursive: true });
38
- spawnSync("git", ["init", dir], { encoding: "utf8" });
39
- spawnSync("git", ["-C", dir, "config", "commit.gpgsign", "false"], { encoding: "utf8" });
40
- }
41
- describe("akm save", () => {
42
- test("returns skipped when stash is not a git repo", () => {
43
- const stashDir = makeTempDir("akm-save-nongit-");
44
- const result = runCli(["save"], stashDir);
45
- expect(result.status).toBe(0);
46
- const json = parseSaveOutput(result.stdout);
47
- expect(json.skipped).toBe(true);
48
- expect(json.committed).toBe(false);
49
- expect(json.pushed).toBe(false);
50
- });
51
- test("reports nothing to commit on a clean git repo", () => {
52
- const stashDir = makeTempDir("akm-save-clean-");
53
- initGitRepo(stashDir);
54
- // Create an initial commit so the repo is not bare
55
- const f = path.join(stashDir, "README.md");
56
- fs.writeFileSync(f, "hello");
57
- spawnSync("git", ["-C", stashDir, "add", "-A"], { encoding: "utf8" });
58
- spawnSync("git", ["-C", stashDir, "-c", "user.name=test", "-c", "user.email=t@t", "commit", "-m", "init"], {
59
- encoding: "utf8",
60
- });
61
- const result = runCli(["save"], stashDir);
62
- expect(result.status).toBe(0);
63
- const json = parseSaveOutput(result.stdout);
64
- expect(json.committed).toBe(false);
65
- expect(json.skipped).toBe(false);
66
- expect(json.output).toContain("nothing to commit");
67
- });
68
- test("commits changes in a git repo with no remote", () => {
69
- const stashDir = makeTempDir("akm-save-commit-");
70
- initGitRepo(stashDir);
71
- // Write a file so there's something to commit
72
- fs.writeFileSync(path.join(stashDir, "skill.md"), "# Test");
73
- const result = runCli(["save", "-m", "test commit"], stashDir);
74
- expect(result.status).toBe(0);
75
- const json = parseSaveOutput(result.stdout);
76
- expect(json.committed).toBe(true);
77
- expect(json.pushed).toBe(false);
78
- expect(json.skipped).toBe(false);
79
- // Verify the commit actually landed
80
- const log = spawnSync("git", ["-C", stashDir, "log", "--oneline"], { encoding: "utf8" });
81
- expect(log.stdout).toContain("test commit");
82
- });
83
- test("uses timestamp message when -m is omitted", () => {
84
- const stashDir = makeTempDir("akm-save-ts-");
85
- initGitRepo(stashDir);
86
- fs.writeFileSync(path.join(stashDir, "skill.md"), "# Test");
87
- const result = runCli(["save"], stashDir);
88
- expect(result.status).toBe(0);
89
- const json = parseSaveOutput(result.stdout);
90
- expect(json.committed).toBe(true);
91
- const log = spawnSync("git", ["-C", stashDir, "log", "--oneline"], { encoding: "utf8" });
92
- expect(log.stdout).toContain("akm save");
93
- });
94
- });