akm-cli 0.9.0-rc.1 → 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 (587) hide show
  1. package/CHANGELOG.md +1190 -52
  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/stash-skeleton/README.md +38 -10
  26. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
  27. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
  28. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
  29. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
  30. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
  38. package/dist/assets/tasks/core/extract.yml +3 -2
  39. package/dist/assets/tasks/core/improve.yml +2 -1
  40. package/dist/assets/tasks/core/index-refresh.yml +1 -0
  41. package/dist/assets/tasks/core/sync.yml +1 -0
  42. package/dist/assets/tasks/core/version-check.yml +2 -1
  43. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  44. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  45. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  46. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  47. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  48. package/dist/assets/templates/html/health.html +5 -4
  49. package/dist/assets/workflows/workflow-template.md +31 -15
  50. package/dist/cli/invocation.js +279 -0
  51. package/dist/cli/parse-args.js +5 -90
  52. package/dist/cli/retired-commands.js +78 -0
  53. package/dist/cli/shared.js +158 -48
  54. package/dist/cli-node.mjs +2 -1
  55. package/dist/cli.js +747 -293
  56. package/dist/commands/agent/agent-dispatch.js +19 -18
  57. package/dist/commands/agent/agent-support.js +0 -24
  58. package/dist/commands/agent/contribute-cli.js +43 -97
  59. package/dist/commands/completions.js +80 -23
  60. package/dist/commands/config-cli.js +44 -281
  61. package/dist/commands/env/env-binding.js +13 -9
  62. package/dist/commands/env/env-cli.js +76 -159
  63. package/dist/commands/env/env.js +12 -163
  64. package/dist/commands/env/marker-path.js +6 -0
  65. package/dist/commands/env/secret-cli.js +45 -61
  66. package/dist/commands/env/secret.js +32 -62
  67. package/dist/commands/feedback-cli.js +179 -85
  68. package/dist/commands/health/accept-rate.js +58 -0
  69. package/dist/commands/health/advisories.js +7 -8
  70. package/dist/commands/health/checks.js +279 -94
  71. package/dist/commands/health/html-report.js +197 -578
  72. package/dist/commands/health/improve-metrics.js +277 -246
  73. package/dist/commands/health/llm-usage.js +19 -19
  74. package/dist/commands/health/md-report.js +16 -7
  75. package/dist/commands/health/metrics.js +67 -32
  76. package/dist/commands/health/renderers.js +47 -0
  77. package/dist/commands/health/report-view-model.js +508 -0
  78. package/dist/commands/health/stash-exposure.js +1 -1
  79. package/dist/commands/health/surfaces.js +16 -56
  80. package/dist/commands/health/task-runs.js +3 -67
  81. package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
  82. package/dist/commands/health/types-improve.js +29 -0
  83. package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
  84. package/dist/commands/health/types-result.js +7 -0
  85. package/dist/commands/health/types-runs.js +4 -0
  86. package/dist/commands/health/types-session-log.js +4 -0
  87. package/dist/commands/health/types-windows.js +4 -0
  88. package/dist/commands/health/types.js +26 -21
  89. package/dist/commands/health/windows.js +2 -3
  90. package/dist/commands/health.js +296 -167
  91. package/dist/commands/improve/anti-collapse.js +5 -5
  92. package/dist/commands/improve/autonomy-gate.js +68 -0
  93. package/dist/commands/improve/collapse-detector.js +65 -52
  94. package/dist/commands/improve/consolidate/chunking.js +9 -7
  95. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  96. package/dist/commands/improve/consolidate/merge.js +4 -0
  97. package/dist/commands/improve/consolidate.js +454 -1354
  98. package/dist/commands/improve/content-hash.js +39 -0
  99. package/dist/commands/improve/distill/content-repair.js +4 -10
  100. package/dist/commands/improve/distill/promote-memory.js +89 -64
  101. package/dist/commands/improve/distill/quality-gate.js +118 -42
  102. package/dist/commands/improve/distill-guards.js +1 -1
  103. package/dist/commands/improve/distill-promotion-policy.js +33 -888
  104. package/dist/commands/improve/distill.js +607 -363
  105. package/dist/commands/improve/eligibility.js +165 -79
  106. package/dist/commands/improve/extract-cli.js +35 -126
  107. package/dist/commands/improve/extract-prompt.js +6 -35
  108. package/dist/commands/improve/extract.js +640 -391
  109. package/dist/commands/improve/feedback-valence.js +2 -12
  110. package/dist/commands/improve/improve-cli.js +134 -135
  111. package/dist/commands/improve/improve-result-file.js +30 -50
  112. package/dist/commands/improve/improve-run-types.js +4 -0
  113. package/dist/commands/improve/improve-strategies.js +135 -0
  114. package/dist/commands/improve/improve.js +904 -701
  115. package/dist/commands/improve/locks.js +64 -111
  116. package/dist/commands/improve/loop-stages.js +1110 -923
  117. package/dist/commands/improve/memory/derived-ref.js +124 -0
  118. package/dist/commands/improve/memory/memory-belief.js +79 -7
  119. package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
  120. package/dist/commands/improve/memory/memory-improve.js +25 -37
  121. package/dist/commands/improve/outcome-loop.js +25 -88
  122. package/dist/commands/improve/preparation.js +1034 -813
  123. package/dist/commands/improve/proactive-maintenance.js +34 -9
  124. package/dist/commands/improve/proposal-envelope.js +31 -0
  125. package/dist/commands/improve/reflect.js +983 -794
  126. package/dist/commands/improve/run-context.js +119 -0
  127. package/dist/commands/improve/salience.js +24 -127
  128. package/dist/commands/improve/session-asset.js +7 -3
  129. package/dist/commands/improve/shared.js +14 -34
  130. package/dist/commands/improve/source-identity.js +28 -0
  131. package/dist/commands/improve/triage.js +20 -17
  132. package/dist/commands/lint/base-linter.js +340 -313
  133. package/dist/commands/lint/env-key-rules.js +31 -47
  134. package/dist/commands/lint/index.js +185 -30
  135. package/dist/commands/{events.js → log.js} +28 -38
  136. package/dist/commands/migrate-cli.js +54 -0
  137. package/dist/commands/migration-tool.js +55 -0
  138. package/dist/commands/observability-cli.js +70 -208
  139. package/dist/commands/proposal/diff-format.js +50 -0
  140. package/dist/commands/proposal/drain-policies.js +0 -6
  141. package/dist/commands/proposal/drain.js +91 -40
  142. package/dist/commands/proposal/proposal-cli.js +134 -132
  143. package/dist/commands/proposal/proposal-types.js +56 -0
  144. package/dist/commands/proposal/proposal.js +83 -65
  145. package/dist/commands/proposal/propose-cli.js +88 -0
  146. package/dist/commands/proposal/propose.js +105 -88
  147. package/dist/commands/proposal/repository.js +1303 -278
  148. package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
  149. package/dist/commands/proposal/validators/proposal-validators.js +61 -12
  150. package/dist/commands/proposal/validators/proposals.js +6 -8
  151. package/dist/commands/read/curate.js +78 -73
  152. package/dist/commands/read/knowledge.js +510 -13
  153. package/dist/commands/read/registry-search.js +2 -2
  154. package/dist/commands/read/remember-cli.js +84 -15
  155. package/dist/commands/read/search-cli.js +203 -96
  156. package/dist/commands/read/search.js +126 -94
  157. package/dist/commands/read/show.js +226 -250
  158. package/dist/commands/registry-cli.js +34 -60
  159. package/dist/commands/remember.js +18 -57
  160. package/dist/commands/sources/add-cli.js +104 -49
  161. package/dist/commands/sources/bundle-cli.js +166 -0
  162. package/dist/commands/sources/bundle-config-ops.js +63 -0
  163. package/dist/commands/sources/info.js +27 -15
  164. package/dist/commands/sources/init.js +30 -40
  165. package/dist/commands/sources/installed-stashes.js +469 -172
  166. package/dist/commands/sources/schema-repair.js +10 -9
  167. package/dist/commands/sources/self-update.js +182 -121
  168. package/dist/commands/sources/source-add.js +169 -178
  169. package/dist/commands/sources/source-clone.js +144 -41
  170. package/dist/commands/sources/source-manage.js +94 -59
  171. package/dist/commands/sources/sources-cli.js +64 -205
  172. package/dist/commands/sources/stash-cli.js +91 -54
  173. package/dist/commands/sources/stash-skeleton.js +1 -1
  174. package/dist/commands/tasks/tasks-cli.js +106 -104
  175. package/dist/commands/tasks/tasks.js +445 -262
  176. package/dist/commands/workflow-cli.js +75 -228
  177. package/dist/core/action-contributors.js +1 -1
  178. package/dist/core/activation-policy.js +49 -0
  179. package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
  180. package/dist/core/adapter/adapters/akm-adapter.js +528 -0
  181. package/dist/core/adapter/adapters/akm-lint.js +392 -0
  182. package/dist/core/adapter/adapters/akm-metadata.js +387 -0
  183. package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
  184. package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
  185. package/dist/core/adapter/adapters/claude-adapter.js +61 -0
  186. package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
  187. package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
  188. package/dist/core/adapter/adapters/index.js +80 -0
  189. package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
  190. package/dist/core/adapter/adapters/okf-adapter.js +391 -0
  191. package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
  192. package/dist/core/adapter/adapters/shared.js +286 -0
  193. package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
  194. package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
  195. package/dist/core/adapter/bundle-adapter.js +4 -0
  196. package/dist/core/adapter/detect-adapter.js +17 -0
  197. package/dist/core/adapter/recognize-match.js +44 -0
  198. package/dist/core/adapter/registry.js +56 -0
  199. package/dist/core/adapter/types.js +4 -0
  200. package/dist/core/asset/akm-markdown.js +30 -0
  201. package/dist/core/asset/asset-placement.js +243 -0
  202. package/dist/core/asset/asset-ref.js +110 -79
  203. package/dist/core/asset/asset-serialize.js +20 -0
  204. package/dist/core/asset/frontmatter.js +28 -12
  205. package/dist/core/asset/markdown.js +40 -51
  206. package/dist/core/asset/resolve-ref.js +274 -0
  207. package/dist/core/asset/stash-meta.js +2 -2
  208. package/dist/core/bundle-id.js +51 -0
  209. package/dist/core/common.js +281 -86
  210. package/dist/core/config/config-io.js +42 -128
  211. package/dist/core/config/config-schema.js +233 -855
  212. package/dist/core/config/config-sources.js +162 -39
  213. package/dist/core/config/config-types.js +16 -11
  214. package/dist/core/config/config-version.js +29 -0
  215. package/dist/core/config/config-walker.js +126 -37
  216. package/dist/core/config/config.js +154 -331
  217. package/dist/core/config/deep-merge.js +41 -0
  218. package/dist/core/config/engine-semantics.js +28 -0
  219. package/dist/core/config/experimental.js +21 -0
  220. package/dist/core/config/schema/embedding.js +38 -0
  221. package/dist/core/config/schema/engines.js +116 -0
  222. package/dist/core/config/schema/experimental.js +47 -0
  223. package/dist/core/config/schema/feedback.js +31 -0
  224. package/dist/core/config/schema/improve-processes.js +389 -0
  225. package/dist/core/config/schema/improve.js +94 -0
  226. package/dist/core/config/schema/index-config.js +176 -0
  227. package/dist/core/config/schema/output.js +18 -0
  228. package/dist/core/config/schema/primitives.js +94 -0
  229. package/dist/core/config/schema/search.js +30 -0
  230. package/dist/core/config/schema/setup.js +18 -0
  231. package/dist/core/config/schema/sources-bundles.js +169 -0
  232. package/dist/core/config/schema/workflow.js +29 -0
  233. package/dist/core/env-secret-ref.js +155 -20
  234. package/dist/core/errors.js +17 -15
  235. package/dist/core/events-types.js +4 -0
  236. package/dist/core/events.js +46 -128
  237. package/dist/core/extra-params.js +62 -0
  238. package/dist/core/file-change.js +17 -0
  239. package/dist/core/file-lock.js +202 -57
  240. package/dist/core/fs-txn.js +392 -0
  241. package/dist/core/git-message.js +59 -0
  242. package/dist/core/improve-result.js +167 -0
  243. package/dist/core/lesson-lint.js +1 -17
  244. package/dist/core/logs-db.js +1 -1
  245. package/dist/core/maintenance-barrier.js +135 -0
  246. package/dist/core/migration-operation.js +44 -0
  247. package/dist/core/mutation-target.js +78 -0
  248. package/dist/core/paths.js +22 -25
  249. package/dist/core/platform.js +10 -0
  250. package/dist/core/recognition-util.js +128 -0
  251. package/dist/core/redaction.js +392 -0
  252. package/dist/core/standards/resolve-standards-context.js +36 -65
  253. package/dist/core/standards/resolve-stash-standards.js +2 -2
  254. package/dist/core/standards/resolve-type-conventions.js +5 -5
  255. package/dist/core/state/migrations.js +242 -11
  256. package/dist/core/state-db.js +98 -10
  257. package/dist/core/structured.js +1 -1
  258. package/dist/core/subprocess.js +303 -0
  259. package/dist/core/text-truncation.js +9 -5
  260. package/dist/core/time.js +20 -0
  261. package/dist/core/type-presentation.js +130 -0
  262. package/dist/core/warn.js +0 -3
  263. package/dist/core/write-source.js +834 -118
  264. package/dist/indexer/bundle-identity-guard.js +92 -0
  265. package/dist/indexer/db/graph-db.js +1 -25
  266. package/dist/indexer/db/llm-cache.js +1 -1
  267. package/dist/indexer/ensure-index.js +30 -9
  268. package/dist/indexer/graph/graph-boost.js +9 -30
  269. package/dist/indexer/graph/graph-extraction.js +41 -27
  270. package/dist/indexer/graph/graph-types.js +4 -0
  271. package/dist/indexer/index-writer-lock.js +93 -49
  272. package/dist/indexer/index-written-assets.js +100 -53
  273. package/dist/indexer/indexer.js +746 -329
  274. package/dist/indexer/init.js +18 -25
  275. package/dist/indexer/installations.js +142 -0
  276. package/dist/indexer/passes/dir-staleness.js +18 -10
  277. package/dist/indexer/passes/memory-inference.js +25 -15
  278. package/dist/indexer/passes/metadata.js +412 -243
  279. package/dist/indexer/scan/doc-to-entry.js +160 -0
  280. package/dist/indexer/scan/drain-dir.js +134 -0
  281. package/dist/indexer/search/db-search.js +292 -108
  282. package/dist/indexer/search/fts-query.js +64 -0
  283. package/dist/indexer/search/ranking-contributors.js +145 -25
  284. package/dist/indexer/search/ranking-types.js +4 -0
  285. package/dist/indexer/search/ranking.js +28 -71
  286. package/dist/indexer/search/search-attribution.js +67 -0
  287. package/dist/indexer/search/search-fields.js +18 -3
  288. package/dist/indexer/search/search-hit-enrichers.js +30 -40
  289. package/dist/indexer/search/search-source.js +157 -111
  290. package/dist/indexer/search/semantic-status.js +4 -1
  291. package/dist/indexer/usage/usage-events.js +10 -30
  292. package/dist/indexer/walk/file-context.js +3 -45
  293. package/dist/indexer/walk/matchers.js +42 -73
  294. package/dist/indexer/walk/path-resolver.js +11 -5
  295. package/dist/indexer/walk/walker.js +42 -14
  296. package/dist/integrations/agent/builder-shared.js +7 -0
  297. package/dist/integrations/agent/builders.js +5 -58
  298. package/dist/integrations/agent/config.js +3 -143
  299. package/dist/integrations/agent/detect.js +17 -2
  300. package/dist/integrations/agent/engine-resolution.js +231 -0
  301. package/dist/integrations/agent/index.js +1 -2
  302. package/dist/integrations/agent/model-aliases.js +8 -3
  303. package/dist/integrations/agent/profiles.js +6 -99
  304. package/dist/integrations/agent/prompts.js +46 -18
  305. package/dist/integrations/agent/runner-dispatch.js +78 -13
  306. package/dist/integrations/agent/runner.js +76 -208
  307. package/dist/integrations/agent/spawn.js +48 -279
  308. package/dist/integrations/harnesses/aider/agent-builder.js +9 -8
  309. package/dist/integrations/harnesses/aider/index.js +2 -12
  310. package/dist/integrations/harnesses/amazonq/agent-builder.js +10 -16
  311. package/dist/integrations/harnesses/amazonq/index.js +3 -17
  312. package/dist/integrations/harnesses/claude/agent-builder.js +2 -3
  313. package/dist/integrations/harnesses/claude/config-import.js +1 -3
  314. package/dist/integrations/harnesses/claude/index.js +1 -14
  315. package/dist/integrations/harnesses/claude/session-log.js +27 -75
  316. package/dist/integrations/harnesses/codex/agent-builder.js +8 -7
  317. package/dist/integrations/harnesses/codex/index.js +2 -13
  318. package/dist/integrations/harnesses/copilot/agent-builder.js +9 -9
  319. package/dist/integrations/harnesses/copilot/index.js +1 -13
  320. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -9
  321. package/dist/integrations/harnesses/gemini/index.js +1 -13
  322. package/dist/integrations/harnesses/ids.js +24 -0
  323. package/dist/integrations/harnesses/index.js +31 -33
  324. package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
  325. package/dist/integrations/harnesses/opencode/config-import.js +1 -3
  326. package/dist/integrations/harnesses/opencode/index.js +1 -18
  327. package/dist/integrations/harnesses/opencode/session-log.js +67 -125
  328. package/dist/integrations/harnesses/opencode-sdk/harness.js +3 -17
  329. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +274 -191
  330. package/dist/integrations/harnesses/openhands/agent-builder.js +12 -10
  331. package/dist/integrations/harnesses/openhands/index.js +2 -12
  332. package/dist/integrations/harnesses/pi/agent-builder.js +11 -18
  333. package/dist/integrations/harnesses/pi/index.js +3 -16
  334. package/dist/integrations/harnesses/shared.js +17 -0
  335. package/dist/integrations/harnesses/types.js +38 -34
  336. package/dist/integrations/lockfile.js +211 -24
  337. package/dist/integrations/session-logs/index.js +24 -40
  338. package/dist/integrations/session-logs/provider-base.js +113 -0
  339. package/dist/llm/client.js +182 -110
  340. package/dist/llm/embedders/deterministic.js +2 -2
  341. package/dist/llm/embedders/remote.js +21 -9
  342. package/dist/llm/feature-gate.js +17 -57
  343. package/dist/llm/graph-extract.js +12 -13
  344. package/dist/llm/index-passes.js +8 -42
  345. package/dist/llm/memory-infer.js +144 -1
  346. package/dist/llm/metadata-enhance.js +45 -30
  347. package/dist/llm/structured-call.js +16 -8
  348. package/dist/llm/usage-persist.js +30 -5
  349. package/dist/llm/usage-telemetry.js +59 -6
  350. package/dist/output/cli-hints.js +1 -2
  351. package/dist/output/command-registry.js +27 -0
  352. package/dist/output/context.js +22 -7
  353. package/dist/output/format-exempt.js +80 -0
  354. package/dist/output/generic-render.js +251 -0
  355. package/dist/output/html-render.js +11 -16
  356. package/dist/output/render-registry.js +57 -0
  357. package/dist/output/renderers.js +15 -281
  358. package/dist/output/shapes/curate.js +10 -1
  359. package/dist/output/shapes/events.js +12 -7
  360. package/dist/output/shapes/helpers.js +58 -84
  361. package/dist/output/shapes/passthrough.js +8 -40
  362. package/dist/output/shapes/proposal/producer.js +15 -7
  363. package/dist/output/shapes/registry.js +12 -6
  364. package/dist/output/shapes.js +0 -9
  365. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  366. package/dist/output/text/bundle-show.js +7 -0
  367. package/dist/output/text/command-format.js +562 -0
  368. package/dist/output/text/env.js +1 -3
  369. package/dist/output/text/events.js +8 -7
  370. package/dist/output/text/helpers.js +15 -1375
  371. package/dist/output/text/proposal/producer.js +4 -2
  372. package/dist/output/text/proposal-format.js +202 -0
  373. package/dist/output/text/registry-commands.js +1 -2
  374. package/dist/output/text/registry.js +12 -6
  375. package/dist/output/text/show-directives.js +117 -0
  376. package/dist/output/text/show-format.js +103 -0
  377. package/dist/output/text/sync.js +5 -0
  378. package/dist/output/text/workflow-format.js +332 -0
  379. package/dist/output/text/workflow.js +1 -2
  380. package/dist/output/text.js +10 -19
  381. package/dist/registry/factory.js +4 -6
  382. package/dist/registry/origin-resolve.js +16 -27
  383. package/dist/registry/providers/skills-sh.js +3 -3
  384. package/dist/registry/providers/static-index.js +15 -25
  385. package/dist/registry/resolve.js +43 -94
  386. package/dist/registry/semver.js +43 -0
  387. package/dist/runtime.js +81 -12
  388. package/dist/scripts/akm-migrate.js +35529 -0
  389. package/dist/setup/detect.js +5 -7
  390. package/dist/setup/detected-engines.js +136 -0
  391. package/dist/setup/engine-config.js +100 -0
  392. package/dist/setup/registry-stash-loader.js +3 -3
  393. package/dist/setup/semantic-assets.js +12 -9
  394. package/dist/setup/setup.js +444 -208
  395. package/dist/setup/steps/connection-shared.js +120 -0
  396. package/dist/setup/steps/connection.js +108 -305
  397. package/dist/setup/steps/platforms.js +13 -12
  398. package/dist/setup/steps/semantic.js +15 -3
  399. package/dist/setup/steps/sources.js +21 -15
  400. package/dist/setup/steps/stashdir.js +6 -4
  401. package/dist/setup/steps/tasks.js +236 -119
  402. package/dist/setup/steps.js +3 -2
  403. package/dist/sources/freshness.js +39 -0
  404. package/dist/sources/provider-factory.js +11 -17
  405. package/dist/sources/providers/filesystem.js +2 -3
  406. package/dist/sources/providers/git-install.js +278 -34
  407. package/dist/sources/providers/git-provider.js +54 -56
  408. package/dist/sources/providers/git-stash.js +420 -91
  409. package/dist/sources/providers/git.js +2 -2
  410. package/dist/sources/providers/npm.js +16 -19
  411. package/dist/sources/providers/provider-utils.js +47 -22
  412. package/dist/sources/providers/sync-from-ref.js +3 -9
  413. package/dist/sources/providers/website.js +2 -2
  414. package/dist/sources/resolve.js +11 -10
  415. package/dist/sources/snapshot-fetchers/types.js +4 -0
  416. package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
  417. package/dist/storage/database.js +60 -4
  418. package/dist/storage/engines/sqlite-migrations.js +156 -5
  419. package/dist/storage/locations.js +1 -2
  420. package/dist/storage/repositories/canaries-repository.js +1 -1
  421. package/dist/storage/repositories/events-repository.js +51 -11
  422. package/dist/storage/repositories/improve-runs-repository.js +6 -32
  423. package/dist/storage/repositories/index-connection.js +79 -0
  424. package/dist/storage/repositories/index-db.js +4 -3
  425. package/dist/storage/repositories/index-entries-repository.js +863 -0
  426. package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
  427. package/dist/storage/repositories/index-entry-types.js +4 -0
  428. package/dist/storage/repositories/index-fts-repository.js +167 -0
  429. package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
  430. package/dist/storage/repositories/index-meta-repository.js +49 -0
  431. package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
  432. package/dist/storage/repositories/index-sql.js +12 -0
  433. package/dist/storage/repositories/index-utility-repository.js +356 -0
  434. package/dist/storage/repositories/index-vec-repository.js +250 -0
  435. package/dist/storage/repositories/outcome-repository.js +119 -0
  436. package/dist/storage/repositories/proposals-repository.js +317 -75
  437. package/dist/storage/repositories/registry-cache.js +1 -1
  438. package/dist/storage/repositories/salience-repository.js +172 -0
  439. package/dist/storage/repositories/task-history-repository.js +110 -3
  440. package/dist/storage/repositories/workflow-runs-repository.js +68 -35
  441. package/dist/tasks/backends/cron.js +169 -46
  442. package/dist/tasks/backends/exec-utils.js +76 -3
  443. package/dist/tasks/backends/index.js +6 -9
  444. package/dist/tasks/backends/launchd.js +292 -55
  445. package/dist/tasks/backends/schtasks.js +557 -70
  446. package/dist/tasks/backends/types.js +4 -0
  447. package/dist/tasks/command-executable.js +93 -0
  448. package/dist/tasks/embedded.js +56 -38
  449. package/dist/tasks/parser.js +156 -64
  450. package/dist/tasks/resolve-akm-bin.js +144 -51
  451. package/dist/tasks/runner.js +377 -209
  452. package/dist/tasks/schedule.js +108 -19
  453. package/dist/tasks/scheduler-invocation.js +296 -0
  454. package/dist/tasks/schema.js +1 -1
  455. package/dist/tasks/task-id.js +35 -0
  456. package/dist/tasks/validator.js +30 -16
  457. package/dist/workflows/authoring/authoring.js +96 -148
  458. package/dist/workflows/authoring/scope-key.js +1 -1
  459. package/dist/workflows/cli.js +0 -20
  460. package/dist/workflows/concurrency-policy.js +15 -0
  461. package/dist/workflows/exec/brief.js +25 -59
  462. package/dist/workflows/exec/frozen-judge.js +47 -0
  463. package/dist/workflows/exec/native-executor.js +157 -94
  464. package/dist/workflows/exec/report.js +365 -200
  465. package/dist/workflows/exec/run-workflow.js +46 -40
  466. package/dist/workflows/exec/scheduler.js +12 -41
  467. package/dist/workflows/exec/step-work.js +239 -205
  468. package/dist/workflows/exec/workflow-engine-gate.js +67 -0
  469. package/dist/workflows/ir/compile.js +141 -283
  470. package/dist/workflows/ir/freeze.js +233 -0
  471. package/dist/workflows/ir/plan-hash.js +40 -5
  472. package/dist/workflows/ir/schema.js +537 -1
  473. package/dist/workflows/parser.js +878 -306
  474. package/dist/workflows/program/expressions.js +20 -208
  475. package/dist/workflows/program/schema.js +7 -10
  476. package/dist/workflows/renderer.js +99 -121
  477. package/dist/workflows/resource-limits.js +22 -0
  478. package/dist/workflows/runtime/checkin.js +1 -1
  479. package/dist/workflows/runtime/plan-classifier.js +131 -0
  480. package/dist/workflows/runtime/runs.js +200 -113
  481. package/dist/workflows/runtime/unit-checkin.js +1 -1
  482. package/dist/workflows/runtime/unit-phases.js +20 -0
  483. package/dist/workflows/runtime/workflow-asset-loader.js +235 -97
  484. package/dist/workflows/schema.js +1 -11
  485. package/dist/workflows/validate-summary.js +4 -26
  486. package/dist/workflows/validator.js +52 -30
  487. package/docs/README.md +42 -78
  488. package/docs/migration/README.md +8 -0
  489. package/docs/migration/release-notes/0.6.0.md +1 -1
  490. package/docs/migration/release-notes/0.7.0.md +9 -8
  491. package/docs/migration/release-notes/0.9.0.md +158 -14
  492. package/docs/migration/v0.7-to-v0.8.md +46 -47
  493. package/docs/migration/v0.8-to-v0.9.md +844 -0
  494. package/docs/reference/README.md +12 -0
  495. package/docs/reference/data-and-telemetry.md +333 -0
  496. package/package.json +21 -17
  497. package/schemas/akm-asset-envelope.json +93 -0
  498. package/schemas/akm-config.json +4636 -0
  499. package/schemas/akm-task.json +87 -0
  500. package/{dist/schemas → schemas}/akm-workflow.json +127 -82
  501. package/dist/akm-migrate-storage +0 -38
  502. package/dist/assets/help/help-accept.md +0 -12
  503. package/dist/assets/help/help-improve.md +0 -84
  504. package/dist/assets/help/help-proposals.md +0 -17
  505. package/dist/assets/help/help-propose.md +0 -17
  506. package/dist/assets/help/help-reject.md +0 -11
  507. package/dist/assets/profiles/frequent.json +0 -13
  508. package/dist/assets/profiles/recombine-only.json +0 -21
  509. package/dist/assets/profiles/reflect-distill.json +0 -30
  510. package/dist/assets/profiles/synthesize.json +0 -15
  511. package/dist/assets/prompts/procedural-system.md +0 -44
  512. package/dist/assets/prompts/recombine-system.md +0 -40
  513. package/dist/assets/prompts/staleness-detect-system.md +0 -6
  514. package/dist/assets/tasks/core/backup.yml +0 -4
  515. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  516. package/dist/assets/templates/html/default.html +0 -78
  517. package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
  518. package/dist/assets/wiki/index-template.md +0 -12
  519. package/dist/assets/wiki/ingest-workflow-template.md +0 -83
  520. package/dist/assets/wiki/log-template.md +0 -8
  521. package/dist/assets/wiki/schema-template.md +0 -61
  522. package/dist/cli/config-migrate.js +0 -150
  523. package/dist/cli/config-validate.js +0 -39
  524. package/dist/commands/graph/graph-cli.js +0 -124
  525. package/dist/commands/graph/graph.js +0 -487
  526. package/dist/commands/improve/calibration.js +0 -161
  527. package/dist/commands/improve/dedup.js +0 -482
  528. package/dist/commands/improve/extract-watch.js +0 -140
  529. package/dist/commands/improve/hot-probation.js +0 -45
  530. package/dist/commands/improve/improve-auto-accept.js +0 -276
  531. package/dist/commands/improve/improve-profiles.js +0 -168
  532. package/dist/commands/improve/procedural.js +0 -398
  533. package/dist/commands/improve/recombine.js +0 -818
  534. package/dist/commands/improve/schema-similarity-gate.js +0 -168
  535. package/dist/commands/lint/agent-linter.js +0 -44
  536. package/dist/commands/lint/command-linter.js +0 -44
  537. package/dist/commands/lint/default-linter.js +0 -16
  538. package/dist/commands/lint/fact-linter.js +0 -39
  539. package/dist/commands/lint/knowledge-linter.js +0 -16
  540. package/dist/commands/lint/memory-linter.js +0 -61
  541. package/dist/commands/lint/registry.js +0 -41
  542. package/dist/commands/lint/skill-linter.js +0 -45
  543. package/dist/commands/lint/task-linter.js +0 -50
  544. package/dist/commands/lint/workflow-linter.js +0 -81
  545. package/dist/commands/proposal/legacy-import.js +0 -115
  546. package/dist/commands/sources/history.js +0 -196
  547. package/dist/commands/tasks/default-tasks.js +0 -186
  548. package/dist/commands/wiki-cli.js +0 -292
  549. package/dist/core/asset/asset-registry.js +0 -76
  550. package/dist/core/asset/asset-spec.js +0 -316
  551. package/dist/core/config/config-migration.js +0 -602
  552. package/dist/core/deep-merge.js +0 -38
  553. package/dist/core/eval/rank-metrics.js +0 -113
  554. package/dist/core/ripgrep/install.js +0 -163
  555. package/dist/core/ripgrep/resolve.js +0 -81
  556. package/dist/indexer/db/db.js +0 -1414
  557. package/dist/indexer/manifest.js +0 -170
  558. package/dist/indexer/passes/metadata-contributors.js +0 -31
  559. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
  560. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -25
  561. package/dist/llm/call-ai.js +0 -62
  562. package/dist/llm/memory-infer-impl.js +0 -138
  563. package/dist/output/shapes/distill.js +0 -14
  564. package/dist/output/shapes/history.js +0 -11
  565. package/dist/output/text/distill.js +0 -6
  566. package/dist/output/text/enable-disable.js +0 -8
  567. package/dist/output/text/history.js +0 -6
  568. package/dist/output/text/wiki.js +0 -16
  569. package/dist/registry/build-index.js +0 -386
  570. package/dist/schemas/akm-config.json +0 -14225
  571. package/dist/scripts/migrate-storage.js +0 -13169
  572. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -10169
  573. package/dist/scripts/migrations/v16-to-v17.js +0 -141
  574. package/dist/setup/legacy-config.js +0 -106
  575. package/dist/storage/repositories/consolidation-repository.js +0 -38
  576. package/dist/storage/repositories/recombine-repository.js +0 -213
  577. package/dist/wiki/wiki-templates.js +0 -15
  578. package/dist/wiki/wiki.js +0 -1012
  579. package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
  580. package/dist/workflows/db.js +0 -350
  581. package/dist/workflows/exec/watch.js +0 -116
  582. package/dist/workflows/program/parser.js +0 -760
  583. package/dist/workflows/program/project.js +0 -105
  584. package/docs/data-and-telemetry.md +0 -227
  585. package/docs/migration/release-notes/0.9.0-beta.60.md +0 -19
  586. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
  587. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
@@ -11,23 +11,36 @@
11
11
  *
12
12
  * `akm secret` manages whole-file secrets under each stash's secrets/ directory.
13
13
  * Unlike env files (.env key/value), the ENTIRE file is the secret value. The bytes
14
- * are NEVER written to stdout or structured output. Values reach a command only
15
- * via `akm secret run` (injected into a child env var) or `akm secret path`
16
- * (the Docker /run/secrets + `_FILE` convention).
14
+ * are NEVER written to stdout or structured output. The only value-use path is
15
+ * `akm secret run` (injected into a child env var).
16
+ *
17
+ * `secret path` and `secret remove` were REMOVED in 0.9.0 (R-027 / D-49): an
18
+ * audit found `path` resolved the ref through the read-side, all-sources
19
+ * resolver while `remove` resolved it through the write-target resolver, so
20
+ * `akm secret path <ref>` and `akm secret remove <ref>` could silently name
21
+ * two DIFFERENT files when a ref existed in more than one stash — inspect one,
22
+ * delete the other. The owner's ruling was to drop both subcommands rather
23
+ * than reconcile the resolvers. A ref's file lives at `<bundle>/secrets/<name>`
24
+ * (matching the ref exactly, e.g. `secrets/deploy-key` -> `secrets/deploy-key`
25
+ * under a bundle root — `akm bundle list` prints each configured bundle's root
26
+ * path); locate or delete it directly, or consume its value without touching
27
+ * disk via `akm secret run <ref> <VAR> -- <command>`.
17
28
  */
18
29
  import { spawnSync } from "node:child_process";
19
30
  import fs from "node:fs";
20
31
  import path from "node:path";
32
+ import { getParsedInvocation } from "../../cli/invocation.js";
21
33
  import { getStringArg } from "../../cli/parse-args.js";
22
34
  import { defineGroupCommand, defineJsonCommand, output } from "../../cli/shared.js";
23
- import { deriveCanonicalAssetName } from "../../core/asset/asset-spec.js";
35
+ import { deriveCanonicalAssetName } from "../../core/asset/asset-placement.js";
24
36
  import { loadConfig } from "../../core/config/config.js";
25
- import { makeSecretRef, resolveSecretPath } from "../../core/env-secret-ref.js";
37
+ import { makeSecretRef, resolveSecretPath, resolveSecretWriteTarget, withEnvSecretWrite, } from "../../core/env-secret-ref.js";
26
38
  import { ConfigError, NotFoundError, UsageError } from "../../core/errors.js";
27
39
  import { appendEvent } from "../../core/events.js";
28
40
  import { resolveSourceEntries } from "../../indexer/search/search-source.js";
29
41
  import { readStdin } from "../../runtime.js";
30
42
  import { buildChildEnv } from "./child-env.js";
43
+ import { sensitiveMarkerPath } from "./marker-path.js";
31
44
  function parseKeyListFlag(raw) {
32
45
  if (raw === undefined)
33
46
  return undefined;
@@ -56,7 +69,7 @@ function listSecretsRecursive() {
56
69
  if (entry.name.endsWith(".lock") || entry.name.endsWith(".sensitive"))
57
70
  continue;
58
71
  // A sibling `<name>.sensitive` marker suppresses listing.
59
- if (fs.existsSync(`${full}.sensitive`))
72
+ if (fs.existsSync(sensitiveMarkerPath(full, "secret")))
60
73
  continue;
61
74
  const canonical = deriveCanonicalAssetName("secret", secretsDir, full);
62
75
  if (!canonical)
@@ -71,7 +84,7 @@ function listSecretsRecursive() {
71
84
  const secretListCommand = defineJsonCommand({
72
85
  meta: {
73
86
  name: "list",
74
- description: "List all secrets across all stashes by name (the file contents are never shown)",
87
+ description: "List all secrets across all bundles by name (the file contents are never shown)",
75
88
  },
76
89
  async run() {
77
90
  output("secret-list", { secrets: listSecretsRecursive() });
@@ -85,7 +98,7 @@ const secretSetCommand = defineJsonCommand({
85
98
  args: {
86
99
  ref: {
87
100
  type: "positional",
88
- description: "Secret ref (flat name, e.g. secret:deploy-key or just deploy-key; use --path for a subdirectory)",
101
+ description: "Secret ref (flat name, e.g. secrets/deploy-key or just deploy-key; use --path for a subdirectory)",
89
102
  required: true,
90
103
  },
91
104
  path: {
@@ -94,10 +107,16 @@ const secretSetCommand = defineJsonCommand({
94
107
  },
95
108
  "from-file": { type: "string", description: "Read the value from this file (stored byte-exact)" },
96
109
  "from-env": { type: "string", description: "Read the value from the named environment variable" },
110
+ target: {
111
+ type: "string",
112
+ description: "Override the write destination. Accepts a source name from your config; falls back to defaultWriteTarget then the working bundle.",
113
+ },
97
114
  },
98
115
  async run({ args }) {
99
116
  const { setSecret } = await import("./secret.js");
100
- const { name, absPath, source } = resolveSecretPath(args.ref, { subPath: getStringArg(args, "path") });
117
+ const { name, absPath, target, ref } = resolveSecretWriteTarget(args.ref, args.target, {
118
+ subPath: getStringArg(args, "path"),
119
+ });
101
120
  const fromEnv = args["from-env"];
102
121
  const fromFile = args["from-file"];
103
122
  if (fromEnv !== undefined && fromFile !== undefined) {
@@ -131,24 +150,8 @@ const secretSetCommand = defineJsonCommand({
131
150
  // byte-exact storage of multi-line material (PEM keys, certs).
132
151
  value = Buffer.from(stdinBuf.toString("utf8").replace(/\n$/, ""), "utf8");
133
152
  }
134
- setSecret(absPath, value);
135
- output("secret-set", { ref: makeSecretRef(name, source) });
136
- },
137
- });
138
- const secretPathCommand = defineJsonCommand({
139
- meta: {
140
- name: "path",
141
- description: "Print the absolute secret file path for the Docker `_FILE` convention, e.g. `MY_SECRET_FILE=$(akm secret path secret:deploy-key)`.",
142
- },
143
- args: {
144
- ref: { type: "positional", description: "Secret ref", required: true },
145
- },
146
- async run({ args }) {
147
- const { name, absPath, source } = resolveSecretPath(args.ref);
148
- if (!fs.existsSync(absPath)) {
149
- throw new NotFoundError(`Secret not found: ${makeSecretRef(name, source)}`);
150
- }
151
- process.stdout.write(`${absPath}\n`);
153
+ withEnvSecretWrite(target, { type: "secret", name }, "Update", [absPath], () => setSecret(absPath, value));
154
+ output("secret-set", { ref });
152
155
  },
153
156
  });
154
157
  const secretRunCommand = defineJsonCommand({
@@ -181,11 +184,10 @@ const secretRunCommand = defineJsonCommand({
181
184
  if (isDangerousEnvKey(varName)) {
182
185
  throw new UsageError(`Refusing to inject a secret into "${varName}": it is a known process-hijacking variable (e.g. LD_PRELOAD, PATH).`, "INVALID_FLAG_VALUE");
183
186
  }
184
- const dashIndex = process.argv.indexOf("--");
185
- if (dashIndex < 0 || dashIndex === process.argv.length - 1) {
187
+ const command = getParsedInvocation().passthroughArgs();
188
+ if (command.length === 0) {
186
189
  throw new UsageError("Missing command. Usage: akm secret run <ref> <VAR> -- <command>");
187
190
  }
188
- const command = process.argv.slice(dashIndex + 1);
189
191
  const { name, absPath, source } = resolveSecretPath(args.ref);
190
192
  if (!fs.existsSync(absPath)) {
191
193
  throw new NotFoundError(`Secret not found: ${makeSecretRef(name, source)}`);
@@ -216,46 +218,28 @@ const secretRunCommand = defineJsonCommand({
216
218
  }
217
219
  throw err;
218
220
  }
219
- process.exit(result.status ?? 0);
220
- },
221
- });
222
- const secretRemoveCommand = defineJsonCommand({
223
- meta: { name: "remove", description: "Remove a secret (and its .sensitive marker, if any)" },
224
- args: {
225
- ref: { type: "positional", description: "Secret ref", required: true },
226
- yes: { type: "boolean", alias: "y", description: "Skip confirmation prompt", default: false },
227
- },
228
- async run({ args }) {
229
- const { name, absPath, source } = resolveSecretPath(args.ref);
230
- const { confirmDestructive } = await import("../../cli/confirm.js");
231
- const confirmed = await confirmDestructive(`Remove secret "${args.ref}"? This cannot be undone.`, {
232
- yes: args.yes === true,
233
- });
234
- if (!confirmed) {
235
- process.stderr.write("Aborted.\n");
236
- return;
237
- }
238
- const { removeSecret } = await import("./secret.js");
239
- if (!fs.existsSync(absPath)) {
240
- throw new NotFoundError(`Secret not found: ${makeSecretRef(name, source)}`);
241
- }
242
- const removed = removeSecret(absPath);
243
- output("secret-remove", { ref: makeSecretRef(name, source), removed });
221
+ // R-067: was `process.exit(result.status ?? 0)`, unconditional even on
222
+ // the success path — it skipped the `finally { await
223
+ // disposeDispatchResources(); }` cleanup in src/cli.ts's `runCommand`.
224
+ // Setting `process.exitCode` and returning still exits with the child's
225
+ // exact status once the event loop drains, but lets cleanup run first —
226
+ // same pattern `emitJsonError` (src/cli/shared.ts) already established.
227
+ process.exitCode = result.status ?? 0;
228
+ return;
244
229
  },
245
230
  });
246
231
  export const secretCommand = defineGroupCommand({
247
232
  meta: {
248
233
  name: "secret",
249
- description: "Manage secrets — a single sensitive value used on its own for authentication (an API token, a PEM private key, a TLS cert), one value per file. Names are visible; the file contents are the value and never appear in structured output. For a group of related configuration loaded together, use `akm env`.",
234
+ description: "Manage secrets — one standalone sensitive value per file (an API token, a PEM private key, a TLS cert).\n\n" +
235
+ "Names are visible; the file contents are the value and never appear in structured output. For a group of related configuration loaded together, use `akm env`. A secret's file lives at `<bundle>/secrets/<name>` (`akm bundle list` shows bundle roots) — read or delete it there directly, or consume its value without writing it anywhere via `akm secret run <ref> <VAR> -- <command>`.",
250
236
  },
251
237
  subCommands: {
252
238
  list: secretListCommand,
253
- path: secretPathCommand,
254
239
  run: secretRunCommand,
255
240
  set: secretSetCommand,
256
- remove: secretRemoveCommand,
257
- },
258
- defaultRun() {
259
- output("secret-list", { secrets: listSecretsRecursive() });
260
241
  },
242
+ // No `defaultRun`: bare `akm secret` is a usage error (exit 2), the canonical
243
+ // bare-group behavior — owner ruling 12. Run `akm secret list` for what the
244
+ // bare form used to print.
261
245
  });
@@ -14,20 +14,26 @@
14
14
  *
15
15
  * Invariant: a secret's bytes must never be written to stdout, returned
16
16
  * through the indexer / `akm show` renderer, or any structured output channel.
17
- * The supported value-use paths are:
17
+ * The supported value-use path is:
18
18
  *
19
19
  * - `akm secret run <ref> <VAR> -- <cmd>` — value injected into the child
20
20
  * process env as `VAR=<value>` (see `readValue`).
21
- * - `akm secret path <ref>` — print the file path so a command can read it
22
- * itself (Docker `/run/secrets` + `_FILE` convention).
21
+ *
22
+ * `akm secret path <ref>` (print the file path for the Docker `/run/secrets` +
23
+ * `_FILE` convention) was removed in 0.9.0 alongside `akm secret remove` — an
24
+ * audit found the two resolved a ref through different stash-selection logic
25
+ * and could silently target different files. A ref's file still lives at
26
+ * `<stash>/secrets/<name>`; locate or delete it there directly.
23
27
  *
24
28
  * Values are stored as raw bytes (no quoting, multi-line allowed) so they
25
29
  * round-trip byte-exact, unlike env values which forbid literal newlines.
26
30
  */
31
+ import { createHash } from "node:crypto";
27
32
  import fs from "node:fs";
28
33
  import path from "node:path";
29
- import { writeFileAtomic } from "../../core/common.js";
30
- import { probeLock, releaseLock, tryAcquireLockSync } from "../../core/file-lock.js";
34
+ import { safeRealpath, writeFileAtomic } from "../../core/common.js";
35
+ import { createLockPayload, probeLock, reclaimStaleLock, releaseLock, tryAcquireLockSync, } from "../../core/file-lock.js";
36
+ import { getDataDir } from "../../core/paths.js";
31
37
  import { sleepSync } from "../../runtime.js";
32
38
  // ── Write-lock helper ─────────────────────────────────────────────────────────
33
39
  /**
@@ -37,19 +43,22 @@ import { sleepSync } from "../../runtime.js";
37
43
  * throw rather than silently proceeding.
38
44
  */
39
45
  export function withSecretLock(secretPath, fn) {
40
- const lockPath = `${secretPath}.lock`;
46
+ const lockPath = secretLockPath(secretPath);
47
+ const lockDir = path.dirname(lockPath);
48
+ fs.mkdirSync(lockDir, { recursive: true, mode: 0o700 });
41
49
  const deadline = Date.now() + 5000;
42
- while (!tryAcquireLockSync(lockPath, String(process.pid))) {
50
+ let ownership;
51
+ while (!ownership) {
52
+ ownership = tryAcquireLockSync(lockPath, createLockPayload());
53
+ if (ownership)
54
+ break;
43
55
  const probe = probeLock(lockPath);
44
- if (probe.state === "stale") {
45
- releaseLock(lockPath);
56
+ if (probe.state === "stale" && reclaimStaleLock(lockPath, probe)) {
46
57
  continue;
47
58
  }
48
59
  if (Date.now() > deadline) {
49
- const holderHint = probe.state === "held"
50
- ? ` Lock file ${lockPath} is held by live PID ${probe.holderPid}.`
51
- : ` Lock file ${lockPath} could not be inspected.`;
52
- throw new Error(`Could not acquire secret lock for ${secretPath} after 5s.${holderHint} Retry once any other akm secret operation finishes, or remove the stale lock file.`);
60
+ const holderHint = probe.state === "held" ? ` It is held by live PID ${probe.holderPid}.` : "";
61
+ throw new Error(`Could not acquire the secret write lock after 5s.${holderHint} Retry once any other akm secret operation finishes.`);
53
62
  }
54
63
  sleepSync(10);
55
64
  }
@@ -57,9 +66,15 @@ export function withSecretLock(secretPath, fn) {
57
66
  return fn();
58
67
  }
59
68
  finally {
60
- releaseLock(lockPath);
69
+ releaseLock(ownership);
61
70
  }
62
71
  }
72
+ export function secretLockPath(secretPath, platform = process.platform) {
73
+ const canonical = safeRealpath(secretPath);
74
+ const identity = platform === "win32" ? canonical.toLowerCase() : canonical;
75
+ const key = createHash("sha256").update(identity).digest("hex");
76
+ return path.join(getDataDir(), "secret-locks", `${key}.lock`);
77
+ }
63
78
  // ── Atomic byte write ──────────────────────────────────────────────────────────
64
79
  function ensureParentDir(filePath) {
65
80
  const dir = path.dirname(filePath);
@@ -68,38 +83,8 @@ function ensureParentDir(filePath) {
68
83
  }
69
84
  // ── Public API ──────────────────────────────────────────────────────────────
70
85
  /**
71
- * Walk a `secrets/` directory and return the POSIX-relative names of every
72
- * secret file. Lock files (`*.lock`), sensitive markers (`*.sensitive`), and
73
- * secrets with a sibling `<name>.sensitive` marker are excluded. The file
74
- * bodies are NEVER read.
75
- */
76
- export function listNames(secretsRoot) {
77
- if (!fs.existsSync(secretsRoot))
78
- return [];
79
- const names = [];
80
- const walk = (dir) => {
81
- for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
82
- const full = path.join(dir, entry.name);
83
- if (entry.isDirectory()) {
84
- walk(full);
85
- continue;
86
- }
87
- if (!entry.isFile())
88
- continue;
89
- if (entry.name.endsWith(".lock") || entry.name.endsWith(".sensitive"))
90
- continue;
91
- // A sibling `<name>.sensitive` marker suppresses listing.
92
- if (fs.existsSync(`${full}.sensitive`))
93
- continue;
94
- names.push(path.relative(secretsRoot, full).split(path.sep).join("/"));
95
- }
96
- };
97
- walk(secretsRoot);
98
- return names.sort();
99
- }
100
- /**
101
- * Read a secret's raw bytes. Internal use only (for `secret run` / `secret
102
- * path`). Callers MUST NOT write the returned value to stdout or any log.
86
+ * Read a secret's raw bytes. Internal use only (for `secret run`). Callers
87
+ * MUST NOT write the returned value to stdout or any log.
103
88
  */
104
89
  export function readValue(secretPath) {
105
90
  return fs.readFileSync(secretPath);
@@ -109,24 +94,9 @@ export function readValue(secretPath) {
109
94
  * mode 0600 under a write-lock. No quoting; multi-line / binary allowed.
110
95
  */
111
96
  export function setSecret(secretPath, value) {
112
- ensureParentDir(secretPath);
113
97
  withSecretLock(secretPath, () => {
98
+ ensureParentDir(secretPath);
114
99
  // Mode 0600: secrets must never be world-readable, even transiently.
115
100
  writeFileAtomic(secretPath, value, 0o600);
116
101
  });
117
102
  }
118
- /**
119
- * Remove a secret file (and its `.sensitive` marker, if present). Returns true
120
- * if the secret existed.
121
- */
122
- export function removeSecret(secretPath) {
123
- return withSecretLock(secretPath, () => {
124
- if (!fs.existsSync(secretPath))
125
- return false;
126
- fs.rmSync(secretPath);
127
- const marker = `${secretPath}.sensitive`;
128
- if (fs.existsSync(marker))
129
- fs.rmSync(marker);
130
- return true;
131
- });
132
- }