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
@@ -2,7 +2,7 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
- * launchd backend for `akm tasks` (macOS default).
5
+ * launchd backend for `akm task` (macOS default).
6
6
  *
7
7
  * Each task is written as a per-user LaunchAgent plist at
8
8
  * `~/Library/LaunchAgents/com.akm.task.<id>.plist` and registered via
@@ -29,7 +29,8 @@ import { ConfigError } from "../../core/errors.js";
29
29
  import { getTaskLogDir } from "../../core/paths.js";
30
30
  import { resolveAkmInvocation } from "../resolve-akm-bin.js";
31
31
  import { parseSchedule, translateToLaunchd } from "../schedule.js";
32
- import { escapeXml, nodeExec, nodeFs } from "./exec-utils.js";
32
+ import { buildScheduledTaskInvocation, parseScheduledTaskArgv, resolveScheduledTaskContext, schedulerContextDescriptor, schedulerContextPath, } from "../scheduler-invocation.js";
33
+ import { escapeXml, nodeExec, nodeFs, runOrThrow } from "./exec-utils.js";
33
34
  export const LAUNCHD_LABEL_PREFIX = "com.akm.task.";
34
35
  export function LAUNCHD_BACKEND(options = {}) {
35
36
  const exec = options.exec ?? defaultLaunchdExec();
@@ -37,57 +38,157 @@ export function LAUNCHD_BACKEND(options = {}) {
37
38
  const agentsDir = options.agentsDir ?? defaultAgentsDir();
38
39
  const logDir = options.logDir ?? getTaskLogDir();
39
40
  const akmArgv = options.akmArgv ?? resolveAkmInvocation().argv;
41
+ const scheduledContext = options.scheduledContext ?? resolveScheduledTaskContext();
40
42
  const plistPath = (id) => path.join(agentsDir, `${LAUNCHD_LABEL_PREFIX}${id}.plist`);
41
43
  const label = (id) => `${LAUNCHD_LABEL_PREFIX}${id}`;
42
44
  const target = (id) => `gui/${exec.uid()}/${label(id)}`;
45
+ const pathEnv = () => {
46
+ if (options.envPath === false)
47
+ return undefined;
48
+ if (typeof options.envPath === "string")
49
+ return options.envPath;
50
+ return process.env.PATH ?? "";
51
+ };
52
+ const defaultContextPath = schedulerContextPath(schedulerContextDescriptor(scheduledContext, pathEnv() ?? ""));
53
+ const setEnableState = (id, enabled) => {
54
+ const verb = enabled ? "enable" : "disable";
55
+ runOrThrow(exec, ["launchctl", verb, target(id)], {
56
+ message: (r) => `launchctl ${verb} failed: ${r.stderr || r.stdout || "no output"}.`,
57
+ });
58
+ };
43
59
  return {
44
60
  name: "launchd",
45
- install(task) {
61
+ install(task, opts) {
46
62
  // Capture PATH at install time so launchd (which strips the environment
47
63
  // aggressively) can find the same binaries the user sees interactively.
48
- let pathEnv;
49
- if (options.envPath === false) {
50
- pathEnv = undefined;
51
- }
52
- else if (typeof options.envPath === "string") {
53
- pathEnv = options.envPath;
54
- }
55
- else {
56
- pathEnv = process.env.PATH ?? "";
64
+ const xml = buildPlistXml(task, [...(opts?.binding ?? akmArgv)], logDir, opts?.contextPath ?? defaultContextPath, opts?.target);
65
+ const file = plistPath(task.id);
66
+ const previousPlist = fsLike.exists(file) ? fsLike.readFile(file) : undefined;
67
+ let previousEnabled = true;
68
+ if (previousPlist !== undefined) {
69
+ const disabledLabels = readDisabledLabels(exec);
70
+ if (disabledLabels === undefined) {
71
+ throw new ConfigError(`launchctl print-disabled failed; cannot safely replace existing task "${task.id}".`, "INVALID_CONFIG_FILE");
72
+ }
73
+ previousEnabled = !disabledLabels.has(label(task.id));
57
74
  }
58
- const xml = buildPlistXml(task, akmArgv, logDir, pathEnv);
59
75
  fsLike.ensureDir(agentsDir);
60
76
  // launchd refuses to start a job when StandardOutPath/StandardErrorPath
61
77
  // points at a non-existent directory; create it before bootstrap.
62
78
  fsLike.ensureDir(logDir);
63
- fsLike.writeFile(plistPath(task.id), xml);
64
- const bootout = exec.run(["launchctl", "bootout", target(task.id)]);
65
- // bootout returning non-zero is fine — agent might not be loaded.
66
- void bootout;
67
- const bootstrap = exec.run(["launchctl", "bootstrap", `gui/${exec.uid()}`, plistPath(task.id)]);
68
- if (bootstrap.status !== 0) {
69
- throw new ConfigError(`launchctl bootstrap failed (exit ${bootstrap.status}): ${bootstrap.stderr || bootstrap.stdout || "no output"}.`, "INVALID_CONFIG_FILE", "Ensure `launchctl` is available; on macOS it is part of the base system.");
79
+ const tempFile = path.join(agentsDir, `.${task.id}.${Date.now()}.tmp`);
80
+ fsLike.writeFile(tempFile, xml);
81
+ let bootoutCompleted = false;
82
+ let previousWasLoaded = false;
83
+ let fileReplaced = false;
84
+ let enableStateTouched = false;
85
+ try {
86
+ const bootout = runOrThrow(exec, ["launchctl", "bootout", target(task.id)], {
87
+ isOk: (r) => r.status === 0 || isServiceNotFoundResult(r),
88
+ message: (r) => `launchctl bootout failed (exit ${r.status}): ${r.stderr || r.stdout || "no output"}.`,
89
+ });
90
+ bootoutCompleted = true;
91
+ previousWasLoaded = previousPlist !== undefined && bootout.status === 0;
92
+ fsLike.replaceFile(tempFile, file);
93
+ fileReplaced = true;
94
+ // A disable override survives bootout and plist replacement. Clear it
95
+ // before bootstrap, then apply the desired state after registration.
96
+ enableStateTouched = true;
97
+ setEnableState(task.id, true);
98
+ runOrThrow(exec, ["launchctl", "bootstrap", `gui/${exec.uid()}`, file], {
99
+ message: (r) => `launchctl bootstrap failed (exit ${r.status}): ${r.stderr || r.stdout || "no output"}.`,
100
+ hint: "Ensure `launchctl` is available; on macOS it is part of the base system.",
101
+ });
102
+ if (!task.enabled) {
103
+ setEnableState(task.id, false);
104
+ }
70
105
  }
71
- if (!task.enabled) {
72
- const disable = exec.run(["launchctl", "disable", target(task.id)]);
73
- if (disable.status !== 0) {
74
- throw new ConfigError(`launchctl disable failed: ${disable.stderr || disable.stdout || "no output"}.`, "INVALID_CONFIG_FILE");
106
+ catch (err) {
107
+ if (!bootoutCompleted)
108
+ throw err;
109
+ const rollbackErrors = [];
110
+ let priorFileRestored = !fileReplaced;
111
+ if (fileReplaced) {
112
+ let replacementUnloaded = false;
113
+ try {
114
+ const rollbackBootout = exec.run(["launchctl", "bootout", target(task.id)]);
115
+ replacementUnloaded = rollbackBootout.status === 0 || isServiceNotFoundResult(rollbackBootout);
116
+ if (!replacementUnloaded) {
117
+ rollbackErrors.push(new ConfigError(`launchctl bootout during rollback failed: ${rollbackBootout.stderr || rollbackBootout.stdout || "no output"}.`, "INVALID_CONFIG_FILE"));
118
+ }
119
+ }
120
+ catch (rollbackError) {
121
+ rollbackErrors.push(rollbackError);
122
+ }
123
+ if (replacementUnloaded) {
124
+ try {
125
+ if (previousPlist === undefined) {
126
+ if (fsLike.exists(file))
127
+ fsLike.removeFile(file);
128
+ }
129
+ else {
130
+ fsLike.writeFile(tempFile, previousPlist);
131
+ fsLike.replaceFile(tempFile, file);
132
+ }
133
+ priorFileRestored = true;
134
+ }
135
+ catch (rollbackError) {
136
+ rollbackErrors.push(rollbackError);
137
+ }
138
+ }
139
+ }
140
+ if (previousPlist !== undefined && previousWasLoaded && priorFileRestored) {
141
+ try {
142
+ setEnableState(task.id, true);
143
+ const restore = exec.run(["launchctl", "bootstrap", `gui/${exec.uid()}`, file]);
144
+ if (restore.status !== 0) {
145
+ rollbackErrors.push(new ConfigError(`launchctl bootstrap during rollback failed: ${restore.stderr || restore.stdout || "no output"}.`, "INVALID_CONFIG_FILE"));
146
+ }
147
+ }
148
+ catch (rollbackError) {
149
+ rollbackErrors.push(rollbackError);
150
+ }
151
+ if (!previousEnabled) {
152
+ try {
153
+ setEnableState(task.id, false);
154
+ }
155
+ catch (rollbackError) {
156
+ rollbackErrors.push(rollbackError);
157
+ }
158
+ }
159
+ }
160
+ else if (enableStateTouched) {
161
+ try {
162
+ setEnableState(task.id, previousPlist === undefined || previousEnabled);
163
+ }
164
+ catch (rollbackError) {
165
+ rollbackErrors.push(rollbackError);
166
+ }
75
167
  }
168
+ if (rollbackErrors.length > 0) {
169
+ const message = err instanceof Error ? err.message : String(err);
170
+ throw new AggregateError([err, ...rollbackErrors], `${message}; rollback for launchd task "${task.id}" was incomplete.`);
171
+ }
172
+ throw err;
173
+ }
174
+ finally {
175
+ if (fsLike.exists(tempFile))
176
+ fsLike.removeFile(tempFile);
76
177
  }
77
178
  },
78
179
  uninstall(id) {
79
- // Bootout first (may fail if agent never loaded — that's fine).
80
- exec.run(["launchctl", "bootout", target(id)]);
180
+ runOrThrow(exec, ["launchctl", "bootout", target(id)], {
181
+ isOk: (r) => r.status === 0 || isServiceNotFoundResult(r),
182
+ message: (r) => `launchctl bootout failed (exit ${r.status}): ${r.stderr || r.stdout || "no output"}.`,
183
+ });
184
+ // launchctl disable overrides persist after the plist is removed.
185
+ setEnableState(id, true);
81
186
  const file = plistPath(id);
82
187
  if (fsLike.exists(file))
83
188
  fsLike.removeFile(file);
84
189
  },
85
190
  setEnabled(id, enabled) {
86
- const verb = enabled ? "enable" : "disable";
87
- const r = exec.run(["launchctl", verb, target(id)]);
88
- if (r.status !== 0) {
89
- throw new ConfigError(`launchctl ${verb} failed: ${r.stderr || r.stdout || "no output"}.`, "INVALID_CONFIG_FILE");
90
- }
191
+ setEnableState(id, enabled);
91
192
  },
92
193
  list() {
93
194
  if (!fsLike.exists(agentsDir))
@@ -98,55 +199,185 @@ export function LAUNCHD_BACKEND(options = {}) {
98
199
  ids.push(file.slice(LAUNCHD_LABEL_PREFIX.length, -".plist".length));
99
200
  }
100
201
  }
101
- return ids.map((id) => ({ id }));
202
+ if (ids.length === 0)
203
+ return [];
204
+ const disabledLabels = readDisabledLabels(exec);
205
+ return ids
206
+ .map((id) => inspectInstalledLaunchdTask(id, fsLike.readFile(plistPath(id)), disabledLabels, exec))
207
+ .filter((ref) => ref !== undefined);
208
+ },
209
+ listForRebind() {
210
+ if (!fsLike.exists(agentsDir))
211
+ return [];
212
+ const refs = [];
213
+ for (const file of fsLike.list(agentsDir)) {
214
+ if (!file.startsWith(LAUNCHD_LABEL_PREFIX) || !file.endsWith(".plist"))
215
+ continue;
216
+ const id = file.slice(LAUNCHD_LABEL_PREFIX.length, -".plist".length);
217
+ const installed = extractPlistInvocation(fsLike.readFile(plistPath(id)));
218
+ refs.push({ id, ...(installed?.target !== undefined ? { target: installed.target } : {}) });
219
+ }
220
+ return refs;
221
+ },
222
+ expectedSignature(task, opts) {
223
+ return normalizeSignature(buildPlistXml(task, [...(opts?.binding ?? akmArgv)], logDir, opts?.contextPath ?? defaultContextPath, opts?.target));
102
224
  },
103
225
  };
104
226
  }
227
+ function inspectInstalledLaunchdTask(id, raw, disabledLabels, exec) {
228
+ const installed = extractPlistInvocation(raw);
229
+ // An invocation that no longer parses (e.g. a pre-0.9 `tasks run` entry
230
+ // surviving the scheduler-ABI respelling) is an orphan of its marker id,
231
+ // not a hard failure: `list()` omits it so `akmTasksSync` treats the id as
232
+ // "not present" and reinstalls it from the current task file.
233
+ if (!installed)
234
+ return undefined;
235
+ const metadata = {
236
+ ...(installed.target !== undefined ? { target: installed.target } : {}),
237
+ binding: installed.binding,
238
+ contextPath: installed.contextPath,
239
+ };
240
+ if (!disabledLabels)
241
+ return { id, ...metadata };
242
+ const jobLabel = `${LAUNCHD_LABEL_PREFIX}${id}`;
243
+ try {
244
+ const loaded = exec.run(["launchctl", "print", `gui/${exec.uid()}/${jobLabel}`]);
245
+ if (loaded.status !== 0)
246
+ return { id, ...metadata };
247
+ }
248
+ catch {
249
+ return { id, ...metadata };
250
+ }
251
+ try {
252
+ const xml = raw.replace(/<!-- akm-enabled:(?:true|false) -->/, `<!-- akm-enabled:${!disabledLabels.has(jobLabel)} -->`);
253
+ return {
254
+ id,
255
+ signature: normalizeSignature(xml),
256
+ ...metadata,
257
+ };
258
+ }
259
+ catch {
260
+ return { id, ...metadata };
261
+ }
262
+ }
263
+ /**
264
+ * Recover the bundle name embedded as a `--bundle <bundle>` pair in a plist's
265
+ * `<ProgramArguments>`. Returns undefined for the primary/default form.
266
+ */
267
+ export function extractPlistTarget(xml) {
268
+ return extractPlistInvocation(xml)?.target;
269
+ }
270
+ export function extractPlistInvocation(xml) {
271
+ const block = xml.match(/<key>ProgramArguments<\/key>\s*<array>([\s\S]*?)<\/array>/);
272
+ if (!block)
273
+ return undefined;
274
+ const args = [...block[1].matchAll(/<string>([\s\S]*?)<\/string>/g)].map((m) => decodeXmlEntities(m[1]));
275
+ return parseScheduledTaskArgv(args);
276
+ }
277
+ function decodeXmlEntities(value) {
278
+ return value
279
+ .replaceAll("&lt;", "<")
280
+ .replaceAll("&gt;", ">")
281
+ .replaceAll("&quot;", '"')
282
+ .replaceAll("&apos;", "'")
283
+ .replaceAll("&amp;", "&");
284
+ }
105
285
  // ── XML builder (exported for tests) ────────────────────────────────────────
106
- export function buildPlistXml(task, akmArgv, logDir, pathEnv) {
286
+ export function buildPlistXml(task, akmArgv, logDir, contextPath, target) {
107
287
  const spec = parseSchedule(task.schedule, "launchd");
108
288
  const trigger = translateToLaunchd(spec);
109
- const argv = [...akmArgv, "tasks", "run", task.id];
289
+ const invocation = buildScheduledTaskInvocation(akmArgv, task.id, contextPath, target);
290
+ const argv = invocation.argv;
110
291
  const programArgs = argv.map((a) => ` <string>${escapeXml(a)}</string>`).join("\n");
111
292
  const logPath = path.join(logDir, `${task.id}.log`);
112
293
  const triggerXml = renderLaunchdTrigger(trigger);
113
- const envVarsXml = pathEnv !== undefined
114
- ? ` <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>${escapeXml(pathEnv)}</string>\n </dict>\n`
115
- : "";
116
- return launchdTemplate
294
+ const xml = launchdTemplate
295
+ .replace("<dict>\n", `<dict>\n <!-- akm-enabled:${task.enabled} -->\n`)
117
296
  .replace("{{LABEL}}", LAUNCHD_LABEL_PREFIX + escapeXml(task.id))
118
297
  .replace("{{PROGRAM_ARGS}}", programArgs)
119
298
  .replaceAll("{{LOG_PATH}}", escapeXml(logPath))
120
- .replace("{{ENV_VARS}}", envVarsXml)
299
+ .replace("{{ENV_VARS}}", "")
121
300
  .replace("{{TRIGGER_XML}}", triggerXml);
301
+ for (const char of xml) {
302
+ const code = char.codePointAt(0) ?? 0;
303
+ if (code <= 0x08 || code === 0x0b || code === 0x0c || (code >= 0x0e && code <= 0x1f)) {
304
+ throw new ConfigError("Launchd plist values must not contain XML-forbidden control characters.", "INVALID_CONFIG_FILE");
305
+ }
306
+ }
307
+ return xml;
122
308
  }
123
309
  function renderLaunchdTrigger(trigger) {
124
- if (trigger.intervalSeconds !== undefined) {
125
- return ` <key>StartInterval</key>
126
- <integer>${trigger.intervalSeconds}</integer>`;
310
+ if (trigger.calendars !== undefined) {
311
+ const lines = [" <key>StartCalendarInterval</key>", " <array>"];
312
+ for (const calendar of trigger.calendars) {
313
+ lines.push(...renderCalendar(calendar, " "));
314
+ }
315
+ lines.push(" </array>");
316
+ return lines.join("\n");
127
317
  }
128
318
  const cal = trigger.calendar ?? {};
129
- const lines = [" <key>StartCalendarInterval</key>", " <dict>"];
130
- if (cal.Minute !== undefined)
131
- lines.push(` <key>Minute</key><integer>${cal.Minute}</integer>`);
132
- if (cal.Hour !== undefined)
133
- lines.push(` <key>Hour</key><integer>${cal.Hour}</integer>`);
134
- if (cal.Day !== undefined)
135
- lines.push(` <key>Day</key><integer>${cal.Day}</integer>`);
136
- if (cal.Month !== undefined)
137
- lines.push(` <key>Month</key><integer>${cal.Month}</integer>`);
138
- if (cal.Weekday !== undefined)
139
- lines.push(` <key>Weekday</key><integer>${cal.Weekday}</integer>`);
140
- lines.push(" </dict>");
319
+ const lines = [" <key>StartCalendarInterval</key>", ...renderCalendar(cal, " ")];
141
320
  return lines.join("\n");
142
321
  }
322
+ function renderCalendar(calendar, indent) {
323
+ const valueIndent = `${indent} `;
324
+ const lines = [`${indent}<dict>`];
325
+ if (calendar.Minute !== undefined) {
326
+ lines.push(`${valueIndent}<key>Minute</key><integer>${calendar.Minute}</integer>`);
327
+ }
328
+ if (calendar.Hour !== undefined)
329
+ lines.push(`${valueIndent}<key>Hour</key><integer>${calendar.Hour}</integer>`);
330
+ if (calendar.Day !== undefined)
331
+ lines.push(`${valueIndent}<key>Day</key><integer>${calendar.Day}</integer>`);
332
+ if (calendar.Month !== undefined)
333
+ lines.push(`${valueIndent}<key>Month</key><integer>${calendar.Month}</integer>`);
334
+ if (calendar.Weekday !== undefined) {
335
+ lines.push(`${valueIndent}<key>Weekday</key><integer>${calendar.Weekday}</integer>`);
336
+ }
337
+ lines.push(`${indent}</dict>`);
338
+ return lines;
339
+ }
340
+ function normalizeSignature(xml) {
341
+ return xml.replace(/\r\n/g, "\n").trim();
342
+ }
343
+ function readDisabledLabels(exec) {
344
+ try {
345
+ const result = exec.run(["launchctl", "print-disabled", `gui/${exec.uid()}`]);
346
+ if (result.status !== 0)
347
+ return undefined;
348
+ return parseDisabledLabels(result.stdout);
349
+ }
350
+ catch {
351
+ return undefined;
352
+ }
353
+ }
354
+ function parseDisabledLabels(output) {
355
+ const envelope = /^\s*disabled services\s*=\s*\{([\s\S]*)\}\s*$/.exec(output);
356
+ if (!envelope)
357
+ return undefined;
358
+ const disabled = new Set();
359
+ let body = envelope[1];
360
+ while (body.trim()) {
361
+ const entry = /^\s*"([^"\r\n]+)"\s*=>\s*(true|false|enabled|disabled)\s*/.exec(body);
362
+ if (!entry)
363
+ return undefined;
364
+ if (entry[2] === "true" || entry[2] === "disabled")
365
+ disabled.add(entry[1]);
366
+ body = body.slice(entry[0].length);
367
+ }
368
+ return disabled;
369
+ }
370
+ function isServiceNotFoundResult(result) {
371
+ const output = `${result.stderr ?? ""}\n${result.stdout ?? ""}`;
372
+ return /could not find service\b|service\b.*\bnot found\b|\bno such process\b/i.test(output);
373
+ }
143
374
  function defaultAgentsDir() {
144
375
  // launchd's per-user LaunchAgents live under the user's home directory.
145
376
  // If we can't determine HOME, refuse rather than silently producing a
146
377
  // relative path that would write somewhere unexpected.
147
378
  const home = os.homedir();
148
379
  if (!home) {
149
- throw new ConfigError("Cannot determine user home directory; launchd backend requires HOME to locate ~/Library/LaunchAgents.", "INVALID_CONFIG_FILE", "Set $HOME (POSIX) or the equivalent before running `akm tasks` on macOS.");
380
+ throw new ConfigError("Cannot determine user home directory; launchd backend requires HOME to locate ~/Library/LaunchAgents.", "INVALID_CONFIG_FILE", "Set $HOME (POSIX) or the equivalent before running `akm task` on macOS.");
150
381
  }
151
382
  return path.join(home, "Library", "LaunchAgents");
152
383
  }
@@ -162,9 +393,15 @@ function defaultLaunchdExec() {
162
393
  function defaultLaunchdFs() {
163
394
  return {
164
395
  ...nodeFs(),
396
+ readFile(file) {
397
+ return fs.readFileSync(file, "utf8");
398
+ },
165
399
  removeFile(file) {
166
400
  fs.rmSync(file, { force: true });
167
401
  },
402
+ replaceFile(source, destination) {
403
+ fs.renameSync(source, destination);
404
+ },
168
405
  list(dir) {
169
406
  try {
170
407
  return fs.readdirSync(dir);