akm-cli 0.10.261017-beta → 0.10.261019

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.
@@ -1,4 +1,4 @@
1
- # akm v0.10.0 migration notes
1
+ # akm v0.10 migration notes (0.10.261019, the first stable 0.10 release)
2
2
 
3
3
  0.10 is a clean-up and tuning release. It covers the daily alphas
4
4
  0.10.26101001 through 0.10.26101202 and the monthly releases that follow
@@ -31,6 +31,19 @@ the old `stashDir` / `sources[]` / `installed[]` layout fails to load and names
31
31
  `akm migrate apply` under akm 0.9.x. If you are on 0.9.14 or earlier, install
32
32
  0.9.31, run `akm migrate apply`, then upgrade.
33
33
 
34
+ ## If you ran a 0.10 beta
35
+
36
+ The betas 0.10.261014 to 0.10.261017 dropped every `opencode-sdk` engine when
37
+ `akm migrate apply` converted `config.json`, so agent work moved from your own
38
+ OpenCode (and its model) to akm's own runtime over your default connection; the
39
+ note it printed did not say so. This release keeps those engines as `opencode`
40
+ harnesses. A
41
+ config a beta already migrated is not converted again: akm keeps the file as it
42
+ was before the rewrite in `<cache dir>/config-backups/` (the five newest), and
43
+ [step 5 of the migration guide](../v0.9-to-v0.10.md#5-fix-what-the-migration-cannot)
44
+ shows how to read the harnesses out of that copy and set them, or write them by
45
+ hand when no copy is left.
46
+
34
47
  ## Version numbers
35
48
 
36
49
  A 0.10 release is numbered `0.10.YYMMNN`: the UTC year and month, then the
@@ -74,7 +87,10 @@ not offer it.
74
87
  config keys, paths and dotted references such as `process.env.CI` in a fenced
75
88
  block now reach the `content` search text; quoted strings, assignment values,
76
89
  URLs and long token-like strings still do not. Search results, fragments and
77
- `akm show` are unchanged. On the first run after upgrading, `akm index` (and
90
+ `akm show` are unchanged. It lifts code lookups and keyword library search
91
+ in akm-eval and costs about 2 NDCG points on the SkillRet skill-selection
92
+ benchmark, where long, code-heavy skills now outrank short, code-free ones;
93
+ tuning is tracked in #1284. On the first run after upgrading, `akm index` (and
78
94
  the index `akm upgrade` runs, which `akm upgrade` waits for) re-reads every
79
95
  bundle directory and re-embeds only the entries whose embedded text changed.
80
96
  Text past `embedding.maxInputTokens` (default 512, about 2,048 characters) is
@@ -114,7 +130,13 @@ Other breaking changes:
114
130
  is the default, and `defaults.improveStrategy` is `improve.strategy`. A config
115
131
  in the old form still loads, read as the new form in memory with one warning
116
132
  that names `akm migrate apply`. `akm migrate apply` converts it under a
117
- backup: the default engine is renamed `default`, keys (`apiKeyFile`, a literal
133
+ backup: every agent engine becomes a harness with its model (an `opencode-sdk`
134
+ engine with no `llmEngine` ran your own OpenCode, so it becomes an `opencode`
135
+ harness; one over an `llmEngine` is akm's own runtime over that connection;
136
+ with no `defaults.llmEngine` and no connection, akm's model work now runs on
137
+ the default harness where 0.9 ran none, and `modelWork: false` on it turns that
138
+ off),
139
+ the default engine is renamed `default`, keys (`apiKeyFile`, a literal
118
140
  or `${secrets/...}` `apiKey`) move to `credentials.json`, `models.json` is
119
141
  folded into the connections' `models` and moved to the config backups,
120
142
  `engine:` in assets, workflows and task sources becomes `connection:` or
@@ -216,13 +238,22 @@ Other breaking changes:
216
238
  Harnesses run as thin shells: akm hands a program the prompt and takes its
217
239
  standard output as the reply.
218
240
  - **OpenCode 2, run by akm.** Agent work on a connection with no harness runs on
219
- akm's own runtime, a pinned OpenCode 2 binary (2.1.4) that akm fetches from the
241
+ akm's own runtime, a pinned OpenCode 2 binary (2.2.0) that akm fetches from the
220
242
  npm registry on first use and runs as a process, with no entry in config. The
221
243
  fetch is the one platform package for your machine (about 114 MB, into its
222
244
  cache), checked against the registry's sha512 integrity before anything is
223
245
  extracted. One fetch runs per cache directory at a time: processes that start
224
246
  together wait for it and download nothing more (#1266). The setup wizard
225
247
  offers to fetch it right away; `--yes` and `--from` leave it to the first run.
248
+ A run whose model makes the same tool call and gets the same result three
249
+ turns in a row is told so in a message to the model, and failed with a
250
+ message if it makes the call again, not left to its deadline. That one
251
+ request raises a connection's `temperature` below 0.7 to 0.7: at temperature
252
+ 0 the message alone changed nothing in the runs measured. A run that
253
+ keeps making different calls is bounded by its timeout: the connection's
254
+ `timeoutMs`, one the run is given, or a scheduled task's `timeout:` (six hours
255
+ when unset); with none, as for `akm agent` by default, it runs until it
256
+ finishes.
226
257
  With no network for that step, enable the `opencode` harness with an installed
227
258
  OpenCode 2 instead. A harness with `platform: "opencode"` is your
228
259
  OpenCode, whichever major is installed, run through its CLI with your config,
@@ -7,7 +7,7 @@ live one level up in `docs/migration/`.
7
7
 
8
8
  ## Available notes
9
9
 
10
- - [0.10.0](0.10.0.md) — The 0.10 series: 0.9.15 version floor, merged CLI spellings, `default`/`consolidate` strategies only, OpenCode 2, feedback-scaled ranking, and `0.10.YYMMNN` versions.
10
+ - [0.10.261019](0.10.261019.md) — The 0.10 series: 0.9.15 version floor, merged CLI spellings, `default`/`consolidate` strategies only, OpenCode 2, feedback-scaled ranking, and `0.10.YYMMNN` versions.
11
11
  - [0.9.19](0.9.19.md) — Bundle-scoped improve planning, proposal reopen, and consolidate/distill guardrails.
12
12
  - [0.9.17](0.9.17.md) — Retire proposals, declared links replacing the LLM entity graph, and scoped improve planning.
13
13
  - [0.9.16](0.9.16.md) — Source-bound scheduler grants, local execution authority, and split unsafe overrides.
@@ -12,7 +12,7 @@ every change that can break a script, a task or a config.
12
12
  Checked against build 0.10.261013 with the connections and harnesses rework
13
13
  (#1244). The
14
14
  user-facing summary of the whole series is the
15
- [0.10.0 release note](release-notes/0.10.0.md); the per-build detail is in the
15
+ [0.10 release note](release-notes/0.10.261019.md); the per-build detail is in the
16
16
  [CHANGELOG](https://github.com/itlackey/akm/blob/main/CHANGELOG.md).
17
17
 
18
18
  ## What the upgrade preserves
@@ -160,6 +160,33 @@ ignores it.
160
160
  in; if not, the connection has no key and a note names the variables. Set the
161
161
  one you used and run `akm setup --api-key-env NAME`, or store the key with `akm
162
162
  setup`.
163
+ - **Agent work no longer runs on your OpenCode (0.10 betas 0.10.261014 to
164
+ 0.10.261017 only).** Those builds dropped every `opencode-sdk` engine when they
165
+ migrated `config.json`, so `akm info` lists no harness, agent work runs on akm's
166
+ own runtime over your default connection, and a `harness:` or `--harness` that
167
+ names one of your old engines fails with exit 78. akm keeps the file as it was
168
+ before it rewrote it in `<cache dir>/config-backups/` (`~/.cache/akm/config-backups/`
169
+ by default), the five newest `config-<timestamp>.json`; the one that still holds
170
+ `"engines"` is the one to use (`grep -l '"engines"' ~/.cache/akm/config-backups/config-*.json`).
171
+ Read what this release converts it to, in a scratch config directory so
172
+ nothing is written, with the `models.json.<timestamp>` of the same run beside
173
+ it if there is one, then set each harness on your config (leave out the `ok`,
174
+ `shape` and `schemaVersion` keys the output adds):
175
+
176
+ ```sh
177
+ scratch=$(mktemp -d)
178
+ cp ~/.cache/akm/config-backups/config-<timestamp>.json "$scratch/config.json"
179
+ cp ~/.cache/akm/config-backups/models.json.<timestamp> "$scratch/models.json"
180
+ AKM_CONFIG_DIR="$scratch" akm config get harnesses
181
+ akm config set harnesses.<name> '<that entry>'
182
+ ```
183
+
184
+ If no pre-migration copy is left (five later config writes prune it), write the
185
+ entries yourself, one per `opencode-sdk` engine you had, the one `defaults.engine`
186
+ named called `default`: `akm config set harnesses.default
187
+ '{"platform":"opencode","models":{"fast":"<provider/model>","balanced":"<provider/model>","reasoning":"<provider/model>"}}'`.
188
+ Add `"agent": "<name>"` if the engine named one. Run `akm info` after: its
189
+ `agents` row names the harness and the model.
163
190
  - **Scripts that pass `--engine` or `--require-engines`.** They keep running,
164
191
  with one warning each. Change `--engine NAME` to `--connection <name>` or
165
192
  `--harness <name>`: how an old engine name resolves, and when it stops, is
@@ -438,6 +465,23 @@ writes `connections` and `harnesses`, renames the default LLM engine to
438
465
  runs to `improve.processes` and `improve.qualityGate`, and keeps a connection or
439
466
  harness the loader cannot use in the file, with a note on what to fix. It also:
440
467
 
468
+ - keeps every agent engine as a harness, with its `model`, `bin`, `args`,
469
+ `workspace`, `agent` and `timeoutMs`. An `opencode-sdk` engine with no
470
+ `llmEngine` ran your own OpenCode, with its own providers, models and logins,
471
+ so it becomes an `opencode` harness (without `args`, which 0.9 did not pass to
472
+ it); the harness `defaults.engine` named, when
473
+ there are several, is renamed `default`, and `engine:` keys and `--engine`
474
+ follow. Agent work keeps running on the program and model it ran on. An
475
+ `opencode-sdk` engine over an `llmEngine` ran OpenCode over that connection,
476
+ which is what akm's own runtime is, so it has no entry of its own;
477
+ - notes, when there is no `defaults.llmEngine` and no connection, that akm's own
478
+ model work (improve, index passes, extraction, judges) now runs on the default
479
+ harness where 0.9 ran none: 0.9 ran it only where `defaults.llmEngine` or a
480
+ setting named an engine, and a workflow gate's judge ran on `defaults.engine`.
481
+ To keep the 0.9 behaviour, set `modelWork: false` on that harness; a call that
482
+ names the harness still runs there, and a gate's judge then needs a
483
+ connection;
484
+
441
485
  - moves every key akm no longer reads from config (an engine's `apiKeyFile`, a
442
486
  literal or `${secrets/...}` `apiKey`, and the same on a connection,
443
487
  `embedding` or `search.curateRerank`) into `credentials.json`, for the
@@ -457,8 +501,10 @@ harness the loader cannot use in the file, with a note on what to fix. It also:
457
501
  the older entry, and a different key or endpoint leaves both, with a note;
458
502
  - folds `models.json` into the `models` of the connections and harnesses it
459
503
  names (a connection's own column first, then the `*` column and the flat
460
- shorthand, then the engine's own model; a model the config already names
461
- stands; the entries it cannot place are listed in the notes) and moves the
504
+ shorthand, then the engine's own model; a harness engine's own model stands
505
+ over every column, as it is what ran when a request named none; a model the
506
+ config already names stands; the entries it cannot place are listed in the
507
+ notes) and moves the
462
508
  file to `<cache dir>/config-backups/`;
463
509
  - rewrites `engine:` on commands, agents, workflows and task sources to
464
510
  `connection:` or `harness:` by what the name is now (a name that is neither is
@@ -480,9 +526,14 @@ strategy's `engine`, `model`, `llm` and `timeoutMs`, an index pass's `engine`
480
526
  that names a harness (an index pass can only name a connection; with none named
481
527
  it runs where all model work does, on the default connection, else the default
482
528
  harness, restricted where the harness can be), `models.json`
483
- entries that name nothing configured, and an `opencode-sdk` engine's own model,
484
- timeout and workspace (akm's own runtime has no entry in config; the connection
485
- its `llmEngine` named becomes `default`). A workflow run frozen by an earlier
529
+ entries that name nothing configured, and the model, timeout and workspace of an
530
+ `opencode-sdk` engine that ran over an `llmEngine` (akm's own runtime has no
531
+ entry in config; that connection becomes `default`). `workflow.judgeEngine`
532
+ is dropped because a gate's judge runs on the default connection, else the
533
+ default harness; its note says whether that moves the judge, and with no
534
+ `workflow.judgeEngine` a note says when the judge `defaults.engine` ran it on
535
+ is no longer where it runs. A workflow run
536
+ frozen by an earlier
486
537
  release (plan version 7 or lower) whose plan holds a command target cannot be
487
538
  resumed: `akm workflow run` abandons it with a message naming `akm workflow run
488
539
  <ref>` to start afresh. Let such runs finish before you upgrade.
@@ -750,7 +801,7 @@ below every daily alpha. Install the first monthly release explicitly once, for
750
801
  example `npm install -g akm-cli@0.10.261001-beta`; `akm upgrade` works normally
751
802
  from there.
752
803
 
753
- `akm help migrate 0.10.0` prints the [0.10.0 release note](release-notes/0.10.0.md).
804
+ `akm help migrate 0.10.261019` (or `akm help migrate latest`) prints the [0.10 release note](release-notes/0.10.261019.md).
754
805
  The loader looks a note up by its exact file name, so `akm help migrate latest`
755
806
  and a release number such as `0.10.261001` print the CHANGELOG section
756
807
  only.
@@ -106,7 +106,7 @@ akm reads these keys of a connection:
106
106
  | `apiKeyFile` | Retired. `akm migrate apply` leaves an engine's key file here, as written, when it cannot read the file yet; akm ignores it (never reads it or sends it) and a later `akm migrate apply` moves the key it names into `credentials.json`. |
107
107
  | `models` | Alias to model. See [Aliases](#aliases). |
108
108
  | `contextLength` | The model's context window in tokens. `akm improve` sizes its prompts from it (consolidate's chunks, reflect's asset content); unset, it assumes 4096. |
109
- | `timeoutMs` | How long one call may take, in milliseconds; `null` runs unbounded. Unset, a model call stops after 600 000 (ten minutes) and agent work runs until it finishes. The ceiling is 2 147 483 647. |
109
+ | `timeoutMs` | How long one call may take, in milliseconds; `null` runs unbounded. Unset, a model call stops after 600 000 (ten minutes) and agent work runs until it finishes; akm's own runtime also tells a model that keeps repeating one tool call and result, and ends the run if it goes on, but does not stop one that keeps making different calls ([Without a harness](#without-a-harness)). The ceiling is 2 147 483 647. |
110
110
  | `concurrency` | How many requests a workflow `map` step may have in flight on this connection, clamped to 1–64. Unset, 1 on a loopback endpoint (a local model server runs one inference at a time) and 4 on a remote one. akm never sends it. |
111
111
 
112
112
  Every other key, on the connection or in a model entry, is a request field in
@@ -225,13 +225,13 @@ bindings.
225
225
 
226
226
  What asks for a harness decides how akm runs it.
227
227
 
228
- **Agent work** (`akm agent`, `akm command run`, `akm proposal new`, agent tasks and workflow agent steps) runs your program the way you would run it yourself. It gets your environment as it is, with nothing filtered out, and your configuration, plugins, settings and logins as they are. akm sets only its own variables for the run: the directories this akm resolved (`AKM_CONFIG_DIR`, `AKM_DATA_DIR`, `AKM_CACHE_DIR`, `AKM_STATE_DIR`, and `AKM_BUNDLE_DIR` when you set one), so a program that runs `akm` uses the same installation, and, when a task runs it, `AKM_EVENT_SOURCE` (unless already set), so the akm commands the program runs count as machine use, not yours. A workflow unit's or task's own `env:` bindings are set over them. On the command line, after your `args` as you wrote them, akm adds the model or agent the asset or flag names, the agent asset's persona where the program takes one there, and what the program needs to run without a person at the terminal: its print or exec mode and its approve-all switch where it asks before acting. Codex runs with the sandbox your Codex configuration sets, or the one your `args` name; model work runs it with `--sandbox read-only` (below). The prompt goes on standard input where the program reads it there and on the command line where it does not; standard output is the reply. `akm agent` with no `--prompt` starts the program interactively instead. What akm scrubs from the output it captures is in [Architecture: Connections and Harnesses](../architecture/architecture.md#connections-and-harnesses) and, for a workflow, [Workflow Schema](workflow-schema.md#the-childs-environment).
228
+ **Agent work** (`akm agent`, `akm command run`, `akm proposal new`, agent tasks and workflow agent steps) runs your program the way you would run it yourself. It gets your environment as it is, with nothing filtered out, and your configuration, plugins, settings and logins as they are. akm sets only its own variables for the run: the directories this akm resolved (`AKM_CONFIG_DIR`, `AKM_DATA_DIR`, `AKM_CACHE_DIR`, `AKM_STATE_DIR`, and `AKM_BUNDLE_DIR` when you set one), so a program that runs `akm` uses the same installation, and, when a task runs it, `AKM_EVENT_SOURCE` (unless already set), so the akm commands the program runs count as machine use, not yours. A workflow unit's or task's own `env:` bindings are set over them. A run given a directory (`--cwd`, a harness's `workspace`) starts there, and `PWD` names it too, as your shell sets it when you `cd` there; OpenCode takes its directory from `PWD`. On the command line, after your `args` as you wrote them, akm adds the model or agent the asset or flag names, the agent asset's persona where the program takes one there, and what the program needs to run without a person at the terminal: its print or exec mode and its approve-all switch where it asks before acting. Codex runs with the sandbox your Codex configuration sets, or the one your `args` name; model work runs it with `--sandbox read-only` (below). The prompt goes on standard input where the program reads it there and on the command line where it does not; standard output is the reply. `akm agent` with no `--prompt` starts the program interactively instead. What akm scrubs from the output it captures is in [Architecture: Connections and Harnesses](../architecture/architecture.md#connections-and-harnesses) and, for a workflow, [Workflow Schema](workflow-schema.md#the-childs-environment).
229
229
 
230
230
  **Model work** (see [Where each process runs](#where-each-process-runs)) is akm's own process, so akm sets the call up as it needs it. The program has the same environment. akm runs it in a scratch directory that it creates for the call and removes after it, stamps the akm commands it runs `improve`, and runs no native agent of yours. Where the program can be restricted, akm also limits its tools. The "Restricted model work" column of the table says on which platforms (OpenCode: on version 2):
231
231
 
232
232
  - Claude Code runs with `--restricted`, so none of your settings files can widen the tools; with `Read` and `Bash` only for `akm search`, `akm show` and `akm curate`; with no MCP servers; and with no transcript saved.
233
233
  - Codex runs with `--sandbox read-only`.
234
- - OpenCode 2 runs as the `akm-model-work` agent, which akm passes inline with the run, merged into your `OPENCODE_CONFIG_CONTENT` and keeping the rest of it; akm reads that variable as OpenCode does, as JSONC (comments and trailing commas), with its `{env:NAME}` references replaced as OpenCode replaces them when the content reads only that way (a reference written outside a string, such as a number), and leaves it out, with one warning, when it is not valid JSONC holding an object. akm writes it in OpenCode 2's native `agents` map, which OpenCode reads over the legacy `agent` map, so an entry of that name in your config, in either map, inline or in a file, does not change it (a same-named entry in your inline `agent` map is left out). Its tools are limited to reading and searching: every tool is denied except `read`, `glob` and `grep`, and `akm_search`, `akm_show` and `akm_curate` when you have the akm OpenCode plugin installed. A tool that a plugin of yours adds is denied too. The limit is on tools: your plugins' own setup and hooks still run in the session. The run is `--standalone`, one process that ends with it, with no background service left behind, and `--title akm`, which names the session and spares the second model request that would generate a title.
234
+ - OpenCode 2 runs as the `akm-model-work` agent, which akm passes inline with the run, merged into your `OPENCODE_CONFIG_CONTENT` and keeping the rest of it; akm reads that variable as OpenCode does, as JSONC (comments and trailing commas), with its `{env:NAME}` references replaced as OpenCode replaces them when the content reads only that way (a reference written outside a string, such as a number), and leaves it out, with one warning, when it is not valid JSONC holding an object. akm writes it in OpenCode 2's native `agents` map, which OpenCode reads over the legacy `agent` map, so an entry of that name in your config, in either map, inline or in a file, does not change it (a same-named entry in your inline `agent` map is left out). Its tools are limited to reading and searching: every tool is denied except `read`, `glob` and `grep`, and `akm_search`, `akm_show` and `akm_curate` when you have the akm OpenCode plugin installed. A tool that a plugin of yours adds is denied too. OpenCode's built-in browser plugin is left out of the run (`-opencode.browser` after your `plugins`): model work denies the browser anyway, and from OpenCode 2.2.0 the plugin's own rules would keep the `skill` tool listed. The limit is on tools: your plugins' own setup and hooks still run in the session. The run is `--standalone`, one process that ends with it, with no background service left behind, and `--title akm`, which names the session and spares the second model request that would generate a title.
235
235
  - On Claude Code, Codex and OpenCode, `args` do not apply to model work, except a `--model` they name.
236
236
  - OpenCode 1 and every other platform cannot be restricted: the run is unrestricted, in the scratch directory, and akm reports that. The other platforms get the agent-work command line, `args` included.
237
237
  - OpenCode model work sets `OPENCODE_DISABLE_FREE_MODELS=1`, which OpenCode 2.1.2 and later honor: a call with no usable provider fails instead of sending the prompt to OpenCode's hosted free model, and so does a call whose model (named, or your OpenCode's default) is one of its free ones. Agent work does not set it: your OpenCode's models are as you would get running it by hand.
@@ -240,7 +240,7 @@ Where model work is restricted, its tools cannot change the library, so what it
240
240
 
241
241
  **History.** A harness run leaves a session in the program's own history, and `akm proposal extract` and improve read that history like any other. The exceptions are the model-work sessions akm marked: Claude Code keeps no transcript of them, and OpenCode 2 records them under the `akm-model-work` agent, which the reader skips. Codex and OpenCode 1 cannot be marked, so their model-work sessions are read like any other. akm's own runtime (below) keeps its sessions in `<akm data dir>/opencode-runtime/data/opencode/opencode.db`, read the same way.
242
242
 
243
- **Stopping.** When akm stops a run (a timeout, an abort or a signal to akm) it sends the program's process group SIGINT, as Ctrl-C would. If anything in the group still runs after 5 seconds, or as soon as the program itself has exited and left members behind, it sends SIGTERM, and 5 seconds after that SIGKILL if anything still runs. Workflow `exec` units and task commands are stopped the same way. Windows has no process groups, and a signal sent to a process there ends it at once. A program that records how a run ended acts on the SIGINT: OpenCode 2 marks its session interrupted and releases it, and only a run that had to be terminated or killed stays suspended in your OpenCode history, where your own OpenCode's background service may resume it when it next starts (up to ten attempts, OpenCode's own policy). Through OpenCode 2's background service (measured on 2.1.4) the interrupt ends the `opencode` command and the service's turn alike: the service abandons the turn's model request and marks the session interrupted, and keeps running itself.
243
+ **Stopping.** When akm stops a run (a timeout, an abort or a signal to akm) it sends the program's process group SIGINT, as Ctrl-C would. If anything in the group still runs after 5 seconds, or as soon as the program itself has exited and left members behind, it sends SIGTERM, and 5 seconds after that SIGKILL if anything still runs. Workflow `exec` units and task commands are stopped the same way. Windows has no process groups, and a signal sent to a process there ends it at once. A program that records how a run ended acts on the SIGINT: OpenCode 2 marks its session interrupted and releases it, and only a run that had to be terminated or killed stays suspended in your OpenCode history, where your own OpenCode's background service may resume it when it next starts (up to ten attempts, OpenCode's own policy). Through OpenCode 2's background service (measured on 2.1.4 and 2.2.0) the interrupt ends the `opencode` command and the service's turn alike: the service abandons the turn's model request and marks the session interrupted, and keeps running itself.
244
244
 
245
245
  **OpenCode.** The `opencode` platform runs your installed OpenCode, either major version, as `opencode run`; the reply is its standard output. Agent work is that command with the prompt on stdin, your `args` as written, `--model` when akm names a model and `--agent` when the asset names an agent. Your OpenCode owns its configuration, logins, token refresh and sessions: akm reads, copies and embeds nothing of yours.
246
246
  - OpenCode 2 runs agent work through its own background service, which stays up after the command. Add `--standalone` to the harness's `args` for a run that is one process.
@@ -254,13 +254,13 @@ alike.
254
254
  ### Without a harness
255
255
 
256
256
  Agent work runs on akm's own runtime when no harness is configured: a pinned
257
- OpenCode 2 binary (2.1.4) that akm runs as a process for each run, driven by the
257
+ OpenCode 2 binary (2.2.0) that akm runs as a process for each run, driven by the
258
258
  default connection. The npm package and the standalone binary do the same.
259
259
 
260
260
  - **The first run fetches OpenCode.** akm downloads the binary for your platform
261
261
  from the npm registry, one package of about 114 MB (240 MB on disk), checks it
262
262
  against the registry's integrity hash, and keeps it in
263
- `<akm cache dir>/opencode/2.1.4/`; later runs, and later versions of akm that
263
+ `<akm cache dir>/opencode/2.2.0/`; later runs, and later versions of akm that
264
264
  pin the same OpenCode, fetch nothing. Nothing else is downloaded: the binary
265
265
  carries the package it reaches the endpoint with. If the fetch fails the run
266
266
  fails as not started, naming the package, its URL and the cache path. With no
@@ -304,7 +304,37 @@ default connection. The npm package and the standalone binary do the same.
304
304
  - A run reports its session id and the tokens its turn used, read from that
305
305
  session once the process has ended; a workflow's `budget.max_tokens` counts
306
306
  them. A failed run is a non-zero exit with OpenCode's own message
307
- (`non_zero_exit`), as for a harness.
307
+ (`non_zero_exit`), as for a harness; when the session recorded why its turn
308
+ failed, the run's error carries that too, so a workflow's unit shows it.
309
+ - A model that repeats itself is told, then stopped. When it has made the same
310
+ tool call, with the same input, and been given the same result three turns in
311
+ a row, akm adds a message from the user to its next request: it names the
312
+ tool, says the result will not change, asks the model to use the result it
313
+ has or take a different approach, and says that calling it again stops the
314
+ run. **That one request overrides a lower temperature the connection sets**:
315
+ a `temperature` below 0.7 (0, say) is sent as 0.7, because a model sampled
316
+ greedily (temperature 0) gave the same call again to every wording in every
317
+ try, so at 0 the message alone does nothing, and at 0.7 it left the repeat in
318
+ about half of them. A connection that sets no `temperature` sends none on that
319
+ request either (the endpoint's default applies, and OpenAI's reasoning models
320
+ refuse any other), and one of 0.7 or more is kept. Every other request keeps
321
+ the connection's settings. If the model makes the same call again, or, after
322
+ other calls, makes it three turns in a row again, the run fails
323
+ (`non_zero_exit`) with a message that names the tool. One that changes course
324
+ is not stopped. Each session of a run (a subagent's too) is told for itself.
325
+ OpenCode has no check of its own for this, and with `timeoutMs` unset such a
326
+ run would never end. A call whose result changes is not a repeat, but a poll
327
+ that gets the same answer three times in a row is. An output too long to send
328
+ whole is compared by its text, not by the file OpenCode saves it to. The
329
+ message is added to the request on its way to the model, so OpenCode's stored
330
+ session does not show it; the stop is recorded as any failure is. Only akm's
331
+ own runtime does this; a harness is your program, with whatever limits it has.
332
+ - A run that keeps making different calls is not stopped by that. Its timeout
333
+ bounds it: the connection's `timeoutMs`, one the run is given (`akm agent
334
+ --timeout-ms`, `akm workflow run --timeout`, a workflow unit's `timeout`) or,
335
+ in a scheduled task, the task's `timeout:` (six hours when unset). With none,
336
+ as for `akm agent` and `akm workflow run` by default, it runs until it
337
+ finishes.
308
338
  - Runs that start together, in one akm process or several, wait while the first
309
339
  run of this OpenCode version prepares its database alone.
310
340
 
@@ -736,7 +766,7 @@ index and a warning from `akm health`.
736
766
  - `models/Xenova/bge-small-en-v1.5/` holding `tokenizer.json`,
737
767
  `tokenizer_config.json`, `config.json` and `onnx/model.onnx`, or set `HF_HOME`
738
768
  to a directory that holds them and `HF_HUB_OFFLINE=1`.
739
- - `opencode/2.1.4/opencode` (`opencode.exe` on Windows) for akm's own agent
769
+ - `opencode/2.2.0/opencode` (`opencode.exe` on Windows) for akm's own agent
740
770
  runtime.
741
771
  The default is `"off"` so a bare or headless install (`akm bundle create`, `--yes`,
742
772
  `--config`) never silently downloads the local embedding model on first
@@ -1139,18 +1169,20 @@ asset keys move as the table says.
1139
1169
  | In the file | What `akm migrate apply` does |
1140
1170
  | --- | --- |
1141
1171
  | `engines.<name>` with `kind: "llm"` | `connections.<name>`. `endpoint`, `contextLength`, `timeoutMs`, `concurrency` and an `apiKey` that is a `$VAR` are kept. `model` becomes `models`, with `fast`, `balanced` and `reasoning` all naming it. `temperature`, `maxTokens`, `enableThinking`, `reasoningEffort` and `extraParams` become request fields (`temperature`, `max_tokens`, `enable_thinking` with `chat_template_kwargs.enable_thinking`, `reasoning_effort`, and the extras as written). `kind`, `provider` and `supportsJsonSchema` are dropped, with a note. |
1142
- | `engines.<name>` with `kind: "agent"` and `platform: "opencode-sdk"` | Removed: akm's own runtime has no entry. Its `llmEngine` connection becomes `default`. |
1172
+ | `engines.<name>` with `kind: "agent"` and `platform: "opencode-sdk"`, no `llmEngine` | `harnesses.<name>` with `platform: "opencode"`. The engine ran your own OpenCode, with its providers, models and logins, and the `opencode` harness runs it now. `bin`, `workspace`, `agent` and `timeoutMs` are kept, and `model` (an OpenCode `provider/model`) becomes `models`, naming it for all three aliases. `args` is dropped, with a note: 0.9 did not pass it to OpenCode. |
1173
+ | `engines.<name>` with `kind: "agent"` and `platform: "opencode-sdk"`, with an `llmEngine` | Removed: OpenCode ran over that connection, which is what akm's own runtime is, so it has no entry. When `defaults.llmEngine` or `defaults.engine` names the engine, and `defaults.llmEngine` names no connection, the `llmEngine` connection becomes `default`. The engine's `model`, `timeoutMs`, `workspace`, `bin` and `agent` are dropped, with a note naming those it set. |
1143
1174
  | `engines.<name>` with `kind: "agent"`, any other platform | `harnesses.<name>`, keeping `platform`, `bin`, `args`, `workspace`, `agent` and `timeoutMs`. `model` becomes `models`, naming it for all three aliases. |
1144
- | `defaults.llmEngine`, else `defaults.engine` when it names an LLM engine | That connection is renamed `default`, and every reference to the old name follows. An entry already called `default` moves aside to `legacy-default`, or the first `legacy-default-<n>` nothing else has: the renaming is one name to one name, so no two entries share a name and none is lost. |
1145
- | `defaults.engine` naming an agent engine, when there are several | That harness is renamed `default`. |
1175
+ | `defaults.llmEngine`, else `defaults.engine` when it names an LLM engine | That connection is renamed `default`, and every reference to the old name follows. An entry already called `default` moves aside to `legacy-default`, or the first `legacy-default-<n>` nothing else has: the renaming is one name to one name, so no two entries share a name and none is lost. A `defaults.llmEngine` that named an agent engine ran akm's model work there; model work runs on the default connection, else the default harness, so a note says when that is another place and names `improve.harness`. With no `defaults.llmEngine` and no connection, 0.9 ran no model work unless a setting named an engine and the default harness takes it now; a note says so and how to turn it off (`modelWork: false`). |
1176
+ | `defaults.engine` naming an agent engine, when there are several | That harness is renamed `default`. With no `defaults.engine`, an engine called `opencode-sdk` is the default agent engine, as the 0.9 fallback made it. |
1177
+ | No `defaults.engine` | 0.9 ran agent work on your own OpenCode, when it was installed. A note says where agent work runs now: on the harness if one is configured, else on akm's own runtime, and then how to enable the harness (`akm setup --harness opencode`). |
1146
1178
  | `defaults.improveStrategy` | `improve.strategy`. |
1147
- | `models.json` | Folded into the `models` of the connections and harnesses it names; what it cannot place is listed in the notes. The file moves to `config-backups/` in the cache directory. |
1179
+ | `models.json` | Folded into the `models` of the connections and harnesses it names; what it cannot place is listed in the notes. The `opencode-sdk` column names the harnesses that were `opencode-sdk` engines, and the `opencode` column those that were `platform: "opencode"`. A harness whose engine had a `model` of its own keeps it for every alias, over any column: it is what ran when a request named none. The file moves to `config-backups/` in the cache directory. |
1148
1180
  | `apiKeyFile`, a literal `apiKey`, a `${secrets/...}` `apiKey` | The key moves to `credentials.json` for the connection and its endpoint; a note names where it was, never its value. A key that cannot be read stays on the connection as it was (`apiKey`, or `apiKeyFile` for a key file), with a note that it is still to do; a later run moves it once it can be read. |
1149
1181
  | `AKM_ENGINE_<NAME>_API_KEY` or `AKM_LLM_API_KEY` set in the environment | `apiKey: "$AKM_ENGINE_<NAME>_API_KEY"` (or `$AKM_LLM_API_KEY`) on that connection. Set in no variable, an engine that names no key gets none, and a note names the variables 0.9 read. |
1150
1182
  | `improve.strategies.<name>.engine`, `model`, `llm`, `timeoutMs` | Dropped, with a note: a strategy says which processes run, not where. |
1151
1183
  | `engine`, `model`, `llm`, `timeoutMs` on a strategy's process, its `qualityGate` or its `triage.judgment` | Moved to `improve.processes.<process>` or `improve.qualityGate`, with `engine` becoming `connection` or `harness` by what it named. When that place already says, the first one is kept, with a note. |
1152
1184
  | `index.defaults.*`, `index.<pass>.engine` | `index.*`, and `connection`. An index pass cannot name a harness, so an engine that named one is dropped, with a note; a pass that names nothing runs where model work does: on the default connection, else the default harness. |
1153
- | `workflow.judgeEngine` | Dropped, with a note. |
1185
+ | `workflow.judgeEngine` | Dropped, with a note: a gate's judge runs on the default connection, else the default harness. The note says whether the engine it named is that default, or the judge has moved. With none set, 0.9 ran the judge on `defaults.engine`; a note says when that is not where it runs now. |
1154
1186
  | `engine:` in an asset's frontmatter, a workflow step or a task source | `connection:` or `harness:`, by what the configured target is; a name it cannot place becomes `harness:`, with a note. A bundle akm may not change, and an asset that is a symbolic link, are skipped. |
1155
1187
 
1156
1188
  An `engine:` key on an asset that has not been migrated is read the same way,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akm-cli",
3
- "version": "0.10.261017-beta",
3
+ "version": "0.10.261019",
4
4
  "type": "module",
5
5
  "description": "akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cursor.",
6
6
  "keywords": [