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,63 @@
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 harness (P2 integration, plan §"The adapter contract").
6
+ *
7
+ * Per-harness barrel gathering the Codex integration surfaces:
8
+ * - agent command builder → ./agent-builder.ts (codexBuilder)
9
+ * - result extractor → ./result-extractor.ts (codexResultExtractor)
10
+ *
11
+ * It also defines {@link CodexHarness}, the {@link AkmHarness} descriptor that
12
+ * `HARNESS_REGISTRY` registers. Dispatch-only: no native session-log reader or
13
+ * config importer yet.
14
+ */
15
+ import { BaseHarness } from "../types.js";
16
+ import { codexBuilder } from "./agent-builder.js";
17
+ import { codexResultExtractor } from "./result-extractor.js";
18
+ export { codexBuilder, codexResumeArgs, writeCodexOutputSchemaFile } from "./agent-builder.js";
19
+ export { codexResultExtractor } from "./result-extractor.js";
20
+ function caps(c) {
21
+ return {
22
+ sessionLogs: false,
23
+ agentDispatch: false,
24
+ detection: false,
25
+ configImport: false,
26
+ runtimeIdentity: false,
27
+ v1Migration: false,
28
+ ...c,
29
+ };
30
+ }
31
+ /**
32
+ * OpenAI Codex CLI.
33
+ *
34
+ * Canonical id is `'codex'`; no alias or distinct runtime identity.
35
+ */
36
+ export class CodexHarness extends BaseHarness {
37
+ id = "codex";
38
+ displayName = "OpenAI Codex CLI";
39
+ aliases = [];
40
+ agentBuilder = codexBuilder;
41
+ resultExtractor = codexResultExtractor;
42
+ // ── Workflow-engine descriptor (plan §"Capability matrix", P2) ────────────
43
+ // akm spawns `codex exec` locally per unit ⇒ local-runner.
44
+ pattern = "local-runner";
45
+ // `--output-schema <file>` enforces a caller-supplied JSON schema natively.
46
+ structuredOutput = "native-schema";
47
+ // No flag-shaped resume: codex resume is the `exec resume <id>` SUBCOMMAND
48
+ // chain (see `codexResumeArgs` in ./agent-builder.ts), which the flag-shaped
49
+ // `HarnessResumeSupport` seam deliberately does not force-fit.
50
+ // Presence flag: CODEX_SANDBOX is stamped only on processes codex itself
51
+ // spawns inside its sandbox, so it genuinely means "running under codex" —
52
+ // but its VALUE (e.g. "seatbelt") is a sandbox mode, not a session id, so it
53
+ // is registered as `presenceEnv` (harness inference only), never
54
+ // `identityEnv` (whose values persist as agent_session_id). CODEX_HOME (the
55
+ // matrix's other candidate) is deliberately NOT registered anywhere: it is a
56
+ // user config-dir var commonly exported in shell profiles, so it would stamp
57
+ // identity onto manual runs (see `AkmHarness.presenceEnv`).
58
+ presenceEnv = ["CODEX_SANDBOX"];
59
+ capabilities = caps({
60
+ agentDispatch: true,
61
+ detection: true,
62
+ });
63
+ }
@@ -0,0 +1,73 @@
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
+ /** Interpret one parsed JSONL event in either codex event dialect. */
11
+ function interpretEvent(event) {
12
+ // Legacy protocol: {"id":..., "msg":{"type": ...}}
13
+ const msg = event.msg;
14
+ if (isRecord(msg)) {
15
+ switch (msg.type) {
16
+ case "session_configured":
17
+ return { sessionId: asNonEmptyString(msg.session_id) };
18
+ case "agent_message":
19
+ return { agentMessage: asNonEmptyString(msg.message) };
20
+ case "task_complete":
21
+ return { finalMessage: asNonEmptyString(msg.last_agent_message) };
22
+ default:
23
+ return {};
24
+ }
25
+ }
26
+ // Newer protocol: flat {"type": "thread.started" | "item.completed" | ...}
27
+ switch (event.type) {
28
+ case "thread.started":
29
+ return { sessionId: asNonEmptyString(event.thread_id) };
30
+ case "item.completed": {
31
+ const item = event.item;
32
+ if (isRecord(item) && item.type === "agent_message") {
33
+ return { agentMessage: asNonEmptyString(item.text) };
34
+ }
35
+ return {};
36
+ }
37
+ default:
38
+ return {};
39
+ }
40
+ }
41
+ /**
42
+ * Codex result extractor: JSONL event stream (either dialect) → final agent
43
+ * message + opportunistic session id, with a plain-stdout fallback.
44
+ */
45
+ export const codexResultExtractor = (result) => {
46
+ let sessionId = result.sessionId;
47
+ let lastAgentMessage;
48
+ let finalMessage;
49
+ for (const line of result.stdout.split("\n")) {
50
+ const trimmed = line.trim();
51
+ // Every codex event line is a JSON object; skip banner/noise lines cheaply.
52
+ if (!trimmed.startsWith("{"))
53
+ continue;
54
+ let parsed;
55
+ try {
56
+ parsed = JSON.parse(trimmed);
57
+ }
58
+ catch {
59
+ continue; // not a complete JSON line (e.g. wrapped text) — ignore
60
+ }
61
+ if (!isRecord(parsed))
62
+ continue;
63
+ const contribution = interpretEvent(parsed);
64
+ if (contribution.sessionId)
65
+ sessionId = contribution.sessionId;
66
+ if (contribution.agentMessage)
67
+ lastAgentMessage = contribution.agentMessage;
68
+ if (contribution.finalMessage)
69
+ finalMessage = contribution.finalMessage;
70
+ }
71
+ const text = finalMessage ?? lastAgentMessage ?? result.stdout.trim();
72
+ return sessionId === undefined ? { text } : { text, sessionId };
73
+ };
@@ -0,0 +1,122 @@
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
+ * GitHub Copilot CLI agent command builder (P2, plan §"The adapter contract"
6
+ * step 2 / §"Capability matrix").
7
+ *
8
+ * Translates a platform-agnostic {@link AgentDispatchRequest} into the exact
9
+ * headless argv the `copilot` CLI expects. Per the capability matrix the
10
+ * headless invocation is:
11
+ *
12
+ * copilot -p "<prompt>" --allow-all-tools
13
+ *
14
+ * with `--output-format json` for structured output, `--model <m>` for model
15
+ * selection, and `--resume <id>` for resume (resume is registry-side —
16
+ * `AkmHarness.resume` — not built here because `AgentDispatchRequest` carries
17
+ * no session id).
18
+ *
19
+ * Platform-specific mapping decisions (all localized here, per the adapter
20
+ * contract):
21
+ *
22
+ * - **systemPrompt** — Copilot CLI has no system-prompt flag (it reads
23
+ * repo/user custom-instructions files instead), so the system prompt is
24
+ * folded into the `-p` payload ahead of the task prompt, separated by a
25
+ * blank line. `assertNotFlag` still guards it so a `--`-prefixed system
26
+ * prompt cannot turn the front of the `-p` value into a flag.
27
+ * - **schema** — the matrix places Copilot in the "via prompt+validate" tier
28
+ * (no native `--output-schema` equivalent, unlike Codex), so the JSON
29
+ * Schema is passed through the prompt: a directive matching the engine's
30
+ * wording (`step-work.ts` `buildUnitPrompt`) is appended to the `-p`
31
+ * payload, and `--output-format json` is emitted so stdout is the
32
+ * documented JSON envelope the copilot result extractor normalizes. The
33
+ * engine's shared retry-until-valid loop performs the actual validation.
34
+ * - **tools** — a string/array tool policy maps to repeated
35
+ * `--allow-tool <t>` flags (Copilot's per-tool approval flag). With no
36
+ * policy at all, headless runs need autonomy, so `--allow-all-tools` is
37
+ * emitted per the matrix. A *structured* policy object is NOT expressible
38
+ * as Copilot flags; it is deliberately dropped without falling back to
39
+ * `--allow-all-tools` (never silently widen a restriction) — in
40
+ * programmatic mode Copilot then denies unapproved tool calls, which is the
41
+ * conservative failure mode.
42
+ *
43
+ * NOT registered anywhere: `builders.ts` / `harnesses/index.ts` wiring is a
44
+ * follow-up integration task. Exported standalone so that task only adds a
45
+ * registry entry.
46
+ */
47
+ import { assertNotFlag } from "../../agent/builder-shared.js";
48
+ import { resolveModel } from "../../agent/model-aliases.js";
49
+ /** Canonical harness/platform id used for model-alias resolution. */
50
+ export const COPILOT_PLATFORM = "copilot";
51
+ /**
52
+ * Split a tool policy into individual tool names for `--allow-tool`.
53
+ * Strings are comma-separated lists; arrays are taken as-is. Structured
54
+ * policy objects return `undefined` (not expressible as Copilot flags — see
55
+ * module doc).
56
+ */
57
+ function toolPolicyEntries(tools) {
58
+ if (typeof tools === "string") {
59
+ return tools
60
+ .split(",")
61
+ .map((t) => t.trim())
62
+ .filter(Boolean);
63
+ }
64
+ if (Array.isArray(tools)) {
65
+ return tools.map((t) => t.trim()).filter(Boolean);
66
+ }
67
+ return undefined;
68
+ }
69
+ /**
70
+ * Assemble the `-p` payload: optional system prompt, the task prompt, and —
71
+ * when a schema is requested — the same schema directive the workflow
72
+ * engine's prompt assembly uses, so both dispatch paths speak one dialect.
73
+ */
74
+ function buildPromptPayload(req) {
75
+ const sections = [];
76
+ if (req.systemPrompt)
77
+ sections.push(req.systemPrompt);
78
+ sections.push(req.prompt);
79
+ if (req.schema) {
80
+ sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):\n${JSON.stringify(req.schema)}`);
81
+ }
82
+ return sections.join("\n\n");
83
+ }
84
+ /**
85
+ * GitHub Copilot CLI builder.
86
+ * Command shape:
87
+ * copilot [--model <m>] (--allow-all-tools | --allow-tool <t> ...)
88
+ * [--output-format json] -p "<systemPrompt?\n\nprompt\n\nschema?>"
89
+ */
90
+ export const copilotBuilder = {
91
+ platform: COPILOT_PLATFORM,
92
+ build(profile, req) {
93
+ assertNotFlag(req.systemPrompt, "systemPrompt");
94
+ assertNotFlag(req.model, "model");
95
+ const args = [...profile.args];
96
+ if (req.model) {
97
+ const resolved = resolveModel(req.model, COPILOT_PLATFORM, profile.modelAliases, profile.globalModelAliases);
98
+ args.push("--model", resolved);
99
+ }
100
+ if (req.tools) {
101
+ const entries = toolPolicyEntries(req.tools);
102
+ // Structured policy objects (entries === undefined) emit NO allow flags:
103
+ // dropping a restriction must never widen to --allow-all-tools.
104
+ for (const tool of entries ?? []) {
105
+ assertNotFlag(tool, "tools entry");
106
+ args.push("--allow-tool", tool);
107
+ }
108
+ }
109
+ else {
110
+ // Headless default per the capability matrix: units must run without
111
+ // interactive tool-approval prompts.
112
+ args.push("--allow-all-tools");
113
+ }
114
+ if (req.schema) {
115
+ // Structured unit: ask for the documented JSON envelope so the result
116
+ // extractor can pull the final message + session id deterministically.
117
+ args.push("--output-format", "json");
118
+ }
119
+ args.push("-p", buildPromptPayload(req));
120
+ return { argv: [profile.bin, ...args] };
121
+ },
122
+ };
@@ -0,0 +1,60 @@
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
+ * GitHub Copilot CLI harness (P2 integration, plan §"The adapter contract").
6
+ *
7
+ * Per-harness barrel gathering the Copilot CLI integration surfaces:
8
+ * - agent command builder → ./agent-builder.ts (copilotBuilder)
9
+ * - result extractor → ./result-extractor.ts (copilotResultExtractor)
10
+ *
11
+ * It also defines {@link CopilotHarness}, the {@link AkmHarness} descriptor
12
+ * that `HARNESS_REGISTRY` registers. This is the LOCAL Copilot CLI
13
+ * (`copilot -p …`); the cloud "Copilot coding agent" is the plan's
14
+ * cloud-delegate pattern and is a separate, future descriptor.
15
+ */
16
+ import { BaseHarness } from "../types.js";
17
+ import { copilotBuilder } from "./agent-builder.js";
18
+ import { copilotResultExtractor } from "./result-extractor.js";
19
+ export { COPILOT_PLATFORM, copilotBuilder } from "./agent-builder.js";
20
+ export { copilotResultExtractor } 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
+ * GitHub Copilot CLI (local headless CLI, not the cloud coding agent).
34
+ *
35
+ * Canonical id is `'copilot'`; no alias or distinct runtime identity.
36
+ */
37
+ export class CopilotHarness extends BaseHarness {
38
+ id = "copilot";
39
+ displayName = "GitHub Copilot CLI";
40
+ aliases = [];
41
+ agentBuilder = copilotBuilder;
42
+ resultExtractor = copilotResultExtractor;
43
+ // ── Workflow-engine descriptor (plan §"Capability matrix", P2) ────────────
44
+ // akm spawns the `copilot` CLI locally per unit ⇒ local-runner.
45
+ pattern = "local-runner";
46
+ // `--output-format json` emits a documented JSON envelope akm parses, then
47
+ // validates against the node schema ⇒ native-json tier.
48
+ structuredOutput = "native-json";
49
+ // `copilot --resume <sessionId>` replays a previous session.
50
+ resume = { flag: "--resume", takesSessionId: true };
51
+ // Session-id env marker only. The matrix's other candidates (GH_TOKEN,
52
+ // bare COPILOT_* presence vars) are credential/presence flags that would
53
+ // stamp identity onto manual runs, so they are deliberately NOT registered
54
+ // (see `AkmHarness.identityEnv`).
55
+ identityEnv = ["COPILOT_SESSION_ID"];
56
+ capabilities = caps({
57
+ agentDispatch: true,
58
+ detection: true,
59
+ });
60
+ }
@@ -0,0 +1,151 @@
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
+ /** Keys that may carry the final answer, in precedence order. */
8
+ const TEXT_KEYS = ["result", "response", "text", "output", "content", "message"];
9
+ /** Keys that may carry the harness-native session id, in precedence order. */
10
+ const SESSION_KEYS = ["session_id", "sessionId", "conversation_id", "conversationId", "thread_id", "threadId"];
11
+ /**
12
+ * Coerce a candidate value into text. Handles the shapes Copilot's envelope
13
+ * nests answers in: bare strings, `{content|text}` wrappers (assistant
14
+ * message objects), and arrays of `{type:"text",text}` content blocks.
15
+ * Depth-bounded: JSON.parse output is acyclic, but nesting is capped anyway
16
+ * so a pathological envelope cannot recurse unboundedly.
17
+ */
18
+ function textOf(value, depth = 0) {
19
+ if (depth > 4)
20
+ return undefined;
21
+ if (typeof value === "string")
22
+ return value;
23
+ if (Array.isArray(value)) {
24
+ const parts = [];
25
+ for (const block of value) {
26
+ const t = textOf(block, depth + 1);
27
+ if (t)
28
+ parts.push(t);
29
+ }
30
+ return parts.length > 0 ? parts.join("\n") : undefined;
31
+ }
32
+ if (isRecord(value)) {
33
+ return textOf(value.content ?? value.text, depth + 1);
34
+ }
35
+ return undefined;
36
+ }
37
+ /** Extract the final-answer text from one parsed JSON value, if any. */
38
+ function extractText(value) {
39
+ if (typeof value === "string")
40
+ return value;
41
+ if (!isRecord(value))
42
+ return undefined;
43
+ for (const key of TEXT_KEYS) {
44
+ if (!(key in value))
45
+ continue;
46
+ const text = textOf(value[key]);
47
+ if (text !== undefined)
48
+ return text;
49
+ }
50
+ return undefined;
51
+ }
52
+ /** Extract a harness-native session id from one parsed JSON value, if any. */
53
+ function extractSessionId(value) {
54
+ if (!isRecord(value))
55
+ return undefined;
56
+ for (const key of SESSION_KEYS) {
57
+ const candidate = value[key];
58
+ if (typeof candidate === "string" && candidate.length > 0)
59
+ return candidate;
60
+ }
61
+ return undefined;
62
+ }
63
+ /**
64
+ * `type` discriminator values Copilot's `--output-format json` envelopes are
65
+ * documented to use (plus the `session.*` event family). Deliberately a
66
+ * CLOSED set: a schema unit's own answer may legitimately be a discriminated
67
+ * union with a `type` field (`{"type":"success","output":"data"}`), and
68
+ * treating ANY string `type` as a transport marker would unwrap — and
69
+ * corrupt — such answers. An unrecognized type degrades to raw pass-through,
70
+ * which the schema validator handles (whole object) and free-text tolerates.
71
+ */
72
+ const ENVELOPE_TYPES = new Set(["result", "response", "message", "assistant", "error"]);
73
+ /**
74
+ * Does this parsed object look like one of Copilot's transport ENVELOPES (a
75
+ * `result`/event document) rather than a bare JSON answer the model produced?
76
+ *
77
+ * Copilot's `--output-format json` documents always carry a transport marker:
78
+ * a known `type` discriminator (`"result"`, `"session.start"`, `"message"`, …)
79
+ * and, in every documented result envelope, a session-id field. A bare
80
+ * structured answer a schema unit was asked for — e.g. `{"result":"ok"}` or
81
+ * `{"type":"success","output":"data"}` — carries neither a known discriminator
82
+ * nor (normally) a session-id key. Unwrapping such an answer would hand the
83
+ * schema validator only the field value (`"ok"`) and reject the run despite
84
+ * valid JSON (PR #714 review), so we only unwrap objects that are genuinely
85
+ * envelopes and pass everything else through raw.
86
+ */
87
+ function isTransportEnvelope(value) {
88
+ const type = value.type;
89
+ if (typeof type === "string" && (ENVELOPE_TYPES.has(type) || type.startsWith("session.")))
90
+ return true;
91
+ return extractSessionId(value) !== undefined;
92
+ }
93
+ /** JSON.parse that returns undefined instead of throwing. */
94
+ function tryParseJson(raw) {
95
+ try {
96
+ return JSON.parse(raw);
97
+ }
98
+ catch {
99
+ return undefined;
100
+ }
101
+ }
102
+ /**
103
+ * Normalize a raw copilot run result into `{ text, sessionId? }`.
104
+ * See the module doc for the three stdout shapes handled.
105
+ */
106
+ export const copilotResultExtractor = (result) => {
107
+ // The raw result's own sessionId (SDK-style paths) is the fallback; an id
108
+ // found in the output stream wins because it is fresher.
109
+ const fallbackSessionId = result.sessionId;
110
+ const raw = result.stdout.trim();
111
+ // Shape 1 — whole stdout is one JSON document (spawn may have pre-parsed
112
+ // it when the profile requested parseOutput: "json").
113
+ const whole = result.parsed !== undefined ? result.parsed : raw.length > 0 ? tryParseJson(raw) : undefined;
114
+ if (whole !== undefined) {
115
+ const sessionId = extractSessionId(whole) ?? fallbackSessionId;
116
+ // A bare JSON OBJECT with no transport marker is a legitimate structured
117
+ // answer (a schema unit's `{"result":"ok"}`), NOT an envelope — pass its
118
+ // raw JSON through so the engine's schema validator receives the whole
119
+ // object instead of an unwrapped field value (PR #714 review). Only
120
+ // genuine Copilot envelopes are unwrapped; non-object JSON (a top-level
121
+ // string/array/primitive) keeps the prior extraction. Either way, an
122
+ // unknown envelope with no recognized text key falls back to raw stdout.
123
+ const text = isRecord(whole) && !isTransportEnvelope(whole) ? raw : (extractText(whole) ?? raw);
124
+ return { text, ...(sessionId ? { sessionId } : {}) };
125
+ }
126
+ // Shape 2 — JSONL event stream: last text-bearing event wins; first
127
+ // session-id-bearing event supplies the id. Non-JSON lines are banner
128
+ // noise and are skipped.
129
+ let lastText;
130
+ let streamSessionId;
131
+ let sawJsonLine = false;
132
+ for (const line of raw.split("\n")) {
133
+ const trimmed = line.trim();
134
+ if (trimmed.length === 0)
135
+ continue;
136
+ const event = tryParseJson(trimmed);
137
+ if (event === undefined)
138
+ continue;
139
+ sawJsonLine = true;
140
+ streamSessionId ??= extractSessionId(event);
141
+ const text = extractText(event);
142
+ if (text !== undefined)
143
+ lastText = text;
144
+ }
145
+ if (sawJsonLine) {
146
+ const sessionId = streamSessionId ?? fallbackSessionId;
147
+ return { text: lastText ?? raw, ...(sessionId ? { sessionId } : {}) };
148
+ }
149
+ // Shape 3 — plain text passthrough.
150
+ return { text: raw, ...(fallbackSessionId ? { sessionId: fallbackSessionId } : {}) };
151
+ };
@@ -0,0 +1,121 @@
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
+ * Gemini CLI agent command builder (P2, plan §"The adapter contract" step 2 /
6
+ * §"Capability matrix").
7
+ *
8
+ * Translates a platform-agnostic {@link AgentDispatchRequest} into the exact
9
+ * headless argv the `gemini` CLI expects. Per the capability matrix the
10
+ * headless invocation is:
11
+ *
12
+ * gemini -p "<prompt>"
13
+ *
14
+ * with `--output-format json` for structured output, `--model <m>` for model
15
+ * selection, and `--resume <id>` for resume. Resume is registry-side
16
+ * (`AkmHarness.resume` — Gemini's resume IS flag-shaped, so the shared
17
+ * `HarnessResumeSupport` seam covers it); it is not built here because
18
+ * `AgentDispatchRequest` carries no session id. The `GEMINI_CLI=1` identity
19
+ * env marker is likewise registry-side (`AkmHarness.identityEnv` /
20
+ * `agent-identity.ts`), not a builder concern.
21
+ *
22
+ * Platform-specific mapping decisions (all localized here, per the adapter
23
+ * contract):
24
+ *
25
+ * - **systemPrompt** — Gemini CLI has no system-prompt flag in headless mode
26
+ * (system text comes from `GEMINI.md` context files / `GEMINI_SYSTEM_MD`),
27
+ * so the system prompt is folded into the `-p` payload ahead of the task
28
+ * prompt, separated by a blank line. `assertNotFlag` still guards it so a
29
+ * `--`-prefixed system prompt cannot turn the front of the `-p` value into
30
+ * a flag.
31
+ * - **schema** — the matrix places Gemini in the "via prompt+validate" tier
32
+ * (no native `--output-schema` equivalent, unlike Codex — so no temp-file
33
+ * plumbing here), so the JSON Schema is passed through the prompt: a
34
+ * directive matching the engine's wording (`step-work.ts`
35
+ * `buildUnitPrompt`) is appended to the `-p` payload, and
36
+ * `--output-format json` is emitted so stdout is the documented JSON
37
+ * envelope the gemini result extractor normalizes. The engine's shared
38
+ * retry-until-valid loop performs the actual validation.
39
+ * - **tools** — a string/array tool policy maps to repeated
40
+ * `--allowed-tools <t>` flags (Gemini's run-without-confirmation
41
+ * allowlist). A *structured* policy object is NOT expressible as Gemini
42
+ * flags; it is deliberately dropped without widening to an auto-approve
43
+ * flag (never silently widen a restriction). With no policy at all,
44
+ * NOTHING is emitted — the matrix's headless shape is the bare
45
+ * `gemini -p "<p>"`; autonomy flags (`--yolo`, `--approval-mode`) belong in
46
+ * `profile.args` where the operator opts in explicitly.
47
+ *
48
+ * NOT registered anywhere: `builders.ts` / `harnesses/index.ts` wiring is a
49
+ * follow-up integration task. Exported standalone so that task only adds a
50
+ * registry entry.
51
+ */
52
+ import { assertNotFlag } from "../../agent/builder-shared.js";
53
+ import { resolveModel } from "../../agent/model-aliases.js";
54
+ /** Canonical harness/platform id used for model-alias resolution. */
55
+ export const GEMINI_PLATFORM = "gemini";
56
+ /**
57
+ * Split a tool policy into individual tool names for `--allowed-tools`.
58
+ * Strings are comma-separated lists; arrays are taken as-is. Structured
59
+ * policy objects return `undefined` (not expressible as Gemini flags — see
60
+ * module doc).
61
+ */
62
+ function toolPolicyEntries(tools) {
63
+ if (typeof tools === "string") {
64
+ return tools
65
+ .split(",")
66
+ .map((t) => t.trim())
67
+ .filter(Boolean);
68
+ }
69
+ if (Array.isArray(tools)) {
70
+ return tools.map((t) => t.trim()).filter(Boolean);
71
+ }
72
+ return undefined;
73
+ }
74
+ /**
75
+ * Assemble the `-p` payload: optional system prompt, the task prompt, and —
76
+ * when a schema is requested — the same schema directive the workflow
77
+ * engine's prompt assembly uses, so both dispatch paths speak one dialect.
78
+ */
79
+ function buildPromptPayload(req) {
80
+ const sections = [];
81
+ if (req.systemPrompt)
82
+ sections.push(req.systemPrompt);
83
+ sections.push(req.prompt);
84
+ if (req.schema) {
85
+ sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):\n${JSON.stringify(req.schema)}`);
86
+ }
87
+ return sections.join("\n\n");
88
+ }
89
+ /**
90
+ * Gemini CLI builder.
91
+ * Command shape:
92
+ * gemini [--model <m>] [--allowed-tools <t> ...]
93
+ * [--output-format json] -p "<systemPrompt?\n\nprompt\n\nschema?>"
94
+ */
95
+ export const geminiBuilder = {
96
+ platform: GEMINI_PLATFORM,
97
+ build(profile, req) {
98
+ assertNotFlag(req.systemPrompt, "systemPrompt");
99
+ assertNotFlag(req.model, "model");
100
+ const args = [...profile.args];
101
+ if (req.model) {
102
+ const resolved = resolveModel(req.model, GEMINI_PLATFORM, profile.modelAliases, profile.globalModelAliases);
103
+ args.push("--model", resolved);
104
+ }
105
+ if (req.tools) {
106
+ // Structured policy objects (entries === undefined) emit NO flags:
107
+ // dropping a restriction must never widen to auto-approval.
108
+ for (const tool of toolPolicyEntries(req.tools) ?? []) {
109
+ assertNotFlag(tool, "tools entry");
110
+ args.push("--allowed-tools", tool);
111
+ }
112
+ }
113
+ if (req.schema) {
114
+ // Structured unit: ask for the documented JSON envelope so the result
115
+ // extractor can pull the final message + session id deterministically.
116
+ args.push("--output-format", "json");
117
+ }
118
+ args.push("-p", buildPromptPayload(req));
119
+ return { argv: [profile.bin, ...args] };
120
+ },
121
+ };
@@ -0,0 +1,60 @@
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
+ * Gemini CLI harness (P2 integration, plan §"The adapter contract").
6
+ *
7
+ * Per-harness barrel gathering the Gemini CLI integration surfaces:
8
+ * - agent command builder → ./agent-builder.ts (geminiBuilder)
9
+ * - result extractor → ./result-extractor.ts (geminiResultExtractor)
10
+ *
11
+ * It also defines {@link GeminiHarness}, the {@link AkmHarness} descriptor
12
+ * that `HARNESS_REGISTRY` registers. Dispatch-only: no native session-log
13
+ * reader or config importer yet.
14
+ */
15
+ import { BaseHarness } from "../types.js";
16
+ import { geminiBuilder } from "./agent-builder.js";
17
+ import { geminiResultExtractor } from "./result-extractor.js";
18
+ export { GEMINI_PLATFORM, geminiBuilder } from "./agent-builder.js";
19
+ export { geminiResultExtractor } from "./result-extractor.js";
20
+ function caps(c) {
21
+ return {
22
+ sessionLogs: false,
23
+ agentDispatch: false,
24
+ detection: false,
25
+ configImport: false,
26
+ runtimeIdentity: false,
27
+ v1Migration: false,
28
+ ...c,
29
+ };
30
+ }
31
+ /**
32
+ * Gemini CLI.
33
+ *
34
+ * Canonical id is `'gemini'`; no alias or distinct runtime identity.
35
+ */
36
+ export class GeminiHarness extends BaseHarness {
37
+ id = "gemini";
38
+ displayName = "Gemini CLI";
39
+ aliases = [];
40
+ agentBuilder = geminiBuilder;
41
+ resultExtractor = geminiResultExtractor;
42
+ // ── Workflow-engine descriptor (plan §"Capability matrix", P2) ────────────
43
+ // akm spawns the `gemini` CLI locally per unit ⇒ local-runner.
44
+ pattern = "local-runner";
45
+ // `--output-format json` emits a documented JSON envelope akm parses, then
46
+ // validates against the node schema ⇒ native-json tier.
47
+ structuredOutput = "native-json";
48
+ // `gemini --resume <id>` replays a previous session.
49
+ resume = { flag: "--resume", takesSessionId: true };
50
+ // The matrix's identity marker: Gemini CLI stamps GEMINI_CLI=1 only on
51
+ // processes it spawns, so it genuinely means "running under gemini" (it is
52
+ // not a user-profile config var) — but its VALUE ("1") is a bare flag, not
53
+ // a session id, so it is registered as `presenceEnv` (harness inference
54
+ // only), never `identityEnv` (whose values persist as agent_session_id).
55
+ presenceEnv = ["GEMINI_CLI"];
56
+ capabilities = caps({
57
+ agentDispatch: true,
58
+ detection: true,
59
+ });
60
+ }