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
@@ -54,8 +54,7 @@ const allowedTypesField = z.array(z.string().min(1)).optional();
54
54
  const excludeRefPrefixesField = z.array(z.string().min(1)).optional();
55
55
  /**
56
56
  * Consolidate process: hard cap on memories processed per pass.
57
- * Reflect/distill: max refs processed (same as profile-level `limit`).
58
- * proactiveMaintenance: fallback when `maxPerRun` is absent.
57
+ * Reflect: max refs processed (same as profile-level `limit`).
59
58
  */
60
59
  const processLimitField = positiveInt.optional();
61
60
  /**
@@ -90,19 +89,6 @@ const clsField = z
90
89
  })
91
90
  .passthrough()
92
91
  .optional();
93
- /**
94
- * WS-3b: Distill→source fidelity check (step 10). After a distill proposal,
95
- * check it against its cited source memories; a contradiction flag forces
96
- * human review. Default OFF. Distill process only.
97
- */
98
- const fidelityCheckField = z.object({ enabled: z.boolean().optional() }).passthrough().optional();
99
- /**
100
- * #639 — semantic value-floor filter for the `reflect` process. When
101
- * enabled, proposals classified as "low-value" by the deterministic noise
102
- * gate are deferred. DEFAULT OFF (absent / { enabled: false } = pre-#639
103
- * byte-identical behaviour). Reflect process only.
104
- */
105
- const lowValueFilterField = z.object({ enabled: z.boolean().optional() }).passthrough().optional();
106
92
  /**
107
93
  * The wording lists of reflect's pre-judge defect filter (`findReflectDefect`).
108
94
  * Each list is optional: one that is set replaces that rule's default list, and
@@ -152,57 +138,28 @@ const triageJudgmentField = z
152
138
  .union([z.boolean(), triageJudgmentObjectField])
153
139
  .transform((value) => typeof value === "boolean" ? { enabled: value } : { ...value, enabled: value.enabled ?? true })
154
140
  .optional();
155
- /**
156
- * WS-3b: Anti-collapse guard (step 8), consolidate process only: a small
157
- * random (non-similarity-driven) fraction of the pool is mixed into the
158
- * clustered order so consolidation is not purely rich-get-richer. Default ON
159
- * (opt out via `enabled: false`); `randomClusterFraction` defaults to 0.05.
160
- * The retired merge guards (`maxGeneration`, `lexicalDiversityCheck`,
161
- * `mergeInformationFloor`, `minSpecificityRetention`) never refused a merge
162
- * and are tolerated as unknown keys.
163
- */
164
- const antiCollapseField = z
165
- .object({
166
- enabled: z.boolean().optional(),
167
- randomClusterFraction: z.number().min(0).max(1).optional(),
168
- })
169
- .passthrough()
170
- .optional();
171
141
  const REFLECT_PROCESS_FIELDS = {
172
142
  allowedTypes: allowedTypesField,
173
143
  excludeRefPrefixes: excludeRefPrefixesField,
174
144
  limit: processLimitField,
175
145
  qualityGate: qualityGateField,
176
- lowValueFilter: lowValueFilterField,
177
146
  defectFilter: defectFilterField,
178
147
  };
179
148
  const DISTILL_PROCESS_FIELDS = {
180
149
  allowedTypes: allowedTypesField,
181
- limit: processLimitField,
182
150
  qualityGate: qualityGateField,
183
151
  // Skip distill entirely when reflect produced zero planned refs.
184
152
  requirePlannedRefs: z.boolean().optional(),
185
153
  cls: clsField,
186
- fidelityCheck: fidelityCheckField,
187
154
  };
188
155
  const CONSOLIDATE_PROCESS_FIELDS = {
189
156
  allowedTypes: allowedTypesField,
190
157
  limit: processLimitField,
191
- // Minimum eligible-memory pool size below which the consolidation pass skips
192
- // entirely (emits `pool_below_min_size`). 0 disables the guard. Default 500.
193
- minPoolSize: z.number().int().min(0).optional(),
194
158
  maxChunkSize: z.number().int().min(1).max(50).optional(),
195
- // Fallback p90 wall-clock time per consolidation chunk in seconds, used for
196
- // cold-start budget estimation when no telemetry history exists. The actual
197
- // p90 is derived from observed run durations once sufficient history
198
- // accumulates; this value is only used on the very first run. Default 30s.
199
- p90ChunkSecondsDefault: z.number().finite().positive().optional(),
200
- antiCollapse: antiCollapseField,
201
159
  };
202
160
  const MEMORY_INFERENCE_PROCESS_FIELDS = {
203
161
  // Minimum pending memory count to run the pass.
204
162
  minPendingCount: z.number().int().min(0).optional(),
205
- cls: clsField,
206
163
  };
207
164
  const EXTRACT_PROCESS_FIELDS = {
208
165
  defaultSince: z.string().min(1).optional(),
@@ -241,10 +198,8 @@ const TRIAGE_PROCESS_FIELDS = {
241
198
  const PROACTIVE_MAINTENANCE_PROCESS_FIELDS = {
242
199
  // Staleness gate + rotation cooldown in days (default 30).
243
200
  dueDays: z.number().int().min(0).optional(),
244
- // Top-N bound per run (default 25). Alias for `limit`; `maxPerRun` wins
245
- // when both are set.
201
+ // Top-N bound per run (default 15).
246
202
  maxPerRun: positiveInt.optional(),
247
- limit: processLimitField,
248
203
  };
249
204
  /** distill/consolidate are memory-only and never read `excludeRefPrefixes` (reflect only, R12). */
250
205
  function rejectExcludeRefPrefixesOutsideReflect(value, ctx) {
@@ -306,8 +261,10 @@ export const ProactiveMaintenanceProcessConfigSchema = z
306
261
  * "unknown enabled process" check below — an old config must keep loading
307
262
  * (AGENTS.md "Reading persisted data"). `graphExtraction`: the LLM
308
263
  * entity-graph extraction it ran was retired in 0.9.17-alpha.9.
264
+ * `feedbackDistillation`: a wrapper of `processes.distill.enabled`, removed in
265
+ * 0.8.0.
309
266
  */
310
- const RETIRED_PROCESS_NAMES = new Set(["graphExtraction"]);
267
+ const RETIRED_PROCESS_NAMES = new Set(["graphExtraction", "feedbackDistillation"]);
311
268
  const ImproveProfileProcessesSchema = z
312
269
  .object({
313
270
  reflect: ReflectProcessConfigSchema.optional(),
@@ -321,19 +278,9 @@ const ImproveProfileProcessesSchema = z
321
278
  })
322
279
  .passthrough()
323
280
  .superRefine((val, ctx) => {
324
- // 0.8.0 removed the duplicated `feedbackDistillation` process key — it was
325
- // a thin wrapper around `processes.distill.enabled`. Keep the migration
326
- // hint so a stale config gets an actionable message rather than silently
327
- // doing nothing. Other unknown process keys remain preserved for
328
- // cross-version compatibility, but an enabled one is rejected below because
329
- // this version cannot execute it.
330
- if ("feedbackDistillation" in val) {
331
- ctx.addIssue({
332
- code: z.ZodIssueCode.custom,
333
- message: "feedbackDistillation was removed in 0.8.0 — use processes.distill.enabled instead. " +
334
- "It now controls both the orchestration gate and the LLM-call gate.",
335
- });
336
- }
281
+ // Unknown process keys remain preserved for cross-version compatibility,
282
+ // but an enabled one is rejected below because this version cannot
283
+ // execute it.
337
284
  for (const [name, process] of Object.entries(val)) {
338
285
  if (!IMPROVE_PROCESS_NAMES.includes(name) &&
339
286
  !RETIRED_PROCESS_NAMES.has(name) &&
@@ -3,33 +3,14 @@
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
5
  * Top-level `improve` config section (salience, state GC, strategies). Retired
6
- * keys (`salience.replayBudget`, `collapseDetector`, `utilityDecay`) are
6
+ * keys (`salience.replayBudget`, `salienceThreshold`, `collapseDetector`, `utilityDecay`) are
7
7
  * tolerated as unknown keys.
8
8
  */
9
9
  import { z } from "zod";
10
10
  import { ImproveProfileConfigSchema } from "./improve-processes.js";
11
11
  import { engineName, nonNegativeNumber } from "./primitives.js";
12
12
  // ── Improve top-level (event retention, salience, state GC) ────────────────
13
- const ImproveSalienceSchema = z
14
- .object({
15
- /**
16
- * WS-2 Part-V gate: enable the outcome-weight term in the salience projection.
17
- * Default TRUE/absent (DEFAULT ON since the G2 saturation cap landed — see
18
- * salience.ts): uses the WS-2 weights (w_e=0.25, w_o=0.15, w_r=0.60) so the
19
- * prediction-error outcome signal shapes rankScore (the R1 loop-closure).
20
- * Set to `false` to opt out and restore the WS-1 parity weights
21
- * (w_e=0.30, w_r=0.70, w_o=0); the `outcome` sub-score is still computed
22
- * and stored for observability in that mode.
23
- */
24
- outcomeWeightEnabled: z.boolean().optional(),
25
- /**
26
- * Minimum encoding salience score [0, 1] for a zero-feedback asset to be
27
- * admitted to the high-salience improve lane (#608).
28
- * Default 0.75. Set to 1.0 to disable the lane entirely.
29
- */
30
- salienceThreshold: z.number().min(0).max(1).optional(),
31
- })
32
- .passthrough();
13
+ const ImproveSalienceSchema = z.object({}).passthrough();
33
14
  // #733 — orphan-GC pass (Workstream C, lean by design: one config gate).
34
15
  // The pass ALWAYS runs and ALWAYS reports counts (via the `asset_state_gc`
35
16
  // event); this gate controls ONLY whether it actually deletes rows whose
@@ -7,40 +7,14 @@
7
7
  * change.
8
8
  */
9
9
  import { z } from "zod";
10
- import { warnOnce } from "../../warn.js";
11
10
  import { engineName, LlmInvocationOverridesSchema, nonEmptyString, positiveInt } from "./primitives.js";
12
11
  // ── Index / per-pass ────────────────────────────────────────────────────────
13
- const INDEX_PASS_RETIRED_KEYS = new Set([
14
- "endpoint",
15
- "provider",
16
- "apiKey",
17
- "baseUrl",
18
- "temperature",
19
- "maxTokens",
20
- "capabilities",
21
- ]);
22
12
  /**
23
- * Per-pass `index.<pass>` entry. The preprocess names and drops the retired
24
- * engine settings above with a targeted message. Any other unknown key is kept
25
- * and named once by the config loader's schema walk, like an unknown key
26
- * anywhere else in config.
13
+ * Per-pass `index.<pass>` entry. Unknown keys (including inline engine
14
+ * settings an earlier release carried) are kept and named by the config
15
+ * loader's schema walk like any other unknown key.
27
16
  */
28
- export const IndexPassConfigSchema = z.preprocess((raw, ctx) => {
29
- if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
30
- return raw; // let z.object below produce the type error
31
- }
32
- const obj = raw;
33
- let cleaned;
34
- for (const key of Object.keys(obj)) {
35
- const dotted = [...(ctx.path ?? []), key].join(".");
36
- if (INDEX_PASS_RETIRED_KEYS.has(key)) {
37
- warnOnce(`index-pass:retired:${dotted}`, `\`${dotted}\` is a retired engine setting and is ignored; select a named engine and use typed invocation fields instead.`);
38
- cleaned ??= { ...obj };
39
- delete cleaned[key];
40
- }
41
- }
42
- return cleaned ?? raw;
43
- }, z
17
+ export const IndexPassConfigSchema = z
44
18
  .object({
45
19
  engine: engineName.optional(),
46
20
  model: nonEmptyString.optional(),
@@ -48,7 +22,7 @@ export const IndexPassConfigSchema = z.preprocess((raw, ctx) => {
48
22
  enabled: z.boolean().optional(),
49
23
  llm: LlmInvocationOverridesSchema.optional(),
50
24
  })
51
- .passthrough());
25
+ .passthrough();
52
26
  const IndexDefaultsSchema = z
53
27
  .object({
54
28
  engine: engineName.optional(),
@@ -80,14 +54,7 @@ const IndexConfigRuntimeSchema = z.preprocess((raw, ctx) => {
80
54
  }
81
55
  if (typeof raw !== "object")
82
56
  return raw;
83
- let cleaned;
84
57
  for (const [passName, value] of Object.entries(raw)) {
85
- if (passName === "stalenessDetection") {
86
- warnOnce("index:stalenessDetection", "`index.stalenessDetection` is a retired pass and is ignored.");
87
- cleaned ??= { ...raw };
88
- delete cleaned.stalenessDetection;
89
- continue;
90
- }
91
58
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
92
59
  ctx.addIssue({
93
60
  code: z.ZodIssueCode.custom,
@@ -96,7 +63,7 @@ const IndexConfigRuntimeSchema = z.preprocess((raw, ctx) => {
96
63
  return raw;
97
64
  }
98
65
  }
99
- return cleaned ?? raw;
66
+ return raw;
100
67
  }, z
101
68
  .object({
102
69
  defaults: IndexDefaultsSchema.optional(),
@@ -70,50 +70,11 @@ export function listEnvsRecursive(listKeysFn, config = loadConfig()) {
70
70
  }
71
71
  return result;
72
72
  }
73
- /**
74
- * The `vault` asset type was removed in 0.9.0. The env/secret input path no
75
- * longer routes through the legacy stored-ref parser (which carries the removal
76
- * signpost), so a `vault:`/`vault/` leading token would otherwise be silently
77
- * qualified into an `env/vault:…` not-found. Detect it here and re-emit the
78
- * migration signpost so 0.8→0.9 muscle memory still gets pointed at env/secret.
79
- */
80
- function assertNotRemovedVaultRef(ref) {
81
- const boundary = ref.indexOf("//");
82
- const bare = boundary >= 0 ? ref.slice(boundary + 2) : ref;
83
- if (/^vault[:/]/.test(bare.trim())) {
84
- throw new UsageError("The `vault` asset type was removed in 0.9.0 — use `env/` (whole .env config) or `secrets/` (a single value).", "INVALID_FLAG_VALUE");
85
- }
86
- }
87
- /**
88
- * Q-08 ruling: the pre-0.9.0 `type:name` ref grammar taught `env:<name>` /
89
- * `secret:<name>` (help text and docs also implied `environment:`/`secrets:`
90
- * variants) as the way to address a single env/secret. That grammar is GONE —
91
- * NO alias, no re-acceptance (same rule as the retired `vault:` prefix above).
92
- * Left unchecked, a colon-prefixed ref does not error here at all: it falls
93
- * through to the "bare name" convenience below and gets silently qualified
94
- * into a literal `env/env:name` (or `secrets/secret:name`) file that can never
95
- * exist — a confusing not-found that hides the real mistake instead of naming
96
- * it. Reject it here, loudly, before that happens.
97
- */
98
- function assertNotColonRef(ref, aliases, replacement) {
99
- const boundary = ref.indexOf("//");
100
- const bare = (boundary >= 0 ? ref.slice(boundary + 2) : ref).trim();
101
- const colon = bare.indexOf(":");
102
- if (colon <= 0)
103
- return;
104
- const head = bare.slice(0, colon).toLowerCase();
105
- if (!aliases.includes(head))
106
- return;
107
- const name = bare.slice(colon + 1);
108
- throw new UsageError(`The \`${head}:\` ref spelling was removed in 0.9.0 — use the slash form instead: \`${replacement}${name}\`.`, "INVALID_FLAG_VALUE");
109
- }
110
73
  export function parseEnvRef(ref) {
111
74
  // Accept a bare env name (`prod`, `sub/prod`) or the new-grammar
112
75
  // `[bundle//]env/name` conceptId. A bare name's leading segment maps to no
113
76
  // asset type, so it is qualified with the `env/` conceptId prefix; anything
114
77
  // already a full new-grammar ref is parsed as-is.
115
- assertNotRemovedVaultRef(ref);
116
- assertNotColonRef(ref, ["env", "environment"], "env/");
117
78
  return parseRefInput(isFullRefInput(ref) ? ref : `env/${ref}`);
118
79
  }
119
80
  export function findEnvSource(origin, type, name) {
@@ -152,10 +113,8 @@ export function makeEnvRef(name, source, config = loadConfig()) {
152
113
  }
153
114
  /**
154
115
  * Resolve an env ref to an absolute `.env` path. Accepts the `env/<name>`
155
- * conceptId (or a bare name, auto-qualified into it) — the retired
156
- * `env:`/`environment:` colon spelling is rejected loudly (Q-08), never
157
- * silently resolved. The path is returned even when the file does not yet
158
- * exist (so `create` writes under `env/`).
116
+ * conceptId (or a bare name, auto-qualified into it). The path is returned
117
+ * even when the file does not yet exist (so `create` writes under `env/`).
159
118
  */
160
119
  export function resolveEnvPath(ref) {
161
120
  const parsed = parseEnvRef(ref);
@@ -177,8 +136,6 @@ export function resolveEnvPath(ref) {
177
136
  export function parseSecretRef(ref) {
178
137
  // Same bare-name-vs-full-ref rule as parseEnvRef; a bare name is qualified
179
138
  // with the `secrets/` conceptId prefix (secret's stash subdir).
180
- assertNotRemovedVaultRef(ref);
181
- assertNotColonRef(ref, ["secret", "secrets"], "secrets/");
182
139
  return parseRefInput(isFullRefInput(ref) ? ref : `secrets/${ref}`);
183
140
  }
184
141
  export function makeSecretRef(name, source) {
@@ -38,8 +38,7 @@ const USAGE_HINTS = {
38
38
  INVALID_FLAG_VALUE: "Run `akm <command> --help` to see accepted values.",
39
39
  INVALID_SOURCE_VALUE: "Pick one of: local, registry, all, or a configured source name.",
40
40
  INVALID_FORMAT_VALUE: "Pick one of: json, jsonl, yaml, text, md, html.",
41
- INVALID_DETAIL_VALUE: "Pick one of: brief, normal, full. For agent/summary projections use --shape.",
42
- INVALID_SHAPE_VALUE: "Pick one of: human, agent, summary (summary falls back to agent, with a warning, on commands with no summary projection).",
41
+ INVALID_DETAIL_VALUE: "Pick one of: brief, normal, full, agent.",
43
42
  INVALID_JSON_CONFIG_VALUE: 'Quote JSON values in your shell, for example: akm config set embedding \'{"endpoint":"http://localhost:11434/v1/embeddings","model":"nomic-embed-text"}\'.',
44
43
  MISSING_OR_AMBIGUOUS_TARGET: "Use `akm bundle update --all` or pass a target like `akm bundle update npm:@scope/pkg` (not both).",
45
44
  TARGET_NOT_UPDATABLE: "Run `akm bundle list` to view your sources, then retry with one of those values.",
@@ -1,7 +1,6 @@
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
- import { isRecord } from "./common.js";
5
4
  export const EXTRA_PARAMS_PROTECTED_TOP_LEVEL_KEYS = [
6
5
  "model",
7
6
  "messages",
@@ -31,8 +30,7 @@ const CREDENTIAL_KEYS = new Set(EXTRA_PARAMS_CREDENTIAL_KEYS);
31
30
  // `EXTRA_PARAMS_PROTECTED_TOP_LEVEL_KEYS` rightly stops a provider extra from
32
31
  // shadowing an AKM-managed field, but naming the rule without naming the fix
33
32
  // leaves the reader stuck (#852). Every protected key gets a one-line remedy
34
- // baked into its issue message; keys with a genuine scalar first-class field
35
- // are also eligible for the automatic config-load lift below.
33
+ // baked into its issue message.
36
34
  /** normalizeExtraParamKey(key) -> the first-class engine field it shadows. */
37
35
  const LEGACY_EXTRA_PARAMS_FIELD = {
38
36
  model: "model",
@@ -41,16 +39,7 @@ const LEGACY_EXTRA_PARAMS_FIELD = {
41
39
  enablethinking: "enableThinking",
42
40
  reasoningeffort: "reasoningEffort",
43
41
  };
44
- /**
45
- * Subset of {@link LEGACY_EXTRA_PARAMS_FIELD} that {@link liftLegacyEngineExtraParams}
46
- * will move onto the first-class field automatically. `model` is deliberately
47
- * excluded: unlike the others it was never a "no first-class field yet"
48
- * workaround (`model` has always been required on an LLM engine), so a
49
- * mismatch is far more likely a genuine mistake than a stale 0.9.1 config —
50
- * it stays a hard rejection rather than being silently reinterpreted.
51
- */
52
- const LIFTABLE_EXTRA_PARAMS_KEYS = new Set(["temperature", "maxtokens", "enablethinking", "reasoningeffort"]);
53
- /** Remedies for protected keys with no scalar first-class field to lift onto. */
42
+ /** Remedies for protected keys with no scalar first-class field. */
54
43
  const EXTRA_PARAMS_NO_FIELD_REMEDY = {
55
44
  messages: "AKM builds the request messages internally — remove it from extraParams",
56
45
  responseformat: "AKM controls the response format internally — remove it from extraParams",
@@ -117,76 +106,3 @@ export function formatExtraParamsIssue(label, issue) {
117
106
  const suffix = issue.path.map((part) => (typeof part === "number" ? `[${part}]` : `.${part}`)).join("");
118
107
  return `${label}${suffix} ${issue.message}`;
119
108
  }
120
- /**
121
- * Compute the legacy `extraParams` -> first-class-field lift for a raw
122
- * parsed config object: a 0.9.1-shaped config using (e.g.)
123
- * `extraParams.reasoning_effort` now needs `reasoningEffort` set instead,
124
- * since that field became first-class — and therefore protected — in 0.9.2
125
- * (#852, following #815).
126
- *
127
- * Pure: never touches the filesystem. Two callers use this differently:
128
- * `akm migrate apply` (scripts/akm-migrate/migrate/config-extra-params.ts) uses the
129
- * returned `config` to persist the rewrite to disk, once; `parseAndValidateConfigText`
130
- * (src/core/config/config.ts) calls this only to detect whether a lift is
131
- * needed and discards `config` — an unmigrated config fails closed there
132
- * with a pointer to `akm migrate apply` rather than silently drifting from
133
- * what's on disk. `conflicts` (an extraParams key and its first-class field
134
- * set to different values) is a genuine authoring error in both callers and
135
- * is never auto-resolved.
136
- */
137
- export function liftLegacyEngineExtraParams(raw) {
138
- const lifted = [];
139
- const conflicts = [];
140
- const rawEngines = raw.engines;
141
- if (!isRecord(rawEngines)) {
142
- return { config: raw, lifted, conflicts };
143
- }
144
- const engines = {};
145
- let anyEngineChanged = false;
146
- for (const [name, engineValue] of Object.entries(rawEngines)) {
147
- if (!isRecord(engineValue) || !isRecord(engineValue.extraParams)) {
148
- engines[name] = engineValue;
149
- continue;
150
- }
151
- const engine = { ...engineValue };
152
- const extraParams = { ...engineValue.extraParams };
153
- let engineChanged = false;
154
- for (const [rawKey, value] of Object.entries(engineValue.extraParams)) {
155
- const normalized = normalizeExtraParamKey(rawKey);
156
- if (!LIFTABLE_EXTRA_PARAMS_KEYS.has(normalized))
157
- continue;
158
- const field = LEGACY_EXTRA_PARAMS_FIELD[normalized];
159
- if (!field)
160
- continue;
161
- const existing = engine[field];
162
- if (existing !== undefined && existing !== value) {
163
- conflicts.push({ engine: name, key: rawKey, field, extraParamsValue: value, fieldValue: existing });
164
- continue;
165
- }
166
- delete extraParams[rawKey];
167
- engineChanged = true;
168
- if (existing === value) {
169
- lifted.push(`engines.${name}.extraParams.${rawKey} is redundant — engines.${name}.${field} is already set to the same value; dropped the extraParams entry`);
170
- continue;
171
- }
172
- engine[field] = value;
173
- lifted.push(`engines.${name}.extraParams.${rawKey} -> engines.${name}.${field}`);
174
- }
175
- if (!engineChanged) {
176
- engines[name] = engineValue;
177
- continue;
178
- }
179
- anyEngineChanged = true;
180
- if (Object.keys(extraParams).length > 0) {
181
- engine.extraParams = extraParams;
182
- }
183
- else {
184
- delete engine.extraParams;
185
- }
186
- engines[name] = engine;
187
- }
188
- if (!anyEngineChanged) {
189
- return { config: raw, lifted, conflicts };
190
- }
191
- return { config: { ...raw, engines }, lifted, conflicts };
192
- }
@@ -126,6 +126,8 @@ function validateConsolidationPlan(value) {
126
126
  ]));
127
127
  if (!isRecord(value.configured))
128
128
  fail("plan.consolidation.configured must be an object");
129
+ // `minPoolSize` is no longer written (the minimum-pool guard was removed in 0.10, #1131); runs an
130
+ // older release persisted still carry it, ignored — AGENTS.md "Reading persisted data".
129
131
  requireExactFields(value.configured, new Set(["enabled", "minPoolSize", "limit", "maxChunkSize"]));
130
132
  if (value.configured.enabled !== undefined && typeof value.configured.enabled !== "boolean") {
131
133
  fail("plan.consolidation.configured.enabled must be a boolean");
@@ -140,7 +142,8 @@ function validateConsolidationPlan(value) {
140
142
  requireExactFields(value.effective, new Set(["enabled", "minPoolSize", "limit", "chunkSize"]));
141
143
  if (typeof value.effective.enabled !== "boolean")
142
144
  fail("plan.consolidation.effective.enabled must be a boolean");
143
- requireCount(value.effective, "minPoolSize", "plan.consolidation.effective");
145
+ if (value.effective.minPoolSize !== undefined)
146
+ requireCount(value.effective, "minPoolSize", "plan.consolidation.effective");
144
147
  requireCount(value.effective, "chunkSize", "plan.consolidation.effective");
145
148
  if (value.effective.limit !== undefined && typeof value.effective.limit !== "number") {
146
149
  fail("plan.consolidation.effective.limit must be a number");
@@ -157,6 +160,9 @@ function validateConsolidationPlan(value) {
157
160
  requireExactFields(value.gates, new Set(["profile", "minimumPool", "delta"]));
158
161
  for (const gateName of ["profile", "minimumPool", "delta"]) {
159
162
  const gate = value.gates[gateName];
163
+ // `minimumPool` is no longer written; only an older release's persisted plan has it.
164
+ if (gate === undefined && gateName === "minimumPool")
165
+ continue;
160
166
  if (!isRecord(gate))
161
167
  fail(`plan.consolidation.gates.${gateName} must be an object`);
162
168
  requireExactFields(gate, new Set(["passed", "reason"]));
@@ -171,6 +177,8 @@ function validateProactivePlan(value) {
171
177
  requireExactFields(value, new Set(["configured", "effective", "candidatePool", "dueTotal", "neverReflected", "selected", "selectedRefs"]));
172
178
  if (!isRecord(value.configured))
173
179
  fail("plan.proactive.configured must be an object");
180
+ // `limit` is no longer written (the `proactiveMaintenance.limit` alias of `maxPerRun` was removed in 0.10, #1091);
181
+ // runs an older release stored may carry it.
174
182
  requireExactFields(value.configured, new Set(["dueDays", "maxPerRun", "limit"]));
175
183
  for (const field of ["dueDays", "maxPerRun", "limit"]) {
176
184
  if (value.configured[field] !== undefined && typeof value.configured[field] !== "number") {
@@ -424,6 +432,8 @@ function validateImprovePlan(value, dryRun, plannedRefNames) {
424
432
  }
425
433
  if (!isRecord(value.triage))
426
434
  fail("plan.triage must be an object");
435
+ // `maxDiffLines` is no longer written (the triage config key was dropped before 0.10, #1091); runs an older
436
+ // release stored may carry it.
427
437
  requireExactFields(value.triage, new Set(["enabled", "configuredMode", "mode", "maxAcceptsPerRun", "maxDiffLines"]));
428
438
  if (typeof value.triage.enabled !== "boolean")
429
439
  fail("plan.triage.enabled must be a boolean");
@@ -51,12 +51,12 @@ function resolveExplicitMutationTarget(config, explicitTarget, options) {
51
51
  }
52
52
  }
53
53
  /**
54
- * Reconcile a qualified mutation ref with the explicit target (`--target`, or
54
+ * Reconcile a qualified mutation ref with the explicit target (`--bundle`, or
55
55
  * the `options.flag` the caller's command spells), then resolve the write
56
56
  * destination.
57
57
  */
58
58
  export function resolveMutationTarget(config, ref, explicitTarget, options = {}) {
59
- const flag = options.flag ?? "--target";
59
+ const flag = options.flag ?? "--bundle";
60
60
  const writeOptions = { requireWritable: options.requireWritable, flag };
61
61
  const qualifiedTarget = ref.origin ? resolveBundleWriteTarget(config, ref.origin, writeOptions) : undefined;
62
62
  const explicitResolved = explicitTarget
@@ -34,13 +34,12 @@ export const SCRIPT_EXTENSIONS = new Set([
34
34
  ".kts",
35
35
  ]);
36
36
  /**
37
- * Recognized workflow asset extensions. Markdown remains first-class and the
38
- * strict local GitHub-shaped source adapter adds `.yml` as a peer format.
39
- * `workflows/<name>` refs resolve against this list.
37
+ * Recognized workflow asset extensions. `workflows/<name>` refs resolve against
38
+ * this list.
40
39
  */
41
- export const WORKFLOW_EXTENSIONS = [".md", ".yml"];
40
+ export const WORKFLOW_EXTENSIONS = [".md"];
42
41
  /**
43
- * Strip a recognized workflow extension (`.md` or `.yml`) from a workflow asset
42
+ * Strip the recognized workflow extension (`.md`) from a workflow asset
44
43
  * *name* so `foo` and `foo.md` collapse to one canonical identity — the same
45
44
  * collapse `workflowSpec.toCanonicalName` performs on a resolved file path.
46
45
  * Callers that turn a `workflows/<name>` ref into run identity (the
package/dist/core/warn.js CHANGED
@@ -15,6 +15,8 @@
15
15
  import fs from "node:fs";
16
16
  import path from "node:path";
17
17
  let quiet = false;
18
+ /** Calls inside {@link withQuiet}; counted so overlapping calls cannot leave the flag flipped. */
19
+ let quietScopes = 0;
18
20
  let verbose = false;
19
21
  let logFilePath;
20
22
  let sinkOverride;
@@ -33,7 +35,22 @@ export function resetQuiet() {
33
35
  quiet = false;
34
36
  }
35
37
  export function isQuiet() {
36
- return quiet;
38
+ return quiet || quietScopes > 0;
39
+ }
40
+ /**
41
+ * Run `fn` with stderr diagnostics suppressed (the log file sink still
42
+ * receives them), then restore. For in-process callers (`src/api.ts`) that
43
+ * must stay silent without touching the host's `--quiet` state: a depth count
44
+ * rather than save/restore of the flag keeps overlapping async calls correct.
45
+ */
46
+ export async function withQuiet(fn) {
47
+ quietScopes++;
48
+ try {
49
+ return await fn();
50
+ }
51
+ finally {
52
+ quietScopes--;
53
+ }
37
54
  }
38
55
  /**
39
56
  * Set the verbose flag from a CLI flag. The `AKM_VERBOSE` env var, when set,
@@ -103,7 +120,7 @@ export function info(...args) {
103
120
  return;
104
121
  }
105
122
  appendToLogFile("INFO", args);
106
- if (!quiet) {
123
+ if (!isQuiet()) {
107
124
  console.warn(...args);
108
125
  }
109
126
  }
@@ -118,7 +135,7 @@ export function warn(...args) {
118
135
  return;
119
136
  }
120
137
  appendToLogFile("WARN", args);
121
- if (!quiet) {
138
+ if (!isQuiet()) {
122
139
  console.warn(...args);
123
140
  }
124
141
  }
@@ -148,7 +165,7 @@ export function error(...args) {
148
165
  return;
149
166
  }
150
167
  appendToLogFile("ERROR", args);
151
- if (!quiet) {
168
+ if (!isQuiet()) {
152
169
  console.error(...args);
153
170
  }
154
171
  }
@@ -7,7 +7,7 @@
7
7
  * The only module that branches on `source.kind` for writes. It does two
8
8
  * things:
9
9
  *
10
- * 1. Resolve the destination: `--target` → `defaultWriteTarget` → working
10
+ * 1. Resolve the destination: `--bundle` → `defaultWriteTarget` → working
11
11
  * stash (`defaultBundle`). `writable` defaults to true on `filesystem` and
12
12
  * false on `git`; `website` / `npm` are never writable (the config loader
13
13
  * rejects `writable: true` on them).
@@ -53,7 +53,7 @@ export function isWriteCapableSourceKind(kind) {
53
53
  return kind === "filesystem" || kind === "git";
54
54
  }
55
55
  /**
56
- * Resolve the destination for a write: explicit `--target`, then
56
+ * Resolve the destination for a write: explicit `--bundle`, then
57
57
  * `defaultWriteTarget`, then the working stash (`defaultBundle`). There is no
58
58
  * fallback to the first writable source.
59
59
  */
@@ -61,7 +61,7 @@ export function resolveWriteTarget(akmConfig, explicitTarget, options = {}) {
61
61
  const allConfiguredSources = resolveConfiguredSources(akmConfig);
62
62
  const configuredSources = resolveActiveConfiguredSources(akmConfig);
63
63
  const requireWritable = options.requireWritable !== false;
64
- const flag = options.flag ?? "--target";
64
+ const flag = options.flag ?? "--bundle";
65
65
  if (explicitTarget) {
66
66
  const match = configuredSources.find((s) => s.name === explicitTarget);
67
67
  if (!match) {
@@ -22,8 +22,7 @@
22
22
  *
23
23
  * Explicit non-goals (binding, spec §4.1): no GitHub locator grammar, no
24
24
  * `akm/command` builtin special case, no resolution, no filesystem access, no
25
- * guessing. Callers layer builtin detection on top (see
26
- * `classifyWorkflowStepUses` in src/workflows/source-semantics.ts).
25
+ * guessing.
27
26
  */
28
27
  import { bundleRefToString, parseBundleRef } from "../core/asset/asset-ref.js";
29
28
  import { UsageError } from "../core/errors.js";