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
@@ -0,0 +1,231 @@
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
+ import path from "node:path";
5
+ import { deepMergeConfig } from "../../core/config/deep-merge.js";
6
+ import { ConfigError } from "../../core/errors.js";
7
+ import { formatExtraParamsIssue, validateExtraParams } from "../../core/extra-params.js";
8
+ import { collectSensitiveValues } from "../../core/redaction.js";
9
+ import { getHarness } from "../harnesses/index.js";
10
+ import { DEFAULT_AGENT_TIMEOUT_MS, DEFAULT_LLM_TIMEOUT_MS } from "./config.js";
11
+ import { resolveLlmModel, resolveModel } from "./model-aliases.js";
12
+ import { getBuiltinAgentProfile } from "./profiles.js";
13
+ function hasOwn(value, key) {
14
+ return Object.hasOwn(value, key);
15
+ }
16
+ function envName(reference) {
17
+ const match = /^\$(?:\{)?([A-Za-z_][A-Za-z0-9_]*)(?:\})?$/.exec(reference);
18
+ return match?.[1];
19
+ }
20
+ function selectedEngineName(config, layers, llmOnly) {
21
+ for (let index = layers.length - 1; index >= 0; index--) {
22
+ if (layers[index]?.engine !== undefined)
23
+ return layers[index]?.engine;
24
+ }
25
+ return llmOnly ? config.defaults?.llmEngine : config.defaults?.engine;
26
+ }
27
+ function resolveEngineConfig(name, config) {
28
+ const engine = config.engines?.[name];
29
+ if (!engine) {
30
+ throw new ConfigError(`Engine "${name}" is not configured.`, "INVALID_CONFIG_FILE");
31
+ }
32
+ return engine;
33
+ }
34
+ function resolveCredential(name, engine, config) {
35
+ if (engine.apiKey !== undefined) {
36
+ const explicit = envName(engine.apiKey);
37
+ if (!explicit)
38
+ throw new ConfigError(`Engine "${name}" has an invalid symbolic apiKey reference.`, "INVALID_CONFIG_FILE");
39
+ return { names: [explicit], required: true };
40
+ }
41
+ const specific = `AKM_ENGINE_${name.toUpperCase().replaceAll("-", "_")}_API_KEY`;
42
+ return config.defaults?.llmEngine === name
43
+ ? { names: [specific, "AKM_LLM_API_KEY"], required: false }
44
+ : { names: [specific], required: false };
45
+ }
46
+ /** Collect materialized engine credentials for output and persistence redaction. */
47
+ export function collectEngineCredentialValues(config, envSource = process.env) {
48
+ const values = new Set();
49
+ for (const [name, engine] of Object.entries(config.engines ?? {})) {
50
+ if (engine.kind !== "llm")
51
+ continue;
52
+ for (const envVar of resolveCredential(name, engine, config)?.names ?? []) {
53
+ const value = envSource[envVar]?.trim();
54
+ if (value)
55
+ values.add(value);
56
+ }
57
+ }
58
+ return collectSensitiveValues(values);
59
+ }
60
+ function effectiveTimeout(engine, layers, fallback) {
61
+ for (let index = layers.length - 1; index >= 0; index--) {
62
+ if (hasOwn(layers[index] ?? {}, "timeoutMs"))
63
+ return layers[index]?.timeoutMs ?? null;
64
+ }
65
+ return hasOwn(engine, "timeoutMs") ? (engine.timeoutMs ?? null) : fallback;
66
+ }
67
+ export function resolveLlmEngineUse(config, layers, options = {}) {
68
+ const name = selectedEngineName(config, layers, true);
69
+ if (!name) {
70
+ if (options.optional)
71
+ return undefined;
72
+ throw new ConfigError("No LLM engine is selected. Set defaults.llmEngine or specify engine.", "LLM_NOT_CONFIGURED");
73
+ }
74
+ const engine = resolveEngineConfig(name, config);
75
+ if (engine.kind !== "llm") {
76
+ throw new ConfigError(`Engine "${name}" is not an LLM engine.`, "INVALID_CONFIG_FILE");
77
+ }
78
+ let connection = {
79
+ provider: engine.provider,
80
+ endpoint: engine.endpoint,
81
+ model: engine.model,
82
+ temperature: engine.temperature,
83
+ maxTokens: engine.maxTokens,
84
+ supportsJsonSchema: engine.supportsJsonSchema,
85
+ extraParams: engine.extraParams,
86
+ contextLength: engine.contextLength,
87
+ enableThinking: engine.enableThinking,
88
+ };
89
+ for (const layer of layers) {
90
+ if (layer.llm)
91
+ connection = deepMergeConfig(connection, layer.llm);
92
+ if (layer.model !== undefined)
93
+ connection.model = layer.model;
94
+ }
95
+ for (const key of Object.keys(connection)) {
96
+ if (connection[key] === undefined)
97
+ delete connection[key];
98
+ }
99
+ connection.model = resolveLlmModel(connection.model, name, config.modelAliases);
100
+ return {
101
+ engine: name,
102
+ connection: connection,
103
+ credential: resolveCredential(name, engine, config),
104
+ timeoutMs: effectiveTimeout(engine, layers, DEFAULT_LLM_TIMEOUT_MS),
105
+ };
106
+ }
107
+ /** Read a resolved symbolic credential only at the runtime dispatch boundary. */
108
+ export function materializeLlmConnection(resolved) {
109
+ if (resolved.connection.extraParams !== undefined) {
110
+ const issue = validateExtraParams(resolved.connection.extraParams)[0];
111
+ if (issue) {
112
+ throw new ConfigError(formatExtraParamsIssue(`Engine "${resolved.engine}" extraParams`, issue), "INVALID_CONFIG_FILE");
113
+ }
114
+ }
115
+ let apiKey;
116
+ for (const name of resolved.credential?.names ?? []) {
117
+ const candidate = process.env[name]?.trim();
118
+ if (candidate) {
119
+ apiKey = candidate;
120
+ break;
121
+ }
122
+ }
123
+ if (resolved.credential?.required && !apiKey) {
124
+ throw new ConfigError(`Required engine credential ${resolved.credential.names[0]} is not set.`, "INVALID_CONFIG_FILE");
125
+ }
126
+ return {
127
+ ...resolved.connection,
128
+ ...(apiKey ? { apiKey } : {}),
129
+ timeoutMs: resolved.timeoutMs,
130
+ };
131
+ }
132
+ function lowerAgentEngine(name, engine, config) {
133
+ const harness = getHarness(engine.platform);
134
+ if (!harness?.capabilities.agentDispatch) {
135
+ throw new ConfigError(`Engine "${name}" names a platform that cannot dispatch agents: ${engine.platform}.`, "INVALID_CONFIG_FILE");
136
+ }
137
+ const platform = harness.id;
138
+ const sdk = platform === "opencode-sdk";
139
+ const builtin = getBuiltinAgentProfile(platform);
140
+ const profile = {
141
+ name,
142
+ platform,
143
+ bin: engine.bin ?? builtin?.bin ?? (sdk ? "opencode" : platform),
144
+ args: engine.args ?? builtin?.args ?? [],
145
+ stdio: "captured",
146
+ ...(builtin?.env ? { env: builtin.env } : {}),
147
+ envPassthrough: builtin?.envPassthrough ?? [],
148
+ parseOutput: "text",
149
+ ...(engine.workspace ? { workspace: path.resolve(engine.workspace) } : {}),
150
+ ...(engine.model
151
+ ? {
152
+ model: resolveModel(engine.model, platform, engine.modelAliases, config.modelAliases),
153
+ modelIsExact: true,
154
+ }
155
+ : {}),
156
+ ...(engine.modelAliases ? { modelAliases: engine.modelAliases } : {}),
157
+ ...(config.modelAliases ? { globalModelAliases: config.modelAliases } : {}),
158
+ };
159
+ if (!sdk) {
160
+ return {
161
+ kind: "agent",
162
+ engine: name,
163
+ profile,
164
+ timeoutMs: hasOwn(engine, "timeoutMs") ? (engine.timeoutMs ?? null) : DEFAULT_AGENT_TIMEOUT_MS,
165
+ };
166
+ }
167
+ const fallbackName = engine.llmEngine ?? config.defaults?.llmEngine;
168
+ const fallback = fallbackName
169
+ ? resolveLlmEngineUse(config, [{ engine: fallbackName }], { optional: true })
170
+ : undefined;
171
+ return {
172
+ kind: "sdk",
173
+ engine: name,
174
+ profile,
175
+ ...(fallback
176
+ ? {
177
+ fallbackConnection: fallback.connection,
178
+ ...(fallback.credential ? { fallbackCredential: fallback.credential } : {}),
179
+ fallbackTimeoutMs: fallback.timeoutMs,
180
+ }
181
+ : {}),
182
+ timeoutMs: hasOwn(engine, "timeoutMs")
183
+ ? (engine.timeoutMs ?? null)
184
+ : (fallback?.timeoutMs ?? DEFAULT_AGENT_TIMEOUT_MS),
185
+ };
186
+ }
187
+ /** Lower a named engine through the canonical harness platform. */
188
+ export function resolveEngine(name, config) {
189
+ const engine = resolveEngineConfig(name, config);
190
+ if (engine.kind === "llm") {
191
+ const resolved = resolveLlmEngineUse(config, [{ engine: name }]);
192
+ if (!resolved)
193
+ throw new ConfigError(`LLM engine "${name}" could not be resolved.`, "LLM_NOT_CONFIGURED");
194
+ return {
195
+ kind: "llm",
196
+ engine: name,
197
+ connection: resolved.connection,
198
+ ...(resolved.credential ? { credential: resolved.credential } : {}),
199
+ timeoutMs: resolved.timeoutMs,
200
+ };
201
+ }
202
+ return lowerAgentEngine(name, engine, config);
203
+ }
204
+ export function resolveDefaultEngine(config) {
205
+ const name = config.defaults?.engine;
206
+ if (!name)
207
+ throw new ConfigError("No default engine is configured.", "INVALID_CONFIG_FILE");
208
+ return resolveEngine(name, config);
209
+ }
210
+ // ── AkmConfig convenience wrappers (moved from core/config/config.ts, WI-9.8
211
+ // KILL 3, D.3 edge A) ────────────────────────────────────────────────────────
212
+ //
213
+ // Moved verbatim: `config.ts` previously called `materializeLlmConnection` +
214
+ // `resolveLlmEngineUse` directly for these two wrappers, which is what made
215
+ // config.ts import this module — and this module imported `LlmConnectionConfig`
216
+ // back from config.ts, closing a 2-file cycle. config.ts CANNOT re-export
217
+ // these (a re-export is still a graph edge to this file), so the small number
218
+ // of call sites that used to import them from "core/config/config" now import
219
+ // them from here instead (see D.3 edge A "callers compose instead").
220
+ /** Resolve and materialize the configured default LLM engine at dispatch time. */
221
+ export function requireLlmConfig(config) {
222
+ return materializeLlmConnection(resolveLlmEngineUse(config, []));
223
+ }
224
+ /**
225
+ * Like {@link requireLlmConfig} but returns `undefined` instead of throwing
226
+ * when no LLM is configured. Use in code paths where the LLM is optional.
227
+ */
228
+ export function getDefaultLlmConfig(config) {
229
+ const resolved = resolveLlmEngineUse(config, [], { optional: true });
230
+ return resolved ? materializeLlmConnection(resolved) : undefined;
231
+ }
@@ -2,9 +2,8 @@
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
  export { getCommandBuilder } from "./builders.js";
5
- export { DEFAULT_AGENT_TIMEOUT_MS, listAgentProfileNames, listResolvedAgentProfiles, requireAgentProfile, resolveAgentProfile, resolveDefaultProfileName, resolveProfileFromConfig, } from "./config.js";
5
+ export { DEFAULT_AGENT_TIMEOUT_MS } from "./config.js";
6
6
  export { _setAgentDetectForTests, defaultWhich, detectAgentCliProfiles, pickDefaultAgentProfile } from "./detect.js";
7
7
  export { listBuiltinModelAliases, resolveModel } from "./model-aliases.js";
8
8
  export { BUILTIN_AGENT_PROFILE_NAMES, getBuiltinAgentProfile, listBuiltinAgentProfiles, } from "./profiles.js";
9
9
  export { buildProposePrompt, buildReflectPrompt, buildSchemaRepairPrompt, extractDraftConfidence, parseAgentProposalPayload, } from "./prompts.js";
10
- export { runAgent } from "./spawn.js";
@@ -11,6 +11,15 @@
11
11
  * always resolve to the full name for determinism)
12
12
  */
13
13
  const BUILTIN_ALIASES = [
14
+ {
15
+ // Anthropic's Mythos-class tier above Opus — the recommended resolution
16
+ // target for the `deep` workflow tier (see docs/reference/workflows.md).
17
+ alias: "fable",
18
+ platforms: {
19
+ claude: "claude-fable-5",
20
+ opencode: "opencode/claude-fable-5",
21
+ },
22
+ },
14
23
  {
15
24
  alias: "opus",
16
25
  platforms: {
@@ -41,19 +50,24 @@ const BUILTIN_ALIASES = [
41
50
  * @param platform Builder platform name ("claude", "opencode", ...).
42
51
  * @param custom Profile-level aliases from config.json — take priority over globals and builtins.
43
52
  * @param global Config-root `modelAliases` tier table (alias → platform → model, `"*"` fallback).
53
+ * @param fallbackPlatforms Additional global tier columns checked after `platform` and before `"*"`.
44
54
  * @returns Resolved model string, or `model` verbatim when no alias matches.
45
55
  */
46
- export function resolveModel(model, platform, custom, global) {
56
+ export function resolveModel(model, platform, custom, global, fallbackPlatforms = []) {
47
57
  const key = model.toLowerCase();
48
58
  if (custom?.[key])
49
59
  return custom[key];
50
60
  const tier = global?.[key];
51
- const fromGlobal = tier?.[platform] ?? tier?.["*"];
61
+ const fromGlobal = tier?.[platform] ?? fallbackPlatforms.map((fallback) => tier?.[fallback]).find(Boolean) ?? tier?.["*"];
52
62
  if (fromGlobal)
53
63
  return fromGlobal;
54
64
  const entry = BUILTIN_ALIASES.find((a) => a.alias === key);
55
65
  return entry?.platforms[platform] ?? model;
56
66
  }
67
+ /** Resolve a direct/fallback LLM model through engine-specific, `llm`, then `*` tiers. */
68
+ export function resolveLlmModel(model, engine, global) {
69
+ return resolveModel(model, engine, undefined, global, ["llm"]);
70
+ }
57
71
  /** Return all built-in alias entries (for tests and documentation). */
58
72
  export function listBuiltinModelAliases() {
59
73
  return BUILTIN_ALIASES;
@@ -9,11 +9,12 @@
9
9
  // every lane's read-back (GRR). It is a provenance tag, never a secret.
10
10
  const COMMON_PASSTHROUGH = ["HOME", "PATH", "USER", "LANG", "LC_ALL", "TERM", "TMPDIR", "AKM_EVENT_SOURCE"];
11
11
  /**
12
- * Built-in profiles for the five agent CLIs the v1 spec calls out
13
- * explicitly. The fields here are conservative defaults — every value is
14
- * overridable from user config.
12
+ * Built-in profiles for the agent CLIs akm knows out of the box: the five the
13
+ * v1 spec calls out explicitly, plus the P2 harness adapters (copilot, pi,
14
+ * amazonq, openhands — plan §"Capability matrix"). The fields here are
15
+ * conservative defaults — every value is overridable from user config.
15
16
  *
16
- * For headless/automation use (propose, reflect, tasks), use the '-headless' variant.
17
+ * Engine lowering selects captured stdio for unattended dispatch.
17
18
  */
18
19
  const BUILTINS = {
19
20
  opencode: {
@@ -56,76 +57,49 @@ const BUILTINS = {
56
57
  envPassthrough: [...COMMON_PASSTHROUGH, "OPENAI_API_KEY", "ANTHROPIC_API_KEY"],
57
58
  parseOutput: "text",
58
59
  },
59
- };
60
- /**
61
- * Headless variants of the five base profiles for automation use (propose, reflect, tasks).
62
- *
63
- * These profiles use `stdio: "captured"` and `parseOutput: "json"` so the
64
- * agent's response can be read from stdout. They share the same `bin` and
65
- * `envPassthrough` as the corresponding base profile but are intentionally
66
- * kept out of `BUILTIN_AGENT_PROFILE_NAMES` (and therefore out of CLI
67
- * detection/enumeration) to avoid showing up as separate installable profiles.
68
- *
69
- * Users may reference them by name via `--profile opencode-headless` or by
70
- * setting `agent.default: "opencode-headless"` in config.json.
71
- */
72
- const HEADLESS_BUILTINS = {
73
- "opencode-headless": {
74
- name: "opencode-headless",
75
- bin: "opencode",
76
- args: ["run"],
77
- stdio: "captured",
78
- envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG"],
79
- parseOutput: "json",
80
- },
81
- "claude-headless": {
82
- name: "claude-headless",
83
- bin: "claude",
60
+ // ── P2 harness-adapter profiles (plan §"Capability matrix") ────────────────
61
+ copilot: {
62
+ name: "copilot",
63
+ bin: "copilot",
84
64
  args: [],
85
- stdio: "captured",
86
- envPassthrough: [...COMMON_PASSTHROUGH, "ANTHROPIC_API_KEY", "CLAUDE_CONFIG"],
87
- parseOutput: "json",
65
+ stdio: "interactive",
66
+ envPassthrough: [...COMMON_PASSTHROUGH, "GH_TOKEN", "GITHUB_TOKEN"],
67
+ parseOutput: "text",
88
68
  },
89
- "codex-headless": {
90
- name: "codex-headless",
91
- bin: "codex",
69
+ pi: {
70
+ name: "pi",
71
+ bin: "pi",
92
72
  args: [],
93
- stdio: "captured",
94
- envPassthrough: [...COMMON_PASSTHROUGH, "OPENAI_API_KEY", "CODEX_CONFIG"],
95
- parseOutput: "json",
73
+ stdio: "interactive",
74
+ envPassthrough: [...COMMON_PASSTHROUGH, "PI_API_KEY", "ANTHROPIC_API_KEY", "OPENAI_API_KEY"],
75
+ parseOutput: "text",
96
76
  },
97
- "gemini-headless": {
98
- name: "gemini-headless",
99
- bin: "gemini",
77
+ amazonq: {
78
+ name: "amazonq",
79
+ bin: "q",
100
80
  args: [],
101
- stdio: "captured",
102
- envPassthrough: [...COMMON_PASSTHROUGH, "GEMINI_API_KEY", "GOOGLE_API_KEY"],
103
- parseOutput: "json",
81
+ stdio: "interactive",
82
+ envPassthrough: [...COMMON_PASSTHROUGH, "AWS_PROFILE", "AWS_REGION"],
83
+ parseOutput: "text",
104
84
  },
105
- "aider-headless": {
106
- name: "aider-headless",
107
- bin: "aider",
108
- args: ["--no-auto-commits"],
109
- stdio: "captured",
110
- envPassthrough: [...COMMON_PASSTHROUGH, "OPENAI_API_KEY", "ANTHROPIC_API_KEY"],
111
- parseOutput: "json",
85
+ openhands: {
86
+ name: "openhands",
87
+ bin: "openhands",
88
+ args: [],
89
+ stdio: "interactive",
90
+ envPassthrough: [...COMMON_PASSTHROUGH, "LLM_MODEL", "LLM_API_KEY", "LLM_BASE_URL"],
91
+ parseOutput: "text",
112
92
  },
113
93
  };
114
- /**
115
- * Names of the five primary built-in profiles. Stable, sorted. Does NOT
116
- * include the `-headless` variants (those are resolvable by name but are
117
- * excluded from detection/enumeration flows).
118
- */
94
+ /** Names of the canonical built-in harness descriptors. Stable, sorted. */
119
95
  export const BUILTIN_AGENT_PROFILE_NAMES = Object.freeze(Object.keys(BUILTINS).sort());
120
- /** Returns the built-in profile by name (including headless variants), or `undefined` if not found. */
96
+ /** Returns the built-in descriptor for a canonical harness id. */
121
97
  export function getBuiltinAgentProfile(name) {
122
- return BUILTINS[name] ?? HEADLESS_BUILTINS[name];
98
+ return BUILTINS[name];
123
99
  }
124
100
  /**
125
- * Return a deep copy of every primary built-in profile keyed by name.
126
- * Headless variants are NOT included — use `getBuiltinAgentProfile(name)`
127
- * to look them up by name. Callers should not assume reference equality with
128
- * subsequent calls.
101
+ * Return a copy of every canonical built-in descriptor keyed by harness id.
102
+ * Callers should not assume reference equality with subsequent calls.
129
103
  */
130
104
  export function listBuiltinAgentProfiles() {
131
105
  const out = {};
@@ -6,17 +6,17 @@
6
6
  *
7
7
  * `akm reflect` and `akm propose` both shell out to the configured agent CLI
8
8
  * (via {@link runAgent}) and ask it for a structured proposal payload. The
9
- * prompts are intentionally similar — both ask the agent to return a single
10
- * JSON object containing `ref`, `content`, and (optionally) `frontmatter` —
11
- * so we share the construction here. Keeping the prompt builders in
9
+ * prompts are intentionally similar and share their construction here. Agent
10
+ * and SDK stdout keeps the JSON/file-write contracts; direct LLM reflect adds
11
+ * native-schema and framed-markdown contracts. Keeping the prompt builders in
12
12
  * `src/integrations/agent/` rather than `src/llm/` is deliberate: these are
13
13
  * shell-out prompts targeting an agent CLI, not in-tree LLM API calls.
14
14
  *
15
- * The output the agent must produce is a *strict* JSON object:
15
+ * The stdout output an agent must produce is a strict JSON object:
16
16
  *
17
17
  * ```json
18
18
  * {
19
- * "ref": "lesson:my-lesson",
19
+ * "ref": "lessons/my-lesson",
20
20
  * "content": "---\ndescription: ...\nwhen_to_use: ...\n---\n\nbody",
21
21
  * "frontmatter": { "description": "...", "when_to_use": "..." }
22
22
  * }
@@ -25,7 +25,11 @@
25
25
  * `frontmatter` is optional — the proposal queue parses it from `content`
26
26
  * during validation. We carry it through if the agent supplies it.
27
27
  */
28
- import { TYPE_DIRS } from "../../core/asset/asset-spec.js";
28
+ import reflectLlmFramedContract from "../../assets/prompts/reflect-llm-framed-contract.md" with { type: "text" };
29
+ import reflectLlmSchemaContract from "../../assets/prompts/reflect-llm-schema-contract.md" with { type: "text" };
30
+ import reflectOutputRepair from "../../assets/prompts/reflect-output-repair.md" with { type: "text" };
31
+ import { placementTypes } from "../../core/asset/asset-placement.js";
32
+ import { parseRefInput } from "../../core/asset/resolve-ref.js";
29
33
  import { authoringRulesForType, DESCRIPTION_MAX_CHARS, DESCRIPTION_MIN_CHARS, requiresDescription, } from "../../core/authoring-rules.js";
30
34
  import { parseEmbeddedJsonResponse, stripCodeFences, stripThinkBlocks } from "../../core/parse.js";
31
35
  /**
@@ -42,7 +46,7 @@ const TYPE_HINTS = {
42
46
  memory: "memory assets are short factual notes the user wants persisted across sessions. Frontmatter usually includes `description`.",
43
47
  workflow: "workflow assets are markdown describing a multi-step process. Include `# <Title>` and ordered `## Step N` sections.",
44
48
  script: "script assets are executable text files. Include a shebang and minimal usage comment.",
45
- env: "env assets are `.env` files holding a group of related CONFIGURATION for an app/service (KEY=VALUE pairs, `#` comments) — URLs, flags, and any credentials it needs. Values may or may not be sensitive; all are protected (key names discoverable, values stay on disk). Inject with `akm env run env:<name> -- <cmd>`; prefer `--clean` in agent contexts so the child starts from a minimal inherited environment. AKM itself does not print values, but the child command can print its environment, so do not run `env`, `printenv`, shell tracing, or similar diagnostics when secrets are in scope. For a single sensitive value used on its own for authentication (token, key, cert) use a `secret` instead. Never echo values back to the user.",
49
+ env: "env assets are `.env` files holding a group of related CONFIGURATION for an app/service (KEY=VALUE pairs, `#` comments) — URLs, flags, and any credentials it needs. Values may or may not be sensitive; all are protected (key names discoverable, values stay on disk). Inject with `akm env run env/<name> -- <cmd>`; prefer `--clean` in agent contexts so the child starts from a minimal inherited environment. AKM itself does not print values, but the child command can print its environment, so do not run `env`, `printenv`, shell tracing, or similar diagnostics when secrets are in scope. For a single sensitive value used on its own for authentication (token, key, cert) use a `secret` instead. Never echo values back to the user.",
46
50
  wiki: "wiki assets are markdown reference pages with `# Title` and structured headings.",
47
51
  fact: "fact assets are durable stash-level facts (personal/team/project details, coding conventions, stash-meta). Frontmatter SHOULD include `description` and a `category` (personal|team|project|convention|meta); set `pinned: true` only for the small always-injected core. Keep each fact short, high-signal, and self-contained — it is durable context, not an episodic note.",
48
52
  };
@@ -50,7 +54,7 @@ function hintForType(type) {
50
54
  return TYPE_HINTS[type] ?? `assets of type "${type}" — produce sensible markdown with optional frontmatter.`;
51
55
  }
52
56
  function knownTypeList() {
53
- return Object.keys(TYPE_DIRS).sort().join(", ");
57
+ return [...placementTypes()].sort().join(", ");
54
58
  }
55
59
  /**
56
60
  * Common envelope every prompt asks the agent to honour when NO draft file
@@ -60,7 +64,10 @@ function knownTypeList() {
60
64
  */
61
65
  const RESPONSE_CONTRACT_JSON = [
62
66
  "Respond ONLY with a single JSON object. No prose before or after.",
63
- 'Shape: {"ref": "<type>:<name>", "content": "<full file contents>", "frontmatter": {...}, "confidence": <number 0..1>}',
67
+ // Slash conceptId, not the retired `<type>:<name>` colon grammar (Q-02/Q-08).
68
+ // This contract is the schema an agent copies from, so a stale spelling here
69
+ // teaches every proposal to use a ref form the CLI now rejects outright.
70
+ 'Shape: {"ref": "<type>/<name>", "content": "<full file contents>", "frontmatter": {...}, "confidence": <number 0..1>}',
64
71
  "`content` is the full file body that will be written if accepted.",
65
72
  "`frontmatter` is optional — include it if `content` starts with `---` so reviewers can sanity-check the keys.",
66
73
  "`confidence` is REQUIRED. Self-rate this proposal on [0, 1] by how certain you are it materially improves the source asset. Calibrate honestly:",
@@ -68,7 +75,7 @@ const RESPONSE_CONTRACT_JSON = [
68
75
  " • 0.70–0.89 — clear improvement, but a reviewer might reasonably prefer different framing or scope.",
69
76
  " • 0.50–0.69 — marginal / judgment call; might help, might not be worth the churn.",
70
77
  " • Below 0.50 — you are not confident this improves on the source. Prefer returning the source body roughly unchanged with a low score over inventing changes.",
71
- "Auto-accept gates on confidence ≥ 0.80 by default. Overclaiming ships low-quality changes; underclaiming leaves good ones stuck in queue. Be honest.",
78
+ "Reviewers and the triage judge read this score when adjudicating the proposal queue. Overclaiming erodes trust in your proposals; underclaiming buries good ones. Be honest.",
72
79
  ].join("\n");
73
80
  /**
74
81
  * Response contract used when a draft file path is available. Instructs the
@@ -86,14 +93,14 @@ function fileWriteContract(draftFilePath) {
86
93
  " • 0.70–0.89 — clear improvement, but a reviewer might prefer different framing.",
87
94
  " • 0.50–0.69 — marginal / judgment call.",
88
95
  " • Below 0.50 — not confident; prefer not writing changes at all.",
89
- "Auto-accept gates on confidence ≥ 0.80. Overclaim → low-quality changes land; underclaim → good changes stuck in queue.",
96
+ "Reviewers and the triage judge read this score during adjudication. Overclaim → trust erodes; underclaim → good changes buried.",
90
97
  ].join("\n");
91
98
  }
92
99
  /**
93
100
  * Extract a confidence score from a `DRAFT_WRITTEN confidence=<n>` line emitted
94
101
  * by an agent following {@link fileWriteContract}. Tolerates trailing prose,
95
102
  * surrounding log lines, and missing/invalid confidence (returns `undefined`
96
- * so callers can keep the proposal but skip auto-accept).
103
+ * so callers can keep the proposal without a score).
97
104
  *
98
105
  * Matched forms (case-insensitive, anywhere in stdout):
99
106
  * - `DRAFT_WRITTEN confidence=0.85`
@@ -111,6 +118,27 @@ export function extractDraftConfidence(stdout) {
111
118
  return undefined;
112
119
  return value;
113
120
  }
121
+ export function reflectLlmResponseContract(mode, targetScoped) {
122
+ if (mode === "json_schema") {
123
+ return reflectLlmSchemaContract
124
+ .replace("{{FIELD_RULE}}", targetScoped
125
+ ? "The response has exactly the required fields `content`, `confidence`, and `frontmatterPatch`; do not echo `ref` or arbitrary `frontmatter`."
126
+ : "The response has exactly the required fields `ref`, `content`, `confidence`, and `frontmatterPatch`; `ref` must identify the selected asset.")
127
+ .trim();
128
+ }
129
+ const refLine = targetScoped ? "" : "AKM_REFLECT_REF: <selected asset ref>\n";
130
+ return reflectLlmFramedContract.replace("{{REF_LINE}}", refLine).trim();
131
+ }
132
+ export function buildReflectOutputRepairPrompt(mode, targetScoped) {
133
+ return reflectOutputRepair.replace("{{OUTPUT_CONTRACT}}", reflectLlmResponseContract(mode, targetScoped)).trim();
134
+ }
135
+ function reflectResponseContract(input) {
136
+ if (input.draftFilePath)
137
+ return fileWriteContract(input.draftFilePath);
138
+ if (input.outputMode)
139
+ return reflectLlmResponseContract(input.outputMode, input.ref !== undefined);
140
+ return RESPONSE_CONTRACT_JSON;
141
+ }
114
142
  /**
115
143
  * Whether the source asset content has a non-empty `description:` key in its
116
144
  * YAML frontmatter. Used by {@link buildReflectPrompt} (#636) to decide whether
@@ -150,7 +178,7 @@ export function buildReflectPrompt(input) {
150
178
  const goalSentence = isLesson
151
179
  ? `Your task is to distill what usage signals reveal about this ${input.type} asset — when to reach for it, what goes wrong without it, and what real use has revealed that the asset itself does not say. Do not reproduce the source content; your proposal must add information the source does not contain.`
152
180
  : isSkill
153
- ? "Your task is to review this skill asset, identify what the feedback and related distilled lessons show is broken, missing, unclear, or durable enough to promote into long-term documentation, and produce a single improved proposal. If the strongest evidence points to companion reference material rather than the main SKILL.md, you may instead propose a skill-adjacent knowledge doc such as `knowledge:skills/<skill>/references/<topic>`."
181
+ ? "Your task is to review this skill asset, identify what the feedback and related distilled lessons show is broken, missing, unclear, or durable enough to promote into long-term documentation, and produce a single improved proposal. If the strongest evidence points to companion reference material rather than the main SKILL.md, you may instead propose a skill-adjacent knowledge doc such as `knowledge/skills/<skill>/references/<topic>`."
154
182
  : `Your task is to review this ${input.type} asset, identify what the feedback signals as broken, missing, or unclear, and produce an improved version. Do not reproduce the source content unchanged; your proposal must correct or add something the source lacks.`;
155
183
  sections.push(goalSentence);
156
184
  sections.push(`Target ref: ${input.ref}`);
@@ -186,7 +214,7 @@ export function buildReflectPrompt(input) {
186
214
  sections.push(input.standardsContext.trim());
187
215
  }
188
216
  {
189
- const resolvedType = input.type ?? (input.ref?.includes(":") ? input.ref.split(":")[0] : "");
217
+ const resolvedType = input.type ?? (input.ref ? parseRefInput(input.ref).type : "");
190
218
  const authoringRules = resolvedType ? authoringRulesForType(resolvedType) : "";
191
219
  if (authoringRules) {
192
220
  sections.push(authoringRules);
@@ -244,7 +272,7 @@ export function buildReflectPrompt(input) {
244
272
  }
245
273
  sections.push("Evaluate whether these lessons contain strong evidence of factual, repeatable guidance that should be promoted into long-term skill documentation.");
246
274
  sections.push("Promote only guidance that is durable, generally applicable, and supported by repeated evidence. Do not copy anecdotal details, one-off incidents, or duplicate wording verbatim.");
247
- sections.push("If the guidance belongs in the main skill instructions, update the skill proposal. If it belongs in a companion reference document, return a `knowledge:skills/<skill>/references/<topic>` proposal instead.");
275
+ sections.push("If the guidance belongs in the main skill instructions, update the skill proposal. If it belongs in a companion reference document, return a `knowledge/skills/<skill>/references/<topic>` proposal instead.");
248
276
  }
249
277
  if (input.rejectedProposals && input.rejectedProposals.length > 0) {
250
278
  const lines = ["## Previously Rejected Proposals"];
@@ -319,12 +347,12 @@ export function buildReflectPrompt(input) {
319
347
  "5. Improve clarity of surrounding prose, fix structural issues, add missing required frontmatter fields. Do NOT rewrite a runbook into an essay.",
320
348
  ].join("\n"));
321
349
  }
322
- if (!input.draftFilePath && input.ref) {
350
+ if (!input.draftFilePath && !input.outputMode && input.ref) {
323
351
  // Reinforce that the `ref` field is mandatory and must exactly match the target.
324
352
  // Small models frequently omit `ref` from the response JSON, causing parse errors.
325
353
  sections.push(`IMPORTANT: The JSON "ref" field is REQUIRED. It MUST be exactly: "${input.ref}"`);
326
354
  }
327
- sections.push(input.draftFilePath ? fileWriteContract(input.draftFilePath) : RESPONSE_CONTRACT_JSON);
355
+ sections.push(reflectResponseContract(input));
328
356
  return { prompt: sections.join("\n\n"), ...(maxOutputChars !== undefined ? { maxOutputChars } : {}) };
329
357
  }
330
358
  /**
@@ -399,7 +427,7 @@ export function buildSchemaRepairPrompt(input) {
399
427
  * can map to {@link AgentFailureReason} `parse_error`.
400
428
  *
401
429
  * Resilient to two common local-LLM failure modes:
402
- * 1. `<think>…</think>` blocks emitted before the JSON (stripped by `stripJsonFences`).
430
+ * 1. `<think>…</think>` blocks emitted before the JSON (stripped before parsing).
403
431
  * 2. Prose preamble / postamble around the JSON object (handled by `extractEmbeddedJson`).
404
432
  */
405
433
  export function parseAgentProposalPayload(stdout) {