akm-cli 0.6.0 → 0.7.0-rc1

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 (319) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/dist/{cli.js → src/cli.js} +672 -29
  3. package/dist/{commands → src/commands}/config-cli.js +5 -4
  4. package/dist/src/commands/distill.js +283 -0
  5. package/dist/src/commands/events.js +108 -0
  6. package/dist/src/commands/history.js +120 -0
  7. package/dist/{commands → src/commands}/installed-stashes.js +28 -2
  8. package/dist/src/commands/proposal.js +119 -0
  9. package/dist/src/commands/propose.js +171 -0
  10. package/dist/src/commands/reflect.js +193 -0
  11. package/dist/{commands → src/commands}/registry-search.js +2 -1
  12. package/dist/{commands → src/commands}/remember.js +12 -0
  13. package/dist/{commands → src/commands}/search.js +74 -1
  14. package/dist/{commands → src/commands}/self-update.js +4 -3
  15. package/dist/{commands → src/commands}/show.js +67 -2
  16. package/dist/{core → src/core}/asset-ref.js +5 -5
  17. package/dist/{core → src/core}/asset-spec.js +12 -0
  18. package/dist/{core → src/core}/common.js +1 -1
  19. package/dist/{core → src/core}/config.js +175 -121
  20. package/dist/{core → src/core}/errors.js +4 -0
  21. package/dist/src/core/events.js +239 -0
  22. package/dist/src/core/lesson-lint.js +86 -0
  23. package/dist/src/core/proposals.js +406 -0
  24. package/dist/src/core/warn.js +72 -0
  25. package/dist/{core → src/core}/write-source.js +80 -5
  26. package/dist/{indexer → src/indexer}/db-search.js +119 -27
  27. package/dist/{indexer → src/indexer}/db.js +76 -23
  28. package/dist/{indexer → src/indexer}/file-context.js +0 -3
  29. package/dist/src/indexer/graph-boost.js +179 -0
  30. package/dist/src/indexer/graph-extraction.js +212 -0
  31. package/dist/{indexer → src/indexer}/indexer.js +73 -6
  32. package/dist/src/indexer/memory-inference.js +263 -0
  33. package/dist/{indexer → src/indexer}/metadata.js +114 -11
  34. package/dist/src/integrations/agent/config.js +292 -0
  35. package/dist/src/integrations/agent/detect.js +94 -0
  36. package/dist/src/integrations/agent/index.js +17 -0
  37. package/dist/src/integrations/agent/profiles.js +65 -0
  38. package/dist/src/integrations/agent/prompts.js +167 -0
  39. package/dist/src/integrations/agent/spawn.js +221 -0
  40. package/dist/{integrations → src/integrations}/lockfile.js +0 -26
  41. package/dist/{llm → src/llm}/client.js +33 -2
  42. package/dist/src/llm/feature-gate.js +108 -0
  43. package/dist/src/llm/graph-extract.js +107 -0
  44. package/dist/src/llm/index-passes.js +35 -0
  45. package/dist/src/llm/memory-infer.js +86 -0
  46. package/dist/{output → src/output}/renderers.js +60 -1
  47. package/dist/src/output/shapes.js +516 -0
  48. package/dist/{output → src/output}/text.js +447 -4
  49. package/dist/{registry → src/registry}/build-index.js +14 -4
  50. package/dist/{registry → src/registry}/factory.js +0 -8
  51. package/dist/{registry → src/registry}/providers/static-index.js +3 -2
  52. package/dist/{registry → src/registry}/resolve.js +68 -2
  53. package/dist/{setup → src/setup}/setup.js +43 -5
  54. package/dist/{sources → src/sources}/providers/git.js +7 -15
  55. package/dist/{wiki → src/wiki}/wiki.js +9 -11
  56. package/dist/tests/add-website-source.test.js +119 -0
  57. package/dist/tests/agent/agent-config-loader.test.js +70 -0
  58. package/dist/tests/agent/agent-config.test.js +221 -0
  59. package/dist/tests/agent/agent-detect.test.js +100 -0
  60. package/dist/tests/agent/agent-spawn.test.js +234 -0
  61. package/dist/tests/agent-output.test.js +186 -0
  62. package/dist/tests/architecture/agent-no-llm-sdk-guard.test.js +103 -0
  63. package/dist/tests/architecture/agent-spawn-seam.test.js +193 -0
  64. package/dist/tests/architecture/llm-stateless-seam.test.js +112 -0
  65. package/dist/tests/asset-ref.test.js +192 -0
  66. package/dist/tests/asset-registry.test.js +103 -0
  67. package/dist/tests/asset-spec.test.js +241 -0
  68. package/dist/tests/bench/attribution.test.js +995 -0
  69. package/dist/tests/bench/cleanup-sigint.test.js +83 -0
  70. package/dist/tests/bench/cleanup.js +203 -0
  71. package/dist/tests/bench/cleanup.test.js +166 -0
  72. package/dist/tests/bench/cli.js +683 -0
  73. package/dist/tests/bench/cli.test.js +177 -0
  74. package/dist/tests/bench/compare.test.js +556 -0
  75. package/dist/tests/bench/corpus.js +314 -0
  76. package/dist/tests/bench/corpus.test.js +258 -0
  77. package/dist/tests/bench/driver.js +346 -0
  78. package/dist/tests/bench/driver.test.js +443 -0
  79. package/dist/tests/bench/evolve-metrics.js +179 -0
  80. package/dist/tests/bench/evolve-metrics.test.js +187 -0
  81. package/dist/tests/bench/evolve.js +580 -0
  82. package/dist/tests/bench/evolve.test.js +616 -0
  83. package/dist/tests/bench/failure-modes.test.js +300 -0
  84. package/dist/tests/bench/feedback-integrity.test.js +456 -0
  85. package/dist/tests/bench/leakage.test.js +125 -0
  86. package/dist/tests/bench/learning-curve.test.js +133 -0
  87. package/dist/tests/bench/metrics.js +2319 -0
  88. package/dist/tests/bench/metrics.test.js +1144 -0
  89. package/dist/tests/bench/no-os-tmpdir-invariant.test.js +43 -0
  90. package/dist/tests/bench/report.js +1821 -0
  91. package/dist/tests/bench/report.test.js +989 -0
  92. package/dist/tests/bench/runner.js +536 -0
  93. package/dist/tests/bench/runner.test.js +958 -0
  94. package/dist/tests/bench/search-bridge.test.js +331 -0
  95. package/dist/tests/bench/tmp.js +41 -0
  96. package/dist/tests/bench/trajectory.js +116 -0
  97. package/dist/tests/bench/trajectory.test.js +127 -0
  98. package/dist/tests/bench/verifier.js +109 -0
  99. package/dist/tests/bench/verifier.test.js +118 -0
  100. package/dist/tests/bench/workflow-evaluator.js +557 -0
  101. package/dist/tests/bench/workflow-evaluator.test.js +421 -0
  102. package/dist/tests/bench/workflow-spec.js +358 -0
  103. package/dist/tests/bench/workflow-spec.test.js +363 -0
  104. package/dist/tests/bench/workflow-trace.js +438 -0
  105. package/dist/tests/bench/workflow-trace.test.js +254 -0
  106. package/dist/tests/benchmark-search-quality.js +536 -0
  107. package/dist/tests/benchmark-suite.js +1441 -0
  108. package/dist/tests/capture-cli.test.js +112 -0
  109. package/dist/tests/cli-errors.test.js +203 -0
  110. package/dist/tests/commands/events.test.js +370 -0
  111. package/dist/tests/commands/history.test.js +223 -0
  112. package/dist/tests/commands/import.test.js +103 -0
  113. package/dist/tests/commands/proposal-cli.test.js +209 -0
  114. package/dist/tests/commands/reflect-propose-cli.test.js +333 -0
  115. package/dist/tests/commands/remember.test.js +97 -0
  116. package/dist/tests/commands/scope-flags.test.js +300 -0
  117. package/dist/tests/commands/search.test.js +537 -0
  118. package/dist/tests/commands/show-indexer-parity.test.js +117 -0
  119. package/dist/tests/commands/show.test.js +294 -0
  120. package/dist/tests/common.test.js +266 -0
  121. package/dist/tests/completions.test.js +142 -0
  122. package/dist/tests/config-cli.test.js +193 -0
  123. package/dist/tests/config-llm-features.test.js +139 -0
  124. package/dist/tests/config.test.js +544 -0
  125. package/dist/tests/contracts/migration-baseline.test.js +43 -0
  126. package/dist/tests/contracts/reflect-propose-envelope.test.js +139 -0
  127. package/dist/tests/contracts/spec-helpers.js +46 -0
  128. package/dist/tests/contracts/v1-spec-section-11-proposal-queue.test.js +228 -0
  129. package/dist/tests/contracts/v1-spec-section-12-agent-config.test.js +56 -0
  130. package/dist/tests/contracts/v1-spec-section-13-lesson-type.test.js +34 -0
  131. package/dist/tests/contracts/v1-spec-section-14-llm-features.test.js +94 -0
  132. package/dist/tests/contracts/v1-spec-section-4-1-asset-types.test.js +39 -0
  133. package/dist/tests/contracts/v1-spec-section-4-2-quality-rules.test.js +44 -0
  134. package/dist/tests/contracts/v1-spec-section-5-configuration.test.js +47 -0
  135. package/dist/tests/contracts/v1-spec-section-6-orchestration.test.js +40 -0
  136. package/dist/tests/contracts/v1-spec-section-7-module-layout.test.js +58 -0
  137. package/dist/tests/contracts/v1-spec-section-8-extension-points.test.js +34 -0
  138. package/dist/tests/contracts/v1-spec-section-9-4-cli-surface.test.js +75 -0
  139. package/dist/tests/contracts/v1-spec-section-9-7-llm-agent-boundary.test.js +36 -0
  140. package/dist/tests/core/write-source.test.js +366 -0
  141. package/dist/tests/curate-command.test.js +87 -0
  142. package/dist/tests/db-scoring.test.js +201 -0
  143. package/dist/tests/db.test.js +654 -0
  144. package/dist/tests/distill-cli-flag.test.js +208 -0
  145. package/dist/tests/distill.test.js +515 -0
  146. package/dist/tests/docker-install.test.js +120 -0
  147. package/dist/tests/e2e.test.js +1398 -0
  148. package/dist/tests/embedder.test.js +340 -0
  149. package/dist/tests/embedding-model-config.test.js +379 -0
  150. package/dist/tests/feedback-command.test.js +172 -0
  151. package/dist/tests/file-context.test.js +552 -0
  152. package/dist/tests/fixtures/scripts/git/summarize-diff.js +9 -0
  153. package/dist/tests/fixtures/scripts/lint/eslint-check.js +7 -0
  154. package/dist/tests/fixtures/stashes/load.js +166 -0
  155. package/dist/tests/fixtures/stashes/load.test.js +88 -0
  156. package/dist/tests/fixtures/stashes/ranking-baseline/scripts/mem0-search.js +12 -0
  157. package/dist/tests/frontmatter.test.js +190 -0
  158. package/dist/tests/fts-field-weighting.test.js +254 -0
  159. package/dist/tests/fuzzy-search.test.js +230 -0
  160. package/dist/tests/git-provider-clone.test.js +45 -0
  161. package/dist/tests/github.test.js +161 -0
  162. package/dist/tests/graph-boost-ranking.test.js +305 -0
  163. package/dist/tests/graph-extraction.test.js +282 -0
  164. package/dist/tests/helpers/usage-events.js +8 -0
  165. package/dist/tests/index-pass-llm.test.js +161 -0
  166. package/dist/tests/indexer.test.js +559 -0
  167. package/dist/tests/info-command.test.js +166 -0
  168. package/dist/tests/init.test.js +69 -0
  169. package/dist/tests/install-script.test.js +246 -0
  170. package/dist/tests/integration/agent-real-profile.test.js +94 -0
  171. package/dist/tests/issue-36-repro.test.js +304 -0
  172. package/dist/tests/issues-191-194.test.js +160 -0
  173. package/dist/tests/lesson-lint.test.js +111 -0
  174. package/dist/tests/llm-client.test.js +115 -0
  175. package/dist/tests/llm-feature-gate.test.js +151 -0
  176. package/dist/tests/llm.test.js +139 -0
  177. package/dist/tests/lockfile.test.js +216 -0
  178. package/dist/tests/manifest.test.js +205 -0
  179. package/dist/tests/markdown.test.js +126 -0
  180. package/dist/tests/matchers-unit.test.js +189 -0
  181. package/dist/tests/memory-inference.test.js +299 -0
  182. package/dist/tests/merge-scoring.test.js +136 -0
  183. package/dist/tests/metadata.test.js +313 -0
  184. package/dist/tests/migration-help.test.js +89 -0
  185. package/dist/tests/origin-resolve.test.js +124 -0
  186. package/dist/tests/output-baseline.test.js +217 -0
  187. package/dist/tests/output-shapes-unit.test.js +476 -0
  188. package/dist/tests/parallel-search.test.js +272 -0
  189. package/dist/tests/parameter-metadata.test.js +365 -0
  190. package/dist/tests/paths.test.js +177 -0
  191. package/dist/tests/progressive-disclosure.test.js +280 -0
  192. package/dist/tests/proposals.test.js +279 -0
  193. package/dist/tests/proposed-quality.test.js +271 -0
  194. package/dist/tests/provider-registry.test.js +32 -0
  195. package/dist/tests/ranking-regression.test.js +548 -0
  196. package/dist/tests/reflect-propose.test.js +455 -0
  197. package/dist/tests/registry-build-index.test.js +378 -0
  198. package/dist/tests/registry-cli.test.js +290 -0
  199. package/dist/tests/registry-index-v2.test.js +430 -0
  200. package/dist/tests/registry-install.test.js +728 -0
  201. package/dist/tests/registry-providers/parity.test.js +189 -0
  202. package/dist/tests/registry-providers/skills-sh.test.js +309 -0
  203. package/dist/tests/registry-providers/static-index.test.js +204 -0
  204. package/dist/tests/registry-resolve.test.js +126 -0
  205. package/dist/tests/registry-search.test.js +723 -0
  206. package/dist/tests/remember-frontmatter.test.js +380 -0
  207. package/dist/tests/remember-unit.test.js +123 -0
  208. package/dist/tests/ripgrep-install.test.js +251 -0
  209. package/dist/tests/ripgrep-resolve.test.js +108 -0
  210. package/dist/tests/ripgrep.test.js +163 -0
  211. package/dist/tests/save-command.test.js +94 -0
  212. package/dist/tests/save-trust-qa-fixes.test.js +270 -0
  213. package/dist/tests/scoring-pipeline.test.js +648 -0
  214. package/dist/tests/search-include-proposed-cli.test.js +118 -0
  215. package/dist/tests/self-update.test.js +442 -0
  216. package/dist/tests/semantic-search-e2e.test.js +512 -0
  217. package/dist/tests/semantic-status.test.js +471 -0
  218. package/dist/tests/setup-run.integration.js +877 -0
  219. package/dist/tests/setup-wizard.test.js +198 -0
  220. package/dist/tests/setup.test.js +131 -0
  221. package/dist/tests/source-add.test.js +11 -0
  222. package/dist/tests/source-clone.test.js +254 -0
  223. package/dist/tests/source-manage.test.js +366 -0
  224. package/dist/tests/source-providers/filesystem.test.js +82 -0
  225. package/dist/tests/source-providers/git.test.js +252 -0
  226. package/dist/tests/source-providers/website.test.js +128 -0
  227. package/dist/tests/source-qa-fixes.test.js +268 -0
  228. package/dist/tests/source-registry.test.js +350 -0
  229. package/dist/tests/source-resolve.test.js +100 -0
  230. package/dist/tests/source-source.test.js +221 -0
  231. package/dist/tests/source.test.js +533 -0
  232. package/dist/tests/tar-utils-scan.test.js +73 -0
  233. package/dist/tests/toggle-components.test.js +73 -0
  234. package/dist/tests/usage-telemetry.test.js +265 -0
  235. package/dist/tests/utility-scoring.test.js +558 -0
  236. package/dist/tests/vault-load-error.test.js +78 -0
  237. package/dist/tests/vault-qa-fixes.test.js +194 -0
  238. package/dist/tests/vault.test.js +429 -0
  239. package/dist/tests/vector-search.test.js +608 -0
  240. package/dist/tests/walker.test.js +252 -0
  241. package/dist/tests/wave2-cluster-bc.test.js +228 -0
  242. package/dist/tests/wave2-cluster-d.test.js +180 -0
  243. package/dist/tests/wave2-cluster-e.test.js +179 -0
  244. package/dist/tests/wiki-qa-fixes.test.js +270 -0
  245. package/dist/tests/wiki.test.js +529 -0
  246. package/dist/tests/workflow-cli.test.js +271 -0
  247. package/dist/tests/workflow-markdown.test.js +171 -0
  248. package/dist/tests/workflow-path-escape.test.js +132 -0
  249. package/dist/tests/workflow-qa-fixes.test.js +377 -0
  250. package/dist/tests/workflows/indexer-rejection.test.js +213 -0
  251. package/docs/README.md +8 -0
  252. package/docs/migration/release-notes/0.7.0.md +244 -0
  253. package/package.json +2 -2
  254. package/dist/core/warn.js +0 -27
  255. package/dist/output/shapes.js +0 -212
  256. /package/dist/{commands → src/commands}/completions.js +0 -0
  257. /package/dist/{commands → src/commands}/curate.js +0 -0
  258. /package/dist/{commands → src/commands}/info.js +0 -0
  259. /package/dist/{commands → src/commands}/init.js +0 -0
  260. /package/dist/{commands → src/commands}/install-audit.js +0 -0
  261. /package/dist/{commands → src/commands}/migration-help.js +0 -0
  262. /package/dist/{commands → src/commands}/source-add.js +0 -0
  263. /package/dist/{commands → src/commands}/source-clone.js +0 -0
  264. /package/dist/{commands → src/commands}/source-manage.js +0 -0
  265. /package/dist/{commands → src/commands}/vault.js +0 -0
  266. /package/dist/{core → src/core}/asset-registry.js +0 -0
  267. /package/dist/{core → src/core}/frontmatter.js +0 -0
  268. /package/dist/{core → src/core}/markdown.js +0 -0
  269. /package/dist/{core → src/core}/paths.js +0 -0
  270. /package/dist/{indexer → src/indexer}/manifest.js +0 -0
  271. /package/dist/{indexer → src/indexer}/matchers.js +0 -0
  272. /package/dist/{indexer → src/indexer}/search-fields.js +0 -0
  273. /package/dist/{indexer → src/indexer}/search-source.js +0 -0
  274. /package/dist/{indexer → src/indexer}/semantic-status.js +0 -0
  275. /package/dist/{indexer → src/indexer}/usage-events.js +0 -0
  276. /package/dist/{indexer → src/indexer}/walker.js +0 -0
  277. /package/dist/{integrations → src/integrations}/github.js +0 -0
  278. /package/dist/{llm → src/llm}/embedder.js +0 -0
  279. /package/dist/{llm → src/llm}/embedders/cache.js +0 -0
  280. /package/dist/{llm → src/llm}/embedders/local.js +0 -0
  281. /package/dist/{llm → src/llm}/embedders/remote.js +0 -0
  282. /package/dist/{llm → src/llm}/embedders/types.js +0 -0
  283. /package/dist/{llm → src/llm}/metadata-enhance.js +0 -0
  284. /package/dist/{output → src/output}/cli-hints.js +0 -0
  285. /package/dist/{output → src/output}/context.js +0 -0
  286. /package/dist/{registry → src/registry}/create-provider-registry.js +0 -0
  287. /package/dist/{registry → src/registry}/origin-resolve.js +0 -0
  288. /package/dist/{registry → src/registry}/providers/index.js +0 -0
  289. /package/dist/{registry → src/registry}/providers/skills-sh.js +0 -0
  290. /package/dist/{registry → src/registry}/providers/types.js +0 -0
  291. /package/dist/{registry → src/registry}/types.js +0 -0
  292. /package/dist/{setup → src/setup}/detect.js +0 -0
  293. /package/dist/{setup → src/setup}/ripgrep-install.js +0 -0
  294. /package/dist/{setup → src/setup}/ripgrep-resolve.js +0 -0
  295. /package/dist/{setup → src/setup}/steps.js +0 -0
  296. /package/dist/{sources → src/sources}/include.js +0 -0
  297. /package/dist/{sources → src/sources}/provider-factory.js +0 -0
  298. /package/dist/{sources → src/sources}/provider.js +0 -0
  299. /package/dist/{sources → src/sources}/providers/filesystem.js +0 -0
  300. /package/dist/{sources → src/sources}/providers/index.js +0 -0
  301. /package/dist/{sources → src/sources}/providers/install-types.js +0 -0
  302. /package/dist/{sources → src/sources}/providers/npm.js +0 -0
  303. /package/dist/{sources → src/sources}/providers/provider-utils.js +0 -0
  304. /package/dist/{sources → src/sources}/providers/sync-from-ref.js +0 -0
  305. /package/dist/{sources → src/sources}/providers/tar-utils.js +0 -0
  306. /package/dist/{sources → src/sources}/providers/website.js +0 -0
  307. /package/dist/{sources → src/sources}/resolve.js +0 -0
  308. /package/dist/{sources → src/sources}/types.js +0 -0
  309. /package/dist/{templates → src/templates}/wiki-templates.js +0 -0
  310. /package/dist/{version.js → src/version.js} +0 -0
  311. /package/dist/{workflows → src/workflows}/authoring.js +0 -0
  312. /package/dist/{workflows → src/workflows}/cli.js +0 -0
  313. /package/dist/{workflows → src/workflows}/db.js +0 -0
  314. /package/dist/{workflows → src/workflows}/document-cache.js +0 -0
  315. /package/dist/{workflows → src/workflows}/parser.js +0 -0
  316. /package/dist/{workflows → src/workflows}/renderer.js +0 -0
  317. /package/dist/{workflows → src/workflows}/runs.js +0 -0
  318. /package/dist/{workflows → src/workflows}/schema.js +0 -0
  319. /package/dist/{workflows → src/workflows}/validator.js +0 -0
@@ -0,0 +1,217 @@
1
+ import { afterEach, describe, expect, test } from "bun:test";
2
+ import { spawn, spawnSync } from "node:child_process";
3
+ import fs from "node:fs";
4
+ import http from "node:http";
5
+ import os from "node:os";
6
+ import path from "node:path";
7
+ const CLI = path.join(__dirname, "..", "src", "cli.ts");
8
+ const tempDirs = [];
9
+ function makeTempDir(prefix) {
10
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
11
+ tempDirs.push(dir);
12
+ return dir;
13
+ }
14
+ function writeFile(filePath, content) {
15
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
16
+ fs.writeFileSync(filePath, content);
17
+ }
18
+ function writeConfig(configDir, config) {
19
+ const configPath = path.join(configDir, "akm", "config.json");
20
+ fs.mkdirSync(path.dirname(configPath), { recursive: true });
21
+ fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`);
22
+ }
23
+ function runCli(stashDir, args, config) {
24
+ const xdgCache = makeTempDir("akm-output-cache-");
25
+ const xdgConfig = makeTempDir("akm-output-config-");
26
+ if (config)
27
+ writeConfig(xdgConfig, config);
28
+ const result = spawnSync("bun", [CLI, ...args], {
29
+ encoding: "utf8",
30
+ timeout: 30_000,
31
+ env: {
32
+ ...process.env,
33
+ AKM_STASH_DIR: stashDir,
34
+ XDG_CACHE_HOME: xdgCache,
35
+ XDG_CONFIG_HOME: xdgConfig,
36
+ },
37
+ });
38
+ expect(result.status).toBe(0);
39
+ return result.stdout.trim();
40
+ }
41
+ async function runCliAsync(stashDir, args, config) {
42
+ const xdgCache = makeTempDir("akm-output-cache-");
43
+ const xdgConfig = makeTempDir("akm-output-config-");
44
+ if (config)
45
+ writeConfig(xdgConfig, config);
46
+ const child = spawn("bun", [CLI, ...args], {
47
+ stdio: ["ignore", "pipe", "pipe"],
48
+ env: {
49
+ ...process.env,
50
+ AKM_STASH_DIR: stashDir,
51
+ XDG_CACHE_HOME: xdgCache,
52
+ XDG_CONFIG_HOME: xdgConfig,
53
+ },
54
+ });
55
+ let stdout = "";
56
+ let stderr = "";
57
+ child.stdout.on("data", (chunk) => {
58
+ stdout += String(chunk);
59
+ });
60
+ child.stderr.on("data", (chunk) => {
61
+ stderr += String(chunk);
62
+ });
63
+ const exitCode = await new Promise((resolve, reject) => {
64
+ child.on("error", reject);
65
+ child.on("close", (code) => resolve(code ?? 1));
66
+ });
67
+ expect(exitCode).toBe(0);
68
+ if (stderr.trim()) {
69
+ expect(stderr.trim()).toBe("");
70
+ }
71
+ return stdout.trim();
72
+ }
73
+ afterEach(() => {
74
+ for (const dir of tempDirs.splice(0)) {
75
+ fs.rmSync(dir, { recursive: true, force: true });
76
+ }
77
+ });
78
+ describe("output baseline", () => {
79
+ test("search default JSON brief shape stays stable", () => {
80
+ const stashDir = makeTempDir("akm-output-stash-");
81
+ writeFile(path.join(stashDir, "agents", "architect.md"), "---\ndescription: This is a deliberately long agent description that should be truncated in brief search output so the default response stays compact and easy to scan for both humans and agents.\n---\nYou are an architect.\n");
82
+ const output = runCli(stashDir, ["search", "architect", "--format=json"]);
83
+ const json = JSON.parse(output);
84
+ // hits is always present; warnings may appear when semantic search is pending
85
+ expect(Object.keys(json)).toContain("hits");
86
+ expect(Object.keys(json.hits[0] ?? {}).sort()).toEqual(["action", "estimatedTokens", "name", "type"]);
87
+ });
88
+ test("search normal detail includes description capped at 250 characters", () => {
89
+ const stashDir = makeTempDir("akm-output-stash-");
90
+ const description = "This is a deliberately long agent description that should be truncated at the normal detail level. It contains enough words to exceed two hundred and fifty characters so we can verify the cap is applied correctly by the CLI output shaping logic and does not let full descriptions through.";
91
+ writeFile(path.join(stashDir, "agents", "architect.md"), `---\ndescription: ${description}\n---\nYou are an architect.\n`);
92
+ const output = runCli(stashDir, ["search", "architect", "--format=json", "--detail=normal"]);
93
+ const json = JSON.parse(output);
94
+ expect(json.hits[0]?.score).toBeDefined();
95
+ expect(typeof json.hits[0]?.description).toBe("string");
96
+ expect(String(json.hits[0]?.description).length).toBeLessThanOrEqual(253); // 250 + "..."
97
+ expect(Object.keys(json.hits[0] ?? {})).not.toContain("ref");
98
+ });
99
+ test("search text output includes score for local hits at normal detail", () => {
100
+ const stashDir = makeTempDir("akm-output-stash-");
101
+ writeFile(path.join(stashDir, "scripts", "deploy.sh"), "#!/usr/bin/env bash\necho deploy\n");
102
+ const output = runCli(stashDir, ["search", "deploy", "--format=text", "--detail=normal"]);
103
+ expect(output).toContain("score:");
104
+ expect(output).toContain("action: akm show");
105
+ });
106
+ test("show default JSON shape stays stable", () => {
107
+ const stashDir = makeTempDir("akm-output-stash-");
108
+ writeFile(path.join(stashDir, "commands", "release.md"), "---\ndescription: Release\n---\nRun release {{version}}\n");
109
+ const output = runCli(stashDir, ["show", "command:release.md", "--format=json"]);
110
+ const json = JSON.parse(output);
111
+ // QA #7: path and editable are now always projected in JSON shape
112
+ expect(Object.keys(json).sort()).toEqual([
113
+ "action",
114
+ "description",
115
+ "editable",
116
+ "name",
117
+ "origin",
118
+ "parameters",
119
+ "path",
120
+ "template",
121
+ "type",
122
+ ]);
123
+ expect(json.origin).toBeNull();
124
+ });
125
+ test("show text output includes null origin for local assets", () => {
126
+ const stashDir = makeTempDir("akm-output-stash-");
127
+ writeFile(path.join(stashDir, "scripts", "deploy.sh"), "#!/usr/bin/env bash\necho deploy\n");
128
+ const output = runCli(stashDir, ["show", "script:deploy.sh", "--format=text"]);
129
+ expect(output).toContain("# origin: null");
130
+ expect(output).toContain("run:");
131
+ });
132
+ test("show shaped output includes action across all asset types", () => {
133
+ const stashDir = makeTempDir("akm-output-stash-");
134
+ writeFile(path.join(stashDir, "scripts", "deploy.sh"), "#!/usr/bin/env bash\necho deploy\n");
135
+ writeFile(path.join(stashDir, "skills", "ops", "SKILL.md"), "# Ops\nFollow this.\n");
136
+ writeFile(path.join(stashDir, "commands", "release.md"), "---\ndescription: Release\n---\nRun release {{version}}\n");
137
+ writeFile(path.join(stashDir, "agents", "coach.md"), "---\ndescription: Coach\n---\nYou are a coach.\n");
138
+ writeFile(path.join(stashDir, "knowledge", "guide.md"), "# Guide\nUse this.\n");
139
+ const refs = ["script:deploy.sh", "skill:ops", "command:release.md", "agent:coach.md", "knowledge:guide.md"];
140
+ for (const ref of refs) {
141
+ const output = runCli(stashDir, ["show", ref, "--format=json"]);
142
+ const json = JSON.parse(output);
143
+ expect(json.origin).toBeNull();
144
+ expect(typeof json.action).toBe("string");
145
+ expect(String(json.action).length).toBeGreaterThan(0);
146
+ }
147
+ });
148
+ test("show full JSON shape keeps schemaVersion gated to full detail", () => {
149
+ const stashDir = makeTempDir("akm-output-stash-");
150
+ writeFile(path.join(stashDir, "scripts", "deploy.sh"), "#!/usr/bin/env bash\necho deploy\n");
151
+ const output = runCli(stashDir, ["show", "script:deploy.sh", "--format=json", "--detail=full"]);
152
+ const json = JSON.parse(output);
153
+ expect(json.schemaVersion).toBe(1);
154
+ expect(Object.keys(json)).toContain("path");
155
+ expect(Object.keys(json)).toContain("editable");
156
+ });
157
+ test("config defaults drive output mode and CLI flags override them", () => {
158
+ const stashDir = makeTempDir("akm-output-stash-");
159
+ writeFile(path.join(stashDir, "scripts", "deploy.sh"), "#!/usr/bin/env bash\necho deploy\n");
160
+ const config = { output: { format: "text", detail: "normal" } };
161
+ const configDriven = runCli(stashDir, ["search", "deploy"], config);
162
+ expect(configDriven).toContain("score:");
163
+ const overridden = runCli(stashDir, ["search", "deploy", "--format=json", "--detail=brief"], config);
164
+ const json = JSON.parse(overridden);
165
+ // hits is always present; warnings may appear when semantic search is pending
166
+ expect(Object.keys(json)).toContain("hits");
167
+ expect(Object.keys(json.hits[0] ?? {})).not.toContain("origin");
168
+ });
169
+ test("search shaped output includes action for local and registry hits", async () => {
170
+ const stashDir = makeTempDir("akm-output-stash-");
171
+ const registryDir = makeTempDir("akm-output-registry-");
172
+ writeFile(path.join(stashDir, "scripts", "deploy.sh"), "#!/usr/bin/env bash\necho deploy\n");
173
+ writeFile(path.join(registryDir, "index.json"), JSON.stringify({
174
+ version: 3,
175
+ updatedAt: "2026-03-11T00:00:00Z",
176
+ stashes: [
177
+ {
178
+ id: "npm:@scope/deploy-stash",
179
+ name: "deploy-stash",
180
+ description: "Registry deploy stash",
181
+ ref: "@scope/deploy-stash",
182
+ source: "npm",
183
+ tags: ["deploy"],
184
+ },
185
+ ],
186
+ }));
187
+ const server = http.createServer((req, res) => {
188
+ if (req.url === "/index.json") {
189
+ res.writeHead(200, { "Content-Type": "application/json" });
190
+ res.end(fs.readFileSync(path.join(registryDir, "index.json"), "utf8"));
191
+ return;
192
+ }
193
+ res.writeHead(404);
194
+ res.end("not found");
195
+ });
196
+ await new Promise((resolve) => server.listen(0, "127.0.0.1", () => resolve()));
197
+ const address = server.address();
198
+ if (!address || typeof address === "string") {
199
+ throw new Error("Failed to start test registry server");
200
+ }
201
+ try {
202
+ const output = await runCliAsync(stashDir, ["search", "deploy", "--format=json", "--detail=brief", "--source=both"], {
203
+ registries: [{ url: `http://127.0.0.1:${address.port}/index.json` }],
204
+ });
205
+ const json = JSON.parse(output);
206
+ // Brief local hits have type; registry hits are in registryHits
207
+ const localHit = json.hits.find((hit) => hit.type === "script");
208
+ const registryHit = (json.registryHits ?? []).find((hit) => hit.name === "deploy-stash");
209
+ expect(localHit?.action).toBeTruthy();
210
+ // QA #28: registry brief no longer includes action (use installRef instead)
211
+ expect(registryHit?.name).toBeTruthy();
212
+ }
213
+ finally {
214
+ await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
215
+ }
216
+ });
217
+ });