akm-cli 0.8.6 → 0.8.14

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 (324) hide show
  1. package/CHANGELOG.md +442 -0
  2. package/dist/assets/help/help-proposals.md +1 -2
  3. package/dist/assets/hints/cli-hints-full.md +34 -19
  4. package/dist/assets/hints/cli-hints-short.md +1 -1
  5. package/dist/assets/profiles/catchup.json +13 -0
  6. package/dist/assets/profiles/consolidate.json +13 -0
  7. package/dist/assets/profiles/frequent.json +13 -0
  8. package/dist/assets/tasks/core/backup.yml +4 -0
  9. package/dist/assets/tasks/core/extract.yml +4 -0
  10. package/dist/assets/tasks/core/improve.yml +4 -0
  11. package/dist/assets/tasks/core/index-refresh.yml +4 -0
  12. package/dist/assets/tasks/core/sync.yml +4 -0
  13. package/dist/assets/tasks/core/update-stashes.yml +4 -0
  14. package/dist/assets/tasks/core/version-check.yml +4 -0
  15. package/dist/assets/templates/html/default.html +78 -0
  16. package/dist/assets/templates/html/health.html +560 -0
  17. package/dist/assets/templates/html/vendor/echarts.min.js +45 -0
  18. package/dist/cli/config-migrate.js +6 -6
  19. package/dist/cli/config-validate.js +4 -4
  20. package/dist/cli/confirm.js +3 -3
  21. package/dist/cli/parse-args.js +1 -1
  22. package/dist/cli/shared.js +72 -19
  23. package/dist/cli-node.mjs +26 -0
  24. package/dist/cli.js +206 -3866
  25. package/dist/commands/{agent-dispatch.js → agent/agent-dispatch.js} +6 -6
  26. package/dist/commands/{agent-support.js → agent/agent-support.js} +2 -2
  27. package/dist/commands/agent/contribute-cli.js +200 -0
  28. package/dist/commands/completions.js +1 -1
  29. package/dist/commands/config-cli.js +230 -3
  30. package/dist/commands/db-cli.js +2 -2
  31. package/dist/commands/env/env-cli.js +529 -0
  32. package/dist/commands/env/env.js +410 -0
  33. package/dist/commands/env/secret-cli.js +259 -0
  34. package/dist/commands/{secret.js → env/secret.js} +6 -47
  35. package/dist/commands/events.js +4 -4
  36. package/dist/commands/feedback-cli.js +18 -34
  37. package/dist/commands/graph/graph-cli.js +132 -0
  38. package/dist/commands/{graph.js → graph/graph.js} +22 -16
  39. package/dist/commands/health/checks.js +279 -0
  40. package/dist/commands/health/html-report.js +448 -0
  41. package/dist/commands/health.js +189 -266
  42. package/dist/commands/{consolidate.js → improve/consolidate.js} +63 -38
  43. package/dist/commands/{distill-promotion-policy.js → improve/distill-promotion-policy.js} +3 -3
  44. package/dist/commands/{distill.js → improve/distill.js} +39 -18
  45. package/dist/commands/{eval-cases.js → improve/eval-cases.js} +1 -1
  46. package/dist/commands/{extract-cli.js → improve/extract-cli.js} +4 -4
  47. package/dist/commands/{extract-prompt.js → improve/extract-prompt.js} +2 -2
  48. package/dist/commands/{extract.js → improve/extract.js} +221 -26
  49. package/dist/commands/{improve-auto-accept.js → improve/improve-auto-accept.js} +30 -4
  50. package/dist/commands/{improve-cli.js → improve/improve-cli.js} +44 -22
  51. package/dist/commands/{improve-profiles.js → improve/improve-profiles.js} +13 -7
  52. package/dist/commands/{improve-result-file.js → improve/improve-result-file.js} +1 -1
  53. package/dist/commands/{improve.js → improve/improve.js} +672 -292
  54. package/dist/{core → commands/improve/memory}/memory-belief.js +2 -2
  55. package/dist/{core → commands/improve/memory}/memory-contradiction-detect.js +5 -5
  56. package/dist/{core → commands/improve/memory}/memory-improve.js +4 -4
  57. package/dist/commands/improve/reflect-noise.js +0 -0
  58. package/dist/commands/{reflect.js → improve/reflect.js} +58 -28
  59. package/dist/commands/improve/session-asset.js +248 -0
  60. package/dist/commands/lint/agent-linter.js +1 -1
  61. package/dist/commands/lint/base-linter.js +55 -37
  62. package/dist/commands/lint/command-linter.js +1 -1
  63. package/dist/commands/lint/default-linter.js +1 -1
  64. package/dist/commands/lint/env-key-rules.js +1 -1
  65. package/dist/commands/lint/index.js +19 -25
  66. package/dist/commands/lint/knowledge-linter.js +1 -1
  67. package/dist/commands/lint/memory-linter.js +1 -1
  68. package/dist/commands/lint/registry.js +8 -8
  69. package/dist/commands/lint/skill-linter.js +1 -1
  70. package/dist/commands/lint/task-linter.js +1 -1
  71. package/dist/commands/lint/workflow-linter.js +1 -1
  72. package/dist/commands/lint.js +1 -1
  73. package/dist/commands/observability-cli.js +244 -0
  74. package/dist/commands/proposal/drain-policies.js +3 -3
  75. package/dist/commands/proposal/drain.js +87 -15
  76. package/dist/commands/proposal/proposal-cli.js +490 -0
  77. package/dist/commands/{proposal.js → proposal/proposal.js} +17 -6
  78. package/dist/commands/{propose.js → proposal/propose.js} +11 -11
  79. package/dist/{core → commands/proposal/validators}/proposal-quality-validators.js +8 -3
  80. package/dist/{core → commands/proposal/validators}/proposal-validators.js +5 -5
  81. package/dist/{core → commands/proposal/validators}/proposals.js +374 -345
  82. package/dist/commands/{curate.js → read/curate.js} +7 -7
  83. package/dist/commands/{knowledge.js → read/knowledge.js} +22 -9
  84. package/dist/commands/{registry-search.js → read/registry-search.js} +5 -5
  85. package/dist/commands/{remember-cli.js → read/remember-cli.js} +15 -7
  86. package/dist/commands/read/search-cli.js +207 -0
  87. package/dist/commands/{search.js → read/search.js} +22 -27
  88. package/dist/commands/{show.js → read/show.js} +31 -45
  89. package/dist/commands/registry-cli.js +8 -8
  90. package/dist/commands/remember.js +14 -10
  91. package/dist/commands/sources/add-cli.js +293 -0
  92. package/dist/commands/{history.js → sources/history.js} +27 -25
  93. package/dist/commands/{info.js → sources/info.js} +6 -6
  94. package/dist/commands/{init.js → sources/init.js} +6 -6
  95. package/dist/commands/{installed-stashes.js → sources/installed-stashes.js} +12 -12
  96. package/dist/commands/{migration-help.js → sources/migration-help.js} +3 -2
  97. package/dist/commands/{schema-repair.js → sources/schema-repair.js} +8 -8
  98. package/dist/commands/{self-update.js → sources/self-update.js} +10 -9
  99. package/dist/commands/{source-add.js → sources/source-add.js} +10 -10
  100. package/dist/commands/{source-clone.js → sources/source-clone.js} +7 -7
  101. package/dist/commands/{source-manage.js → sources/source-manage.js} +4 -4
  102. package/dist/commands/sources/sources-cli.js +305 -0
  103. package/dist/commands/sources/stash-cli.js +219 -0
  104. package/dist/commands/{stash-skeleton.js → sources/stash-skeleton.js} +2 -1
  105. package/dist/commands/tasks/default-tasks.js +173 -0
  106. package/dist/commands/tasks/tasks-cli.js +210 -0
  107. package/dist/commands/{tasks.js → tasks/tasks.js} +14 -14
  108. package/dist/commands/wiki-cli.js +307 -0
  109. package/dist/commands/workflow-cli.js +329 -0
  110. package/dist/core/action-contributors.js +1 -1
  111. package/dist/core/assert.js +40 -0
  112. package/dist/core/asset/asset-create.js +54 -0
  113. package/dist/core/{asset-ref.js → asset/asset-ref.js} +21 -4
  114. package/dist/core/{asset-registry.js → asset/asset-registry.js} +3 -3
  115. package/dist/core/{asset-spec.js → asset/asset-spec.js} +17 -31
  116. package/dist/core/{markdown.js → asset/markdown.js} +1 -1
  117. package/dist/core/{stash-meta.js → asset/stash-meta.js} +1 -1
  118. package/dist/core/best-effort.js +64 -0
  119. package/dist/core/common.js +32 -18
  120. package/dist/core/{config-io.js → config/config-io.js} +29 -19
  121. package/dist/core/{config-migration.js → config/config-migration.js} +11 -9
  122. package/dist/core/{config-schema.js → config/config-schema.js} +50 -7
  123. package/dist/core/config/config-types.js +16 -0
  124. package/dist/core/{config-walker.js → config/config-walker.js} +2 -2
  125. package/dist/core/{config.js → config/config.js} +10 -8
  126. package/dist/core/env-secret-ref.js +90 -0
  127. package/dist/core/errors.js +13 -3
  128. package/dist/core/events.js +27 -4
  129. package/dist/core/file-lock.js +1 -1
  130. package/dist/core/improve-types.js +48 -0
  131. package/dist/core/lesson-lint.js +2 -2
  132. package/dist/core/logs-db.js +304 -0
  133. package/dist/core/paths.js +2 -2
  134. package/dist/core/ripgrep/install.js +2 -2
  135. package/dist/core/ripgrep/resolve.js +2 -2
  136. package/dist/core/state-db.js +195 -60
  137. package/dist/core/text-truncation.js +148 -0
  138. package/dist/core/time.js +1 -1
  139. package/dist/core/write-source.js +98 -85
  140. package/dist/indexer/{db-backup.js → db/db-backup.js} +9 -24
  141. package/dist/indexer/{db.js → db/db.js} +128 -118
  142. package/dist/indexer/{graph-db.js → db/graph-db.js} +9 -4
  143. package/dist/indexer/{llm-cache.js → db/llm-cache.js} +15 -12
  144. package/dist/indexer/ensure-index.js +4 -4
  145. package/dist/indexer/{graph-boost.js → graph/graph-boost.js} +1 -1
  146. package/dist/indexer/{graph-extraction.js → graph/graph-extraction.js} +55 -13
  147. package/dist/indexer/indexer.js +37 -30
  148. package/dist/indexer/init.js +54 -0
  149. package/dist/indexer/manifest.js +10 -10
  150. package/dist/indexer/{memory-inference.js → passes/memory-inference.js} +141 -33
  151. package/dist/indexer/{metadata-contributors.js → passes/metadata-contributors.js} +10 -8
  152. package/dist/indexer/{metadata.js → passes/metadata.js} +15 -19
  153. package/dist/indexer/{staleness-detect.js → passes/staleness-detect.js} +53 -12
  154. package/dist/indexer/{db-search.js → search/db-search.js} +28 -16
  155. package/dist/indexer/{ranking-contributors.js → search/ranking-contributors.js} +1 -1
  156. package/dist/indexer/{ranking.js → search/ranking.js} +2 -2
  157. package/dist/indexer/{search-hit-enrichers.js → search/search-hit-enrichers.js} +3 -3
  158. package/dist/indexer/{search-source.js → search/search-source.js} +8 -8
  159. package/dist/indexer/{semantic-status.js → search/semantic-status.js} +3 -3
  160. package/dist/indexer/usage/unmigrated-vaults-guard.js +94 -0
  161. package/dist/indexer/{usage-events.js → usage/usage-events.js} +32 -0
  162. package/dist/indexer/{file-context.js → walk/file-context.js} +10 -15
  163. package/dist/indexer/{matchers.js → walk/matchers.js} +13 -9
  164. package/dist/indexer/{path-resolver.js → walk/path-resolver.js} +6 -6
  165. package/dist/indexer/{project-context.js → walk/project-context.js} +1 -1
  166. package/dist/indexer/{walker.js → walk/walker.js} +4 -3
  167. package/dist/integrations/agent/builder-shared.js +39 -0
  168. package/dist/integrations/agent/builders.js +14 -81
  169. package/dist/integrations/agent/config.js +6 -4
  170. package/dist/integrations/agent/detect.js +1 -1
  171. package/dist/integrations/agent/index.js +23 -8
  172. package/dist/integrations/agent/prompts.js +2 -3
  173. package/dist/integrations/agent/runner.js +22 -3
  174. package/dist/integrations/agent/spawn.js +9 -10
  175. package/dist/integrations/harnesses/claude/agent-builder.js +48 -0
  176. package/dist/integrations/harnesses/claude/config-import.js +70 -0
  177. package/dist/integrations/harnesses/claude/index.js +64 -0
  178. package/dist/integrations/{session-logs/providers/claude-code.js → harnesses/claude/session-log.js} +32 -5
  179. package/dist/integrations/harnesses/index.js +144 -0
  180. package/dist/integrations/harnesses/opencode/agent-builder.js +43 -0
  181. package/dist/integrations/harnesses/opencode/config-import.js +82 -0
  182. package/dist/integrations/harnesses/opencode/index.js +59 -0
  183. package/dist/integrations/{session-logs/providers/opencode.js → harnesses/opencode/session-log.js} +1 -1
  184. package/dist/integrations/harnesses/opencode-sdk/index.js +49 -0
  185. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +234 -0
  186. package/dist/integrations/harnesses/types.js +43 -0
  187. package/dist/integrations/lockfile.js +7 -16
  188. package/dist/integrations/session-logs/index.js +82 -9
  189. package/dist/llm/call-ai.js +4 -4
  190. package/dist/llm/client.js +146 -6
  191. package/dist/llm/embedder.js +6 -6
  192. package/dist/llm/embedders/local.js +9 -22
  193. package/dist/llm/embedders/remote.js +2 -2
  194. package/dist/llm/embedders/types.js +1 -1
  195. package/dist/llm/graph-extract.js +31 -12
  196. package/dist/llm/index-passes.js +1 -1
  197. package/dist/llm/memory-infer.js +12 -5
  198. package/dist/llm/metadata-enhance.js +2 -2
  199. package/dist/llm/usage-persist.js +77 -0
  200. package/dist/llm/usage-telemetry.js +103 -0
  201. package/dist/output/context.js +9 -46
  202. package/dist/output/html-render.js +73 -0
  203. package/dist/output/renderers.js +88 -58
  204. package/dist/output/shapes/curate.js +7 -3
  205. package/dist/output/shapes/distill.js +7 -3
  206. package/dist/output/shapes/env-list.js +18 -16
  207. package/dist/output/shapes/events.js +5 -4
  208. package/dist/output/shapes/helpers.js +19 -5
  209. package/dist/output/shapes/history.js +7 -3
  210. package/dist/output/shapes/passthrough.js +8 -11
  211. package/dist/output/shapes/{proposal-accept.js → proposal/accept.js} +7 -3
  212. package/dist/output/shapes/{proposal-diff.js → proposal/diff.js} +7 -3
  213. package/dist/output/shapes/{proposal-list.js → proposal/list.js} +7 -3
  214. package/dist/output/shapes/{proposal-producer.js → proposal/producer.js} +5 -4
  215. package/dist/output/shapes/{proposal-reject.js → proposal/reject.js} +7 -3
  216. package/dist/output/shapes/{proposal-show.js → proposal/show.js} +7 -3
  217. package/dist/output/shapes/registry-search.js +7 -3
  218. package/dist/output/shapes/registry.js +12 -0
  219. package/dist/output/shapes/search.js +7 -3
  220. package/dist/output/shapes/secret-list.js +18 -16
  221. package/dist/output/shapes/show.js +7 -3
  222. package/dist/output/shapes.js +55 -30
  223. package/dist/output/text/add.js +2 -3
  224. package/dist/output/text/clone.js +2 -3
  225. package/dist/output/text/config.js +2 -3
  226. package/dist/output/text/curate.js +4 -3
  227. package/dist/output/text/distill.js +2 -3
  228. package/dist/output/text/enable-disable.js +5 -4
  229. package/dist/output/text/env.js +13 -0
  230. package/dist/output/text/events.js +5 -4
  231. package/dist/output/text/feedback.js +4 -3
  232. package/dist/output/text/helpers.js +123 -40
  233. package/dist/output/text/history.js +2 -3
  234. package/dist/output/text/import.js +2 -3
  235. package/dist/output/text/index.js +2 -3
  236. package/dist/output/text/info.js +2 -3
  237. package/dist/output/text/init.js +2 -3
  238. package/dist/output/text/list.js +2 -3
  239. package/dist/output/text/proposal/producer.js +9 -0
  240. package/dist/output/text/proposal/proposal.js +13 -0
  241. package/dist/output/text/registry-commands.js +8 -7
  242. package/dist/output/text/registry.js +12 -0
  243. package/dist/output/text/remember.js +4 -3
  244. package/dist/output/text/remove.js +2 -3
  245. package/dist/output/text/save.js +2 -3
  246. package/dist/output/text/search.js +4 -3
  247. package/dist/output/text/show.js +4 -3
  248. package/dist/output/text/update.js +2 -3
  249. package/dist/output/text/upgrade.js +2 -3
  250. package/dist/output/text/wiki.js +12 -11
  251. package/dist/output/text/workflow.js +12 -10
  252. package/dist/output/text.js +66 -32
  253. package/dist/registry/build-index.js +11 -10
  254. package/dist/registry/factory.js +1 -1
  255. package/dist/registry/origin-resolve.js +1 -1
  256. package/dist/registry/providers/index.js +2 -2
  257. package/dist/registry/providers/skills-sh.js +91 -72
  258. package/dist/registry/providers/static-index.js +75 -52
  259. package/dist/registry/resolve.js +3 -3
  260. package/dist/runtime.js +242 -0
  261. package/dist/scripts/migrate-storage.js +1654 -683
  262. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +254 -168
  263. package/dist/setup/detect.js +311 -9
  264. package/dist/setup/harness-config-import.js +6 -120
  265. package/dist/setup/setup.js +454 -43
  266. package/dist/sources/include.js +1 -1
  267. package/dist/sources/provider-factory.js +2 -2
  268. package/dist/sources/providers/filesystem.js +3 -3
  269. package/dist/sources/providers/git.js +9 -9
  270. package/dist/sources/providers/index.js +4 -4
  271. package/dist/sources/providers/npm.js +6 -6
  272. package/dist/sources/providers/provider-utils.js +13 -20
  273. package/dist/sources/providers/sync-from-ref.js +5 -5
  274. package/dist/sources/providers/tar-utils.js +2 -2
  275. package/dist/sources/providers/website.js +2 -2
  276. package/dist/sources/resolve.js +5 -5
  277. package/dist/sources/website-ingest.js +5 -5
  278. package/dist/storage/database.js +102 -0
  279. package/dist/storage/engines/sqlite-migrations.js +42 -0
  280. package/dist/storage/locations.js +25 -0
  281. package/dist/storage/repositories/index-db.js +43 -0
  282. package/dist/storage/repositories/workflow-runs-repository.js +141 -0
  283. package/dist/tasks/backends/cron.js +4 -4
  284. package/dist/tasks/backends/exec-utils.js +32 -0
  285. package/dist/tasks/backends/index.js +3 -3
  286. package/dist/tasks/backends/launchd.js +7 -14
  287. package/dist/tasks/backends/schtasks.js +7 -16
  288. package/dist/tasks/embedded.js +71 -0
  289. package/dist/tasks/parser.js +2 -2
  290. package/dist/tasks/resolveAkmBin.js +1 -1
  291. package/dist/tasks/runner.js +127 -31
  292. package/dist/tasks/schedule.js +1 -1
  293. package/dist/tasks/validator.js +7 -7
  294. package/dist/text-import-hook.mjs +51 -0
  295. package/dist/version.js +2 -1
  296. package/dist/wiki/wiki.js +7 -7
  297. package/dist/workflows/{authoring.js → authoring/authoring.js} +6 -6
  298. package/dist/workflows/{scope-key.js → authoring/scope-key.js} +1 -1
  299. package/dist/workflows/cli.js +1 -1
  300. package/dist/workflows/db.js +54 -32
  301. package/dist/workflows/parser.js +4 -4
  302. package/dist/workflows/renderer.js +5 -5
  303. package/dist/workflows/runtime/agent-identity.js +56 -0
  304. package/dist/workflows/runtime/checkin.js +57 -0
  305. package/dist/workflows/{runs.js → runtime/runs.js} +197 -101
  306. package/dist/workflows/validate-summary.js +82 -0
  307. package/docs/README.md +1 -1
  308. package/docs/data-and-telemetry.md +6 -6
  309. package/package.json +17 -8
  310. package/dist/commands/add-cli.js +0 -279
  311. package/dist/commands/env.js +0 -213
  312. package/dist/integrations/agent/sdk-runner.js +0 -126
  313. package/dist/output/shapes/vault-list.js +0 -19
  314. package/dist/output/text/proposal-producer.js +0 -8
  315. package/dist/output/text/proposal.js +0 -12
  316. package/dist/output/text/vault.js +0 -16
  317. /package/dist/core/{asset-serialize.js → asset/asset-serialize.js} +0 -0
  318. /package/dist/core/{frontmatter.js → asset/frontmatter.js} +0 -0
  319. /package/dist/core/{config-sources.js → config/config-sources.js} +0 -0
  320. /package/dist/indexer/{graph-dedup.js → graph/graph-dedup.js} +0 -0
  321. /package/dist/{core/config-types.js → indexer/passes/pass-context.js} +0 -0
  322. /package/dist/indexer/{search-fields.js → search/search-fields.js} +0 -0
  323. /package/dist/indexer/{index-context.js → walk/index-context.js} +0 -0
  324. /package/dist/workflows/{document-cache.js → runtime/document-cache.js} +0 -0
@@ -13,13 +13,13 @@
13
13
  * pure helpers (`curateSearchResults`, `orderCuratedTypes`,
14
14
  * `deriveCurateFallbackQueries`) by importing them directly.
15
15
  */
16
- import { rethrowIfTestIsolationError, UsageError } from "../core/errors";
17
- import { appendEvent } from "../core/events";
18
- import { closeDatabase, openExistingDatabase } from "../indexer/db";
19
- import { insertUsageEvent } from "../indexer/usage-events";
20
- import { truncateDescription } from "../output/shapes";
21
- import { akmSearch, parseSearchSource } from "./search";
22
- import { akmShowUnified } from "./show";
16
+ import { rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
17
+ import { appendEvent } from "../../core/events.js";
18
+ import { closeDatabase, openExistingDatabase } from "../../indexer/db/db.js";
19
+ import { insertUsageEvent } from "../../indexer/usage/usage-events.js";
20
+ import { truncateDescription } from "../../output/shapes.js";
21
+ import { akmSearch, parseSearchSource } from "./search.js";
22
+ import { akmShowUnified } from "./show.js";
23
23
  const CURATE_FALLBACK_FILTER_WORDS = new Set([
24
24
  "a",
25
25
  "an",
@@ -10,12 +10,13 @@
10
10
  */
11
11
  import fs from "node:fs";
12
12
  import path from "node:path";
13
- import { resolveAssetPathFromName } from "../core/asset-spec";
14
- import { isHttpUrl, isWithin, tryReadStdinText } from "../core/common";
15
- import { loadConfig } from "../core/config";
16
- import { UsageError } from "../core/errors";
17
- import { resolveWriteTarget, writeAssetToSource } from "../core/write-source";
18
- import { fetchWebsiteMarkdownSnapshot } from "../sources/website-ingest";
13
+ import { assertFlatAssetName, combineCreatePath, normalizeCreateSubPath } from "../../core/asset/asset-create.js";
14
+ import { resolveAssetPathFromName } from "../../core/asset/asset-spec.js";
15
+ import { isHttpUrl, isWithin, tryReadStdinText } from "../../core/common.js";
16
+ import { loadConfig } from "../../core/config/config.js";
17
+ import { UsageError } from "../../core/errors.js";
18
+ import { commitWriteTargetBoundary, formatRefForMessage, resolveWriteTarget, writeAssetToSource, } from "../../core/write-source.js";
19
+ import { fetchWebsiteMarkdownSnapshot } from "../../sources/website-ingest.js";
19
20
  const MAX_CAPTURED_ASSET_SLUG_LENGTH = 64;
20
21
  // ── Asset-name normalisation ─────────────────────────────────────────────────
21
22
  /**
@@ -38,6 +39,9 @@ export function normalizeMarkdownAssetName(name, fallback) {
38
39
  }
39
40
  return trimmed;
40
41
  }
42
+ // `--path`/`--name` create semantics are shared across all asset-creating
43
+ // commands; re-exported here so existing `./knowledge` importers keep working.
44
+ export { assertFlatAssetName, combineCreatePath, normalizeCreateSubPath };
41
45
  function slugifyAssetName(value, fallbackPrefix) {
42
46
  const slug = value
43
47
  .toLowerCase()
@@ -114,9 +118,14 @@ export async function readKnowledgeInput(source) {
114
118
  */
115
119
  export async function writeMarkdownAsset(options) {
116
120
  const cfg = loadConfig();
117
- const { source, config } = resolveWriteTarget(cfg, options.target);
121
+ const target = resolveWriteTarget(cfg, options.target);
122
+ const { source, config } = target;
118
123
  const typeRoot = path.join(source.path, options.type === "knowledge" ? "knowledge" : "memories");
119
- const normalizedName = normalizeMarkdownAssetName(options.name, inferAssetName(options.content, options.fallbackPrefix, options.preferredName));
124
+ // `--name` is the flat asset name; `--path` is the subdirectory under the
125
+ // type root. Combine them into the nested name the path resolver expects.
126
+ const subPath = normalizeCreateSubPath(options.path);
127
+ const baseName = normalizeMarkdownAssetName(options.name, inferAssetName(options.content, options.fallbackPrefix, options.preferredName));
128
+ const normalizedName = combineCreatePath(subPath, baseName);
120
129
  // Pre-flight: existence + force semantics. The helper itself overwrites
121
130
  // unconditionally; the CLI surfaces a friendlier UsageError before any
122
131
  // disk activity when --force is absent.
@@ -127,7 +136,11 @@ export async function writeMarkdownAsset(options) {
127
136
  if (fs.existsSync(assetPath) && !options.force) {
128
137
  throw new UsageError(`${options.type === "knowledge" ? "Knowledge" : "Memory"} "${normalizedName}" already exists. Re-run with --force to overwrite it.`, "RESOURCE_ALREADY_EXISTS");
129
138
  }
130
- const result = await writeAssetToSource(source, config, { type: options.type, name: normalizedName }, options.content);
139
+ const ref = { type: options.type, name: normalizedName };
140
+ const result = await writeAssetToSource(source, config, ref, options.content);
141
+ // 0.9.0 (issue #507): single batch commit at the write boundary for git
142
+ // targets. No-op for filesystem/primary-stash targets.
143
+ commitWriteTargetBoundary(target, `Update ${formatRefForMessage(ref)}`);
131
144
  return {
132
145
  ref: result.ref,
133
146
  path: result.path,
@@ -1,12 +1,12 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { toErrorMessage } from "../core/common";
5
- import { DEFAULT_CONFIG } from "../core/config";
6
- import { warn } from "../core/warn";
7
- import { resolveProviderFactory } from "../registry/factory";
4
+ import { toErrorMessage } from "../../core/common.js";
5
+ import { DEFAULT_CONFIG } from "../../core/config/config.js";
6
+ import { warn } from "../../core/warn.js";
7
+ import { resolveProviderFactory } from "../../registry/factory.js";
8
8
  // ── Eagerly import providers to trigger self-registration ───────────────────
9
- import "../registry/providers/index";
9
+ import "../../registry/providers/index.js";
10
10
  // ── Public API ──────────────────────────────────────────────────────────────
11
11
  export async function searchRegistry(query, options) {
12
12
  const trimmed = query.trim();
@@ -2,12 +2,12 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import { defineCommand } from "citty";
5
- import { output, parseAllFlagValues, runWithJsonErrors } from "../cli/shared";
6
- import { UsageError } from "../core/errors";
7
- import { appendEvent } from "../core/events";
8
- import { inferAssetName, writeMarkdownAsset } from "./knowledge";
9
- import { buildMemoryFrontmatter, parseDuration, readMemoryContent, resolveRememberContentArg, runAutoHeuristics, runLlmEnrich, } from "./remember";
10
- import { akmSearch } from "./search";
5
+ import { output, parseAllFlagValues, runWithJsonErrors } from "../../cli/shared.js";
6
+ import { UsageError } from "../../core/errors.js";
7
+ import { appendEvent } from "../../core/events.js";
8
+ import { buildMemoryFrontmatter, parseDuration, readMemoryContent, resolveRememberContentArg, runAutoHeuristics, runLlmEnrich, } from "../remember.js";
9
+ import { assertFlatAssetName, inferAssetName, writeMarkdownAsset } from "./knowledge.js";
10
+ import { akmSearch } from "./search.js";
11
11
  // ── Helper: similar memory search ────────────────────────────────────────────
12
12
  /**
13
13
  * Best-effort top-3 similar memory search for `--show-similar`.
@@ -39,7 +39,11 @@ export const rememberCommand = defineCommand({
39
39
  },
40
40
  name: {
41
41
  type: "string",
42
- description: "Memory name (defaults to a slug from the content)",
42
+ description: "Memory name (flat, no '/'; defaults to a slug from the content). Use --path for a subdirectory.",
43
+ },
44
+ path: {
45
+ type: "string",
46
+ description: "Relative subdirectory under memories/ to place the memory in (e.g. 'personal/projects'). The filename still comes from --name or the content slug.",
43
47
  },
44
48
  force: {
45
49
  type: "boolean",
@@ -100,6 +104,8 @@ export const rememberCommand = defineCommand({
100
104
  async run({ args }) {
101
105
  return runWithJsonErrors(async () => {
102
106
  const body = readMemoryContent(resolveRememberContentArg(args.content));
107
+ // `--name` is a flat name; subdirectory placement is `--path`'s job.
108
+ assertFlatAssetName(args.name);
103
109
  // Determine if the user has requested any structured metadata mode.
104
110
  // Collect all --tag occurrences directly from process.argv because citty
105
111
  // only exposes the last value for repeated string flags.
@@ -138,6 +144,7 @@ export const rememberCommand = defineCommand({
138
144
  preferredName: inferAssetName(body, "memory"),
139
145
  force: args.force,
140
146
  target: args.target,
147
+ path: args.path,
141
148
  });
142
149
  appendEvent({
143
150
  eventType: "remember",
@@ -232,6 +239,7 @@ export const rememberCommand = defineCommand({
232
239
  fallbackPrefix: "memory",
233
240
  force: args.force,
234
241
  target: args.target,
242
+ path: args.path,
235
243
  });
236
244
  appendEvent({
237
245
  eventType: "remember",
@@ -0,0 +1,207 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * `akm search`, `akm curate`, and `akm show` command family. Extracted verbatim
6
+ * from src/cli.ts (WS6) so the God Module shrinks; the `main.subCommands.search`,
7
+ * `.curate`, and `.show` keys and every command's args/output shape are
8
+ * byte-identical. The three commands form a clean cluster: they share the
9
+ * private `resolveEventSource()` helper and the `parseScopeFilterFlags`
10
+ * search-source parsers. Handlers whose body is a plain
11
+ * `runWithJsonErrors(async () => { … })` are migrated to `defineJsonCommand`,
12
+ * which emits the same JSON envelope (stdout/stderr/exit-code) as the inline
13
+ * form.
14
+ */
15
+ import { parsePositiveIntFlag } from "../../cli/parse-args.js";
16
+ import { defineJsonCommand, output, parseAllFlagValues } from "../../cli/shared.js";
17
+ import { parseAssetRef } from "../../core/asset/asset-ref.js";
18
+ import { parseMetaRef } from "../../core/asset/stash-meta.js";
19
+ import { UsageError } from "../../core/errors.js";
20
+ import { getHyphenatedBoolean, getOutputMode, parseFlagValue } from "../../output/context.js";
21
+ import { akmCurate } from "./curate.js";
22
+ import { akmSearch, parseBeliefFilterMode, parseScopeFilterFlags, parseSearchSource } from "./search.js";
23
+ import { akmShowUnified } from "./show.js";
24
+ // AKM_EVENT_SOURCE attributes a query to a `user` invocation or the internal
25
+ // `improve` loop so the event log can distinguish them; any other value is
26
+ // treated as unset.
27
+ function resolveEventSource() {
28
+ const raw = process.env.AKM_EVENT_SOURCE;
29
+ if (raw === "improve")
30
+ return "improve";
31
+ if (raw === "user")
32
+ return "user";
33
+ return undefined;
34
+ }
35
+ export const searchCommand = defineJsonCommand({
36
+ meta: { name: "search", description: "Search the stash" },
37
+ args: {
38
+ query: { type: "positional", description: "Search query (omit to list all assets)", required: false, default: "" },
39
+ type: {
40
+ type: "string",
41
+ description: "Asset type filter (skill, command, agent, knowledge, workflow, script, memory, env, secret, wiki, lesson, or any). Use workflow to find step-by-step task assets.",
42
+ },
43
+ limit: { type: "string", description: "Maximum number of results" },
44
+ source: { type: "string", description: "Search source (stash|registry|both)", default: "stash" },
45
+ filter: {
46
+ type: "string",
47
+ description: "Scope filter (repeatable): --filter user=<id> --filter agent=<id> --filter run=<id> --filter channel=<name>. Narrows results without changing ranking.",
48
+ },
49
+ "include-proposed": {
50
+ type: "boolean",
51
+ description: 'Include entries with quality:"proposed" in the result set. Excluded by default (v1 spec §4.2).',
52
+ default: false,
53
+ },
54
+ belief: {
55
+ type: "string",
56
+ description: "Memory belief filter: all|current|historical. current keeps active memory beliefs; historical keeps contradicted/superseded/archived memory beliefs.",
57
+ default: "all",
58
+ },
59
+ format: { type: "string", description: "Output format (json|jsonl|text|yaml)" },
60
+ detail: { type: "string", description: "Detail level (brief|normal|full)" },
61
+ "no-project-context": {
62
+ type: "boolean",
63
+ description: "Disable the automatic project-context ranking boost (also disabled by AKM_DISABLE_PROJECT_CONTEXT=1).",
64
+ default: false,
65
+ },
66
+ },
67
+ async run({ args }) {
68
+ const query = (args.query ?? "").trim();
69
+ if (!query) {
70
+ throw new UsageError('A search query is required. Usage: akm search "<query>" [--type <type>] [--limit <n>]', "MISSING_REQUIRED_ARGUMENT", 'Pass a query like `akm search "docker"` or `akm search "code review" --type skill`.');
71
+ }
72
+ const type = args.type;
73
+ const limit = parsePositiveIntFlag(args.limit ?? undefined);
74
+ const source = parseSearchSource(args.source);
75
+ // Repeatable; citty exposes only the last `--filter` value, so read all
76
+ // occurrences directly from argv (same pattern as `--tag`).
77
+ const filterTokens = parseAllFlagValues("--filter");
78
+ const filters = parseScopeFilterFlags(filterTokens, "--filter");
79
+ const includeProposed = args["include-proposed"] === true;
80
+ const belief = parseBeliefFilterMode(typeof args.belief === "string" ? args.belief : undefined);
81
+ const noProjectContext = getHyphenatedBoolean(args, "no-project-context");
82
+ // --no-project-context sets env so searchDatabase picks it up without
83
+ // threading the flag through the entire call stack.
84
+ if (noProjectContext)
85
+ process.env.AKM_DISABLE_PROJECT_CONTEXT = "1";
86
+ const result = await akmSearch({
87
+ query,
88
+ type,
89
+ limit,
90
+ source,
91
+ filters,
92
+ includeProposed,
93
+ belief,
94
+ eventSource: resolveEventSource(),
95
+ });
96
+ output("search", result);
97
+ },
98
+ });
99
+ export const curateCommand = defineJsonCommand({
100
+ meta: { name: "curate", description: "Curate the best matching assets for a task or prompt" },
101
+ args: {
102
+ // Optional in citty so run() is invoked when omitted; we re-validate
103
+ // below to surface a structured UsageError (exit 2) instead of citty's
104
+ // default help-banner exit-0.
105
+ query: { type: "positional", description: "Task or prompt to curate assets for", required: false },
106
+ type: {
107
+ type: "string",
108
+ description: "Asset type filter (skill, command, agent, knowledge, workflow, script, memory, env, secret, wiki, lesson, or any). Use workflow to curate step-by-step task assets.",
109
+ },
110
+ limit: { type: "string", description: "Maximum number of curated results", default: "4" },
111
+ source: { type: "string", description: "Search source (stash|registry|both)", default: "stash" },
112
+ // Output-contract flags. The active values are read from the process-level
113
+ // singleton (parsed from argv at startup); these declarations make them
114
+ // visible in `akm curate --help` and document the supported axes.
115
+ format: { type: "string", description: "Output format (json|jsonl|text|yaml)" },
116
+ detail: { type: "string", description: "Detail level (brief|normal|full)" },
117
+ shape: { type: "string", description: "Output projection (human|agent)" },
118
+ },
119
+ async run({ args }) {
120
+ if (!args.query || !String(args.query).trim()) {
121
+ throw new UsageError('A curate query is required. Usage: akm curate "<task or prompt>" [--type <type>] [--limit <n>]', "MISSING_REQUIRED_ARGUMENT", 'Describe the task you want assets for, e.g. `akm curate "deploy to prod"`.');
122
+ }
123
+ const type = args.type;
124
+ const limitParsed = parsePositiveIntFlag(args.limit ?? undefined);
125
+ const limit = limitParsed && limitParsed > 0 ? limitParsed : 4;
126
+ const source = parseSearchSource(args.source ?? "stash");
127
+ const curated = await akmCurate({ query: args.query, type, limit, source });
128
+ output("curate", curated);
129
+ },
130
+ });
131
+ export const showCommand = defineJsonCommand({
132
+ meta: {
133
+ name: "show",
134
+ description: "Show a stash asset by ref (e.g. akm show knowledge:guide.md toc, akm show knowledge:guide.md section 'Auth')",
135
+ },
136
+ args: {
137
+ ref: {
138
+ type: "positional",
139
+ description: 'Asset ref ([origin//]type:name) optionally followed by a view mode. View modes: `toc` (table of contents), `section "Heading"` (extract one section), `lines <start> <end>` (line range), `frontmatter` (YAML metadata only), `full` (raw file). Example: `akm show knowledge:guide.md section "Auth"`.',
140
+ required: true,
141
+ },
142
+ format: { type: "string", description: "Output format (json|jsonl|text|yaml)" },
143
+ detail: { type: "string", description: "Detail level (brief|normal|full)" },
144
+ shape: { type: "string", description: "Output projection (human|agent|summary)" },
145
+ scope: {
146
+ type: "string",
147
+ description: "Scope filter (repeatable): --scope user=<id> --scope agent=<id> --scope run=<id> --scope channel=<name>. Narrows resolution to assets whose frontmatter scope matches.",
148
+ },
149
+ },
150
+ async run({ args }) {
151
+ // `[origin//]meta[:name]` targets the stash `.meta/` convention, which is
152
+ // not a typed asset ref — skip ref validation and let akmShowUnified
153
+ // direct-read it. (`parseAssetRef` would reject the non-type `meta`.)
154
+ if (!parseMetaRef(args.ref))
155
+ parseAssetRef(args.ref);
156
+ // The knowledge-view positional syntax (`akm show knowledge:foo section "Auth"`)
157
+ // is rewritten to `--akmView` / `--akmHeading` / `--akmStart` / `--akmEnd`
158
+ // by `normalizeShowArgv` before citty parses argv. We read those values
159
+ // directly via `parseFlagValue` so the flags don't surface as user-facing
160
+ // options in `akm show --help`.
161
+ const akmView = parseFlagValue(process.argv, "--akmView");
162
+ const akmHeading = parseFlagValue(process.argv, "--akmHeading");
163
+ const akmStart = parseFlagValue(process.argv, "--akmStart");
164
+ const akmEnd = parseFlagValue(process.argv, "--akmEnd");
165
+ let view;
166
+ if (akmView) {
167
+ switch (akmView) {
168
+ case "section":
169
+ view = { mode: "section", heading: akmHeading ?? "" };
170
+ break;
171
+ case "lines":
172
+ view = {
173
+ mode: "lines",
174
+ start: Number(akmStart ?? "1"),
175
+ end: akmEnd ? parseInt(akmEnd, 10) : Number.MAX_SAFE_INTEGER,
176
+ };
177
+ break;
178
+ case "toc":
179
+ case "frontmatter":
180
+ case "full":
181
+ view = { mode: akmView };
182
+ break;
183
+ default:
184
+ throw new UsageError(`Unknown view mode: ${akmView}. Expected one of: full|toc|frontmatter|section|lines`);
185
+ }
186
+ }
187
+ const cliShape = getOutputMode().shape;
188
+ const explicitDetail = parseFlagValue(process.argv, "--detail");
189
+ // `--shape summary` selects the compact metadata projection for show
190
+ // (the legacy `--detail summary` spelling still maps here via the
191
+ // back-compat path in resolveOutputMode). `--detail brief` forces the
192
+ // brief response regardless of shape.
193
+ const showDetail = explicitDetail === "brief" ? "brief" : cliShape === "summary" ? "summary" : undefined;
194
+ // `--scope` is repeatable — citty only exposes the last value, so read
195
+ // every occurrence directly from argv (same pattern as `--filter`).
196
+ const scopeTokens = parseAllFlagValues("--scope");
197
+ const scope = parseScopeFilterFlags(scopeTokens, "--scope");
198
+ const result = await akmShowUnified({
199
+ ref: args.ref,
200
+ view,
201
+ detail: showDetail,
202
+ scope,
203
+ eventSource: resolveEventSource(),
204
+ });
205
+ output("show", result);
206
+ },
207
+ });
@@ -11,19 +11,20 @@
11
11
  * a registry search behind `--source registry|both`, and log a usage event.
12
12
  * Provider `search()` methods do not exist.
13
13
  */
14
- import { loadConfig } from "../core/config";
15
- import { rethrowIfTestIsolationError, UsageError } from "../core/errors";
16
- import { appendEvent } from "../core/events";
17
- import { isTransientStashPath } from "../core/paths";
18
- import { bumpUtilityScoresBatch, closeDatabase, openExistingDatabase } from "../indexer/db";
19
- import { searchLocal } from "../indexer/db-search";
20
- import { resolveSourceEntries } from "../indexer/search-source";
21
- import { getCurrentWorkflowScopeKey } from "../workflows/scope-key";
14
+ import { loadConfig } from "../../core/config/config.js";
15
+ import { rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
16
+ import { appendEvent } from "../../core/events.js";
17
+ import { isTransientStashPath } from "../../core/paths.js";
18
+ import { bumpUtilityScoresBatch, getEntryIdByFilePath } from "../../indexer/db/db.js";
19
+ import { searchLocal } from "../../indexer/search/db-search.js";
20
+ import { resolveSourceEntries } from "../../indexer/search/search-source.js";
21
+ import { getCurrentWorkflowScopeKey } from "../../workflows/authoring/scope-key.js";
22
22
  // Eagerly import source providers to trigger self-registration before the
23
23
  // indexer or path-resolution code runs.
24
- import "../sources/providers/index";
25
- import { insertUsageEvent } from "../indexer/usage-events";
26
- import { searchRegistry } from "./registry-search";
24
+ import "../../sources/providers/index.js";
25
+ import { insertUsageEvent } from "../../indexer/usage/usage-events.js";
26
+ import { withIndexDb } from "../../storage/repositories/index-db.js";
27
+ import { searchRegistry } from "./registry-search.js";
27
28
  const DEFAULT_LIMIT = 20;
28
29
  export async function akmSearch(input) {
29
30
  const t0 = Date.now();
@@ -78,7 +79,7 @@ export async function akmSearch(input) {
78
79
  timing: { totalMs: Date.now() - t0 },
79
80
  };
80
81
  if (!input.skipLogging)
81
- logSearchEvent(query, response, undefined, undefined, input.eventSource);
82
+ logSearchEvent(query, response, undefined, input.eventSource);
82
83
  return response;
83
84
  }
84
85
  // Primary stash directory — used for DB path lookups and as the default
@@ -122,7 +123,7 @@ export async function akmSearch(input) {
122
123
  timing: { totalMs: Date.now() - t0, rankMs: localResult?.rankMs, embedMs: localResult?.embedMs },
123
124
  };
124
125
  if (!input.skipLogging)
125
- logSearchEvent(query, response, undefined, localResult?.mode ?? "keyword", input.eventSource);
126
+ logSearchEvent(query, response, localResult?.mode ?? "keyword", input.eventSource);
126
127
  return response;
127
128
  }
128
129
  const registryHits = (registryResult?.hits ?? []).map((hit) => {
@@ -157,7 +158,7 @@ export async function akmSearch(input) {
157
158
  timing: { totalMs: Date.now() - t0 },
158
159
  };
159
160
  if (!input.skipLogging)
160
- logSearchEvent(query, response, undefined, undefined, input.eventSource);
161
+ logSearchEvent(query, response, undefined, input.eventSource);
161
162
  return response;
162
163
  }
163
164
  // source === "both"
@@ -175,7 +176,7 @@ export async function akmSearch(input) {
175
176
  timing: { totalMs: Date.now() - t0 },
176
177
  };
177
178
  if (!input.skipLogging)
178
- logSearchEvent(query, response, undefined, undefined, input.eventSource);
179
+ logSearchEvent(query, response, undefined, input.eventSource);
179
180
  return response;
180
181
  }
181
182
  /**
@@ -183,12 +184,11 @@ export async function akmSearch(input) {
183
184
  */
184
185
  function resolveEntryIds(db, hits) {
185
186
  const results = [];
186
- const stmt = db.prepare("SELECT id FROM entries WHERE file_path = ? LIMIT 1");
187
187
  for (const hit of hits) {
188
188
  try {
189
- const row = stmt.get(hit.path);
190
- if (row)
191
- results.push({ entryId: row.id, ref: hit.ref });
189
+ const entryId = getEntryIdByFilePath(db, hit.path);
190
+ if (entryId !== undefined)
191
+ results.push({ entryId, ref: hit.ref });
192
192
  }
193
193
  catch {
194
194
  /* skip unresolvable */
@@ -211,7 +211,7 @@ function resolveEntryIds(db, hits) {
211
211
  * Per-entry events are recorded only for stash hits because registry hits
212
212
  * have no local entry_id to reference.
213
213
  */
214
- function logSearchEvent(query, response, existingDb, mode = "keyword", eventSource = "user") {
214
+ function logSearchEvent(query, response, mode = "keyword", eventSource = "user") {
215
215
  // Emit a structured event to events.jsonl so workflow-trace consumers
216
216
  // detect akm search invocations without relying on stdout scraping.
217
217
  const stashHits = response.hits.filter((h) => h.type !== "registry");
@@ -223,8 +223,7 @@ function logSearchEvent(query, response, existingDb, mode = "keyword", eventSour
223
223
  metadata: { query, hitCount: stashHits.length, resultRefs: allResultRefs, mode },
224
224
  });
225
225
  try {
226
- const db = existingDb ?? openExistingDatabase();
227
- try {
226
+ withIndexDb((db) => {
228
227
  const resolved = resolveEntryIds(db, stashHits.slice(0, 50));
229
228
  for (const { entryId, ref } of resolved) {
230
229
  insertUsageEvent(db, {
@@ -266,11 +265,7 @@ function logSearchEvent(query, response, existingDb, mode = "keyword", eventSour
266
265
  }),
267
266
  source: eventSource,
268
267
  });
269
- }
270
- finally {
271
- if (!existingDb)
272
- closeDatabase(db);
273
- }
268
+ });
274
269
  }
275
270
  catch (err) {
276
271
  rethrowIfTestIsolationError(err);
@@ -18,32 +18,33 @@
18
18
  */
19
19
  import fs from "node:fs";
20
20
  import path from "node:path";
21
- import { parseAssetRef } from "../core/asset-ref";
22
- import { asNonEmptyString } from "../core/common";
23
- import { loadConfig } from "../core/config";
24
- import { NotFoundError, rethrowIfTestIsolationError, UsageError } from "../core/errors";
25
- import { appendEvent, readEvents } from "../core/events";
26
- import { parseFrontmatter } from "../core/frontmatter";
27
- import { META_DIR, parseMetaRef, resolveMetaFilePath } from "../core/stash-meta";
28
- import { closeDatabase, findEntryIdByRef, openExistingDatabase } from "../indexer/db";
29
- import { ensureIndex } from "../indexer/ensure-index";
30
- import { buildFileContext, buildRenderContext, getRenderer, runMatchers } from "../indexer/file-context";
31
- import { listRelatedPathsForFile } from "../indexer/graph-boost";
32
- import { lookup } from "../indexer/indexer";
33
- import { resolveAssetPath } from "../indexer/path-resolver";
34
- import { buildEditHint, findSourceForPath, isEditable, resolveSourceEntries } from "../indexer/search-source";
35
- import { insertUsageEvent } from "../indexer/usage-events";
36
- import { resolveSourcesForOrigin } from "../registry/origin-resolve";
21
+ import { parseAssetRef } from "../../core/asset/asset-ref.js";
22
+ import { parseFrontmatter } from "../../core/asset/frontmatter.js";
23
+ import { META_DIR, parseMetaRef, resolveMetaFilePath } from "../../core/asset/stash-meta.js";
24
+ import { asNonEmptyString } from "../../core/common.js";
25
+ import { loadConfig } from "../../core/config/config.js";
26
+ import { NotFoundError, rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
27
+ import { appendEvent, readEvents } from "../../core/events.js";
28
+ import { findEntryIdByRef } from "../../indexer/db/db.js";
29
+ import { ensureIndex } from "../../indexer/ensure-index.js";
30
+ import { listRelatedPathsForFile } from "../../indexer/graph/graph-boost.js";
31
+ import { lookup } from "../../indexer/indexer.js";
32
+ import { buildEditHint, findSourceForPath, isEditable, resolveSourceEntries } from "../../indexer/search/search-source.js";
33
+ import { insertUsageEvent } from "../../indexer/usage/usage-events.js";
34
+ import { buildFileContext, buildRenderContext, getRenderer, runMatchers } from "../../indexer/walk/file-context.js";
35
+ import { resolveAssetPath } from "../../indexer/walk/path-resolver.js";
36
+ import { resolveSourcesForOrigin } from "../../registry/origin-resolve.js";
37
+ import { withIndexDb } from "../../storage/repositories/index-db.js";
37
38
  // Eagerly import source providers to trigger self-registration.
38
- import "../sources/providers/index";
39
- import { getActiveWorkflowRun } from "../workflows/runs";
40
- import { getCurrentWorkflowScopeKey } from "../workflows/scope-key";
39
+ import "../../sources/providers/index.js";
40
+ import { getCurrentWorkflowScopeKey } from "../../workflows/authoring/scope-key.js";
41
+ import { getActiveWorkflowRun } from "../../workflows/runtime/runs.js";
41
42
  /**
42
43
  * Show a wiki root (no page path) — returns the same payload as
43
44
  * `akm wiki show <name>`.
44
45
  */
45
46
  async function showWikiRoot(stashDir, wikiName) {
46
- const { showWiki } = await import("../wiki/wiki.js");
47
+ const { showWiki } = await import("../../wiki/wiki.js");
47
48
  const result = showWiki(stashDir, wikiName);
48
49
  return {
49
50
  type: "wiki",
@@ -59,7 +60,7 @@ async function showWikiRoot(stashDir, wikiName) {
59
60
  };
60
61
  }
61
62
  async function showWikiRootForSource(stashDir, source, wikiName) {
62
- const { showWikiAtPath } = await import("../wiki/wiki.js");
63
+ const { showWikiAtPath } = await import("../../wiki/wiki.js");
63
64
  if (source.wikiName === wikiName) {
64
65
  const result = showWikiAtPath(wikiName, source.path);
65
66
  return {
@@ -156,7 +157,7 @@ export async function akmShowUnified(input) {
156
157
  }
157
158
  // Count prior shows of this ref before logging the current one.
158
159
  const priorShowCount = recentShowCount(ref);
159
- logShowEvent(ref, undefined, input.eventSource);
160
+ logShowEvent(ref, input.eventSource);
160
161
  if (priorShowCount >= 2) {
161
162
  // Agent has shown this same asset 3+ times — inject a loop-break hint.
162
163
  result.showLoopWarning = priorShowCount + 1;
@@ -253,7 +254,7 @@ function recentShowCount(ref) {
253
254
  return 0;
254
255
  }
255
256
  }
256
- function logShowEvent(ref, existingDb, eventSource = "user") {
257
+ function logShowEvent(ref, eventSource = "user") {
257
258
  // Emit a structured event to events.jsonl so workflow-trace consumers
258
259
  // detect akm show invocations without relying on stdout scraping.
259
260
  const parsed = parseAssetRef(ref);
@@ -288,19 +289,14 @@ function logShowEvent(ref, existingDb, eventSource = "user") {
288
289
  /* fire-and-forget — select is best-effort */
289
290
  }
290
291
  try {
291
- const db = existingDb ?? openExistingDatabase();
292
- try {
292
+ withIndexDb((db) => {
293
293
  insertUsageEvent(db, {
294
294
  event_type: "show",
295
295
  entry_ref: ref,
296
296
  entry_id: findEntryIdByRef(db, ref),
297
297
  source: eventSource,
298
298
  });
299
- }
300
- finally {
301
- if (!existingDb)
302
- closeDatabase(db);
303
- }
299
+ });
304
300
  }
305
301
  catch (err) {
306
302
  rethrowIfTestIsolationError(err);
@@ -371,20 +367,16 @@ export async function showLocal(input) {
371
367
  editable,
372
368
  ...(!editable ? { editHint: buildEditHint(assetPath, parsed.type, parsed.name, source?.registryId) } : {}),
373
369
  related: (() => {
374
- let db;
375
370
  try {
376
- db = openExistingDatabase();
377
- const related = listRelatedPathsForFile(sourceStashDir, assetPath, 5, db);
378
- return { total: related.length, hits: related };
371
+ return withIndexDb((db) => {
372
+ const related = listRelatedPathsForFile(sourceStashDir, assetPath, 5, db);
373
+ return { total: related.length, hits: related };
374
+ });
379
375
  }
380
376
  catch (err) {
381
377
  rethrowIfTestIsolationError(err);
382
378
  return { total: 0, hits: [] };
383
379
  }
384
- finally {
385
- if (db)
386
- closeDatabase(db);
387
- }
388
380
  })(),
389
381
  };
390
382
  const activeRun = await getActiveWorkflowRun(getCurrentWorkflowScopeKey());
@@ -482,8 +474,6 @@ export function normalizeShowArgv(argv) {
482
474
  // argv[0]=bun argv[1]=script argv[2]=subcommand argv[3]=ref argv[4..]=rest
483
475
  if (argv[2] !== "show")
484
476
  return argv;
485
- if (argv[3] === "proposal")
486
- return argv;
487
477
  if (argv.includes("--view") || argv.includes("--heading") || argv.includes("--start") || argv.includes("--end")) {
488
478
  throw new UsageError('Legacy show flags are no longer supported. Use positional syntax like `akm show knowledge:guide toc` or `akm show knowledge:guide section "Auth"`.');
489
479
  }
@@ -494,11 +484,7 @@ export function normalizeShowArgv(argv) {
494
484
  const showArgs = [];
495
485
  for (let i = 0; i < rest.length; i++) {
496
486
  const arg = rest[i];
497
- if (arg === "--quiet" ||
498
- arg === "-q" ||
499
- arg === "--verbose" ||
500
- arg === "--for-agent" ||
501
- arg === "--for-agent=true") {
487
+ if (arg === "--quiet" || arg === "-q" || arg === "--verbose") {
502
488
  globalFlags.push(arg);
503
489
  continue;
504
490
  }