akm-cli 0.9.0-rc.0 → 0.9.0-rc.13

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 (598) hide show
  1. package/CHANGELOG.md +1283 -22
  2. package/README.md +62 -37
  3. package/SECURITY.md +46 -31
  4. package/dist/akm +162 -38
  5. package/dist/akm-migrate +44 -0
  6. package/dist/assets/backends/schtasks-template.xml +2 -1
  7. package/dist/assets/hints/cli-hints-full.md +268 -118
  8. package/dist/assets/hints/cli-hints-short.md +87 -24
  9. package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
  10. package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
  11. package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
  12. package/dist/assets/improve-strategies/frequent.json +15 -0
  13. package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
  14. package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
  15. package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
  16. package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
  17. package/dist/assets/improve-strategies/reflect-distill.json +30 -0
  18. package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
  19. package/dist/assets/prompts/consolidate-system.md +5 -5
  20. package/dist/assets/prompts/extract-session.md +2 -6
  21. package/dist/assets/prompts/memory-infer-user.md +2 -3
  22. package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
  23. package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
  24. package/dist/assets/prompts/reflect-output-repair.md +3 -0
  25. package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
  26. package/dist/assets/stash-skeleton/README.md +38 -10
  27. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
  28. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
  29. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
  30. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
  38. package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
  39. package/dist/assets/tasks/core/extract.yml +3 -2
  40. package/dist/assets/tasks/core/improve.yml +2 -1
  41. package/dist/assets/tasks/core/index-refresh.yml +1 -0
  42. package/dist/assets/tasks/core/sync.yml +1 -0
  43. package/dist/assets/tasks/core/version-check.yml +2 -1
  44. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  45. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  46. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  47. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  48. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  49. package/dist/assets/templates/html/health.html +5 -4
  50. package/dist/assets/workflows/workflow-template.md +31 -15
  51. package/dist/cli/invocation.js +279 -0
  52. package/dist/cli/parse-args.js +5 -90
  53. package/dist/cli/retired-commands.js +78 -0
  54. package/dist/cli/shared.js +158 -48
  55. package/dist/cli-node.mjs +2 -1
  56. package/dist/cli.js +747 -293
  57. package/dist/commands/agent/agent-dispatch.js +19 -18
  58. package/dist/commands/agent/agent-support.js +0 -24
  59. package/dist/commands/agent/contribute-cli.js +43 -97
  60. package/dist/commands/completions.js +80 -23
  61. package/dist/commands/config-cli.js +44 -281
  62. package/dist/commands/env/env-binding.js +99 -0
  63. package/dist/commands/env/env-cli.js +84 -224
  64. package/dist/commands/env/env.js +12 -163
  65. package/dist/commands/env/marker-path.js +6 -0
  66. package/dist/commands/env/secret-cli.js +45 -61
  67. package/dist/commands/env/secret.js +32 -62
  68. package/dist/commands/feedback-cli.js +179 -85
  69. package/dist/commands/health/accept-rate.js +58 -0
  70. package/dist/commands/health/advisories.js +7 -8
  71. package/dist/commands/health/checks.js +279 -94
  72. package/dist/commands/health/html-report.js +197 -578
  73. package/dist/commands/health/improve-metrics.js +277 -246
  74. package/dist/commands/health/llm-usage.js +19 -19
  75. package/dist/commands/health/md-report.js +16 -7
  76. package/dist/commands/health/metrics.js +67 -32
  77. package/dist/commands/health/renderers.js +47 -0
  78. package/dist/commands/health/report-view-model.js +508 -0
  79. package/dist/commands/health/stash-exposure.js +1 -1
  80. package/dist/commands/health/surfaces.js +16 -56
  81. package/dist/commands/health/task-runs.js +3 -67
  82. package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
  83. package/dist/commands/health/types-improve.js +29 -0
  84. package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
  85. package/dist/commands/health/types-result.js +7 -0
  86. package/dist/commands/health/types-runs.js +4 -0
  87. package/dist/commands/health/types-session-log.js +4 -0
  88. package/dist/commands/health/types-windows.js +4 -0
  89. package/dist/commands/health/types.js +26 -21
  90. package/dist/commands/health/windows.js +2 -3
  91. package/dist/commands/health.js +296 -167
  92. package/dist/commands/improve/anti-collapse.js +5 -5
  93. package/dist/commands/improve/autonomy-gate.js +68 -0
  94. package/dist/commands/improve/collapse-detector.js +65 -52
  95. package/dist/commands/improve/consolidate/chunking.js +9 -7
  96. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  97. package/dist/commands/improve/consolidate/merge.js +4 -0
  98. package/dist/commands/improve/consolidate.js +454 -1354
  99. package/dist/commands/improve/content-hash.js +39 -0
  100. package/dist/commands/improve/distill/content-repair.js +4 -10
  101. package/dist/commands/improve/distill/promote-memory.js +89 -64
  102. package/dist/commands/improve/distill/quality-gate.js +118 -42
  103. package/dist/commands/improve/distill-guards.js +1 -1
  104. package/dist/commands/improve/distill-promotion-policy.js +33 -888
  105. package/dist/commands/improve/distill.js +607 -363
  106. package/dist/commands/improve/eligibility.js +165 -79
  107. package/dist/commands/improve/extract-cli.js +35 -126
  108. package/dist/commands/improve/extract-prompt.js +6 -35
  109. package/dist/commands/improve/extract.js +640 -391
  110. package/dist/commands/improve/feedback-valence.js +2 -12
  111. package/dist/commands/improve/improve-cli.js +134 -135
  112. package/dist/commands/improve/improve-result-file.js +30 -50
  113. package/dist/commands/improve/improve-run-types.js +4 -0
  114. package/dist/commands/improve/improve-strategies.js +135 -0
  115. package/dist/commands/improve/improve.js +904 -701
  116. package/dist/commands/improve/locks.js +64 -111
  117. package/dist/commands/improve/loop-stages.js +1110 -923
  118. package/dist/commands/improve/memory/derived-ref.js +124 -0
  119. package/dist/commands/improve/memory/memory-belief.js +79 -7
  120. package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
  121. package/dist/commands/improve/memory/memory-improve.js +25 -37
  122. package/dist/commands/improve/outcome-loop.js +25 -88
  123. package/dist/commands/improve/preparation.js +1034 -813
  124. package/dist/commands/improve/proactive-maintenance.js +34 -9
  125. package/dist/commands/improve/proposal-envelope.js +31 -0
  126. package/dist/commands/improve/reflect.js +983 -794
  127. package/dist/commands/improve/run-context.js +119 -0
  128. package/dist/commands/improve/salience.js +24 -127
  129. package/dist/commands/improve/session-asset.js +7 -3
  130. package/dist/commands/improve/shared.js +14 -34
  131. package/dist/commands/improve/source-identity.js +28 -0
  132. package/dist/commands/improve/triage.js +20 -17
  133. package/dist/commands/lint/base-linter.js +340 -313
  134. package/dist/commands/lint/env-key-rules.js +31 -47
  135. package/dist/commands/lint/index.js +185 -30
  136. package/dist/commands/{events.js → log.js} +28 -38
  137. package/dist/commands/migrate-cli.js +54 -0
  138. package/dist/commands/migration-tool.js +55 -0
  139. package/dist/commands/observability-cli.js +70 -208
  140. package/dist/commands/proposal/diff-format.js +50 -0
  141. package/dist/commands/proposal/drain-policies.js +0 -6
  142. package/dist/commands/proposal/drain.js +91 -40
  143. package/dist/commands/proposal/proposal-cli.js +134 -132
  144. package/dist/commands/proposal/proposal-types.js +56 -0
  145. package/dist/commands/proposal/proposal.js +83 -65
  146. package/dist/commands/proposal/propose-cli.js +88 -0
  147. package/dist/commands/proposal/propose.js +105 -88
  148. package/dist/commands/proposal/repository.js +1303 -278
  149. package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
  150. package/dist/commands/proposal/validators/proposal-validators.js +61 -12
  151. package/dist/commands/proposal/validators/proposals.js +6 -8
  152. package/dist/commands/read/curate.js +78 -73
  153. package/dist/commands/read/knowledge.js +510 -13
  154. package/dist/commands/read/registry-search.js +2 -2
  155. package/dist/commands/read/remember-cli.js +84 -15
  156. package/dist/commands/read/search-cli.js +203 -96
  157. package/dist/commands/read/search.js +126 -94
  158. package/dist/commands/read/show.js +226 -250
  159. package/dist/commands/registry-cli.js +34 -60
  160. package/dist/commands/remember.js +18 -57
  161. package/dist/commands/sources/add-cli.js +104 -49
  162. package/dist/commands/sources/bundle-cli.js +166 -0
  163. package/dist/commands/sources/bundle-config-ops.js +63 -0
  164. package/dist/commands/sources/info.js +27 -15
  165. package/dist/commands/sources/init.js +30 -40
  166. package/dist/commands/sources/installed-stashes.js +469 -172
  167. package/dist/commands/sources/migration-help.js +7 -4
  168. package/dist/commands/sources/schema-repair.js +10 -9
  169. package/dist/commands/sources/self-update.js +182 -121
  170. package/dist/commands/sources/source-add.js +169 -178
  171. package/dist/commands/sources/source-clone.js +144 -41
  172. package/dist/commands/sources/source-manage.js +94 -59
  173. package/dist/commands/sources/sources-cli.js +64 -205
  174. package/dist/commands/sources/stash-cli.js +91 -54
  175. package/dist/commands/sources/stash-skeleton.js +1 -1
  176. package/dist/commands/tasks/tasks-cli.js +106 -104
  177. package/dist/commands/tasks/tasks.js +445 -262
  178. package/dist/commands/workflow-cli.js +232 -121
  179. package/dist/core/action-contributors.js +1 -1
  180. package/dist/core/activation-policy.js +49 -0
  181. package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
  182. package/dist/core/adapter/adapters/akm-adapter.js +528 -0
  183. package/dist/core/adapter/adapters/akm-lint.js +392 -0
  184. package/dist/core/adapter/adapters/akm-metadata.js +387 -0
  185. package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
  186. package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
  187. package/dist/core/adapter/adapters/claude-adapter.js +61 -0
  188. package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
  189. package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
  190. package/dist/core/adapter/adapters/index.js +80 -0
  191. package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
  192. package/dist/core/adapter/adapters/okf-adapter.js +391 -0
  193. package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
  194. package/dist/core/adapter/adapters/shared.js +286 -0
  195. package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
  196. package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
  197. package/dist/core/adapter/bundle-adapter.js +4 -0
  198. package/dist/core/adapter/detect-adapter.js +17 -0
  199. package/dist/core/adapter/recognize-match.js +44 -0
  200. package/dist/core/adapter/registry.js +56 -0
  201. package/dist/core/adapter/types.js +4 -0
  202. package/dist/core/asset/akm-markdown.js +30 -0
  203. package/dist/core/asset/asset-placement.js +243 -0
  204. package/dist/core/asset/asset-ref.js +110 -79
  205. package/dist/core/asset/asset-serialize.js +20 -0
  206. package/dist/core/asset/frontmatter.js +28 -12
  207. package/dist/core/asset/markdown.js +40 -51
  208. package/dist/core/asset/resolve-ref.js +274 -0
  209. package/dist/core/asset/stash-meta.js +2 -2
  210. package/dist/core/bundle-id.js +51 -0
  211. package/dist/core/common.js +281 -86
  212. package/dist/core/config/config-io.js +42 -128
  213. package/dist/core/config/config-schema.js +233 -834
  214. package/dist/core/config/config-sources.js +162 -39
  215. package/dist/core/config/config-types.js +16 -11
  216. package/dist/core/config/config-version.js +29 -0
  217. package/dist/core/config/config-walker.js +126 -37
  218. package/dist/core/config/config.js +154 -331
  219. package/dist/core/config/deep-merge.js +41 -0
  220. package/dist/core/config/engine-semantics.js +28 -0
  221. package/dist/core/config/experimental.js +21 -0
  222. package/dist/core/config/schema/embedding.js +38 -0
  223. package/dist/core/config/schema/engines.js +116 -0
  224. package/dist/core/config/schema/experimental.js +47 -0
  225. package/dist/core/config/schema/feedback.js +31 -0
  226. package/dist/core/config/schema/improve-processes.js +389 -0
  227. package/dist/core/config/schema/improve.js +94 -0
  228. package/dist/core/config/schema/index-config.js +176 -0
  229. package/dist/core/config/schema/output.js +18 -0
  230. package/dist/core/config/schema/primitives.js +94 -0
  231. package/dist/core/config/schema/search.js +30 -0
  232. package/dist/core/config/schema/setup.js +18 -0
  233. package/dist/core/config/schema/sources-bundles.js +169 -0
  234. package/dist/core/config/schema/workflow.js +29 -0
  235. package/dist/core/env-secret-ref.js +155 -20
  236. package/dist/core/errors.js +17 -15
  237. package/dist/core/events-types.js +4 -0
  238. package/dist/core/events.js +46 -128
  239. package/dist/core/extra-params.js +62 -0
  240. package/dist/core/file-change.js +17 -0
  241. package/dist/core/file-lock.js +202 -57
  242. package/dist/core/fs-txn.js +392 -0
  243. package/dist/core/git-message.js +59 -0
  244. package/dist/core/improve-result.js +167 -0
  245. package/dist/core/json-schema.js +142 -0
  246. package/dist/core/lesson-lint.js +1 -17
  247. package/dist/core/logs-db.js +1 -1
  248. package/dist/core/maintenance-barrier.js +135 -0
  249. package/dist/core/migration-operation.js +44 -0
  250. package/dist/core/mutation-target.js +78 -0
  251. package/dist/core/paths.js +22 -25
  252. package/dist/core/platform.js +10 -0
  253. package/dist/core/recognition-util.js +128 -0
  254. package/dist/core/redaction.js +392 -0
  255. package/dist/core/standards/resolve-standards-context.js +36 -65
  256. package/dist/core/standards/resolve-stash-standards.js +2 -2
  257. package/dist/core/standards/resolve-type-conventions.js +5 -5
  258. package/dist/core/state/migrations.js +242 -11
  259. package/dist/core/state-db.js +98 -10
  260. package/dist/core/structured.js +1 -1
  261. package/dist/core/subprocess.js +303 -0
  262. package/dist/core/text-truncation.js +9 -5
  263. package/dist/core/time.js +20 -0
  264. package/dist/core/type-presentation.js +130 -0
  265. package/dist/core/warn.js +0 -3
  266. package/dist/core/write-source.js +834 -118
  267. package/dist/indexer/bundle-identity-guard.js +92 -0
  268. package/dist/indexer/db/graph-db.js +1 -25
  269. package/dist/indexer/db/llm-cache.js +1 -1
  270. package/dist/indexer/ensure-index.js +30 -9
  271. package/dist/indexer/graph/graph-boost.js +9 -30
  272. package/dist/indexer/graph/graph-extraction.js +41 -27
  273. package/dist/indexer/graph/graph-types.js +4 -0
  274. package/dist/indexer/index-writer-lock.js +93 -49
  275. package/dist/indexer/index-written-assets.js +100 -53
  276. package/dist/indexer/indexer.js +746 -329
  277. package/dist/indexer/init.js +18 -25
  278. package/dist/indexer/installations.js +142 -0
  279. package/dist/indexer/passes/dir-staleness.js +18 -10
  280. package/dist/indexer/passes/memory-inference.js +25 -15
  281. package/dist/indexer/passes/metadata.js +412 -243
  282. package/dist/indexer/scan/doc-to-entry.js +160 -0
  283. package/dist/indexer/scan/drain-dir.js +134 -0
  284. package/dist/indexer/search/db-search.js +292 -108
  285. package/dist/indexer/search/fts-query.js +64 -0
  286. package/dist/indexer/search/ranking-contributors.js +145 -25
  287. package/dist/indexer/search/ranking-types.js +4 -0
  288. package/dist/indexer/search/ranking.js +28 -71
  289. package/dist/indexer/search/search-attribution.js +67 -0
  290. package/dist/indexer/search/search-fields.js +18 -3
  291. package/dist/indexer/search/search-hit-enrichers.js +30 -40
  292. package/dist/indexer/search/search-source.js +157 -111
  293. package/dist/indexer/search/semantic-status.js +4 -1
  294. package/dist/indexer/usage/usage-events.js +10 -30
  295. package/dist/indexer/walk/file-context.js +3 -45
  296. package/dist/indexer/walk/matchers.js +42 -34
  297. package/dist/indexer/walk/path-resolver.js +11 -5
  298. package/dist/indexer/walk/walker.js +42 -14
  299. package/dist/integrations/agent/builder-shared.js +7 -0
  300. package/dist/integrations/agent/builders.js +5 -56
  301. package/dist/integrations/agent/config.js +3 -143
  302. package/dist/integrations/agent/detect.js +17 -2
  303. package/dist/integrations/agent/engine-resolution.js +231 -0
  304. package/dist/integrations/agent/index.js +1 -2
  305. package/dist/integrations/agent/model-aliases.js +16 -2
  306. package/dist/integrations/agent/profiles.js +36 -62
  307. package/dist/integrations/agent/prompts.js +46 -18
  308. package/dist/integrations/agent/runner-dispatch.js +93 -4
  309. package/dist/integrations/agent/runner.js +76 -208
  310. package/dist/integrations/agent/spawn.js +88 -196
  311. package/dist/integrations/harnesses/aider/agent-builder.js +114 -0
  312. package/dist/integrations/harnesses/aider/index.js +48 -0
  313. package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
  314. package/dist/integrations/harnesses/amazonq/agent-builder.js +147 -0
  315. package/dist/integrations/harnesses/amazonq/index.js +45 -0
  316. package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
  317. package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
  318. package/dist/integrations/harnesses/claude/config-import.js +1 -3
  319. package/dist/integrations/harnesses/claude/index.js +24 -35
  320. package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
  321. package/dist/integrations/harnesses/claude/session-log.js +27 -75
  322. package/dist/integrations/harnesses/codex/agent-builder.js +138 -0
  323. package/dist/integrations/harnesses/codex/index.js +52 -0
  324. package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
  325. package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
  326. package/dist/integrations/harnesses/copilot/index.js +48 -0
  327. package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
  328. package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
  329. package/dist/integrations/harnesses/gemini/index.js +48 -0
  330. package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
  331. package/dist/integrations/harnesses/ids.js +24 -0
  332. package/dist/integrations/harnesses/index.js +54 -34
  333. package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
  334. package/dist/integrations/harnesses/opencode/config-import.js +1 -3
  335. package/dist/integrations/harnesses/opencode/index.js +14 -32
  336. package/dist/integrations/harnesses/opencode/session-log.js +67 -125
  337. package/dist/integrations/harnesses/opencode-sdk/harness.js +51 -0
  338. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
  339. package/dist/integrations/harnesses/openhands/agent-builder.js +128 -0
  340. package/dist/integrations/harnesses/openhands/index.js +48 -0
  341. package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
  342. package/dist/integrations/harnesses/pi/agent-builder.js +97 -0
  343. package/dist/integrations/harnesses/pi/index.js +45 -0
  344. package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
  345. package/dist/integrations/harnesses/shared.js +17 -0
  346. package/dist/integrations/harnesses/types.js +43 -32
  347. package/dist/integrations/lockfile.js +211 -24
  348. package/dist/integrations/session-logs/index.js +36 -39
  349. package/dist/integrations/session-logs/provider-base.js +113 -0
  350. package/dist/llm/client.js +182 -110
  351. package/dist/llm/embedders/deterministic.js +2 -2
  352. package/dist/llm/embedders/remote.js +21 -9
  353. package/dist/llm/feature-gate.js +17 -57
  354. package/dist/llm/graph-extract.js +12 -13
  355. package/dist/llm/index-passes.js +8 -42
  356. package/dist/llm/memory-infer.js +144 -1
  357. package/dist/llm/metadata-enhance.js +45 -30
  358. package/dist/llm/structured-call.js +16 -8
  359. package/dist/llm/usage-persist.js +30 -5
  360. package/dist/llm/usage-telemetry.js +59 -6
  361. package/dist/output/cli-hints.js +1 -2
  362. package/dist/output/command-registry.js +27 -0
  363. package/dist/output/context.js +22 -7
  364. package/dist/output/format-exempt.js +80 -0
  365. package/dist/output/generic-render.js +251 -0
  366. package/dist/output/html-render.js +11 -16
  367. package/dist/output/render-registry.js +57 -0
  368. package/dist/output/renderers.js +14 -279
  369. package/dist/output/shapes/curate.js +10 -1
  370. package/dist/output/shapes/events.js +12 -7
  371. package/dist/output/shapes/helpers.js +58 -84
  372. package/dist/output/shapes/passthrough.js +11 -39
  373. package/dist/output/shapes/proposal/producer.js +15 -7
  374. package/dist/output/shapes/registry.js +12 -6
  375. package/dist/output/shapes.js +0 -9
  376. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  377. package/dist/output/text/bundle-show.js +7 -0
  378. package/dist/output/text/command-format.js +562 -0
  379. package/dist/output/text/env.js +1 -3
  380. package/dist/output/text/events.js +8 -7
  381. package/dist/output/text/helpers.js +15 -1164
  382. package/dist/output/text/proposal/producer.js +4 -2
  383. package/dist/output/text/proposal-format.js +202 -0
  384. package/dist/output/text/registry-commands.js +1 -2
  385. package/dist/output/text/registry.js +12 -6
  386. package/dist/output/text/show-directives.js +117 -0
  387. package/dist/output/text/show-format.js +103 -0
  388. package/dist/output/text/sync.js +5 -0
  389. package/dist/output/text/workflow-format.js +332 -0
  390. package/dist/output/text/workflow.js +3 -2
  391. package/dist/output/text.js +10 -19
  392. package/dist/registry/factory.js +4 -6
  393. package/dist/registry/origin-resolve.js +16 -27
  394. package/dist/registry/providers/skills-sh.js +3 -3
  395. package/dist/registry/providers/static-index.js +15 -25
  396. package/dist/registry/resolve.js +43 -94
  397. package/dist/registry/semver.js +43 -0
  398. package/dist/runtime.js +81 -12
  399. package/dist/scripts/akm-migrate.js +35529 -0
  400. package/dist/setup/detect.js +5 -7
  401. package/dist/setup/detected-engines.js +136 -0
  402. package/dist/setup/engine-config.js +100 -0
  403. package/dist/setup/registry-stash-loader.js +3 -3
  404. package/dist/setup/semantic-assets.js +12 -9
  405. package/dist/setup/setup.js +444 -208
  406. package/dist/setup/steps/connection-shared.js +120 -0
  407. package/dist/setup/steps/connection.js +108 -305
  408. package/dist/setup/steps/platforms.js +13 -12
  409. package/dist/setup/steps/semantic.js +15 -3
  410. package/dist/setup/steps/sources.js +21 -15
  411. package/dist/setup/steps/stashdir.js +6 -4
  412. package/dist/setup/steps/tasks.js +236 -119
  413. package/dist/setup/steps.js +3 -2
  414. package/dist/sources/freshness.js +39 -0
  415. package/dist/sources/provider-factory.js +11 -17
  416. package/dist/sources/providers/filesystem.js +2 -3
  417. package/dist/sources/providers/git-install.js +278 -34
  418. package/dist/sources/providers/git-provider.js +54 -56
  419. package/dist/sources/providers/git-stash.js +420 -91
  420. package/dist/sources/providers/git.js +2 -2
  421. package/dist/sources/providers/npm.js +16 -19
  422. package/dist/sources/providers/provider-utils.js +47 -22
  423. package/dist/sources/providers/sync-from-ref.js +3 -9
  424. package/dist/sources/providers/website.js +2 -2
  425. package/dist/sources/resolve.js +11 -10
  426. package/dist/sources/snapshot-fetchers/types.js +4 -0
  427. package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
  428. package/dist/storage/database.js +60 -4
  429. package/dist/storage/engines/sqlite-migrations.js +156 -5
  430. package/dist/storage/locations.js +1 -2
  431. package/dist/storage/repositories/canaries-repository.js +1 -1
  432. package/dist/storage/repositories/events-repository.js +51 -11
  433. package/dist/storage/repositories/improve-runs-repository.js +6 -32
  434. package/dist/storage/repositories/index-connection.js +79 -0
  435. package/dist/storage/repositories/index-db.js +4 -3
  436. package/dist/storage/repositories/index-entries-repository.js +863 -0
  437. package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
  438. package/dist/storage/repositories/index-entry-types.js +4 -0
  439. package/dist/storage/repositories/index-fts-repository.js +167 -0
  440. package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
  441. package/dist/storage/repositories/index-meta-repository.js +49 -0
  442. package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
  443. package/dist/storage/repositories/index-sql.js +12 -0
  444. package/dist/storage/repositories/index-utility-repository.js +356 -0
  445. package/dist/storage/repositories/index-vec-repository.js +250 -0
  446. package/dist/storage/repositories/outcome-repository.js +119 -0
  447. package/dist/storage/repositories/proposals-repository.js +317 -75
  448. package/dist/storage/repositories/registry-cache.js +1 -1
  449. package/dist/storage/repositories/salience-repository.js +172 -0
  450. package/dist/storage/repositories/task-history-repository.js +110 -3
  451. package/dist/storage/repositories/workflow-runs-repository.js +240 -19
  452. package/dist/tasks/backends/cron.js +169 -46
  453. package/dist/tasks/backends/exec-utils.js +76 -3
  454. package/dist/tasks/backends/index.js +6 -9
  455. package/dist/tasks/backends/launchd.js +292 -55
  456. package/dist/tasks/backends/schtasks.js +557 -70
  457. package/dist/tasks/backends/types.js +4 -0
  458. package/dist/tasks/command-executable.js +93 -0
  459. package/dist/tasks/embedded.js +56 -38
  460. package/dist/tasks/parser.js +156 -64
  461. package/dist/tasks/resolve-akm-bin.js +144 -51
  462. package/dist/tasks/runner.js +377 -209
  463. package/dist/tasks/schedule.js +108 -19
  464. package/dist/tasks/scheduler-invocation.js +296 -0
  465. package/dist/tasks/schema.js +1 -1
  466. package/dist/tasks/task-id.js +35 -0
  467. package/dist/tasks/validator.js +30 -16
  468. package/dist/text-import-hook.mjs +1 -1
  469. package/dist/workflows/authoring/authoring.js +104 -43
  470. package/dist/workflows/authoring/scope-key.js +1 -1
  471. package/dist/workflows/cli.js +0 -16
  472. package/dist/workflows/concurrency-policy.js +15 -0
  473. package/dist/workflows/exec/brief.js +450 -0
  474. package/dist/workflows/exec/frozen-judge.js +47 -0
  475. package/dist/workflows/exec/native-executor.js +1038 -0
  476. package/dist/workflows/exec/param-secrets.js +115 -0
  477. package/dist/workflows/exec/report.js +1460 -0
  478. package/dist/workflows/exec/run-workflow.js +602 -0
  479. package/dist/workflows/exec/scheduler.js +71 -0
  480. package/dist/workflows/exec/step-work.js +1190 -0
  481. package/dist/workflows/exec/unit-writer.js +23 -0
  482. package/dist/workflows/exec/workflow-engine-gate.js +67 -0
  483. package/dist/workflows/exec/worktree.js +171 -0
  484. package/dist/workflows/ir/compile.js +246 -0
  485. package/dist/workflows/ir/freeze.js +233 -0
  486. package/dist/workflows/ir/params.js +54 -0
  487. package/dist/workflows/ir/plan-hash.js +68 -0
  488. package/dist/workflows/ir/schema.js +540 -0
  489. package/dist/workflows/parser.js +878 -304
  490. package/dist/workflows/program/expressions.js +181 -0
  491. package/dist/workflows/program/schema.js +51 -0
  492. package/dist/workflows/renderer.js +100 -45
  493. package/dist/workflows/resource-limits.js +22 -0
  494. package/dist/workflows/runtime/agent-identity.js +59 -14
  495. package/dist/workflows/runtime/checkin.js +1 -1
  496. package/dist/workflows/runtime/plan-classifier.js +131 -0
  497. package/dist/workflows/runtime/runs.js +376 -119
  498. package/dist/workflows/runtime/unit-checkin.js +45 -0
  499. package/dist/workflows/runtime/unit-phases.js +20 -0
  500. package/dist/workflows/runtime/workflow-asset-loader.js +241 -40
  501. package/dist/workflows/schema.js +1 -11
  502. package/dist/workflows/validate-summary.js +2 -3
  503. package/dist/workflows/validator.js +52 -30
  504. package/docs/README.md +42 -78
  505. package/docs/migration/README.md +8 -0
  506. package/docs/migration/release-notes/0.6.0.md +1 -1
  507. package/docs/migration/release-notes/0.7.0.md +9 -8
  508. package/docs/migration/release-notes/0.9.0.md +158 -14
  509. package/docs/migration/v0.7-to-v0.8.md +46 -47
  510. package/docs/migration/v0.8-to-v0.9.md +844 -0
  511. package/docs/reference/README.md +12 -0
  512. package/docs/reference/data-and-telemetry.md +333 -0
  513. package/package.json +21 -17
  514. package/schemas/akm-asset-envelope.json +93 -0
  515. package/schemas/akm-config.json +4636 -0
  516. package/schemas/akm-task.json +87 -0
  517. package/schemas/akm-workflow.json +373 -0
  518. package/dist/akm-migrate-storage +0 -38
  519. package/dist/assets/help/help-accept.md +0 -12
  520. package/dist/assets/help/help-improve.md +0 -84
  521. package/dist/assets/help/help-proposals.md +0 -17
  522. package/dist/assets/help/help-propose.md +0 -17
  523. package/dist/assets/help/help-reject.md +0 -11
  524. package/dist/assets/profiles/frequent.json +0 -13
  525. package/dist/assets/profiles/recombine-only.json +0 -21
  526. package/dist/assets/profiles/reflect-distill.json +0 -30
  527. package/dist/assets/profiles/synthesize.json +0 -15
  528. package/dist/assets/prompts/procedural-system.md +0 -44
  529. package/dist/assets/prompts/recombine-system.md +0 -40
  530. package/dist/assets/prompts/staleness-detect-system.md +0 -6
  531. package/dist/assets/tasks/core/backup.yml +0 -4
  532. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  533. package/dist/assets/templates/html/default.html +0 -78
  534. package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
  535. package/dist/assets/wiki/index-template.md +0 -12
  536. package/dist/assets/wiki/ingest-workflow-template.md +0 -83
  537. package/dist/assets/wiki/log-template.md +0 -8
  538. package/dist/assets/wiki/schema-template.md +0 -61
  539. package/dist/cli/config-migrate.js +0 -150
  540. package/dist/cli/config-validate.js +0 -39
  541. package/dist/commands/graph/graph-cli.js +0 -124
  542. package/dist/commands/graph/graph.js +0 -487
  543. package/dist/commands/improve/calibration.js +0 -161
  544. package/dist/commands/improve/dedup.js +0 -482
  545. package/dist/commands/improve/extract-watch.js +0 -140
  546. package/dist/commands/improve/hot-probation.js +0 -45
  547. package/dist/commands/improve/improve-auto-accept.js +0 -276
  548. package/dist/commands/improve/improve-profiles.js +0 -168
  549. package/dist/commands/improve/procedural.js +0 -398
  550. package/dist/commands/improve/recombine.js +0 -818
  551. package/dist/commands/improve/schema-similarity-gate.js +0 -168
  552. package/dist/commands/lint/agent-linter.js +0 -44
  553. package/dist/commands/lint/command-linter.js +0 -44
  554. package/dist/commands/lint/default-linter.js +0 -16
  555. package/dist/commands/lint/fact-linter.js +0 -39
  556. package/dist/commands/lint/knowledge-linter.js +0 -16
  557. package/dist/commands/lint/memory-linter.js +0 -61
  558. package/dist/commands/lint/registry.js +0 -41
  559. package/dist/commands/lint/skill-linter.js +0 -45
  560. package/dist/commands/lint/task-linter.js +0 -50
  561. package/dist/commands/lint/workflow-linter.js +0 -81
  562. package/dist/commands/proposal/legacy-import.js +0 -115
  563. package/dist/commands/sources/history.js +0 -196
  564. package/dist/commands/tasks/default-tasks.js +0 -186
  565. package/dist/commands/wiki-cli.js +0 -292
  566. package/dist/core/asset/asset-registry.js +0 -76
  567. package/dist/core/asset/asset-spec.js +0 -259
  568. package/dist/core/config/config-migration.js +0 -602
  569. package/dist/core/deep-merge.js +0 -38
  570. package/dist/core/eval/rank-metrics.js +0 -113
  571. package/dist/core/ripgrep/install.js +0 -163
  572. package/dist/core/ripgrep/resolve.js +0 -81
  573. package/dist/indexer/db/db.js +0 -1413
  574. package/dist/indexer/manifest.js +0 -170
  575. package/dist/indexer/passes/metadata-contributors.js +0 -31
  576. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
  577. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -49
  578. package/dist/llm/call-ai.js +0 -62
  579. package/dist/llm/memory-infer-impl.js +0 -138
  580. package/dist/output/shapes/distill.js +0 -14
  581. package/dist/output/shapes/history.js +0 -11
  582. package/dist/output/text/distill.js +0 -6
  583. package/dist/output/text/enable-disable.js +0 -8
  584. package/dist/output/text/history.js +0 -6
  585. package/dist/output/text/wiki.js +0 -16
  586. package/dist/registry/build-index.js +0 -386
  587. package/dist/scripts/migrate-storage.js +0 -19108
  588. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -9411
  589. package/dist/scripts/migrations/v16-to-v17.js +0 -141
  590. package/dist/setup/legacy-config.js +0 -106
  591. package/dist/storage/repositories/consolidation-repository.js +0 -38
  592. package/dist/storage/repositories/recombine-repository.js +0 -213
  593. package/dist/wiki/wiki-templates.js +0 -15
  594. package/dist/wiki/wiki.js +0 -1012
  595. package/dist/workflows/db.js +0 -215
  596. package/docs/data-and-telemetry.md +0 -226
  597. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
  598. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
@@ -1,23 +1,20 @@
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 { defineCommand } from "citty";
5
- import { parsePositiveIntFlag } from "../cli/parse-args.js";
6
- import { defineJsonCommand, output } from "../cli/shared.js";
7
- import { DEFAULT_CONFIG, loadUserConfig, saveConfig } from "../core/config/config.js";
4
+ import { defineGroupCommand, defineJsonCommand, output } from "../cli/shared.js";
5
+ import { getEffectiveRegistries, loadUserConfig, mutateConfig } from "../core/config/config.js";
8
6
  import { UsageError } from "../core/errors.js";
9
7
  import { warn } from "../core/warn.js";
10
- import { buildRegistryIndex, writeRegistryIndex } from "../registry/build-index.js";
11
- import { searchRegistry } from "./read/registry-search.js";
12
- export const registryCommand = defineCommand({
13
- meta: { name: "registry", description: "Manage stash registries" },
8
+ export const registryCommand = defineGroupCommand({
9
+ meta: { name: "registry", description: "Manage bundle registries" },
14
10
  subCommands: {
15
11
  list: defineJsonCommand({
16
12
  meta: { name: "list", description: "List configured registries" },
17
13
  async run() {
18
14
  const config = loadUserConfig();
19
- const registries = config.registries ?? DEFAULT_CONFIG.registries;
20
- output("registry-list", { registries });
15
+ // R-066 #5: mirror the shared config↔default-fallback helper instead
16
+ // of re-deriving it inline.
17
+ output("registry-list", { registries: getEffectiveRegistries(config) });
21
18
  },
22
19
  }),
23
20
  add: defineJsonCommand({
@@ -45,13 +42,6 @@ export const registryCommand = defineCommand({
45
42
  }
46
43
  warn("Warning: registry URL uses plain HTTP (not HTTPS). --allow-insecure was set; an on-path attacker could substitute a malicious index.");
47
44
  }
48
- const config = loadUserConfig();
49
- const registries = [...(config.registries ?? [])];
50
- // Deduplicate by URL
51
- if (registries.some((r) => r.url === args.url)) {
52
- output("registry-add", { registries, added: false, message: "Registry URL already configured" });
53
- return;
54
- }
55
45
  const entry = { url: args.url };
56
46
  if (args.name)
57
47
  entry.name = args.name;
@@ -65,9 +55,20 @@ export const registryCommand = defineCommand({
65
55
  throw new UsageError("--options must be valid JSON");
66
56
  }
67
57
  }
68
- registries.push(entry);
69
- saveConfig({ ...config, registries });
70
- output("registry-add", { registries, added: true });
58
+ let added = false;
59
+ const updated = mutateConfig((config) => {
60
+ const registries = [...(config.registries ?? [])];
61
+ if (registries.some((registry) => registry.url === args.url))
62
+ return config;
63
+ registries.push(entry);
64
+ added = true;
65
+ return { ...config, registries };
66
+ }).config;
67
+ output("registry-add", {
68
+ registries: updated.registries ?? [],
69
+ added,
70
+ ...(!added ? { message: "Registry URL already configured" } : {}),
71
+ });
71
72
  },
72
73
  }),
73
74
  remove: defineJsonCommand({
@@ -92,46 +93,19 @@ export const registryCommand = defineCommand({
92
93
  process.stderr.write("Aborted.\n");
93
94
  return;
94
95
  }
95
- const removed = registries.splice(idx, 1)[0];
96
- saveConfig({ ...config, registries });
97
- output("registry-remove", { registries, removed: true, entry: removed });
98
- },
99
- }),
100
- search: defineJsonCommand({
101
- meta: { name: "search", description: "Search enabled registries for stashes" },
102
- args: {
103
- query: { type: "positional", description: "Search query", required: true },
104
- limit: { type: "string", description: "Maximum number of results" },
105
- assets: { type: "boolean", description: "Include asset-level search results", default: false },
106
- },
107
- async run({ args }) {
108
- const limitRaw = parsePositiveIntFlag(args.limit ?? undefined);
109
- const result = await searchRegistry(args.query, { limit: limitRaw, includeAssets: args.assets });
110
- output("registry-search", result);
111
- },
112
- }),
113
- "build-index": defineJsonCommand({
114
- meta: { name: "build-index", description: "Build a v2 registry index from discovery and manual entries" },
115
- args: {
116
- out: { type: "string", description: "Output path for the generated index" },
117
- manual: { type: "string", description: "Manual entries JSON file" },
118
- "npm-registry": { type: "string", description: "Override npm registry base URL" },
119
- "github-api": { type: "string", description: "Override GitHub API base URL" },
120
- },
121
- async run({ args }) {
122
- const result = await buildRegistryIndex({
123
- manualEntriesPath: args.manual,
124
- npmRegistryBase: args["npm-registry"],
125
- githubApiBase: args["github-api"],
126
- });
127
- const outPath = writeRegistryIndex(result.index, args.out);
128
- output("registry-build-index", {
129
- outPath,
130
- version: result.index.version,
131
- updatedAt: result.index.updatedAt,
132
- totalKits: result.counts.total,
133
- counts: result.counts,
134
- manualEntriesPath: result.paths.manualEntriesPath,
96
+ let removed;
97
+ const updated = mutateConfig((latest) => {
98
+ const current = [...(latest.registries ?? [])];
99
+ const currentIndex = current.findIndex((registry) => registry.url === args.target || registry.name === args.target);
100
+ if (currentIndex < 0)
101
+ return latest;
102
+ removed = current.splice(currentIndex, 1)[0];
103
+ return { ...latest, registries: current };
104
+ }).config;
105
+ output("registry-remove", {
106
+ registries: updated.registries ?? [],
107
+ removed: removed !== undefined,
108
+ ...(removed ? { entry: removed } : { message: "No matching registry found" }),
135
109
  });
136
110
  },
137
111
  }),
@@ -10,12 +10,13 @@
10
10
  */
11
11
  import { serializeFrontmatter } from "../core/asset/asset-serialize.js";
12
12
  import { toErrorMessage, tryReadStdinText } from "../core/common.js";
13
- import { getDefaultLlmConfig, loadConfig } from "../core/config/config.js";
13
+ import { loadConfig } from "../core/config/config.js";
14
14
  import { UsageError } from "../core/errors.js";
15
+ import { parseEmbeddedJsonResponse } from "../core/parse.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),
@@ -50,6 +51,8 @@ export function buildMemoryFrontmatter(fields) {
50
51
  obj.tags = fields.tags;
51
52
  if (fields.source?.trim())
52
53
  obj.source = fields.source;
54
+ if (fields.xrefs && fields.xrefs.length > 0)
55
+ obj.xrefs = fields.xrefs;
53
56
  if (fields.observed_at?.trim())
54
57
  obj.observed_at = fields.observed_at;
55
58
  if (fields.expires?.trim())
@@ -147,7 +150,7 @@ export async function runLlmEnrich(body) {
147
150
  warn("Warning: --enrich requires an LLM to be configured. Run `akm setup` to configure one.");
148
151
  return { tags: [] };
149
152
  }
150
- const { chatCompletion, parseEmbeddedJsonResponse: parseJsonResponse } = await import("../llm/client.js");
153
+ const { chatCompletion } = await import("../llm/client.js");
151
154
  // #576: attribute this entry point's LLM call to the `remember` stage. The
152
155
  // wrapper is ambient — if a usage sink is active it tags the record; if not,
153
156
  // it is a no-op.
@@ -182,7 +185,7 @@ Return ONLY the JSON object, no prose, no markdown fences.`;
182
185
  }
183
186
  }
184
187
  })();
185
- const parsed = parseJsonResponse(result);
188
+ const parsed = parseEmbeddedJsonResponse(result);
186
189
  if (!parsed) {
187
190
  warn("Warning: --enrich received invalid JSON from the LLM. Writing memory without enrichment.");
188
191
  return { tags: [] };
@@ -201,56 +204,14 @@ Return ONLY the JSON object, no prose, no markdown fences.`;
201
204
  return { tags: [] };
202
205
  }
203
206
  }
204
- // ── Content-arg disambiguation ───────────────────────────────────────────────
205
- /**
206
- * Guard against citty consuming a global flag value as the `content` positional.
207
- *
208
- * When the user runs `akm remember --format json` without a content argument,
209
- * citty may assign `"json"` to the `content` positional because of how it
210
- * handles flag order. This helper detects that case and returns `undefined`
211
- * so `readMemoryContent` falls through to stdin.
212
- */
213
- export function resolveRememberContentArg(content) {
214
- if (content === undefined)
215
- return undefined;
216
- const parsedFormat = parseFlagValue(process.argv, "--format");
217
- if (parsedFormat !== undefined &&
218
- content === parsedFormat &&
219
- wasRememberFlagValueConsumedAsContent(content, parsedFormat, "--format")) {
220
- return undefined;
221
- }
222
- const parsedDetail = parseFlagValue(process.argv, "--detail");
223
- if (parsedDetail !== undefined &&
224
- content === parsedDetail &&
225
- wasRememberFlagValueConsumedAsContent(content, parsedDetail, "--detail")) {
226
- return undefined;
227
- }
228
- return content;
229
- }
230
- function wasRememberFlagValueConsumedAsContent(content, flagValue, flagName) {
231
- const argv = process.argv.slice(2);
232
- const rememberIndex = argv.indexOf("remember");
233
- const tokens = rememberIndex >= 0 ? argv.slice(rememberIndex + 1) : argv;
234
- let flagIndex = -1;
235
- let flagConsumesNextToken = false;
236
- for (let i = 0; i < tokens.length; i += 1) {
237
- const token = tokens[i];
238
- if (token === flagName) {
239
- flagIndex = i;
240
- flagConsumesNextToken = true;
241
- break;
242
- }
243
- if (token === `${flagName}=${flagValue}`) {
244
- flagIndex = i;
245
- break;
246
- }
247
- }
248
- if (flagIndex === -1)
249
- return false;
250
- if (tokens.slice(0, flagIndex).includes(content))
251
- return false;
252
- const firstTokenAfterFlag = flagIndex + (flagConsumesNextToken ? 2 : 1);
253
- if (tokens.slice(firstTokenAfterFlag).includes(content))
254
- return false;
255
- return true;
256
- }
207
+ // R-061(c): `resolveRememberContentArg` / `wasRememberFlagValueConsumedAsContent`
208
+ // used to live here — a heuristic guarding against citty consuming a global
209
+ // flag's value (`--format`/`--detail`) as the `content` positional. That guard
210
+ // predated `rememberCommand` declaring `GLOBAL_OUTPUT_ARGS` (via
211
+ // `defineJsonCommand`): once the leaf command itself declares `format`/
212
+ // `detail` args, citty's parser consumes their space-separated values as the
213
+ // flag's own value and never assigns them to `content` in the first place, so
214
+ // the heuristic no longer has anything to guard against. Verified: `akm
215
+ // remember "yaml" --format yaml` and `akm remember "brief" --detail brief`
216
+ // both write the literal content unchanged. Deleted rather than kept as
217
+ // defense-in-depth per the cleanup program's dead-code policy.
@@ -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)
@@ -37,24 +38,84 @@ export function shouldWarnOnPlainHttp(ref) {
37
38
  return true;
38
39
  }
39
40
  }
40
- /** Scan every env file in the freshly-installed stash for dangerous env keys. */
41
+ /**
42
+ * Recursively enumerate every real env FILE under `rootDir` (a stash's
43
+ * `env/` directory). "Real env file" is the SAME test used everywhere else
44
+ * in akm decides what `akm env run` / `akm env list` / the indexer will
45
+ * actually load as environment variables — `fileName === ".env" ||
46
+ * fileName.endsWith(".env")` — see `src/indexer/walk/matchers.ts` and
47
+ * `listEnvsRecursive` in `src/commands/env/env-cli.ts`. Reusing that exact
48
+ * rule here (rather than inventing a second, possibly-divergent one) is what
49
+ * closes the nested-directory bypass: `env/nested/inner.env` IS loaded by
50
+ * `akm env run` today via that same recursive walk, so it must be scanned
51
+ * too (previously only a flat, non-recursive `env/*.env` listing was
52
+ * scanned).
53
+ *
54
+ * Deliberately excludes files that do NOT end in `.env` (e.g.
55
+ * `env/notes.txt`). Such a file is never sourced as environment variables by
56
+ * any akm codepath, so a dangerous key sitting in its contents cannot hijack
57
+ * process execution via `akm env run` — there is no live attack through this
58
+ * gate for it. Residual gap: this scanner does not protect against an
59
+ * operator later renaming/copying that file to a `*.env` name, or feeding it
60
+ * into `akm env run` through some other mechanism outside akm; closing that
61
+ * would mean content-sniffing every byte of every file in the stash (README,
62
+ * lockfiles, binaries, …) for a vector that requires a subsequent human
63
+ * action to become live, which is a materially different and much more
64
+ * expensive check than "is this a file `akm` will actually source".
65
+ */
66
+ function collectEnvFilePathsRecursive(rootDir) {
67
+ const results = [];
68
+ const walk = (dir) => {
69
+ let entries;
70
+ try {
71
+ entries = fs.readdirSync(dir, { withFileTypes: true });
72
+ }
73
+ catch {
74
+ return;
75
+ }
76
+ for (const entry of entries) {
77
+ const full = path.join(dir, entry.name);
78
+ if (entry.isDirectory()) {
79
+ walk(full);
80
+ continue;
81
+ }
82
+ if (!entry.isFile())
83
+ continue;
84
+ if (entry.name !== ".env" && !entry.name.endsWith(".env"))
85
+ continue;
86
+ results.push(full);
87
+ }
88
+ };
89
+ walk(rootDir);
90
+ return results;
91
+ }
92
+ /** Scan every real env file (recursively, see {@link collectEnvFilePathsRecursive}) in the freshly-installed stash for dangerous env keys. */
41
93
  function collectDangerousKeyFindings(installedStashRoot, checkEnvForDangerousKeys) {
42
94
  const allFindings = [];
43
95
  const subdir = "env";
44
96
  const prefix = "env";
45
97
  const dir = path.join(installedStashRoot, subdir);
46
- const envFiles = fs.existsSync(dir) ? fs.readdirSync(dir).filter((f) => f.endsWith(".env")) : [];
47
- for (const envFile of envFiles) {
48
- const envPath = path.join(dir, envFile);
49
- const baseName = path.basename(envFile, ".env");
50
- const vaultRef = baseName === "" ? `${prefix}:default` : `${prefix}:${baseName}`;
51
- const relPath = path.join(subdir, envFile);
52
- const findings = checkEnvForDangerousKeys(envPath, relPath, vaultRef);
98
+ if (!fs.existsSync(dir))
99
+ return allFindings;
100
+ for (const envPath of collectEnvFilePathsRecursive(dir)) {
101
+ const relToEnvDir = path.relative(dir, envPath);
102
+ // Only the LAST path segment carries the ".env" suffix / dotfile-default
103
+ // naming rule; intermediate directory segments pass through unchanged.
104
+ // e.g. "nested/inner.env" -> "nested/inner", "nested/.env" ->
105
+ // "nested/default" (not "nested/", which is what naively stripping the
106
+ // suffix from the whole relative path would produce).
107
+ const segments = relToEnvDir.split(path.sep);
108
+ const lastSegment = segments[segments.length - 1] ?? "";
109
+ const lastSegmentBase = lastSegment.endsWith(".env") ? lastSegment.slice(0, -".env".length) : lastSegment;
110
+ const refSegments = [...segments.slice(0, -1), lastSegmentBase === "" ? "default" : lastSegmentBase];
111
+ const envRef = `${prefix}/${refSegments.join("/")}`;
112
+ const relPath = path.join(subdir, relToEnvDir);
113
+ const findings = checkEnvForDangerousKeys(envPath, relPath, envRef);
53
114
  for (const finding of findings) {
54
115
  // Extract the key name from the detail string for the summary line.
55
116
  const keyMatch = finding.detail.match(/Env key `([^`]+)`/);
56
117
  const keyName = keyMatch ? keyMatch[1] : finding.file;
57
- allFindings.push({ vaultRef, keyName, relPath });
118
+ allFindings.push({ envRef, keyName, relPath });
58
119
  }
59
120
  }
60
121
  return allFindings;
@@ -79,12 +140,18 @@ export async function auditInstalledStashForDangerousKeys(opts) {
79
140
  catch {
80
141
  return { blocked: false };
81
142
  }
82
- if (allFindings.length === 0)
143
+ // The workspace activation policy fixes the baseline stance; the interactive
144
+ // confirm / rollback below is layered on top of the `"gate"` stance only.
145
+ const stance = decideDangerousKeyInstall({
146
+ findingsPresent: allFindings.length > 0,
147
+ allowInsecure: allowDangerousKeys,
148
+ });
149
+ if (stance === "allow")
83
150
  return { blocked: false };
84
- if (allowDangerousKeys) {
151
+ if (stance === "warn-allow") {
85
152
  // Operator has explicitly accepted the risk — warn and continue.
86
153
  for (const f of allFindings) {
87
- 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.`);
154
+ warn(`[dangerous-env-key] ${f.relPath}: key \`${f.keyName}\` in ${f.envRef} can hijack process execution via \`akm env run\`. Proceeding because --allow-insecure was set.`);
88
155
  }
89
156
  return { blocked: false };
90
157
  }
@@ -98,7 +165,7 @@ export async function auditInstalledStashForDangerousKeys(opts) {
98
165
  }
99
166
  catch (_rollbackErr) {
100
167
  return (`Rollback failed — stash may still be installed at ${installedStashRoot}. ` +
101
- `Remove it manually with: akm remove ${rollbackTarget}`);
168
+ `Remove it manually with: akm bundle remove ${rollbackTarget}`);
102
169
  }
103
170
  }
104
171
  if (isTTY) {
@@ -106,14 +173,14 @@ export async function auditInstalledStashForDangerousKeys(opts) {
106
173
  // Guard on stdin (not stdout) because p.confirm() reads from stdin;
107
174
  // stdout may be a TTY while stdin is piped, which would cause a hang.
108
175
  const stashLabel = ref;
109
- const groupedByVault = new Map();
176
+ const groupedByEnv = new Map();
110
177
  for (const f of allFindings) {
111
- const existing = groupedByVault.get(f.vaultRef) ?? [];
178
+ const existing = groupedByEnv.get(f.envRef) ?? [];
112
179
  existing.push(f.keyName);
113
- groupedByVault.set(f.vaultRef, existing);
180
+ groupedByEnv.set(f.envRef, existing);
114
181
  }
115
- for (const [vaultRef, keys] of groupedByVault) {
116
- warn(`[warn] Env "${vaultRef}" in stash "${stashLabel}" contains potentially dangerous keys:`);
182
+ for (const [envRef, keys] of groupedByEnv) {
183
+ warn(`[warn] Env "${envRef}" in stash "${stashLabel}" contains potentially dangerous keys:`);
117
184
  for (const key of keys) {
118
185
  warn(` - ${key}: can hijack process execution via \`akm env run\``);
119
186
  }
@@ -127,7 +194,7 @@ export async function auditInstalledStashForDangerousKeys(opts) {
127
194
  console.error(JSON.stringify({
128
195
  ok: false,
129
196
  error: "Install aborted: stash contains dangerous env keys. Remove the keys or re-run with --allow-insecure to bypass.",
130
- code: "DANGEROUS_VAULT_KEY",
197
+ code: "DANGEROUS_ENV_KEY",
131
198
  ...(rollbackWarning ? { rollbackWarning } : {}),
132
199
  }, null, 2));
133
200
  return { blocked: true, exitCode: 1 };
@@ -137,11 +204,11 @@ export async function auditInstalledStashForDangerousKeys(opts) {
137
204
  }
138
205
  // Non-interactive path without bypass flag: fail hard.
139
206
  const rollbackWarning = await rollback();
140
- const keyList = allFindings.map((f) => ` - ${f.keyName} (${f.vaultRef})`).join("\n");
207
+ const keyList = allFindings.map((f) => ` - ${f.keyName} (${f.envRef})`).join("\n");
141
208
  console.error(JSON.stringify({
142
209
  ok: false,
143
210
  error: `Install blocked: stash "${ref}" contains dangerous env keys that can hijack process execution via \`akm env run\`:\n${keyList}\nRe-run with --allow-insecure to bypass this check after reviewing the env file.`,
144
- code: "DANGEROUS_VAULT_KEY",
211
+ code: "DANGEROUS_ENV_KEY",
145
212
  ...(rollbackWarning ? { rollbackWarning } : {}),
146
213
  }, null, 2));
147
214
  return { blocked: true, exitCode: 1 };
@@ -163,18 +230,14 @@ export const addCommand = defineJsonCommand({
163
230
  name: { type: "string", description: "Human-friendly name for the source" },
164
231
  writable: {
165
232
  type: "boolean",
166
- description: "Mark a git stash as writable so changes can be pushed back",
233
+ description: "Mark a git bundle as writable so changes can be pushed back",
167
234
  default: false,
168
235
  },
169
- type: {
170
- type: "string",
171
- description: "Override asset type for all files in this stash (currently supports: wiki)",
172
- },
173
236
  "max-pages": { type: "string", description: "Maximum pages to crawl for website sources (default: 50)" },
174
237
  "max-depth": { type: "string", description: "Maximum crawl depth for website sources (default: 3)" },
175
238
  "allow-insecure": {
176
239
  type: "boolean",
177
- description: "Allow a plain HTTP source URL and skip confirmation for dangerous env keys (e.g. LD_PRELOAD, PATH). Use only after explicitly reviewing the stash.",
240
+ description: "Allow a plain HTTP source URL and skip confirmation for dangerous env keys (e.g. LD_PRELOAD, PATH). Use only after explicitly reviewing the bundle.",
178
241
  default: false,
179
242
  },
180
243
  },
@@ -182,7 +245,9 @@ export const addCommand = defineJsonCommand({
182
245
  const ref = args.ref.trim();
183
246
  const allowInsecure = args["allow-insecure"];
184
247
  const allowDangerousKeys = allowInsecure;
185
- // URL with --provider → stash source (remote or git provider)
248
+ // --provider → declarative bundle source (URL for git/website; bare
249
+ // package spec for npm — R-013). Config-only write; content is not
250
+ // synced until a later `akm update`.
186
251
  if (args.provider) {
187
252
  if (shouldWarnOnPlainHttp(ref)) {
188
253
  if (!allowInsecure) {
@@ -228,25 +293,9 @@ export const addCommand = defineJsonCommand({
228
293
  warn("Warning: source URL uses plain HTTP (not HTTPS). --allow-insecure was set; an on-path attacker could substitute a malicious payload.");
229
294
  }
230
295
  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
296
  const result = await akmAdd({
247
297
  ref,
248
298
  name: args.name,
249
- overrideType: args.type,
250
299
  options: Object.keys(websiteOptions).length > 0 ? websiteOptions : undefined,
251
300
  writable: args.writable,
252
301
  });
@@ -255,7 +304,6 @@ export const addCommand = defineJsonCommand({
255
304
  metadata: {
256
305
  target: ref,
257
306
  name: args.name ?? null,
258
- overrideType: args.type ?? null,
259
307
  writable: args.writable === true,
260
308
  },
261
309
  });
@@ -271,8 +319,14 @@ export const addCommand = defineJsonCommand({
271
319
  // Use the canonical installed id (most reliably resolved by akmRemove) rather
272
320
  // than the raw user-supplied ref which may not match after URL normalisation.
273
321
  const rollbackTarget = result.installed?.id ?? result.sourceAdded?.stashRoot ?? ref;
274
- // The audit RETURNS its decision; we decide `process.exit` here, OUTSIDE
275
- // any catch, so the abort cannot be lost to a swallowed exception (C3).
322
+ // The audit RETURNS its decision; we decide the exit outcome here,
323
+ // OUTSIDE any catch, so the abort cannot be lost to a swallowed
324
+ // exception (C3). F4: `process.exitCode = …; return;` instead of
325
+ // `process.exit(...)` — the DANGEROUS_ENV_KEY error envelope has
326
+ // already been written to stderr by the audit itself (or is about to
327
+ // be), so an explicit `return` here (skipping the success `output("add",
328
+ // …)` below) is load-bearing, not merely cosmetic: it is what stops a
329
+ // blocked install from ALSO printing a success envelope.
276
330
  const decision = await auditInstalledStashForDangerousKeys({
277
331
  installedStashRoot,
278
332
  ref,
@@ -281,7 +335,8 @@ export const addCommand = defineJsonCommand({
281
335
  isTTY: process.stdin.isTTY === true,
282
336
  });
283
337
  if (decision.blocked) {
284
- process.exit(decision.exitCode);
338
+ process.exitCode = decision.exitCode;
339
+ return;
285
340
  }
286
341
  }
287
342
  output("add", result);