akm-cli 0.7.0 → 0.7.1

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 (327) hide show
  1. package/package.json +8 -8
  2. package/dist/tests/add-website-source.test.js +0 -119
  3. package/dist/tests/agent/agent-config-loader.test.js +0 -70
  4. package/dist/tests/agent/agent-config.test.js +0 -221
  5. package/dist/tests/agent/agent-detect.test.js +0 -100
  6. package/dist/tests/agent/agent-spawn.test.js +0 -234
  7. package/dist/tests/agent-output.test.js +0 -186
  8. package/dist/tests/architecture/agent-no-llm-sdk-guard.test.js +0 -103
  9. package/dist/tests/architecture/agent-spawn-seam.test.js +0 -193
  10. package/dist/tests/architecture/llm-stateless-seam.test.js +0 -112
  11. package/dist/tests/asset-ref.test.js +0 -192
  12. package/dist/tests/asset-registry.test.js +0 -103
  13. package/dist/tests/asset-spec.test.js +0 -241
  14. package/dist/tests/bench/attribution.test.js +0 -996
  15. package/dist/tests/bench/cleanup-sigint.test.js +0 -83
  16. package/dist/tests/bench/cleanup.js +0 -234
  17. package/dist/tests/bench/cleanup.test.js +0 -166
  18. package/dist/tests/bench/cli.js +0 -1018
  19. package/dist/tests/bench/cli.test.js +0 -445
  20. package/dist/tests/bench/compare.test.js +0 -556
  21. package/dist/tests/bench/corpus.js +0 -317
  22. package/dist/tests/bench/corpus.test.js +0 -258
  23. package/dist/tests/bench/doctor.js +0 -525
  24. package/dist/tests/bench/driver.js +0 -401
  25. package/dist/tests/bench/driver.test.js +0 -584
  26. package/dist/tests/bench/environment.js +0 -233
  27. package/dist/tests/bench/environment.test.js +0 -199
  28. package/dist/tests/bench/evolve-metrics.js +0 -179
  29. package/dist/tests/bench/evolve-metrics.test.js +0 -187
  30. package/dist/tests/bench/evolve.js +0 -647
  31. package/dist/tests/bench/evolve.test.js +0 -624
  32. package/dist/tests/bench/failure-modes.test.js +0 -349
  33. package/dist/tests/bench/feedback-integrity.test.js +0 -457
  34. package/dist/tests/bench/leakage.test.js +0 -228
  35. package/dist/tests/bench/learning-curve.test.js +0 -134
  36. package/dist/tests/bench/metrics.js +0 -2395
  37. package/dist/tests/bench/metrics.test.js +0 -1150
  38. package/dist/tests/bench/no-os-tmpdir-invariant.test.js +0 -43
  39. package/dist/tests/bench/opencode-config.js +0 -194
  40. package/dist/tests/bench/opencode-config.test.js +0 -370
  41. package/dist/tests/bench/report.js +0 -1885
  42. package/dist/tests/bench/report.test.js +0 -1038
  43. package/dist/tests/bench/run-config.js +0 -355
  44. package/dist/tests/bench/run-config.test.js +0 -298
  45. package/dist/tests/bench/run-curate-test.js +0 -32
  46. package/dist/tests/bench/run-failing-tasks.js +0 -56
  47. package/dist/tests/bench/run-full-bench.js +0 -51
  48. package/dist/tests/bench/run-items36-targeted.js +0 -69
  49. package/dist/tests/bench/run-nano-quick.js +0 -42
  50. package/dist/tests/bench/run-waveg-targeted.js +0 -62
  51. package/dist/tests/bench/runner.js +0 -699
  52. package/dist/tests/bench/runner.test.js +0 -958
  53. package/dist/tests/bench/search-bridge.test.js +0 -331
  54. package/dist/tests/bench/tmp.js +0 -131
  55. package/dist/tests/bench/trajectory.js +0 -116
  56. package/dist/tests/bench/trajectory.test.js +0 -127
  57. package/dist/tests/bench/verifier.js +0 -114
  58. package/dist/tests/bench/verifier.test.js +0 -118
  59. package/dist/tests/bench/workflow-evaluator.js +0 -557
  60. package/dist/tests/bench/workflow-evaluator.test.js +0 -421
  61. package/dist/tests/bench/workflow-spec.js +0 -345
  62. package/dist/tests/bench/workflow-spec.test.js +0 -363
  63. package/dist/tests/bench/workflow-trace.js +0 -472
  64. package/dist/tests/bench/workflow-trace.test.js +0 -254
  65. package/dist/tests/benchmark-search-quality.js +0 -536
  66. package/dist/tests/benchmark-suite.js +0 -1441
  67. package/dist/tests/capture-cli.test.js +0 -112
  68. package/dist/tests/cli-errors.test.js +0 -204
  69. package/dist/tests/commands/events.test.js +0 -370
  70. package/dist/tests/commands/history.test.js +0 -418
  71. package/dist/tests/commands/import.test.js +0 -103
  72. package/dist/tests/commands/proposal-cli.test.js +0 -209
  73. package/dist/tests/commands/reflect-propose-cli.test.js +0 -333
  74. package/dist/tests/commands/remember.test.js +0 -97
  75. package/dist/tests/commands/scope-flags.test.js +0 -300
  76. package/dist/tests/commands/search.test.js +0 -537
  77. package/dist/tests/commands/show-indexer-parity.test.js +0 -117
  78. package/dist/tests/commands/show.test.js +0 -294
  79. package/dist/tests/common.test.js +0 -266
  80. package/dist/tests/completions.test.js +0 -142
  81. package/dist/tests/config-cli.test.js +0 -193
  82. package/dist/tests/config-llm-features.test.js +0 -139
  83. package/dist/tests/config.test.js +0 -569
  84. package/dist/tests/contracts/migration-baseline.test.js +0 -43
  85. package/dist/tests/contracts/reflect-propose-envelope.test.js +0 -139
  86. package/dist/tests/contracts/spec-helpers.js +0 -46
  87. package/dist/tests/contracts/v1-spec-section-11-proposal-queue.test.js +0 -228
  88. package/dist/tests/contracts/v1-spec-section-12-agent-config.test.js +0 -56
  89. package/dist/tests/contracts/v1-spec-section-13-lesson-type.test.js +0 -34
  90. package/dist/tests/contracts/v1-spec-section-14-llm-features.test.js +0 -94
  91. package/dist/tests/contracts/v1-spec-section-4-1-asset-types.test.js +0 -39
  92. package/dist/tests/contracts/v1-spec-section-4-2-quality-rules.test.js +0 -44
  93. package/dist/tests/contracts/v1-spec-section-5-configuration.test.js +0 -47
  94. package/dist/tests/contracts/v1-spec-section-6-orchestration.test.js +0 -40
  95. package/dist/tests/contracts/v1-spec-section-7-module-layout.test.js +0 -58
  96. package/dist/tests/contracts/v1-spec-section-8-extension-points.test.js +0 -34
  97. package/dist/tests/contracts/v1-spec-section-9-4-cli-surface.test.js +0 -75
  98. package/dist/tests/contracts/v1-spec-section-9-7-llm-agent-boundary.test.js +0 -36
  99. package/dist/tests/core/write-source.test.js +0 -366
  100. package/dist/tests/curate-command.test.js +0 -87
  101. package/dist/tests/db-scoring.test.js +0 -201
  102. package/dist/tests/db.test.js +0 -654
  103. package/dist/tests/distill-cli-flag.test.js +0 -208
  104. package/dist/tests/distill.test.js +0 -515
  105. package/dist/tests/docker-install.test.js +0 -120
  106. package/dist/tests/e2e.test.js +0 -1419
  107. package/dist/tests/embedder.test.js +0 -340
  108. package/dist/tests/embedding-model-config.test.js +0 -379
  109. package/dist/tests/feedback-command.test.js +0 -172
  110. package/dist/tests/file-context.test.js +0 -552
  111. package/dist/tests/fixtures/scripts/git/summarize-diff.js +0 -9
  112. package/dist/tests/fixtures/scripts/lint/eslint-check.js +0 -7
  113. package/dist/tests/fixtures/stashes/load.js +0 -166
  114. package/dist/tests/fixtures/stashes/load.test.js +0 -97
  115. package/dist/tests/fixtures/stashes/ranking-baseline/scripts/mem0-search.js +0 -12
  116. package/dist/tests/frontmatter.test.js +0 -190
  117. package/dist/tests/fts-field-weighting.test.js +0 -254
  118. package/dist/tests/fuzzy-search.test.js +0 -230
  119. package/dist/tests/git-provider-clone.test.js +0 -45
  120. package/dist/tests/github.test.js +0 -161
  121. package/dist/tests/graph-boost-ranking.test.js +0 -305
  122. package/dist/tests/graph-extraction.test.js +0 -282
  123. package/dist/tests/helpers/usage-events.js +0 -8
  124. package/dist/tests/index-pass-llm.test.js +0 -161
  125. package/dist/tests/indexer.test.js +0 -570
  126. package/dist/tests/info-command.test.js +0 -166
  127. package/dist/tests/init.test.js +0 -69
  128. package/dist/tests/install-script.test.js +0 -246
  129. package/dist/tests/integration/agent-real-profile.test.js +0 -94
  130. package/dist/tests/issue-36-repro.test.js +0 -304
  131. package/dist/tests/issues-191-194.test.js +0 -160
  132. package/dist/tests/lesson-lint.test.js +0 -111
  133. package/dist/tests/llm-client.test.js +0 -115
  134. package/dist/tests/llm-feature-gate.test.js +0 -151
  135. package/dist/tests/llm.test.js +0 -139
  136. package/dist/tests/lockfile.test.js +0 -216
  137. package/dist/tests/manifest.test.js +0 -205
  138. package/dist/tests/markdown.test.js +0 -126
  139. package/dist/tests/matchers-unit.test.js +0 -189
  140. package/dist/tests/memory-inference.test.js +0 -299
  141. package/dist/tests/merge-scoring.test.js +0 -136
  142. package/dist/tests/metadata.test.js +0 -313
  143. package/dist/tests/migration-help.test.js +0 -89
  144. package/dist/tests/origin-resolve.test.js +0 -124
  145. package/dist/tests/output-baseline.test.js +0 -218
  146. package/dist/tests/output-shapes-unit.test.js +0 -478
  147. package/dist/tests/parallel-search.test.js +0 -272
  148. package/dist/tests/parameter-metadata.test.js +0 -365
  149. package/dist/tests/paths.test.js +0 -177
  150. package/dist/tests/progressive-disclosure.test.js +0 -280
  151. package/dist/tests/proposals.test.js +0 -279
  152. package/dist/tests/proposed-quality.test.js +0 -271
  153. package/dist/tests/provider-registry.test.js +0 -32
  154. package/dist/tests/ranking-regression.test.js +0 -548
  155. package/dist/tests/reflect-propose.test.js +0 -455
  156. package/dist/tests/registry-build-index.test.js +0 -394
  157. package/dist/tests/registry-cli.test.js +0 -290
  158. package/dist/tests/registry-index-v2.test.js +0 -430
  159. package/dist/tests/registry-install.test.js +0 -728
  160. package/dist/tests/registry-providers/parity.test.js +0 -189
  161. package/dist/tests/registry-providers/skills-sh.test.js +0 -309
  162. package/dist/tests/registry-providers/static-index.test.js +0 -238
  163. package/dist/tests/registry-resolve.test.js +0 -126
  164. package/dist/tests/registry-search.test.js +0 -923
  165. package/dist/tests/remember-frontmatter.test.js +0 -378
  166. package/dist/tests/remember-unit.test.js +0 -123
  167. package/dist/tests/ripgrep-install.test.js +0 -251
  168. package/dist/tests/ripgrep-resolve.test.js +0 -108
  169. package/dist/tests/ripgrep.test.js +0 -163
  170. package/dist/tests/save-command.test.js +0 -94
  171. package/dist/tests/save-trust-qa-fixes.test.js +0 -270
  172. package/dist/tests/scoring-pipeline.test.js +0 -648
  173. package/dist/tests/search-include-proposed-cli.test.js +0 -118
  174. package/dist/tests/self-update.test.js +0 -442
  175. package/dist/tests/semantic-search-e2e.test.js +0 -512
  176. package/dist/tests/semantic-status.test.js +0 -471
  177. package/dist/tests/setup-run.integration.js +0 -877
  178. package/dist/tests/setup-wizard.test.js +0 -198
  179. package/dist/tests/setup.test.js +0 -131
  180. package/dist/tests/source-add.test.js +0 -11
  181. package/dist/tests/source-clone.test.js +0 -254
  182. package/dist/tests/source-manage.test.js +0 -366
  183. package/dist/tests/source-providers/filesystem.test.js +0 -82
  184. package/dist/tests/source-providers/git.test.js +0 -252
  185. package/dist/tests/source-providers/website.test.js +0 -128
  186. package/dist/tests/source-qa-fixes.test.js +0 -286
  187. package/dist/tests/source-registry.test.js +0 -350
  188. package/dist/tests/source-resolve.test.js +0 -100
  189. package/dist/tests/source-source.test.js +0 -281
  190. package/dist/tests/source.test.js +0 -533
  191. package/dist/tests/tar-utils-scan.test.js +0 -73
  192. package/dist/tests/toggle-components.test.js +0 -73
  193. package/dist/tests/usage-telemetry.test.js +0 -265
  194. package/dist/tests/utility-scoring.test.js +0 -558
  195. package/dist/tests/vault-load-error.test.js +0 -78
  196. package/dist/tests/vault-qa-fixes.test.js +0 -194
  197. package/dist/tests/vault.test.js +0 -429
  198. package/dist/tests/vector-search.test.js +0 -608
  199. package/dist/tests/walker.test.js +0 -252
  200. package/dist/tests/wave2-cluster-bc.test.js +0 -228
  201. package/dist/tests/wave2-cluster-d.test.js +0 -180
  202. package/dist/tests/wave2-cluster-e.test.js +0 -179
  203. package/dist/tests/wiki-qa-fixes.test.js +0 -270
  204. package/dist/tests/wiki.test.js +0 -529
  205. package/dist/tests/workflow-cli.test.js +0 -271
  206. package/dist/tests/workflow-markdown.test.js +0 -171
  207. package/dist/tests/workflow-path-escape.test.js +0 -132
  208. package/dist/tests/workflow-qa-fixes.test.js +0 -395
  209. package/dist/tests/workflows/indexer-rejection.test.js +0 -213
  210. /package/dist/{src/cli.js → cli.js} +0 -0
  211. /package/dist/{src/commands → commands}/completions.js +0 -0
  212. /package/dist/{src/commands → commands}/config-cli.js +0 -0
  213. /package/dist/{src/commands → commands}/curate.js +0 -0
  214. /package/dist/{src/commands → commands}/distill.js +0 -0
  215. /package/dist/{src/commands → commands}/events.js +0 -0
  216. /package/dist/{src/commands → commands}/history.js +0 -0
  217. /package/dist/{src/commands → commands}/info.js +0 -0
  218. /package/dist/{src/commands → commands}/init.js +0 -0
  219. /package/dist/{src/commands → commands}/install-audit.js +0 -0
  220. /package/dist/{src/commands → commands}/installed-stashes.js +0 -0
  221. /package/dist/{src/commands → commands}/migration-help.js +0 -0
  222. /package/dist/{src/commands → commands}/proposal.js +0 -0
  223. /package/dist/{src/commands → commands}/propose.js +0 -0
  224. /package/dist/{src/commands → commands}/reflect.js +0 -0
  225. /package/dist/{src/commands → commands}/registry-search.js +0 -0
  226. /package/dist/{src/commands → commands}/remember.js +0 -0
  227. /package/dist/{src/commands → commands}/search.js +0 -0
  228. /package/dist/{src/commands → commands}/self-update.js +0 -0
  229. /package/dist/{src/commands → commands}/show.js +0 -0
  230. /package/dist/{src/commands → commands}/source-add.js +0 -0
  231. /package/dist/{src/commands → commands}/source-clone.js +0 -0
  232. /package/dist/{src/commands → commands}/source-manage.js +0 -0
  233. /package/dist/{src/commands → commands}/vault.js +0 -0
  234. /package/dist/{src/core → core}/asset-ref.js +0 -0
  235. /package/dist/{src/core → core}/asset-registry.js +0 -0
  236. /package/dist/{src/core → core}/asset-spec.js +0 -0
  237. /package/dist/{src/core → core}/common.js +0 -0
  238. /package/dist/{src/core → core}/config.js +0 -0
  239. /package/dist/{src/core → core}/errors.js +0 -0
  240. /package/dist/{src/core → core}/events.js +0 -0
  241. /package/dist/{src/core → core}/frontmatter.js +0 -0
  242. /package/dist/{src/core → core}/lesson-lint.js +0 -0
  243. /package/dist/{src/core → core}/markdown.js +0 -0
  244. /package/dist/{src/core → core}/paths.js +0 -0
  245. /package/dist/{src/core → core}/proposals.js +0 -0
  246. /package/dist/{src/core → core}/warn.js +0 -0
  247. /package/dist/{src/core → core}/write-source.js +0 -0
  248. /package/dist/{src/indexer → indexer}/db-search.js +0 -0
  249. /package/dist/{src/indexer → indexer}/db.js +0 -0
  250. /package/dist/{src/indexer → indexer}/file-context.js +0 -0
  251. /package/dist/{src/indexer → indexer}/graph-boost.js +0 -0
  252. /package/dist/{src/indexer → indexer}/graph-extraction.js +0 -0
  253. /package/dist/{src/indexer → indexer}/indexer.js +0 -0
  254. /package/dist/{src/indexer → indexer}/manifest.js +0 -0
  255. /package/dist/{src/indexer → indexer}/matchers.js +0 -0
  256. /package/dist/{src/indexer → indexer}/memory-inference.js +0 -0
  257. /package/dist/{src/indexer → indexer}/metadata.js +0 -0
  258. /package/dist/{src/indexer → indexer}/search-fields.js +0 -0
  259. /package/dist/{src/indexer → indexer}/search-source.js +0 -0
  260. /package/dist/{src/indexer → indexer}/semantic-status.js +0 -0
  261. /package/dist/{src/indexer → indexer}/usage-events.js +0 -0
  262. /package/dist/{src/indexer → indexer}/walker.js +0 -0
  263. /package/dist/{src/integrations → integrations}/agent/config.js +0 -0
  264. /package/dist/{src/integrations → integrations}/agent/detect.js +0 -0
  265. /package/dist/{src/integrations → integrations}/agent/index.js +0 -0
  266. /package/dist/{src/integrations → integrations}/agent/profiles.js +0 -0
  267. /package/dist/{src/integrations → integrations}/agent/prompts.js +0 -0
  268. /package/dist/{src/integrations → integrations}/agent/spawn.js +0 -0
  269. /package/dist/{src/integrations → integrations}/github.js +0 -0
  270. /package/dist/{src/integrations → integrations}/lockfile.js +0 -0
  271. /package/dist/{src/llm → llm}/client.js +0 -0
  272. /package/dist/{src/llm → llm}/embedder.js +0 -0
  273. /package/dist/{src/llm → llm}/embedders/cache.js +0 -0
  274. /package/dist/{src/llm → llm}/embedders/local.js +0 -0
  275. /package/dist/{src/llm → llm}/embedders/remote.js +0 -0
  276. /package/dist/{src/llm → llm}/embedders/types.js +0 -0
  277. /package/dist/{src/llm → llm}/feature-gate.js +0 -0
  278. /package/dist/{src/llm → llm}/graph-extract.js +0 -0
  279. /package/dist/{src/llm → llm}/index-passes.js +0 -0
  280. /package/dist/{src/llm → llm}/memory-infer.js +0 -0
  281. /package/dist/{src/llm → llm}/metadata-enhance.js +0 -0
  282. /package/dist/{src/output → output}/cli-hints.js +0 -0
  283. /package/dist/{src/output → output}/context.js +0 -0
  284. /package/dist/{src/output → output}/renderers.js +0 -0
  285. /package/dist/{src/output → output}/shapes.js +0 -0
  286. /package/dist/{src/output → output}/text.js +0 -0
  287. /package/dist/{src/registry → registry}/build-index.js +0 -0
  288. /package/dist/{src/registry → registry}/create-provider-registry.js +0 -0
  289. /package/dist/{src/registry → registry}/factory.js +0 -0
  290. /package/dist/{src/registry → registry}/origin-resolve.js +0 -0
  291. /package/dist/{src/registry → registry}/providers/index.js +0 -0
  292. /package/dist/{src/registry → registry}/providers/skills-sh.js +0 -0
  293. /package/dist/{src/registry → registry}/providers/static-index.js +0 -0
  294. /package/dist/{src/registry → registry}/providers/types.js +0 -0
  295. /package/dist/{src/registry → registry}/resolve.js +0 -0
  296. /package/dist/{src/registry → registry}/types.js +0 -0
  297. /package/dist/{src/setup → setup}/detect.js +0 -0
  298. /package/dist/{src/setup → setup}/ripgrep-install.js +0 -0
  299. /package/dist/{src/setup → setup}/ripgrep-resolve.js +0 -0
  300. /package/dist/{src/setup → setup}/setup.js +0 -0
  301. /package/dist/{src/setup → setup}/steps.js +0 -0
  302. /package/dist/{src/sources → sources}/include.js +0 -0
  303. /package/dist/{src/sources → sources}/provider-factory.js +0 -0
  304. /package/dist/{src/sources → sources}/provider.js +0 -0
  305. /package/dist/{src/sources → sources}/providers/filesystem.js +0 -0
  306. /package/dist/{src/sources → sources}/providers/git.js +0 -0
  307. /package/dist/{src/sources → sources}/providers/index.js +0 -0
  308. /package/dist/{src/sources → sources}/providers/install-types.js +0 -0
  309. /package/dist/{src/sources → sources}/providers/npm.js +0 -0
  310. /package/dist/{src/sources → sources}/providers/provider-utils.js +0 -0
  311. /package/dist/{src/sources → sources}/providers/sync-from-ref.js +0 -0
  312. /package/dist/{src/sources → sources}/providers/tar-utils.js +0 -0
  313. /package/dist/{src/sources → sources}/providers/website.js +0 -0
  314. /package/dist/{src/sources → sources}/resolve.js +0 -0
  315. /package/dist/{src/sources → sources}/types.js +0 -0
  316. /package/dist/{src/templates → templates}/wiki-templates.js +0 -0
  317. /package/dist/{src/version.js → version.js} +0 -0
  318. /package/dist/{src/wiki → wiki}/wiki.js +0 -0
  319. /package/dist/{src/workflows → workflows}/authoring.js +0 -0
  320. /package/dist/{src/workflows → workflows}/cli.js +0 -0
  321. /package/dist/{src/workflows → workflows}/db.js +0 -0
  322. /package/dist/{src/workflows → workflows}/document-cache.js +0 -0
  323. /package/dist/{src/workflows → workflows}/parser.js +0 -0
  324. /package/dist/{src/workflows → workflows}/renderer.js +0 -0
  325. /package/dist/{src/workflows → workflows}/runs.js +0 -0
  326. /package/dist/{src/workflows → workflows}/schema.js +0 -0
  327. /package/dist/{src/workflows → workflows}/validator.js +0 -0
@@ -1,395 +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
- function createWorkflowEnv() {
14
- const stashDir = makeTempDir("akm-wfqa-stash-");
15
- const xdgCache = makeTempDir("akm-wfqa-cache-");
16
- const xdgConfig = makeTempDir("akm-wfqa-config-");
17
- return {
18
- ...process.env,
19
- AKM_STASH_DIR: stashDir,
20
- XDG_CACHE_HOME: xdgCache,
21
- XDG_CONFIG_HOME: xdgConfig,
22
- };
23
- }
24
- function runCli(args, env) {
25
- return spawnSync("bun", [CLI, ...args], {
26
- encoding: "utf8",
27
- timeout: 30_000,
28
- env,
29
- });
30
- }
31
- afterEach(() => {
32
- for (const dir of tempDirs.splice(0)) {
33
- fs.rmSync(dir, { recursive: true, force: true });
34
- }
35
- });
36
- const TWO_STEP_WORKFLOW = `---
37
- description: Test workflow
38
- ---
39
-
40
- # Workflow: Test Flow
41
-
42
- ## Step: First Step
43
- Step ID: first
44
-
45
- ### Instructions
46
- Do the first thing.
47
-
48
- ### Completion Criteria
49
- - First thing done
50
-
51
- ## Step: Second Step
52
- Step ID: second
53
-
54
- ### Instructions
55
- Do the second thing.
56
- `;
57
- function setupWorkflow(env, name = "test-flow") {
58
- const sourceDir = makeTempDir("akm-wfqa-src-");
59
- const sourcePath = path.join(sourceDir, "wf.md");
60
- fs.writeFileSync(sourcePath, TWO_STEP_WORKFLOW, "utf8");
61
- const result = runCli(["workflow", "create", name, "--from", sourcePath], env);
62
- if (result.status !== 0) {
63
- throw new Error(`Failed to create workflow: ${result.stderr}`);
64
- }
65
- }
66
- // ---------------------------------------------------------------------------
67
- // 1. resumeWorkflowRun — blocked → active; fails on completed
68
- // ---------------------------------------------------------------------------
69
- describe("workflow resume command", () => {
70
- test("resume flips a blocked run back to active", () => {
71
- const env = createWorkflowEnv();
72
- setupWorkflow(env);
73
- const started = runCli(["workflow", "start", "workflow:test-flow"], env);
74
- expect(started.status).toBe(0);
75
- const { run: startRun } = JSON.parse(started.stdout);
76
- // Complete first step as blocked
77
- expect(runCli(["workflow", "complete", startRun.id, "--step", "first", "--state", "blocked"], env).status).toBe(0);
78
- // Verify it's blocked
79
- const statusBlocked = runCli(["workflow", "status", startRun.id], env);
80
- expect(statusBlocked.status).toBe(0);
81
- const { run: blockedRun } = JSON.parse(statusBlocked.stdout);
82
- expect(blockedRun.status).toBe("blocked");
83
- // Resume it
84
- const resumed = runCli(["workflow", "resume", startRun.id], env);
85
- expect(resumed.status).toBe(0);
86
- const { run: resumedRun } = JSON.parse(resumed.stdout);
87
- expect(resumedRun.status).toBe("active");
88
- });
89
- test("resume on a completed run returns an error", () => {
90
- const env = createWorkflowEnv();
91
- setupWorkflow(env);
92
- const started = runCli(["workflow", "start", "workflow:test-flow"], env);
93
- expect(started.status).toBe(0);
94
- const { run: startRun } = JSON.parse(started.stdout);
95
- expect(runCli(["workflow", "complete", startRun.id, "--step", "first"], env).status).toBe(0);
96
- expect(runCli(["workflow", "complete", startRun.id, "--step", "second"], env).status).toBe(0);
97
- const resumed = runCli(["workflow", "resume", startRun.id], env);
98
- expect(resumed.status).toBe(2);
99
- const err = JSON.parse(resumed.stderr);
100
- expect(err.error).toContain("already completed");
101
- });
102
- test("resume on a failed run flips it to active", () => {
103
- const env = createWorkflowEnv();
104
- setupWorkflow(env);
105
- const started = runCli(["workflow", "start", "workflow:test-flow"], env);
106
- expect(started.status).toBe(0);
107
- const { run: startRun } = JSON.parse(started.stdout);
108
- expect(runCli(["workflow", "complete", startRun.id, "--step", "first", "--state", "failed"], env).status).toBe(0);
109
- const resumed = runCli(["workflow", "resume", startRun.id], env);
110
- expect(resumed.status).toBe(0);
111
- const { run: resumedRun } = JSON.parse(resumed.stdout);
112
- expect(resumedRun.status).toBe("active");
113
- });
114
- // Issue #156: after resuming a blocked run, the previously-blocked step must be
115
- // re-actionable so it can be reclassified to completed/failed/skipped.
116
- for (const newState of ["completed", "failed", "skipped"]) {
117
- test(`resume re-opens a blocked step so it can be reclassified to ${newState}`, () => {
118
- const env = createWorkflowEnv();
119
- setupWorkflow(env);
120
- const started = runCli(["workflow", "start", "workflow:test-flow"], env);
121
- expect(started.status).toBe(0);
122
- const { run: startRun } = JSON.parse(started.stdout);
123
- expect(runCli(["workflow", "complete", startRun.id, "--step", "first", "--state", "blocked"], env).status).toBe(0);
124
- expect(runCli(["workflow", "resume", startRun.id], env).status).toBe(0);
125
- const reclassified = runCli(["workflow", "complete", startRun.id, "--step", "first", "--state", newState, "--notes", "resolved"], env);
126
- expect(reclassified.status).toBe(0);
127
- const parsed = JSON.parse(reclassified.stdout);
128
- const firstStep = parsed.workflow.steps.find((s) => s.id === "first");
129
- expect(firstStep?.status).toBe(newState);
130
- });
131
- }
132
- test("resume does not disturb already-completed earlier steps", () => {
133
- const env = createWorkflowEnv();
134
- setupWorkflow(env);
135
- const started = runCli(["workflow", "start", "workflow:test-flow"], env);
136
- expect(started.status).toBe(0);
137
- const { run: startRun } = JSON.parse(started.stdout);
138
- expect(runCli(["workflow", "complete", startRun.id, "--step", "first"], env).status).toBe(0);
139
- expect(runCli(["workflow", "complete", startRun.id, "--step", "second", "--state", "blocked"], env).status).toBe(0);
140
- expect(runCli(["workflow", "resume", startRun.id], env).status).toBe(0);
141
- const status = runCli(["workflow", "status", startRun.id], env);
142
- expect(status.status).toBe(0);
143
- const detail = JSON.parse(status.stdout);
144
- expect(detail.workflow.steps.find((s) => s.id === "first")?.status).toBe("completed");
145
- expect(detail.workflow.steps.find((s) => s.id === "second")?.status).toBe("pending");
146
- });
147
- });
148
- // ---------------------------------------------------------------------------
149
- // 2. listWorkflowRuns --active includes blocked runs
150
- // ---------------------------------------------------------------------------
151
- describe("workflow list --active includes blocked", () => {
152
- test("blocked run appears in --active list", () => {
153
- const env = createWorkflowEnv();
154
- setupWorkflow(env);
155
- const started = runCli(["workflow", "start", "workflow:test-flow"], env);
156
- expect(started.status).toBe(0);
157
- const { run: startRun } = JSON.parse(started.stdout);
158
- expect(runCli(["workflow", "complete", startRun.id, "--step", "first", "--state", "blocked"], env).status).toBe(0);
159
- const listed = runCli(["workflow", "list", "--ref", "workflow:test-flow", "--active"], env);
160
- expect(listed.status).toBe(0);
161
- const { runs } = JSON.parse(listed.stdout);
162
- expect(runs.some((r) => r.id === startRun.id && r.status === "blocked")).toBe(true);
163
- });
164
- test("completed run does NOT appear in --active list", () => {
165
- const env = createWorkflowEnv();
166
- setupWorkflow(env);
167
- const started = runCli(["workflow", "start", "workflow:test-flow"], env);
168
- expect(started.status).toBe(0);
169
- const { run: startRun } = JSON.parse(started.stdout);
170
- expect(runCli(["workflow", "complete", startRun.id, "--step", "first"], env).status).toBe(0);
171
- expect(runCli(["workflow", "complete", startRun.id, "--step", "second"], env).status).toBe(0);
172
- const listed = runCli(["workflow", "list", "--active"], env);
173
- expect(listed.status).toBe(0);
174
- const { runs } = JSON.parse(listed.stdout);
175
- expect(runs.some((r) => r.id === startRun.id)).toBe(false);
176
- });
177
- });
178
- // ---------------------------------------------------------------------------
179
- // 3. workflow next on a completed run: done:true, step:null
180
- // ---------------------------------------------------------------------------
181
- describe("workflow next — completed run signals done", () => {
182
- test("next on a completed run-id returns done:true and step:null", () => {
183
- const env = createWorkflowEnv();
184
- setupWorkflow(env);
185
- const started = runCli(["workflow", "start", "workflow:test-flow"], env);
186
- expect(started.status).toBe(0);
187
- const { run: startRun } = JSON.parse(started.stdout);
188
- expect(runCli(["workflow", "complete", startRun.id, "--step", "first"], env).status).toBe(0);
189
- expect(runCli(["workflow", "complete", startRun.id, "--step", "second"], env).status).toBe(0);
190
- const next = runCli(["workflow", "next", startRun.id], env);
191
- expect(next.status).toBe(0);
192
- const nextJson = JSON.parse(next.stdout);
193
- expect(nextJson.done).toBe(true);
194
- expect(nextJson.step).toBeNull();
195
- });
196
- });
197
- // ---------------------------------------------------------------------------
198
- // 4. workflow next <ref> auto-start: autoStarted:true
199
- // ---------------------------------------------------------------------------
200
- describe("workflow next — auto-start flags autoStarted", () => {
201
- test("next on a ref with no existing run returns autoStarted:true", () => {
202
- const env = createWorkflowEnv();
203
- setupWorkflow(env);
204
- const next = runCli(["workflow", "next", "workflow:test-flow"], env);
205
- expect(next.status).toBe(0);
206
- const nextJson = JSON.parse(next.stdout);
207
- expect(nextJson.autoStarted).toBe(true);
208
- expect(nextJson.run.status).toBe("active");
209
- expect(nextJson.step.id).toBe("first");
210
- });
211
- test("next on a ref with existing active run does NOT set autoStarted", () => {
212
- const env = createWorkflowEnv();
213
- setupWorkflow(env);
214
- // First call auto-starts
215
- const first = runCli(["workflow", "next", "workflow:test-flow"], env);
216
- expect(first.status).toBe(0);
217
- // Second call resumes existing — no autoStarted
218
- const second = runCli(["workflow", "next", "workflow:test-flow"], env);
219
- expect(second.status).toBe(0);
220
- const secondJson = JSON.parse(second.stdout);
221
- expect(secondJson.autoStarted).toBeUndefined();
222
- });
223
- });
224
- // ---------------------------------------------------------------------------
225
- // 5. workflow next --params: sets params on auto-start; fails on existing run
226
- // ---------------------------------------------------------------------------
227
- describe("workflow next --params", () => {
228
- test("--params is accepted when auto-starting a new run", () => {
229
- const env = createWorkflowEnv();
230
- setupWorkflow(env);
231
- const next = runCli(["workflow", "next", "workflow:test-flow", "--params", '{"x":1}'], env);
232
- expect(next.status).toBe(0);
233
- const nextJson = JSON.parse(next.stdout);
234
- expect(nextJson.autoStarted).toBe(true);
235
- expect(nextJson.run.params?.x).toBe(1);
236
- });
237
- test("--params fails when an active run already exists (ref specifier)", () => {
238
- const env = createWorkflowEnv();
239
- setupWorkflow(env);
240
- // Start a run first
241
- expect(runCli(["workflow", "start", "workflow:test-flow"], env).status).toBe(0);
242
- const next = runCli(["workflow", "next", "workflow:test-flow", "--params", '{"x":1}'], env);
243
- expect(next.status).toBe(2);
244
- const err = JSON.parse(next.stderr);
245
- expect(err.error).toContain("--params can only be set on a new run");
246
- });
247
- test("--params fails when given a direct run-id (existing run)", () => {
248
- const env = createWorkflowEnv();
249
- setupWorkflow(env);
250
- const started = runCli(["workflow", "start", "workflow:test-flow"], env);
251
- expect(started.status).toBe(0);
252
- const { run: startRun } = JSON.parse(started.stdout);
253
- const next = runCli(["workflow", "next", startRun.id, "--params", '{"x":1}'], env);
254
- expect(next.status).toBe(2);
255
- const err = JSON.parse(next.stderr);
256
- expect(err.error).toContain("--params can only be used when starting a new run from a workflow ref");
257
- expect(err.error).toContain("existing run id");
258
- });
259
- });
260
- // ---------------------------------------------------------------------------
261
- // 6. workflow status workflow:<name> resolves to most-recent run
262
- // ---------------------------------------------------------------------------
263
- describe("workflow status with workflow ref", () => {
264
- test("status workflow:<name> resolves to the most-recently-updated run", () => {
265
- const env = createWorkflowEnv();
266
- setupWorkflow(env);
267
- const started = runCli(["workflow", "start", "workflow:test-flow"], env);
268
- expect(started.status).toBe(0);
269
- const { run: startRun } = JSON.parse(started.stdout);
270
- const status = runCli(["workflow", "status", "workflow:test-flow"], env);
271
- expect(status.status).toBe(0);
272
- const statusJson = JSON.parse(status.stdout);
273
- expect(statusJson.run.id).toBe(startRun.id);
274
- expect(statusJson.run.status).toBe("active");
275
- });
276
- test("status workflow:<name> returns NotFoundError when no runs exist", () => {
277
- const env = createWorkflowEnv();
278
- setupWorkflow(env);
279
- const status = runCli(["workflow", "status", "workflow:test-flow"], env);
280
- // No runs created yet — should fail with not-found (exit 1)
281
- expect(status.status).toBe(1);
282
- const err = JSON.parse(status.stderr);
283
- expect(err.error).toContain("No workflow runs found");
284
- });
285
- test("next with an unknown run id returns WORKFLOW_NOT_FOUND", () => {
286
- const env = createWorkflowEnv();
287
- setupWorkflow(env);
288
- const next = runCli(["workflow", "next", "bogus-run-id"], env);
289
- expect(next.status).toBe(1);
290
- const err = JSON.parse(next.stderr);
291
- expect(err.code).toBe("WORKFLOW_NOT_FOUND");
292
- expect(err.hint).toContain("akm workflow list --active");
293
- });
294
- test("status with an unknown run id returns WORKFLOW_NOT_FOUND", () => {
295
- const env = createWorkflowEnv();
296
- setupWorkflow(env);
297
- const status = runCli(["workflow", "status", "bogus-run-id"], env);
298
- expect(status.status).toBe(1);
299
- const err = JSON.parse(status.stderr);
300
- expect(err.code).toBe("WORKFLOW_NOT_FOUND");
301
- expect(err.hint).toContain("akm workflow list --active");
302
- });
303
- });
304
- // ---------------------------------------------------------------------------
305
- // 7. workflow create name validation
306
- // ---------------------------------------------------------------------------
307
- describe("workflow create — name validation", () => {
308
- test("name with spaces is rejected", () => {
309
- const env = createWorkflowEnv();
310
- const result = runCli(["workflow", "create", "name with spaces"], env);
311
- expect(result.status).toBe(2);
312
- const err = JSON.parse(result.stderr);
313
- expect(err.error).toContain("Workflow name must start with a lowercase letter");
314
- });
315
- test("name with uppercase is rejected", () => {
316
- const env = createWorkflowEnv();
317
- const result = runCli(["workflow", "create", "MyWorkflow"], env);
318
- expect(result.status).toBe(2);
319
- const err = JSON.parse(result.stderr);
320
- expect(err.error).toContain("Workflow name must start with a lowercase letter");
321
- });
322
- test("valid lowercase name is accepted", () => {
323
- const env = createWorkflowEnv();
324
- const result = runCli(["workflow", "create", "my-workflow"], env);
325
- expect(result.status).toBe(0);
326
- const json = JSON.parse(result.stdout);
327
- expect(json.ref).toBe("workflow:my-workflow");
328
- });
329
- test("hierarchical name with forward slash is accepted", () => {
330
- // Slashes are allowed for hierarchical naming (e.g. release/ship)
331
- const env = createWorkflowEnv();
332
- const result = runCli(["workflow", "create", "release/ship"], env);
333
- expect(result.status).toBe(0);
334
- const json = JSON.parse(result.stdout);
335
- expect(json.ref).toBe("workflow:release/ship");
336
- });
337
- test("name validation error message mentions slashes", () => {
338
- const env = createWorkflowEnv();
339
- const result = runCli(["workflow", "create", "BAD NAME"], env);
340
- expect(result.status).toBe(2);
341
- const err = JSON.parse(result.stderr);
342
- expect(err.error).toContain("slashes");
343
- });
344
- });
345
- // ---------------------------------------------------------------------------
346
- // 8. workflow create --force without --from/--reset is rejected
347
- // ---------------------------------------------------------------------------
348
- describe("workflow create --force guard", () => {
349
- test("--force without --from or --reset is rejected", () => {
350
- const env = createWorkflowEnv();
351
- setupWorkflow(env);
352
- const result = runCli(["workflow", "create", "test-flow", "--force"], env);
353
- expect(result.status).toBe(2);
354
- const err = JSON.parse(result.stderr);
355
- expect(err.error).toContain("Refusing to overwrite with template");
356
- });
357
- test("--force --reset succeeds and overwrites with template", () => {
358
- const env = createWorkflowEnv();
359
- setupWorkflow(env);
360
- const result = runCli(["workflow", "create", "test-flow", "--force", "--reset"], env);
361
- expect(result.status).toBe(0);
362
- const json = JSON.parse(result.stdout);
363
- expect(json.ok).toBe(true);
364
- expect(json.ref).toBe("workflow:test-flow");
365
- });
366
- test("--force --from <file> succeeds and overwrites with file content", () => {
367
- const env = createWorkflowEnv();
368
- setupWorkflow(env);
369
- const sourceDir = makeTempDir("akm-wfqa-src2-");
370
- const sourcePath = path.join(sourceDir, "new.md");
371
- fs.writeFileSync(sourcePath, TWO_STEP_WORKFLOW, "utf8");
372
- const result = runCli(["workflow", "create", "test-flow", "--force", "--from", sourcePath], env);
373
- expect(result.status).toBe(0);
374
- const json = JSON.parse(result.stdout);
375
- expect(json.ok).toBe(true);
376
- });
377
- });
378
- // ---------------------------------------------------------------------------
379
- // 9. complete --state help text documents default (just ensure it runs)
380
- // ---------------------------------------------------------------------------
381
- describe("workflow complete --state default", () => {
382
- test("complete without --state defaults to completed", () => {
383
- const env = createWorkflowEnv();
384
- setupWorkflow(env);
385
- const started = runCli(["workflow", "start", "workflow:test-flow"], env);
386
- expect(started.status).toBe(0);
387
- const { run: startRun } = JSON.parse(started.stdout);
388
- // No --state flag → should default to 'completed'
389
- const completed = runCli(["workflow", "complete", startRun.id, "--step", "first"], env);
390
- expect(completed.status).toBe(0);
391
- const json = JSON.parse(completed.stdout);
392
- const step = json.workflow.steps.find((s) => s.id === "first");
393
- expect(step?.status).toBe("completed");
394
- });
395
- });
@@ -1,213 +0,0 @@
1
- import { afterEach, beforeEach, 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 { getDbPath } from "../../src/core/paths";
6
- import { resetQuiet, resetVerbose, setVerbose } from "../../src/core/warn";
7
- import { closeDatabase, openDatabase } from "../../src/indexer/db";
8
- import { akmIndex } from "../../src/indexer/indexer";
9
- let testConfigDir = "";
10
- let testCacheDir = "";
11
- const originalXdgConfigHome = process.env.XDG_CONFIG_HOME;
12
- const originalXdgCacheHome = process.env.XDG_CACHE_HOME;
13
- beforeEach(() => {
14
- testConfigDir = fs.mkdtempSync(path.join(os.tmpdir(), "akm-wf-idx-config-"));
15
- testCacheDir = fs.mkdtempSync(path.join(os.tmpdir(), "akm-wf-idx-cache-"));
16
- process.env.XDG_CONFIG_HOME = testConfigDir;
17
- process.env.XDG_CACHE_HOME = testCacheDir;
18
- const dbPath = getDbPath();
19
- for (const f of [dbPath, `${dbPath}-wal`, `${dbPath}-shm`]) {
20
- try {
21
- fs.unlinkSync(f);
22
- }
23
- catch {
24
- /* ignore */
25
- }
26
- }
27
- // Defensive: other test files may have left the warn module's quiet/verbose
28
- // latches on. Reset both before each test so the noise-gate assertions read
29
- // a clean state.
30
- resetQuiet();
31
- resetVerbose();
32
- delete process.env.AKM_VERBOSE;
33
- });
34
- afterEach(() => {
35
- if (originalXdgConfigHome === undefined)
36
- delete process.env.XDG_CONFIG_HOME;
37
- else
38
- process.env.XDG_CONFIG_HOME = originalXdgConfigHome;
39
- if (originalXdgCacheHome === undefined)
40
- delete process.env.XDG_CACHE_HOME;
41
- else
42
- process.env.XDG_CACHE_HOME = originalXdgCacheHome;
43
- if (testConfigDir) {
44
- fs.rmSync(testConfigDir, { recursive: true, force: true });
45
- testConfigDir = "";
46
- }
47
- if (testCacheDir) {
48
- fs.rmSync(testCacheDir, { recursive: true, force: true });
49
- testCacheDir = "";
50
- }
51
- resetVerbose();
52
- delete process.env.AKM_VERBOSE;
53
- });
54
- function tmpStash() {
55
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), "akm-wf-idx-"));
56
- fs.mkdirSync(path.join(dir, "workflows"), { recursive: true });
57
- return dir;
58
- }
59
- function writeWorkflow(stashDir, name, content) {
60
- const file = path.join(stashDir, "workflows", `${name}.md`);
61
- fs.writeFileSync(file, content);
62
- return file;
63
- }
64
- const VALID_WORKFLOW = `# Workflow: Ship Release
65
-
66
- ## Step: Validate
67
- Step ID: validate
68
-
69
- ### Instructions
70
- Confirm release notes are present.
71
- `;
72
- const BROKEN_WORKFLOW = `# Workflow: Bad
73
-
74
- ## Step: First
75
- Step ID: first
76
- ### Instructions
77
- do A
78
-
79
- ## Step: Second
80
- Step ID: first
81
- ### Instructions
82
- do B
83
- `;
84
- test("indexer admits valid workflows and writes their JSON to workflow_documents", async () => {
85
- const stashDir = tmpStash();
86
- writeWorkflow(stashDir, "good", VALID_WORKFLOW);
87
- const result = await akmIndex({ stashDir, full: true });
88
- expect(result.totalEntries).toBe(1);
89
- const db = openDatabase();
90
- try {
91
- const row = db
92
- .prepare(`SELECT wd.document_json, wd.schema_version, wd.source_path
93
- FROM workflow_documents wd
94
- JOIN entries e ON e.id = wd.entry_id
95
- WHERE e.entry_type = 'workflow' AND e.entry_key LIKE ?`)
96
- .get(`${stashDir}:workflow:%`);
97
- expect(row).toBeDefined();
98
- if (!row)
99
- return;
100
- expect(row.schema_version).toBe(1);
101
- expect(row.source_path).toContain("good.md");
102
- const doc = JSON.parse(row.document_json);
103
- expect(doc.title).toBe("Ship Release");
104
- expect(doc.steps).toHaveLength(1);
105
- expect(doc.steps[0].instructions.text).toContain("Confirm release notes");
106
- expect(doc.steps[0].source.start).toBeGreaterThan(0);
107
- }
108
- finally {
109
- closeDatabase(db);
110
- }
111
- });
112
- test("indexer rejects broken workflows and surfaces every error in IndexResponse.warnings", async () => {
113
- const stashDir = tmpStash();
114
- writeWorkflow(stashDir, "good", VALID_WORKFLOW);
115
- const brokenPath = writeWorkflow(stashDir, "bad", BROKEN_WORKFLOW);
116
- const result = await akmIndex({ stashDir, full: true });
117
- expect(result.totalEntries).toBe(1); // only the good one
118
- expect(result.warnings ?? []).toBeDefined();
119
- const warnings = result.warnings ?? [];
120
- // The broken workflow has a duplicate step ID; the warning string must
121
- // mention the file and at least one of its errors.
122
- const brokenWarning = warnings.find((w) => w.includes(brokenPath));
123
- expect(brokenWarning).toBeDefined();
124
- expect(brokenWarning).toMatch(/already used|Step ID/);
125
- const db = openDatabase();
126
- try {
127
- const goodRow = db
128
- .prepare(`SELECT 1 FROM workflow_documents wd
129
- JOIN entries e ON e.id = wd.entry_id
130
- WHERE e.entry_key = ?`)
131
- .get(`${stashDir}:workflow:good`);
132
- expect(goodRow).toBeDefined();
133
- const badRow = db
134
- .prepare(`SELECT 1 FROM workflow_documents wd
135
- JOIN entries e ON e.id = wd.entry_id
136
- WHERE e.entry_key = ?`)
137
- .get(`${stashDir}:workflow:bad`);
138
- expect(badRow).toBeFalsy();
139
- }
140
- finally {
141
- closeDatabase(db);
142
- }
143
- });
144
- // ── Workflow validation noise gate (issue #273) ─────────────────────────────
145
- async function captureStderr(fn) {
146
- const lines = [];
147
- const originalWarn = console.warn.bind(console);
148
- console.warn = (...args) => {
149
- lines.push(args.map((a) => (typeof a === "string" ? a : JSON.stringify(a))).join(" "));
150
- };
151
- try {
152
- const result = await fn();
153
- return { result, lines };
154
- }
155
- finally {
156
- console.warn = originalWarn;
157
- }
158
- }
159
- test("default verbosity emits one summary line, not per-spec workflow warnings", async () => {
160
- const stashDir = tmpStash();
161
- // Two broken workflows so we can prove the summary line is emitted instead
162
- // of two separate per-spec warnings on stderr.
163
- writeWorkflow(stashDir, "bad1", BROKEN_WORKFLOW);
164
- writeWorkflow(stashDir, "bad2", BROKEN_WORKFLOW);
165
- const { lines } = await captureStderr(() => akmIndex({ stashDir, full: true }));
166
- const perSpec = lines.filter((l) => l.startsWith("Skipped workflow "));
167
- expect(perSpec).toHaveLength(0);
168
- const summary = lines.filter((l) => l.includes("workflow specs skipped due to validation errors"));
169
- expect(summary).toHaveLength(1);
170
- expect(summary[0]).toMatch(/^2 workflow specs skipped/);
171
- expect(summary[0]).toContain("--verbose");
172
- expect(summary[0]).toContain("AKM_VERBOSE");
173
- });
174
- test("default verbosity uses singular 'workflow spec' when only one was skipped", async () => {
175
- const stashDir = tmpStash();
176
- writeWorkflow(stashDir, "bad", BROKEN_WORKFLOW);
177
- const { lines } = await captureStderr(() => akmIndex({ stashDir, full: true }));
178
- const summary = lines.filter((l) => l.includes("workflow spec skipped"));
179
- expect(summary).toHaveLength(1);
180
- expect(summary[0]).toMatch(/^1 workflow spec skipped/);
181
- });
182
- test("--verbose flag restores per-spec workflow warnings and suppresses the summary", async () => {
183
- const stashDir = tmpStash();
184
- writeWorkflow(stashDir, "bad1", BROKEN_WORKFLOW);
185
- writeWorkflow(stashDir, "bad2", BROKEN_WORKFLOW);
186
- setVerbose(true);
187
- const { lines } = await captureStderr(() => akmIndex({ stashDir, full: true }));
188
- const perSpec = lines.filter((l) => l.startsWith("Skipped workflow "));
189
- expect(perSpec).toHaveLength(2);
190
- const summary = lines.filter((l) => l.includes("workflow specs skipped due to validation errors"));
191
- expect(summary).toHaveLength(0);
192
- });
193
- test("AKM_VERBOSE=1 restores per-spec output even with the verbose flag unset", async () => {
194
- const stashDir = tmpStash();
195
- writeWorkflow(stashDir, "bad", BROKEN_WORKFLOW);
196
- process.env.AKM_VERBOSE = "1";
197
- const { lines } = await captureStderr(() => akmIndex({ stashDir, full: true }));
198
- const perSpec = lines.filter((l) => l.startsWith("Skipped workflow "));
199
- expect(perSpec).toHaveLength(1);
200
- const summary = lines.filter((l) => l.includes("workflow spec skipped"));
201
- expect(summary).toHaveLength(0);
202
- });
203
- test("AKM_VERBOSE=0 hard-disables verbose output even when --verbose flag was set", async () => {
204
- const stashDir = tmpStash();
205
- writeWorkflow(stashDir, "bad", BROKEN_WORKFLOW);
206
- setVerbose(true);
207
- process.env.AKM_VERBOSE = "0";
208
- const { lines } = await captureStderr(() => akmIndex({ stashDir, full: true }));
209
- const perSpec = lines.filter((l) => l.startsWith("Skipped workflow "));
210
- expect(perSpec).toHaveLength(0);
211
- const summary = lines.filter((l) => l.includes("workflow spec skipped"));
212
- expect(summary).toHaveLength(1);
213
- });
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes