akm-cli 0.9.0-beta.9 → 0.9.0-rc.1

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 (381) hide show
  1. package/CHANGELOG.md +715 -0
  2. package/README.md +12 -4
  3. package/dist/akm +38 -0
  4. package/dist/akm-migrate-storage +38 -0
  5. package/dist/assets/help/help-improve.md +9 -6
  6. package/dist/assets/hints/cli-hints-full.md +6 -5
  7. package/dist/assets/profiles/default.json +9 -4
  8. package/dist/assets/profiles/frequent.json +1 -1
  9. package/dist/assets/profiles/memory-focus.json +1 -1
  10. package/dist/assets/profiles/proactive-maintenance.json +25 -0
  11. package/dist/assets/profiles/quick.json +1 -1
  12. package/dist/assets/profiles/recombine-only.json +21 -0
  13. package/dist/assets/profiles/reflect-distill.json +30 -0
  14. package/dist/assets/profiles/synthesize.json +15 -0
  15. package/dist/assets/profiles/thorough.json +1 -1
  16. package/dist/assets/prompts/consolidate-system.md +23 -0
  17. package/dist/assets/prompts/contradiction-judge.md +33 -0
  18. package/dist/assets/prompts/distill-knowledge-system.md +22 -0
  19. package/dist/assets/prompts/distill-lesson-system.md +36 -0
  20. package/dist/assets/prompts/extract-session.md +11 -3
  21. package/dist/assets/prompts/graph-extract-system.md +1 -0
  22. package/dist/assets/prompts/graph-extract-user-prompt.md +1 -1
  23. package/dist/assets/prompts/memory-infer-system.md +1 -0
  24. package/dist/assets/prompts/memory-infer-user.md +5 -0
  25. package/dist/assets/prompts/metadata-enhance-system.md +1 -0
  26. package/dist/assets/prompts/procedural-system.md +44 -0
  27. package/dist/assets/prompts/recombine-system.md +40 -0
  28. package/dist/assets/prompts/staleness-detect-system.md +6 -0
  29. package/dist/assets/prompts/validate-summary-judge.md +1 -0
  30. package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +38 -0
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +38 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +39 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +40 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +43 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +38 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +43 -0
  38. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +40 -0
  39. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +43 -0
  40. package/dist/assets/templates/html/health.html +281 -111
  41. package/dist/assets/wiki/ingest-workflow-template.md +45 -16
  42. package/dist/assets/wiki/schema-template.md +4 -4
  43. package/dist/cli/clack.js +56 -0
  44. package/dist/cli/config-migrate.js +7 -1
  45. package/dist/cli/confirm.js +1 -1
  46. package/dist/cli/parse-args.js +46 -1
  47. package/dist/cli/shared.js +28 -0
  48. package/dist/cli.js +25 -21
  49. package/dist/commands/agent/agent-dispatch.js +3 -2
  50. package/dist/commands/agent/agent-support.js +0 -7
  51. package/dist/commands/agent/contribute-cli.js +26 -7
  52. package/dist/commands/config-cli.js +26 -13
  53. package/dist/commands/env/child-env.js +47 -0
  54. package/dist/commands/env/env-binding.js +95 -0
  55. package/dist/commands/env/env-cli.js +228 -292
  56. package/dist/commands/env/env.js +14 -67
  57. package/dist/commands/env/secret-cli.js +140 -138
  58. package/dist/commands/feedback-cli.js +156 -155
  59. package/dist/commands/graph/graph-cli.js +5 -13
  60. package/dist/commands/graph/graph.js +3 -3
  61. package/dist/commands/health/advisories.js +151 -0
  62. package/dist/commands/health/checks.js +103 -16
  63. package/dist/commands/health/html-report.js +447 -81
  64. package/dist/commands/health/improve-metrics.js +771 -0
  65. package/dist/commands/health/llm-usage.js +65 -0
  66. package/dist/commands/health/md-report.js +103 -0
  67. package/dist/commands/health/metrics.js +278 -0
  68. package/dist/commands/health/stash-exposure.js +46 -0
  69. package/dist/commands/health/surfaces.js +216 -0
  70. package/dist/commands/health/task-runs.js +135 -0
  71. package/dist/commands/health/types.js +26 -0
  72. package/dist/commands/health/windows.js +195 -0
  73. package/dist/commands/health.js +91 -1091
  74. package/dist/commands/improve/anti-collapse.js +170 -0
  75. package/dist/commands/improve/calibration.js +161 -0
  76. package/dist/commands/improve/collapse-detector.js +421 -0
  77. package/dist/commands/improve/consolidate/chunking.js +141 -0
  78. package/dist/commands/improve/consolidate/eligibility.js +64 -0
  79. package/dist/commands/improve/consolidate/merge.js +145 -0
  80. package/dist/commands/improve/consolidate/sanitize.js +231 -0
  81. package/dist/commands/{lint.js → improve/consolidate/types.js} +1 -1
  82. package/dist/commands/improve/consolidate.js +1295 -1277
  83. package/dist/commands/improve/dedup.js +482 -0
  84. package/dist/commands/improve/distill/content-repair.js +202 -0
  85. package/dist/commands/improve/distill/promote-memory.js +229 -0
  86. package/dist/commands/improve/distill/quality-gate.js +236 -0
  87. package/dist/commands/improve/distill-guards.js +127 -0
  88. package/dist/commands/improve/distill-promotion-policy.js +826 -167
  89. package/dist/commands/improve/distill.js +228 -605
  90. package/dist/commands/improve/eligibility.js +434 -0
  91. package/dist/commands/improve/encoding-salience.js +205 -0
  92. package/dist/commands/improve/extract-cli.js +179 -59
  93. package/dist/commands/improve/extract-prompt.js +54 -3
  94. package/dist/commands/improve/extract-watch.js +140 -0
  95. package/dist/commands/improve/extract.js +409 -43
  96. package/dist/commands/improve/feedback-valence.js +54 -0
  97. package/dist/commands/improve/hot-probation.js +45 -0
  98. package/dist/commands/improve/improve-auto-accept.js +157 -10
  99. package/dist/commands/improve/improve-cli.js +115 -73
  100. package/dist/commands/improve/improve-profiles.js +28 -8
  101. package/dist/commands/improve/improve-result-file.js +15 -25
  102. package/dist/commands/improve/improve-session.js +58 -0
  103. package/dist/commands/improve/improve.js +485 -2764
  104. package/dist/commands/improve/locks.js +154 -0
  105. package/dist/commands/improve/loop-stages.js +1100 -0
  106. package/dist/commands/improve/memory/memory-belief.js +14 -15
  107. package/dist/commands/improve/memory/memory-contradiction-detect.js +83 -60
  108. package/dist/commands/improve/memory/memory-improve.js +27 -27
  109. package/dist/commands/improve/outcome-loop.js +270 -0
  110. package/dist/commands/improve/preparation.js +2002 -0
  111. package/dist/commands/improve/proactive-maintenance.js +37 -35
  112. package/dist/commands/improve/procedural.js +398 -0
  113. package/dist/commands/improve/recombine.js +818 -0
  114. package/dist/commands/improve/reflect-noise.js +0 -0
  115. package/dist/commands/improve/reflect.js +206 -45
  116. package/dist/commands/improve/salience.js +455 -0
  117. package/dist/commands/improve/schema-similarity-gate.js +168 -0
  118. package/dist/commands/improve/shared.js +51 -0
  119. package/dist/commands/improve/triage.js +93 -0
  120. package/dist/commands/lint/agent-linter.js +19 -24
  121. package/dist/commands/lint/base-linter.js +173 -60
  122. package/dist/commands/lint/command-linter.js +19 -24
  123. package/dist/commands/lint/env-key-rules.js +38 -1
  124. package/dist/commands/lint/fact-linter.js +39 -0
  125. package/dist/commands/lint/index.js +31 -13
  126. package/dist/commands/lint/memory-linter.js +1 -1
  127. package/dist/commands/lint/registry.js +7 -2
  128. package/dist/commands/lint/task-linter.js +3 -3
  129. package/dist/commands/lint/workflow-linter.js +26 -1
  130. package/dist/commands/observability-cli.js +4 -4
  131. package/dist/commands/proposal/drain-policies.js +13 -4
  132. package/dist/commands/proposal/drain.js +45 -51
  133. package/dist/commands/proposal/legacy-import.js +115 -0
  134. package/dist/commands/proposal/proposal-cli.js +24 -34
  135. package/dist/commands/proposal/proposal.js +2 -1
  136. package/dist/commands/proposal/propose.js +8 -3
  137. package/dist/commands/proposal/repository.js +829 -0
  138. package/dist/commands/proposal/validators/proposal-quality-validators.js +9 -8
  139. package/dist/commands/proposal/validators/proposals.js +93 -895
  140. package/dist/commands/read/curate.js +410 -111
  141. package/dist/commands/read/knowledge.js +10 -3
  142. package/dist/commands/read/remember-cli.js +133 -138
  143. package/dist/commands/read/search-cli.js +15 -8
  144. package/dist/commands/read/search.js +22 -11
  145. package/dist/commands/read/show.js +106 -14
  146. package/dist/commands/registry-cli.js +76 -87
  147. package/dist/commands/remember.js +11 -12
  148. package/dist/commands/sources/add-cli.js +91 -95
  149. package/dist/commands/sources/history.js +1 -1
  150. package/dist/commands/sources/init.js +66 -18
  151. package/dist/commands/sources/installed-stashes.js +11 -3
  152. package/dist/commands/sources/migration-help.js +7 -4
  153. package/dist/commands/sources/schema-repair.js +44 -46
  154. package/dist/commands/sources/self-update.js +2 -2
  155. package/dist/commands/sources/source-add.js +7 -3
  156. package/dist/commands/sources/sources-cli.js +3 -3
  157. package/dist/commands/sources/stash-cli.js +19 -39
  158. package/dist/commands/sources/stash-skeleton.js +57 -8
  159. package/dist/commands/tasks/default-tasks.js +15 -2
  160. package/dist/commands/tasks/tasks-cli.js +20 -29
  161. package/dist/commands/tasks/tasks.js +39 -11
  162. package/dist/commands/wiki-cli.js +23 -38
  163. package/dist/commands/workflow-cli.js +291 -13
  164. package/dist/core/asset/asset-registry.js +3 -1
  165. package/dist/core/asset/asset-spec.js +79 -5
  166. package/dist/core/asset/frontmatter.js +188 -167
  167. package/dist/core/asset/markdown.js +8 -0
  168. package/dist/core/authoring-rules.js +92 -0
  169. package/dist/core/common.js +4 -23
  170. package/dist/core/concurrent.js +10 -1
  171. package/dist/core/config/config-io.js +10 -1
  172. package/dist/core/config/config-migration.js +18 -40
  173. package/dist/core/config/config-schema.js +403 -62
  174. package/dist/core/config/config-types.js +3 -3
  175. package/dist/core/config/config.js +67 -22
  176. package/dist/core/deep-merge.js +38 -0
  177. package/dist/core/errors.js +1 -0
  178. package/dist/core/eval/rank-metrics.js +113 -0
  179. package/dist/core/events.js +4 -7
  180. package/dist/core/improve-types.js +47 -8
  181. package/dist/core/json-schema.js +142 -0
  182. package/dist/core/logs-db.js +14 -75
  183. package/dist/core/parse.js +36 -16
  184. package/dist/core/paths.js +18 -18
  185. package/dist/core/standards/resolve-standards-context.js +87 -0
  186. package/dist/core/standards/resolve-stash-standards.js +99 -0
  187. package/dist/core/standards/resolve-type-conventions.js +66 -0
  188. package/dist/core/state/migrations.js +770 -0
  189. package/dist/core/state-db.js +132 -1126
  190. package/dist/core/structured.js +69 -0
  191. package/dist/core/time.js +53 -0
  192. package/dist/core/warn.js +21 -0
  193. package/dist/core/write-source.js +37 -0
  194. package/dist/indexer/db/db.js +261 -770
  195. package/dist/indexer/db/entry-mapper.js +41 -0
  196. package/dist/indexer/db/graph-db.js +129 -86
  197. package/dist/indexer/db/llm-cache.js +2 -2
  198. package/dist/indexer/db/schema.js +516 -0
  199. package/dist/indexer/ensure-index.js +36 -92
  200. package/dist/indexer/feedback/utility-policy.js +75 -0
  201. package/dist/indexer/graph/graph-boost.js +51 -41
  202. package/dist/indexer/graph/graph-extraction.js +207 -4
  203. package/dist/indexer/index-writer-lock.js +18 -11
  204. package/dist/indexer/index-written-assets.js +105 -0
  205. package/dist/indexer/indexer.js +182 -204
  206. package/dist/indexer/passes/dir-staleness.js +114 -0
  207. package/dist/indexer/passes/memory-inference.js +13 -5
  208. package/dist/indexer/passes/metadata.js +20 -0
  209. package/dist/indexer/read-preflight.js +23 -0
  210. package/dist/indexer/search/db-search.js +89 -13
  211. package/dist/indexer/search/fts-query.js +51 -0
  212. package/dist/indexer/search/ranking-contributors.js +95 -9
  213. package/dist/indexer/search/ranking.js +79 -3
  214. package/dist/indexer/search/search-fields.js +6 -0
  215. package/dist/indexer/search/search-source.js +32 -21
  216. package/dist/indexer/search/semantic-status.js +4 -0
  217. package/dist/indexer/walk/matchers.js +48 -0
  218. package/dist/indexer/walk/walker.js +21 -13
  219. package/dist/integrations/agent/builders.js +41 -13
  220. package/dist/integrations/agent/config.js +20 -59
  221. package/dist/integrations/agent/detect.js +9 -0
  222. package/dist/integrations/agent/index.js +3 -19
  223. package/dist/integrations/agent/model-aliases.js +16 -2
  224. package/dist/integrations/agent/profiles.js +79 -6
  225. package/dist/integrations/agent/prompts.js +75 -9
  226. package/dist/integrations/agent/runner-dispatch.js +83 -0
  227. package/dist/integrations/agent/runner.js +13 -9
  228. package/dist/integrations/agent/spawn.js +206 -81
  229. package/dist/integrations/harnesses/aider/agent-builder.js +113 -0
  230. package/dist/integrations/harnesses/aider/index.js +58 -0
  231. package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
  232. package/dist/integrations/harnesses/amazonq/agent-builder.js +153 -0
  233. package/dist/integrations/harnesses/amazonq/index.js +59 -0
  234. package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
  235. package/dist/integrations/harnesses/claude/agent-builder.js +46 -7
  236. package/dist/integrations/harnesses/claude/index.js +27 -23
  237. package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
  238. package/dist/integrations/harnesses/claude/session-log.js +10 -0
  239. package/dist/integrations/harnesses/codex/agent-builder.js +137 -0
  240. package/dist/integrations/harnesses/codex/index.js +63 -0
  241. package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
  242. package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
  243. package/dist/integrations/harnesses/copilot/index.js +60 -0
  244. package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
  245. package/dist/integrations/harnesses/gemini/agent-builder.js +121 -0
  246. package/dist/integrations/harnesses/gemini/index.js +60 -0
  247. package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
  248. package/dist/integrations/harnesses/index.js +28 -7
  249. package/dist/integrations/harnesses/opencode/agent-builder.js +1 -1
  250. package/dist/integrations/harnesses/opencode/index.js +17 -16
  251. package/dist/integrations/harnesses/opencode/session-log.js +173 -3
  252. package/dist/integrations/harnesses/opencode-sdk/harness.js +65 -0
  253. package/dist/integrations/harnesses/opencode-sdk/index.js +10 -34
  254. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +642 -71
  255. package/dist/integrations/harnesses/openhands/agent-builder.js +126 -0
  256. package/dist/integrations/harnesses/openhands/index.js +58 -0
  257. package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
  258. package/dist/integrations/harnesses/pi/agent-builder.js +104 -0
  259. package/dist/integrations/harnesses/pi/index.js +58 -0
  260. package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
  261. package/dist/integrations/harnesses/types.js +8 -0
  262. package/dist/integrations/session-logs/index.js +40 -11
  263. package/dist/llm/call-ai.js +2 -2
  264. package/dist/llm/client.js +34 -11
  265. package/dist/llm/embedder.js +67 -4
  266. package/dist/llm/embedders/cache.js +3 -1
  267. package/dist/llm/embedders/deterministic.js +66 -0
  268. package/dist/llm/embedders/local.js +73 -3
  269. package/dist/llm/feature-gate.js +16 -15
  270. package/dist/llm/graph-extract.js +67 -44
  271. package/dist/llm/memory-infer-impl.js +138 -0
  272. package/dist/llm/memory-infer.js +1 -127
  273. package/dist/llm/metadata-enhance.js +44 -31
  274. package/dist/llm/structured-call.js +49 -0
  275. package/dist/migrate-storage-node.mjs +8 -0
  276. package/dist/output/context.js +5 -5
  277. package/dist/output/renderers.js +87 -15
  278. package/dist/output/shapes/curate.js +14 -2
  279. package/dist/output/shapes/helpers.js +0 -3
  280. package/dist/output/shapes/passthrough.js +6 -1
  281. package/dist/output/text/helpers.js +241 -2
  282. package/dist/output/text/workflow.js +4 -1
  283. package/dist/registry/providers/skills-sh.js +21 -147
  284. package/dist/registry/providers/static-index.js +15 -157
  285. package/dist/registry/resolve.js +27 -9
  286. package/dist/runtime.js +25 -1
  287. package/dist/schemas/akm-config.json +14225 -0
  288. package/dist/schemas/akm-workflow.json +328 -0
  289. package/dist/scripts/migrate-storage.js +2743 -8390
  290. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +1652 -607
  291. package/dist/setup/detect.js +9 -0
  292. package/dist/setup/legacy-config.js +106 -0
  293. package/dist/setup/prompt.js +57 -0
  294. package/dist/setup/providers.js +14 -0
  295. package/dist/setup/registry-stash-loader.js +12 -0
  296. package/dist/setup/semantic-assets.js +124 -0
  297. package/dist/setup/setup.js +52 -1614
  298. package/dist/setup/steps/connection.js +734 -0
  299. package/dist/setup/steps/output.js +31 -0
  300. package/dist/setup/steps/platforms.js +124 -0
  301. package/dist/setup/steps/semantic.js +27 -0
  302. package/dist/setup/steps/sources.js +222 -0
  303. package/dist/setup/steps/stashdir.js +42 -0
  304. package/dist/setup/steps/tasks.js +152 -0
  305. package/dist/sources/include.js +6 -2
  306. package/dist/sources/providers/filesystem.js +0 -1
  307. package/dist/sources/providers/git-install.js +210 -0
  308. package/dist/sources/providers/git-provider.js +234 -0
  309. package/dist/sources/providers/git-stash.js +248 -0
  310. package/dist/sources/providers/git.js +10 -661
  311. package/dist/sources/providers/npm.js +2 -6
  312. package/dist/sources/providers/provider-utils.js +13 -7
  313. package/dist/sources/providers/sync-from-ref.js +9 -1
  314. package/dist/sources/providers/website.js +9 -5
  315. package/dist/sources/website-ingest.js +187 -29
  316. package/dist/sources/wiki-fetchers/registry.js +53 -0
  317. package/dist/sources/wiki-fetchers/youtube.js +239 -0
  318. package/dist/storage/database.js +45 -10
  319. package/dist/storage/managed-db.js +82 -0
  320. package/dist/storage/repositories/canaries-repository.js +107 -0
  321. package/dist/storage/repositories/consolidation-repository.js +38 -0
  322. package/dist/storage/repositories/embeddings-repository.js +72 -0
  323. package/dist/storage/repositories/events-repository.js +187 -0
  324. package/dist/storage/repositories/extract-sessions-repository.js +96 -0
  325. package/dist/storage/repositories/improve-runs-repository.js +146 -0
  326. package/dist/storage/repositories/index-db.js +14 -8
  327. package/dist/storage/repositories/proposals-repository.js +220 -0
  328. package/dist/storage/repositories/recombine-repository.js +213 -0
  329. package/dist/storage/repositories/registry-cache.js +93 -0
  330. package/dist/storage/repositories/registry-index-cache-repository.js +46 -0
  331. package/dist/storage/repositories/task-history-repository.js +93 -0
  332. package/dist/storage/repositories/workflow-runs-repository.js +189 -1
  333. package/dist/storage/sqlite-pragmas.js +146 -0
  334. package/dist/tasks/backends/cron.js +1 -1
  335. package/dist/tasks/backends/index.js +9 -0
  336. package/dist/tasks/backends/launchd.js +1 -1
  337. package/dist/tasks/backends/schtasks.js +1 -1
  338. package/dist/tasks/{resolveAkmBin.js → resolve-akm-bin.js} +2 -2
  339. package/dist/tasks/runner.js +15 -13
  340. package/dist/text-import-hook.mjs +1 -1
  341. package/dist/wiki/wiki.js +52 -11
  342. package/dist/workflows/authoring/authoring.js +123 -10
  343. package/dist/workflows/authoring/workflow-program-template.yaml +31 -0
  344. package/dist/workflows/cli.js +5 -0
  345. package/dist/workflows/db.js +138 -4
  346. package/dist/workflows/exec/brief.js +484 -0
  347. package/dist/workflows/exec/native-executor.js +975 -0
  348. package/dist/workflows/exec/param-secrets.js +115 -0
  349. package/dist/workflows/exec/report.js +1295 -0
  350. package/dist/workflows/exec/run-workflow.js +596 -0
  351. package/dist/workflows/exec/scheduler.js +100 -0
  352. package/dist/workflows/exec/step-work.js +1156 -0
  353. package/dist/workflows/exec/unit-writer.js +23 -0
  354. package/dist/workflows/exec/watch.js +116 -0
  355. package/dist/workflows/exec/worktree.js +171 -0
  356. package/dist/workflows/ir/compile.js +388 -0
  357. package/dist/workflows/ir/params.js +54 -0
  358. package/dist/workflows/ir/plan-hash.js +33 -0
  359. package/dist/workflows/ir/schema.js +4 -0
  360. package/dist/workflows/parser.js +3 -1
  361. package/dist/workflows/program/expressions.js +369 -0
  362. package/dist/workflows/program/parser.js +760 -0
  363. package/dist/workflows/program/project.js +105 -0
  364. package/dist/workflows/program/schema.js +54 -0
  365. package/dist/workflows/renderer.js +82 -5
  366. package/dist/workflows/runtime/agent-identity.js +59 -14
  367. package/dist/workflows/runtime/runs.js +248 -153
  368. package/dist/workflows/runtime/unit-checkin.js +45 -0
  369. package/dist/workflows/runtime/workflow-asset-loader.js +188 -0
  370. package/dist/workflows/validate-summary.js +26 -10
  371. package/dist/workflows/validator.js +1 -1
  372. package/docs/README.md +69 -18
  373. package/docs/data-and-telemetry.md +7 -5
  374. package/docs/migration/release-notes/0.7.0.md +1 -1
  375. package/docs/migration/release-notes/0.9.0-beta.60.md +19 -0
  376. package/docs/migration/release-notes/0.9.0.md +39 -0
  377. package/package.json +10 -10
  378. package/dist/assets/tasks/core/update-stashes.yml +0 -4
  379. package/dist/commands/db-cli.js +0 -23
  380. package/dist/indexer/db/db-backup.js +0 -376
  381. package/dist/indexer/passes/staleness-detect.js +0 -488
@@ -0,0 +1,153 @@
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
+ * Amazon Q Developer CLI agent command builder (P2, plan §"The adapter
6
+ * contract" step 2 / §"Capability matrix").
7
+ *
8
+ * Translates a platform-agnostic {@link AgentDispatchRequest} into the exact
9
+ * headless argv the `q` CLI expects. Per the capability matrix the headless
10
+ * invocation is:
11
+ *
12
+ * q chat --no-interactive --trust-all-tools "<prompt>"
13
+ *
14
+ * with `--model <m>` for model selection and `--resume` for resume. Resume is
15
+ * registry-side (`AkmHarness.resume`, {@link AMAZONQ_RESUME_FLAG}) — and NOTE:
16
+ * unlike every other harness's resume, Q's `--resume` is a bare flag that
17
+ * replays the previous conversation *of the working directory*; it takes no
18
+ * session id. There is nothing to thread from `workflow_run_units` — akm's own
19
+ * unit rows remain the durable resume source of truth regardless (plan
20
+ * §"Session, MCP, and identity across harnesses").
21
+ *
22
+ * Platform-specific mapping decisions (all localized here, per the adapter
23
+ * contract):
24
+ *
25
+ * - **subcommand** — headless dispatch is the `chat` subcommand. The builder
26
+ * prepends `chat` itself (mirroring the codex builder's `exec` handling); a
27
+ * user profile that already pins `chat` as its first arg is not doubled.
28
+ * - **prompt** — the trailing positional `[INPUT]` argument of `q chat`,
29
+ * preceded by the `--` end-of-options separator (mirroring the
30
+ * claude/codex/pi builders) so a prompt whose text begins with `-`/`--` can
31
+ * never be parsed as flags. `--no-interactive` makes Q print the response
32
+ * and exit instead of opening the REPL.
33
+ * - **systemPrompt** — `q chat` has no system-prompt flag (persona/context
34
+ * comes from Q's own agent config files), so the system prompt is folded
35
+ * into the positional payload ahead of the task prompt, separated by a
36
+ * blank line. `assertNotFlag` still guards it.
37
+ * - **schema** — the matrix places Q in the NO-structured-output tier
38
+ * ("via prompt+validate": *(none documented)* — there is no `--json` or
39
+ * `--output-format` to ask for). The JSON Schema is therefore passed
40
+ * through the prompt: a directive matching the engine's wording
41
+ * (`step-work.ts` `buildUnitPrompt`) is appended to the payload.
42
+ * Stdout stays plain text; `./result-extractor.ts` strips terminal framing
43
+ * and the engine's shared embedded-JSON parse + retry-until-valid loop does
44
+ * the rest. No schema temp file is written — that seam is codex-only
45
+ * (`--output-schema`); inventing a flag here would produce a silently
46
+ * broken command.
47
+ * - **tools** — a string/array tool policy maps to Q's documented
48
+ * `--trust-tools=<t1,t2>` allowlist flag (equals-joined, per `q chat
49
+ * --help`). With no policy at all, headless runs need autonomy, so
50
+ * `--trust-all-tools` is emitted per the matrix. A *structured* policy
51
+ * object is NOT expressible as Q flags; it is deliberately dropped without
52
+ * falling back to `--trust-all-tools` (never silently widen a restriction)
53
+ * — Q then refuses untrusted tool actions in non-interactive mode, which is
54
+ * the conservative failure mode.
55
+ * - **effort** — stays unconsumed (reserved; the shared request contract's
56
+ * "no builder consumes it yet" note stays true).
57
+ *
58
+ * NOT registered anywhere: `builders.ts` / `harnesses/index.ts` wiring is a
59
+ * follow-up integration task (as is the registry-side capability entry —
60
+ * pattern `local-runner`, structuredOutput `none`). Exported standalone so
61
+ * that task only adds a registry entry.
62
+ */
63
+ import { assertNotFlag } from "../../agent/builder-shared.js";
64
+ import { resolveModel } from "../../agent/model-aliases.js";
65
+ /** Canonical harness/platform id used for model-alias resolution. */
66
+ export const AMAZONQ_PLATFORM = "amazonq";
67
+ /**
68
+ * Resume flag per the capability matrix (`--resume`). Exported for the
69
+ * integration task's `AkmHarness.resume` registry entry. Bare flag: Q resumes
70
+ * the previous conversation of the current working directory and takes NO
71
+ * session id value — do not append one after it.
72
+ */
73
+ export const AMAZONQ_RESUME_FLAG = "--resume";
74
+ /**
75
+ * Split a tool policy into individual tool names for `--trust-tools`.
76
+ * Strings are comma-separated lists; arrays are taken as-is. Structured
77
+ * policy objects return `undefined` (not expressible as Q flags — see
78
+ * module doc).
79
+ */
80
+ function toolPolicyEntries(tools) {
81
+ if (typeof tools === "string") {
82
+ return tools
83
+ .split(",")
84
+ .map((t) => t.trim())
85
+ .filter(Boolean);
86
+ }
87
+ if (Array.isArray(tools)) {
88
+ return tools.map((t) => t.trim()).filter(Boolean);
89
+ }
90
+ return undefined;
91
+ }
92
+ /**
93
+ * Assemble the positional prompt payload: optional system prompt, the task
94
+ * prompt, and — when a schema is requested — the same schema directive the
95
+ * workflow engine's prompt assembly uses, so both dispatch paths speak one
96
+ * dialect.
97
+ */
98
+ function buildPromptPayload(req) {
99
+ const sections = [];
100
+ if (req.systemPrompt)
101
+ sections.push(req.systemPrompt);
102
+ sections.push(req.prompt);
103
+ if (req.schema) {
104
+ sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):\n${JSON.stringify(req.schema)}`);
105
+ }
106
+ return sections.join("\n\n");
107
+ }
108
+ /**
109
+ * Amazon Q Developer CLI builder.
110
+ * Command shape:
111
+ * q chat --no-interactive (--trust-all-tools | --trust-tools=<t1,t2>)
112
+ * [--model <m>] -- "<systemPrompt?\n\nprompt\n\nschema directive?>"
113
+ */
114
+ export const amazonqBuilder = {
115
+ platform: AMAZONQ_PLATFORM,
116
+ build(profile, req) {
117
+ assertNotFlag(req.systemPrompt, "systemPrompt");
118
+ assertNotFlag(req.model, "model");
119
+ // Built-in q profiles would ship `args: []`; headless dispatch is the
120
+ // `chat` subcommand. Don't double it when a user profile already pins it.
121
+ const extra = profile.args[0] === "chat" ? profile.args.slice(1) : [...profile.args];
122
+ const args = ["chat", ...extra];
123
+ // Print the response and exit — required for captured dispatch.
124
+ args.push("--no-interactive");
125
+ if (req.tools) {
126
+ // Structured policy objects (entries === undefined) emit NO trust
127
+ // flags: dropping a restriction must never widen to --trust-all-tools.
128
+ const entries = toolPolicyEntries(req.tools);
129
+ if (entries !== undefined) {
130
+ for (const tool of entries) {
131
+ assertNotFlag(tool, "tools entry");
132
+ }
133
+ // Q's documented allowlist form is equals-joined and comma-separated
134
+ // (`--trust-tools=fs_read,fs_write`); an empty list trusts no tools.
135
+ args.push(`--trust-tools=${entries.join(",")}`);
136
+ }
137
+ }
138
+ else {
139
+ // Headless default per the capability matrix: units must run without
140
+ // interactive tool-approval prompts.
141
+ args.push("--trust-all-tools");
142
+ }
143
+ if (req.model) {
144
+ const resolved = resolveModel(req.model, AMAZONQ_PLATFORM, profile.modelAliases, profile.globalModelAliases);
145
+ args.push("--model", resolved);
146
+ }
147
+ // No system-prompt / schema flags exist on `q chat` — both travel in the
148
+ // positional payload, after the end-of-options separator.
149
+ args.push("--");
150
+ args.push(buildPromptPayload(req));
151
+ return { argv: [profile.bin, ...args] };
152
+ },
153
+ };
@@ -0,0 +1,59 @@
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
+ * Amazon Q Developer CLI harness (P2 integration, plan §"The adapter
6
+ * contract").
7
+ *
8
+ * Per-harness barrel gathering the Amazon Q integration surfaces:
9
+ * - agent command builder → ./agent-builder.ts (amazonqBuilder)
10
+ * - result extractor → ./result-extractor.ts (amazonqResultExtractor)
11
+ *
12
+ * It also defines {@link AmazonqHarness}, the {@link AkmHarness} descriptor
13
+ * that `HARNESS_REGISTRY` registers. Dispatch-only: no native session-log
14
+ * reader or config importer yet.
15
+ */
16
+ import { BaseHarness } from "../types.js";
17
+ import { AMAZONQ_RESUME_FLAG, amazonqBuilder } from "./agent-builder.js";
18
+ import { amazonqResultExtractor } from "./result-extractor.js";
19
+ export { AMAZONQ_PLATFORM, AMAZONQ_RESUME_FLAG, amazonqBuilder } from "./agent-builder.js";
20
+ export { amazonqResultExtractor, stripTerminalFraming } from "./result-extractor.js";
21
+ function caps(c) {
22
+ return {
23
+ sessionLogs: false,
24
+ agentDispatch: false,
25
+ detection: false,
26
+ configImport: false,
27
+ runtimeIdentity: false,
28
+ v1Migration: false,
29
+ ...c,
30
+ };
31
+ }
32
+ /**
33
+ * Amazon Q Developer CLI (`q`).
34
+ *
35
+ * Canonical id is `'amazonq'`; no alias or distinct runtime identity.
36
+ */
37
+ export class AmazonqHarness extends BaseHarness {
38
+ id = "amazonq";
39
+ displayName = "Amazon Q Developer CLI";
40
+ aliases = [];
41
+ agentBuilder = amazonqBuilder;
42
+ resultExtractor = amazonqResultExtractor;
43
+ // ── Workflow-engine descriptor (plan §"Capability matrix", P2) ────────────
44
+ // akm spawns `q chat` locally per unit ⇒ local-runner.
45
+ pattern = "local-runner";
46
+ // No documented structured output: akm injects the schema into the prompt
47
+ // and extracts embedded JSON from plain-text stdout.
48
+ structuredOutput = "none";
49
+ // Q's `--resume` is a BARE flag (takesSessionId: false): it replays the
50
+ // previous conversation of the working directory and takes no session id
51
+ // (see AMAZONQ_RESUME_FLAG in ./agent-builder.ts).
52
+ resume = { flag: AMAZONQ_RESUME_FLAG, takesSessionId: false };
53
+ // No `identityEnv`: the matrix lists Q's identity markers as uncertain, and
54
+ // Q stamps no session var onto child processes.
55
+ capabilities = caps({
56
+ agentDispatch: true,
57
+ detection: true,
58
+ });
59
+ }
@@ -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
+ const ESC = "\u001B";
5
+ const BEL = "\u0007";
6
+ /**
7
+ * Matches ANSI CSI sequences (colors, cursor movement, erase-line) and OSC
8
+ * sequences (title, hyperlink) terminated by BEL or ST. Built via the RegExp
9
+ * constructor so the control characters live in named string constants
10
+ * instead of regex-literal escapes.
11
+ */
12
+ const ANSI_SEQUENCE = new RegExp(`${ESC}\\[[0-9;?]*[ -/]*[@-~]` + `|${ESC}\\][^${BEL}${ESC}]*(?:${BEL}|${ESC}\\\\)`, "g");
13
+ /**
14
+ * Resolve carriage-return overwrites within one physical line: a terminal
15
+ * would redraw from column 0 at each `\r`, so only the segment after the last
16
+ * `\r` survives (spinner frames like "⠋ Thinking..." disappear exactly as
17
+ * they do on screen). A trailing bare `\r` (CRLF line endings) is handled by
18
+ * splitting on `\r?\n` before this runs.
19
+ */
20
+ function resolveCarriageReturns(line) {
21
+ const lastCr = line.lastIndexOf("\r");
22
+ return lastCr === -1 ? line : line.slice(lastCr + 1);
23
+ }
24
+ /** Strip terminal framing from raw captured stdout. See module doc, rule 1. */
25
+ export function stripTerminalFraming(raw) {
26
+ const lines = raw.split(/\r?\n/).map((line) => resolveCarriageReturns(line).replace(ANSI_SEQUENCE, ""));
27
+ // Drop Q's "> " response marker from the first non-empty line only — deeper
28
+ // occurrences may be legitimate content (markdown blockquotes).
29
+ for (let i = 0; i < lines.length; i++) {
30
+ const line = lines[i] ?? "";
31
+ if (line.trim().length === 0)
32
+ continue;
33
+ if (line.startsWith("> "))
34
+ lines[i] = line.slice(2);
35
+ break;
36
+ }
37
+ return lines.join("\n").trim();
38
+ }
39
+ /**
40
+ * Normalize a raw Amazon Q run result into `{ text, sessionId? }`.
41
+ * See the module doc for the rules.
42
+ */
43
+ export const amazonqResultExtractor = (result) => {
44
+ const sessionId = result.sessionId;
45
+ // Rule 2: a pre-parsed whole-stdout JSON *string* is the answer itself.
46
+ const text = typeof result.parsed === "string" ? result.parsed.trim() : stripTerminalFraming(result.stdout);
47
+ return { text, ...(sessionId ? { sessionId } : {}) };
48
+ };
@@ -11,15 +11,49 @@
11
11
  * in `agent/builders.ts`, which imports this builder back into
12
12
  * `BUILTIN_BUILDERS`.
13
13
  *
14
- * Behaviour-preserving relocation: the produced argv is byte-identical to the
15
- * pre-migration `claudeBuilder`. The builder's `platform` stays `'claude'` (the
16
- * canonical harness id).
14
+ * ## Structured output (Codex round-3 finding A)
15
+ *
16
+ * The headless `claude -p` (`--print`) CLI has NO native output-SCHEMA flag
17
+ * (unlike Codex's `--output-schema <file>`). Its documented structured path is
18
+ * `--output-format json`, which wraps the run in a RESULT ENVELOPE
19
+ * (`{"type":"result","result":"<final answer>","session_id":"…", …}`) — the
20
+ * "native-json" tier, NOT "native-schema". (The registry's earlier
21
+ * `native-schema` claim described Claude Code's IN-HARNESS `Workflow`/`agent()`
22
+ * tool-input-schema path, which is a different execution surface than the
23
+ * agentBuilder dispatch akm's local-runner uses; the descriptor is aligned to
24
+ * `native-json` to match this builder honestly.)
25
+ *
26
+ * So for a schema-bearing unit this builder emits `--output-format json` and
27
+ * appends the SAME schema directive the engine's prompt assembly uses
28
+ * (`step-work.ts` `buildUnitPrompt`) so a direct (non-workflow) dispatch is
29
+ * self-sufficient — matching the copilot/gemini native-json builders. The
30
+ * result envelope is unwrapped by `./result-extractor.ts`, and the engine's
31
+ * shared `runStructured` retry-until-valid loop still validates the extracted
32
+ * text against the node schema (constrained/hinted output is trusted but
33
+ * verified). Without a schema the argv is byte-identical to the pre-fix shape.
34
+ *
35
+ * The builder's `platform` stays `'claude'` (the canonical harness id).
17
36
  */
18
- import { assertNotFlag, normalizeTools } from "../../agent/builder-shared.js";
37
+ import { assertNotFlag, normalizeTools, } from "../../agent/builder-shared.js";
19
38
  import { resolveModel } from "../../agent/model-aliases.js";
39
+ /**
40
+ * Assemble the positional prompt: the task prompt and — when a schema is
41
+ * requested — the same schema directive the workflow engine's prompt assembly
42
+ * uses (`step-work.ts` `buildUnitPrompt`), so both dispatch paths speak one
43
+ * dialect. Claude Code takes the system prompt as a `--system-prompt` FLAG (it
44
+ * has one, unlike copilot/gemini), so only the schema directive is folded in
45
+ * here.
46
+ */
47
+ function buildPromptPayload(req) {
48
+ if (!req.schema)
49
+ return req.prompt;
50
+ return `${req.prompt}\n\nRespond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):\n${JSON.stringify(req.schema)}`;
51
+ }
20
52
  /**
21
53
  * Claude Code builder.
22
- * Command shape: claude [--system-prompt "..."] [--model <m>] [--allowedTools <t>] --print "<prompt>"
54
+ * Command shape:
55
+ * claude [--system-prompt "..."] [--model <m>] [--allowedTools <t>]
56
+ * [--output-format json] --print -- "<prompt (+ schema directive)>"
23
57
  *
24
58
  * --print switches Claude Code to non-interactive captured output mode.
25
59
  */
@@ -33,16 +67,21 @@ export const claudeBuilder = {
33
67
  args.push("--system-prompt", req.systemPrompt);
34
68
  }
35
69
  if (req.model) {
36
- const resolved = resolveModel(req.model, "claude", profile.modelAliases);
70
+ const resolved = resolveModel(req.model, "claude", profile.modelAliases, profile.globalModelAliases);
37
71
  args.push("--model", resolved);
38
72
  }
39
73
  if (req.tools) {
40
74
  args.push("--allowedTools", normalizeTools(req.tools));
41
75
  }
76
+ if (req.schema) {
77
+ // Structured unit: request the documented JSON result envelope so
78
+ // `./result-extractor.ts` can pull the final answer + session id.
79
+ args.push("--output-format", "json");
80
+ }
42
81
  // --print = non-interactive, outputs to stdout — required for captured mode
43
82
  args.push("--print");
44
83
  args.push("--");
45
- args.push(req.prompt);
84
+ args.push(buildPromptPayload(req));
46
85
  return { argv: [profile.bin, ...args] };
47
86
  },
48
87
  };
@@ -1,32 +1,13 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /**
5
- * Claude Code harness (#563).
6
- *
7
- * This is the per-harness barrel that gathers the Claude Code integration
8
- * surfaces that were previously scattered across the codebase:
9
- * - session-log reader → ./session-log.ts (ClaudeCodeProvider)
10
- * - agent command builder → ./agent-builder.ts (claudeBuilder)
11
- * - config importer → ./config-import.ts (claudeCodeImporter)
12
- *
13
- * It also defines {@link ClaudeHarness}, the {@link AkmHarness} descriptor that
14
- * `HARNESS_REGISTRY` registers.
15
- *
16
- * ## id normalization bridge ('claude' vs 'claude-code')
17
- *
18
- * The canonical, persisted id is `'claude'` (used by the agent runner, agent
19
- * profiles, the Zod config schema and `--type` resolution after normalization).
20
- * `'claude-code'` is the historical RUNTIME identity — the string stamped on
21
- * session-log events/refs, the extracted-session dedup key, and the value
22
- * `resolveAgentIdentity` reports. It is registered as an `alias` and exposed as
23
- * `runtimeId` so BOTH directions round-trip via `normalizeHarnessId()` /
24
- * `denormalizeRuntimeIdentity()`. Existing persisted configs and session logs
25
- * that say `'claude-code'` keep working unchanged.
26
- */
27
4
  import { BaseHarness } from "../types.js";
5
+ import { claudeBuilder } from "./agent-builder.js";
6
+ import { claudeResultExtractor } from "./result-extractor.js";
7
+ import { ClaudeCodeProvider } from "./session-log.js";
28
8
  export { claudeBuilder } from "./agent-builder.js";
29
9
  export { claudeCodeImporter } from "./config-import.js";
10
+ export { claudeResultExtractor } from "./result-extractor.js";
30
11
  export { ClaudeCodeProvider } from "./session-log.js";
31
12
  function caps(c) {
32
13
  return {
@@ -53,6 +34,29 @@ export class ClaudeHarness extends BaseHarness {
53
34
  // Home-relative config dir scanned by `akm setup` (#567). Claude Code has a
54
35
  // session-log provider, so offering it as a stash source is functional.
55
36
  setupDetectionDir = ".claude";
37
+ agentBuilder = claudeBuilder;
38
+ resultExtractor = claudeResultExtractor;
39
+ // ── Workflow-engine descriptor (plan §"Capability matrix", P2) ────────────
40
+ // Claude Code is the in-harness pattern: the orchestrating session itself
41
+ // drives units via the `akm workflow` gate spine (`claude -p` headless
42
+ // dispatch also exists via `agentBuilder`, but the pattern classification
43
+ // follows the matrix row).
44
+ pattern = "in-harness";
45
+ // Structured output tier for the AGENT-DISPATCH (`claude -p`) path akm's
46
+ // local runner uses (Codex round-3 finding A). The headless CLI has NO
47
+ // output-schema flag — its documented structured path is `--output-format
48
+ // json`, a RESULT ENVELOPE akm parses (`./result-extractor.ts`) and then
49
+ // validates against the node schema ⇒ the "native-json" tier. (Claude Code's
50
+ // in-harness `Workflow`/`agent()` tool-input-schema path IS native-schema,
51
+ // but that is a different surface than the dispatch builder — the descriptor
52
+ // is aligned to what the builder honestly does.)
53
+ structuredOutput = "native-json";
54
+ // `claude --resume <sessionId>` replays a previous session in headless mode.
55
+ resume = { flag: "--resume", takesSessionId: true };
56
+ // Session-id env marker: presence of a concrete session id (not the bare
57
+ // "running under Claude Code" flag) attributes a run to this harness.
58
+ identityEnv = ["CLAUDE_SESSION_ID"];
59
+ sessionLogProvider = () => new ClaudeCodeProvider();
56
60
  capabilities = caps({
57
61
  sessionLogs: true,
58
62
  agentDispatch: true,
@@ -0,0 +1,52 @@
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
+ function isRecord(value) {
5
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6
+ }
7
+ function asNonEmptyString(value) {
8
+ return typeof value === "string" && value.length > 0 ? value : undefined;
9
+ }
10
+ /** JSON.parse that returns undefined instead of throwing. */
11
+ function tryParseJson(raw) {
12
+ try {
13
+ return JSON.parse(raw);
14
+ }
15
+ catch {
16
+ return undefined;
17
+ }
18
+ }
19
+ /**
20
+ * Is this parsed object Claude Code's `--output-format json` RESULT ENVELOPE
21
+ * (rather than a bare JSON answer a schema unit produced without the flag)? A
22
+ * genuine envelope declares `type: "result"`, or carries the two envelope-only
23
+ * fields together (a string `result` AND a `session_id`). A bare structured
24
+ * answer — `{"result":"ok"}` — carries neither marker, so it is passed through
25
+ * raw and the engine's schema validator sees the whole object.
26
+ */
27
+ function isResultEnvelope(value) {
28
+ if (value.type === "result")
29
+ return true;
30
+ return typeof value.result === "string" && asNonEmptyString(value.session_id) !== undefined;
31
+ }
32
+ /**
33
+ * Normalize a raw claude run result into `{ text, sessionId? }`. See the module
34
+ * doc for the two stdout shapes (JSON result envelope vs plain text).
35
+ */
36
+ export const claudeResultExtractor = (result) => {
37
+ const fallbackSessionId = result.sessionId;
38
+ const raw = result.stdout;
39
+ const trimmed = raw.trim();
40
+ // Only attempt an envelope parse when stdout looks like a single JSON object
41
+ // (`--output-format json`). A plain-text run is passed through UNCHANGED
42
+ // (untrimmed) so schemaless dispatch stays byte-identical to today.
43
+ if (trimmed.startsWith("{")) {
44
+ const whole = result.parsed !== undefined ? result.parsed : tryParseJson(trimmed);
45
+ if (isRecord(whole) && isResultEnvelope(whole)) {
46
+ const text = typeof whole.result === "string" ? whole.result : trimmed;
47
+ const sessionId = asNonEmptyString(whole.session_id) ?? fallbackSessionId;
48
+ return { text, ...(sessionId ? { sessionId } : {}) };
49
+ }
50
+ }
51
+ return { text: raw, ...(fallbackSessionId ? { sessionId: fallbackSessionId } : {}) };
52
+ };
@@ -107,6 +107,16 @@ export class ClaudeCodeProvider {
107
107
  isAvailable() {
108
108
  return fs.existsSync(claudeProjectsDir());
109
109
  }
110
+ /**
111
+ * Directory holding Claude Code's per-project session JSONL files
112
+ * (`~/.claude/projects`, honoring `AKM_CLAUDE_PROJECTS_DIR`). Returns `[]`
113
+ * when the directory does not exist on this machine. See {@link
114
+ * SessionLogHarness.watchRoots}.
115
+ */
116
+ watchRoots() {
117
+ const dir = claudeProjectsDir();
118
+ return fs.existsSync(dir) ? [dir] : [];
119
+ }
110
120
  *readEvents(input) {
111
121
  try {
112
122
  for (const jsonlPath of this.#walkJsonl(claudeProjectsDir())) {
@@ -0,0 +1,137 @@
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
+ * OpenAI Codex CLI agent command builder (P2, plan §"The adapter contract" /
6
+ * §"Capability matrix").
7
+ *
8
+ * Translates a platform-agnostic {@link AgentDispatchRequest} into the exact
9
+ * headless argv the `codex` CLI expects:
10
+ *
11
+ * codex exec --sandbox workspace-write [--model <m>] --json [--output-schema <file>] -- "<prompt>"
12
+ *
13
+ * Capability-matrix facts this builder encodes (July 2026 research):
14
+ * - Headless invocation is the `exec` subcommand (`codex exec "<p>"`), not a
15
+ * flag. The built-in codex profiles carry `args: []`, so the builder
16
+ * prepends `exec` itself; a user profile that already pins `exec` as its
17
+ * first arg is not doubled.
18
+ * - `--json` switches stdout to a JSONL event stream — the input contract of
19
+ * `./result-extractor.ts`. Always emitted, mirroring how the Claude builder
20
+ * always emits `--print`: dispatch is the captured, non-interactive path.
21
+ * - Codex is the NATIVE-SCHEMA tier (plan §"Structured-output
22
+ * normalization"): `req.schema` is written to a temp file and passed via
23
+ * `--output-schema <file>`. The file is tiny, uniquely named under the OS
24
+ * temp dir, and intentionally NOT cleaned up here — `BuiltCommand` has no
25
+ * post-run hook, and the spawned process reads the file after `build()`
26
+ * returns. OS temp reaping owns the lifecycle. The engine still validates
27
+ * the output defensively (the constrained output is trusted but verified).
28
+ * - `codex exec` has no system-prompt flag; `req.systemPrompt` is folded
29
+ * into the prompt payload (system text first, blank line, then the task),
30
+ * after the `--` end-of-options separator so it can never be parsed as a
31
+ * flag.
32
+ * - Tool policy is omitted, but the builder DOES inject `--sandbox
33
+ * workspace-write` so dispatched units can write to their working
34
+ * directory. `codex exec` defaults to a read-only sandbox that silently
35
+ * blocks file writes; without this flag the unit returns "workspace is
36
+ * read-only" and the engine marks the step complete with no real mutation.
37
+ * `--ask-for-approval` is NOT injected — that flag only exists on the
38
+ * interactive `codex` command, not on `codex exec`, and exec mode is
39
+ * already non-approval-blocking. Profile-supplied `--sandbox` flags
40
+ * (long or short form) are preserved (not duplicated).
41
+ * - Resume is the `codex exec resume <id>` SUBCOMMAND, not a flag, so it is
42
+ * not expressible through `AgentDispatchRequest` (which has no session
43
+ * field yet); {@link codexResumeArgs} exposes the argv prefix for the
44
+ * integration task that wires session-id reuse from `workflow_run_units`.
45
+ * - `req.effort` stays unconsumed (reserved; codex would take it as
46
+ * `-c model_reasoning_effort=<v>` — left to the integration task so the
47
+ * shared request contract's "no builder consumes it yet" note stays true).
48
+ *
49
+ * NOT registered anywhere yet: `HARNESS_REGISTRY` / `BUILTIN_BUILDERS` wiring
50
+ * is a follow-up integration task. Exported cleanly for that task to import.
51
+ */
52
+ import { mkdtempSync, writeFileSync } from "node:fs";
53
+ import { tmpdir } from "node:os";
54
+ import { join } from "node:path";
55
+ import { assertNotFlag } from "../../agent/builder-shared.js";
56
+ import { resolveModel } from "../../agent/model-aliases.js";
57
+ /**
58
+ * Write a node's JSON Schema to a fresh temp file for `--output-schema`.
59
+ *
60
+ * A unique `mkdtemp` directory per build avoids collisions between concurrent
61
+ * fan-out units dispatching in the same process. Returns the absolute file
62
+ * path (the value handed to the flag).
63
+ */
64
+ export function writeCodexOutputSchemaFile(schema) {
65
+ const dir = mkdtempSync(join(tmpdir(), "akm-codex-schema-"));
66
+ const file = join(dir, "output-schema.json");
67
+ writeFileSync(file, `${JSON.stringify(schema, null, 2)}\n`, "utf8");
68
+ return file;
69
+ }
70
+ /**
71
+ * Argv prefix that resumes a previous codex session: `exec resume <id>`.
72
+ * Codex resume is a subcommand chain, not a flag — kept here so the flag-shaped
73
+ * `HarnessResumeSupport` seam is not force-fitted. The harness-native session
74
+ * id comes from the unit row (stored opportunistically by the result
75
+ * extractor); akm never depends on it (plan §"Session, MCP, and identity").
76
+ */
77
+ export function codexResumeArgs(sessionId) {
78
+ assertNotFlag(sessionId, "sessionId");
79
+ return ["exec", "resume", sessionId];
80
+ }
81
+ /**
82
+ * Return `base` plus the `--sandbox workspace-write` flag that makes `codex exec`
83
+ * able to write to its working directory. `codex exec` defaults to a read-only
84
+ * sandbox that silently blocks file writes — without this flag the unit returns
85
+ * "workspace is read-only" and the engine marks the step complete with no real
86
+ * mutation. If the profile already pins `--sandbox` (long or short form) the
87
+ * default is not duplicated.
88
+ *
89
+ * Note: `--ask-for-approval` is an *interactive* codex flag only — `codex exec`
90
+ * does not accept it (it errors with "unexpected argument"). Non-interactive
91
+ * exec mode is implicitly non-approval-blocking; `--sandbox workspace-write`
92
+ * alone is sufficient for dispatched units.
93
+ */
94
+ function ensureSandboxFlags(base) {
95
+ const out = [...base];
96
+ if (!out.includes("--sandbox") && !out.includes("-s")) {
97
+ out.push("--sandbox", "workspace-write");
98
+ }
99
+ return out;
100
+ }
101
+ /**
102
+ * OpenAI Codex builder.
103
+ * Command shape: codex exec --sandbox workspace-write [--model <m>] --json [--output-schema <file>] -- "<prompt>"
104
+ */
105
+ export const codexBuilder = {
106
+ platform: "codex",
107
+ build(profile, req) {
108
+ assertNotFlag(req.systemPrompt, "systemPrompt");
109
+ assertNotFlag(req.model, "model");
110
+ // Built-in codex profiles ship `args: []`; headless dispatch is the `exec`
111
+ // subcommand. Don't double it when a user profile already pins it.
112
+ const extra = profile.args[0] === "exec" ? profile.args.slice(1) : [...profile.args];
113
+ // `codex exec` defaults to a read-only sandbox that silently blocks file
114
+ // writes — dispatched units would return "workspace is read-only" and the
115
+ // engine would mark them complete with no real mutation. Force
116
+ // `workspace-write` (writes scoped to cwd) unless the profile already pins
117
+ // its own --sandbox flag (`--ask-for-approval` is not injectable here —
118
+ // see ensureSandboxFlags).
119
+ const sandboxArgs = ensureSandboxFlags(extra);
120
+ const args = ["exec", ...sandboxArgs];
121
+ if (req.model) {
122
+ const resolved = resolveModel(req.model, "codex", profile.modelAliases, profile.globalModelAliases);
123
+ args.push("--model", resolved);
124
+ }
125
+ // JSONL event stream on stdout — the codex result extractor's input.
126
+ args.push("--json");
127
+ if (req.schema) {
128
+ // Native-schema tier: pass the node schema straight through.
129
+ args.push("--output-schema", writeCodexOutputSchemaFile(req.schema));
130
+ }
131
+ // No system-prompt flag exists on `codex exec` — fold it into the prompt.
132
+ const prompt = req.systemPrompt ? `${req.systemPrompt}\n\n${req.prompt}` : req.prompt;
133
+ args.push("--");
134
+ args.push(prompt);
135
+ return { argv: [profile.bin, ...args] };
136
+ },
137
+ };