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
@@ -5,9 +5,10 @@
5
5
  * Reading a run row's frozen plan: the ONE plan decoder and its tolerant
6
6
  * row-level wrapper.
7
7
  *
8
- * {@link decodeWorkflowPlan} accepts every plan shape a release has stored —
9
- * irVersion 4 and 5 (with their `sourceReadSet` and host-identity fields) as
10
- * well as the current one — and keeps keys it does not know rather than
8
+ * {@link decodeWorkflowPlan} accepts every plan shape a release at or above
9
+ * the 0.9.15 floor has stored — irVersion 5 (with its `sourceReadSet` and
10
+ * host-identity fields, which 0.9.15 and 0.9.16 wrote) as well as the current
11
+ * one — and keeps keys it does not know rather than
11
12
  * refusing them. It rejects only a plan it cannot run: no steps, a unit with
12
13
  * no frozen target, a request that does not decode. `plan_ir_version` and
13
14
  * `plan_hash` are informational columns: neither gates execution. A plan that
@@ -62,30 +63,17 @@ export function frozenStepRows(plan) {
62
63
  ? step.root.kind === "map"
63
64
  ? step.root.template.instructions
64
65
  : step.root.instructions
65
- : routeInstructions(step.route),
66
+ : "",
66
67
  completionJson: step.gate.criteria.length > 0 ? JSON.stringify(step.gate.criteria) : null,
67
68
  sequenceIndex: step.sequenceIndex,
68
69
  }));
69
70
  }
70
- function routeInstructions(route) {
71
- const branches = Object.entries(route.when)
72
- .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
73
- .map(([match, stepId]) => `"${match}" -> ${stepId}`);
74
- if (route.defaultStepId !== undefined)
75
- branches.push(`default -> ${route.defaultStepId}`);
76
- return `Route on ${route.input}: ${branches.join(", ")}.`;
77
- }
78
71
  /** Decode a stored plan (any release's) into the one plan type. */
79
72
  export function decodeWorkflowPlan(input, options = {}) {
80
73
  const raw = record(input, "plan");
81
74
  if (!Array.isArray(raw.steps) || raw.steps.length === 0)
82
75
  fail("steps must be a non-empty array");
83
76
  const steps = raw.steps.map((value, index) => decodeStep(value, index));
84
- if (raw.outputs !== undefined) {
85
- for (const [name, entry] of Object.entries(record(raw.outputs, "outputs"))) {
86
- string(record(entry, `outputs.${name}`).from, `outputs.${name}.from`);
87
- }
88
- }
89
77
  const sourceHash = typeof raw.sourceHash === "string" ? raw.sourceHash : legacySourceHash(raw.sourceReadSet, options.workflowRef);
90
78
  return {
91
79
  ...raw,
@@ -109,28 +97,18 @@ function legacySourceHash(readSet, workflowRef) {
109
97
  function decodeStep(value, index) {
110
98
  const step = record(value, `step ${index}`);
111
99
  const stepId = string(step.stepId, `step ${index} stepId`);
112
- const route = step.route === undefined ? undefined : decodeRoute(step.route, stepId);
113
- const root = step.root === undefined ? undefined : decodeNode(step.root, stepId);
114
- if (!root && !route)
115
- fail(`step ${stepId} has neither a frozen root nor a route`);
100
+ if (step.root === undefined)
101
+ fail(`step ${stepId} has no frozen root`);
102
+ const root = decodeNode(step.root, stepId);
116
103
  return {
117
104
  ...step,
118
105
  stepId,
119
106
  title: typeof step.title === "string" ? step.title : stepId,
120
107
  sequenceIndex: index,
121
- ...(root ? { root } : {}),
122
- ...(route ? { route } : {}),
108
+ root,
123
109
  gate: decodeGate(step.gate, stepId),
124
110
  };
125
111
  }
126
- function decodeRoute(value, stepId) {
127
- const route = record(value, `step ${stepId} route`);
128
- string(route.input, `step ${stepId} route.input`);
129
- const when = record(route.when, `step ${stepId} route.when`);
130
- for (const target of Object.values(when))
131
- string(target, `step ${stepId} route target`);
132
- return route;
133
- }
134
112
  function decodeNode(value, stepId) {
135
113
  const node = record(value, `step ${stepId} root`);
136
114
  if (node.kind !== "map")
@@ -154,7 +132,6 @@ function decodeUnit(node, stepId) {
154
132
  id,
155
133
  instructions: typeof node.instructions === "string" ? node.instructions : "",
156
134
  onError: node.onError === "continue" ? "continue" : "fail",
157
- isolation: node.isolation === "worktree" ? "worktree" : "none",
158
135
  frozenTarget: decodeTarget(node.frozenTarget, label),
159
136
  environment: Array.isArray(node.environment)
160
137
  ? node.environment.map((binding, index) => decodeEnvironmentBinding(binding, `${label} environment[${index}]`))
@@ -180,11 +157,7 @@ function decodeGate(value, stepId) {
180
157
  function decodeTarget(value, label) {
181
158
  const target = record(value, `${label} frozenTarget`);
182
159
  const inputBindings = decodeInputBindings(target.inputBindings, label);
183
- const gitCommitOid = typeof target.gitCommitOid === "string" ? target.gitCommitOid : undefined;
184
- const optional = {
185
- ...(gitCommitOid ? { gitCommitOid } : {}),
186
- ...(inputBindings ? { inputBindings } : {}),
187
- };
160
+ const optional = inputBindings ? { inputBindings } : {};
188
161
  switch (target.kind) {
189
162
  case "command":
190
163
  return decodeCommandTarget(target, label);
@@ -196,20 +169,6 @@ function decodeTarget(value, label) {
196
169
  cwdIdentity: record(target.cwdIdentity, `${label} cwdIdentity`),
197
170
  ...optional,
198
171
  };
199
- case "script":
200
- return {
201
- kind: "script",
202
- ref: string(target.ref, `${label} script ref`),
203
- contentHash: string(target.contentHash, `${label} contentHash`),
204
- exec: decodeExec(target.exec, label),
205
- interpreter: string(target.interpreter, `${label} interpreter`),
206
- extension: string(target.extension, `${label} extension`),
207
- bytesBase64: typeof target.bytesBase64 === "string" ? target.bytesBase64 : fail(`${label} has no script bytes`),
208
- byteLength: typeof target.byteLength === "number" ? target.byteLength : 0,
209
- cwdIdentity: record(target.cwdIdentity, `${label} cwdIdentity`),
210
- materialization: "ephemeral-0700-delete",
211
- ...optional,
212
- };
213
172
  case "child-workflow":
214
173
  return {
215
174
  kind: "child-workflow",
@@ -217,7 +176,7 @@ function decodeTarget(value, label) {
217
176
  planHash: string(target.planHash, `${label} planHash`),
218
177
  frozenPlan: decodeWorkflowPlan(target.frozenPlan),
219
178
  contentHash: string(target.contentHash, `${label} contentHash`),
220
- via: target.via === "task" ? "task" : "direct",
179
+ ...(target.via === "task" || target.via === "direct" ? { via: target.via } : {}),
221
180
  ...(typeof target.taskRef === "string" ? { taskRef: target.taskRef } : {}),
222
181
  ...(inputBindings ? { inputBindings } : {}),
223
182
  };
@@ -247,7 +206,6 @@ function decodeCommandTarget(target, label) {
247
206
  ...(target.cwdIdentity && typeof target.cwdIdentity === "object"
248
207
  ? { cwdIdentity: target.cwdIdentity }
249
208
  : {}),
250
- ...(typeof target.gitCommitOid === "string" ? { gitCommitOid: target.gitCommitOid } : {}),
251
209
  ...(inputBindings ? { inputBindings } : {}),
252
210
  };
253
211
  }
@@ -13,12 +13,11 @@ import { getCurrentWorkflowScopeKey } from "../authoring/scope-key.js";
13
13
  import { frozenSummaryJudge } from "../exec/frozen-judge.js";
14
14
  import { detectSecretShapedParams } from "../exec/param-secrets.js";
15
15
  import { freezeWorkflow } from "../freeze/freeze.js";
16
- import { materializeWorkflowParameterFlags, validateWorkflowParams } from "../ir/params.js";
16
+ import { applyWorkflowParamDefaults, materializeWorkflowParameterFlags, validateWorkflowParams, } from "../ir/params.js";
17
17
  import { canonicalPlanJson, computePlanHash } from "../ir/plan-hash.js";
18
18
  import { clip, WORKFLOW_UNIT_DIAGNOSTIC_CLIP } from "../resource-limits.js";
19
19
  import { validateStepSummary } from "../validate-summary.js";
20
20
  import { resolveAgentIdentity } from "./agent-identity.js";
21
- import { resolveWorkflowRunOutputs } from "./run-outputs.js";
22
21
  import { frozenStepRows, readRunPlan } from "./run-plan.js";
23
22
  import { canonicalizeWorkflowRefInput, loadWorkflowAsset, resolveWorkflowEntryId } from "./workflow-asset-loader.js";
24
23
  /**
@@ -76,9 +75,7 @@ export async function startWorkflowRun(ref, params = {}, options) {
76
75
  if (options?.parameterFlags?.length && Object.keys(params).length > 0) {
77
76
  throw new UsageError("Workflow parameters must use either an object or per-parameter flags, not both.");
78
77
  }
79
- const effectiveParams = options?.parameterFlags?.length
80
- ? materializeWorkflowParameterFlags(plan, options.parameterFlags)
81
- : params;
78
+ const effectiveParams = applyWorkflowParamDefaults(plan, options?.parameterFlags?.length ? materializeWorkflowParameterFlags(plan, options.parameterFlags) : params);
82
79
  // Non-fatal WARNINGS: untyped-step and undeclared-param advisories surface
83
80
  // as `warn()` lines at start (stderr, consistent with the repo's other
84
81
  // author-facing warnings) without blocking the run.
@@ -394,10 +391,9 @@ export async function completeWorkflowStep(input) {
394
391
  return withWorkflowRunsRepo((repo) => {
395
392
  let updatedRun;
396
393
  let refreshedSteps = [];
397
- let outputWarnings;
398
394
  repo.transaction(() => {
399
395
  const run = readWorkflowRun(repo, input.runId);
400
- const plan = requireRunPlan(run);
396
+ const _plan = requireRunPlan(run);
401
397
  if (run.status !== "active") {
402
398
  throw new UsageError(`Workflow run ${run.id} is ${run.status} and cannot be updated.`);
403
399
  }
@@ -428,15 +424,6 @@ export async function completeWorkflowStep(input) {
428
424
  });
429
425
  refreshedSteps = readWorkflowRunSteps(repo, run.id);
430
426
  const state = deriveRunState(refreshedSteps);
431
- // Declared outputs resolve inside this transaction once the run
432
- // completes; a failure rolls the step completion back whole.
433
- let outputsJson; // undefined = untouched, keep the row's existing value
434
- if (state.status === "completed" && plan.outputs) {
435
- const resolved = resolveWorkflowRunOutputs(plan, refreshedSteps);
436
- outputsJson = JSON.stringify(resolved.outputs);
437
- repo.setRunOutputs(run.id, outputsJson);
438
- outputWarnings = resolved.errors;
439
- }
440
427
  repo.updateRunState({
441
428
  status: state.status,
442
429
  currentStepId: state.currentStepId,
@@ -450,16 +437,9 @@ export async function completeWorkflowStep(input) {
450
437
  current_step_id: state.currentStepId,
451
438
  updated_at: completedAt,
452
439
  completed_at: state.completedAt,
453
- ...(outputsJson !== undefined ? { outputs_json: outputsJson } : {}),
454
440
  };
455
441
  });
456
442
  const detail = buildWorkflowRunDetail(repo, updatedRun, refreshedSteps);
457
- if (outputWarnings?.length) {
458
- const messages = outputWarnings.map((e) => `Workflow run ${input.runId} declared ${e}`);
459
- for (const message of messages)
460
- warn(message);
461
- detail.warnings = [...(detail.warnings ?? []), ...messages];
462
- }
463
443
  // #11: emit `workflow_step_completed` ONLY for a genuine `completed`
464
444
  // transition; every other non-pending status (failed/skipped/blocked)
465
445
  // carries the honest `workflow_step_updated` name. The status is ALWAYS
@@ -680,10 +660,7 @@ function toWorkflowRunSummary(run) {
680
660
  agentHarness: run.agent_harness ?? null,
681
661
  agentSessionId: run.agent_session_id ?? null,
682
662
  planIrVersion: run.plan_ir_version ?? null,
683
- // P3b: all three optional and conditionally spread, so every
684
- // pre-existing (non-child, no-outputs-declared) run's envelope is
685
- // byte-identical.
686
- ...(run.outputs_json ? { outputs: parseJsonObject(run.outputs_json) ?? {} } : {}),
663
+ // Optional and conditionally spread, so a non-child run's envelope is unchanged.
687
664
  ...(run.parent_run_id ? { parentRunId: run.parent_run_id } : {}),
688
665
  ...(run.parent_unit_id ? { spawnedByUnitId: run.parent_unit_id } : {}),
689
666
  };
@@ -4,11 +4,9 @@
4
4
  /**
5
5
  * Authoritative workflow-source ownership.
6
6
  *
7
- * Markdown and the bounded GitHub-shaped YAML subset are peer authoring
8
- * formats, but one canonical workflow ref must have exactly one source file.
9
- * This module is the shared filesystem arbitration point used before indexing,
10
- * cache reuse, lookup/show, and runtime load/start. It never chooses one
11
- * extension by priority: two recognized siblings are a hard collision.
7
+ * One canonical workflow ref must have exactly one source file. This module
8
+ * is the shared filesystem arbitration point used before indexing, cache
9
+ * reuse, lookup/show, and runtime load/start.
12
10
  */
13
11
  import fs from "node:fs";
14
12
  import path from "node:path";
@@ -29,7 +27,7 @@ export class WorkflowSourceCollisionError extends WorkflowSourceRejectionError {
29
27
  constructor(canonicalName, sourcePaths) {
30
28
  const sorted = [...sourcePaths].sort(compareCodePoints);
31
29
  super(`Workflow "${canonicalName}" resolves to multiple workflow source files: ${sorted.join(", ")}. ` +
32
- "A canonical workflow ref must be owned by exactly one recognized .md or .yml source; remove or rename the duplicate.", "RESOURCE_ALREADY_EXISTS", sorted);
30
+ "A canonical workflow ref must be owned by exactly one recognized .md source; remove or rename the duplicate.", "RESOURCE_ALREADY_EXISTS", sorted);
33
31
  this.name = "WorkflowSourceCollisionError";
34
32
  this.canonicalName = canonicalName;
35
33
  Object.setPrototypeOf(this, new.target.prototype);
@@ -46,15 +44,15 @@ export class WorkflowSourceIdentityError extends UsageError {
46
44
  export class WorkflowSourceNameError extends WorkflowSourceRejectionError {
47
45
  constructor(sourcePath, nestedSuffix) {
48
46
  super(`Workflow source filename ${sourcePath} has an extensionless stem ending in recognized workflow suffix "${nestedSuffix}". ` +
49
- "Nested workflow suffixes are invalid; remove the inner .md or .yml suffix instead of relying on repeated stripping.", "WORKFLOW_SOURCE_INVALID", [sourcePath]);
47
+ "Nested workflow suffixes are invalid; remove the inner .md suffix instead of relying on repeated stripping.", "WORKFLOW_SOURCE_INVALID", [sourcePath]);
50
48
  this.name = "WorkflowSourceNameError";
51
49
  Object.setPrototypeOf(this, new.target.prototype);
52
50
  }
53
51
  }
54
52
  export class WorkflowSourceLinkIdentityError extends WorkflowSourceRejectionError {
55
53
  constructor(sourcePath, targetPath) {
56
- super(`Workflow source ${sourcePath} resolves through a symlink to ${targetPath} with a different source format. ` +
57
- "The authored workflow path and resolved source must use the same .md or .yml format.", "WORKFLOW_SOURCE_INVALID", [sourcePath]);
54
+ super(`Workflow source ${sourcePath} resolves through a symlink to ${targetPath} with a different extension. ` +
55
+ "The authored workflow path and resolved source must both be .md.", "WORKFLOW_SOURCE_INVALID", [sourcePath]);
58
56
  this.name = "WorkflowSourceLinkIdentityError";
59
57
  Object.setPrototypeOf(this, new.target.prototype);
60
58
  }
@@ -240,13 +238,13 @@ function inspectWorkflowSourceDomain(candidates, canonicalName, realRoot) {
240
238
  function pickWorkflowSource(adapterId, canonicalName, sources) {
241
239
  if (sources.length <= 1)
242
240
  return sources[0];
243
- const winner = [...sources].sort((left, right) => left.format === right.format ? 0 : left.format === "markdown" ? -1 : 1)[0];
241
+ const winner = sources[0];
244
242
  const shadowed = sources.filter((source) => source !== winner);
245
243
  const displayName = adapterId === "akm" ? `workflows/${canonicalName}` : canonicalName;
246
- warnOnce(`workflow-source-collision:${displayName}`, `Workflow "${displayName}" has both a .md and .yml source (${shadowed
244
+ warnOnce(`workflow-source-collision:${displayName}`, `Workflow "${displayName}" has several sources (${shadowed
247
245
  .map((source) => source.relativePath)
248
- .join(", ")} shadowed by ${winner?.relativePath}); using the .md source. Remove the shadowed sibling to ` +
249
- "silence this warning.");
246
+ .join(", ")} shadowed by ${winner?.relativePath}); using ${winner?.relativePath}. Remove the shadowed ` +
247
+ "sibling to silence this warning.");
250
248
  return winner;
251
249
  }
252
250
  function inspectWorkflowSourceCandidate(candidate, canonicalName, realRoot) {
@@ -297,7 +295,6 @@ function inspectWorkflowSourceCandidate(candidate, canonicalName, realRoot) {
297
295
  realPath,
298
296
  relativePath: candidate.relativePath,
299
297
  canonicalName,
300
- format: candidate.lowerExtension === ".md" ? "markdown" : "github-yaml",
301
298
  },
302
299
  };
303
300
  }
@@ -321,8 +318,7 @@ export function assertIndexedWorkflowSourceIdentity(ref, indexedPath, authoritat
321
318
  throw new WorkflowSourceIdentityError(ref, indexedPath, authoritative.path);
322
319
  }
323
320
  const indexedExtension = path.extname(indexedPath).toLowerCase();
324
- const authoritativeExtension = authoritative.format === "markdown" ? ".md" : ".yml";
325
- if (indexedExtension !== authoritativeExtension) {
321
+ if (indexedExtension !== ".md") {
326
322
  throw new WorkflowSourceIdentityError(ref, indexedPath, authoritative.path);
327
323
  }
328
324
  }
@@ -1,12 +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
- /** Semantic checks shared by the workflow grammars (`parser.ts`, `github-yaml.ts`) and freeze. */
4
+ /** Semantic checks for the Markdown workflow grammar (`parser.ts`). */
5
5
  import fs from "node:fs";
6
6
  import path from "node:path";
7
- import { parseBuiltinCommandAction } from "../commands/command/builtin-action.js";
8
- import { classifyTargetRef } from "../execution/target-ref.js";
9
- import { parseSchedule } from "../tasks/schedule.js";
10
7
  export class WorkflowSourceSemanticError extends Error {
11
8
  code;
12
9
  constructor(code, message) {
@@ -15,36 +12,6 @@ export class WorkflowSourceSemanticError extends Error {
15
12
  this.name = "WorkflowSourceSemanticError";
16
13
  }
17
14
  }
18
- /** The argv a `run:` string executes under `shell`. */
19
- export function workflowShellCommand(shell, content) {
20
- if (shell === "cmd")
21
- return ["cmd", "/d", "/s", "/c", content];
22
- if (shell === "pwsh" || shell === "powershell")
23
- return [shell, "-Command", content];
24
- return [shell, "-c", content];
25
- }
26
- export function canonicalizeWorkflowCron(value) {
27
- const canonical = value.trim().split(/\s+/).join(" ");
28
- if (canonical.startsWith("@") || canonical.split(" ").length !== 5) {
29
- throw new WorkflowSourceSemanticError("invalid-cron", "GitHub schedule cron must use exactly five fields.");
30
- }
31
- try {
32
- parseSchedule(canonical, "cron");
33
- }
34
- catch (cause) {
35
- throw new WorkflowSourceSemanticError("invalid-cron", cause instanceof Error ? cause.message : "Invalid cron schedule.");
36
- }
37
- return canonical;
38
- }
39
- export function canonicalizeWorkflowRun(value) {
40
- if (value.includes("${{")) {
41
- throw new WorkflowSourceSemanticError("unsupported-github-expression", "GitHub expressions and contexts are not supported.");
42
- }
43
- if (value.includes("\0")) {
44
- throw new WorkflowSourceSemanticError("invalid-exec-argv", "Local run may not contain NUL bytes.");
45
- }
46
- return value;
47
- }
48
15
  export function canonicalizeWorkflowWorkingDirectory(value, workspaceRoot) {
49
16
  if (hasControlCharacter(value)) {
50
17
  throw new WorkflowSourceSemanticError("working-directory-control-character", "working-directory may not contain NUL or control characters.");
@@ -74,65 +41,6 @@ function hasControlCharacter(value) {
74
41
  }
75
42
  return false;
76
43
  }
77
- export function classifyWorkflowStepUses(value) {
78
- if (value.includes("${{")) {
79
- throw new WorkflowSourceSemanticError("unsupported-github-expression", "GitHub expressions are unsupported in uses.");
80
- }
81
- if (value.length === 0 || value.trim() !== value || /\s/.test(value)) {
82
- throw new WorkflowSourceSemanticError("unsupported-uses-target", "uses must be one exact, non-empty executable ref");
83
- }
84
- if (value === "akm/command")
85
- return { kind: "builtin-command", ref: "akm/command" };
86
- try {
87
- return classifyTargetRef(value);
88
- }
89
- catch (cause) {
90
- throw usesFailure(value, cause);
91
- }
92
- }
93
- /**
94
- * Validate AKM's built-in command action at the shared source/decoder boundary.
95
- *
96
- * Inline YAML actions are portable templates and therefore use WP4's one
97
- * authoritative template validator. Markdown prose is explicitly `literal`,
98
- * while a stored ref remains resolution-owned because its template bytes are
99
- * not available until the later resolver loads the command asset.
100
- */
101
- export function validateWorkflowBuiltinCommand(value, mode) {
102
- let action;
103
- try {
104
- action = parseBuiltinCommandAction(value);
105
- }
106
- catch (cause) {
107
- throw new WorkflowSourceSemanticError("builtin-command-inputs", cause instanceof Error ? cause.message : "Invalid akm/command inputs.");
108
- }
109
- const expectedMode = action.kind === "stored" ? "stored-ref" : "portable-template";
110
- const effectiveMode = mode ?? expectedMode;
111
- if (action.kind === "stored") {
112
- if (effectiveMode !== "stored-ref") {
113
- throw new WorkflowSourceSemanticError("builtin-command-inputs", "Stored akm/command refs require commandMode stored-ref.");
114
- }
115
- return action;
116
- }
117
- if (effectiveMode === "stored-ref") {
118
- throw new WorkflowSourceSemanticError("builtin-command-inputs", "Inline akm/command content cannot use commandMode stored-ref.");
119
- }
120
- if (effectiveMode === "literal" && action.arguments !== undefined) {
121
- throw new WorkflowSourceSemanticError("builtin-command-inputs", "Literal akm/command content cannot declare arguments because no substitution occurs.");
122
- }
123
- return action;
124
- }
125
- function usesFailure(value, cause) {
126
- const message = cause instanceof Error ? cause.message : String(cause);
127
- const code = value.startsWith("docker://")
128
- ? "docker-action-unsupported"
129
- : value.startsWith("./") || value.startsWith("../") || value.startsWith("/")
130
- ? "local-action-path-unsupported"
131
- : /^(?:[A-Za-z0-9][A-Za-z0-9._-]*\/\/)?agents\//.test(value)
132
- ? "non-executable-asset-ref"
133
- : "unsupported-uses-target";
134
- return new WorkflowSourceSemanticError(code, message);
135
- }
136
44
  function verifyPhysicalContainment(workspaceRoot, relative) {
137
45
  let root;
138
46
  try {
package/docs/README.md CHANGED
@@ -17,7 +17,7 @@ Full per-directory indexes: [Guides](guides/README.md),
17
17
  - [Getting Started](guides/getting-started.md) -- Install akm, connect a source, and pull a curated shortlist in five to seven minutes
18
18
  - [Concepts](guides/concepts.md) -- Capabilities, bundles, adapters, asset types, and refs -- the mental model in one page
19
19
  - [Agent Install Guide](agents/agent-install.md) -- Step-by-step automated (non-interactive) install for agents
20
- - `akm help agents` (short guide by default; `akm help agents --full` for the complete guide) -- The CLI reference agents load to use akm; always the embedded corpus at `src/assets/hints/cli-hints-{full,short}.md`
20
+ - `akm hints` (complete guide by default; `akm hints --detail brief` for the short one) -- The CLI reference agents load to use akm; always the embedded corpus at `src/assets/hints/cli-hints-{full,short}.md`
21
21
 
22
22
  ## Use
23
23
 
@@ -3,8 +3,8 @@
3
3
  Documentation for wiring AI agents into akm.
4
4
 
5
5
  Run `akm hints` for the complete CLI reference agents should load into a
6
- system prompt, or `akm help agents` for the compact guide.
7
- (the short form is the default; pass `--full` for the complete guide). It always prints the embedded
6
+ system prompt, or `akm hints --detail brief` for the compact guide.
7
+ It always prints the embedded
8
8
  corpus at `src/assets/hints/cli-hints-full.md` / `cli-hints-short.md` --
9
9
  browse those files directly if you want to read the reference without running
10
10
  the CLI. There used to be a separate `docs/agents/AGENTS.md` /
@@ -12,4 +12,4 @@ the CLI. There used to be a separate `docs/agents/AGENTS.md` /
12
12
  re-diverging from the embedded copy with no test to catch it, so it was
13
13
  deleted and its still-true unique content was merged into the embedded files.
14
14
 
15
- - [Agent Install Guide](agent-install.md) -- Short redirect covering the install shape (binary, `akm setup --yes`, a source, an index, `akm help agents`); for the exact no-prompts command sequence, see the [headless install recipe](../guides/recipes/headless-install.md)
15
+ - [Agent Install Guide](agent-install.md) -- Short redirect covering the install shape (binary, `akm setup --yes`, a source, an index, `akm hints`); for the exact no-prompts command sequence, see the [headless install recipe](../guides/recipes/headless-install.md)
@@ -2,7 +2,7 @@
2
2
 
3
3
  `akm` is a portable capability library agents install and configure without
4
4
  interactive prompts: install the binary, run `akm setup --yes`, add a source,
5
- build the index, then expose `akm help agents` output to the agent so it
5
+ build the index, then expose `akm hints` output to the agent so it
6
6
  knows how to search and load bundle content. Configuration lives in
7
7
  top-level keys validated against the config schema, and semantic search can
8
8
  run on local embeddings or a remote endpoint depending on what the host
@@ -101,23 +101,21 @@ interface BundleAdapter {
101
101
  // reading authored bytes or walking the bundle.
102
102
  readCandidates?(c: BundleComponent, conceptId: string): Array<{ path: string; conceptId: string }>;
103
103
 
104
- // OPTIONAL — placement / discovery.
105
- placeNew?(c: BundleComponent, conceptId: string): string; // where a new item would live
104
+ // OPTIONAL — discovery.
106
105
  directoryList?(c: BundleComponent): string[]; // owned dirs; feeds git exact-path staging
107
106
  looksLikeRoot?(root: string): boolean; // install-time probe
108
107
  }
109
108
  ```
110
109
 
111
110
  `recognize` and `validate` are required on every adapter; `index`,
112
- `affectedItems`, `readCandidates`, `placeNew`, `directoryList`, and
111
+ `affectedItems`, `readCandidates`, `directoryList`, and
113
112
  `looksLikeRoot` are optional capability methods. An adapter overriding `index()` must keep
114
113
  `recognize()` coherent with it (conformance: `index()` == fold of
115
114
  `recognize()` over the core walk) or declare component-level
116
115
  incrementality.
117
116
 
118
- `readCandidates` is intentionally distinct from both `extensions` and
119
- `placeNew`: extensions are non-exhaustive walk hints, while placement is a
120
- write-normalization policy. Read candidates preserve canonical directory
117
+ `readCandidates` is intentionally distinct from `extensions`: extensions are
118
+ non-exhaustive walk hints. Read candidates preserve canonical directory
121
119
  manifests (for example `skills/<name>/SKILL.md`) so lookup, index-backed show, and workflow runtime share one
122
120
  physical-owner decision. Each candidate carries its canonical concept identity,
123
121
  so a byte-denying ownership probe never has to infer identity from the query.
@@ -145,30 +143,21 @@ concern.
145
143
 
146
144
  ---
147
145
 
148
- ## `placeNew()` wiring status
146
+ ## Placement
149
147
 
150
- The interface declares `placeNew()` as an optional capability method, and 9
151
- of the 11 built-in adapters already implement it — all but `okf` and
152
- `website-snapshot` (`claude` and `opencode` inherit theirs from the shared
153
- tool-dir factory). **Nothing in the write path calls it yet**: AKM-native
154
- writes still resolve through AKM's own flat type→directory placement table
155
- (`src/core/asset/asset-placement.ts`'s `PLACEMENT_SPECS`), not through the
156
- owning adapter's `placeNew()`.
157
-
158
- Placement for every existing bundle is already correct today — this is a
159
- deliberately sequenced routing change, not unfinished behavior. It's
160
- scoped out of 0.9.0 by
161
- [D12](../architecture/specs/0.9.0-decisions.md#d12--bundleadapterplacenew-stays-unwired-until-010)
162
- and deferred to 0.10; nothing user-visible changes in 0.10 for this alone.
163
- See [STABILITY.md](../../STABILITY.md) ("On the horizon") for the
164
- up-to-date status if this changes.
148
+ Adapters do not place new items. AKM-native writes resolve through AKM's own
149
+ flat type→directory placement table (`src/core/asset/asset-placement.ts`'s
150
+ `PLACEMENT_SPECS`), which is correct for akm-layout bundles — the only bundles
151
+ the write commands touch in practice. A per-adapter `placeNew()` existed
152
+ through 0.9 but nothing called it, and it was removed in 0.10. Supporting
153
+ writable bundles in another layout would need it back: see
154
+ [#1163](https://github.com/itlackey/akm/issues/1163).
165
155
 
166
156
  ---
167
157
 
168
158
  ## Write allowlists
169
159
 
170
- `placeNew()` wiring is a separate question from **which bundles AKM-native
171
- write commands are allowed to touch at all** — that's decided today by a
160
+ Which bundles AKM-native write commands are allowed to touch at all is decided by a
172
161
  small allowlist check, `assertAkmAssetWrite` (`src/core/write-source.ts`),
173
162
  run before any write command touches the filesystem. It compares the target
174
163
  bundle's detected (or configured) adapter id against an allowlist and throws
@@ -181,12 +170,10 @@ The default allowlist is `["akm"]`. Two command families widen it explicitly:
181
170
  | `akm env create` / `env remove` / `secret set` | `dotenv` |
182
171
  | `akm workflow create` | `akm-workflow` |
183
172
 
184
- Every other adapter — including every adapter that already implements
185
- `placeNew()` (`agent-skills`, `claude`, `opencode`, `akm-task`,
186
- `generic-files`) — is rejected by every AKM-native write command in 0.9.0.
173
+ Every other adapter (`agent-skills`, `claude`, `opencode`, `akm-task`,
174
+ `generic-files`, and so on) is rejected by every AKM-native write command.
187
175
  `akm task add` in particular uses the *default* allowlist (`akm` only), so a
188
- standalone `akm-task` bundle is read-only through AKM-native write commands
189
- even though `akm-task`'s own `placeNew()` is implemented.
176
+ standalone `akm-task` bundle is read-only through AKM-native write commands.
190
177
 
191
178
  Reading, searching, and `akm lint` are unaffected by this allowlist — only
192
179
  creating, editing, or deleting through AKM's own commands is restricted.
@@ -197,8 +184,7 @@ This allowlist boundary is also where AKM's [execution
197
184
  boundary](../guides/concepts.md) principle shows up on the write side: AKM
198
185
  retrieves and validates every supported format, but it only lets its own
199
186
  write commands mutate a narrow, explicitly-declared set of targets — it
200
- does not widen write access to a format just because that format's adapter
201
- happens to expose a `placeNew()` implementation.
187
+ does not widen write access to a format just because it can read it.
202
188
 
203
189
  ---
204
190
 
@@ -260,8 +260,7 @@ schema (`src/core/config/schema/sources-bundles.ts`).
260
260
  refresh.
261
261
 
262
262
  Write-target resolution (`resolveWriteTarget`) follows: an explicit
263
- destination flag (`--bundle` on `remember`/`clone`/`improve`, `--target` on
264
- `import`/env/secret mutations) -> `config.defaultWriteTarget` -> working
263
+ destination flag (`--bundle`) -> `config.defaultWriteTarget` -> working
265
264
  bundle (`defaultBundle`) -> `ConfigError`. The resolved target keeps the
266
265
  optional configured selector separate from the stable `source.name`: APIs
267
266
  that must re-resolve a destination use the selector, while durable refs and
@@ -299,8 +298,8 @@ whose proposal queue is read or adjudicated; it does not override the proposal's
299
298
  write destination. Qualified proposals and unqualified proposals created in a
300
299
  configured secondary queue record the destination source name and materialized
301
300
  root. Diff, accept, and revert use that binding by default and reject an explicit
302
- `--target` that resolves elsewhere. An unbound short proposal requires either
303
- an explicit `--target` or an authenticated `--queue` context; it does not
301
+ `--bundle` that resolves elsewhere. An unbound short proposal requires either
302
+ an explicit `--bundle` or an authenticated `--queue` context; it does not
304
303
  inherit a default write target.
305
304
 
306
305
  ---
@@ -442,7 +441,7 @@ An explicit missing or incompatible engine is an error and never falls
442
441
  through to another configured engine.
443
442
 
444
443
  Task-v3 execution and durable workflow-v4 dispatch use this runtime boundary.
445
- Markdown and GitHub-shaped YAML compile through source IR v1; new starts freeze
444
+ Markdown workflows compile through source IR v1; new starts freeze
446
445
  v4-family `irVersion: 5`. A stored plan that decodes runs whatever release
447
446
  froze it; one that does not is marked abandoned and `akm workflow run <ref>`
448
447
  starts afresh. Only a plan a newer akm froze is refused, naming the upgrade.