akm-cli 0.9.0-rc.4 → 0.9.0-rc.6

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 (438) hide show
  1. package/CHANGELOG.md +122 -26
  2. package/README.md +7 -7
  3. package/SECURITY.md +11 -10
  4. package/dist/akm +2 -2
  5. package/dist/akm-migrate-storage +2 -2
  6. package/dist/assets/hints/cli-hints-full.md +60 -73
  7. package/dist/assets/hints/cli-hints-short.md +8 -12
  8. package/dist/assets/improve-strategies/default.json +5 -7
  9. package/dist/assets/improve-strategies/frequent.json +2 -2
  10. package/dist/assets/improve-strategies/proactive-maintenance.json +2 -2
  11. package/dist/assets/improve-strategies/quick.json +1 -1
  12. package/dist/assets/improve-strategies/reflect-distill.json +3 -3
  13. package/dist/assets/improve-strategies/thorough.json +1 -1
  14. package/dist/assets/prompts/consolidate-system.md +5 -5
  15. package/dist/assets/prompts/extract-session.md +2 -6
  16. package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
  17. package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
  18. package/dist/assets/prompts/reflect-output-repair.md +3 -0
  19. package/dist/assets/stash-skeleton/README.md +10 -11
  20. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +1 -1
  21. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +1 -1
  22. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +1 -1
  23. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -2
  24. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -2
  25. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +1 -1
  26. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -2
  27. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +1 -1
  28. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +18 -18
  29. package/dist/assets/stash-skeleton/facts/conventions/domains.md +8 -9
  30. package/dist/assets/stash-skeleton/facts/conventions/organization.md +13 -15
  31. package/dist/assets/tasks/core/extract.yml +2 -2
  32. package/dist/assets/tasks/core/improve.yml +1 -1
  33. package/dist/assets/templates/html/health.html +2 -3
  34. package/dist/cli/config-migrate.js +1328 -101
  35. package/dist/cli/invocation.js +255 -0
  36. package/dist/cli/parse-args.js +20 -83
  37. package/dist/cli/shared.js +15 -37
  38. package/dist/cli.js +18 -49
  39. package/dist/commands/agent/agent-dispatch.js +2 -2
  40. package/dist/commands/agent/contribute-cli.js +5 -4
  41. package/dist/commands/bundle/bundle-cli.js +68 -0
  42. package/dist/commands/bundle/bundle.js +219 -0
  43. package/dist/commands/completions.js +2 -2
  44. package/dist/commands/config-cli.js +6 -3
  45. package/dist/commands/env/env-binding.js +13 -9
  46. package/dist/commands/env/env-cli.js +49 -48
  47. package/dist/commands/env/secret-cli.js +24 -10
  48. package/dist/commands/events.js +2 -2
  49. package/dist/commands/feedback-cli.js +59 -33
  50. package/dist/commands/graph/graph.js +6 -4
  51. package/dist/commands/health/advisories.js +4 -4
  52. package/dist/commands/health/html-report.js +190 -593
  53. package/dist/commands/health/improve-metrics.js +240 -188
  54. package/dist/commands/health/metrics.js +9 -17
  55. package/dist/commands/health/report-view-model.js +509 -0
  56. package/dist/commands/health/surfaces.js +6 -3
  57. package/dist/commands/health/types-checks.js +4 -0
  58. package/dist/commands/health/types-improve.js +22 -0
  59. package/dist/commands/health/types-metrics.js +4 -0
  60. package/dist/commands/health/types-result.js +7 -0
  61. package/dist/commands/health/types-runs.js +4 -0
  62. package/dist/commands/health/types-session-log.js +4 -0
  63. package/dist/commands/health/types-windows.js +4 -0
  64. package/dist/commands/health/types.js +26 -21
  65. package/dist/commands/health/windows.js +1 -2
  66. package/dist/commands/health.js +219 -161
  67. package/dist/commands/improve/collapse-detector.js +25 -14
  68. package/dist/commands/improve/consolidate/chunking.js +7 -5
  69. package/dist/commands/improve/consolidate.js +640 -740
  70. package/dist/commands/improve/content-hash.js +39 -0
  71. package/dist/commands/improve/distill/content-repair.js +4 -10
  72. package/dist/commands/improve/distill/promote-memory.js +79 -49
  73. package/dist/commands/improve/distill/quality-gate.js +113 -35
  74. package/dist/commands/improve/distill-promotion-policy.js +24 -885
  75. package/dist/commands/improve/distill.js +565 -337
  76. package/dist/commands/improve/eligibility.js +75 -36
  77. package/dist/commands/improve/extract-cli.js +6 -6
  78. package/dist/commands/improve/extract-prompt.js +5 -34
  79. package/dist/commands/improve/extract.js +526 -357
  80. package/dist/commands/improve/feedback-valence.js +2 -12
  81. package/dist/commands/improve/improve-cli.js +11 -20
  82. package/dist/commands/improve/improve-result-file.js +7 -6
  83. package/dist/commands/improve/improve-run-types.js +4 -0
  84. package/dist/commands/improve/improve-strategies.js +3 -9
  85. package/dist/commands/improve/improve.js +822 -727
  86. package/dist/commands/improve/locks.js +27 -95
  87. package/dist/commands/improve/loop-stages.js +941 -963
  88. package/dist/commands/improve/memory/derived-ref.js +122 -0
  89. package/dist/commands/improve/memory/memory-contradiction-detect.js +35 -38
  90. package/dist/commands/improve/memory/memory-improve.js +24 -37
  91. package/dist/commands/improve/outcome-loop.js +13 -33
  92. package/dist/commands/improve/preparation.js +889 -691
  93. package/dist/commands/improve/proactive-maintenance.js +37 -9
  94. package/dist/commands/improve/proposal-envelope.js +31 -0
  95. package/dist/commands/improve/reflect.js +974 -588
  96. package/dist/commands/improve/run-context.js +119 -0
  97. package/dist/commands/improve/salience.js +8 -4
  98. package/dist/commands/improve/session-asset.js +7 -3
  99. package/dist/commands/improve/shared.js +14 -40
  100. package/dist/commands/improve/source-identity.js +39 -26
  101. package/dist/commands/improve/triage.js +20 -17
  102. package/dist/commands/lint/base-linter.js +288 -295
  103. package/dist/commands/lint/index.js +132 -19
  104. package/dist/commands/mv-cli.js +257 -234
  105. package/dist/commands/observability-cli.js +2 -1
  106. package/dist/commands/proposal/diff-format.js +50 -0
  107. package/dist/commands/proposal/drain-policies.js +0 -6
  108. package/dist/commands/proposal/drain.js +17 -16
  109. package/dist/commands/proposal/proposal-cli.js +40 -77
  110. package/dist/commands/proposal/proposal-types.js +56 -0
  111. package/dist/commands/proposal/proposal.js +39 -1
  112. package/dist/commands/proposal/propose.js +41 -19
  113. package/dist/commands/proposal/repository.js +566 -486
  114. package/dist/commands/proposal/validators/proposal-quality-validators.js +22 -6
  115. package/dist/commands/proposal/validators/proposal-validators.js +6 -5
  116. package/dist/commands/proposal/validators/proposals.js +5 -4
  117. package/dist/commands/read/curate.js +50 -28
  118. package/dist/commands/read/knowledge.js +25 -16
  119. package/dist/commands/read/remember-cli.js +12 -4
  120. package/dist/commands/read/search-cli.js +33 -33
  121. package/dist/commands/read/search.js +68 -55
  122. package/dist/commands/read/show.js +54 -135
  123. package/dist/commands/remember.js +7 -5
  124. package/dist/commands/sources/add-cli.js +10 -24
  125. package/dist/commands/sources/bundle-config-ops.js +58 -0
  126. package/dist/commands/sources/history.js +13 -8
  127. package/dist/commands/sources/info.js +10 -11
  128. package/dist/commands/sources/init.js +12 -21
  129. package/dist/commands/sources/installed-stashes.js +151 -138
  130. package/dist/commands/sources/schema-repair.js +5 -3
  131. package/dist/commands/sources/self-update.js +9 -7
  132. package/dist/commands/sources/source-add.js +116 -154
  133. package/dist/commands/sources/source-clone.js +33 -14
  134. package/dist/commands/sources/source-manage.js +43 -32
  135. package/dist/commands/sources/sources-cli.js +12 -7
  136. package/dist/commands/sources/stash-cli.js +12 -5
  137. package/dist/commands/sources/stash-skeleton.js +1 -1
  138. package/dist/commands/tasks/default-tasks.js +13 -13
  139. package/dist/commands/tasks/tasks-cli.js +3 -3
  140. package/dist/commands/tasks/tasks.js +71 -31
  141. package/dist/commands/workflow-cli.js +22 -26
  142. package/dist/core/action-contributors.js +1 -1
  143. package/dist/core/activation-policy.js +49 -0
  144. package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
  145. package/dist/core/adapter/adapters/akm-adapter.js +509 -0
  146. package/dist/core/adapter/adapters/akm-lint.js +381 -0
  147. package/dist/core/adapter/adapters/akm-metadata.js +416 -0
  148. package/dist/core/adapter/adapters/akm-task-adapter.js +150 -0
  149. package/dist/core/adapter/adapters/akm-workflow-adapter.js +196 -0
  150. package/dist/core/adapter/adapters/claude-adapter.js +61 -0
  151. package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
  152. package/dist/core/adapter/adapters/generic-files-adapter.js +117 -0
  153. package/dist/core/adapter/adapters/index.js +80 -0
  154. package/dist/core/adapter/adapters/llm-wiki-adapter.js +413 -0
  155. package/dist/core/adapter/adapters/okf-adapter.js +223 -0
  156. package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
  157. package/dist/core/adapter/adapters/shared.js +286 -0
  158. package/dist/core/adapter/adapters/tool-dir-shared.js +212 -0
  159. package/dist/core/adapter/adapters/website-snapshot-adapter.js +154 -0
  160. package/dist/core/adapter/bundle-adapter.js +4 -0
  161. package/dist/core/adapter/recognize-match.js +42 -0
  162. package/dist/core/adapter/registry.js +56 -0
  163. package/dist/core/adapter/types.js +4 -0
  164. package/dist/core/asset/asset-placement.js +229 -0
  165. package/dist/core/asset/asset-ref.js +107 -78
  166. package/dist/core/asset/asset-serialize.js +20 -0
  167. package/dist/core/asset/frontmatter.js +1 -1
  168. package/dist/core/asset/resolve-ref.js +223 -0
  169. package/dist/core/asset/stash-meta.js +1 -1
  170. package/dist/core/common.js +141 -49
  171. package/dist/core/config/config-io.js +0 -108
  172. package/dist/core/config/config-schema.js +94 -1039
  173. package/dist/core/config/config-sources.js +115 -36
  174. package/dist/core/config/config-types.js +16 -11
  175. package/dist/core/config/config-walker.js +4 -2
  176. package/dist/core/config/config.js +21 -26
  177. package/dist/core/config/engine-semantics.js +0 -4
  178. package/dist/core/config/schema/embedding.js +38 -0
  179. package/dist/core/config/schema/engines.js +116 -0
  180. package/dist/core/config/schema/feedback.js +31 -0
  181. package/dist/core/config/schema/improve-processes.js +395 -0
  182. package/dist/core/config/schema/improve.js +76 -0
  183. package/dist/core/config/schema/index-config.js +183 -0
  184. package/dist/core/config/schema/output.js +15 -0
  185. package/dist/core/config/schema/primitives.js +94 -0
  186. package/dist/core/config/schema/search.js +30 -0
  187. package/dist/core/config/schema/setup.js +27 -0
  188. package/dist/core/config/schema/sources-bundles.js +164 -0
  189. package/dist/core/config/schema/workflow.js +29 -0
  190. package/dist/core/env-secret-ref.js +113 -8
  191. package/dist/core/errors.js +1 -1
  192. package/dist/core/events-types.js +4 -0
  193. package/dist/core/extra-params.js +1 -0
  194. package/dist/core/file-change.js +16 -0
  195. package/dist/core/fs-txn.js +316 -0
  196. package/dist/core/git-message.js +59 -0
  197. package/dist/core/improve-result.js +9 -1
  198. package/dist/core/logs-db.js +1 -1
  199. package/dist/core/maintenance-barrier.js +16 -0
  200. package/dist/core/migration-backup.js +332 -160
  201. package/dist/core/paths.js +3 -6
  202. package/dist/core/platform.js +10 -0
  203. package/dist/core/recognition-util.js +130 -0
  204. package/dist/core/redaction.js +2 -2
  205. package/dist/core/standards/resolve-standards-context.js +47 -64
  206. package/dist/core/standards/resolve-type-conventions.js +3 -3
  207. package/dist/core/state/migrations.js +201 -8
  208. package/dist/core/state-db.js +38 -2
  209. package/dist/core/subprocess.js +303 -0
  210. package/dist/core/time.js +20 -0
  211. package/dist/core/type-presentation.js +130 -0
  212. package/dist/core/write-source.js +39 -67
  213. package/dist/indexer/bundle-identity-guard.js +91 -0
  214. package/dist/indexer/db/graph-db.js +1 -1
  215. package/dist/indexer/db/llm-cache.js +1 -1
  216. package/dist/indexer/ensure-index.js +29 -9
  217. package/dist/indexer/graph/graph-boost.js +28 -24
  218. package/dist/indexer/graph/graph-extraction.js +5 -6
  219. package/dist/indexer/graph/graph-types.js +4 -0
  220. package/dist/indexer/index-written-assets.js +44 -17
  221. package/dist/indexer/indexer.js +289 -153
  222. package/dist/indexer/init.js +18 -25
  223. package/dist/indexer/installations.js +224 -0
  224. package/dist/indexer/passes/dir-staleness.js +2 -1
  225. package/dist/indexer/passes/memory-inference.js +8 -4
  226. package/dist/indexer/passes/metadata.js +96 -243
  227. package/dist/indexer/scan/doc-to-entry.js +123 -0
  228. package/dist/indexer/scan/drain-dir.js +144 -0
  229. package/dist/indexer/search/db-search.js +171 -99
  230. package/dist/indexer/search/fts-query.js +1 -1
  231. package/dist/indexer/search/ranking-contributors.js +57 -7
  232. package/dist/indexer/search/ranking-types.js +4 -0
  233. package/dist/indexer/search/ranking.js +31 -6
  234. package/dist/indexer/search/search-attribution.js +67 -0
  235. package/dist/indexer/search/search-hit-enrichers.js +30 -40
  236. package/dist/indexer/search/search-source.js +109 -52
  237. package/dist/indexer/search/semantic-status.js +4 -1
  238. package/dist/indexer/usage/unmigrated-vaults-guard.js +2 -1
  239. package/dist/indexer/usage/usage-events.js +72 -9
  240. package/dist/indexer/walk/file-context.js +1 -44
  241. package/dist/indexer/walk/matchers.js +16 -32
  242. package/dist/indexer/walk/path-resolver.js +6 -5
  243. package/dist/indexer/walk/walker.js +4 -2
  244. package/dist/integrations/agent/engine-resolution.js +22 -0
  245. package/dist/integrations/agent/model-aliases.js +1 -1
  246. package/dist/integrations/agent/prompts.js +35 -11
  247. package/dist/integrations/agent/spawn.js +41 -270
  248. package/dist/integrations/harnesses/aider/agent-builder.js +2 -2
  249. package/dist/integrations/harnesses/aider/index.js +2 -11
  250. package/dist/integrations/harnesses/amazonq/agent-builder.js +1 -9
  251. package/dist/integrations/harnesses/amazonq/index.js +3 -16
  252. package/dist/integrations/harnesses/claude/config-import.js +1 -3
  253. package/dist/integrations/harnesses/claude/index.js +1 -12
  254. package/dist/integrations/harnesses/claude/session-log.js +27 -65
  255. package/dist/integrations/harnesses/codex/agent-builder.js +1 -2
  256. package/dist/integrations/harnesses/codex/index.js +2 -12
  257. package/dist/integrations/harnesses/copilot/agent-builder.js +2 -3
  258. package/dist/integrations/harnesses/copilot/index.js +1 -12
  259. package/dist/integrations/harnesses/gemini/agent-builder.js +1 -3
  260. package/dist/integrations/harnesses/gemini/index.js +1 -12
  261. package/dist/integrations/harnesses/ids.js +24 -0
  262. package/dist/integrations/harnesses/index.js +27 -2
  263. package/dist/integrations/harnesses/opencode/config-import.js +1 -3
  264. package/dist/integrations/harnesses/opencode/index.js +1 -12
  265. package/dist/integrations/harnesses/opencode/session-log.js +67 -110
  266. package/dist/integrations/harnesses/opencode-sdk/harness.js +2 -11
  267. package/dist/integrations/harnesses/openhands/agent-builder.js +3 -3
  268. package/dist/integrations/harnesses/openhands/index.js +2 -11
  269. package/dist/integrations/harnesses/pi/agent-builder.js +3 -11
  270. package/dist/integrations/harnesses/pi/index.js +3 -15
  271. package/dist/integrations/harnesses/shared.js +17 -0
  272. package/dist/integrations/harnesses/types.js +37 -2
  273. package/dist/integrations/lockfile.js +36 -0
  274. package/dist/integrations/session-logs/index.js +21 -12
  275. package/dist/integrations/session-logs/provider-base.js +113 -0
  276. package/dist/llm/client.js +7 -5
  277. package/dist/llm/embedders/deterministic.js +2 -2
  278. package/dist/llm/embedders/remote.js +8 -4
  279. package/dist/llm/graph-extract.js +7 -2
  280. package/dist/llm/metadata-enhance.js +43 -26
  281. package/dist/llm/structured-call.js +15 -7
  282. package/dist/migrate/legacy/config-source-migration.js +223 -0
  283. package/dist/migrate/legacy/content-migration.js +305 -0
  284. package/dist/migrate/legacy/legacy-layout.js +779 -0
  285. package/dist/migrate/legacy/legacy-paths.js +25 -0
  286. package/dist/migrate/legacy/legacy-stash-json.js +72 -0
  287. package/dist/migrate/legacy/proposal-fs-import.js +168 -0
  288. package/dist/migrate/legacy/task-target-ref-migration.js +272 -0
  289. package/dist/migrate/legacy/three-db-cutover.js +840 -0
  290. package/dist/migrate/legacy/workflow-migrations-bodies.js +52 -0
  291. package/dist/migrate/legacy/workflow-migrations-frozen.js +21 -0
  292. package/dist/migrate/legacy-ref-grammar.js +209 -0
  293. package/dist/output/command-registry.js +27 -0
  294. package/dist/output/html-render.js +11 -16
  295. package/dist/output/renderers.js +32 -276
  296. package/dist/output/shapes/passthrough.js +3 -9
  297. package/dist/output/shapes/registry.js +12 -6
  298. package/dist/output/text/command-format.js +547 -0
  299. package/dist/output/text/helpers.js +15 -1377
  300. package/dist/output/text/proposal-format.js +230 -0
  301. package/dist/output/text/registry.js +12 -6
  302. package/dist/output/text/show-directives.js +107 -0
  303. package/dist/output/text/show-format.js +103 -0
  304. package/dist/output/text/workflow-format.js +345 -0
  305. package/dist/output/text.js +1 -3
  306. package/dist/registry/build-index.js +13 -17
  307. package/dist/registry/providers/static-index.js +2 -2
  308. package/dist/registry/resolve.js +4 -90
  309. package/dist/registry/semver.js +93 -0
  310. package/dist/runtime.js +90 -0
  311. package/dist/schemas/akm-config.json +2956 -14890
  312. package/dist/schemas/akm-task.json +2 -2
  313. package/dist/schemas/akm-workflow.json +2 -2
  314. package/dist/scripts/migrate-storage.js +2312 -19642
  315. package/dist/setup/detect.js +5 -7
  316. package/dist/setup/engine-config.js +2 -1
  317. package/dist/setup/registry-stash-loader.js +1 -1
  318. package/dist/setup/semantic-assets.js +12 -9
  319. package/dist/setup/setup.js +109 -39
  320. package/dist/setup/steps/connection-shared.js +120 -0
  321. package/dist/setup/steps/connection.js +50 -274
  322. package/dist/setup/steps/platforms.js +1 -0
  323. package/dist/setup/steps/sources.js +13 -6
  324. package/dist/setup/steps/stashdir.js +5 -2
  325. package/dist/sources/freshness.js +39 -0
  326. package/dist/sources/providers/git-provider.js +29 -33
  327. package/dist/sources/providers/git-stash.js +10 -5
  328. package/dist/sources/providers/provider-utils.js +40 -18
  329. package/dist/sources/providers/website.js +1 -1
  330. package/dist/sources/resolve.js +5 -5
  331. package/dist/sources/snapshot-fetchers/types.js +4 -0
  332. package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +105 -39
  333. package/dist/storage/database.js +47 -3
  334. package/dist/storage/engines/sqlite-migrations.js +34 -16
  335. package/dist/storage/locations.js +1 -2
  336. package/dist/storage/repositories/improve-runs-repository.js +0 -20
  337. package/dist/storage/repositories/index-connection.js +80 -0
  338. package/dist/storage/repositories/index-db.js +4 -3
  339. package/dist/storage/repositories/index-entries-repository.js +952 -0
  340. package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +15 -2
  341. package/dist/storage/repositories/index-entry-types.js +4 -0
  342. package/dist/storage/repositories/index-fts-repository.js +164 -0
  343. package/dist/storage/repositories/index-llm-cache-repository.js +109 -0
  344. package/dist/storage/repositories/index-meta-repository.js +50 -0
  345. package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +241 -100
  346. package/dist/storage/repositories/index-sql.js +12 -0
  347. package/dist/storage/repositories/index-utility-repository.js +369 -0
  348. package/dist/storage/repositories/index-vec-repository.js +245 -0
  349. package/dist/storage/repositories/proposals-repository.js +41 -50
  350. package/dist/storage/repositories/registry-cache.js +1 -1
  351. package/dist/storage/repositories/workflow-runs-repository.js +17 -11
  352. package/dist/tasks/backends/cron.js +5 -5
  353. package/dist/tasks/backends/exec-utils.js +21 -0
  354. package/dist/tasks/backends/index.js +6 -9
  355. package/dist/tasks/backends/launchd.js +16 -17
  356. package/dist/tasks/backends/schtasks.js +33 -41
  357. package/dist/tasks/backends/types.js +4 -0
  358. package/dist/tasks/parser.js +25 -5
  359. package/dist/tasks/runner.js +33 -39
  360. package/dist/tasks/validator.js +5 -6
  361. package/dist/workflows/authoring/authoring.js +8 -11
  362. package/dist/workflows/exec/brief.js +10 -7
  363. package/dist/workflows/exec/report.js +261 -156
  364. package/dist/workflows/exec/run-workflow.js +2 -1
  365. package/dist/workflows/exec/step-work.js +3 -9
  366. package/dist/workflows/program/parser.js +4 -60
  367. package/dist/workflows/renderer.js +11 -60
  368. package/dist/workflows/runtime/checkin.js +1 -1
  369. package/dist/workflows/runtime/plan-classifier.js +7 -4
  370. package/dist/workflows/runtime/runs.js +11 -10
  371. package/dist/workflows/runtime/unit-checkin.js +1 -1
  372. package/dist/workflows/runtime/unit-phases.js +20 -0
  373. package/dist/workflows/runtime/workflow-asset-loader.js +27 -16
  374. package/dist/workflows/validate-summary.js +2 -2
  375. package/dist/workflows/validator.js +18 -2
  376. package/docs/migration/release-notes/0.9.0.md +45 -3
  377. package/docs/migration/v0.8-to-v0.9.md +466 -262
  378. package/docs/{data-and-telemetry.md → reference/data-and-telemetry.md} +61 -17
  379. package/package.json +10 -9
  380. package/schemas/akm-config.json +2956 -14890
  381. package/schemas/akm-task.json +2 -2
  382. package/schemas/akm-workflow.json +2 -2
  383. package/dist/assets/help/help-accept.md +0 -12
  384. package/dist/assets/help/help-improve.md +0 -84
  385. package/dist/assets/help/help-proposals.md +0 -17
  386. package/dist/assets/help/help-propose.md +0 -17
  387. package/dist/assets/help/help-reject.md +0 -11
  388. package/dist/assets/improve-strategies/recombine-only.json +0 -23
  389. package/dist/assets/improve-strategies/synthesize.json +0 -17
  390. package/dist/assets/prompts/procedural-system.md +0 -44
  391. package/dist/assets/prompts/recombine-system.md +0 -40
  392. package/dist/assets/prompts/staleness-detect-system.md +0 -6
  393. package/dist/assets/templates/html/default.html +0 -78
  394. package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
  395. package/dist/assets/wiki/index-template.md +0 -12
  396. package/dist/assets/wiki/ingest-workflow-template.md +0 -83
  397. package/dist/assets/wiki/log-template.md +0 -8
  398. package/dist/assets/wiki/schema-template.md +0 -61
  399. package/dist/commands/improve/calibration.js +0 -161
  400. package/dist/commands/improve/dedup.js +0 -482
  401. package/dist/commands/improve/hot-probation.js +0 -45
  402. package/dist/commands/improve/improve-auto-accept.js +0 -262
  403. package/dist/commands/improve/procedural.js +0 -403
  404. package/dist/commands/improve/recombine.js +0 -843
  405. package/dist/commands/improve/schema-similarity-gate.js +0 -168
  406. package/dist/commands/lint/agent-linter.js +0 -44
  407. package/dist/commands/lint/command-linter.js +0 -44
  408. package/dist/commands/lint/default-linter.js +0 -16
  409. package/dist/commands/lint/fact-linter.js +0 -39
  410. package/dist/commands/lint/knowledge-linter.js +0 -16
  411. package/dist/commands/lint/memory-linter.js +0 -61
  412. package/dist/commands/lint/registry.js +0 -41
  413. package/dist/commands/lint/skill-linter.js +0 -45
  414. package/dist/commands/lint/task-linter.js +0 -50
  415. package/dist/commands/lint/workflow-linter.js +0 -81
  416. package/dist/commands/proposal/legacy-import.js +0 -115
  417. package/dist/commands/wiki-cli.js +0 -291
  418. package/dist/core/asset/asset-registry.js +0 -76
  419. package/dist/core/asset/asset-spec.js +0 -316
  420. package/dist/core/eval/rank-metrics.js +0 -113
  421. package/dist/core/ripgrep/install.js +0 -163
  422. package/dist/core/ripgrep/resolve.js +0 -81
  423. package/dist/indexer/db/db.js +0 -1585
  424. package/dist/indexer/manifest.js +0 -170
  425. package/dist/indexer/passes/metadata-contributors.js +0 -31
  426. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -25
  427. package/dist/output/text/wiki.js +0 -16
  428. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -18228
  429. package/dist/scripts/migrations/v16-to-v17.js +0 -141
  430. package/dist/storage/repositories/consolidation-repository.js +0 -38
  431. package/dist/storage/repositories/recombine-repository.js +0 -213
  432. package/dist/wiki/wiki-templates.js +0 -15
  433. package/dist/wiki/wiki.js +0 -1013
  434. package/dist/workflows/db.js +0 -413
  435. package/docs/README.md +0 -103
  436. package/docs/migration/release-notes/0.9.0-beta.60.md +0 -19
  437. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
  438. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
@@ -11,18 +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 { parseAssetRef, refToString } from "../../core/asset/asset-ref.js";
15
- import { loadConfig } from "../../core/config/config.js";
14
+ import { getSources, loadConfig } from "../../core/config/config.js";
16
15
  import { rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
17
16
  import { appendEvent } from "../../core/events.js";
18
17
  import { isTransientStashPath } from "../../core/paths.js";
19
- import { bumpUtilityScoresBatch, getEntryIdByFilePath } from "../../indexer/db/db.js";
20
18
  import { resolveReadSources } from "../../indexer/read-preflight.js";
21
19
  import { searchLocal } from "../../indexer/search/db-search.js";
20
+ import { getSearchHitAttribution, usageEventAttributionMetadata, } from "../../indexer/search/search-attribution.js";
21
+ import { getEntryIdByFilePath, getItemRefById } from "../../storage/repositories/index-entries-repository.js";
22
+ import { bumpUtilityScoresBatch } from "../../storage/repositories/index-utility-repository.js";
22
23
  import { getCurrentWorkflowScopeKey } from "../../workflows/authoring/scope-key.js";
23
24
  // Eagerly import source providers to trigger self-registration before the
24
25
  // indexer or path-resolution code runs.
25
26
  import "../../sources/providers/index.js";
27
+ import { withStateDbTelemetry } from "../../core/state-db.js";
26
28
  import { insertUsageEvent } from "../../indexer/usage/usage-events.js";
27
29
  import { TELEMETRY_BUSY_TIMEOUT_MS, withIndexDb } from "../../storage/repositories/index-db.js";
28
30
  import { searchRegistry } from "./registry-search.js";
@@ -36,23 +38,14 @@ export async function akmSearch(input) {
36
38
  const parsedSource = parseSearchSource(input.source ?? "stash");
37
39
  const config = loadConfig();
38
40
  // Named-source filter: when --source is not a standard enum value, treat it
39
- // as a named source from config.sources[].name. Validate early (before
41
+ // as a named source (a `bundles` key). Validated early (before
40
42
  // resolveSourceEntries, which can throw STASH_DIR_NOT_FOUND) so that a bad
41
43
  // --source name always produces INVALID_SOURCE_VALUE regardless of stash state.
42
44
  let namedSourceName;
43
45
  let source;
44
46
  if (parsedSource !== "stash" && parsedSource !== "registry" && parsedSource !== "both") {
45
47
  namedSourceName = parsedSource;
46
- // Check that the named source exists in the config before touching the stash.
47
- const configSources = config.sources ?? [];
48
- const foundInConfig = configSources.some((s) => s.name === namedSourceName) || configSources.some((s) => s.path === namedSourceName);
49
- if (!foundInConfig) {
50
- const validNames = configSources.map((s) => s.name).filter((n) => Boolean(n));
51
- const hint = validNames.length > 0
52
- ? `Known source names: ${validNames.join(", ")}`
53
- : "No named sources are configured. Run `akm list` to see installed stashes.";
54
- throw new UsageError(`Unknown source name: "${namedSourceName}". ${hint}`, "INVALID_SOURCE_VALUE");
55
- }
48
+ assertNamedSourceExists(config, namedSourceName);
56
49
  source = "stash";
57
50
  }
58
51
  else {
@@ -79,8 +72,7 @@ export async function akmSearch(input) {
79
72
  warnings: ["No stashes configured. Run `akm init` to create your working stash."],
80
73
  timing: { totalMs: Date.now() - t0 },
81
74
  };
82
- if (!input.skipLogging)
83
- logSearchEvent(query, response, undefined, input.eventSource);
75
+ maybeLogSearchEvent(input, query, response);
84
76
  return response;
85
77
  }
86
78
  // Primary stash directory — used for DB path lookups and as the default
@@ -126,9 +118,7 @@ export async function akmSearch(input) {
126
118
  warnings: localResult?.warnings?.length ? localResult.warnings : undefined,
127
119
  timing: { totalMs: Date.now() - t0, rankMs: localResult?.rankMs, embedMs: localResult?.embedMs },
128
120
  };
129
- if (!input.skipLogging) {
130
- logSearchEvent(query, response, localResult?.mode ?? "keyword", input.eventSource, input.disableScopedUtility === true);
131
- }
121
+ maybeLogSearchEvent(input, query, response, localResult?.mode ?? "keyword");
132
122
  return response;
133
123
  }
134
124
  const registryHits = (registryResult?.hits ?? []).map((hit) => {
@@ -162,8 +152,7 @@ export async function akmSearch(input) {
162
152
  warnings: registryResult?.warnings.length ? registryResult.warnings : undefined,
163
153
  timing: { totalMs: Date.now() - t0 },
164
154
  };
165
- if (!input.skipLogging)
166
- logSearchEvent(query, response, undefined, input.eventSource, input.disableScopedUtility === true);
155
+ maybeLogSearchEvent(input, query, response);
167
156
  return response;
168
157
  }
169
158
  // source === "both"
@@ -180,10 +169,14 @@ export async function akmSearch(input) {
180
169
  warnings: warnings.length ? warnings : undefined,
181
170
  timing: { totalMs: Date.now() - t0 },
182
171
  };
183
- if (!input.skipLogging)
184
- logSearchEvent(query, response, undefined, input.eventSource, input.disableScopedUtility === true);
172
+ maybeLogSearchEvent(input, query, response);
185
173
  return response;
186
174
  }
175
+ function maybeLogSearchEvent(input, query, response, mode) {
176
+ if (input.skipLogging)
177
+ return;
178
+ logSearchEvent(query, response, mode, input.eventSource, input.disableScopedUtility === true, input.attributionProjection);
179
+ }
187
180
  /**
188
181
  * Resolve entry IDs by file_path lookup (exact match, not LIKE).
189
182
  */
@@ -193,9 +186,13 @@ function resolveEntryIds(db, hits) {
193
186
  try {
194
187
  const entryId = getEntryIdByFilePath(db, hit.path);
195
188
  if (entryId !== undefined) {
196
- const parsed = parseAssetRef(hit.ref);
197
- const origin = parsed.origin ?? hit.origin ?? undefined;
198
- results.push({ entryId, ref: refToString({ ...parsed, ...(origin ? { origin } : {}) }) });
189
+ // F4c: persist the DURABLE fully-qualified `bundle//conceptId` spelling,
190
+ // derived from the resolved entry row's `item_ref` (D-R3: durable keys
191
+ // come from the resolved item, never raw input).
192
+ const itemRef = getItemRefById(db, entryId);
193
+ if (itemRef !== null) {
194
+ results.push({ entryId, ref: itemRef, hit });
195
+ }
199
196
  }
200
197
  }
201
198
  catch {
@@ -219,7 +216,7 @@ function resolveEntryIds(db, hits) {
219
216
  * Per-entry events are recorded only for stash hits because registry hits
220
217
  * have no local entry_id to reference.
221
218
  */
222
- function logSearchEvent(query, response, mode = "keyword", eventSource = "user", disableScopedUtility = false) {
219
+ function logSearchEvent(query, response, mode = "keyword", eventSource = "user", disableScopedUtility = false, attributionProjection = "full") {
223
220
  // Emit a structured event to events.jsonl so workflow-trace consumers
224
221
  // detect akm search invocations without relying on stdout scraping.
225
222
  const stashHits = response.hits.filter((h) => h.type !== "registry");
@@ -236,21 +233,42 @@ function logSearchEvent(query, response, mode = "keyword", eventSource = "user",
236
233
  // Under contention these usage hints are skipped, not waited for.
237
234
  withIndexDb((db) => {
238
235
  const resolved = resolveEntryIds(db, stashHits.slice(0, 50));
239
- for (const { entryId, ref } of resolved) {
240
- insertUsageEvent(db, {
236
+ // usage_events telemetry now writes to state.db (Chunk-8 WI-8.3);
237
+ // entry_id/entry_ref are resolved from index.db above and carried across.
238
+ const stashHitCount = response.hits.length;
239
+ const registryHitCount = Array.isArray(response.registryHits) ? response.registryHits.length : 0;
240
+ withStateDbTelemetry((stateDb) => {
241
+ for (const { entryId, ref, hit } of resolved) {
242
+ insertUsageEvent(stateDb, {
243
+ event_type: "search",
244
+ query,
245
+ entry_id: entryId,
246
+ entry_ref: ref,
247
+ metadata: usageEventAttributionMetadata(getSearchHitAttribution(hit), ref, attributionProjection),
248
+ source: eventSource,
249
+ });
250
+ }
251
+ // Count registry hits separately so registry-only searches record a
252
+ // non-zero resultCount. response.hits is always [] when source="registry".
253
+ insertUsageEvent(stateDb, {
241
254
  event_type: "search",
242
255
  query,
243
- entry_id: entryId,
244
- entry_ref: ref,
256
+ metadata: JSON.stringify({
257
+ resultCount: stashHitCount + registryHitCount,
258
+ stashHitCount,
259
+ registryHitCount,
260
+ resolvedCount: resolved.length,
261
+ mode,
262
+ }),
245
263
  source: eventSource,
246
264
  });
247
- }
265
+ }, TELEMETRY_BUSY_TIMEOUT_MS);
248
266
  // Bump utility scores for all resolved entries (MemRL retrieval signal).
249
267
  // The indexer overwrites these at next reindex; bumps are temporary hints.
250
268
  // Gated to user-sourced events: pipeline searches (improve probes, task
251
269
  // runner) must not feed the utility signal (meta-review 05 DRIFT-6 —
252
270
  // the bump previously fired unconditionally, so even correctly-tagged
253
- // machine traffic inflated utility).
271
+ // machine traffic inflated utility). utility_scores stays in index.db.
254
272
  const resolvedIds = eventSource === "user" ? resolved.map((r) => r.entryId).filter((id) => id !== undefined) : [];
255
273
  if (resolvedIds.length > 0) {
256
274
  let scopeKey;
@@ -264,22 +282,6 @@ function logSearchEvent(query, response, mode = "keyword", eventSource = "user",
264
282
  }
265
283
  bumpUtilityScoresBatch(db, resolvedIds, 1.0, 0.1, scopeKey);
266
284
  }
267
- // Count registry hits separately so registry-only searches record a
268
- // non-zero resultCount. response.hits is always [] when source="registry".
269
- const stashHitCount = response.hits.length;
270
- const registryHitCount = Array.isArray(response.registryHits) ? response.registryHits.length : 0;
271
- insertUsageEvent(db, {
272
- event_type: "search",
273
- query,
274
- metadata: JSON.stringify({
275
- resultCount: stashHitCount + registryHitCount,
276
- stashHitCount,
277
- registryHitCount,
278
- resolvedCount: resolved.length,
279
- mode,
280
- }),
281
- source: eventSource,
282
- });
283
285
  }, { busyTimeoutMs: TELEMETRY_BUSY_TIMEOUT_MS });
284
286
  }
285
287
  catch (err) {
@@ -288,6 +290,23 @@ function logSearchEvent(query, response, mode = "keyword", eventSource = "user",
288
290
  }
289
291
  }
290
292
  // ── Helpers ──────────────────────────────────────────────────────────────────
293
+ /**
294
+ * Validate a named `--source` against the bundle-derived source list (0.9.0
295
+ * spec §10.1: a named source is a `bundles` key, matched via its derived
296
+ * source entry's `name`, or an exact path). Throws INVALID_SOURCE_VALUE with
297
+ * the known names before any stash access can fail differently.
298
+ */
299
+ function assertNamedSourceExists(config, namedSourceName) {
300
+ const configSources = getSources(config);
301
+ const foundInConfig = configSources.some((s) => s.name === namedSourceName) || configSources.some((s) => s.path === namedSourceName);
302
+ if (!foundInConfig) {
303
+ const validNames = configSources.map((s) => s.name).filter((n) => Boolean(n));
304
+ const hint = validNames.length > 0
305
+ ? `Known source names: ${validNames.join(", ")}`
306
+ : "No named sources are configured. Run `akm list` to see installed stashes.";
307
+ throw new UsageError(`Unknown source name: "${namedSourceName}". ${hint}`, "INVALID_SOURCE_VALUE");
308
+ }
309
+ }
291
310
  function normalizeLimit(limit) {
292
311
  if (typeof limit !== "number" || Number.isNaN(limit) || limit <= 0) {
293
312
  return DEFAULT_LIMIT;
@@ -399,9 +418,3 @@ export function entryMatchesScopeFilters(scope, filters) {
399
418
  }
400
419
  return true;
401
420
  }
402
- /**
403
- * Merge stash hits and registry hits via simple concatenation.
404
- */
405
- export function mergeSearchHits(localHits, registryHits, limit) {
406
- return [...localHits, ...registryHits].slice(0, limit);
407
- }
@@ -8,100 +8,45 @@
8
8
  *
9
9
  * show(ref) → indexer.lookup(ref) → readFile(entry.filePath)
10
10
  *
11
- * The richer presentation logic (matchers, renderers, wiki-root handling,
12
- * edit-hints, summary-detail truncation) lives below in this file. The flow:
11
+ * The richer presentation logic (matchers, renderers, edit-hints,
12
+ * summary-detail truncation) lives below in this file. The flow:
13
13
  *
14
- * 1. Special-case wiki-root refs (`wiki:<name>` with no page path).
15
- * 2. Auto-index when stale so the index is current.
16
- * 3. Ask `indexer.lookup(ref)` for the row in the FTS index.
17
- * 4. Render the file via the matcher/renderer pipeline.
14
+ * 1. Auto-index when stale so the index is current.
15
+ * 2. Ask `indexer.lookup(ref)` for the row in the FTS index.
16
+ * 3. Render the file via the matcher/renderer pipeline.
18
17
  */
19
18
  import fs from "node:fs";
20
- import path from "node:path";
21
19
  import { findCittyTopLevelCommandIndex } from "../../cli/parse-args.js";
22
- import { parseAssetRef, refToString } from "../../core/asset/asset-ref.js";
20
+ import { recognizeMatch } from "../../core/adapter/recognize-match.js";
23
21
  import { parseFrontmatter } from "../../core/asset/frontmatter.js";
22
+ import { displayRef, parseQualifiedRefInput } from "../../core/asset/resolve-ref.js";
24
23
  import { META_DIR, parseMetaRef, resolveMetaFilePath } from "../../core/asset/stash-meta.js";
25
24
  import { asNonEmptyString } from "../../core/common.js";
26
25
  import { getIndexPassConfig, loadConfig } from "../../core/config/config.js";
27
26
  import { NotFoundError, rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
28
27
  import { appendEvent, readEvents } from "../../core/events.js";
29
- import { closeDatabase, computeBodyHash, findEntryIdByRef, getEntryIdByFilePath, openExistingDatabase, } from "../../indexer/db/db.js";
28
+ import { withStateDbTelemetry } from "../../core/state-db.js";
30
29
  import { hasGraphData } from "../../indexer/db/graph-db.js";
31
30
  import { listRelatedPathsForFile } from "../../indexer/graph/graph-boost.js";
32
31
  import { extractGraphForSingleFile } from "../../indexer/graph/graph-extraction.js";
33
32
  import { lookup } from "../../indexer/indexer.js";
34
33
  import { ensurePrimaryIndexForRead, resolveReadSources } from "../../indexer/read-preflight.js";
34
+ import { usageEventAttributionMetadata } from "../../indexer/search/search-attribution.js";
35
35
  import { buildEditHint, findSourceForPath, isEditable, resolveSourceEntries } from "../../indexer/search/search-source.js";
36
36
  import { insertUsageEvent } from "../../indexer/usage/usage-events.js";
37
- import { buildFileContext, buildRenderContext, getRenderer, runMatchers } from "../../indexer/walk/file-context.js";
37
+ import { buildFileContext, buildRenderContext, getRenderer } from "../../indexer/walk/file-context.js";
38
38
  import { resolveAssetPath } from "../../indexer/walk/path-resolver.js";
39
39
  import { resolveIndexPassLLM } from "../../llm/index-passes.js";
40
40
  import { resolveSourcesForOrigin } from "../../registry/origin-resolve.js";
41
41
  import { resolveStorageLocations } from "../../storage/locations.js";
42
+ import { closeDatabase, openExistingDatabase } from "../../storage/repositories/index-connection.js";
42
43
  import { TELEMETRY_BUSY_TIMEOUT_MS, withIndexDb } from "../../storage/repositories/index-db.js";
44
+ import { findEntryIdByRef, getEntryById, getEntryIdByFilePath, getItemRefById, } from "../../storage/repositories/index-entries-repository.js";
45
+ import { computeBodyHash } from "../../storage/repositories/index-llm-cache-repository.js";
43
46
  // Eagerly import source providers to trigger self-registration.
44
47
  import "../../sources/providers/index.js";
45
48
  import { getCurrentWorkflowScopeKey } from "../../workflows/authoring/scope-key.js";
46
49
  import { getActiveWorkflowRun } from "../../workflows/runtime/runs.js";
47
- /**
48
- * Show a wiki root (no page path) — returns the same payload as
49
- * `akm wiki show <name>`.
50
- */
51
- async function showWikiRoot(stashDir, wikiName) {
52
- const { showWiki } = await import("../../wiki/wiki.js");
53
- const result = showWiki(stashDir, wikiName);
54
- return {
55
- type: "wiki",
56
- name: result.ref,
57
- path: result.path,
58
- ...(result.description ? { description: result.description } : {}),
59
- origin: null,
60
- editable: false,
61
- pages: result.pages,
62
- raws: result.raws,
63
- ...(result.lastModified ? { lastModified: result.lastModified } : {}),
64
- recentLog: result.recentLog,
65
- };
66
- }
67
- async function showWikiRootForSource(stashDir, source, wikiName) {
68
- const { showWikiAtPath } = await import("../../wiki/wiki.js");
69
- if (source.wikiName === wikiName) {
70
- const result = showWikiAtPath(wikiName, source.path);
71
- return {
72
- type: "wiki",
73
- name: result.ref,
74
- path: result.path,
75
- ...(result.description ? { description: result.description } : {}),
76
- origin: null,
77
- editable: false,
78
- pages: result.pages,
79
- raws: result.raws,
80
- ...(result.lastModified ? { lastModified: result.lastModified } : {}),
81
- recentLog: result.recentLog,
82
- };
83
- }
84
- return showWikiRoot(stashDir, wikiName);
85
- }
86
- function resolveRegisteredWikiAssetPath(wikiRoot, wikiName, assetName) {
87
- const pageName = assetName === wikiName ? "" : assetName.slice(wikiName.length + 1);
88
- if (!pageName) {
89
- throw new NotFoundError(`Wiki page not found: wiki:${assetName}`);
90
- }
91
- const candidate = path.resolve(wikiRoot, `${pageName}.md`);
92
- const resolvedRoot = fs.realpathSync(wikiRoot);
93
- if (!candidate.startsWith(resolvedRoot + path.sep)) {
94
- throw new UsageError("Ref resolves outside the stash root.", "PATH_ESCAPE_VIOLATION");
95
- }
96
- if (!fs.existsSync(candidate) || !fs.statSync(candidate).isFile()) {
97
- throw new NotFoundError(`Stash asset not found for ref: wiki:${assetName}`);
98
- }
99
- const realTarget = fs.realpathSync(candidate);
100
- if (!realTarget.startsWith(resolvedRoot + path.sep)) {
101
- throw new UsageError("Ref resolves outside the stash root.", "PATH_ESCAPE_VIOLATION");
102
- }
103
- return realTarget;
104
- }
105
50
  /**
106
51
  * Unified show: queries the local FTS5 index, then falls back to on-disk
107
52
  * type-dir resolution if the index has no row. Spec §6.2; no remote provider
@@ -122,30 +67,6 @@ export async function akmShowUnified(input) {
122
67
  if (metaRef)
123
68
  return showStashMeta(metaRef);
124
69
  }
125
- // 0. Wiki-root shortcut: `wiki:<name>` with no page path routes to the
126
- // wiki summary (same payload as `akm wiki show <name>`). Honour
127
- // `parsed.origin` by resolving against the matching stash source(s),
128
- // falling back to the primary stash when no origin is given.
129
- {
130
- const parsed = parseAssetRef(ref);
131
- if (parsed.type === "wiki" && !parsed.name.includes("/")) {
132
- const allSources = resolveSourceEntries();
133
- const searchSources = resolveSourcesForOrigin(parsed.origin, allSources);
134
- let lastError;
135
- for (const source of searchSources) {
136
- try {
137
- return await showWikiRootForSource(allSources[0]?.path ?? source.path, source, parsed.name);
138
- }
139
- catch (err) {
140
- if (!(err instanceof NotFoundError))
141
- throw err;
142
- lastError = err;
143
- }
144
- }
145
- throw (lastError ??
146
- new NotFoundError(`Wiki not found: ${parsed.name}. Run \`akm wiki create ${parsed.name}\` to create it.`));
147
- }
148
- }
149
70
  // Auto-index when stale so the index is current before lookup.
150
71
  const { primarySource } = resolveReadSources();
151
72
  await ensurePrimaryIndexForRead(primarySource);
@@ -159,11 +80,13 @@ export async function akmShowUnified(input) {
159
80
  enforceScopeOrThrow(result.path, ref, input.scope);
160
81
  }
161
82
  // Count prior shows of this ref before logging the current one.
162
- const priorShowCount = recentShowCount(ref);
163
- logShowEvent(ref, input.eventSource, result.path, result.origin);
164
- if (priorShowCount >= 2) {
165
- // Agent has shown this same asset 3+ times — inject a loop-break hint.
166
- result.showLoopWarning = priorShowCount + 1;
83
+ if (!input.skipLogging) {
84
+ const priorShowCount = recentShowCount(ref);
85
+ logShowEvent(ref, input.eventSource, result.path, result.origin);
86
+ if (priorShowCount >= 2) {
87
+ // Agent has shown this same asset 3+ times — inject a loop-break hint.
88
+ result.showLoopWarning = priorShowCount + 1;
89
+ }
167
90
  }
168
91
  return result;
169
92
  }
@@ -260,8 +183,10 @@ function recentShowCount(ref) {
260
183
  function logShowEvent(ref, eventSource = "user", filePath, origin) {
261
184
  // Emit a structured event to events.jsonl so workflow-trace consumers
262
185
  // detect akm show invocations without relying on stdout scraping.
263
- const parsed = parseAssetRef(ref);
264
- const eventRef = refToString({ ...parsed, ...(parsed.origin || !origin ? {} : { origin }) });
186
+ const parsed = parseQualifiedRefInput(ref);
187
+ // New-grammar display ref: also the lookup key below, which `findEntryIdByRef`
188
+ // resolves against `item_ref`.
189
+ const eventRef = displayRef({ type: parsed.type, name: parsed.name, bundleId: parsed.origin ?? origin ?? undefined });
265
190
  appendEvent({ eventType: "show", ref: eventRef, metadata: { type: parsed.type, name: parsed.name } });
266
191
  // Detect if this show is a selection from a recent search result.
267
192
  try {
@@ -294,12 +219,22 @@ function logShowEvent(ref, eventSource = "user", filePath, origin) {
294
219
  }
295
220
  try {
296
221
  withIndexDb((db) => {
297
- insertUsageEvent(db, {
298
- event_type: "show",
299
- entry_ref: eventRef,
300
- entry_id: filePath ? getEntryIdByFilePath(db, filePath) : findEntryIdByRef(db, eventRef),
301
- source: eventSource,
302
- });
222
+ const entryId = filePath ? getEntryIdByFilePath(db, filePath) : findEntryIdByRef(db, eventRef);
223
+ // The DURABLE usage-event key is the resolved entry's fully-qualified
224
+ // `item_ref`; the new-grammar `eventRef` is the fallback for an
225
+ // unresolved / not-yet-indexed show. entry_id/item_ref resolve from
226
+ // index.db (`db`); the usage_events write lands in state.db (WI-8.3).
227
+ const entryRef = (entryId !== undefined ? getItemRefById(db, entryId) : null) ?? eventRef;
228
+ const entry = entryId !== undefined ? getEntryById(db, entryId) : undefined;
229
+ withStateDbTelemetry((stateDb) => {
230
+ insertUsageEvent(stateDb, {
231
+ event_type: "show",
232
+ entry_ref: entryRef,
233
+ entry_id: entryId,
234
+ metadata: usageEventAttributionMetadata(entry?.entry.derivedFrom ? { memoryInference: { exposure: "direct" } } : undefined, entryRef),
235
+ source: eventSource,
236
+ });
237
+ }, TELEMETRY_BUSY_TIMEOUT_MS);
303
238
  }, { busyTimeoutMs: TELEMETRY_BUSY_TIMEOUT_MS });
304
239
  }
305
240
  catch (err) {
@@ -309,51 +244,34 @@ function logShowEvent(ref, eventSource = "user", filePath, origin) {
309
244
  }
310
245
  /** @internal Use akmShowUnified() for all external callers. */
311
246
  export async function showLocal(input) {
312
- const parsed = parseAssetRef(input.ref);
247
+ const parsed = parseQualifiedRefInput(input.ref);
313
248
  const displayType = parsed.type;
314
249
  const config = loadConfig();
315
250
  const allSources = resolveSourceEntries(input.stashDir);
316
251
  const searchSources = resolveSourcesForOrigin(parsed.origin, allSources);
317
252
  const allSourceDirs = searchSources.map((s) => s.path);
318
- let assetPath;
319
- const matchedSource = parsed.type === "wiki" ? searchSources.find((source) => parsed.name.startsWith(`${source.wikiName}/`)) : undefined;
320
- let lastError;
321
- if (parsed.type === "wiki" && matchedSource?.wikiName) {
322
- try {
323
- assetPath = resolveRegisteredWikiAssetPath(matchedSource.path, matchedSource.wikiName, parsed.name);
324
- }
325
- catch (err) {
326
- lastError = err instanceof Error ? err : new Error(String(err));
327
- }
328
- }
329
- if (!assetPath) {
330
- const resolvedAssetPath = await resolveAssetPath(parsed, {
331
- stashDir: input.stashDir,
332
- mode: "index-first",
333
- });
334
- assetPath = resolvedAssetPath ?? undefined;
335
- }
253
+ const resolvedAssetPath = await resolveAssetPath(parsed, {
254
+ stashDir: input.stashDir,
255
+ mode: "index-first",
256
+ });
257
+ const assetPath = resolvedAssetPath ?? undefined;
336
258
  if (!assetPath && parsed.origin && searchSources.length === 0) {
337
259
  const installCmd = `akm add ${parsed.origin}`;
338
260
  throw new NotFoundError(`Stash asset not found for ref: ${displayType}:${parsed.name}. ` +
339
261
  `Stash "${parsed.origin}" is not installed. Run: ${installCmd}`);
340
262
  }
341
263
  if (!assetPath) {
342
- throw (lastError ??
343
- new NotFoundError(`Stash asset not found for ref: ${displayType}:${parsed.name}. ` +
344
- "Check the name with `akm search` or verify the asset exists in your stash."));
264
+ throw new NotFoundError(`Stash asset not found for ref: ${displayType}:${parsed.name}. ` +
265
+ "Check the name with `akm search` or verify the asset exists in your stash.");
345
266
  }
346
- const source = matchedSource ?? findSourceForPath(assetPath, allSources);
267
+ const source = findSourceForPath(assetPath, allSources);
347
268
  const sourceStashDir = source?.path ?? allSourceDirs[0];
348
269
  if (!sourceStashDir) {
349
270
  throw new UsageError(`Could not determine stash root for asset: ${displayType}:${parsed.name}. ` +
350
271
  "Run `akm init` to create the stash directory, or check `akm stash list` for configured paths.");
351
272
  }
352
273
  const fileCtx = buildFileContext(sourceStashDir, assetPath);
353
- const forcedWikiMatch = parsed.type === "wiki" && source?.wikiName && parsed.name.startsWith(`${source.wikiName}/`)
354
- ? { type: "wiki", specificity: 20, renderer: "wiki-md", meta: {} }
355
- : undefined;
356
- const match = forcedWikiMatch ?? (await runMatchers(fileCtx));
274
+ const match = recognizeMatch(fileCtx);
357
275
  if (!match) {
358
276
  throw new UsageError(`Could not display asset "${displayType}:${parsed.name}" — unsupported file type or unrecognized layout`);
359
277
  }
@@ -477,7 +395,7 @@ async function maybeExtractGraphInline(config, sourceStashDir, assetPath) {
477
395
  * renderer graph. Spec §6.2's literal flow.
478
396
  */
479
397
  export async function showByRef(ref) {
480
- const parsed = parseAssetRef(ref);
398
+ const parsed = parseQualifiedRefInput(ref);
481
399
  const entry = await lookup(parsed);
482
400
  if (!entry) {
483
401
  throw new NotFoundError(`Asset not found for ref: ${parsed.type}:${parsed.name}`);
@@ -587,8 +505,9 @@ export function normalizeShowArgv(argv) {
587
505
  }
588
506
  if (arg === "--format" || arg === "--detail" || arg === "--shape") {
589
507
  globalFlags.push(arg);
590
- if (rest[i + 1] !== undefined) {
591
- globalFlags.push(rest[i + 1]);
508
+ const nextArg = rest[i + 1];
509
+ if (nextArg !== undefined) {
510
+ globalFlags.push(nextArg);
592
511
  i++;
593
512
  }
594
513
  continue;
@@ -8,14 +8,15 @@
8
8
  * heuristic derivation, LLM enrichment) is testable in isolation and the
9
9
  * CLI entry point stays focused on argument parsing + output routing.
10
10
  */
11
+ import { getParsedInvocation } from "../cli/invocation.js";
11
12
  import { serializeFrontmatter } from "../core/asset/asset-serialize.js";
12
13
  import { toErrorMessage, tryReadStdinText } from "../core/common.js";
13
- import { getDefaultLlmConfig, loadConfig } from "../core/config/config.js";
14
+ import { loadConfig } from "../core/config/config.js";
14
15
  import { UsageError } from "../core/errors.js";
15
16
  import { DURATION_UNITS, parseDuration as parseDurationSpec } from "../core/time.js";
16
17
  import { warn } from "../core/warn.js";
17
18
  import { SCOPE_KEYS } from "../indexer/passes/metadata.js";
18
- import { parseFlagValue } from "../output/context.js";
19
+ import { getDefaultLlmConfig } from "../integrations/agent/engine-resolution.js";
19
20
  /**
20
21
  * Parse a shorthand duration string to a number of milliseconds.
21
22
  * Supports the CLI-wide canonical grammar: `30d` (days), `12h` (hours),
@@ -215,13 +216,14 @@ Return ONLY the JSON object, no prose, no markdown fences.`;
215
216
  export function resolveRememberContentArg(content) {
216
217
  if (content === undefined)
217
218
  return undefined;
218
- const parsedFormat = parseFlagValue(process.argv, "--format");
219
+ const invocation = getParsedInvocation();
220
+ const parsedFormat = invocation.getFlagValue("--format");
219
221
  if (parsedFormat !== undefined &&
220
222
  content === parsedFormat &&
221
223
  wasRememberFlagValueConsumedAsContent(content, parsedFormat, "--format")) {
222
224
  return undefined;
223
225
  }
224
- const parsedDetail = parseFlagValue(process.argv, "--detail");
226
+ const parsedDetail = invocation.getFlagValue("--detail");
225
227
  if (parsedDetail !== undefined &&
226
228
  content === parsedDetail &&
227
229
  wasRememberFlagValueConsumedAsContent(content, parsedDetail, "--detail")) {
@@ -230,7 +232,7 @@ export function resolveRememberContentArg(content) {
230
232
  return content;
231
233
  }
232
234
  function wasRememberFlagValueConsumedAsContent(content, flagValue, flagName) {
233
- const argv = process.argv.slice(2);
235
+ const argv = getParsedInvocation().userArgs;
234
236
  const rememberIndex = argv.indexOf("remember");
235
237
  const tokens = rememberIndex >= 0 ? argv.slice(rememberIndex + 1) : argv;
236
238
  let flagIndex = -1;
@@ -5,13 +5,14 @@ import fs from "node:fs";
5
5
  import path from "node:path";
6
6
  import * as p from "../../cli/clack.js";
7
7
  import { defineJsonCommand, output } from "../../cli/shared.js";
8
+ import { decideDangerousKeyInstall } from "../../core/activation-policy.js";
8
9
  import { UsageError } from "../../core/errors.js";
9
10
  import { appendEvent } from "../../core/events.js";
10
11
  import { warn } from "../../core/warn.js";
11
12
  import { akmRemove } from "./installed-stashes.js";
12
13
  import { akmAdd } from "./source-add.js";
13
14
  import { addStash } from "./source-manage.js";
14
- // ── Shared website-options helper (also used by wikiRegisterCommand) ──────────
15
+ // ── Shared website-options helper ──────────
15
16
  export function buildWebsiteOptions(args) {
16
17
  const websiteOptions = {};
17
18
  if (typeof args["max-pages"] === "string" && args["max-pages"].length > 0)
@@ -79,9 +80,15 @@ export async function auditInstalledStashForDangerousKeys(opts) {
79
80
  catch {
80
81
  return { blocked: false };
81
82
  }
82
- if (allFindings.length === 0)
83
+ // The workspace activation policy fixes the baseline stance; the interactive
84
+ // confirm / rollback below is layered on top of the `"gate"` stance only.
85
+ const stance = decideDangerousKeyInstall({
86
+ findingsPresent: allFindings.length > 0,
87
+ allowInsecure: allowDangerousKeys,
88
+ });
89
+ if (stance === "allow")
83
90
  return { blocked: false };
84
- if (allowDangerousKeys) {
91
+ if (stance === "warn-allow") {
85
92
  // Operator has explicitly accepted the risk — warn and continue.
86
93
  for (const f of allFindings) {
87
94
  warn(`[dangerous-vault-key] ${f.relPath}: key \`${f.keyName}\` in ${f.vaultRef} can hijack process execution via \`akm env run\`. Proceeding because --allow-insecure was set.`);
@@ -166,10 +173,6 @@ export const addCommand = defineJsonCommand({
166
173
  description: "Mark a git stash as writable so changes can be pushed back",
167
174
  default: false,
168
175
  },
169
- type: {
170
- type: "string",
171
- description: "Override asset type for all files in this stash (currently supports: wiki)",
172
- },
173
176
  "max-pages": { type: "string", description: "Maximum pages to crawl for website sources (default: 50)" },
174
177
  "max-depth": { type: "string", description: "Maximum crawl depth for website sources (default: 3)" },
175
178
  "allow-insecure": {
@@ -228,25 +231,9 @@ export const addCommand = defineJsonCommand({
228
231
  warn("Warning: source URL uses plain HTTP (not HTTPS). --allow-insecure was set; an on-path attacker could substitute a malicious payload.");
229
232
  }
230
233
  const websiteOptions = buildWebsiteOptions(args);
231
- if (args.type === "wiki") {
232
- const { registerWikiSource } = await import("./source-add.js");
233
- const result = await registerWikiSource({
234
- ref,
235
- name: args.name,
236
- options: Object.keys(websiteOptions).length > 0 ? websiteOptions : undefined,
237
- writable: args.writable,
238
- });
239
- appendEvent({
240
- eventType: "add",
241
- metadata: { target: ref, type: "wiki", name: args.name ?? null, writable: args.writable === true },
242
- });
243
- output("add", result);
244
- return;
245
- }
246
234
  const result = await akmAdd({
247
235
  ref,
248
236
  name: args.name,
249
- overrideType: args.type,
250
237
  options: Object.keys(websiteOptions).length > 0 ? websiteOptions : undefined,
251
238
  writable: args.writable,
252
239
  });
@@ -255,7 +242,6 @@ export const addCommand = defineJsonCommand({
255
242
  metadata: {
256
243
  target: ref,
257
244
  name: args.name ?? null,
258
- overrideType: args.type ?? null,
259
245
  writable: args.writable === true,
260
246
  },
261
247
  });