akm-cli 0.9.31 → 0.10.26101002-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/CHANGELOG.md +265 -0
  2. package/STABILITY.md +79 -53
  3. package/dist/api-node.mjs +20 -0
  4. package/dist/api.d.ts +23 -0
  5. package/dist/api.js +45 -0
  6. package/dist/assets/hints/cli-hints-full.md +13 -27
  7. package/dist/assets/hints/cli-hints-short.md +1 -1
  8. package/dist/assets/improve-strategies/default.json +3 -3
  9. package/dist/assets/prompts/consolidate-pair.md +9 -7
  10. package/dist/cli/shared.js +31 -48
  11. package/dist/cli/unknown-flags.js +6 -43
  12. package/dist/cli.js +8 -34
  13. package/dist/commands/agent/contribute-cli.js +1 -1
  14. package/dist/commands/completions.js +1 -2
  15. package/dist/commands/config-cli.js +5 -28
  16. package/dist/commands/env/env-cli.js +5 -5
  17. package/dist/commands/env/secret-cli.js +2 -2
  18. package/dist/commands/health/checks.js +41 -16
  19. package/dist/commands/health/plugin-staleness.js +52 -22
  20. package/dist/commands/improve/autonomy-gate.js +5 -3
  21. package/dist/commands/improve/consolidate/pair-pass.js +7 -1
  22. package/dist/commands/improve/consolidate.js +6 -35
  23. package/dist/commands/improve/distill/lesson-update.js +91 -0
  24. package/dist/commands/improve/distill-guards.js +1 -43
  25. package/dist/commands/improve/distill.js +140 -20
  26. package/dist/commands/improve/eligibility.js +14 -1
  27. package/dist/commands/improve/extract-cli.js +1 -1
  28. package/dist/commands/improve/improve-cli.js +87 -102
  29. package/dist/commands/improve/improve-strategies.js +8 -12
  30. package/dist/commands/improve/improve.js +2 -2
  31. package/dist/commands/improve/loop-stages.js +0 -1
  32. package/dist/commands/improve/planner.js +0 -1
  33. package/dist/commands/improve/preparation.js +40 -99
  34. package/dist/commands/improve/proactive-maintenance.js +2 -2
  35. package/dist/commands/improve/reflect-noise.js +3 -55
  36. package/dist/commands/improve/reflect.js +3 -8
  37. package/dist/commands/improve/retrieval-scope.js +2 -2
  38. package/dist/commands/improve/salience.js +2 -9
  39. package/dist/commands/improve/stage.js +14 -9
  40. package/dist/commands/lint/index.js +5 -20
  41. package/dist/commands/observability-cli.js +3 -9
  42. package/dist/commands/proposal/drain.js +39 -6
  43. package/dist/commands/proposal/proposal-cli.js +11 -31
  44. package/dist/commands/proposal/repository.js +3 -3
  45. package/dist/commands/read/knowledge.js +3 -3
  46. package/dist/commands/read/remember-cli.js +0 -13
  47. package/dist/commands/read/search-cli.js +29 -97
  48. package/dist/commands/read/search.js +0 -11
  49. package/dist/commands/read/show.js +0 -19
  50. package/dist/commands/sources/plugin-upgrade.js +164 -101
  51. package/dist/commands/sources/sources-cli.js +1 -15
  52. package/dist/commands/sources/stash-cli.js +4 -12
  53. package/dist/commands/tasks/tasks-cli.js +4 -115
  54. package/dist/commands/workflow/plan.js +11 -33
  55. package/dist/commands/workflow-cli.js +2 -7
  56. package/dist/core/adapter/adapter-ids.js +1 -2
  57. package/dist/core/adapter/adapters/agent-skills-adapter.js +0 -4
  58. package/dist/core/adapter/adapters/akm-adapter.js +9 -48
  59. package/dist/core/adapter/adapters/akm-lint.js +10 -26
  60. package/dist/core/adapter/adapters/akm-metadata.js +2 -72
  61. package/dist/core/adapter/adapters/akm-task-adapter.js +0 -5
  62. package/dist/core/adapter/adapters/akm-workflow-adapter.js +9 -28
  63. package/dist/core/adapter/adapters/dotenv-adapter.js +1 -20
  64. package/dist/core/adapter/adapters/generic-files-adapter.js +0 -10
  65. package/dist/core/adapter/adapters/llm-wiki-adapter.js +0 -4
  66. package/dist/core/adapter/adapters/tool-dir-shared.js +0 -24
  67. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -4
  68. package/dist/core/adapter/recognize-match.js +3 -4
  69. package/dist/core/common.js +18 -2
  70. package/dist/core/config/config-schema.js +12 -15
  71. package/dist/core/config/config-types.js +6 -15
  72. package/dist/core/config/config-walker.js +6 -23
  73. package/dist/core/config/config.js +17 -80
  74. package/dist/core/config/engine-semantics.js +7 -3
  75. package/dist/core/config/schema/engines.js +7 -7
  76. package/dist/core/config/schema/improve-processes.js +8 -61
  77. package/dist/core/config/schema/improve.js +2 -21
  78. package/dist/core/config/schema/index-config.js +6 -39
  79. package/dist/core/env-secret-ref.js +2 -45
  80. package/dist/core/errors.js +1 -2
  81. package/dist/core/extra-params.js +2 -86
  82. package/dist/core/improve-result.js +11 -1
  83. package/dist/core/mutation-target.js +2 -2
  84. package/dist/core/recognition-util.js +4 -5
  85. package/dist/core/warn.js +21 -4
  86. package/dist/core/write-source.js +3 -3
  87. package/dist/execution/target-ref.js +1 -2
  88. package/dist/indexer/search/db-search.js +4 -19
  89. package/dist/indexer/search/fts-query.js +0 -19
  90. package/dist/integrations/agent/engine-resolution.js +5 -2
  91. package/dist/integrations/agent/index.js +1 -1
  92. package/dist/integrations/agent/profiles.js +41 -98
  93. package/dist/integrations/agent/request-lowering.js +3 -3
  94. package/dist/integrations/harnesses/aider/index.js +5 -0
  95. package/dist/integrations/harnesses/amazonq/index.js +1 -0
  96. package/dist/integrations/harnesses/claude/config-import.js +2 -3
  97. package/dist/integrations/harnesses/claude/index.js +5 -0
  98. package/dist/integrations/harnesses/codex/index.js +1 -0
  99. package/dist/integrations/harnesses/copilot/index.js +1 -0
  100. package/dist/integrations/harnesses/gemini/index.js +1 -0
  101. package/dist/integrations/harnesses/index.js +18 -39
  102. package/dist/integrations/harnesses/opencode/agent-builder.js +60 -35
  103. package/dist/integrations/harnesses/opencode/config-import.js +121 -52
  104. package/dist/integrations/harnesses/opencode/index.js +22 -0
  105. package/dist/integrations/harnesses/opencode/plugin-layout.js +68 -0
  106. package/dist/integrations/harnesses/opencode/session-log-types.js +12 -0
  107. package/dist/integrations/harnesses/opencode/session-log-v1.js +72 -0
  108. package/dist/integrations/harnesses/opencode/session-log-v2.js +140 -0
  109. package/dist/integrations/harnesses/opencode/session-log.js +104 -115
  110. package/dist/integrations/harnesses/opencode/version.js +98 -0
  111. package/dist/integrations/harnesses/opencode-sdk/{harness.js → index.js} +5 -17
  112. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +105 -206
  113. package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +199 -0
  114. package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +228 -0
  115. package/dist/integrations/harnesses/opencode-sdk/wire.js +66 -0
  116. package/dist/integrations/harnesses/openhands/index.js +1 -0
  117. package/dist/integrations/harnesses/pi/index.js +1 -0
  118. package/dist/integrations/harnesses/shared.js +2 -0
  119. package/dist/integrations/harnesses/types.js +2 -0
  120. package/dist/llm/client.js +41 -11
  121. package/dist/output/cli-hints.js +1 -1
  122. package/dist/output/context.js +10 -19
  123. package/dist/output/format-exempt.js +5 -8
  124. package/dist/output/shapes/helpers.js +1 -22
  125. package/dist/output/shapes/passthrough.js +0 -1
  126. package/dist/output/shapes.js +3 -31
  127. package/dist/output/stdout.js +5 -1
  128. package/dist/output/text/command-format.js +6 -1
  129. package/dist/output/text/workflow-format.js +4 -22
  130. package/dist/scripts/akm-migrate-node.js +13049 -14013
  131. package/dist/scripts/akm-migrate.js +16316 -17276
  132. package/dist/setup/detect.js +10 -4
  133. package/dist/setup/harness-config-import.js +5 -14
  134. package/dist/setup/setup.js +1 -1
  135. package/dist/setup/steps/tasks.js +12 -13
  136. package/dist/storage/repositories/task-history-repository.js +0 -5
  137. package/dist/storage/repositories/workflow-runs-repository.js +5 -15
  138. package/dist/tasks/embedded.js +2 -1
  139. package/dist/tasks/run/task-history.js +0 -2
  140. package/dist/tasks/schedule-gates.js +39 -0
  141. package/dist/tasks/scheduler-binding.js +0 -16
  142. package/dist/tasks/scheduler-sync.js +3 -97
  143. package/dist/tasks/source/bounded-document.js +1 -1
  144. package/dist/tasks/source/task-source-v4.js +2 -12
  145. package/dist/tasks/task-run-reserved-flags.js +2 -31
  146. package/dist/workflows/authoring/authoring.js +6 -6
  147. package/dist/workflows/compile.js +8 -65
  148. package/dist/workflows/exec/child-workflow.js +22 -3
  149. package/dist/workflows/exec/native-executor.js +12 -147
  150. package/dist/workflows/exec/run-workflow.js +31 -103
  151. package/dist/workflows/exec/step-work.js +9 -178
  152. package/dist/workflows/exec/unit-dispatch.js +0 -10
  153. package/dist/workflows/freeze/environment.js +3 -44
  154. package/dist/workflows/freeze/freeze.js +8 -41
  155. package/dist/workflows/freeze/targets/child-workflow.js +27 -63
  156. package/dist/workflows/freeze/targets/command.js +2 -16
  157. package/dist/workflows/freeze/targets/shell.js +0 -2
  158. package/dist/workflows/freeze/task-bindings.js +2 -28
  159. package/dist/workflows/ir/params.js +12 -2
  160. package/dist/workflows/parser.js +82 -232
  161. package/dist/workflows/plan.js +1 -1
  162. package/dist/workflows/renderer.js +10 -19
  163. package/dist/workflows/runtime/run-plan.js +11 -53
  164. package/dist/workflows/runtime/runs.js +4 -27
  165. package/dist/workflows/source-files.js +12 -16
  166. package/dist/workflows/source-semantics.js +1 -93
  167. package/docs/README.md +1 -1
  168. package/docs/agents/README.md +3 -3
  169. package/docs/agents/agent-install.md +1 -1
  170. package/docs/architecture/adapters.md +17 -31
  171. package/docs/architecture/architecture.md +4 -5
  172. package/docs/architecture/improvement.md +52 -21
  173. package/docs/architecture/internals/improve-workflow.md +15 -8
  174. package/docs/architecture/internals/indexing.md +1 -1
  175. package/docs/architecture/internals/search.md +1 -2
  176. package/docs/architecture/internals/storage-locations.md +5 -5
  177. package/docs/architecture/persisted-data-compat.md +13 -4
  178. package/docs/architecture/specs/0.9.0-decisions.md +6 -2
  179. package/docs/architecture/specs/improve-collapse-churn-detector-design.md +2 -2
  180. package/docs/architecture/specs/workflow-format-unification.md +1 -6
  181. package/docs/architecture/testing/manual-testing-checklist.md +20 -29
  182. package/docs/architecture/testing/task-workflow-manual-tests.md +106 -203
  183. package/docs/architecture/testing/testing-workflow.md +1 -1
  184. package/docs/architecture/workflow-engine.md +5 -56
  185. package/docs/guides/author-workflows.md +39 -69
  186. package/docs/guides/capture-knowledge.md +1 -1
  187. package/docs/guides/claude-code-vs-akm-workflows.md +1 -2
  188. package/docs/guides/discover-and-load.md +4 -4
  189. package/docs/guides/getting-started.md +1 -1
  190. package/docs/guides/improve-the-library.md +7 -7
  191. package/docs/guides/recipes/headless-install.md +2 -2
  192. package/docs/guides/run-workflows.md +1 -1
  193. package/docs/guides/use-with-any-agent.md +49 -4
  194. package/docs/integration/bundling-akm.md +7 -6
  195. package/docs/maintainers/curate-workmap.md +1 -2
  196. package/docs/maintainers/release-checklist.md +30 -1
  197. package/docs/posts/akm-command-tour.md +3 -3
  198. package/docs/product-surface.md +1 -1
  199. package/docs/reference/README.md +1 -0
  200. package/docs/reference/api.md +65 -0
  201. package/docs/reference/asset-types.md +3 -5
  202. package/docs/reference/bundle-types.md +2 -4
  203. package/docs/reference/cli.md +129 -171
  204. package/docs/reference/configuration.md +84 -19
  205. package/docs/reference/data-and-telemetry.md +1 -1
  206. package/docs/reference/env-and-secrets.md +2 -2
  207. package/docs/reference/supported-formats.md +3 -4
  208. package/docs/reference/tasks.md +12 -19
  209. package/docs/reference/website-sources.md +1 -1
  210. package/docs/reference/workflow-schema.md +89 -317
  211. package/docs/reference/workflows.md +20 -48
  212. package/package.json +12 -2
  213. package/schemas/akm-config.json +2 -243
  214. package/schemas/akm-task.json +2 -3
  215. package/schemas/akm-workflow.json +47 -84
  216. package/dist/assets/improve-strategies/catchup.json +0 -41
  217. package/dist/assets/improve-strategies/proactive-maintenance.json +0 -24
  218. package/dist/assets/improve-strategies/quick.json +0 -17
  219. package/dist/assets/improve-strategies/reflect-distill.json +0 -29
  220. package/dist/assets/improve-strategies/thorough.json +0 -49
  221. package/dist/assets/tasks/improve/akm-improve-catchup.yml +0 -6
  222. package/dist/assets/tasks/improve/akm-improve-frequent.yml +0 -4
  223. package/dist/assets/tasks/improve/akm-improve-nightly.yml +0 -4
  224. package/dist/cli/retired-commands.js +0 -118
  225. package/dist/commands/tasks/validate.js +0 -176
  226. package/dist/core/config/legacy-source-shape-shim.js +0 -117
  227. package/dist/integrations/harnesses/ids.js +0 -28
  228. package/dist/tasks/source/task-source-v3-frozen.js +0 -424
  229. package/dist/tasks/source/task-to-v4.js +0 -863
  230. package/dist/workflows/exec/worktree.js +0 -372
  231. package/dist/workflows/freeze/child-output-references.js +0 -83
  232. package/dist/workflows/freeze/identity.js +0 -22
  233. package/dist/workflows/freeze/targets/script.js +0 -50
  234. package/dist/workflows/freeze/targets/task.js +0 -124
  235. package/dist/workflows/github-yaml.js +0 -506
  236. package/dist/workflows/runtime/run-outputs.js +0 -80
package/dist/api.js ADDED
@@ -0,0 +1,45 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * `akm-cli/api` — the one supported programmatic entry point. Everything else
6
+ * in this package is CLI-only. See docs/reference/api.md for the contract.
7
+ *
8
+ * Each export runs the same code path as its CLI command and computes the
9
+ * document the CLI would print, in-process: no child process, no write to
10
+ * stdout/stderr, no `process.chdir`, no change to the host's `process.env`,
11
+ * and no process-level output-mode, quiet or verbose state left changed.
12
+ */
13
+ import { renderOutput } from "./cli/shared.js";
14
+ import { runCurate } from "./commands/read/search-cli.js";
15
+ import { loadConfig } from "./core/config/config.js";
16
+ import { UsageError } from "./core/errors.js";
17
+ import { withQuiet } from "./core/warn.js";
18
+ import { installLlmUsagePersistenceIfAbsent } from "./llm/usage-persist.js";
19
+ import { resolveOutputMode } from "./output/context.js";
20
+ import { stdoutText } from "./output/stdout.js";
21
+ /**
22
+ * Returns exactly the stdout text of
23
+ * `akm --detail agent -q curate <query> [--limit N] [--type T] --format <format>`
24
+ * including its trailing newline. Rejects with the error the CLI
25
+ * would fail with: its message, and its error code on the `code` property.
26
+ */
27
+ export async function curate(query, options = {}) {
28
+ const format = options.format ?? "json";
29
+ if (format !== "text" && format !== "json") {
30
+ throw new UsageError(`Invalid value for --format: ${format}. Expected one of: json|text`, "INVALID_FORMAT_VALUE");
31
+ }
32
+ return withQuiet(async () => {
33
+ // Same startup order as the CLI: config first (an invalid config fails
34
+ // the call before anything runs), then the output mode from argv + config.
35
+ const mode = resolveOutputMode(["--detail", "agent", "--format", format], loadConfig().output ?? {});
36
+ const disposeLlmUsageSink = installLlmUsagePersistenceIfAbsent();
37
+ try {
38
+ const curated = await runCurate({ query, type: options.type, limit: options.limit === undefined ? undefined : String(options.limit) }, mode);
39
+ return stdoutText(renderOutput("curate", curated, { ...mode, format }));
40
+ }
41
+ finally {
42
+ disposeLlmUsageSink();
43
+ }
44
+ });
45
+ }
@@ -23,8 +23,7 @@ akm search "team-catalog//" # List every item in one bundle
23
23
  | `--from` | `local`, `registry`, `all`, or a configured bundle name | `local` |
24
24
  | `--limit` | number | `20` |
25
25
  | `--format` | `json`, `jsonl`, `text`, `yaml`, `md`, `html` | `json` |
26
- | `--detail` | `brief`, `normal`, `full` | `brief` |
27
- | `--shape` | `human`, `agent`, `summary` (`summary` only on `show`) | `human` |
26
+ | `--detail` | `brief`, `normal`, `full`, `agent` (`agent`: search, curate and show only) | `brief` |
28
27
 
29
28
  Ref-prefix queries (a conceptId prefix ending in `/`, optionally bundle-qualified)
30
29
  return a deterministic listing, not a relevance ranking. Drop the trailing slash
@@ -90,9 +89,9 @@ akm import ./doc.md --xref knowledge/auth-flow # Merge provenance xrefs into the
90
89
  akm import ./new.md --supersedes knowledge/old # Import a correction AND demote the doc it replaces
91
90
  akm import - --name scratch-notes < notes.md # Import stdin as a knowledge doc
92
91
  akm import https://example.com/docs/auth # Fetch one URL and import it as knowledge
93
- akm import ./doc.md --target my-other-bundle # Route import to a named writable bundle source
92
+ akm import ./doc.md --bundle my-other-bundle # Route import to a named writable bundle source
94
93
  akm workflow create ship-release # Create a workflow asset in the bundle
95
- akm lint --type workflows # Parse and compile every .md/.yml workflow source; list every error
94
+ akm lint --type workflows # Parse and compile every workflow source; list every error
96
95
  akm workflow run workflows/ship-release # Start or resume and execute the workflow
97
96
  akm feedback skills/code-review --positive # Record that an asset helped (ranks it higher; no rewrite)
98
97
  akm feedback agents/reviewer --negative --reason "says to run jest; the suite runs on vitest" # Content wrong or stale: lowers its ranking; improve may repair its frontmatter
@@ -176,9 +175,8 @@ akm secret run secrets/deploy-token GITHUB_TOKEN -- gh release create v1.0.0 #
176
175
 
177
176
  ## Workflows
178
177
 
179
- Workflows live under `<bundle>/workflows/` as peer `.md` and `.yml` sources.
180
- Both compile to the same source IR; see `docs/reference/workflow-schema.md` for
181
- the bounded GitHub-shaped YAML subset.
178
+ Workflows live under `<bundle>/workflows/` as `.md` sources; see
179
+ `docs/reference/workflow-schema.md` for the frontmatter and body syntax.
182
180
 
183
181
  Ref-based workflow commands are scoped to the current project/worktree/directory,
184
182
  so one active run does not block unrelated directories from starting the same
@@ -235,7 +233,6 @@ rename instead of starting fresh, run `bun scripts/rekey-asset-ref.ts <old-ref>
235
233
  ## Sync
236
234
 
237
235
  Commit local changes in a git-backed bundle. Behaviour adapts automatically.
238
- (`akm save` was the pre-0.8 spelling; it was removed in 0.9.0 — use `akm sync`.)
239
236
 
240
237
  - **No `.git` directory** — no-op (silent skip)
241
238
  - **Git repo, no remote** — stage and commit only (the default bundle always falls here)
@@ -255,15 +252,13 @@ akm sync my-skills -m "Update patterns" # Sync named bundle with message
255
252
  The `--sync` / `--no-sync` and `--push` / `--no-push` flags control this:
256
253
 
257
254
  ```sh
258
- akm improve # auto-sync per strategy default (most strategies: on; proactive-maintenance/reflect-distill: off)
255
+ akm improve # auto-sync per strategy default (both strategies: on)
259
256
  akm improve --no-sync # skip the end-of-run commit
260
257
  akm improve --no-push # commit but skip push for this run
261
258
  akm improve --sync # force sync even on strategies that disable it
262
259
  ```
263
260
 
264
- Strategy sync defaults: `catchup`, `consolidate`, `default`, `quick`, and
265
- `thorough` auto-commit + push; `proactive-maintenance` and `reflect-distill`
266
- skip sync entirely. Override with `--sync` / `--no-sync` flags.
261
+ Strategy sync defaults: `consolidate` and `default` auto-commit + push. Override with `--sync` / `--no-sync` flags.
267
262
 
268
263
  The `--writable` flag on `akm bundle add` opts a remote git bundle into push-on-sync:
269
264
 
@@ -313,7 +308,6 @@ akm config list # Show current config
313
308
  akm config get <key> # Read a value
314
309
  akm config set <key> <value> # Set a value
315
310
  akm config unset <key> # Remove a key
316
- akm config path --all # Show all config paths
317
311
  ```
318
312
 
319
313
  ## Other Commands
@@ -331,11 +325,10 @@ akm lint --fix # Auto-fix Tier 1 issues
331
325
  akm lint --fail-on-flagged # Exit non-zero when summary.flagged > 0 (CI-friendly)
332
326
  akm upgrade # Upgrade akm using its install method, then update installed harness plugins
333
327
  akm upgrade --check # Report pending CLI and plugin updates, changing nothing
334
- akm upgrade --next # Follow prereleases (@next); OpenCode needs "akm-opencode@next" in its plugin list
328
+ akm upgrade --next # Follow prereleases (@next); OpenCode needs "akm-opencode@next" (or "akm-opencode-v2@next" on OpenCode 2) in its plugin list
335
329
  akm help migrate 0.6.0 # Print migration notes for a release (or: latest)
336
330
  akm help bundle # Print options and subcommands for one command
337
- akm help agents --full # Print this reference
338
- akm hints # Print this complete agent guide
331
+ akm hints # Print this complete agent guide (--detail brief for the short one)
339
332
  akm completions # Print bash completion script
340
333
  akm completions --install # Install completions
341
334
  ```
@@ -354,7 +347,7 @@ akm proposal show <id> # Render the proposal bo
354
347
  akm proposal diff <ref-or-id> # Diff by ref, UUID, or 8-char prefix
355
348
  akm proposal diff skills/akm-dream # Diff by asset ref
356
349
  akm proposal accept 7c115132 # Accept by UUID prefix
357
- akm proposal accept <id> --target team-bundle # Accept to a named writable bundle source
350
+ akm proposal accept <id> --bundle team-bundle # Accept to a named writable bundle source
358
351
  akm proposal reject skills/my-skill --reason "not ready" # Reject by asset ref
359
352
  akm proposal reject <id> --reason "..." # Archive with a reason
360
353
  akm proposal reopen <id> --reason "..." # Undo a rejection: back to pending (refused if the target changed)
@@ -364,11 +357,6 @@ akm proposal extract --auto # Mine native session fi
364
357
  akm proposal extract --type claude # Restrict extraction to one harness
365
358
  ```
366
359
 
367
- The flat verbs `akm proposals` / `akm show proposal` / `akm accept` /
368
- `akm reject` / `akm diff` / `akm revert` were removed in 0.9.0 — use the
369
- `akm proposal <verb>` forms above. `akm extract` and `akm propose` moved
370
- here as `proposal extract` / `proposal new`.
371
-
372
360
  ## Scheduled Tasks
373
361
 
374
362
  Tasks are pure-YAML assets at `<bundle>/tasks/<id>.yml`, bound to the OS
@@ -387,7 +375,7 @@ akm task doctor # Scheduler binding + runtime eli
387
375
  akm task history # Recent run rows (status, timing)
388
376
  akm task run <id> # Run one task immediately (works when disabled)
389
377
  akm task explain <ref> # Read-only: declared inputs, target, schedule — spawns nothing
390
- akm search --type task # Enumerate task assets (there is no `task list`)
378
+ akm search --type task # Enumerate task assets
391
379
  ```
392
380
 
393
381
  Task files use task source v4 (`version: 4`). There is no `akm:` options bag
@@ -428,7 +416,7 @@ akm log --run <run-id> # Events for one workflow-engine
428
416
 
429
417
  ## Output Control
430
418
 
431
- Result-envelope commands accept `--format`, `--detail`, and `--shape` flags:
419
+ Result-envelope commands accept `--format` and `--detail` flags:
432
420
 
433
421
  - `--format json` (default) — structured JSON
434
422
  - `--format jsonl` — one JSON object per line (streaming-friendly)
@@ -439,9 +427,7 @@ Result-envelope commands accept `--format`, `--detail`, and `--shape` flags:
439
427
  - `--detail brief` (default) — compact output
440
428
  - `--detail normal` — adds tags, refs, origins
441
429
  - `--detail full` — includes scores, paths, timing, debug info
442
- - `--shape human` (default) — standard projection
443
- - `--shape agent` — agent-optimized output: strips non-actionable fields
444
- - `--shape summary` — metadata only (no content/template/prompt), under 200 tokens; only `akm show` has a dedicated summary projection — elsewhere it falls back to `agent` with a warning
430
+ - `--detail agent` — agent-optimized output on `search`, `curate` and `show`: strips non-actionable fields (other commands ignore it)
445
431
 
446
432
  Run `akm help <command>` or `akm <command> -h` for per-command help. Run
447
433
  `akm --help` for the sectioned command overview.
@@ -35,7 +35,7 @@ akm remember "note" --bundle my-bundle # Route write to a named writable
35
35
  akm remember "note" --xref knowledge/auth-flow # Cite provenance in frontmatter xrefs (repeatable)
36
36
  akm remember "fix" --supersedes memories/old-note # Write a correction AND demote the superseded asset
37
37
  akm import ./notes/release-checklist.md # Import a knowledge doc into your bundle
38
- akm import ./doc.md --target my-bundle # Route import to a named writable bundle source
38
+ akm import ./doc.md --bundle my-bundle # Route import to a named writable bundle source
39
39
  akm proposal diff skills/akm-dream # Diff proposal by ref, UUID, or 8-char prefix
40
40
  akm proposal accept 7c115132 # Accept by UUID prefix
41
41
  akm proposal reject skills/my-skill --reason "..." # Reject by ref
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "Standard improve pass — reflect (rewrites only from negative feedback), distill, consolidation (promotion plus the reviewed pair-pass retire/supersede proposals), and validation. Memory inference is listed below but only runs when experimental.improveAutonomy is set; improve-stage extract and proactive maintenance off.",
2
+ "description": "Standard improve pass — reflect (rewrites only from negative feedback), distill, consolidation (promotion plus the reviewed pair-pass retire/supersede proposals), and validation. Memory inference is listed below but only runs when experimental.improveAutonomy is set; improve-stage extract off. Proactive maintenance plans up to 15 assets not reflected or distilled for 30 days.",
3
3
  "processes": {
4
4
  "reflect": {
5
5
  "enabled": true,
@@ -11,8 +11,8 @@
11
11
  "memoryInference": { "enabled": true },
12
12
  "extract": { "enabled": false, "triage": { "enabled": true, "minScore": 2 } },
13
13
  "validation": { "enabled": true },
14
- "proactiveMaintenance": { "enabled": false, "dueDays": 30, "maxPerRun": 15 },
15
- "triage": { "enabled": false, "applyMode": "queue", "policy": "personal-stash" }
14
+ "proactiveMaintenance": { "enabled": true, "dueDays": 30, "maxPerRun": 15 },
15
+ "triage": { "enabled": true, "applyMode": "promote", "maxAcceptsPerRun": 200 }
16
16
  },
17
17
  "sync": { "enabled": true, "push": true }
18
18
  }
@@ -1,19 +1,21 @@
1
- You compare two assets from one person's agent-memory library (memories and knowledge notes an AI coding agent reads). Asset A is the OLDER one and asset B the NEWER one, by the dates shown. akm deletes one of them only when the other keeps every claim a reader would need, so your two lists decide what is safe to delete.
1
+ You compare two assets from one person's agent-memory library (memories and knowledge notes an AI coding agent reads). Asset A is the OLDER one and asset B the NEWER one, by the dates shown, unless both carry the same date and are labelled "same age". akm deletes one of them only when the other keeps every claim a reader would need, so your two lists decide what is safe to delete.
2
2
 
3
3
  First list what each asset has that the other lacks:
4
- - "onlyInA": every durable claim of A that B neither states nor updates.
5
- - "onlyInB": every durable claim of B that A neither states nor updates.
4
+ - "onlyInA": every durable claim of A that B does not state or replace.
5
+ - "onlyInB": every durable claim of B that A does not state or replace.
6
6
 
7
7
  A durable claim is a fact, decision, value, command, flag, path, file name, URL, number, version, name, error message, condition or rule someone would act on. Ignore wording, headings, dates of writing, tags and boilerplate. A claim is stated when the other asset says it in any wording or format. It is not stated when the other asset is vaguer (a config file instead of the specific path) or drops a number, command, step or condition. Write each item as a short phrase that quotes its identifier. Use [] when there is nothing.
8
8
 
9
+ B replaces a claim of A only when both are about the same named thing (the same service, integration, partner, component, region or file) and B gives a new value for it that is current: B says so (now, instead of, since, renamed, corrected, no longer) or B is created later than A. Notes about different named things never replace each other, whatever their dates: list each one's own name, value and path as its claims. A different value for the same thing with neither sign is a conflict, not a replacement: list A's value in "onlyInA" and B's value in "onlyInB".
10
+
9
11
  Then classify the relation as exactly one of:
10
12
  - "duplicate": both lists are empty.
11
13
  - "subsumed": exactly one list is empty. The asset with the empty list is redundant.
12
- - "supersedes": B updates, corrects, reverses or replaces a claim in A (a newer version, a changed decision, a fixed bug, a new value), and onlyInA is empty.
13
- - "contradicts": they make logically exclusive claims about the same thing and nothing shows which one is current.
14
+ - "supersedes": B replaces a claim in A as defined above (a newer version, a changed decision, a fixed bug, a new value), and onlyInA is empty.
15
+ - "contradicts": they make logically exclusive claims about the same thing and nothing shows which one is current: B does not say it replaces the claim and was not created later.
14
16
  - "overlap": same subject, and both lists have items.
15
- - "unrelated": different subjects or different facts that happen to share words.
17
+ - "unrelated": different subjects, or different named things written to one layout (two services, partners or regions), or different facts that happen to share words.
16
18
 
17
19
  Set "redundant" to the asset that could be deleted with no loss: "A" for "duplicate", the asset with the empty list for "subsumed", "A" for "supersedes"; else null. Set "stale" to "A" when the relation is "supersedes", else null.
18
20
 
19
- Answer ONLY with JSON: {"onlyInA": ["..."], "onlyInB": ["..."], "relation": "...", "redundant": "A"|"B"|null, "stale": "A"|null, "confidence": 0.0-1.0, "reason": "<at most 25 words: name the asset that can be deleted and what the other asset still holds>"}
21
+ Answer ONLY with JSON: {"onlyInA": ["..."], "onlyInB": ["..."], "relation": "...", "redundant": "A"|"B"|null, "stale": "A"|null, "confidence": 0.0-1.0, "reason": "<at most 25 words: name the asset that can be deleted and what the other asset still holds; for supersedes, quote the words of B that replace the claim or say B is created later>"}
@@ -156,19 +156,8 @@ export const GLOBAL_OUTPUT_ARGS = {
156
156
  format: { type: "string", description: "Output format: json|jsonl|yaml|text|md|html (global flag)" },
157
157
  detail: {
158
158
  type: "string",
159
- description: "Detail level (verbosity): brief|normal|full (global flag).",
160
- },
161
- // R-050(c): single-sourced with the root command's own `--shape` help
162
- // (`main.args.shape` in src/cli.ts, which spreads this object) so the
163
- // caveat is visible from every leaf's own `--help`, not only the top-level
164
- // one. `summary` outside `show` falls back to `agent` with a warning
165
- // (shapeForCommand in src/output/shapes.ts) — `--shape` is a global flag,
166
- // so a script that passes it to a mixed batch of commands still works.
167
- shape: {
168
- type: "string",
169
- description: "Output projection: human|agent|summary (global flag). 'agent' trims to agent-essential fields; " +
170
- "'summary' only has a dedicated projection on 'akm show' — elsewhere it falls back to 'agent' with a " +
171
- "warning. Default: human.",
159
+ description: "Detail level: brief|normal|full (verbosity), or agent (trims search, curate and show to agent-essential " +
160
+ "fields; other commands ignore it) (global flag).",
172
161
  },
173
162
  output: {
174
163
  type: "string",
@@ -294,51 +283,45 @@ export function outputWithExitCode(command, result, exitCode) {
294
283
  }
295
284
  export function output(command, result) {
296
285
  const mode = getOutputMode();
297
- const shaped = shapeForCommand(command, result, mode.detail, mode.shape);
298
- if (mode.format === "jsonl") {
299
- outputJsonl(command, shaped);
286
+ const { format } = mode;
287
+ if (format === "jsonl") {
288
+ outputJsonl(command, shapeForCommand(command, result, mode.detail, mode.shape));
300
289
  return;
301
290
  }
291
+ deliverRendered(renderOutput(command, result, { ...mode, format }), mode.outputPath);
292
+ }
293
+ /**
294
+ * Shape and render a command result into the document `output()` delivers.
295
+ * Pure: reads no process-level output mode and writes nothing, so in-process
296
+ * callers (`src/api.ts`) get text byte-identical to the CLI's stdout from an
297
+ * explicit `mode`.
298
+ */
299
+ export function renderOutput(command, result, mode) {
300
+ const shaped = shapeForCommand(command, result, mode.detail, mode.shape);
302
301
  switch (mode.format) {
303
302
  case "json":
304
- deliverRendered(JSON.stringify(shaped, null, 2), mode.outputPath);
305
- return;
303
+ return JSON.stringify(shaped, null, 2);
306
304
  case "yaml":
307
- deliverRendered(yamlStringify(shaped), mode.outputPath);
308
- return;
309
- case "text": {
305
+ return yamlStringify(shaped);
306
+ case "text":
310
307
  // D7 — registry first, generic rendering of the shaped envelope second.
311
- // Mirrors the md/html fallback immediately below: a command with no
312
- // registered text formatter used to fall through to
308
+ // A command with no registered text formatter used to fall through to
313
309
  // `JSON.stringify(shaped, null, 2)`, i.e. silently hand back JSON while
314
- // claiming `--format text` — the same "wrong format wearing the right
315
- // flag" bug D7 already closed for md/html. `renderGenericText` (a
316
- // DISTINCT function from `renderGenericMarkdown` — see its doc comment
317
- // in src/output/generic-render.ts for why reusing the md renderer here
318
- // was itself a version of the same bug) renders flat `key=value` text
319
- // matching the house style already established by registered text
320
- // formatters like `config list`.
321
- const plain = formatPlain(command, shaped, mode.detail);
322
- deliverRendered(plain ?? renderGenericText(command, shaped), mode.outputPath);
323
- return;
324
- }
325
- case "md": {
326
- // D7 — registry first, generic rendering of the shaped envelope second.
327
- // No command emits JSON under `--format md` any more: silently handing
328
- // back the wrong format was the worst of the three behaviours this
329
- // replaced.
330
- const rendered = getMdRendererHandler(command)?.(shaped, mode.detail);
331
- deliverRendered(rendered ?? renderGenericMarkdown(command, shaped), mode.outputPath);
332
- return;
333
- }
334
- case "html": {
310
+ // claiming `--format text`. `renderGenericText` renders flat
311
+ // `key=value` text matching the house style of registered formatters
312
+ // like `config list`; it is a DISTINCT function from
313
+ // `renderGenericMarkdown` (see src/output/generic-render.ts).
314
+ return formatPlain(command, shaped, mode.detail) ?? renderGenericText(command, shaped);
315
+ case "md":
316
+ // D7 — registry first, generic rendering second; no command emits JSON
317
+ // under `--format md`.
318
+ return getMdRendererHandler(command)?.(shaped, mode.detail) ?? renderGenericMarkdown(command, shaped);
319
+ case "html":
335
320
  // `akm health` and `akm metrics` are the only commands with a bespoke
336
321
  // HTML report, so they are called directly rather than through a
337
322
  // registry with two possible registrants (see `output/render-registry.ts`).
338
- const rendered = command === "health" ? renderHealthHtml(shaped) : command === "metrics" ? renderMetricsHtml(shaped) : null;
339
- deliverRendered(rendered ?? renderGenericHtml(command, shaped), mode.outputPath);
340
- return;
341
- }
323
+ return ((command === "health" ? renderHealthHtml(shaped) : command === "metrics" ? renderMetricsHtml(shaped) : null) ??
324
+ renderGenericHtml(command, shaped));
342
325
  }
343
326
  }
344
327
  // parseAllFlagValues moved to ./invocation (chunk-9 WI-9.9 argv-normalization
@@ -28,7 +28,6 @@
28
28
  import { UsageError } from "../core/errors.js";
29
29
  import { warn } from "../core/warn.js";
30
30
  import { cittyComparableName, findCittyTopLevelCommandIndex, toAliasArray, } from "./invocation.js";
31
- import { retiredFlagHint } from "./retired-commands.js";
32
31
  /**
33
32
  * Commands that must never refuse on an unrecognized flag — `akm info` warns
34
33
  * and continues instead of exiting 2, the same tolerance a bare `akm help
@@ -39,36 +38,6 @@ import { retiredFlagHint } from "./retired-commands.js";
39
38
  const UNKNOWN_FLAG_TOLERANT_COMMANDS = new Set(["info"]);
40
39
  /** Flags citty implements itself, which no command declares. */
41
40
  const IMPLICIT_FLAGS = ["help", "h", "version", "v"];
42
- /**
43
- * Retired flags whose commands still diagnose them THEMSELVES, with a message
44
- * that names the replacement ("`--scope` was removed, use `--filter`",
45
- * "`--source` was renamed to `--generator`"). A generic "unknown flag" would
46
- * preempt the better diagnosis, so these are passed through — but ONLY on the
47
- * command path that owns the diagnostic, keyed by the resolved path. On every
48
- * other command the same spelling is a genuine typo and still fails fast
49
- * A retired flag is rejected everywhere else, where silently dropping it could
50
- * run a real mutation.
51
- *
52
- * Shrink-only: when a command drops its bespoke diagnostic, drop the entry and
53
- * the generic error takes over.
54
- */
55
- const SELF_DIAGNOSED_FLAGS = new Map(Object.entries({
56
- show: ["akmView", "scope"], // removed view grammar; --scope points at --filter
57
- index: ["enrich", "re-enrich"], // removed index-time enrichment flags
58
- "proposal accept": ["source"], // renamed to --generator
59
- "proposal reject": ["source"], // renamed to --generator
60
- "proposal drain": ["profile"], // retired, points at --strategy
61
- search: ["source"], // renamed to --from
62
- curate: ["source"], // renamed to --from
63
- "task list": ["source"], // renamed to --from (alias of `search --type task`, #951)
64
- remember: ["target"], // renamed to --bundle
65
- clone: ["target"], // renamed to --bundle
66
- improve: ["auto-accept", "target"], // retired in 0.9.0 / renamed to --bundle
67
- "task add": ["target"], // renamed to --bundle
68
- "task run": ["target"], // renamed to --bundle
69
- "task history": ["target"], // renamed to --bundle
70
- "task sync": ["target"], // renamed to --bundle
71
- }).map(([path, flags]) => [path, new Set(flags.map(cittyComparableName))]));
72
41
  /**
73
42
  * Union the arg definitions declared along the resolved command path. The
74
43
  * subcommand walk delegates to {@link findCittyTopLevelCommandIndex} — the
@@ -111,6 +80,12 @@ function collectKnownArgs(root, rawArgs) {
111
80
  break;
112
81
  const idx = findCittyTopLevelCommandIndex(args, (cmd.args ?? {}));
113
82
  const token = idx >= 0 ? args[idx] : undefined;
83
+ // A command that takes a positional AND has subcommands (`improve [scope]`
84
+ // beside `improve report`) is itself the target when the token is absent
85
+ // or names none of them.
86
+ const takesPositional = Object.values(cmd.args ?? {}).some((def) => def.type === "positional");
87
+ if (takesPositional && (token === undefined || !subCommands[token]))
88
+ break;
114
89
  // A group with no subcommand token: citty reports "no command specified".
115
90
  if (token === undefined)
116
91
  return { names, valueFlags, booleanFlags, displayNames, path, resolved: false };
@@ -166,15 +141,6 @@ export function closestMatch(attempted, candidates, threshold) {
166
141
  * @param attempted The spelling to edit-distance against `--long` candidates.
167
142
  */
168
143
  function throwUnknownFlag(shown, attempted, known) {
169
- // Flags the 0.9 overhaul removed outright get their retirement note, not a
170
- // did-you-mean — same reasoning as `retiredCommandHint` in src/cli.ts:
171
- // edit distance can point at an unrelated survivor rather than the real
172
- // replacement procedure (e.g. `index --background` is closer to no other
173
- // `index` flag than it is to any useful suggestion).
174
- const retired = retiredFlagHint(known.path, attempted);
175
- if (retired) {
176
- throw new UsageError(`Unknown flag "${shown}".`, "UNKNOWN_FLAG", retired);
177
- }
178
144
  const threshold = Math.max(2, Math.ceil(attempted.length / 3));
179
145
  const suggestion = closestMatch(attempted, known.displayNames, threshold);
180
146
  throw new UsageError(`Unknown flag "${shown}".`, "UNKNOWN_FLAG", suggestion
@@ -207,7 +173,6 @@ export function assertKnownFlags(root, rawArgs) {
207
173
  // scanner, so it needs the identical exemption).
208
174
  const dynamicNamedFlagCommands = new Set(["workflow run", "task run", "task explain"]);
209
175
  const dynamicWorkflowParams = dynamicNamedFlagCommands.has(known.path.join(" "));
210
- const selfDiagnosed = SELF_DIAGNOSED_FLAGS.get(known.path.join(" "));
211
176
  const tolerant = UNKNOWN_FLAG_TOLERANT_COMMANDS.has(known.path.join(" "));
212
177
  for (let i = 0; i < ownArgs.length; i += 1) {
213
178
  const token = ownArgs[i];
@@ -250,8 +215,6 @@ export function assertKnownFlags(root, rawArgs) {
250
215
  ? rawName.slice(3)
251
216
  : undefined;
252
217
  const candidates = [cittyComparableName(rawName), ...(negated ? [cittyComparableName(negated)] : [])];
253
- if (selfDiagnosed !== undefined && candidates.some((name) => selfDiagnosed.has(name)))
254
- continue;
255
218
  if (!candidates.some((name) => known.names.has(name))) {
256
219
  // `workflow run` owns one deliberately dynamic namespace: long options
257
220
  // become exact-name workflow parameters and are checked against the
package/dist/cli.js CHANGED
@@ -58,7 +58,6 @@ process.on("uncaughtException", (err) => {
58
58
  import fs from "node:fs";
59
59
  import { defineCommand, parseArgs, renderUsage, runCommand, showUsage } from "citty";
60
60
  import { findCittyTopLevelCommandIndex, getParsedInvocation, parseAllFlagValues, resolveHelpMigrateVersionArg, setParsedInvocation, } from "./cli/invocation.js";
61
- import { retiredCommandHint } from "./cli/retired-commands.js";
62
61
  import { defineGroupCommand, EXIT_CODES, emitJsonError, GLOBAL_OUTPUT_ARGS, output, runWithJsonErrors, } from "./cli/shared.js";
63
62
  import { assertKnownFlags, closestMatch } from "./cli/unknown-flags.js";
64
63
  import { agentCommand, lintCommand } from "./commands/agent/contribute-cli.js";
@@ -137,7 +136,7 @@ function printSetupTtyHint(result) {
137
136
  if (!result?.bundleDir)
138
137
  return;
139
138
  console.error(plainize(`\n✓ Bundle created at ${result.bundleDir}\n` +
140
- ' Next: `akm bundle add <source>`, `akm index`, `akm search "<query>"`, `akm help agents`'));
139
+ ' Next: `akm bundle add <source>`, `akm index`, `akm search "<query>"`, `akm hints`'));
141
140
  }
142
141
  /**
143
142
  * Module Naming:
@@ -264,7 +263,7 @@ const healthCommand = defineCommand({
264
263
  args: {
265
264
  // R-051: `health` is a raw `defineCommand` (not `defineJsonCommand`), so
266
265
  // it does not get `GLOBAL_OUTPUT_ARGS` for free. `--format`/`--detail`/
267
- // `--shape`/`--output` already parsed correctly here (this command has
266
+ // `--output` already parsed correctly here (this command has
268
267
  // no positional for a stray value to fall into), so this is purely a
269
268
  // `--help` visibility / consistency fix, not a behavior change.
270
269
  ...GLOBAL_OUTPUT_ARGS,
@@ -383,9 +382,6 @@ const healthCommand = defineCommand({
383
382
  }
384
383
  },
385
384
  });
386
- function loadAgentHints(full) {
387
- return full ? EMBEDDED_HINTS_FULL : EMBEDDED_HINTS;
388
- }
389
385
  const hintsCommand = defineCommand({
390
386
  meta: {
391
387
  name: "hints",
@@ -401,7 +397,7 @@ const hintsCommand = defineCommand({
401
397
  run({ args }) {
402
398
  return runWithJsonErrors(() => {
403
399
  const detail = parseDetailLevel(args.detail) ?? "normal";
404
- process.stdout.write(loadAgentHints(detail !== "brief"));
400
+ process.stdout.write(detail === "brief" ? EMBEDDED_HINTS : EMBEDDED_HINTS_FULL);
405
401
  });
406
402
  },
407
403
  });
@@ -504,24 +500,6 @@ const helpCommand = defineGroupCommand({
504
500
  },
505
501
  subCommands: {
506
502
  ...commandHelpTopics,
507
- agents: defineCommand({
508
- meta: {
509
- name: "agents",
510
- description: "Print agent instructions on how to use akm — the short guide by default; pass --full for the complete guide",
511
- },
512
- args: {
513
- full: {
514
- type: "boolean",
515
- default: false,
516
- description: "Print the complete guide instead of the short one.",
517
- },
518
- },
519
- run({ args }) {
520
- return runWithJsonErrors(() => {
521
- process.stdout.write(loadAgentHints(args.full === true));
522
- });
523
- },
524
- }),
525
503
  migrate: defineCommand({
526
504
  meta: {
527
505
  name: "migrate",
@@ -855,7 +833,7 @@ function renderCommandSections() {
855
833
  * USAGE line + global OPTIONS, then cuts the string before citty's own
856
834
  * "COMMANDS" heading (present because `main` has `subCommands`) and appends
857
835
  * the grouped sections plus a one-line bundle/ref-grammar tagline and the
858
- * `akm help agents` pointer.
836
+ * `akm hints` pointer.
859
837
  */
860
838
  async function renderSectionedRootHelp() {
861
839
  const base = await renderUsage(main, undefined);
@@ -872,7 +850,7 @@ async function renderSectionedRootHelp() {
872
850
  "`akm search` output rather than synthesizing them.",
873
851
  "",
874
852
  "Run `akm help <command>` or `akm <command> --help` for details on any command.",
875
- "Agents: run `akm hints` for the complete guide or `akm help agents` for the short guide.",
853
+ "Agents: run `akm hints` for the complete guide, or `akm hints --detail brief` for the short one.",
876
854
  ].join("\n");
877
855
  return [head, "", renderCommandSections(), "", epilogue].join("\n");
878
856
  }
@@ -910,7 +888,7 @@ function findUnknownCommandAttempt(rawArgs) {
910
888
  }
911
889
  /** Closest command within a length-scaled distance threshold (shared DP in cli/unknown-flags.ts). */
912
890
  function closestCommandMatch(attempted, candidates) {
913
- return closestMatch(attempted, candidates, Math.max(2, Math.ceil(attempted.length / 2)));
891
+ return closestMatch(attempted, candidates, Math.floor(attempted.length / 3));
914
892
  }
915
893
  const CLI_HELP_POINTER = "Run `akm --help` for usage.";
916
894
  /**
@@ -944,12 +922,8 @@ function cittyCliErrorUsageCode(error) {
944
922
  function toUsageErrorFromCliError(error, rawArgs) {
945
923
  const code = cittyCliErrorUsageCode(error);
946
924
  const attempt = code === "UNKNOWN_COMMAND" ? findUnknownCommandAttempt(rawArgs) : undefined;
947
- // Retired spellings from the 0.9 hard break get their replacement, not a
948
- // did-you-mean: edit distance suggests the WRONG command for most of them
949
- // (`init`→`info`, `update`→`upgrade`), and agents follow suggestions.
950
- const retired = attempt ? retiredCommandHint(attempt.parentPath, attempt.attempted) : undefined;
951
- const suggestion = retired === undefined && attempt ? closestCommandMatch(attempt.attempted, attempt.candidates) : undefined;
952
- const hint = retired ?? (suggestion ? `Did you mean \`${suggestion}\`? ${CLI_HELP_POINTER}` : CLI_HELP_POINTER);
925
+ const suggestion = attempt ? closestCommandMatch(attempt.attempted, attempt.candidates) : undefined;
926
+ const hint = suggestion ? `Did you mean \`${suggestion}\`? ${CLI_HELP_POINTER}` : CLI_HELP_POINTER;
953
927
  // citty colorizes error.message with ANSI escapes even when stdout/stderr
954
928
  // is not a TTY. Strip them so the JSON envelope's `error` field is plain
955
929
  // text instead of embedding raw escape sequences.
@@ -112,7 +112,7 @@ export const lintCommand = defineCommand({
112
112
  args: {
113
113
  // R-051: `lint` is a raw `defineCommand` (not `defineJsonCommand`), so it
114
114
  // does not get `GLOBAL_OUTPUT_ARGS` for free. `--format`/`--detail`/
115
- // `--shape`/`--output` already parsed correctly here (this command has no
115
+ // `--output` already parsed correctly here (this command has no
116
116
  // positional for a stray value to fall into), so this is purely a
117
117
  // `--help` visibility / consistency fix, not a behavior change.
118
118
  ...GLOBAL_OUTPUT_ARGS,
@@ -7,8 +7,7 @@ import path from "node:path";
7
7
  import { placementTypes } from "../core/asset/asset-placement.js";
8
8
  const FLAG_VALUES = {
9
9
  "--format": [{ values: ["json", "jsonl", "yaml", "text", "md", "html"] }],
10
- "--detail": [{ values: ["brief", "normal", "full"] }],
11
- "--shape": [{ values: ["human", "agent", "summary"] }],
10
+ "--detail": [{ values: ["brief", "normal", "full", "agent"] }],
12
11
  "--type": [{ values: () => [...placementTypes(), "any"] }],
13
12
  "--shell": [{ values: ["bash"] }],
14
13
  "--from": [{ paths: ["akm search", "akm curate"], values: ["local", "registry", "all"] }],
@@ -14,11 +14,11 @@
14
14
  */
15
15
  import { isDeepStrictEqual } from "node:util";
16
16
  import { defineGroupCommand, defineJsonCommand, output } from "../cli/shared.js";
17
- import { isRecord, resolveStashDir } from "../core/common.js";
17
+ import { isRecord } from "../core/common.js";
18
18
  import { DEFAULT_CONFIG, getConfigValueSource, loadConfig, mutateConfig, parseAndValidateConfigText, resolveConfigRefSource, } from "../core/config/config.js";
19
19
  import { configGet, configSet, configUnset, unknownKeyHint } from "../core/config/config-walker.js";
20
20
  import { UsageError } from "../core/errors.js";
21
- import { getCacheDir, getConfigPath, getDbPath, getDefaultStashDir } from "../core/paths.js";
21
+ import { getConfigPath } from "../core/paths.js";
22
22
  import { formatRegistryUrl } from "../core/registry-url.js";
23
23
  // ── Public API ──────────────────────────────────────────────────────────────
24
24
  export function getConfigValue(config, key) {
@@ -118,32 +118,9 @@ export const configCommand = defineGroupCommand({
118
118
  meta: { name: "config", description: "Show and manage configuration" },
119
119
  subCommands: {
120
120
  path: defineJsonCommand({
121
- meta: { name: "path", description: "Show paths to config, bundle, cache, and index" },
122
- args: {
123
- all: { type: "boolean", description: "Show all paths (config, bundle, cache, index)", default: false },
124
- },
125
- run({ args }) {
126
- const configPath = getConfigPath();
127
- if (args.all) {
128
- let stashDir;
129
- try {
130
- stashDir = resolveStashDir();
131
- }
132
- catch {
133
- stashDir = `${getDefaultStashDir()} (not initialized)`;
134
- }
135
- const cacheDir = getCacheDir();
136
- const result = {
137
- config: configPath,
138
- bundle: stashDir,
139
- cache: cacheDir,
140
- index: getDbPath(),
141
- };
142
- output("config", result);
143
- }
144
- else {
145
- console.log(configPath);
146
- }
121
+ meta: { name: "path", description: "Print the path to the config file" },
122
+ run() {
123
+ console.log(getConfigPath());
147
124
  },
148
125
  }),
149
126
  list: defineJsonCommand({