akm-cli 0.9.14 → 0.9.15-beta.2

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 (120) hide show
  1. package/CHANGELOG.md +559 -0
  2. package/STABILITY.md +6 -3
  3. package/dist/akm +54 -1
  4. package/dist/akm-migrate +34 -1
  5. package/dist/assets/prompts/reflect-feedback-framing.md +1 -0
  6. package/dist/assets/prompts/reflect-llm-framed-contract.md +2 -0
  7. package/dist/assets/prompts/reflect-llm-schema-contract.md +2 -0
  8. package/dist/assets/tasks/core/improve.yml +1 -1
  9. package/dist/assets/tasks/core/index-refresh.yml +1 -1
  10. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +1 -1
  11. package/dist/assets/tasks/improve/akm-improve-catchup.yml +1 -1
  12. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
  13. package/dist/assets/tasks/improve/akm-improve-frequent.yml +1 -1
  14. package/dist/assets/tasks/improve/akm-improve-nightly.yml +1 -1
  15. package/dist/cli/retired-commands.js +0 -1
  16. package/dist/cli/shared.js +9 -0
  17. package/dist/cli/unknown-flags.js +1 -0
  18. package/dist/cli.js +40 -3
  19. package/dist/commands/config-cli.js +85 -3
  20. package/dist/commands/env/env-cli.js +1 -42
  21. package/dist/commands/env/env.js +1 -1
  22. package/dist/commands/env/secret-cli.js +1 -2
  23. package/dist/commands/health/checks.js +357 -63
  24. package/dist/commands/health/engine-usage.js +45 -0
  25. package/dist/commands/health/improve-metrics.js +18 -0
  26. package/dist/commands/health/llm-usage.js +41 -1
  27. package/dist/commands/health/plugin-staleness.js +7 -3
  28. package/dist/commands/health/version-drift.js +93 -0
  29. package/dist/commands/health/windows.js +3 -1
  30. package/dist/commands/health.js +44 -9
  31. package/dist/commands/improve/consolidate/chunking.js +4 -2
  32. package/dist/commands/improve/improve-cli.js +99 -5
  33. package/dist/commands/improve/improve-report.js +154 -0
  34. package/dist/commands/improve/improve-result-file.js +45 -33
  35. package/dist/commands/improve/improve-strategies.js +133 -3
  36. package/dist/commands/improve/improve-usage-report.js +182 -0
  37. package/dist/commands/improve/improve.js +40 -3
  38. package/dist/commands/improve/locks.js +28 -78
  39. package/dist/commands/improve/planner.js +1 -0
  40. package/dist/commands/improve/preparation.js +9 -1
  41. package/dist/commands/improve/reflect.js +44 -4
  42. package/dist/commands/models-cli.js +50 -1
  43. package/dist/commands/proposal/repository.js +8 -3
  44. package/dist/commands/proposal/validators/proposal-quality-validators.js +41 -6
  45. package/dist/commands/proposal/validators/proposal-validators.js +24 -0
  46. package/dist/commands/read/search-cli.js +38 -2
  47. package/dist/commands/read/show.js +103 -4
  48. package/dist/commands/sources/info.js +5 -1
  49. package/dist/commands/sources/installed-stashes.js +58 -16
  50. package/dist/commands/sources/self-update.js +2 -2
  51. package/dist/commands/sources/stash-cli.js +48 -0
  52. package/dist/commands/tasks/tasks-cli.js +49 -2
  53. package/dist/commands/workflow-cli.js +86 -12
  54. package/dist/core/asset/markdown-fragments.js +35 -0
  55. package/dist/core/config/config-schema.js +14 -0
  56. package/dist/core/config/config.js +302 -24
  57. package/dist/core/config/schema/embedding.js +41 -0
  58. package/dist/core/env-secret-ref.js +58 -5
  59. package/dist/core/errors.js +30 -0
  60. package/dist/core/file-lock.js +49 -15
  61. package/dist/core/improve-result.js +51 -0
  62. package/dist/core/loopback.js +17 -0
  63. package/dist/core/parent-watchdog.js +64 -0
  64. package/dist/core/paths.js +11 -0
  65. package/dist/core/run-lock.js +107 -0
  66. package/dist/core/sensitive-marker-path.js +19 -0
  67. package/dist/core/state-db.js +74 -14
  68. package/dist/indexer/index-rebuild-lock.js +73 -0
  69. package/dist/indexer/index-writer-lock.js +40 -1
  70. package/dist/indexer/index-written-assets.js +29 -1
  71. package/dist/indexer/indexer.js +93 -29
  72. package/dist/indexer/materialize-embeddings.js +564 -48
  73. package/dist/indexer/search/db-search.js +49 -2
  74. package/dist/indexer/search/search-source.js +23 -1
  75. package/dist/integrations/agent/engine-resolution.js +96 -6
  76. package/dist/integrations/agent/execution-definitions.js +6 -15
  77. package/dist/integrations/agent/execution-lowering.js +6 -1
  78. package/dist/integrations/agent/execution-preparation.js +1 -1
  79. package/dist/integrations/agent/model-map.js +123 -20
  80. package/dist/integrations/agent/prompts.js +40 -8
  81. package/dist/integrations/agent/runner-dispatch.js +9 -3
  82. package/dist/integrations/agent/runner.js +2 -0
  83. package/dist/llm/client.js +8 -3
  84. package/dist/llm/embedder.js +20 -8
  85. package/dist/llm/embedders/local.js +10 -2
  86. package/dist/llm/embedders/remote.js +497 -32
  87. package/dist/output/shapes/helpers.js +38 -2
  88. package/dist/output/shapes/models-list.js +16 -0
  89. package/dist/output/shapes/passthrough.js +2 -0
  90. package/dist/output/shapes.js +4 -0
  91. package/dist/output/text/command-format.js +29 -0
  92. package/dist/output/text/helpers.js +1 -1
  93. package/dist/output/text/improve-report.js +27 -0
  94. package/dist/{commands/env/marker-path.js → output/text/models.js} +4 -3
  95. package/dist/output/text/show-format.js +4 -0
  96. package/dist/output/text.js +4 -0
  97. package/dist/scripts/akm-migrate-node.js +25146 -21759
  98. package/dist/scripts/akm-migrate.js +24271 -20885
  99. package/dist/storage/repositories/embedding-salvage-repository.js +184 -0
  100. package/dist/storage/repositories/improve-runs-repository.js +34 -0
  101. package/dist/storage/repositories/index-fts-repository.js +49 -6
  102. package/dist/storage/repositories/index-schema.js +16 -0
  103. package/dist/storage/repositories/index-vec-repository.js +30 -0
  104. package/dist/storage/repositories/workflow-runs-repository.js +55 -18
  105. package/dist/tasks/backends/cron.js +14 -7
  106. package/dist/tasks/run/run-native-task.js +23 -1
  107. package/dist/tasks/run/run-workflow-task.js +16 -0
  108. package/dist/workflows/exec/child-workflow.js +2 -2
  109. package/dist/workflows/exec/dispatch-redaction.js +21 -9
  110. package/dist/workflows/exec/run-workflow.js +6 -5
  111. package/dist/workflows/runtime/runs.js +33 -5
  112. package/docs/migration/release-notes/0.9.15.md +133 -0
  113. package/docs/migration/release-notes/README.md +5 -0
  114. package/docs/reference/cli.md +271 -30
  115. package/docs/reference/configuration.md +234 -21
  116. package/docs/reference/data-and-telemetry.md +8 -0
  117. package/docs/reference/tasks.md +16 -1
  118. package/docs/reference/workflow-schema.md +5 -1
  119. package/package.json +1 -1
  120. package/schemas/akm-config.json +47 -0
@@ -117,6 +117,7 @@ Every command exits with one of the following codes:
117
117
  | 2 | Usage / bad input | `UsageError` |
118
118
  | 4 | Health warning (`akm health` only) | — |
119
119
  | 70 | Internal / unclassified error | unexpected throw |
120
+ | 75 | Transient — retry shortly (sysexits `EX_TEMPFAIL`); another akm process holds a lock or is writing `state.db` right now, not a bad command line | `TransientError` |
120
121
  | 78 | Configuration error | `ConfigError` |
121
122
 
122
123
  Failures classified by akm emit a JSON error envelope on **stderr** before
@@ -195,7 +196,7 @@ The setup wizard configures AKM in two steps:
195
196
 
196
197
  **Step 1 — Small model connection** (for background processing)
197
198
  Configures the OpenAI-compatible endpoint and model used for `akm index`
198
- metadata enhancement, `akm remember --enrich`, and `akm curate --rerank`. Supports Ollama,
199
+ metadata enhancement and `akm remember --enrich`. Supports Ollama,
199
200
  OpenAI, LM Studio, or any custom endpoint. Skipping disables enrichment features.
200
201
 
201
202
  **Step 2 — Agent connection** (for agentic commands)
@@ -218,10 +219,12 @@ Build or refresh the search index.
218
219
 
219
220
  ```sh
220
221
  akm index # Incremental (only changed directories)
221
- akm index --full # Full rebuild
222
+ akm index --full # Full rebuild (reuses unchanged embeddings — see below)
222
223
  akm index --verbose # Print phase progress to stderr
223
224
  akm index --clean # Normal index + remove stale entries from the DB
224
225
  akm index --clean --dry-run # Report stale entries without deleting
226
+ akm index --reembed # Force re-embedding of every entry
227
+ akm index --skip-if-locked # for scheduled/opportunistic runs: skip (exit 0) if a run is already in progress
225
228
  ```
226
229
 
227
230
  Returns stats: `totalEntries`, `generatedMetadata`, `directoriesScanned`,
@@ -231,6 +234,18 @@ semantic-search settings, and phase-by-phase progress to stderr while the
231
234
  index is being built. Malformed workflow assets are skipped with file-path
232
235
  warnings instead of aborting the full run.
233
236
 
237
+ **Progress in non-verbose JSON mode (default output format, #954):** even
238
+ without `--verbose`, phase-start messages and the embedding heartbeat
239
+ (`Still generating embeddings: X/N stored, F failed; waiting on embedding
240
+ provider.`) are now written to stderr, and a failed embedding batch logs at
241
+ the default level instead of `--verbose`-only — a long-running index build
242
+ against a slow or unresponsive provider is no longer silent until the whole
243
+ run finishes. Text-mode output keeps its spinner instead (no stderr line
244
+ growth); JSON stdout output is unaffected either way. The high-frequency
245
+ per-batch `Embedded N/M entries.` line stays out of non-verbose stderr (it
246
+ fires after every committed batch) — pass `--verbose` for that level of
247
+ detail.
248
+
234
249
  **`--clean` flag:** After indexing completes, verifies every indexed entry's source
235
250
  file still exists on disk. Removes any entries whose file is missing (for local
236
251
  bundle sources only; remote entries are skipped). Returns a `clean` block in the
@@ -239,6 +254,43 @@ Use `--clean` to resolve the edge case where a deleted file in an unchanged
239
254
  directory lingers in the index across incremental runs. With `--dry-run`, reports
240
255
  which entries would be removed without modifying the database.
241
256
 
257
+ **`--full` no longer re-embeds unchanged content (#955):** a full rebuild
258
+ (and an index-generation bump on first open under a new binary) used to
259
+ delete every embedding unconditionally, forcing a full re-embed of the
260
+ whole corpus even when nothing changed. Vectors about to be discarded are
261
+ now salvaged (keyed by a hash of their content plus the fingerprint they
262
+ were generated under) and handed straight back to unchanged entries at the
263
+ start of the next embedding pass, with zero provider calls for them — a
264
+ progress line reports the split (`Reused N embeddings from the previous
265
+ generation; embedding M new.`). Content that changed even by one byte, or
266
+ a fingerprint that no longer matches, still goes through the provider
267
+ normally. `--reembed` is the way to force a full re-embed regardless.
268
+
269
+ **`--reembed` flag:** Forces a full purge and re-embed of every entry,
270
+ independent of the embedding-model-rename compatibility check described
271
+ below. Ordinary indexing already tells a config-only rename of
272
+ `embedding.model` (e.g. a gateway that changes how it names the same model)
273
+ apart from a genuine model change, and keeps the stored vectors when they
274
+ are still compatible; `--reembed` skips that check and forces a rebuild
275
+ regardless of what it would have decided.
276
+
277
+ **`--skip-if-locked` flag:** Every explicit `akm index` run acquires an
278
+ opt-in, PID-liveness-only rebuild lock and releases it on exit — this is
279
+ advisory, never the blocking lock #872 removed (see
280
+ [Locks](https://github.com/itlackey/akm/blob/main/docs/architecture/internals/indexing.md#locks)). A human-typed
281
+ `akm index` with no flag is never gated by it: if another run already holds
282
+ the lock, it warns and proceeds anyway, contending with the existing run.
283
+ `--skip-if-locked` changes that only for the invocation that passes it: if
284
+ the lock is already held by a live process, it skips gracefully (exit 0,
285
+ `{ ok: true, skipped: { reason: "lock-held", pid, launcherPid, startedAt } }`
286
+ — `launcherPid` is the holder's launcher pid when known, `null` otherwise,
287
+ #956) instead of contending. `akm index` and `akm curate` are both safe to call frequently —
288
+ `curate` never blocks on a rebuild in progress ([read-path indexing stays
289
+ non-blocking](#curate)) — but a hook, cron job, or scheduled task that
290
+ invokes `akm index` directly should pass `--skip-if-locked` so it steps
291
+ aside instead of piling up behind a longer rebuild (the shipped
292
+ `index-refresh` task does this).
293
+
242
294
  `akm index` always rebuilds the search index and keeps metadata in the index.
243
295
  When a selected named LLM engine (`defaults.llmEngine` or an indexing-pass
244
296
  override) is configured and the per-pass gate allows it, metadata
@@ -261,6 +313,10 @@ Returns a JSON object with:
261
313
  | `version` | Current akm version |
262
314
  | `bundleDir` | Primary bundle directory — same resolution `akm bundle list` uses |
263
315
  | `defaultBundle` | Name of the primary bundle from config, or `null` when none is configured |
316
+ | `dataDir` | Resolved data directory (`getDataDir()`) |
317
+ | `configDir` | Resolved config directory (`getConfigDir()`) |
318
+ | `cacheDir` | Resolved cache directory (`getCacheDir()`) |
319
+ | `stateDir` | Resolved state directory (`getStateDir()`) |
264
320
  | `assetTypes` | List of recognized asset types |
265
321
  | `searchModes` | Active search modes (`fts`, optionally `semantic` and `hybrid`) |
266
322
  | `semanticSearch` | Semantic search status: `mode`, `status`, and optional `reason`/`message` |
@@ -277,6 +333,10 @@ Returns a JSON object with:
277
333
 
278
334
  Use `akm info` to verify that semantic search is working after setup.
279
335
 
336
+ Scripts that need akm's resolved paths (for example a health check that
337
+ differs between a host install and a container) can read them with
338
+ `akm info --format json | jq -r .dataDir` instead of hardcoding a path.
339
+
280
340
  ### health
281
341
 
282
342
  Check akm runtime health, durable state, and recent improve-loop telemetry.
@@ -298,14 +358,15 @@ akm health --report --window-compare 7d --format html
298
358
  | `--window-compare` | Compare the current window against the prior window of the same duration (e.g. `24h`, `7d`). With `--report`, overrides the default trend window. |
299
359
  | `--group-by` | Group rows by `run` (one row per `improve_runs` entry). Omit for the default summary. |
300
360
  | `--windows` | Explicit comparison window(s) as `name=...,since=ISO,until=ISO` (repeatable, up to 4). Mutually exclusive with `--window-compare`. |
301
- | `--no-probe` | Skip the `default-llm-engine` / `configured-engines` reachability probes (for an offline or air-gapped host). |
361
+ | `--no-probe` | Skip the `default-llm-engine` / `configured-engines` reachability probes and the `cli-version` update check (for an offline or air-gapped host). |
302
362
 
303
363
  The command reads `state.db`, verifies that the required tables exist, performs a
304
364
  write-read probe against the events stream, inspects `task_history`, checks the
305
365
  default agent engine, and summarizes recent `improve_*` events. Unless
306
366
  `--no-probe` is given, it also sends a bounded (3s timeout) reachability probe
307
367
  to the `default-llm-engine` and every `configured-engines` LLM connection (and
308
- an SDK engine's LLM fallback), one probe per distinct endpoint.
368
+ an SDK engine's LLM fallback), one probe per distinct endpoint, and checks the
369
+ installed akm-cli version against the latest GitHub release (`cli-version`).
309
370
 
310
371
  Primary result fields:
311
372
 
@@ -313,7 +374,7 @@ Primary result fields:
313
374
  | --- | --- |
314
375
  | `status` | Overall health verdict: `pass`, `warn`, or `fail` |
315
376
  | `hardChecks` | Deterministic checks such as `state-db-schema`, `state-db-round-trip`, `state-db-migrations`, `task-log-backing`, `active-runs`, `default-engine`, `model-map-files`, `default-llm-engine`, `configured-engines`, and `active-improve-strategy` |
316
- | `advisories` | Non-fatal warnings including `semantic-search-runtime` and `session-extraction` (akmExtract pipeline health) |
377
+ | `advisories` | Non-fatal warnings including `semantic-search-runtime`, `session-extraction` (akmExtract pipeline health), `cli-version` (installed vs latest release), `thinking-control` (an `enableThinking: false` engine whose recorded usage still shows reasoning tokens), and `engine-last-used` (an engine bound to an enabled improve process with no recorded use in 30 days) |
317
378
  | `metrics` | Aggregate task/runtime metrics: `taskFailRate`, `agentFailureRate`, `stuckActiveRuns`, `logBackingRate`, `probeRoundTripMs` |
318
379
  | `improve` | Recent improve-loop counts derived from `improve_invoked`, `improve_skipped`, and `improve_completed` events |
319
380
 
@@ -333,10 +394,25 @@ holds a pending historical-destructive migration and something other than
333
394
  `default-llm-engine` and `configured-engines` probe reachability (not just
334
395
  configuration) for a `kind: "llm"` engine — an unreachable endpoint is a hard
335
396
  `fail` for `default-llm-engine` and a `warn` for any other engine. `--no-probe`
336
- skips this. `active-improve-strategy` names the resolved engine per process
397
+ skips this. When a required credential is missing from the shell but an
398
+ `env/` asset defines the same variable name, the warn names that asset's ref
399
+ (never the variable name) and points at `akm env run <ref> -- ...`.
400
+ `active-improve-strategy` names the resolved engine per process
337
401
  in its evidence and message, so a strategy-level `engine` pin that shadows
338
402
  `defaults.llmEngine` is visible without config archaeology.
339
403
 
404
+ `cli-version` compares the installed akm-cli version against the latest
405
+ GitHub release — the same source `akm upgrade` trusts — and `warn`s with the
406
+ upgrade command when a newer release exists. `--no-probe`, offline, or a
407
+ rate-limited request all degrade it to `unknown`, never a false `warn`.
408
+
409
+ `engine-last-used` checks, for every engine bound to an enabled process in
410
+ the active improve strategy, whether it has a recorded `llm_usage` call in
411
+ the last 30 days (independent of `--since`). It `warn`s naming the idle
412
+ engine and its bound process, and stays `unknown` — not a noisy `warn` —
413
+ until at least one improve run has been recorded (started) in that window,
414
+ so a fresh install is quiet.
415
+
340
416
  The `session-extraction` advisory is derived from the `extract_sessions_seen`
341
417
  ledger for the last 7 days — not `improve_runs`, which the hook-driven `akm
342
418
  proposal extract --session-id ...` invocation never writes. It reports
@@ -439,6 +515,12 @@ availability:
439
515
  - **`ref`** -- The asset handle to pass to `akm show` (for example
440
516
  `team//scripts/deploy.sh`); present at `brief`, `full`, and `agent` for local
441
517
  hits
518
+ - **fragment provenance** -- when `ref` selects an indexed Markdown fragment,
519
+ `selectedRef` and `parentRef` distinguish the ranked evidence from its parent;
520
+ one-based `fragmentOrdinal`, `fragmentCount`, source-line bounds, neighbor
521
+ refs, and separate fragment/parent size estimates are available without
522
+ changing ranking. `estimatedTokens` describes the fragment for a
523
+ fragment-qualified hit; `parentEstimatedTokens` describes the whole asset.
442
524
  - **`name`** -- The asset's filename or identifier; present at all levels
443
525
  - **`origin`** -- The source bundle (e.g. `npm:@scope/pkg`), present only for
444
526
  managed source assets; surfaced at `full` only
@@ -482,9 +564,9 @@ ranking.
482
564
 
483
565
  ### curate
484
566
 
485
- Pick the assets worth loading for a task. Unlike `akm search`, curate reranks by
486
- intent, attaches a preview and run details per hit, adds related support refs,
487
- and summarizes the set — the usual starting point for an agent.
567
+ Pick the assets worth loading for a task. Unlike `akm search`, curate attaches
568
+ a preview and run details per hit, adds related support refs, and summarizes
569
+ the set — the usual starting point for an agent.
488
570
 
489
571
  ```sh
490
572
  akm curate "plan a release"
@@ -515,6 +597,10 @@ only for read-only items. Their `followUp` remains `akm show <ref>` rather than
515
597
  being replaced by clone guidance.
516
598
  Use `--type workflow` when you want curated step-by-step procedures instead of
517
599
  individual scripts, skills, or docs.
600
+ `akm curate` is safe to call frequently, including from a hook that fires on
601
+ every prompt: it only ever reads the index as it currently stands (the same
602
+ non-blocking `ensureIndex()` path `search` uses) and never waits on or
603
+ contends with a full `akm index` rebuild in progress.
518
604
  Use `--no-track-usage` when this inspection must not update local usage or
519
605
  ranking signals.
520
606
 
@@ -535,6 +621,7 @@ akm show commands/release
535
621
  akm show workflows/ship-release
536
622
  akm show knowledge/guide # the whole document
537
623
  akm show knowledge/guide#authentication # just that section
624
+ akm show '<search-result-ref>' --context lead --max-tokens 800
538
625
  akm show knowledge/guide#nope # lists the available fragment slugs
539
626
 
540
627
  # Bundle .meta/ orientation docs — direct-read, not indexed:
@@ -548,6 +635,14 @@ akm show memories/retro --filter user=alice
548
635
  akm show memories/retro --filter user=alice --filter agent=claude
549
636
  ```
550
637
 
638
+ | Flag | Values | Default | Description |
639
+ | --- | --- | --- | --- |
640
+ | `--context` | `exact`, `lead` | `exact` | Fragment presentation. `exact` preserves the selected-section behavior. `lead` returns the indexed-safe first fragment followed by `[Selected matching fragment]` and the selected fragment. |
641
+ | `--max-chars` | positive integer | `3200` for `lead` | Hard contextual content budget in characters; requires `--context lead` and is mutually exclusive with `--max-tokens`. |
642
+ | `--max-tokens` | positive integer | _(none)_ | Approximate contextual budget using four characters per token; requires `--context lead` and is mutually exclusive with `--max-chars`. |
643
+ | `--filter` | `<key>=<value>` | _(none)_ | Repeatable scope filter (`user`, `agent`, `run`, `channel`). |
644
+ | `--track-usage`, `--no-track-usage` | flag | `true` | Record or suppress local usage-event and ranking updates for this successful read. |
645
+
551
646
  `meta` is not an asset type — `[<origin>//]meta[:<name>]` direct-reads a
552
647
  human-authored orientation doc from a bundle's optional `.meta/` directory
553
648
  (`<name>` defaults to `index`; `.meta/<name>.md` is tried before an
@@ -575,8 +670,27 @@ reduced metadata-first view without `content`/`template`/`prompt`;
575
670
  `editable` is `false`, `editHint`; `--shape agent` strips non-action metadata
576
671
  (e.g. `origin`, `tags`) down to the action-relevant field set while still
577
672
  including `ref`/`path`/`editable`; `--shape summary`
578
- returns a compact view with only `type`, `name`, `ref`, `description`, `tags`,
579
- `parameters`, `workflowTitle`, `action`, `run`, `origin`, and `keys`.
673
+ returns a compact view with `type`, `name`, `ref`, `description`, `tags`,
674
+ `parameters`, `workflowTitle`, `action`, `run`, `origin`, and `keys`, plus the
675
+ optional fragment metadata described below.
676
+
677
+ Opaque fragment shows and `--context lead` keep `ref` as the canonical parent
678
+ identity and add
679
+ `selectedRef`, `parentRef`, one-based `fragmentOrdinal`, `fragmentCount`,
680
+ `startLine`, `endLine`, optional `previousRef`/`nextRef`, and separate
681
+ fragment/parent character and token estimates. Contextual shows also report
682
+ `contextMode`, `contextMaxChars`, and `contextTruncated`. Heading aliases are
683
+ canonicalized in contextual `selectedRef` to the resolved opaque indexed
684
+ selector. Default exact shows through a friendly `#heading` retain their
685
+ source-live body and do not attach indexed-safe provenance that could describe
686
+ a different revision or projection.
687
+
688
+ `--context lead` is opt-in and accepts only fragment-qualified indexed Markdown
689
+ assets. Both the lead and selected content come from the same line-preserving,
690
+ safe indexed revision used by fragment search, even when the source file changes
691
+ between search and show. The selected block is labelled and kept last. When the
692
+ budget is tight, AKM clips or omits lead content before clipping selected
693
+ evidence; `contextTruncated` reports either case.
580
694
 
581
695
  Returns type-specific payloads:
582
696
 
@@ -618,6 +732,7 @@ akm workflow resume <run-id>
618
732
  akm workflow abandon <run-id>
619
733
  akm workflow list --active
620
734
  akm workflow list --children # also list child workflow runs
735
+ akm workflow list --all-scopes # include runs started from a different working directory
621
736
  akm workflow plan workflows/ship-release # compile+freeze preview, zero writes
622
737
  ```
623
738
 
@@ -630,8 +745,8 @@ Subcommands:
630
745
  | --- | --- |
631
746
  | `create <name>` | Validate and write a Markdown workflow under `workflows/`. `--path <dir>` places it in a subdirectory; `--from <file>` imports content; `--force` (requires `--from` or `--reset`) overwrites; `--print` prints the template that would be written instead of writing it |
632
747
  | `run <run-id\|ref>` | Stable canonical start/resume/execute command. A ref starts a run or resumes the active run in the current scope (announced as `resumed: true`, see below); a run id continues that exact active run. `--new` starts a fresh run even when one is already active. Executes until completion, failure, verification rejection, interruption, or an explicit limit |
633
- | `status <run-id\|ref>` | Show the full run state, including all step statuses. `--units` also lists per-unit rows from the run journal (diagnostics only). Renders a `children:` tree when the run composes child workflows |
634
- | `list` | List workflow runs (optionally filtered by `--ref`; `--active` shows only `status=active` runs, excluding `blocked`/`failed`/`completed`). Child workflow runs are excluded unless `--children` is passed |
748
+ | `status <run-id\|ref>` | Show the full run state, including all step statuses. `--units` also lists per-unit rows from the run journal (diagnostics only). Renders a `children:` tree when the run composes child workflows. `--all-scopes` widens the ref-fallthrough lookup (only reached when the target does not resolve to a run id) to every scope instead of just the current one |
749
+ | `list` | List workflow runs (optionally filtered by `--ref`; `--active` shows only `status=active` runs, excluding `blocked`/`failed`/`completed`). Child workflow runs are excluded unless `--children` is passed. `--all-scopes` searches every scope instead of only the current one (#942) |
635
750
  | `resume <run-id>` | Flip a `blocked` or `failed` run back to `active`. Completed runs cannot be resumed |
636
751
  | `abandon <run-id>` | Mark a run failed so it stops counting as active (`resume` can reopen it) |
637
752
  | `plan <ref>` | **Evolving.** Compile and freeze a workflow WITHOUT publishing a run: the canonical step graph, per-step frozen target kinds, task/child expansion, input bindings, source read set, and lowering notices — zero durable writes. Returns the full JSON envelope by default, like every other command; pass `--format text` for a human-readable summary |
@@ -662,6 +777,7 @@ akm workflow run workflows/ship-release --version 1.2.3
662
777
  akm workflow run workflows/review --files a.ts --files b.ts
663
778
  akm workflow run <run-id> --max-steps 3
664
779
  akm workflow run <run-id> --max-retries 2 --timeout 10m
780
+ akm workflow run <run-id> --skip-if-locked # for scheduled runs: skip (exit 0) instead of failing on contention
665
781
  ```
666
782
 
667
783
  Parameter flags must follow the target and exactly match keys declared in the
@@ -686,6 +802,7 @@ The old `--params <json>` bag is removed.
686
802
  | `--max-retries <n>` | When a step fails, reopen the same run and retry the failed step up to this many additional times. Range: 0 through 100; default 0. Gate rejection and interruption are not retried. |
687
803
  | `--timeout <duration>` | Abort the whole invocation after `N`, `Nms`, `Ns`, or `Nm`; bare `N` is milliseconds. The active step remains resumable. |
688
804
  | `--new` | Start a fresh run even when one is already active for this ref, instead of resuming it. The existing active run is left untouched — it is never abandoned automatically. A workflow ref only: passing a run id with `--new` is a usage error (exit 2). Parameter flags are allowed together with `--new`, since it is starting a new run. |
805
+ | `--skip-if-locked` | If another akm process already holds this run's engine lease (`RUN_LEASE_HELD`), or `state.db` is busy with another writer (`STATE_DB_CONTENDED`), skip gracefully (exit 0) instead of failing (exit 75, `TransientError`). The envelope reports `{ skipped: { reason: "lock-held" \| "state-db-contended", message } }`. Every other failure (a bad flag, an unresolvable target) still fails loudly regardless of this flag. Use for high-frequency scheduled runs so they don't pile up failures while a longer-running invocation is in progress — same family as `improve --skip-if-locked`. |
689
806
 
690
807
  **Resuming an active run is announced, not silent.** Passing a ref that
691
808
  already has an active run in the current scope resumes that run rather than
@@ -729,9 +846,10 @@ ancestor when present, otherwise the nearest git root, otherwise the bundle root
729
846
  when the cwd is inside it, otherwise the cwd itself. In practice this means:
730
847
 
731
848
  - `workflow run workflows/<name>` resumes the active run for the current project/worktree/directory (announced with `resumed: true`), or starts one when none is active. `--new` always starts a fresh run.
732
- - `workflow status workflows/<name>` resolves the most-recently-updated run in the current scope only.
733
- - `workflow list` shows runs for the current scope only.
734
- - Direct run-id commands like `workflow status <run-id>` still work even if the run was started from another directory.
849
+ - `workflow status workflows/<name>` resolves the most-recently-updated run in the current scope only, unless `--all-scopes` is passed.
850
+ - `workflow list` shows runs for the current scope only, unless `--all-scopes` is passed. Its envelope always carries a top-level `scopeKey` naming the scope that was searched (`null` under `--all-scopes`), so an empty `runs: []` is never indistinguishable from "nothing anywhere".
851
+ - Direct run-id commands like `workflow status <run-id>`, `workflow resume <run-id>`, and `workflow abandon <run-id>` still work even if the run was started from another directory.
852
+ - Starting a ref by name (`workflow run workflows/<name>`) never collides across scopes — each scope can hold its own active run of the same ref — but if an active run of that ref exists in a *different* scope, the started run's envelope carries a `warnings[]` entry naming that run's id, scope, and start time, with the `akm workflow run <id>` / `akm workflow abandon <id>` remedy, so a stray run in another scope does not go unnoticed (#942).
735
853
 
736
854
  #### workflow create
737
855
 
@@ -772,13 +890,16 @@ affect the in-flight run.
772
890
  akm workflow status <run-id>
773
891
  akm workflow status workflows/ship-release
774
892
  akm workflow status <run-id> --units # also list per-unit rows from the run journal
893
+ akm workflow status workflows/ship-release --all-scopes # resolve across every scope, not just the current one
775
894
  ```
776
895
 
777
896
  Accepts a run id, a unique 8+ character run-id prefix, or a workflow ref.
778
897
  When given a workflow ref, resolves to the most-recently-updated run for that
779
- ref in the current working scope. `--units` adds per-unit rows (unit id,
780
- status, failure reason, and any result/error diagnostic text) from the run
781
- journal diagnostics only; step evidence stays deterministic and is
898
+ ref in the current working scope, unless `--all-scopes` is passed (only
899
+ relevant when the target does not resolve to a run id; a run id is always
900
+ scope-agnostic, `--all-scopes` or not, #942). `--units` adds per-unit rows
901
+ (unit id, status, failure reason, and any result/error diagnostic text) from
902
+ the run journal — diagnostics only; step evidence stays deterministic and is
782
903
  unaffected.
783
904
 
784
905
  #### workflow plan
@@ -1565,28 +1686,35 @@ error (exit 2), the canonical bare-group behavior — name a subcommand.
1565
1686
  ```sh
1566
1687
  akm config list # List current config
1567
1688
  akm config get output.format # Read one key
1689
+ akm config get output.format --show-source # Read one key, with where it came from
1568
1690
  akm config set output.detail full # Set one key
1569
1691
  akm config set output.detail full --silent # Set without the post-write config dump on stdout
1570
1692
  akm config unset llm # Remove an optional key
1571
1693
  akm config path # Print path to config file
1572
1694
  akm config path --all # Print all config-related paths
1695
+ akm config diff other-host/config.json # Effective-config differences, secrets redacted
1573
1696
  ```
1574
1697
 
1575
1698
  Subcommands:
1576
1699
 
1577
1700
  | Subcommand | Description |
1578
1701
  | --- | --- |
1579
- | `get <key>` | Read one config key |
1702
+ | `get <key>` | Read one config key (the effective, post-`extends` value). `--show-source` wraps it as `{ value, source }`, where `source` is `local`, `extends:<ref>`, or `default`. |
1580
1703
  | `list` | List current configuration |
1581
1704
  | `set <key> <value>` | Set one config key; prints the resulting config with `ok: true` |
1582
1705
  | `unset <key>` | Unset an optional key, or a whole `embedding`/engine section; prints the resulting config with `ok: true` |
1583
1706
  | `path` | Show paths to config, bundle, cache, and index. `--all` prints every path; without it, just the config path. Load-bearing: `config path` is the one subcommand the CLI still allows to run when the on-disk config itself fails to load, so you always have a way to locate a broken config. |
1707
+ | `diff <path\|bundle//path>` | Compare this instance's effective config (its own `extends` already applied) against another config file or bundle-relative file (loaded through the same loader — its `extends` honoured too); prints sorted `{ path, local, other }` rows for every differing leaf, secrets redacted on both sides. |
1584
1708
 
1585
1709
  `set` and `unset` accept `--silent` to suppress the post-write config dump
1586
1710
  entirely — nothing is printed on stdout, and the exit code is the status (the
1587
1711
  write still happens and errors still print) — use it from hooks and CI
1588
1712
  scripts.
1589
1713
 
1714
+ See [configuration.md](configuration.md)'s "Sharing configuration across
1715
+ installs" for the `extends` config key that `diff` and `get --show-source`
1716
+ work with.
1717
+
1590
1718
  > **Removed in 0.9.0:** `akm config enable`/`akm config disable`. Use
1591
1719
  > `akm registry add|remove` to toggle a registry, the general mechanism.
1592
1720
  > `akm config show` (an alias of `list`) and `akm config validate` (load-time
@@ -1597,14 +1725,22 @@ See [configuration.md](configuration.md) for details.
1597
1725
  ### models
1598
1726
 
1599
1727
  Manage the installed and operator-owned model intent map. Bare `akm models`
1600
- is a usage error; use the explicit copy operation when you want an editable
1601
- full map.
1728
+ is a usage error; use `list` to inspect the effective table or `copy-defaults`
1729
+ when you want an editable full map.
1602
1730
 
1603
1731
  ```sh
1732
+ akm models list
1604
1733
  akm models copy-defaults
1605
1734
  akm models copy-defaults --overwrite
1606
1735
  ```
1607
1736
 
1737
+ `list` shows the fully resolved alias table — one row per (alias, column)
1738
+ pair with its `model`, optional `inference`, `source` (`default`: unchanged
1739
+ from the installed file; `user`: touched by the user overlay), and `via`
1740
+ (`literal`: a model string; `engine`: borrowed from a configured
1741
+ `engines.<name>` connection, in which case the row also names that `engine`).
1742
+ Read-only; it never writes `models.json`.
1743
+
1608
1744
  `copy-defaults` validates the packaged version-1 `models.json`, then stages and
1609
1745
  syncs it beside the normal AKM configuration target. Creation uses an atomic
1610
1746
  no-replace publish and fails safely on filesystems that cannot provide it.
@@ -1614,7 +1750,8 @@ filesystems do not offer a conditional rename that locks the previously
1614
1750
  observed inode. Symlinks and other non-regular targets observed during checks
1615
1751
  are refused. See
1616
1752
  [Model-map files](configuration.md#model-map-files) for schema, overlay, and
1617
- resolution semantics.
1753
+ resolution semantics — including the `engine` field (0.9.15) that lets a
1754
+ column borrow its model from a configured engine instead of a literal string.
1618
1755
 
1619
1756
  ### help
1620
1757
 
@@ -2068,8 +2205,13 @@ akm agent [<agent-ref>] [--engine <name>] [--prompt <text>] [--model <model>] [-
2068
2205
 
2069
2206
  When `<agent-ref>` is provided, akm resolves the bundle agent's persona,
2070
2207
  `modelHint`, and requested `toolPolicy`. The `--model` flag wins over any model
2071
- specified in the asset. The requested tool policy never grants access by
2072
- itself: authorization runs before lowering, credentials, or provider dispatch.
2208
+ specified in the asset. An alias resolves per the selected `--engine`'s
2209
+ model-map column (see [Model-map files](configuration.md#model-map-files)),
2210
+ which — as of 0.9.15 — may itself be an `engine`-backed indirection, so
2211
+ `--engine local-fast --model fast` can resolve to `local-fast`'s own
2212
+ `engines.local-fast.model` instead of a hardcoded per-platform literal. The
2213
+ requested tool policy never grants access by itself: authorization runs before
2214
+ lowering, credentials, or provider dispatch.
2073
2215
  The current CLI has no built-in allow-all authorizer, so a nonempty request is
2074
2216
  rejected rather than silently weakened.
2075
2217
  Selecting a persona or model without `--prompt` or `--prompt-stdin` is also
@@ -2175,14 +2317,22 @@ akm improve memory
2175
2317
  akm improve skills/code-review
2176
2318
  akm improve workflows/release-checklist --task "reduce duplication"
2177
2319
  akm improve --skip-if-locked # for high-frequency scheduled runs: skip (exit 0) if a run is already in progress
2320
+ akm improve --require-engines # for scheduled runs: abort (exit 78) instead of degrading if an engine/credential is unavailable
2178
2321
  akm improve --no-sync # skip the end-of-run git commit entirely (default: on for git-backed bundles)
2179
2322
  akm improve --sync --no-push # commit only, skip the push after it
2323
+ akm improve --plan --strategy thorough # preview thorough's resolved engine/model routing; nothing is dispatched
2324
+ akm improve report # LLM usage/routing report for the most recent real run
2325
+ akm improve report --run <id> # ...for one specific improve_runs id
2326
+ akm improve report --since 7d # ...aggregated over every real run started in the last 7 days
2180
2327
  ```
2181
2328
 
2182
2329
  | Flag | Description |
2183
2330
  | --- | --- |
2331
+ | `--run <id>` | `report` scope only (#944): show the usage report for one specific `improve_runs` row instead of the most recent real run. Mutually exclusive with `--since`. Rejected with any other scope, or no scope. |
2332
+ | `--since <window>` | `report` scope only (#944): aggregate the usage report over every real (non-dry-run) run started since `<window>` (a duration like `24h`/`7d`, or an ISO timestamp) instead of one run. Mutually exclusive with `--run`. Rejected with any other scope, or no scope. |
2184
2333
  | `--task` | Optional extra guidance for this improvement pass |
2185
2334
  | `--dry-run` | Show the schema-v2 result on stdout without creating config, data, state, cache, bundle, log, or result artifacts. Dry-run results are never persisted, including on errors or signals. |
2335
+ | `--plan` | Alias for `--dry-run` (#947). Sets the exact same internal flag; no separate code path. Prefer this spelling when the goal is previewing `plan.processes` (resolved process -> engine -> model routing) rather than checking what would be written. |
2186
2336
  | `--bundle` | Select the proposal/write target; when the ref scope is bundle-qualified, it must name the same bundle |
2187
2337
  | `--limit <n>` | Base cap for ordinary assets (highest utility first); configured replay slots are additive |
2188
2338
  | `--timeout-ms <ms>` | Wall-clock budget for the run (default: `7200000` = 2 hours) |
@@ -2190,6 +2340,7 @@ akm improve --sync --no-push # commit only, skip the push after it
2190
2340
  | `--strategy <name>` | Override the active improve strategy (a built-in or entry under `improve.strategies`) |
2191
2341
  | `--json-to-stdout` | Also emit the full persisted JSON result on stdout for a live run. Without this flag, stdout stays empty. Dry-runs always emit their result and are never persisted. |
2192
2342
  | `--skip-if-locked` | If another improve run already holds the lock, skip gracefully (exit 0) instead of failing with "already running" (exit 78). Use for high-frequency scheduled runs so they don't pile up failures while a longer run is in progress. |
2343
+ | `--require-engines` | Abort (exit 78, before any indexing, lock, or log side effect) if the active strategy would enable a process whose engine or credential cannot be resolved in this process's environment. Without this flag, improve degrades gracefully: it skips the affected processes and reports them in the result's `skippedProcesses`. Recommended alongside `--skip-if-locked` for scheduled runs, since the operator's own shell can pass config validation while a scheduler's stripped-down environment (see #953) cannot. |
2193
2344
  | `--sync` / `--no-sync` | Commit (and optionally push) the git-backed primary bundle when the run finishes. Default: on for git-backed bundles (per profile config). |
2194
2345
  | `--push` / `--no-push` | Push after the end-of-run sync commit when writable with a remote configured. `--no-push` commits only, skipping the push. Default: per profile config (`true`). `sync.push` stays outside the autonomy gate — this is a per-run opt-out, not a default change. |
2195
2346
 
@@ -2227,6 +2378,24 @@ Selection behavior defaults to recent feedback signals first, with a
2227
2378
  zero-feedback retrieval fallback for high-traffic refs. Use
2228
2379
  `--require-feedback-signal` to disable retrieval fallback for the run.
2229
2380
 
2381
+ When the active strategy enables a process (or the triage judgment engine)
2382
+ whose engine or credential cannot be resolved in this process's environment,
2383
+ the run does not silently do nothing for it: the process is skipped, and the
2384
+ result carries `skippedProcesses` — an array of `{process, configKey, reason}`
2385
+ entries (omitted entirely when nothing was skipped). When the process resolved
2386
+ a real engine whose credential just isn't reachable here (as opposed to never
2387
+ resolving an engine at all), the entry also carries the structurally resolved
2388
+ `engine`/`model`/`contextLength` it would have used — never the credential
2389
+ itself. `ok` and the exit code are unchanged either way, matching `extract`'s
2390
+ `skipReasons` contract: consumers that need to know branch on
2391
+ `skippedProcesses` (or pass `--require-engines` to abort instead of
2392
+ degrading). `reason` names which engine and which credential reference (an env
2393
+ var, `apiKeyFile` path, or `secret://` reference — never its value) is
2394
+ missing. A `--dry-run`/`--plan` preview never dispatches, so it never aborts
2395
+ on an unavailable credential either — even a strategy left with every process
2396
+ disabled this way still returns its plan, with the affected processes in
2397
+ `skippedProcesses`.
2398
+
2230
2399
  For dry runs, `plannedRefs` is the effective post-limit work set, not every
2231
2400
  ref in the requested scope. The `plan` object preserves both views: raw scope
2232
2401
  size and per-gate removals, configured and effective caps, final ranked refs
@@ -2243,11 +2412,75 @@ not an atomic cross-store snapshot or a reservation. Live execution re-inspects
2243
2412
  mutable inputs, so a later run can differ after index, state, filesystem,
2244
2413
  clock, or session-log changes.
2245
2414
 
2415
+ `plan.processes` (#947) is the resolved process -> engine -> model routing
2416
+ table: one row per improve process (`reflect`, `distill`, `consolidate`,
2417
+ `memoryInference`, `graphExtraction`, `extract`, `validation`, `triage`,
2418
+ `proactiveMaintenance`), plus a `triage.judgment` row when the strategy
2419
+ configures a judgment engine. Each row carries `enabled`, the resolved
2420
+ `engine`/`model` (llm-backed processes only) and `engineKind`, this process's
2421
+ own lowering `notices`, and — for reflect/distill/consolidate only —
2422
+ `eligibleRefs`, the count of this run's `effectiveRefs` the process would act
2423
+ on (`shouldSkipRef`'s allowedTypes/process-disabled check; a count, not a
2424
+ per-ref matrix, to keep the envelope bounded). A row that could not resolve an
2425
+ engine or credential carries `unavailable: {configKey, reason}` — the same
2426
+ data behind `skippedProcesses` above, reshaped per process. When the process
2427
+ resolved a real engine whose credential just isn't reachable here, the row
2428
+ still carries that engine's `engine`/`model`/`engineKind` alongside
2429
+ `unavailable`, rather than omitting them the way a never-configured process
2430
+ does — so a preview can show what would have run. This table is
2431
+ resolved before any dispatch on every invocation (dry or live), so
2432
+ `akm improve --dry-run --strategy <name>` (or `--plan`) previews an ad-hoc
2433
+ strategy override without changing config first; `akm health`'s
2434
+ `active-improve-strategy` check performs the equivalent resolution but only
2435
+ for the configured default strategy (`defaults.improveStrategy`), and reports
2436
+ no model or per-process notices. Neither `--dry-run` nor `--plan` probes
2437
+ engine reachability over the network — pair with `akm health --probe` (or the
2438
+ default probe-on behavior) to check whether a named engine actually answers.
2439
+
2246
2440
  When reinforced facts need promotion, `knowledge` is the higher-authority
2247
2441
  destination than `memory`. The deterministic search ranking also prefers
2248
2442
  `knowledge` over `memory` hits, including inferred `.derived` memories, when
2249
2443
  the evidence is otherwise comparable.
2250
2444
 
2445
+ #### improve report
2446
+
2447
+ `akm improve report` (#944) answers "which engine did each LLM-backed process
2448
+ use this run, how much did it cost, and which enabled processes made zero
2449
+ calls (and why)" without hand-written SQLite against `state.db`. It is a
2450
+ `scope` value, not a subcommand — `report` is not, and will never be, a real
2451
+ asset type, so it is intercepted before any lock/log/index side effect (same
2452
+ precedent as the retired `canary` scope).
2453
+
2454
+ Every real (non-dry-run) `akm improve` invocation persists a `usageReport`
2455
+ field on the result (`result_json` in `improve_runs`, and in the
2456
+ `--json-to-stdout` / dry-run JSON): `{ byProcessEngineModel, noCalls }`.
2457
+ `byProcessEngineModel` is a cross-tab of this run's own `llm_usage` events
2458
+ (#576) — one row per distinct `(process, engine, model)` triple, each with
2459
+ `calls`, `failures`, `promptTokens`, `completionTokens`, `totalTokens`,
2460
+ `reasoningTokens`, and `totalDurationMs`. `noCalls` lists every LLM-backed
2461
+ process (`reflect`, `distill`, `consolidate`, `memoryInference`,
2462
+ `graphExtraction`, `extract`, `validation` — not `triage`/`proactiveMaintenance`,
2463
+ which never make an attributable LLM call themselves) the active strategy
2464
+ enabled but that ended the run with zero calls, each with a `reason` drawn
2465
+ from the existing skip-reason vocabulary: `"engine_unavailable"` (also in
2466
+ `skippedProcesses`), `"autonomy_gated"`, `"strategy_filtered_all_passes"`, a
2467
+ reflect/distill dominant skip reason (e.g. `"no_new_signal"`, `"cooldown"`),
2468
+ or `"no_signal"` as the fallback — never a fabricated category. The field is
2469
+ omitted entirely when both would be empty. The same table is printed to
2470
+ stderr (`[improve] usage report ...`) after every real run, independent of
2471
+ `--json-to-stdout`.
2472
+
2473
+ `akm improve report` reads that field back: with no flags, the most recent
2474
+ real run; `--run <id>`, one specific run; `--since <window>`, summed across
2475
+ every real run in the window (`byProcessEngineModel` rows merged by
2476
+ `(process, engine, model)`; `noCalls` lists a process only if it made zero
2477
+ calls across every included run). A run recorded before 0.9.15 has no
2478
+ persisted `usageReport` — the command recomputes `byProcessEngineModel` from
2479
+ that run's own `llm_usage` events instead of erroring, sets `noCalls` to `[]`
2480
+ (eligibility reasons are not reconstructable after the fact), and adds a
2481
+ `notes` entry saying so rather than fabricating precision the old row can't
2482
+ support.
2483
+
2251
2484
  ### proposal
2252
2485
 
2253
2486
  Manage the proposal queue. The canonical grammar is `akm proposal <verb>`:
@@ -2532,13 +2765,14 @@ shell commands. It manages on-disk task definitions under
2532
2765
  (cron / launchd / schtasks). Task source v4 YAML (`version: 4`) is the only
2533
2766
  executable source contract this release accepts; `akm task add` writes v4 —
2534
2767
  see the canonical [Tasks reference](tasks.md). The
2535
- group is `add | run | explain | validate | sync | doctor | history | prune`
2536
- — there is no `list` or `remove`; use `akm search --type task` /
2537
- `akm show tasks/<id>` to inspect, and edit the file + `akm task sync` to
2538
- change or remove a schedule.
2768
+ group is `add | run | explain | validate | list | sync | doctor | history | prune`
2769
+ — there is no `show` or `remove`; use `akm show tasks/<id>` to inspect one
2770
+ task, and edit the file + `akm task sync` to change or remove a schedule.
2771
+ `task list` is a delegating alias for `akm search --type task` — both
2772
+ spellings return the identical envelope.
2539
2773
 
2540
2774
  ```sh
2541
- akm search --type task # List tasks (cross-bundle)
2775
+ akm task list # List tasks (cross-bundle) — alias for `search --type task`
2542
2776
  akm show tasks/<id> # Inspect one task
2543
2777
  akm task add <id> --schedule "@daily" \ # Register a new task and install it
2544
2778
  --command "akm improve --strategy default"
@@ -2563,6 +2797,13 @@ scheduler), `--force` (overwrite an existing task with the same id), and
2563
2797
  `--rebind` (explicitly permit scheduler creation from a local invocation that
2564
2798
  would otherwise be considered ineligible).
2565
2799
 
2800
+ `akm task list [<query>] [--limit <n>] [--from local|registry|all]` is a
2801
+ pure alias for `akm search --type task` with the query, `--limit`, and
2802
+ `--from` flags passed through — same envelope, same `results` alias, no
2803
+ second implementation. 0.9.0 removed `task list` as a redundant
2804
+ implementation of task listing (see the 0.9.0 CHANGELOG entry); this
2805
+ reintroduces only the spelling, not the logic.
2806
+
2566
2807
  `akm task explain <ref> [input flags]` prints a task's declared `inputs:`,
2567
2808
  the values that would actually be supplied (with provenance), the resolved
2568
2809
  target, effective execution settings, and schedule bindings — **read-only**: