akm-cli 0.9.31 → 0.10.26101002-alpha

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 (236) hide show
  1. package/CHANGELOG.md +265 -0
  2. package/STABILITY.md +79 -53
  3. package/dist/api-node.mjs +20 -0
  4. package/dist/api.d.ts +23 -0
  5. package/dist/api.js +45 -0
  6. package/dist/assets/hints/cli-hints-full.md +13 -27
  7. package/dist/assets/hints/cli-hints-short.md +1 -1
  8. package/dist/assets/improve-strategies/default.json +3 -3
  9. package/dist/assets/prompts/consolidate-pair.md +9 -7
  10. package/dist/cli/shared.js +31 -48
  11. package/dist/cli/unknown-flags.js +6 -43
  12. package/dist/cli.js +8 -34
  13. package/dist/commands/agent/contribute-cli.js +1 -1
  14. package/dist/commands/completions.js +1 -2
  15. package/dist/commands/config-cli.js +5 -28
  16. package/dist/commands/env/env-cli.js +5 -5
  17. package/dist/commands/env/secret-cli.js +2 -2
  18. package/dist/commands/health/checks.js +41 -16
  19. package/dist/commands/health/plugin-staleness.js +52 -22
  20. package/dist/commands/improve/autonomy-gate.js +5 -3
  21. package/dist/commands/improve/consolidate/pair-pass.js +7 -1
  22. package/dist/commands/improve/consolidate.js +6 -35
  23. package/dist/commands/improve/distill/lesson-update.js +91 -0
  24. package/dist/commands/improve/distill-guards.js +1 -43
  25. package/dist/commands/improve/distill.js +140 -20
  26. package/dist/commands/improve/eligibility.js +14 -1
  27. package/dist/commands/improve/extract-cli.js +1 -1
  28. package/dist/commands/improve/improve-cli.js +87 -102
  29. package/dist/commands/improve/improve-strategies.js +8 -12
  30. package/dist/commands/improve/improve.js +2 -2
  31. package/dist/commands/improve/loop-stages.js +0 -1
  32. package/dist/commands/improve/planner.js +0 -1
  33. package/dist/commands/improve/preparation.js +40 -99
  34. package/dist/commands/improve/proactive-maintenance.js +2 -2
  35. package/dist/commands/improve/reflect-noise.js +3 -55
  36. package/dist/commands/improve/reflect.js +3 -8
  37. package/dist/commands/improve/retrieval-scope.js +2 -2
  38. package/dist/commands/improve/salience.js +2 -9
  39. package/dist/commands/improve/stage.js +14 -9
  40. package/dist/commands/lint/index.js +5 -20
  41. package/dist/commands/observability-cli.js +3 -9
  42. package/dist/commands/proposal/drain.js +39 -6
  43. package/dist/commands/proposal/proposal-cli.js +11 -31
  44. package/dist/commands/proposal/repository.js +3 -3
  45. package/dist/commands/read/knowledge.js +3 -3
  46. package/dist/commands/read/remember-cli.js +0 -13
  47. package/dist/commands/read/search-cli.js +29 -97
  48. package/dist/commands/read/search.js +0 -11
  49. package/dist/commands/read/show.js +0 -19
  50. package/dist/commands/sources/plugin-upgrade.js +164 -101
  51. package/dist/commands/sources/sources-cli.js +1 -15
  52. package/dist/commands/sources/stash-cli.js +4 -12
  53. package/dist/commands/tasks/tasks-cli.js +4 -115
  54. package/dist/commands/workflow/plan.js +11 -33
  55. package/dist/commands/workflow-cli.js +2 -7
  56. package/dist/core/adapter/adapter-ids.js +1 -2
  57. package/dist/core/adapter/adapters/agent-skills-adapter.js +0 -4
  58. package/dist/core/adapter/adapters/akm-adapter.js +9 -48
  59. package/dist/core/adapter/adapters/akm-lint.js +10 -26
  60. package/dist/core/adapter/adapters/akm-metadata.js +2 -72
  61. package/dist/core/adapter/adapters/akm-task-adapter.js +0 -5
  62. package/dist/core/adapter/adapters/akm-workflow-adapter.js +9 -28
  63. package/dist/core/adapter/adapters/dotenv-adapter.js +1 -20
  64. package/dist/core/adapter/adapters/generic-files-adapter.js +0 -10
  65. package/dist/core/adapter/adapters/llm-wiki-adapter.js +0 -4
  66. package/dist/core/adapter/adapters/tool-dir-shared.js +0 -24
  67. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -4
  68. package/dist/core/adapter/recognize-match.js +3 -4
  69. package/dist/core/common.js +18 -2
  70. package/dist/core/config/config-schema.js +12 -15
  71. package/dist/core/config/config-types.js +6 -15
  72. package/dist/core/config/config-walker.js +6 -23
  73. package/dist/core/config/config.js +17 -80
  74. package/dist/core/config/engine-semantics.js +7 -3
  75. package/dist/core/config/schema/engines.js +7 -7
  76. package/dist/core/config/schema/improve-processes.js +8 -61
  77. package/dist/core/config/schema/improve.js +2 -21
  78. package/dist/core/config/schema/index-config.js +6 -39
  79. package/dist/core/env-secret-ref.js +2 -45
  80. package/dist/core/errors.js +1 -2
  81. package/dist/core/extra-params.js +2 -86
  82. package/dist/core/improve-result.js +11 -1
  83. package/dist/core/mutation-target.js +2 -2
  84. package/dist/core/recognition-util.js +4 -5
  85. package/dist/core/warn.js +21 -4
  86. package/dist/core/write-source.js +3 -3
  87. package/dist/execution/target-ref.js +1 -2
  88. package/dist/indexer/search/db-search.js +4 -19
  89. package/dist/indexer/search/fts-query.js +0 -19
  90. package/dist/integrations/agent/engine-resolution.js +5 -2
  91. package/dist/integrations/agent/index.js +1 -1
  92. package/dist/integrations/agent/profiles.js +41 -98
  93. package/dist/integrations/agent/request-lowering.js +3 -3
  94. package/dist/integrations/harnesses/aider/index.js +5 -0
  95. package/dist/integrations/harnesses/amazonq/index.js +1 -0
  96. package/dist/integrations/harnesses/claude/config-import.js +2 -3
  97. package/dist/integrations/harnesses/claude/index.js +5 -0
  98. package/dist/integrations/harnesses/codex/index.js +1 -0
  99. package/dist/integrations/harnesses/copilot/index.js +1 -0
  100. package/dist/integrations/harnesses/gemini/index.js +1 -0
  101. package/dist/integrations/harnesses/index.js +18 -39
  102. package/dist/integrations/harnesses/opencode/agent-builder.js +60 -35
  103. package/dist/integrations/harnesses/opencode/config-import.js +121 -52
  104. package/dist/integrations/harnesses/opencode/index.js +22 -0
  105. package/dist/integrations/harnesses/opencode/plugin-layout.js +68 -0
  106. package/dist/integrations/harnesses/opencode/session-log-types.js +12 -0
  107. package/dist/integrations/harnesses/opencode/session-log-v1.js +72 -0
  108. package/dist/integrations/harnesses/opencode/session-log-v2.js +140 -0
  109. package/dist/integrations/harnesses/opencode/session-log.js +104 -115
  110. package/dist/integrations/harnesses/opencode/version.js +98 -0
  111. package/dist/integrations/harnesses/opencode-sdk/{harness.js → index.js} +5 -17
  112. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +105 -206
  113. package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +199 -0
  114. package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +228 -0
  115. package/dist/integrations/harnesses/opencode-sdk/wire.js +66 -0
  116. package/dist/integrations/harnesses/openhands/index.js +1 -0
  117. package/dist/integrations/harnesses/pi/index.js +1 -0
  118. package/dist/integrations/harnesses/shared.js +2 -0
  119. package/dist/integrations/harnesses/types.js +2 -0
  120. package/dist/llm/client.js +41 -11
  121. package/dist/output/cli-hints.js +1 -1
  122. package/dist/output/context.js +10 -19
  123. package/dist/output/format-exempt.js +5 -8
  124. package/dist/output/shapes/helpers.js +1 -22
  125. package/dist/output/shapes/passthrough.js +0 -1
  126. package/dist/output/shapes.js +3 -31
  127. package/dist/output/stdout.js +5 -1
  128. package/dist/output/text/command-format.js +6 -1
  129. package/dist/output/text/workflow-format.js +4 -22
  130. package/dist/scripts/akm-migrate-node.js +13049 -14013
  131. package/dist/scripts/akm-migrate.js +16316 -17276
  132. package/dist/setup/detect.js +10 -4
  133. package/dist/setup/harness-config-import.js +5 -14
  134. package/dist/setup/setup.js +1 -1
  135. package/dist/setup/steps/tasks.js +12 -13
  136. package/dist/storage/repositories/task-history-repository.js +0 -5
  137. package/dist/storage/repositories/workflow-runs-repository.js +5 -15
  138. package/dist/tasks/embedded.js +2 -1
  139. package/dist/tasks/run/task-history.js +0 -2
  140. package/dist/tasks/schedule-gates.js +39 -0
  141. package/dist/tasks/scheduler-binding.js +0 -16
  142. package/dist/tasks/scheduler-sync.js +3 -97
  143. package/dist/tasks/source/bounded-document.js +1 -1
  144. package/dist/tasks/source/task-source-v4.js +2 -12
  145. package/dist/tasks/task-run-reserved-flags.js +2 -31
  146. package/dist/workflows/authoring/authoring.js +6 -6
  147. package/dist/workflows/compile.js +8 -65
  148. package/dist/workflows/exec/child-workflow.js +22 -3
  149. package/dist/workflows/exec/native-executor.js +12 -147
  150. package/dist/workflows/exec/run-workflow.js +31 -103
  151. package/dist/workflows/exec/step-work.js +9 -178
  152. package/dist/workflows/exec/unit-dispatch.js +0 -10
  153. package/dist/workflows/freeze/environment.js +3 -44
  154. package/dist/workflows/freeze/freeze.js +8 -41
  155. package/dist/workflows/freeze/targets/child-workflow.js +27 -63
  156. package/dist/workflows/freeze/targets/command.js +2 -16
  157. package/dist/workflows/freeze/targets/shell.js +0 -2
  158. package/dist/workflows/freeze/task-bindings.js +2 -28
  159. package/dist/workflows/ir/params.js +12 -2
  160. package/dist/workflows/parser.js +82 -232
  161. package/dist/workflows/plan.js +1 -1
  162. package/dist/workflows/renderer.js +10 -19
  163. package/dist/workflows/runtime/run-plan.js +11 -53
  164. package/dist/workflows/runtime/runs.js +4 -27
  165. package/dist/workflows/source-files.js +12 -16
  166. package/dist/workflows/source-semantics.js +1 -93
  167. package/docs/README.md +1 -1
  168. package/docs/agents/README.md +3 -3
  169. package/docs/agents/agent-install.md +1 -1
  170. package/docs/architecture/adapters.md +17 -31
  171. package/docs/architecture/architecture.md +4 -5
  172. package/docs/architecture/improvement.md +52 -21
  173. package/docs/architecture/internals/improve-workflow.md +15 -8
  174. package/docs/architecture/internals/indexing.md +1 -1
  175. package/docs/architecture/internals/search.md +1 -2
  176. package/docs/architecture/internals/storage-locations.md +5 -5
  177. package/docs/architecture/persisted-data-compat.md +13 -4
  178. package/docs/architecture/specs/0.9.0-decisions.md +6 -2
  179. package/docs/architecture/specs/improve-collapse-churn-detector-design.md +2 -2
  180. package/docs/architecture/specs/workflow-format-unification.md +1 -6
  181. package/docs/architecture/testing/manual-testing-checklist.md +20 -29
  182. package/docs/architecture/testing/task-workflow-manual-tests.md +106 -203
  183. package/docs/architecture/testing/testing-workflow.md +1 -1
  184. package/docs/architecture/workflow-engine.md +5 -56
  185. package/docs/guides/author-workflows.md +39 -69
  186. package/docs/guides/capture-knowledge.md +1 -1
  187. package/docs/guides/claude-code-vs-akm-workflows.md +1 -2
  188. package/docs/guides/discover-and-load.md +4 -4
  189. package/docs/guides/getting-started.md +1 -1
  190. package/docs/guides/improve-the-library.md +7 -7
  191. package/docs/guides/recipes/headless-install.md +2 -2
  192. package/docs/guides/run-workflows.md +1 -1
  193. package/docs/guides/use-with-any-agent.md +49 -4
  194. package/docs/integration/bundling-akm.md +7 -6
  195. package/docs/maintainers/curate-workmap.md +1 -2
  196. package/docs/maintainers/release-checklist.md +30 -1
  197. package/docs/posts/akm-command-tour.md +3 -3
  198. package/docs/product-surface.md +1 -1
  199. package/docs/reference/README.md +1 -0
  200. package/docs/reference/api.md +65 -0
  201. package/docs/reference/asset-types.md +3 -5
  202. package/docs/reference/bundle-types.md +2 -4
  203. package/docs/reference/cli.md +129 -171
  204. package/docs/reference/configuration.md +84 -19
  205. package/docs/reference/data-and-telemetry.md +1 -1
  206. package/docs/reference/env-and-secrets.md +2 -2
  207. package/docs/reference/supported-formats.md +3 -4
  208. package/docs/reference/tasks.md +12 -19
  209. package/docs/reference/website-sources.md +1 -1
  210. package/docs/reference/workflow-schema.md +89 -317
  211. package/docs/reference/workflows.md +20 -48
  212. package/package.json +12 -2
  213. package/schemas/akm-config.json +2 -243
  214. package/schemas/akm-task.json +2 -3
  215. package/schemas/akm-workflow.json +47 -84
  216. package/dist/assets/improve-strategies/catchup.json +0 -41
  217. package/dist/assets/improve-strategies/proactive-maintenance.json +0 -24
  218. package/dist/assets/improve-strategies/quick.json +0 -17
  219. package/dist/assets/improve-strategies/reflect-distill.json +0 -29
  220. package/dist/assets/improve-strategies/thorough.json +0 -49
  221. package/dist/assets/tasks/improve/akm-improve-catchup.yml +0 -6
  222. package/dist/assets/tasks/improve/akm-improve-frequent.yml +0 -4
  223. package/dist/assets/tasks/improve/akm-improve-nightly.yml +0 -4
  224. package/dist/cli/retired-commands.js +0 -118
  225. package/dist/commands/tasks/validate.js +0 -176
  226. package/dist/core/config/legacy-source-shape-shim.js +0 -117
  227. package/dist/integrations/harnesses/ids.js +0 -28
  228. package/dist/tasks/source/task-source-v3-frozen.js +0 -424
  229. package/dist/tasks/source/task-to-v4.js +0 -863
  230. package/dist/workflows/exec/worktree.js +0 -372
  231. package/dist/workflows/freeze/child-output-references.js +0 -83
  232. package/dist/workflows/freeze/identity.js +0 -22
  233. package/dist/workflows/freeze/targets/script.js +0 -50
  234. package/dist/workflows/freeze/targets/task.js +0 -124
  235. package/dist/workflows/github-yaml.js +0 -506
  236. package/dist/workflows/runtime/run-outputs.js +0 -80
@@ -1,176 +0,0 @@
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
- * `akm task validate <path>` (#907) — parse ONE task file by filesystem
6
- * path, not a concept ref/id, and report the same diagnostic `akm task
7
- * sync` would produce for it. The file need not live in any configured
8
- * bundle: unlike every other `akm task` subcommand, this one never resolves
9
- * a bundle/adapter/concept id at all — it reads exactly the path it was
10
- * given and classifies it.
11
- *
12
- * Reuses the exact version router `parseTaskSource`
13
- * (`src/tasks/source/parse-task-source.ts`) every other task-source reader
14
- * uses (`akm task sync`'s `compileTaskSources` included) — this module never
15
- * forks a second parser. `readBoundedTaskSourceYaml` /
16
- * `peekTaskSourceVersion` / `own` are the SAME front-end helpers the router
17
- * calls first; they are used here only to recover the file's DECLARED schema
18
- * version for the report and to tell `blocked` from `invalid`.
19
- *
20
- * Beyond parsing, this module also runs the SAME two per-source gates
21
- * `akm task sync`'s `compileTaskSources` runs before it ever installs a
22
- * schedule — `assertTaskScheduleInputsSatisfyContract` and
23
- * `assertTaskScheduleCronValid` (both extracted from `scheduler-sync.ts` for
24
- * exactly this reuse) — so a file `sync` would reject can never
25
- * be reported `valid` here. Cron dialect is checked against
26
- * `backendNameForPlatform()`, the same platform default `sync` falls back
27
- * to whenever it has no injected/native-inspected backend to hand (see
28
- * `akmTasksAdd`, `src/commands/tasks/tasks.ts`); a bare file was never
29
- * installed anywhere; there is no native scheduler state to inspect for it.
30
- *
31
- * Deliberately DOES NOT call `prepareTaskV3Execution` (the function
32
- * `compileTaskSources` calls between those two gates) or resolve an
33
- * execution engine: that path resolves a composed command/persona ref
34
- * against the local index and lowers the task's cascade-composed
35
- * engine/model — both of which assume a real, indexed bundle and a
36
- * configured engine. A bare file passed to `validate` has neither, so
37
- * running that step would make an otherwise-valid command-kind task report
38
- * `invalid` on any machine with no engine configured. `resolved`
39
- * is therefore the compiled task shape `sync` itself would build a
40
- * scheduler binding from — id, the compiled v4 `version`, `target`
41
- * (`uses`/`run`), the declared `inputs` contract, and `schedule` bindings —
42
- * never an execution-lowered plan.
43
- *
44
- * Outcome classification (mirrors `parse-task-source.ts`'s own routing
45
- * table in its header, extended for the two gates above):
46
- * - `valid` — parses as task source v4 and passes both sync gates.
47
- * - `blocked` — declared `version: 2` or `3`, or a `version: 4`
48
- * document still carrying the retired
49
- * `schedule[].enabled`: what `akm migrate apply`
50
- * rewrites. The runtime reads only v4 (#987), so the
51
- * reason names that command.
52
- * - `invalid` — the document declares SOME version (`4`, or anything
53
- * other than 2/3/4) but fails to parse/validate, OR it
54
- * parsed but fails one of the two sync gates above, OR
55
- * the YAML itself does not parse at all (a genuine
56
- * syntax error, not merely a non-task shape) — reported
57
- * with the parser's own reason.
58
- * - `not-a-task` — the document parses as YAML but never declares a
59
- * `version:` field at all (or isn't a YAML mapping) —
60
- * the strongest signal available that the file was
61
- * never intended as a task source in the first place.
62
- */
63
- import fs from "node:fs";
64
- import path from "node:path";
65
- import { UsageError } from "../../core/errors.js";
66
- import { backendNameForPlatform } from "../../tasks/backends/index.js";
67
- import { assertTaskScheduleCronValid, assertTaskScheduleInputsSatisfyContract } from "../../tasks/scheduler-sync.js";
68
- import { own, readBoundedTaskSourceYaml } from "../../tasks/source/bounded-document.js";
69
- import { parseTaskSource, peekTaskSourceVersion, v4ScheduleHasRetiredEnabledKey, } from "../../tasks/source/parse-task-source.js";
70
- /** True when `root` is a YAML mapping that itself declares a `version:` key, regardless of that key's type/value. */
71
- function declaresVersionKey(root) {
72
- return root !== null && typeof root === "object" && !Array.isArray(root) && own(root, "version");
73
- }
74
- function buildResolved(id, v4) {
75
- return {
76
- id,
77
- version: v4.version,
78
- ...(v4.name !== undefined ? { name: v4.name } : {}),
79
- ...(v4.description !== undefined ? { description: v4.description } : {}),
80
- target: v4.target,
81
- inputs: v4.inputs ?? {},
82
- schedule: v4.schedule,
83
- };
84
- }
85
- export async function akmTaskValidate(filePath) {
86
- const resolvedPath = path.resolve(filePath);
87
- let stat;
88
- try {
89
- stat = fs.statSync(resolvedPath);
90
- }
91
- catch {
92
- throw new UsageError(`Task file not found: ${JSON.stringify(filePath)}.`, "INVALID_FLAG_VALUE");
93
- }
94
- if (!stat.isFile()) {
95
- throw new UsageError(`${JSON.stringify(filePath)} is not a regular file.`, "INVALID_FLAG_VALUE");
96
- }
97
- let yaml;
98
- try {
99
- yaml = fs.readFileSync(resolvedPath, "utf8");
100
- }
101
- catch (cause) {
102
- throw new UsageError(`Task file ${JSON.stringify(filePath)} could not be read: ${cause instanceof Error ? cause.message : String(cause)}`, "INVALID_FLAG_VALUE");
103
- }
104
- // Peek the declared version BEFORE the real parse, using the identical
105
- // bounded YAML front end `parseTaskSource` calls internally — never a
106
- // second/looser YAML reader. A front-end failure here (unparseable YAML,
107
- // not a mapping, exceeds a resource bound) means the document itself does
108
- // not parse at all — tracked as `peekFailed` so that case reports
109
- // `invalid`, never `not-a-task` (`not-a-task` is reserved for
110
- // YAML that DOES parse but never declared a task shape). The real parse
111
- // below throws the identical error either way, so nothing is lost by
112
- // swallowing it here.
113
- let root;
114
- let peekFailed = false;
115
- try {
116
- root = readBoundedTaskSourceYaml({ yaml, filePath: resolvedPath }, { sourceLabel: "task source" }).root;
117
- }
118
- catch {
119
- peekFailed = true;
120
- }
121
- const declaredVersion = peekFailed ? undefined : peekTaskSourceVersion(root);
122
- const hasVersionKey = !peekFailed && declaresVersionKey(root);
123
- const workspaceRoot = path.dirname(resolvedPath);
124
- const backend = backendNameForPlatform();
125
- let parsed;
126
- try {
127
- parsed = parseTaskSource({ yaml, filePath: resolvedPath, workspaceRoot });
128
- }
129
- catch (cause) {
130
- if (!(cause instanceof UsageError))
131
- throw cause;
132
- const reason = cause.message;
133
- // What `akm migrate apply` rewrites is the only refusal for these
134
- // shapes (`parse-task-source.ts`), so no message-text sniffing is needed.
135
- if (declaredVersion === 2 ||
136
- declaredVersion === 3 ||
137
- (declaredVersion === 4 && v4ScheduleHasRetiredEnabledKey(root))) {
138
- return { ok: false, path: resolvedPath, sourceVersion: declaredVersion, outcome: "blocked", reason };
139
- }
140
- if (peekFailed) {
141
- return { ok: false, path: resolvedPath, outcome: "invalid", reason };
142
- }
143
- if (!hasVersionKey) {
144
- return { ok: false, path: resolvedPath, outcome: "not-a-task", reason };
145
- }
146
- return {
147
- ok: false,
148
- path: resolvedPath,
149
- ...(declaredVersion !== undefined ? { sourceVersion: declaredVersion } : {}),
150
- outcome: "invalid",
151
- reason,
152
- };
153
- }
154
- // Success is unreachable from any path that leaves `declaredVersion`
155
- // undefined — the router requires a numeric version 4 to reach here.
156
- const sourceVersion = declaredVersion ?? 4;
157
- // The document itself parsed — now the two gates `compileTaskSources`
158
- // runs before accepting it. A violation here is `invalid`.
159
- try {
160
- assertTaskScheduleInputsSatisfyContract(parsed.v4, resolvedPath);
161
- assertTaskScheduleCronValid(parsed.v4, backend);
162
- }
163
- catch (cause) {
164
- if (!(cause instanceof UsageError))
165
- throw cause;
166
- return { ok: false, path: resolvedPath, sourceVersion, outcome: "invalid", reason: cause.message };
167
- }
168
- const id = path.parse(resolvedPath).name;
169
- return {
170
- ok: true,
171
- path: resolvedPath,
172
- sourceVersion,
173
- outcome: "valid",
174
- resolved: buildResolved(id, parsed.v4),
175
- };
176
- }
@@ -1,117 +0,0 @@
1
- import path from "node:path";
2
- import { isBundleSlug } from "../asset/asset-ref.js";
3
- import { warnOnce } from "../warn.js";
4
- function isPlainRecord(value) {
5
- return typeof value === "object" && value !== null && !Array.isArray(value);
6
- }
7
- const DEFAULT_WRITABLE_BY_TYPE = {
8
- filesystem: true,
9
- git: false,
10
- website: false,
11
- npm: false,
12
- };
13
- function bundleFromLegacySource(entry, index) {
14
- if (!isPlainRecord(entry))
15
- return undefined;
16
- const type = typeof entry.type === "string" ? entry.type : undefined;
17
- const bundle = {};
18
- switch (type) {
19
- case "filesystem":
20
- if (typeof entry.path !== "string" || !entry.path)
21
- return undefined;
22
- bundle.path = entry.path;
23
- break;
24
- case "git":
25
- if (typeof entry.url !== "string" || !entry.url)
26
- return undefined;
27
- bundle.git = entry.url;
28
- break;
29
- case "website":
30
- if (typeof entry.url !== "string" || !entry.url)
31
- return undefined;
32
- bundle.website = { url: entry.url };
33
- break;
34
- case "npm": {
35
- const spec = typeof entry.url === "string" && entry.url ? entry.url : entry.path;
36
- if (typeof spec !== "string" || !spec)
37
- return undefined;
38
- bundle.npm = spec;
39
- break;
40
- }
41
- default:
42
- return undefined;
43
- }
44
- const writable = typeof entry.writable === "boolean" ? entry.writable : DEFAULT_WRITABLE_BY_TYPE[type ?? ""];
45
- if (writable !== undefined)
46
- bundle.writable = writable;
47
- if (typeof entry.enabled === "boolean")
48
- bundle.enabled = entry.enabled;
49
- const name = typeof entry.name === "string" ? entry.name : undefined;
50
- const key = name && isBundleSlug(name) ? name : `source-${index + 1}`;
51
- return [key, bundle];
52
- }
53
- function filesystemLocator(bundle) {
54
- if (!isPlainRecord(bundle) || typeof bundle.path !== "string" || bundle.path.length === 0)
55
- return undefined;
56
- return path.resolve(bundle.path);
57
- }
58
- /**
59
- * Pure legacy `stashDir`/`sources[]`/`installed` -> `bundles`/`defaultBundle`
60
- * conversion. Triggers on key *presence* (not on the value being usable), so
61
- * an unusable value — `stashDir: ""`, `sources: []` — is still removed along
62
- * with the rest of the legacy shape; only a usable `stashDir` or `sources[]`
63
- * entry is actually folded into `bundles`. Never warns — see
64
- * {@link migrateLegacySourceShape} for the warn-once wrapper callers use.
65
- */
66
- export function convertLegacySourceShape(raw) {
67
- const hasStashDir = "stashDir" in raw;
68
- const hasSources = "sources" in raw;
69
- const hasInstalled = "installed" in raw && raw.installed !== undefined;
70
- if (!hasStashDir && !hasSources && !hasInstalled)
71
- return { config: raw, converted: [] };
72
- const { stashDir: _stashDir, sources: _sources, installed: _installed, ...rest } = raw;
73
- const bundles = isPlainRecord(rest.bundles) ? { ...rest.bundles } : {};
74
- let defaultBundle = typeof rest.defaultBundle === "string" ? rest.defaultBundle : undefined;
75
- const usableStashDir = typeof raw.stashDir === "string" && raw.stashDir.trim().length > 0;
76
- if (usableStashDir) {
77
- bundles.stash = { path: raw.stashDir, writable: true };
78
- defaultBundle ??= "stash";
79
- }
80
- if (Array.isArray(raw.sources)) {
81
- raw.sources.forEach((entry, index) => {
82
- const converted = bundleFromLegacySource(entry, index);
83
- if (!converted)
84
- return;
85
- const [key, bundle] = converted;
86
- const locator = filesystemLocator(bundle);
87
- if (locator && Object.values(bundles).some((candidate) => filesystemLocator(candidate) === locator))
88
- return;
89
- bundles[key] = bundle;
90
- defaultBundle ??= key;
91
- });
92
- }
93
- const converted = [hasStashDir && "stashDir", hasSources && "sources", hasInstalled && "installed"].filter((key) => typeof key === "string");
94
- // Only add a `bundles` key when there is something to say: either a
95
- // legacy entry actually converted into one, or the config already had a
96
- // `bundles` map (preserved as-is). An unusable `stashDir: ""` / `sources: []`
97
- // with no pre-existing `bundles` should just disappear, not leave behind
98
- // an empty `bundles: {}`.
99
- const hasBundles = Object.keys(bundles).length > 0 || isPlainRecord(rest.bundles);
100
- return {
101
- config: { ...rest, ...(hasBundles ? { bundles } : {}), ...(defaultBundle !== undefined ? { defaultBundle } : {}) },
102
- converted,
103
- };
104
- }
105
- /**
106
- * Warn-once wrapper around {@link convertLegacySourceShape} for the
107
- * in-memory read path: converts the legacy shape and, when it removed
108
- * anything, warns once that `akm migrate apply` will persist the rewrite.
109
- */
110
- export function migrateLegacySourceShape(raw, sourcePath) {
111
- const { config, converted } = convertLegacySourceShape(raw);
112
- if (converted.length === 0)
113
- return config;
114
- const where = sourcePath ? ` at ${sourcePath}` : "";
115
- warnOnce(`legacy-source-shape${sourcePath ? `:${sourcePath}` : ""}`, `Config${where} uses the retired ${converted.join("/")} shape — auto-migrated in memory to \`bundles\`/\`defaultBundle\`. Run \`akm migrate apply\` to rewrite the config file and silence this warning.`);
116
- return config;
117
- }
@@ -1,28 +0,0 @@
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
- export const HARNESS_ID_TABLE = [
5
- { id: "opencode", agentDispatch: true, enforcesModelWorkTools: true, nativeAgentSelector: true },
6
- { id: "claude", agentDispatch: true, enforcesModelWorkTools: true, nativeAgentSelector: true },
7
- { id: "opencode-sdk", agentDispatch: true, enforcesModelWorkTools: true, nativeAgentSelector: true },
8
- { id: "codex", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
9
- { id: "copilot", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
10
- { id: "pi", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
11
- { id: "gemini", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
12
- { id: "aider", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
13
- { id: "amazonq", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
14
- { id: "openhands", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
15
- ];
16
- /**
17
- * Canonical, ordered list of valid harness / platform ids — the
18
- * dependency-free counterpart of `./index.ts`'s `VALID_HARNESS_IDS` (which
19
- * remains the barrel's own derivation for its own consumers). Both are
20
- * asserted equal at `HARNESS_REGISTRY` construction time.
21
- */
22
- export const VALID_HARNESS_IDS = Object.freeze(HARNESS_ID_TABLE.map((h) => h.id));
23
- /** Harness ids whose `capabilities.agentDispatch` is `true`. */
24
- export const HARNESS_AGENT_DISPATCH_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.agentDispatch).map((h) => h.id));
25
- /** Harness ids that confine the model-work tool policy, so unattended model work may run on them. */
26
- export const HARNESS_MODEL_WORK_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.enforcesModelWorkTools).map((h) => h.id));
27
- /** Harness ids that can run a named native agent, so an engine may name a default `agent`. */
28
- export const HARNESS_NATIVE_AGENT_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.nativeAgentSelector).map((h) => h.id));