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,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
+ function isRecord(value) {
5
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6
+ }
7
+ /**
8
+ * Keys that may carry the final answer, in precedence order. `response` is
9
+ * Gemini's documented `--output-format json` envelope key.
10
+ */
11
+ const TEXT_KEYS = ["response", "result", "text", "output", "content", "message"];
12
+ /** Keys that may carry the harness-native session id, in precedence order. */
13
+ const SESSION_KEYS = ["session_id", "sessionId", "conversation_id", "conversationId", "chat_id", "chatId"];
14
+ /**
15
+ * Coerce a candidate value into text. Handles the shapes Gemini nests
16
+ * answers in: bare strings, `{content|text}` wrappers (assistant message
17
+ * objects), and arrays of `{type:"text",text}` content blocks (Gemini API
18
+ * `parts`-style lists). Depth-bounded: JSON.parse output is acyclic, but
19
+ * nesting is capped anyway so a pathological envelope cannot recurse
20
+ * unboundedly.
21
+ */
22
+ function textOf(value, depth = 0) {
23
+ if (depth > 4)
24
+ return undefined;
25
+ if (typeof value === "string")
26
+ return value;
27
+ if (Array.isArray(value)) {
28
+ const parts = [];
29
+ for (const block of value) {
30
+ const t = textOf(block, depth + 1);
31
+ if (t)
32
+ parts.push(t);
33
+ }
34
+ return parts.length > 0 ? parts.join("\n") : undefined;
35
+ }
36
+ if (isRecord(value)) {
37
+ return textOf(value.content ?? value.text, depth + 1);
38
+ }
39
+ return undefined;
40
+ }
41
+ /** Extract the final-answer text from one parsed JSON value, if any. */
42
+ function extractText(value) {
43
+ if (typeof value === "string")
44
+ return value;
45
+ if (!isRecord(value))
46
+ return undefined;
47
+ for (const key of TEXT_KEYS) {
48
+ if (!(key in value))
49
+ continue;
50
+ const text = textOf(value[key]);
51
+ if (text !== undefined)
52
+ return text;
53
+ }
54
+ return undefined;
55
+ }
56
+ /** Extract a harness-native session id from one parsed JSON value, if any. */
57
+ function extractSessionId(value) {
58
+ if (!isRecord(value))
59
+ return undefined;
60
+ for (const key of SESSION_KEYS) {
61
+ const candidate = value[key];
62
+ if (typeof candidate === "string" && candidate.length > 0)
63
+ return candidate;
64
+ }
65
+ return undefined;
66
+ }
67
+ /** JSON.parse that returns undefined instead of throwing. */
68
+ function tryParseJson(raw) {
69
+ try {
70
+ return JSON.parse(raw);
71
+ }
72
+ catch {
73
+ return undefined;
74
+ }
75
+ }
76
+ /**
77
+ * Normalize a raw gemini run result into `{ text, sessionId? }`.
78
+ * See the module doc for the three stdout shapes handled.
79
+ */
80
+ export const geminiResultExtractor = (result) => {
81
+ // The raw result's own sessionId (SDK-style paths) is the fallback; an id
82
+ // found in the output stream wins because it is fresher.
83
+ const fallbackSessionId = result.sessionId;
84
+ const raw = result.stdout.trim();
85
+ // Shape 1 — whole stdout is one JSON document (spawn may have pre-parsed
86
+ // it when the profile requested parseOutput: "json").
87
+ const whole = result.parsed !== undefined ? result.parsed : raw.length > 0 ? tryParseJson(raw) : undefined;
88
+ if (whole !== undefined) {
89
+ const sessionId = extractSessionId(whole) ?? fallbackSessionId;
90
+ // Unknown envelope (no recognized text key — includes the error-only
91
+ // variant): fall back to raw stdout so downstream embedded-JSON parsing
92
+ // and failure handling still have the full material to work with.
93
+ const text = extractText(whole) ?? raw;
94
+ return { text, ...(sessionId ? { sessionId } : {}) };
95
+ }
96
+ // Shape 2 — JSONL event stream: last text-bearing event wins; first
97
+ // session-id-bearing event supplies the id. Non-JSON lines are banner
98
+ // noise and are skipped.
99
+ let lastText;
100
+ let streamSessionId;
101
+ let sawJsonLine = false;
102
+ for (const line of raw.split("\n")) {
103
+ const trimmed = line.trim();
104
+ if (trimmed.length === 0)
105
+ continue;
106
+ const event = tryParseJson(trimmed);
107
+ if (event === undefined)
108
+ continue;
109
+ sawJsonLine = true;
110
+ streamSessionId ??= extractSessionId(event);
111
+ const text = extractText(event);
112
+ if (text !== undefined)
113
+ lastText = text;
114
+ }
115
+ if (sawJsonLine) {
116
+ const sessionId = streamSessionId ?? fallbackSessionId;
117
+ return { text: lastText ?? raw, ...(sessionId ? { sessionId } : {}) };
118
+ }
119
+ // Shape 3 — plain text passthrough.
120
+ return { text: raw, ...(fallbackSessionId ? { sessionId: fallbackSessionId } : {}) };
121
+ };
@@ -17,9 +17,22 @@
17
17
  * harness in #563/#564; this step only owns ids + capability membership and
18
18
  * wires the existing call sites to consult it (behaviour-preserving).
19
19
  */
20
+ import { AiderHarness } from "./aider/index.js";
21
+ import { AmazonqHarness } from "./amazonq/index.js";
20
22
  import { ClaudeHarness } from "./claude/index.js";
23
+ import { CodexHarness } from "./codex/index.js";
24
+ import { CopilotHarness } from "./copilot/index.js";
25
+ import { GeminiHarness } from "./gemini/index.js";
21
26
  import { OpencodeHarness } from "./opencode/index.js";
22
- import { OpencodeSdkHarness } from "./opencode-sdk/index.js";
27
+ // Import the descriptor from its LEAF module, not the per-harness barrel: the
28
+ // barrel re-exports `./sdk-runner` (which imports `core/config`, and
29
+ // `core/config/config-types` derives `VALID_HARNESS_IDS` back from this file).
30
+ // Importing the class through the barrel would form an initialization cycle
31
+ // that throws a TDZ error when the barrel is the first module loaded in a fresh
32
+ // graph (see ./opencode-sdk/harness.ts). This keeps the registry a config-leaf.
33
+ import { OpencodeSdkHarness } from "./opencode-sdk/harness.js";
34
+ import { OpenhandsHarness } from "./openhands/index.js";
35
+ import { PiHarness } from "./pi/index.js";
23
36
  // Each harness descriptor (ClaudeHarness, OpencodeHarness, OpencodeSdkHarness)
24
37
  // lives in its own per-harness directory alongside that harness's session-log
25
38
  // reader, agent builder, config importer, and/or SDK runner (#563/#564). They
@@ -33,13 +46,22 @@ import { OpencodeSdkHarness } from "./opencode-sdk/index.js";
33
46
  * `z.enum(...)`, and the `platform` union all need the literal types.
34
47
  */
35
48
  // Order is significant: VALID_HARNESS_IDS derives from this array and feeds the
36
- // committed JSON-schema enum order. Kept as [opencode, claude, opencode-sdk] to
37
- // match the pre-unification VALID_HARNESS_IDS so the generated schema does not
38
- // drift (behaviour-preserving, #562).
49
+ // committed JSON-schema enum order. The original [opencode, claude,
50
+ // opencode-sdk] prefix is preserved so the pre-unification portion of the
51
+ // generated schema enum does not reorder (#562); the seven P2 harness adapters
52
+ // (plan §"Capability matrix") are appended after it, which extends the enum
53
+ // additively (schemas/akm-config.json is regenerated in lockstep).
39
54
  export const HARNESS_REGISTRY = Object.freeze([
40
55
  new OpencodeHarness(),
41
56
  new ClaudeHarness(),
42
57
  new OpencodeSdkHarness(),
58
+ new CodexHarness(),
59
+ new CopilotHarness(),
60
+ new PiHarness(),
61
+ new GeminiHarness(),
62
+ new AiderHarness(),
63
+ new AmazonqHarness(),
64
+ new OpenhandsHarness(),
43
65
  ]);
44
66
  /** Lookup by canonical id. */
45
67
  export const HARNESS_BY_ID = new Map(HARNESS_REGISTRY.map((h) => [h.id, h]));
@@ -60,9 +82,8 @@ const HARNESS_BY_ANY_ID = (() => {
60
82
  })();
61
83
  /**
62
84
  * Canonical, ordered list of valid harness / platform ids. The Zod
63
- * `AgentPlatformSchema` enum, the `AgentProfileConfigV2` platform union,
64
- * `parseAgentProfilesMapV2`'s membership check, and setup's `DetectedHarness`
65
- * union all derive from this so they cannot drift.
85
+ * `AgentPlatformSchema` enum, the `AgentProfileConfig` platform union, and
86
+ * setup's `DetectedHarness` union all derive from this so they cannot drift.
66
87
  */
67
88
  export const VALID_HARNESS_IDS = Object.freeze(HARNESS_REGISTRY.map((h) => h.id));
68
89
  /** Harnesses that expose readable native session logs. */
@@ -33,7 +33,7 @@ export const opencodeBuilder = {
33
33
  args.push("--system-prompt", req.systemPrompt);
34
34
  }
35
35
  if (req.model) {
36
- const resolved = resolveModel(req.model, "opencode", profile.modelAliases);
36
+ const resolved = resolveModel(req.model, "opencode", profile.modelAliases, profile.globalModelAliases);
37
37
  args.push("--model", resolved);
38
38
  }
39
39
  args.push("--");
@@ -1,23 +1,9 @@
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
- * OpenCode harness (#564).
6
- *
7
- * Per-harness barrel that gathers the OpenCode integration surfaces previously
8
- * scattered across the codebase:
9
- * - session-log reader → ./session-log.ts (OpenCodeProvider)
10
- * - agent command builder → ./agent-builder.ts (opencodeBuilder)
11
- * - config importer → ./config-import.ts (openCodeImporter)
12
- *
13
- * It also defines {@link OpencodeHarness}, the {@link AkmHarness} descriptor
14
- * that `HARNESS_REGISTRY` registers.
15
- *
16
- * id normalization: OpenCode's canonical id (`'opencode'`) is also its runtime
17
- * identity and session-log provider name — there is no historical split (unlike
18
- * Claude Code's 'claude' vs 'claude-code'), so no alias bridge is needed.
19
- */
20
4
  import { BaseHarness } from "../types.js";
5
+ import { opencodeBuilder } from "./agent-builder.js";
6
+ import { OpenCodeProvider } from "./session-log.js";
21
7
  export { opencodeBuilder } from "./agent-builder.js";
22
8
  export { openCodeImporter } from "./config-import.js";
23
9
  export { OpenCodeProvider } from "./session-log.js";
@@ -48,6 +34,21 @@ export class OpencodeHarness extends BaseHarness {
48
34
  // `v1ProfilePlatform()` resolves most-specific-id-first, so "opencode-sdk-*"
49
35
  // is claimed by OpencodeSdkHarness before this prefix can over-match it.
50
36
  v1ProfilePrefixes = ["opencode"];
37
+ agentBuilder = opencodeBuilder;
38
+ // ── Workflow-engine descriptor (plan §"Capability matrix", P2) ────────────
39
+ // This entry is the CLI spawn path (`opencode run …`): akm launches the
40
+ // harness locally per unit ⇒ local-runner. (The SDK path is the separate
41
+ // `opencode-sdk` harness.)
42
+ pattern = "local-runner";
43
+ // The CLI path emits plain text — no JSON stream akm consumes — so the
44
+ // engine uses the prompt-injected schema + embedded-JSON extraction tier
45
+ // (the matrix's "via prompt+validate"). The SDK entry is native-json.
46
+ structuredOutput = "none";
47
+ // `opencode run --session <id>` continues a previous session.
48
+ resume = { flag: "--session", takesSessionId: true };
49
+ // Session-id env marker for run attribution.
50
+ identityEnv = ["OPENCODE_SESSION_ID"];
51
+ sessionLogProvider = () => new OpenCodeProvider();
51
52
  capabilities = caps({
52
53
  sessionLogs: true,
53
54
  agentDispatch: true,
@@ -4,6 +4,7 @@
4
4
  import fs from "node:fs";
5
5
  import os from "node:os";
6
6
  import path from "node:path";
7
+ import { openDatabase } from "../../../storage/database.js";
7
8
  import { extractInlineRefMentions } from "../../session-logs/inline-refs.js";
8
9
  function getOpenCodeBaseDir() {
9
10
  if (process.platform === "darwin") {
@@ -12,20 +13,49 @@ function getOpenCodeBaseDir() {
12
13
  return path.join(os.homedir(), ".local", "share", "opencode");
13
14
  }
14
15
  /**
15
- * Opencode storage layout (observed 2026-05):
16
- * <base>/storage/session/<projectId>/<sessionId>.json — metadata
17
- * <base>/storage/message/<sessionId>/<messageId>.json one per message
16
+ * Opencode storage layouts:
17
+ *
18
+ * SQLite (current, observed 2026-06): `<base>/opencode.db` a Drizzle-managed
19
+ * database with `session` / `message` / `part` tables. Message text lives in
20
+ * `part` rows (`data` JSON, `type: "text"`); `message.data` holds role/timing.
21
+ * This is the layout current opencode builds write; it is preferred whenever
22
+ * `opencode.db` exists.
23
+ *
24
+ * JSON files (legacy, observed 2026-05): `<base>/storage/session/<projectId>/
25
+ * <sessionId>.json` (metadata) + `<base>/storage/message/<sessionId>/
26
+ * <messageId>.json` (one per message). Read only when `opencode.db` is absent.
18
27
  *
19
28
  * Older builds wrote logs directly into `<base>/log/` and `<base>/*.log`;
20
29
  * those are still scanned by {@link OpenCodeProvider.readEvents} for
21
30
  * backward compatibility with the existing failure-pattern aggregator.
22
31
  */
32
+ /** Filename of opencode's SQLite session store, relative to its base dir. */
33
+ const OPENCODE_DB_FILENAME = "opencode.db";
23
34
  export class OpenCodeProvider {
24
35
  name = "opencode";
25
36
  #baseDir = getOpenCodeBaseDir();
26
37
  isAvailable() {
27
38
  return fs.existsSync(this.#baseDir);
28
39
  }
40
+ /** Absolute path to opencode's SQLite store under `base`. */
41
+ #dbPath(base) {
42
+ return path.join(base, OPENCODE_DB_FILENAME);
43
+ }
44
+ /**
45
+ * Directories/files opencode writes session data under. Returns the base dir
46
+ * when the SQLite store (`opencode.db`) exists, the legacy JSON session root
47
+ * (`<base>/storage/session`) when present, or both during a migration overlap.
48
+ * Empty when neither exists. See {@link SessionLogHarness.watchRoots}.
49
+ */
50
+ watchRoots() {
51
+ const roots = [];
52
+ if (fs.existsSync(this.#dbPath(this.#baseDir)))
53
+ roots.push(this.#baseDir);
54
+ const sessionRoot = path.join(this.#baseDir, "storage", "session");
55
+ if (fs.existsSync(sessionRoot))
56
+ roots.push(sessionRoot);
57
+ return roots;
58
+ }
29
59
  *readEvents(input) {
30
60
  // Legacy behavior: stream raw log lines from the top-level dir and `log/`
31
61
  // subdirectory. Kept to keep `getExecutionLogCandidates` working without
@@ -82,6 +112,9 @@ export class OpenCodeProvider {
82
112
  listSessions(input = {}) {
83
113
  const base = input.location ?? this.#baseDir;
84
114
  const sinceMs = input.sinceMs ?? 0;
115
+ const dbPath = this.#dbPath(base);
116
+ if (fs.existsSync(dbPath))
117
+ return this.#listSessionsFromDb(dbPath, sinceMs);
85
118
  const sessionRoot = path.join(base, "storage", "session");
86
119
  if (!fs.existsSync(sessionRoot))
87
120
  return [];
@@ -142,6 +175,8 @@ export class OpenCodeProvider {
142
175
  return summaries.sort((a, b) => (b.endedAt ?? 0) - (a.endedAt ?? 0));
143
176
  }
144
177
  readSession(ref) {
178
+ if (path.basename(ref.filePath) === OPENCODE_DB_FILENAME)
179
+ return this.#readSessionFromDb(ref);
145
180
  let meta = {};
146
181
  try {
147
182
  meta = JSON.parse(fs.readFileSync(ref.filePath, "utf8"));
@@ -199,6 +234,141 @@ export class OpenCodeProvider {
199
234
  inlineRefs,
200
235
  };
201
236
  }
237
+ /**
238
+ * List sessions from the SQLite store. `filePath` on each summary is the
239
+ * `opencode.db` path so {@link readSession} can route back to the DB reader.
240
+ * Returns `[]` (never throws) when the DB is unreadable or lacks the expected
241
+ * schema — callers treat a missing harness as "no sessions".
242
+ */
243
+ #listSessionsFromDb(dbPath, sinceMs) {
244
+ let db;
245
+ try {
246
+ db = openDatabase(dbPath, { readonly: true, create: false });
247
+ }
248
+ catch {
249
+ return [];
250
+ }
251
+ try {
252
+ const rows = db
253
+ .prepare("SELECT id, title, directory, time_created, time_updated FROM session WHERE time_updated >= ? ORDER BY time_updated DESC")
254
+ .all(sinceMs);
255
+ return rows.map((r) => {
256
+ const startedAt = typeof r.time_created === "number" ? r.time_created : undefined;
257
+ const endedAt = typeof r.time_updated === "number" ? r.time_updated : undefined;
258
+ const title = typeof r.title === "string" && r.title.length > 0 ? r.title : undefined;
259
+ const projectHint = typeof r.directory === "string" && r.directory.length > 0 ? r.directory : undefined;
260
+ return {
261
+ harness: this.name,
262
+ sessionId: r.id,
263
+ filePath: dbPath,
264
+ ...(startedAt !== undefined ? { startedAt } : {}),
265
+ ...(endedAt !== undefined ? { endedAt } : {}),
266
+ ...(projectHint ? { projectHint } : {}),
267
+ ...(title ? { title } : {}),
268
+ };
269
+ });
270
+ }
271
+ catch {
272
+ // Missing `session` table / unexpected schema — treat as no sessions.
273
+ return [];
274
+ }
275
+ finally {
276
+ db.close();
277
+ }
278
+ }
279
+ /**
280
+ * Read one session from the SQLite store. Message text lives in `part` rows
281
+ * (`type: "text"`); `message.data` carries role + timing. One event per
282
+ * message, text-parts concatenated in time order. Returns empty events
283
+ * (never throws) when the DB is unreadable.
284
+ */
285
+ #readSessionFromDb(ref) {
286
+ const emptyRef = { harness: this.name, sessionId: ref.sessionId, filePath: ref.filePath };
287
+ let db;
288
+ try {
289
+ db = openDatabase(ref.filePath, { readonly: true, create: false });
290
+ }
291
+ catch {
292
+ return { ref: emptyRef, events: [], inlineRefs: [] };
293
+ }
294
+ try {
295
+ const meta = db
296
+ .prepare("SELECT title, directory, time_created, time_updated FROM session WHERE id = ?")
297
+ .get(ref.sessionId);
298
+ const startedAt = typeof meta?.time_created === "number" ? meta.time_created : undefined;
299
+ const endedAt = typeof meta?.time_updated === "number" ? meta.time_updated : undefined;
300
+ const title = typeof meta?.title === "string" && meta.title.length > 0 ? meta.title : undefined;
301
+ const projectHint = typeof meta?.directory === "string" && meta.directory.length > 0 ? meta.directory : undefined;
302
+ const messages = db
303
+ .prepare("SELECT id, data, time_created FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC")
304
+ .all(ref.sessionId);
305
+ const parts = db
306
+ .prepare("SELECT message_id, data FROM part WHERE session_id = ? ORDER BY time_created ASC, id ASC")
307
+ .all(ref.sessionId);
308
+ // Group text-part bodies by their parent message.
309
+ const textByMessage = new Map();
310
+ for (const part of parts) {
311
+ let parsed;
312
+ try {
313
+ parsed = JSON.parse(part.data);
314
+ }
315
+ catch {
316
+ continue;
317
+ }
318
+ if (parsed?.type !== "text")
319
+ continue;
320
+ const text = parsed.text;
321
+ if (typeof text !== "string" || text.length < 1)
322
+ continue;
323
+ const bucket = textByMessage.get(part.message_id) ?? [];
324
+ bucket.push(text);
325
+ textByMessage.set(part.message_id, bucket);
326
+ }
327
+ const events = [];
328
+ const inlineRefs = [];
329
+ for (const message of messages) {
330
+ let mdata = {};
331
+ try {
332
+ mdata = JSON.parse(message.data);
333
+ }
334
+ catch {
335
+ // role/timing unavailable — fall through with defaults
336
+ }
337
+ const role = typeof mdata.role === "string" ? mdata.role : "unknown";
338
+ const mtime = mdata.time?.created;
339
+ const ts = typeof mtime === "number"
340
+ ? mtime
341
+ : typeof message.time_created === "number"
342
+ ? message.time_created
343
+ : undefined;
344
+ const text = (textByMessage.get(message.id) ?? []).join("\n").trim();
345
+ if (text.length < 1)
346
+ continue;
347
+ events.push({ harness: this.name, text, ts, sessionId: ref.sessionId, role, filePath: ref.filePath });
348
+ inlineRefs.push(...extractInlineRefMentions(text, ts));
349
+ }
350
+ events.sort((a, b) => (a.ts ?? 0) - (b.ts ?? 0));
351
+ return {
352
+ ref: {
353
+ harness: this.name,
354
+ sessionId: ref.sessionId,
355
+ filePath: ref.filePath,
356
+ ...(startedAt !== undefined ? { startedAt } : {}),
357
+ ...(endedAt !== undefined ? { endedAt } : {}),
358
+ ...(projectHint ? { projectHint } : {}),
359
+ ...(title ? { title } : {}),
360
+ },
361
+ events,
362
+ inlineRefs,
363
+ };
364
+ }
365
+ catch {
366
+ return { ref: emptyRef, events: [], inlineRefs: [] };
367
+ }
368
+ finally {
369
+ db.close();
370
+ }
371
+ }
202
372
  /**
203
373
  * Derive opencode base dir from a session metadata file path so a caller
204
374
  * passing a custom `--location` can still find the message dir.
@@ -0,0 +1,65 @@
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
+ * OpenCode SDK harness DESCRIPTOR (#564).
6
+ *
7
+ * This module is a dependency-graph LEAF: it imports only the harness base
8
+ * types (`../types`) and nothing from `core/config` or the SDK runner. Keeping
9
+ * the descriptor separate from the runtime runner (`./sdk-runner`, which pulls
10
+ * `core/config`) is load-bearing: `HARNESS_REGISTRY` in `../index.ts` imports
11
+ * this class from HERE, not from the per-harness barrel (`./index.ts`). The
12
+ * barrel additionally re-exports `runOpencodeSdk`/`closeServer` from
13
+ * `./sdk-runner`; that re-export makes the barrel transitively depend on
14
+ * `core/config`, and `core/config/config-types` derives `VALID_HARNESS_IDS`
15
+ * back from `../index.ts`. If the registry imported the class through the
16
+ * barrel, that cycle would evaluate `../index.ts` (and `new
17
+ * OpencodeSdkHarness()`) while the barrel — and hence this class binding — was
18
+ * still initializing, throwing a temporal-dead-zone "Cannot access
19
+ * 'OpencodeSdkHarness' before initialization" whenever the barrel is the first
20
+ * module loaded in a fresh graph (e.g. the workflow-exec subprocess entry).
21
+ * Importing the descriptor from this leaf keeps the registry a config-leaf and
22
+ * breaks the cycle.
23
+ */
24
+ import { BaseHarness } from "../types.js";
25
+ function caps(c) {
26
+ return {
27
+ sessionLogs: false,
28
+ agentDispatch: false,
29
+ detection: false,
30
+ configImport: false,
31
+ runtimeIdentity: false,
32
+ v1Migration: false,
33
+ ...c,
34
+ };
35
+ }
36
+ /**
37
+ * OpenCode SDK (embedded-SDK dispatch path).
38
+ *
39
+ * Dispatch-only: no native session logs, but detected at setup and migrated
40
+ * from v1 profile names.
41
+ */
42
+ export class OpencodeSdkHarness extends BaseHarness {
43
+ id = "opencode-sdk";
44
+ displayName = "OpenCode SDK";
45
+ aliases = [];
46
+ // Decorated v1 profile names like "opencode-sdk-fast" belong to the SDK path.
47
+ v1ProfilePrefixes = ["opencode-sdk"];
48
+ // ── Workflow-engine descriptor (plan §"Capability matrix", P2) ────────────
49
+ // Embedded-SDK dispatch on this machine ⇒ local-runner (the matrix's
50
+ // "local (sdk/cli)" row, SDK half).
51
+ pattern = "local-runner";
52
+ // `session.prompt` returns structured SDK events/messages; akm extracts the
53
+ // final message then validates against the node schema ⇒ native-json tier.
54
+ structuredOutput = "native-json";
55
+ // No `resume` flag: session reuse is programmatic — the SDK session id is
56
+ // stored opportunistically on the unit row and passed back to
57
+ // `session.prompt`, not replayed via a CLI flag.
58
+ // No `identityEnv`: the SDK runs in-process; it does not mark a child
59
+ // process environment with a session id of its own.
60
+ capabilities = caps({
61
+ agentDispatch: true,
62
+ detection: true,
63
+ v1Migration: true,
64
+ });
65
+ }
@@ -5,10 +5,15 @@
5
5
  * OpenCode SDK harness (#564).
6
6
  *
7
7
  * Per-harness barrel for the SDK-mode dispatch path:
8
- * - agent runner → ./sdk-runner.ts (runOpencodeSdk / runAgentSdk)
8
+ * - descriptor → ./harness.ts ({@link OpencodeSdkHarness}, the
9
+ * {@link AkmHarness} that `HARNESS_REGISTRY` registers)
10
+ * - agent runner → ./sdk-runner.ts (runOpencodeSdk)
9
11
  *
10
- * It also defines {@link OpencodeSdkHarness}, the {@link AkmHarness} descriptor
11
- * that `HARNESS_REGISTRY` registers.
12
+ * The descriptor lives in its own leaf module (`./harness.ts`) rather than
13
+ * here so that the registry can import the class WITHOUT pulling in
14
+ * `./sdk-runner` (and its `core/config` dependency) — see the header of
15
+ * `./harness.ts` for the temporal-dead-zone cycle this avoids. This barrel is
16
+ * the runtime entry point that re-exports both.
12
17
  *
13
18
  * Unlike the CLI harnesses, the SDK path has no native session logs of its own
14
19
  * (`capabilities.sessionLogs = false`): it dispatches via the embedded
@@ -16,34 +21,5 @@
16
21
  * session files. It is still detected at setup and migrated from v1 profile
17
22
  * names. Canonical id is `'opencode-sdk'` with no alias.
18
23
  */
19
- import { BaseHarness } from "../types.js";
20
- export { closeServer, runAgentSdk, runOpencodeSdk } from "./sdk-runner.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
- * OpenCode SDK (embedded-SDK dispatch path).
34
- *
35
- * Dispatch-only: no native session logs, but detected at setup and migrated
36
- * from v1 profile names.
37
- */
38
- export class OpencodeSdkHarness extends BaseHarness {
39
- id = "opencode-sdk";
40
- displayName = "OpenCode SDK";
41
- aliases = [];
42
- // Decorated v1 profile names like "opencode-sdk-fast" belong to the SDK path.
43
- v1ProfilePrefixes = ["opencode-sdk"];
44
- capabilities = caps({
45
- agentDispatch: true,
46
- detection: true,
47
- v1Migration: true,
48
- });
49
- }
24
+ export { OpencodeSdkHarness } from "./harness.js";
25
+ export { closeServer, runOpencodeSdk } from "./sdk-runner.js";