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
@@ -18,35 +18,9 @@ import fs from "node:fs";
18
18
  import os from "node:os";
19
19
  import path from "node:path";
20
20
  import { parseEmbeddedJsonResponse } from "../../core/parse.js";
21
- import { spawn as runtimeSpawn } from "../../runtime.js";
21
+ import { runManagedSubprocess, } from "../../core/subprocess.js";
22
22
  import { getCommandBuilder } from "./builders.js";
23
23
  import { DEFAULT_AGENT_TIMEOUT_MS } from "./config.js";
24
- /**
25
- * Kill the process group of `proc` with `signal`, falling back to
26
- * `proc.kill(signal)` when `proc.pid` is unavailable (e.g. test fakes).
27
- *
28
- * Passing a negative PID to `process.kill` targets the entire process
29
- * group, so opencode's child processes (the .opencode binary, etc.) are
30
- * reaped alongside the node wrapper. The fallback keeps test fakes working
31
- * without modification.
32
- */
33
- function killGroup(proc, signal) {
34
- if (typeof proc.pid === "number") {
35
- try {
36
- process.kill(-proc.pid, signal);
37
- return;
38
- }
39
- catch {
40
- // Process may have already exited; fall through to direct kill.
41
- }
42
- }
43
- try {
44
- proc.kill(signal);
45
- }
46
- catch {
47
- /* ignore */
48
- }
49
- }
50
24
  const DEFAULT_TIMEOUT_MS = DEFAULT_AGENT_TIMEOUT_MS;
51
25
  /**
52
26
  * Supplement `existingPath` with well-known user binary directories when
@@ -102,14 +76,6 @@ function pathCandidatesForCurrentPlatform(home) {
102
76
  "/usr/local/bin",
103
77
  ];
104
78
  }
105
- function resolveSpawnFn(options) {
106
- if (options.spawn)
107
- return options.spawn;
108
- // Default to the runtime-boundary spawn, which delegates to the native
109
- // subprocess API on each runtime. Tests inject `options.spawn` to avoid
110
- // poking real binaries.
111
- return runtimeSpawn;
112
- }
113
79
  /**
114
80
  * Build the child env. Starts empty and copies through:
115
81
  * • Every name in `profile.envPassthrough`.
@@ -143,21 +109,19 @@ function buildChildEnv(profile, options) {
143
109
  }
144
110
  return env;
145
111
  }
146
- async function readStream(stream, opts) {
147
- if (!stream)
148
- return "";
149
- const readPromise = new Response(stream).text().catch(() => "");
150
- if (!opts?.timeoutMs)
151
- return readPromise;
152
- // Race the stream read against a timeout so a process that is killed via
153
- // SIGTERM/SIGKILL but whose pipe endpoints stay open (e.g. background
154
- // threads still holding the fd) cannot block the caller indefinitely.
155
- // On timeout we return whatever we received so far (empty string here since
156
- // `readPromise` is all-or-nothing with `Response.text()`).
157
- const timeoutPromise = new Promise((resolve) => {
158
- setTimeout(() => resolve(""), opts.timeoutMs);
159
- });
160
- return Promise.race([readPromise, timeoutPromise]);
112
+ function streamFailureMessage(profileName, stdout, stderr) {
113
+ const failures = [];
114
+ if (stdout.error)
115
+ failures.push(`stdout read failed: ${stdout.error instanceof Error ? stdout.error.message : String(stdout.error)}`);
116
+ if (stderr.error)
117
+ failures.push(`stderr read failed: ${stderr.error instanceof Error ? stderr.error.message : String(stderr.error)}`);
118
+ if (stdout.timedOut)
119
+ failures.push("stdout drain timed out");
120
+ if (stderr.timedOut)
121
+ failures.push("stderr drain timed out");
122
+ if (failures.length === 0)
123
+ return undefined;
124
+ return `agent CLI "${profileName}" output capture failed: ${failures.join("; ")}`;
161
125
  }
162
126
  /**
163
127
  * Spawn the agent CLI described by `profile` with `prompt` (forwarded as
@@ -179,26 +143,37 @@ async function readStream(stream, opts) {
179
143
  */
180
144
  export async function runAgent(profile, prompt, options = {}) {
181
145
  const stdioMode = options.stdio ?? profile.stdio;
182
- // null = explicitly disabled (no kill timer). undefined = inherit from profile/default.
183
- const timeoutMs = options.timeoutMs !== undefined ? options.timeoutMs : (profile.timeoutMs ?? DEFAULT_TIMEOUT_MS);
146
+ // null = explicitly disabled (no kill timer). undefined = runtime default.
147
+ const timeoutMs = options.timeoutMs !== undefined ? options.timeoutMs : DEFAULT_TIMEOUT_MS;
184
148
  const parseOutput = options.parseOutput ?? profile.parseOutput;
185
149
  const setTimeoutImpl = options.setTimeoutFn ?? setTimeout;
186
150
  const clearTimeoutImpl = options.clearTimeoutFn ?? clearTimeout;
151
+ // Observability seam — ids/status only, best-effort (see RunAgentOptions.onEvent).
152
+ const emitSpawnEvent = (type, data) => {
153
+ if (!options.onEvent)
154
+ return;
155
+ try {
156
+ options.onEvent({ type, data });
157
+ }
158
+ catch {
159
+ // Observability must never break the dispatch.
160
+ }
161
+ };
187
162
  // Build argv via the platform-specific builder when dispatch params are
188
- // provided; fall back to the legacy positional-prompt form otherwise.
163
+ // provided; otherwise use the direct positional-prompt form.
189
164
  let builtArgv;
190
165
  let builtEnv;
191
166
  if (options.dispatch !== undefined) {
192
- const builder = getCommandBuilder(profile.commandBuilder ?? profile.name, options.builderRegistry);
167
+ const builder = getCommandBuilder(profile.platform ?? profile.name, options.builderRegistry);
193
168
  const built = builder.build(profile, options.dispatch);
194
169
  builtArgv = built.argv;
195
170
  builtEnv = built.env;
196
171
  }
197
172
  else {
198
- const legacyArgs = [...profile.args, ...(options.args ?? [])];
173
+ const positionalArgs = [...profile.args, ...(options.args ?? [])];
199
174
  if (prompt !== undefined)
200
- legacyArgs.push(prompt);
201
- builtArgv = [profile.bin, ...legacyArgs];
175
+ positionalArgs.push(prompt);
176
+ builtArgv = [profile.bin, ...positionalArgs];
202
177
  }
203
178
  // Extra args (e.g. forwarded CLI positionals) are appended after the builder output.
204
179
  const finalArgv = [...builtArgv, ...(options.dispatch ? (options.args ?? []) : [])];
@@ -217,141 +192,43 @@ export async function runAgent(profile, prompt, options = {}) {
217
192
  error: `agent CLI "${profile.name}" not started: caller signal already aborted`,
218
193
  };
219
194
  }
220
- let proc;
221
- try {
222
- const spawnFn = resolveSpawnFn(options);
223
- proc = spawnFn(finalArgv, {
224
- stdin: stdioMode === "captured" ? (options.stdin !== undefined ? "pipe" : "ignore") : "inherit",
225
- stdout: stdioMode === "captured" ? "pipe" : "inherit",
226
- stderr: stdioMode === "captured" ? "pipe" : "inherit",
227
- env,
228
- // options.cwd wins; dispatch.cwd is the request-level fallback (it was
229
- // declared on AgentDispatchRequest but consumed by nothing — P0.5 fix).
230
- ...((options.cwd ?? options.dispatch?.cwd) ? { cwd: options.cwd ?? options.dispatch?.cwd } : {}),
231
- // Spawn in its own process group so killGroup(-pid, signal) reaches all
232
- // descendants (e.g. the .opencode binary that opencode's node wrapper forks).
233
- // Only applied in captured mode — interactive mode inherits the parent
234
- // terminal's process group intentionally.
235
- ...(stdioMode === "captured" ? { detached: true } : {}),
236
- });
237
- }
238
- catch (err) {
239
- const durationMs = Date.now() - start;
240
- return {
241
- ok: false,
242
- exitCode: null,
243
- stdout: "",
244
- stderr: "",
245
- durationMs,
246
- reason: "spawn_failed",
247
- error: err instanceof Error ? err.message : String(err),
248
- };
249
- }
250
- // Hard timeout. We prefer SIGTERM, then SIGKILL if SIGTERM is ignored,
251
- // but the subprocess only exposes a single .kill() — one signal is enough
252
- // for the structured-failure contract.
195
+ // Spawn/timeout/abort/capture are owned by the managed-subprocess primitive
196
+ // (src/core/subprocess.ts): process-GROUP spawn (detached in captured mode),
197
+ // the SIGTERM→SIGKILL kill ladder on timeout/abort, bounded output capture,
198
+ // and the optional stdin payload. runAgent keeps its agent-specific surface —
199
+ // the onEvent observability seam, the failure taxonomy, and JSON parsing.
253
200
  //
254
- // BUG-M3: only flag `timedOut` when the child has not already exited. A
255
- // timer firing in the same microtask as `proc.exited` resolving could
256
- // otherwise label a clean exit as a timeout.
257
- //
258
- // When timeoutMs is null the kill timer is skipped entirely — the task runs
259
- // until the process exits naturally. Intended for long-running local-model
260
- // tasks where wall-clock time is unpredictable.
261
- let timedOut = false;
262
- let timer;
263
- if (timeoutMs !== null) {
264
- timer = setTimeoutImpl(() => {
265
- if (!proc || proc.exitCode !== null)
266
- return;
267
- timedOut = true;
268
- killGroup(proc, "SIGTERM");
269
- // Follow up with SIGKILL after 5 s in case the process ignores SIGTERM.
270
- setTimeoutImpl(() => {
271
- if (!proc || proc.exitCode !== null)
272
- return;
273
- killGroup(proc, "SIGKILL");
274
- }, 5000);
275
- }, timeoutMs);
276
- }
277
- // Cooperative cancel: same SIGTERM→SIGKILL discipline as the timeout, but
278
- // flagged separately so the result carries `reason: "aborted"`.
279
- let aborted = false;
280
- const abortSignal = options.signal;
281
- const onAbort = () => {
282
- if (!proc || proc.exitCode !== null)
283
- return;
284
- aborted = true;
285
- killGroup(proc, "SIGTERM");
286
- const sigkillTimer = setTimeoutImpl(() => {
287
- if (!proc || proc.exitCode !== null)
288
- return;
289
- killGroup(proc, "SIGKILL");
290
- }, 5000);
291
- if (typeof sigkillTimer !== "number")
292
- sigkillTimer.unref?.();
293
- };
294
- if (abortSignal) {
295
- // A signal that aborted between the pre-spawn check and here is handled
296
- // by calling the listener directly.
297
- if (abortSignal.aborted)
298
- onAbort();
299
- else
300
- abortSignal.addEventListener("abort", onAbort, { once: true });
301
- }
302
- // Stream-drain timeout: the overall wall-clock budget plus a 2 s grace
303
- // period. When a process is killed via SIGTERM/SIGKILL (from our timeout
304
- // handler or from outside) some runtimes keep the pipe write-end open in
305
- // background threads, which would cause `Response.text()` to block forever.
306
- // Capping stream draining ensures the caller never hangs past the wall
307
- // budget regardless of subprocess pipe behaviour.
308
- // When there is no kill timer, allow up to 30 s for streams to drain.
309
- const streamDrainTimeoutMs = timeoutMs !== null ? timeoutMs + 2_000 : 30_000;
310
- const stdoutPromise = stdioMode === "captured"
311
- ? readStream(proc.stdout ?? null, { timeoutMs: streamDrainTimeoutMs })
312
- : Promise.resolve("");
313
- const stderrPromise = stdioMode === "captured"
314
- ? readStream(proc.stderr ?? null, { timeoutMs: streamDrainTimeoutMs })
315
- : Promise.resolve("");
316
- // Optional stdin payload (captured mode only).
317
- //
318
- // BUG-H1: race the stdin write/close against `proc.exited` and the
319
- // timeout timer. If the child never drains stdin, an unraced
320
- // `await writer.write()` would block forever and prevent `runAgent`
321
- // from ever returning.
322
- if (options.stdin !== undefined && stdioMode === "captured" && proc.stdin) {
323
- const stdinPayload = options.stdin;
324
- const stdinStream = proc.stdin;
325
- const stdinDone = (async () => {
326
- try {
327
- const writer = stdinStream.getWriter();
328
- const bytes = new TextEncoder().encode(stdinPayload);
329
- await writer.write(bytes);
330
- await writer.close();
331
- }
332
- catch {
333
- // Best-effort: ignore stdin write failures, the child will get EOF.
334
- }
335
- })();
336
- // Resolve as soon as either the write completes or the child exits.
337
- // We don't await the result — only that one of the two has settled —
338
- // so a stuck writer cannot keep us pinned past the timeout.
339
- await Promise.race([stdinDone, proc.exited.catch(() => undefined)]);
340
- }
341
- let exitCode = null;
342
- try {
343
- exitCode = await proc.exited;
344
- }
345
- catch (err) {
346
- if (timer !== undefined)
347
- clearTimeoutImpl(timer);
348
- abortSignal?.removeEventListener("abort", onAbort);
349
- // BUG-H2: drain stream readers before the early return so they don't
350
- // surface as unhandled rejections after the function resolves.
351
- // The streams already carry a built-in drain timeout so this allSettled
352
- // will not block indefinitely.
353
- await Promise.allSettled([stdoutPromise, stderrPromise]);
354
- const durationMs = Date.now() - start;
201
+ // `onSpawn` fires spawn_start once the child is live (never for a pre-spawn
202
+ // abort or a synchronous spawn failure), and captures the proc so spawn_exit
203
+ // can carry the same pid.
204
+ let spawnedProc;
205
+ const result = await runManagedSubprocess(finalArgv, {
206
+ capture: stdioMode === "captured",
207
+ env,
208
+ ...(options.cwd ? { cwd: options.cwd } : {}),
209
+ ...(options.stdin !== undefined ? { stdin: options.stdin } : {}),
210
+ timeoutMs,
211
+ ...(options.signal ? { signal: options.signal } : {}),
212
+ ...(options.spawn ? { spawnFn: options.spawn } : {}),
213
+ setTimeoutFn: setTimeoutImpl,
214
+ clearTimeoutFn: clearTimeoutImpl,
215
+ onSpawn: (proc) => {
216
+ spawnedProc = proc;
217
+ emitSpawnEvent("spawn_start", {
218
+ profile: profile.name,
219
+ ...(typeof proc.pid === "number" ? { pid: proc.pid } : {}),
220
+ });
221
+ },
222
+ });
223
+ const pidField = spawnedProc && typeof spawnedProc.pid === "number" ? { pid: spawnedProc.pid } : {};
224
+ const durationMs = Date.now() - start;
225
+ // Spawn/exit failure. A synchronous spawn throw never reached a live child
226
+ // (no spawn_start fired, so no spawn_exit either); a rejected proc.exited did
227
+ // (spawn_start already fired, so it emits a spawn_exit with status spawn_failed).
228
+ if (result.spawnError) {
229
+ if (spawnedProc) {
230
+ emitSpawnEvent("spawn_exit", { profile: profile.name, ...pidField, exitCode: null, status: "spawn_failed" });
231
+ }
355
232
  return {
356
233
  ok: false,
357
234
  exitCode: null,
@@ -359,13 +236,16 @@ export async function runAgent(profile, prompt, options = {}) {
359
236
  stderr: "",
360
237
  durationMs,
361
238
  reason: "spawn_failed",
362
- error: err instanceof Error ? err.message : String(err),
239
+ error: result.spawnError.message,
363
240
  };
364
241
  }
365
- clearTimeoutImpl(timer);
366
- abortSignal?.removeEventListener("abort", onAbort);
367
- const [stdout, stderr] = await Promise.all([stdoutPromise, stderrPromise]);
368
- const durationMs = Date.now() - start;
242
+ const { exitCode, timedOut, aborted, stdout, stderr } = result;
243
+ emitSpawnEvent("spawn_exit", {
244
+ profile: profile.name,
245
+ ...pidField,
246
+ exitCode,
247
+ status: aborted ? "aborted" : timedOut ? "timeout" : exitCode !== 0 ? "non_zero_exit" : "ok",
248
+ });
369
249
  if (aborted) {
370
250
  return {
371
251
  ok: false,
@@ -388,6 +268,18 @@ export async function runAgent(profile, prompt, options = {}) {
388
268
  error: `agent CLI "${profile.name}" timed out after ${timeoutMs ?? 0}ms`,
389
269
  };
390
270
  }
271
+ const captureFailure = streamFailureMessage(profile.name, result.stdoutRead, result.stderrRead);
272
+ if (captureFailure) {
273
+ return {
274
+ ok: false,
275
+ exitCode,
276
+ stdout,
277
+ stderr,
278
+ durationMs,
279
+ reason: "spawn_failed",
280
+ error: captureFailure,
281
+ };
282
+ }
391
283
  if (exitCode !== 0) {
392
284
  return {
393
285
  ok: false,
@@ -0,0 +1,114 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * Aider CLI agent command builder (P2, plan §"The adapter contract" step 2 /
6
+ * §"Capability matrix").
7
+ *
8
+ * Translates a platform-agnostic {@link AgentDispatchRequest} into the exact
9
+ * headless argv the `aider` CLI expects. Per the capability matrix the
10
+ * headless invocation is:
11
+ *
12
+ * aider -m "<p>" --yes-always
13
+ *
14
+ * with `--model <m>` for model selection, NO structured-output mode (Aider is
15
+ * the "none" tier — prompt-injected schema + embedded-JSON extraction), and
16
+ * NO session flag (resume is chat-history files, not an id).
17
+ *
18
+ * Platform-specific mapping decisions (all localized here, per the adapter
19
+ * contract):
20
+ *
21
+ * - **prompt** — `--message` is Aider's one-shot non-interactive mode (the
22
+ * matrix's `-m`; the long form is used for self-documenting argv). Unlike
23
+ * claude/codex/pi there is NO positional prompt and NO `--` end-of-options
24
+ * separator to hide behind: the prompt is a *flag value*. The glued
25
+ * `--message=<payload>` form is therefore used so a payload that begins
26
+ * with `-`/`--` binds to the flag lexically and can never be parsed as a
27
+ * separate option by Aider's argument parser.
28
+ * - **--yes-always** — always emitted: auto-confirms every interactive
29
+ * prompt (create file? run command? …), which is what makes a captured,
30
+ * unattended run possible. This is the matrix's documented headless shape.
31
+ * - **--no-pretty** — always emitted: disables colored/pretty terminal
32
+ * rendering so captured stdout is clean text for `./result-extractor.ts`
33
+ * (the same "dispatch is the captured path" reasoning as the Claude
34
+ * builder's unconditional `--print` and Codex's unconditional `--json`).
35
+ * - **systemPrompt** — Aider has no system-prompt flag (its nearest concept
36
+ * is conventions files via `--read`, which take a path, not text). Folded
37
+ * into the message payload — system text first, blank line, then the task —
38
+ * mirroring the codex builder's treatment.
39
+ * - **schema** — the matrix places Aider in the "via prompt+validate" tier
40
+ * with *no* structured output mode at all (plan §"Structured-output
41
+ * normalization", tier "none"): there is no schema flag and no JSON output
42
+ * flag, so the JSON Schema is injected into the message payload using the
43
+ * exact directive wording of the engine's prompt assembly
44
+ * (`step-work.ts` `buildUnitPrompt`) and the pi builder, so all
45
+ * dispatch paths speak one dialect. Downstream, embedded-JSON extraction +
46
+ * the engine's shared retry-until-valid loop supply the validation Aider
47
+ * lacks. No temp schema file is written — that is Codex's native-schema
48
+ * mechanism (`--output-schema`), which Aider does not have.
49
+ * - **tools** — deliberately unconsumed. Aider has no per-tool allowlist
50
+ * flag; tool-ish behaviour is governed by its own switches (`--yes-always`,
51
+ * git integration, shell-command confirmation). A restrictive policy is
52
+ * therefore dropped rather than approximated — never silently widened.
53
+ * - **resume/session** — NOT expressible: Aider persists context in
54
+ * chat-history files (`.aider.chat.history.md`), not session ids, so there
55
+ * is no flag-shaped resume to describe and the extractor
56
+ * never yields a `sessionId`. akm's `workflow_run_units` remains the
57
+ * durable source of truth; resume works even against a harness with no
58
+ * session model (plan §"Session, MCP, and identity across harnesses" —
59
+ * Aider is the plan's named example).
60
+ * - **effort** — stays unconsumed (reserved; the shared request contract's
61
+ * "no builder consumes it yet" note stays true).
62
+ *
63
+ * Registered: `aiderBuilder` is `AiderHarness.agentBuilder` (`./index.ts`),
64
+ * one of the ten harnesses `HARNESS_REGISTRY` constructs
65
+ * (`harnesses/index.ts`); `agent/builders.ts` derives `BUILTIN_BUILDERS` from
66
+ * that registry, so this builder is reachable under the `"aider"` platform
67
+ * name without any further wiring. The registry entry also declares
68
+ * `structuredOutput: "none"` alongside it (`./index.ts`).
69
+ */
70
+ import { assertNotFlag, resolveDispatchModel, } from "../../agent/builder-shared.js";
71
+ /** Canonical harness/platform id used for model-alias resolution. */
72
+ export const AIDER_PLATFORM = "aider";
73
+ /**
74
+ * Assemble the `--message` payload: optional system text, the task prompt,
75
+ * and — when a schema is requested — the same schema directive the workflow
76
+ * engine's prompt assembly uses (Aider has no native structured output, so
77
+ * the prompt is the only channel; plan §"Structured-output normalization",
78
+ * tier "none").
79
+ */
80
+ function buildMessagePayload(req) {
81
+ const sections = [];
82
+ if (req.systemPrompt)
83
+ sections.push(req.systemPrompt);
84
+ sections.push(req.prompt);
85
+ if (req.schema) {
86
+ sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):\n${JSON.stringify(req.schema)}`);
87
+ }
88
+ return sections.join("\n\n");
89
+ }
90
+ /**
91
+ * Aider builder.
92
+ * Command shape:
93
+ * aider [--model <m>] --yes-always --no-pretty --message=<[system\n\n]prompt[\n\nschema directive]>
94
+ */
95
+ export const aiderBuilder = {
96
+ platform: AIDER_PLATFORM,
97
+ build(profile, req) {
98
+ assertNotFlag(req.systemPrompt, "systemPrompt");
99
+ assertNotFlag(req.model, "model");
100
+ const args = [...profile.args];
101
+ if (req.model) {
102
+ const resolved = resolveDispatchModel(req, profile, AIDER_PLATFORM);
103
+ args.push("--model", resolved);
104
+ }
105
+ // Headless essentials (matrix shape): auto-confirm everything, and keep
106
+ // captured stdout free of pretty/ANSI rendering for the extractor.
107
+ args.push("--yes-always");
108
+ args.push("--no-pretty");
109
+ // Glued form: the payload is a flag VALUE (no positional prompt exists),
110
+ // so `=` binding keeps a dash-leading payload from parsing as an option.
111
+ args.push(`--message=${buildMessagePayload(req)}`);
112
+ return { argv: [profile.bin, ...args] };
113
+ },
114
+ };
@@ -0,0 +1,48 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * Aider CLI harness (P2 integration, plan §"The adapter contract").
6
+ *
7
+ * Per-harness barrel gathering the Aider integration surfaces:
8
+ * - agent command builder → ./agent-builder.ts (aiderBuilder)
9
+ * - result extractor → ./result-extractor.ts (aiderResultExtractor)
10
+ *
11
+ * It also defines {@link AiderHarness}, the {@link AkmHarness} descriptor that
12
+ * `HARNESS_REGISTRY` registers. Dispatch-only: no native session-log reader or
13
+ * config importer yet.
14
+ */
15
+ import { caps } from "../shared.js";
16
+ import { BaseHarness } from "../types.js";
17
+ import { aiderBuilder } from "./agent-builder.js";
18
+ import { aiderResultExtractor } from "./result-extractor.js";
19
+ export { AIDER_PLATFORM, aiderBuilder } from "./agent-builder.js";
20
+ export { aiderResultExtractor } from "./result-extractor.js";
21
+ /**
22
+ * Aider.
23
+ *
24
+ * Canonical id is `'aider'`; no alias or distinct runtime identity.
25
+ */
26
+ export class AiderHarness extends BaseHarness {
27
+ id = "aider";
28
+ displayName = "Aider";
29
+ aliases = [];
30
+ agentBuilder = aiderBuilder;
31
+ resultExtractor = aiderResultExtractor;
32
+ // ── Workflow-engine descriptor (plan §"Capability matrix", P2) ────────────
33
+ // akm spawns the `aider` CLI locally per unit ⇒ local-runner.
34
+ pattern = "local-runner";
35
+ // No structured-output mode at all (the matrix's "none — parse output"):
36
+ // akm injects the schema into the prompt and extracts embedded JSON.
37
+ structuredOutput = "none";
38
+ // No flag-shaped resume: Aider persists context in chat-history files
39
+ // (`.aider.chat.history.md`), not session ids — the plan's named example of
40
+ // a harness with no session model. akm's `workflow_run_units` remains the
41
+ // durable resume source of truth.
42
+ // No `identityEnv`: the matrix lists Aider's identity markers as uncertain,
43
+ // and Aider stamps no session var onto child processes.
44
+ capabilities = caps({
45
+ agentDispatch: true,
46
+ detection: true,
47
+ });
48
+ }
@@ -0,0 +1,53 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * ANSI escape sequences (CSI color/cursor codes). Defensive only: the builder
6
+ * always passes `--no-pretty`, but a user profile may override that.
7
+ * Constructed from a char code so no literal control character appears in
8
+ * source (lint-friendly, same bytes).
9
+ */
10
+ const ANSI_ESCAPE_RE = new RegExp(`${String.fromCharCode(27)}\\[[0-9;?]*[ -/]*[@-~]`, "g");
11
+ /**
12
+ * Aider's own announcement lines — banner, model/repo configuration echo,
13
+ * chat-history notices, edit/commit/usage reports. All patterns are anchored
14
+ * at line start and match documented phrasings only; anything else is treated
15
+ * as reply content.
16
+ */
17
+ const NOISE_LINE_PATTERNS = [
18
+ /^aider v\d/, // version banner
19
+ /^(Main model|Weak model|Editor model|Model):\s/, // model announcements
20
+ /^Git repo:\s/, // repo detection
21
+ /^Repo-map:\s/, // repo-map status
22
+ /^Added .+ to the chat\.?$/, // file add notices
23
+ /^Restored previous conversation history\.?$/, // chat-history reload notice
24
+ /^Use \/help\b/, // onboarding hint line
25
+ /^Tokens: .+/, // usage/cost footer
26
+ /^Cost: .+/, // standalone cost footer
27
+ /^Applied edit to .+/, // edit application notices
28
+ /^Commit [0-9a-f]{6,}\b/, // auto-commit notices
29
+ /^You can use \/undo\b/, // undo hint after auto-commit
30
+ /^[─━-]{4,}$/, // ── / ━━ / ---- separator rules
31
+ ];
32
+ function isNoiseLine(line) {
33
+ return NOISE_LINE_PATTERNS.some((pattern) => pattern.test(line));
34
+ }
35
+ /**
36
+ * Normalize a raw aider run result into `{ text, sessionId? }`.
37
+ * See the module doc for the stdout shape handled.
38
+ */
39
+ export const aiderResultExtractor = (result) => {
40
+ const raw = result.stdout.replace(ANSI_ESCAPE_RE, "").trim();
41
+ const kept = raw
42
+ .split("\n")
43
+ .filter((line) => !isNoiseLine(line.trim()))
44
+ .join("\n")
45
+ .trim();
46
+ // Never return empty text when stdout had content: an all-noise filter
47
+ // outcome means the patterns over-matched for this capture, so fall back to
48
+ // the full trimmed stdout (downstream parsing still gets material).
49
+ const text = kept.length > 0 ? kept : raw;
50
+ // No session model (chat-history files, not ids): only a spawn-layer id
51
+ // passes through; output never supplies one.
52
+ return result.sessionId === undefined ? { text } : { text, sessionId: result.sessionId };
53
+ };