akm-cli 0.9.29 → 0.9.31

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 (162) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +10 -10
  3. package/ROADMAP.md +112 -0
  4. package/dist/commands/improve/improve-cli.js +33 -12
  5. package/dist/commands/sources/plugin-upgrade.js +46 -23
  6. package/dist/core/file-lock.js +10 -1
  7. package/dist/llm/client.js +33 -3
  8. package/dist/scripts/akm-migrate-node.js +5 -1
  9. package/dist/scripts/akm-migrate.js +5 -1
  10. package/docs/README.md +42 -41
  11. package/docs/agents/README.md +15 -0
  12. package/docs/agents/agent-install.md +14 -0
  13. package/docs/architecture/README.md +67 -0
  14. package/docs/architecture/adapters.md +272 -0
  15. package/docs/architecture/akm-architecture-decision-history.md +2055 -0
  16. package/docs/architecture/akm-core-principles.md +126 -0
  17. package/docs/architecture/architecture.md +579 -0
  18. package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +550 -0
  19. package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +72 -0
  20. package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +142 -0
  21. package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +189 -0
  22. package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +97 -0
  23. package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +108 -0
  24. package/docs/architecture/decisions/0006-task-source-version-routing.md +124 -0
  25. package/docs/architecture/decisions/0007-workflow-composition-bounds.md +83 -0
  26. package/docs/architecture/decisions/0008-task-binding-normalization.md +88 -0
  27. package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +80 -0
  28. package/docs/architecture/decisions/0010-driver-protocol-cut.md +36 -0
  29. package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +125 -0
  30. package/docs/architecture/decisions/README.md +62 -0
  31. package/docs/architecture/improvement.md +440 -0
  32. package/docs/architecture/internals/classification.md +154 -0
  33. package/docs/architecture/internals/fresh-host-rebuild-runbook.md +40 -0
  34. package/docs/architecture/internals/functional-contract-patterns.md +340 -0
  35. package/docs/architecture/internals/health-advisories.md +110 -0
  36. package/docs/architecture/internals/improve-workflow.md +713 -0
  37. package/docs/architecture/internals/indexing.md +498 -0
  38. package/docs/architecture/internals/registry-network-boundary.md +57 -0
  39. package/docs/architecture/internals/search.md +249 -0
  40. package/docs/architecture/internals/storage-locations.md +943 -0
  41. package/docs/architecture/persisted-data-compat.md +59 -0
  42. package/docs/architecture/reviews/env-secret-access.md +319 -0
  43. package/docs/architecture/runtime-boundary-design.md +153 -0
  44. package/docs/architecture/specs/0.9.0-close-out-plan.md +361 -0
  45. package/docs/architecture/specs/0.9.0-decisions.md +528 -0
  46. package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +745 -0
  47. package/docs/architecture/specs/0.9.0-open-items-register.md +135 -0
  48. package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +740 -0
  49. package/docs/architecture/specs/0.9.0-release-surface-review.md +636 -0
  50. package/docs/architecture/specs/agent-command-engine-model-design.md +513 -0
  51. package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +501 -0
  52. package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +291 -0
  53. package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +2059 -0
  54. package/docs/architecture/specs/di-seams-plan.md +539 -0
  55. package/docs/architecture/specs/driver-protocol-keep-or-cut.md +275 -0
  56. package/docs/architecture/specs/fact-asset-type.md +142 -0
  57. package/docs/architecture/specs/improve-collapse-churn-detector-design.md +634 -0
  58. package/docs/architecture/specs/okf-support.md +148 -0
  59. package/docs/architecture/specs/ref.md +329 -0
  60. package/docs/architecture/specs/reviews/task-workflow-unification/README.md +72 -0
  61. package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +152 -0
  62. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +352 -0
  63. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +300 -0
  64. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +402 -0
  65. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +758 -0
  66. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +645 -0
  67. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +602 -0
  68. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +27 -0
  69. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +27 -0
  70. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +74 -0
  71. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +15 -0
  72. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +132 -0
  73. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +147 -0
  74. package/docs/architecture/specs/stash-conventions-code-spec.md +275 -0
  75. package/docs/architecture/specs/stash-organization-conventions.md +377 -0
  76. package/docs/architecture/specs/task-workflow-format-unification.md +721 -0
  77. package/docs/architecture/specs/workflow-engine-buy-vs-build.md +231 -0
  78. package/docs/architecture/specs/workflow-format-unification.md +437 -0
  79. package/docs/architecture/testing/manual-testing-checklist.md +3420 -0
  80. package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +924 -0
  81. package/docs/architecture/testing/task-workflow-manual-tests.md +1817 -0
  82. package/docs/architecture/testing/testing-workflow.md +446 -0
  83. package/docs/architecture/workflow-engine.md +274 -0
  84. package/docs/guides/README.md +33 -0
  85. package/docs/guides/author-bundles.md +310 -0
  86. package/docs/guides/author-workflows.md +520 -0
  87. package/docs/guides/bundles.md +321 -0
  88. package/docs/guides/capture-knowledge.md +136 -0
  89. package/docs/guides/claude-code-vs-akm-workflows.md +30 -0
  90. package/docs/guides/concepts.md +93 -0
  91. package/docs/guides/discover-and-load.md +158 -0
  92. package/docs/guides/getting-started.md +240 -0
  93. package/docs/guides/improve-the-library.md +246 -0
  94. package/docs/guides/knowledge-management.md +18 -0
  95. package/docs/guides/recipes/headless-install.md +97 -0
  96. package/docs/guides/recipes/website-source.md +28 -0
  97. package/docs/guides/run-workflows.md +279 -0
  98. package/docs/guides/scheduling.md +123 -0
  99. package/docs/guides/use-with-any-agent.md +129 -0
  100. package/docs/guides/wikis.md +81 -0
  101. package/docs/maintainers/README.md +19 -0
  102. package/docs/maintainers/curate-workmap.md +336 -0
  103. package/docs/maintainers/eval.md +3 -0
  104. package/docs/maintainers/local-development.md +108 -0
  105. package/docs/maintainers/release-checklist.md +103 -0
  106. package/docs/migration/README.md +2 -2
  107. package/docs/migration/release-notes/0.0.13.md +1 -1
  108. package/docs/migration/release-notes/0.1.0.md +1 -1
  109. package/docs/migration/release-notes/0.2.0.md +1 -1
  110. package/docs/migration/release-notes/0.3.0.md +1 -1
  111. package/docs/migration/release-notes/0.5.0.md +1 -1
  112. package/docs/migration/release-notes/0.6.0.md +1 -1
  113. package/docs/migration/release-notes/0.7.0.md +1 -1
  114. package/docs/migration/release-notes/0.7.3.md +2 -2
  115. package/docs/migration/release-notes/0.7.4.md +1 -1
  116. package/docs/migration/release-notes/0.7.5.md +1 -1
  117. package/docs/migration/release-notes/0.8.0.md +1 -1
  118. package/docs/migration/release-notes/0.9.0.md +1 -1
  119. package/docs/migration/release-notes/0.9.14.md +1 -1
  120. package/docs/migration/release-notes/0.9.15.md +1 -1
  121. package/docs/migration/release-notes/0.9.16.md +1 -1
  122. package/docs/migration/release-notes/0.9.17.md +1 -1
  123. package/docs/migration/release-notes/0.9.19.md +1 -1
  124. package/docs/migration/release-notes/0.9.2.md +1 -1
  125. package/docs/migration/release-notes/README.md +27 -31
  126. package/docs/migration/v0.5-to-v0.6.md +759 -0
  127. package/docs/migration/v0.8-to-v0.9.md +1 -1
  128. package/docs/plans/0.9.2-agent-command-workflow-plan.md +423 -0
  129. package/docs/posts/README.md +30 -0
  130. package/docs/posts/akm-command-tour.md +495 -0
  131. package/docs/posts/akm-logo-sized.webp +0 -0
  132. package/docs/posts/belief-aware-memory-12.md +139 -0
  133. package/docs/posts/config-v2-lessons-16.md +191 -0
  134. package/docs/posts/improve-loop-autonomous-10.md +225 -0
  135. package/docs/posts/improve-pipeline-debugging-0803.md +179 -0
  136. package/docs/posts/intro-part-01.md +76 -0
  137. package/docs/posts/intro-part-02.md +221 -0
  138. package/docs/posts/intro-part-03.md +190 -0
  139. package/docs/posts/intro-part-04.md +221 -0
  140. package/docs/posts/llm-mode-reflect-13.md +166 -0
  141. package/docs/posts/openpalm-built-on-akm.md +86 -0
  142. package/docs/posts/progressive-disclosure-06.md +129 -0
  143. package/docs/posts/proposal-safety-net-15.md +112 -0
  144. package/docs/posts/release-0.5.0.md +247 -0
  145. package/docs/posts/release-0.6.0.md +117 -0
  146. package/docs/posts/release-0.7.0.md +159 -0
  147. package/docs/posts/release-0.8.0.md +332 -0
  148. package/docs/posts/scattered-skills-05.md +100 -0
  149. package/docs/posts/task-assets-persistent-workflows-11.md +222 -0
  150. package/docs/posts/team-skills-07.md +198 -0
  151. package/docs/posts/wiki-agent-knowledge-08.md +223 -0
  152. package/docs/posts/workflows-vaults-09.md +321 -0
  153. package/docs/product-surface.md +54 -0
  154. package/docs/reference/README.md +1 -2
  155. package/docs/reference/asset-types.md +168 -0
  156. package/docs/reference/cli.md +5 -6
  157. package/docs/reference/env-and-secrets.md +126 -0
  158. package/docs/reference/memory.md +124 -0
  159. package/docs/reference/refs.md +156 -0
  160. package/docs/reference/registry.md +489 -0
  161. package/docs/reference/website-sources.md +141 -0
  162. package/package.json +12 -15
@@ -0,0 +1,191 @@
1
+ ---
2
+ title: 'One Schema to Rule Them All: The Config v2 Rewrite'
3
+ cover_image: 'https://raw.githubusercontent.com/itlackey/akm/main/docs/posts/akm-logo-sized.webp'
4
+ series: akm-knowledge
5
+ description: 'How replacing ~1.4k LOC of hand-written config parsers with a single Zod schema eliminated silent failures, auto-generates the JSON schema, and makes adding a new config field a one-line change.'
6
+ tags:
7
+ - ai
8
+ - agents
9
+ - cli
10
+ - configuration
11
+ published: true
12
+ id: 3814550
13
+ date: '2026-06-04T00:32:02Z'
14
+ ---
15
+
16
+ > This is a dated article from AKM's publishing archive. For current product behavior, see the
17
+ > [documentation index](https://github.com/itlackey/akm/blob/main/docs/README.md).
18
+
19
+ This is part sixteen in a series about managing the growing pile of skills, scripts, and context that AI coding agents depend on. The [0.8.0 release notes](https://dev.to/itlackey/akm-080-cli-redesign-task-assets-and-belief-aware-memory-335a) cover the storage and pipeline changes that shipped alongside this rewrite; [Part thirteen](https://dev.to/itlackey/from-30-minutes-to-8-how-llm-mode-reflect-works-5epl) covers how the new `profiles.improve` config drives the improve pipeline.
20
+
21
+ Config files are where projects go to accumulate technical debt quietly. Each new feature gets a new key. Each new key gets a new parser. Each parser has slightly different error handling, slightly different defaults, and slightly different ideas about what "invalid" means. Nobody notices until a user files an issue that says "I had a typo in my config and akm just silently used defaults for three weeks."
22
+
23
+ That was the state of akm's config layer going into 0.8.0.
24
+
25
+ ## What the Old Shape Looked Like
26
+
27
+ The v1 config had three top-level blocks that grew independently over two years: `llm.*` for LLM connection settings, `agent.*` for agent process settings, and `llm.features.*` boolean flags gating per-feature LLM calls. The features block was nested under `llm` for historical reasons even though many features used the agent, not the LLM. The agent's per-process map lived under `agent.processes`, while LLM-gated features used `llm.features.index.metadata_enhance` style dotted paths.
28
+
29
+ Each block had its own parser function. `parseLlmConfig`, `parseEmbeddingConfig`, `parseIndexConfig`, and a dozen more. The comment at the top of the new `config-schema.ts` is blunt about it: the Zod schema "replaces the ~1.4k LOC of legacy per-shape parsers."
30
+
31
+ The problems that accumulated in that ~1.4k LOC:
32
+
33
+ **Unknown keys were silently accepted.** If you wrote `llm.temperaure` (typo), the parser ignored it and fell back to the default temperature. No warning. You tuned a key that did nothing.
34
+
35
+ **Bad JSON was masked.** The config loader caught JSON parse errors and fell back to `DEFAULT_CONFIG` — the compiled-in defaults. Your entire config file could be corrupt and akm would start without complaint, using defaults across the board.
36
+
37
+ **Missing files fell back to defaults.** Same behavior. A missing config file and a present-but-corrupt one looked identical at runtime.
38
+
39
+ **Adding a field meant adding a parser.** Want a new boolean flag under a feature? Find the right parser function, add the extraction logic, add the type declaration, add the hint string, add the test. The cost of a new field was not one line — it was a small PR touching four or five places.
40
+
41
+ ## What Zod Gives You
42
+
43
+ The 0.8.0 rewrite consolidates all of that into `src/core/config-schema.ts`: a single Zod schema that is the source of truth for the on-disk shape.
44
+
45
+ Zod handles the parse, transform, and validate steps that were previously scattered across ~1.4k LOC of hand-written code. A new config field is a one-line schema addition. Type inference means the TypeScript types for `AkmConfig` are derived from the schema automatically — no parallel maintenance between the schema and the type declarations.
46
+
47
+ The schema design makes deliberate tradeoffs between strictness and resilience:
48
+
49
+ The top-level object uses `.passthrough()` so unknown future keys round-trip intact. If a user upgrades and then downgrades, keys added by the newer version survive without triggering errors on the older version. `sanitizeConfigForWrite` decides what to strip on write.
50
+
51
+ Nested sub-objects use `.catch(undefined)` for field-level shape errors so that a typo in one field does not destroy an otherwise valid config. This preserves the legacy parser's warn-and-ignore semantics for individual fields while still catching structural problems.
52
+
53
+ `.strict()` walls gate the records that are most typo-prone: `registries[]`, `sources[]`, and `profiles.*` sub-shapes. A typo in a profile name or a source type now produces a validation error at load time.
54
+
55
+ Two cases are hard-rejected by `superRefine` rather than silently dropped: the old `stashes[]` key (replaced by `sources[]`) and a legacy source type that had been removed. Both have explicit migration paths — silently ignoring them would mask user data loss.
56
+
57
+ ## The Silent Failure Fixes
58
+
59
+ The new loader changed three behaviors that were causing silent failures in the field.
60
+
61
+ **Unknown keys now error at the profile level.** A typo in `profiles.llm.my-profile` is caught at load time rather than ignored. The error message names the unexpected key and points at the profile block.
62
+
63
+ **Bad JSON now throws.** If `config.json` is not valid JSON, akm throws a `ConfigError` with the file path and the parse error. No fallback to defaults. The user finds out immediately.
64
+
65
+ **Missing files stay missing.** A missing config file is a different situation from a corrupt one, and akm treats them differently now. First run with no config: `akm setup` or an explicit `akm config set` creates the file. A missing file during a subsequent run is an error, not a silent fallback.
66
+
67
+ ## Auto-Generated JSON Schema
68
+
69
+ With a Zod schema as the source of truth, generating a JSON schema for editor autocompletion is a natural output. The `schemas/akm-config.json` file is generated from the Zod schema and checked in. A CI drift test fails if the checked-in file is out of sync with the schema source — there is no manual step to remember when adding a field.
70
+
71
+ Point your editor at the schema and you get field completion and inline documentation in `config.json`:
72
+
73
+ ```jsonc
74
+ {
75
+ "$schema": "https://itlackey.github.io/akm/schemas/akm-config.0.8.0.json",
76
+ "configVersion": "0.8.0"
77
+ }
78
+ ```
79
+
80
+ The `$schema` key is optional. VSCode and other JSON Schema-aware editors pick it up automatically for field completion and inline docs.
81
+
82
+ ## The New Config Shape
83
+
84
+ The 0.8.0 shape replaces the scattered `llm.*`, `agent.*`, and `llm.features.*` blocks with a unified `profiles` tree and first-class feature sections.
85
+
86
+ | Old location | New location |
87
+ |---|---|
88
+ | `llm.endpoint`, `llm.model`, `llm.apiKey` | `profiles.llm.<name>.endpoint`, `.model`, `.apiKey` |
89
+ | `agent.platform`, `agent.bin`, `agent.args` | `profiles.agent.<name>.platform`, `.bin`, `.args` |
90
+ | `agent.processes.<name>.*` | `profiles.improve.<name>.processes.*` |
91
+ | `llm.features.index.metadata_enhance` | `index.metadataEnhance.enabled` |
92
+ | `llm.features.search.curate_rerank` | `search.curateRerank.enabled` |
93
+
94
+ Named LLM connections live under `profiles.llm.<name>`, declared once and referenced by name from process entries. Named agent connections live under `profiles.agent.<name>`. The improve profile (`profiles.improve.<name>.processes.*`) binds processes to specific LLM or agent profiles and controls per-process gating. Non-improve features (`index.metadataEnhance`, `index.stalenessDetection`, `search.curateRerank`) are first-class top-level entries.
95
+
96
+ The `configVersion` field is the version gate. Configs without it, or with a pre-0.8.0 value, are auto-migrated at first run.
97
+
98
+ ## The Minimal Working Config
99
+
100
+ The smallest config that gets you a fully functional 0.8.0 installation with a cloud LLM for improve operations:
101
+
102
+ ```jsonc
103
+ {
104
+ "configVersion": "0.8.0",
105
+ "$schema": "https://itlackey.github.io/akm/schemas/akm-config.0.8.0.json",
106
+ "profiles": {
107
+ "llm": {
108
+ "openai-mini": {
109
+ "endpoint": "https://api.openai.com/v1/chat/completions",
110
+ "model": "gpt-4o-mini",
111
+ "apiKey": "${OPENAI_API_KEY}",
112
+ "temperature": 0.3,
113
+ "supportsJsonSchema": true
114
+ }
115
+ },
116
+ "agent": {
117
+ "opencode-default": { "platform": "opencode", "bin": "opencode", "args": ["run"] }
118
+ },
119
+ "improve": {
120
+ "default": {
121
+ "processes": {
122
+ "reflect": { "enabled": true, "mode": "llm", "profile": "openai-mini" },
123
+ "distill": { "enabled": true, "mode": "llm", "profile": "openai-mini" },
124
+ "consolidate": { "enabled": true, "mode": "llm", "profile": "openai-mini" },
125
+ "memoryInference": { "enabled": true },
126
+ "graphExtraction": { "enabled": true, "profile": "openai-mini" }
127
+ }
128
+ }
129
+ }
130
+ },
131
+ "defaults": {
132
+ "llm": "openai-mini",
133
+ "agent": "opencode-default",
134
+ "improve": "default"
135
+ },
136
+ "embedding": {
137
+ "endpoint": "http://localhost:11434/v1/embeddings",
138
+ "model": "nomic-embed-text",
139
+ "dimension": 384
140
+ },
141
+ "stashDir": "~/akm"
142
+ }
143
+ ```
144
+
145
+ This is a trimmed example focused on the core profiles and defaults. The full minimal config in [configuration reference](../reference/configuration.md) also includes `feedbackDistillation`, `index`, and `search` top-level blocks with their defaults. If you omit those blocks, akm uses compiled-in defaults for them.
146
+
147
+ For local models, swap `openai-mini` for an Ollama or LM Studio profile and drop the `apiKey` field. The `supportsJsonSchema` flag tells akm to use structured JSON output for providers that support it — set it to `true` for OpenAI-compatible endpoints that honor `response_format: {type: "json_schema"}`, leave it off for local models that do not.
148
+
149
+ ## Migrating from v1
150
+
151
+ If you are on 0.7.x, you do not need to hand-edit your config. The migration command handles the key remapping:
152
+
153
+ ```sh
154
+ # Preview the transformation without writing
155
+ akm config migrate --dry-run # doclint:ignore (0.7.x→0.8.0 config-schema migration command, not present in 0.9.0)
156
+
157
+ # Apply migration — writes a timestamped backup first
158
+ akm config migrate # doclint:ignore (0.7.x→0.8.0 config-schema migration command, not present in 0.9.0)
159
+ ```
160
+
161
+ `--dry-run` shows which keys move and what the new shape looks like without writing anything. When you run without `--dry-run`, akm writes a timestamped backup to `~/.cache/akm/config-backups/` before touching the live file. Locate it with:
162
+
163
+ ```sh
164
+ ls -1t ~/.cache/akm/config-backups/ | head
165
+ ```
166
+
167
+ Auto-migration also runs on the first command after upgrade — a one-time notice prints to stderr with the backup path and a reminder to set `AKM_NO_AUTO_MIGRATE=1` to suppress future auto-migration. That env flag is useful for read-only CI mounts where you want to run `akm config migrate` explicitly in a deploy step.
168
+
169
+ After migration, verify the result:
170
+
171
+ ```sh
172
+ akm config get configVersion
173
+ # "0.8.0"
174
+
175
+ akm config
176
+ # Full config in the new shape
177
+ ```
178
+
179
+ The complete old-to-new key mapping is in [docs/migration/v0.7-to-v0.8.md](https://github.com/itlackey/akm/blob/main/docs/migration/v0.7-to-v0.8.md).
180
+
181
+ ## What Adding a Field Looks Like Now
182
+
183
+ Before the rewrite, adding a new per-process option involved touching the parser function, the type declaration, the hint string, and the test. In the Zod schema, the same change is one line in the relevant sub-schema object. TypeScript picks up the new field automatically through inference. The JSON schema regenerates on the next build. The CI drift test catches it if the regeneration step is skipped.
184
+
185
+ The cost of that improvement is worth making concrete: the schema file is 641 LOC. The migration logic is another 643 LOC. The config loader itself is 590 LOC. That is 1,874 lines total (approximate) — replacing the ~1.4k LOC of parsers while also adding the migration pipeline, the strict validation, and the structured error reporting that were not present before. The maintenance surface per feature is lower, not higher.
186
+
187
+ ---
188
+
189
+ Config v2 is in akm 0.8.0. The full configuration reference is in [configuration reference](../reference/configuration.md). The [0.8.0 release notes](https://dev.to/itlackey/akm-080-cli-redesign-task-assets-and-belief-aware-memory-335a) cover the broader storage and pipeline changes that landed alongside the config rewrite. If you are running the improve pipeline and want to see how the `profiles.improve` config behaves in practice, [Your Agent Has a Memory That Runs While You Sleep](https://dev.to/itlackey/your-agent-has-a-memory-that-runs-while-you-sleep-20oh) covers 24 hours of autonomous operation with the full process config in place.
190
+
191
+ If you are upgrading, start with `akm config migrate --dry-run` and check that the output matches your expectations before applying.
@@ -0,0 +1,225 @@
1
+ ---
2
+ title: 'The Improvement Loop: How akm Keeps Your Agent Sharp'
3
+ cover_image: 'https://raw.githubusercontent.com/itlackey/akm/main/docs/posts/akm-logo-sized.webp'
4
+ series: akm-knowledge
5
+ description: 'akm improve runs a multi-phase pipeline — reflect, distill, consolidate, memory inference, graph extraction — that continuously refines your agent knowledge base. Here is what each phase does and how to wire it into your workflow.'
6
+ tags:
7
+ - ai
8
+ - agents
9
+ - cli
10
+ - automation
11
+ published: true
12
+ id: 3814541
13
+ date: '2026-06-04T00:32:02Z'
14
+ ---
15
+
16
+ > This is a dated article from AKM's publishing archive. For current product behavior, see the
17
+ > [documentation index](https://github.com/itlackey/akm/blob/main/docs/README.md).
18
+
19
+ This is part ten in a series about managing the growing pile of skills, scripts, and context that AI coding agents depend on. [Part nine](https://dev.to/itlackey/agents-that-remember-where-they-were-1koe) covered workflow assets, vault assets, and the writable git stash. [Part eight](https://dev.to/itlackey/building-agent-knowledge-bases-that-actually-scale-23pb) tackled multi-wiki support for structured research. Earlier parts addressed teams, distributed stashes, feedback scoring, and community knowledge.
20
+
21
+ This one is about entropy.
22
+
23
+ You ship a feature. Your agent writes several memories during the session — partial findings, a workaround, a note about the build step that kept failing. Those memories are accurate when written. Three sprints later, the workaround is no longer needed, two of the memories say slightly different things about the same subsystem, and the note about the build step refers to a CI config that was replaced. None of this is catastrophic. But it accumulates. After six months, a significant fraction of your stash is stale, redundant, or quietly wrong.
24
+
25
+ You could audit it manually. In practice, you won't — the stash is too large, the relevance of any given memory is hard to assess without the context where it was created, and the judgment calls (merge these two? promote this? delete that?) are exactly the kind of work that's tedious for a human and tractable for an LLM.
26
+
27
+ `akm improve` is the answer to that problem. It is a multi-phase pipeline that reads your stash, evaluates asset quality, consolidates scattered memories, extracts structured facts, and maps entity relationships — on a schedule, without manual intervention, producing proposals you can review before anything changes.
28
+
29
+ ## The Five Phases
30
+
31
+ `akm improve` is not a single LLM call. It is a sequenced pipeline where each phase produces inputs for the next.
32
+
33
+ **Reflect** evaluates asset quality. For each asset in scope, the reflect pass reviews the content against usage signals — search hits, retrieval counts, feedback — and produces a quality assessment. Low-quality assets are flagged as candidates for improvement. Since 0.8.0, reflect can run as a direct LLM HTTP call instead of spawning an agent subprocess, which cuts per-call latency from ~30 seconds to ~6–10 seconds:
34
+
35
+ | Reflect mode | Time per call | 69-ref run |
36
+ |---|---|---|
37
+ | agent (CLI subprocess) | ~30s | ~35 min |
38
+ | sdk (in-process) | ~10–15s | ~12–17 min |
39
+ | llm (direct HTTP) | ~6–10s | ~8–10 min |
40
+
41
+ **Distill** turns observations from reflect into lesson proposals. Where reflect says "this skill is incomplete and frequently retrieved with poor satisfaction," distill produces a draft improvement — a new version of the skill, a supplementary lesson, or a deprecation proposal. These proposals go into the queue; nothing is written to your stash until you accept them.
42
+
43
+ **Consolidate** handles the memory pool specifically. Your memory pool accumulates entries from agent sessions — `akm remember` calls, auto-captured observations, and task agent outputs. Consolidation groups related memories into chunks, sends each chunk to the LLM for a curation plan (merge near-duplicates, promote high-signal items, delete redundant entries, surface contradictions), and executes those plans. The result is a smaller, cleaner memory pool and new stash promotions.
44
+
45
+ **Memory inference** runs after consolidation. It takes the post-consolidation state and runs a lightweight factual extraction pass — pulling out atomic facts that did not make it into explicit memory entries. These become additional promotion candidates. In steady-state operation, memory inference yields around 60–70% (69.3% in a recent 24-hour window) usable atomic facts on each pass.
46
+
47
+ **Graph extraction** runs last, against the final post-improve state. It builds the entity-relation index that powers `akm graph` commands — which stash entries mention a given entity, which entities co-occur, and which assets produced zero entities (quality-triage candidates via `akm graph orphans`). As of 0.8.0, extraction is incremental: only assets that changed during the improve run are re-extracted, and batches of four run in parallel by default.
48
+
49
+ Each phase is independently enabled or disabled per profile. A `quick` profile runs reflect only. A `memory-focus` profile runs reflect and memory inference on memory and lesson types. A `thorough` profile runs all five phases and auto-syncs the result to your git-backed stash.
50
+
51
+ ## Running the Loop
52
+
53
+ The basic invocation:
54
+
55
+ ```sh
56
+ akm improve
57
+ ```
58
+
59
+ That runs all enabled phases on the full stash, scoped by your default improve profile. Before running for the first time, use `--dry-run` to see what would be processed without writing anything:
60
+
61
+ ```sh
62
+ akm improve --dry-run
63
+ ```
64
+
65
+ The dry-run output shows which assets are selected, in what order, and which phases would run. Nothing is written to `state.db` from the dry-run path — the improve result is flagged `.dryRun: true` and excluded from health metrics.
66
+
67
+ To scope the pass to a specific asset type:
68
+
69
+ ```sh
70
+ akm improve memory # memory pool only
71
+ akm improve skill # skills only
72
+ akm improve skills/deploy # one specific asset
73
+ ```
74
+
75
+ To add extra guidance for the pass — useful when you know a particular focus area is relevant:
76
+
77
+ ```sh
78
+ akm improve --task "focus on deduplication in the build tooling notes"
79
+ ```
80
+
81
+ To cap the number of assets processed (highest-utility first by default):
82
+
83
+ ```sh
84
+ akm improve --limit 20
85
+ ```
86
+
87
+ The asset selection order is: assets with recent feedback signals first, then high-retrieval-count assets with no feedback, then everything else. Use `--require-feedback-signal` to restrict the pass to assets that have received explicit feedback and skip the retrieval fallback entirely.
88
+
89
+ ## Profiles
90
+
91
+ A profile controls which phases run, which LLM connections are used, whether auto-sync fires at the end of the run, and the confidence threshold for auto-accepting proposals. Built-in profiles:
92
+
93
+ | Profile | Phases | Auto-sync | Auto-push |
94
+ |---|---|---|---|
95
+ | `default` | All five | Yes | Yes |
96
+ | `thorough` | All five, larger batches | Yes | Yes |
97
+ | `quick` | Reflect only | No | No |
98
+ | `memory-focus` | Reflect + memory inference, memory and lesson types only | No | No |
99
+
100
+ Pass `--profile` to override for a single run:
101
+
102
+ ```sh
103
+ akm improve --profile quick # doclint:ignore (0.8.0-era flag spelling for this configVersion-0.8.0 post; renamed `--strategy` in 0.9.0)
104
+ akm improve --profile memory-focus # doclint:ignore (0.8.0-era flag spelling for this configVersion-0.8.0 post; renamed `--strategy` in 0.9.0)
105
+ ```
106
+
107
+ Define custom profiles in your config under `profiles.improve.<name>`. Each process entry in the profile uses a unified `{mode, profile, timeoutMs, options}` shape, so you can point reflect at a fast local model and consolidation at a more capable one:
108
+
109
+ ```jsonc
110
+ {
111
+ "configVersion": "0.8.0",
112
+ "profiles": {
113
+ "llm": {
114
+ "fast": { "endpoint": "http://localhost:1234/v1/chat/completions", "model": "qwen3.5-9b" },
115
+ "careful": { "endpoint": "http://192.168.0.99:1234/v1/chat/completions", "model": "qwen3-32b" }
116
+ },
117
+ "improve": {
118
+ "default": {
119
+ "processes": {
120
+ "reflect": { "mode": "llm", "profile": "fast" },
121
+ "consolidate": { "mode": "llm", "profile": "careful" }
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+ ```
128
+
129
+ ## The Proposal Queue
130
+
131
+ Every improvement that `akm improve` generates flows through the proposal queue before touching your stash. Nothing is written directly. The queue is the safety layer.
132
+
133
+ After a run, review what was generated:
134
+
135
+ ```sh
136
+ akm proposal list
137
+ akm proposal list --status pending
138
+ ```
139
+
140
+ Inspect a specific proposal:
141
+
142
+ ```sh
143
+ akm proposal show <id>
144
+ akm proposal diff <id> # side-by-side diff vs. the live asset
145
+ ```
146
+
147
+ Accept or reject:
148
+
149
+ ```sh
150
+ akm proposal accept <id>
151
+ akm proposal reject <id> --reason "duplicates the deployment-gotchas lesson"
152
+ ```
153
+
154
+ `akm proposal accept` runs full schema validation before writing anything to the stash. Accepted proposals are promoted as normal stash assets and become immediately searchable.
155
+
156
+ The `--auto-accept` flag enables confidence-threshold-based auto-promotion. The default safe threshold is 90 — proposals where the LLM scored its own confidence at 90 or above are promoted automatically; everything below goes to the queue for manual review:
157
+
158
+ ```sh
159
+ akm improve --auto-accept=90 # explicit threshold (same as the default) — doclint:ignore (0.8.0-only flag; 0.9.0 replaced threshold auto-accept with the proposal queue/drain engine)
160
+ akm improve --auto-accept=false # disable auto-accept, send everything to queue — doclint:ignore (0.8.0-only flag; 0.9.0 replaced threshold auto-accept with the proposal queue/drain engine)
161
+ ```
162
+
163
+ For the first few runs on a new stash, disable auto-accept and review the queue manually. Once you have a sense of what the pipeline generates, you can raise the threshold progressively.
164
+
165
+ ## Scheduling
166
+
167
+ Running `akm improve` once is useful. Running it continuously is where the compounding starts.
168
+
169
+ The pipeline is designed to run on a cron schedule. In production, every 30 minutes is a common cadence — enough time for the consolidation LLM calls to complete, short enough that memories from any given session get curated within the hour.
170
+
171
+ Define a task asset to schedule it:
172
+
173
+ ```yaml
174
+ # ~/akm/tasks/improve-loop.yml
175
+ name: improve-loop
176
+ trigger:
177
+ cron: '*/30 * * * *'
178
+ agent:
179
+ command: akm
180
+ args: ["improve", "--profile", "default", "--limit", "30"]
181
+ enabled: true
182
+ ```
183
+
184
+ Register the task:
185
+
186
+ ```sh
187
+ akm tasks sync # doclint:ignore (`tasks` was renamed to singular `task` in 0.9.0)
188
+ ```
189
+
190
+ After that, `akm improve` runs every 30 minutes without manual intervention. The `--limit 30` cap keeps each run predictably bounded. If there is nothing worth improving — no new feedback, no high-retrieval zero-feedback assets — the run completes quickly after selection with zero proposals generated.
191
+
192
+ For git-backed stashes, the `default` and `thorough` profiles auto-commit at the end of each run. The commit message template is configurable:
193
+
194
+ ```jsonc
195
+ "sync": { "message": "akm improve {scope} — {refs} refs ({date})" }
196
+ ```
197
+
198
+ Use `--no-sync` to suppress the commit for a specific run, or `--no-push` to commit locally without pushing.
199
+
200
+ ## Knowing the Loop Is Working
201
+
202
+ `akm health` gives you a structured view of recent improve activity without querying SQLite directly:
203
+
204
+ ```sh
205
+ akm health --since 24h
206
+ akm health --since 4h --format text
207
+ ```
208
+
209
+ The output covers run counts, skip reason breakdowns, consolidation outcomes, memory inference yield, and phase latencies. If a run was a dry-run, it is excluded from the health metrics automatically.
210
+
211
+ After any significant stash change, running `akm health` is the fastest way to confirm the pipeline is in a healthy state rather than silently stuck on a locked journal or a stale database entry.
212
+
213
+ ## What Changes Over Time
214
+
215
+ The value of the improve loop is not in any single run. It is in what accumulates.
216
+
217
+ After a week of 30-minute cycles on an active stash, the memory pool is smaller and more coherent. Duplicate memories from related sessions have been merged. High-signal observations have been promoted to named stash entries your agent can reference directly. The graph extraction index has been built up incrementally so `akm graph entity <name>` returns useful results instead of nothing.
218
+
219
+ After a month, the stash reflects your actual working patterns rather than the raw notes from when you first captured something. Assets that were retrieved frequently and rated poorly have been flagged and improved. Assets that were never retrieved have surfaced as candidates for deletion or consolidation. The memory you have is accurate to what you know now, not what you wrote six months ago.
220
+
221
+ That is the loop. It runs while you work. It runs while you sleep. Each pass leaves the stash slightly more accurate, slightly more consolidated, slightly more useful. The proposals it generates are the visible surface — the queue where you can see what the pipeline decided and override it. The underlying stash quality improvement is what compounds.
222
+
223
+ ---
224
+
225
+ `akm improve` is part of akm 0.8.x. The full pipeline configuration reference is at [configuration reference](../reference/configuration.md). Profile options, LLM connection setup, and scheduling details are in the [improvement loop architecture doc](../architecture/improvement.md). For a concrete look at 24 hours of autonomous operation — hardware benchmarks, the two reliability fixes that make continuous runs viable, and the Discord health report setup — see [Your Agent Has a Memory That Runs While You Sleep](https://dev.to/itlackey/your-agent-has-a-memory-that-runs-while-you-sleep-20oh). The repo is at [github.com/itlackey/akm](https://github.com/itlackey/akm).
@@ -0,0 +1,179 @@
1
+ ---
2
+ title: 'Your Agent Has a Memory That Runs While You Sleep'
3
+ cover_image: 'https://raw.githubusercontent.com/itlackey/akm/main/docs/posts/akm-logo-sized.webp'
4
+ series: akm-knowledge
5
+ description: 'akm improve runs continuously on consumer GPUs with local models, curating your agent knowledge base in the background. Here is what 24 hours of autonomous operation looks like, what hardware it takes, and what we fixed to make it reliable.'
6
+ tags:
7
+ - ai
8
+ - agents
9
+ - cli
10
+ - local-ai
11
+ published: true
12
+ id: 3814547
13
+ date: '2026-06-04T00:32:02Z'
14
+ ---
15
+
16
+ > This is a dated article from AKM's publishing archive. For current product behavior, see the
17
+ > [documentation index](https://github.com/itlackey/akm/blob/main/docs/README.md).
18
+
19
+ This post is part of the akm-knowledge series. [Part ten](https://dev.to/itlackey/the-improvement-loop-how-akm-keeps-your-agent-sharp-2d4d) introduced the improve pipeline — what each phase does and how to schedule it. This post goes deeper on what continuous operation looks like in practice: the hardware numbers, the reliability bugs we hit at 48 runs per day, and the observability layer we built to keep watch.
20
+
21
+ Most people think of AI agent memory as something that happens during a session. You talk to your agent, it learns things, maybe you save a few notes, the session ends. The next session starts cold.
22
+
23
+ `akm improve` is built around a different model: a continuous background process that runs on your own hardware, against local models, and quietly curates your agent's knowledge base while you work on other things. No cloud API required. No per-token billing for the maintenance pass. A GPU you already own, a model you already have downloaded, running on a schedule.
24
+
25
+ This post covers what 24 hours of autonomous operation actually looks like, how consumer-grade GPUs handle the load, the reliability work that makes continuous operation viable, and the observability layer that lets you know it's working without watching logs.
26
+
27
+ ## What akm improve Does in 24 Hours
28
+
29
+ `akm improve` is a multi-phase pipeline. The core pass — consolidation — loads your memory pool, groups related memories into chunks, sends each chunk to a local LLM for a consolidation plan (merge similar memories, promote high-signal ones to your stash, delete redundant ones, surface contradictions), and then executes those plans. After consolidation, memory inference runs a lightweight factual extraction pass, and graph extraction updates the entity-relation index.
30
+
31
+ The pipeline is scheduled to run automatically. Here is what one 24-hour window produced:
32
+
33
+ | Metric | Value |
34
+ |--------|-------|
35
+ | Runs completed | **48 / 48** — zero failures |
36
+ | Memories processed | **14,189** |
37
+ | Promoted to stash | **1,361** |
38
+ | Merged (deduplication) | **49** (64 secondaries absorbed) |
39
+ | Contradictions surfaced | **211** |
40
+ | Deleted (redundant) | **31** |
41
+ | Memory inference yield | **69.3%** — 115 new atomic facts written |
42
+ | Graph entities extracted | **181** across 9 files |
43
+ | Task fail rate | **0%** |
44
+ | Index entries | **7,398** — all embedded, status `ready-vec` |
45
+
46
+ Every run that completes leaves your stash in better shape than before it started. Memories that accumulated across dozens of agent sessions get compressed, merged, and organized without manual intervention. The 1,361 promotions in this window represent memories that were considered significant enough by the local LLM to persist as named stash entries. The 49 merges collapsed near-duplicate content. The 211 contradictions were flagged for review rather than silently overwritten.
47
+
48
+ This is the loop. It runs every 30 minutes. You don't have to think about it.
49
+
50
+ ## Running It on Consumer Hardware
51
+
52
+ The consolidation LLM in this setup is `qwen3.5-9b` (or similar) running locally via LM Studio on an OpenAI-compatible endpoint. The model fits comfortably on most modern gaming GPUs. No API key. No per-call cost. The inference happens on hardware sitting on your desk.
53
+
54
+ We run two LM Studio servers — both serving the same model via OpenAI-compatible endpoints — and benchmarked them head to head.
55
+
56
+ **Shredder** is a desktop with an RTX 5090. **Splinter** runs an RTX 4060 Ti, a card that launched at $299 and is common in mid-range gaming builds. Same model weights. Same chunk sizes. Different VRAM bandwidth and tensor core counts.
57
+
58
+ | | RTX 5090 (Shredder) | RTX 4060 Ti (Splinter) |
59
+ |--|---------------------|------------------------|
60
+ | **Per-chunk latency** | ~6.8s | ~22.6s |
61
+ | **13-chunk consolidation** | ~87s (~1.5 min) | ~290s (~4.8 min) |
62
+ | **Speed ratio** | 1× (baseline) | 3.3× slower |
63
+ | **Runs per hour (fits schedule)** | ✅ yes | ✅ yes |
64
+ | **Approximate street price** | ~$2,000 | ~$300 |
65
+
66
+ The 5090 is faster, but the 4060 Ti finishes a full consolidation pass in under 5 minutes — well inside the 30-minute run window. Both cards sustain 48 runs per day without missing a cycle.
67
+
68
+ Where the gap shows up is in the tail. Because the 24h window included runs on both backends, the aggregate latency numbers reflect both:
69
+
70
+ | Phase | Median | P95 | What drives the P95 |
71
+ |-------|--------|-----|---------------------|
72
+ | Total (end-to-end) | **7.2 min** | 23.4 min | Splinter-routed consolidation runs |
73
+ | Consolidation | **1.4 min** | 5.8 min | Chunk count variance + Splinter |
74
+ | Memory inference | **5.9s** | 25.3s | Fresh (non-cached) inference attempts |
75
+ | Graph extraction | **< 1s** | 53s | Cache misses on modified files |
76
+
77
+ The median of 7.2 minutes reflects the majority of runs going to Shredder. The P95 of 23.4 minutes is almost entirely Splinter runs with larger chunk windows. A setup running exclusively on a 4060 Ti would see a flatter distribution — median around 10–12 minutes, P95 around 18–20 minutes — with no 5090 runs pulling the median down.
78
+
79
+ For most setups, a single mid-range GPU is the right starting point. The consolidation pass is CPU-light and network-light — the bottleneck is token generation throughput on the GPU. If you have a second machine with a GPU and spare VRAM, you can point a second LM Studio server at it and split load exactly as we did here.
80
+
81
+ The embeddings server is separate — `nomic-embed-text-v1.5` running on localhost — and handles the semantic search index. It stays warm between runs, so re-embedding after promotions adds negligible latency. Any GPU with 4GB+ of VRAM can host it alongside the consolidation model if you have the headroom, or it runs on CPU at acceptable speed for indexing workloads.
82
+
83
+ ## What "Local Models" Actually Means for Quality
84
+
85
+ The concern with local models is usually quality: will a 9B parameter model running on a gaming GPU produce consolidation plans good enough to trust with your knowledge base?
86
+
87
+ The answer, based on 48 runs and 14,189 memories, is yes — with the right constraints.
88
+
89
+ The consolidation prompt is designed to be conservative. The LLM is asked to identify candidates for merge, promote, or delete within a bounded chunk of related memories. It is not given unbounded latitude. Plans are validated against the loaded memory pool before execution — if the model invents a ref that doesn't exist, the op is dropped with a warning. If a promoted memory fails schema validation, it is rejected.
90
+
91
+ The 69.3% yield rate on memory inference tells the same story. Out of 166 fresh attempts at factual extraction, 115 produced usable atomic facts. The model is making useful inferences at a rate that justifies running it continuously.
92
+
93
+ The practical limit of local 9B models shows up in graph extraction: 2 truncations in the 24h window indicate chunks that exceeded the model's context window. These produce partial rather than failed extractions — the model handles what it can see. Larger models extend this ceiling; a 5090 can hold larger quantizations in VRAM.
94
+
95
+ ## Making Continuous Operation Reliable
96
+
97
+ Running 48 times a day means reliability issues that would be minor in a manual workflow become systemic. Two bugs were affecting the consolidation pass and wasting inference on every affected run.
98
+
99
+ **The stale database problem.** After a run that deleted files, the database retained entries pointing to files that no longer existed on disk. The next run loaded those ghost entries, the LLM generated merge plans against them, and Phase B failed silently when the file wasn't found. Every affected secondary in those plans was charged a wasted inference call.
100
+
101
+ The fix is a pre-flight filter that runs before the LLM sees anything:
102
+
103
+ ```typescript
104
+ memories = memories.filter((m) => fs.existsSync(m.filePath));
105
+ ```
106
+
107
+ Stale entries never reach the model. A warning is logged so the count is visible in health output if the filter ever catches something:
108
+
109
+ ```
110
+ Pre-flight: filtered 3 stale DB entries (file absent on disk) from memory pool before chunking.
111
+ ```
112
+
113
+ **The hallucination problem.** On certain chunk compositions — particularly when session checkpoint memories and named sessions appear in the same window — the local model would blend naming conventions and produce a merge plan with a primary ref that didn't exist in the pool.
114
+
115
+ A typical example: `memory:opencode-session-20260529-a1b2` and `memory:checkpoint-20260529T214550` in the same chunk produce a hallucinated primary of `memory:opencode-session-20260529T214550-ses_18a4`. The plan looks reasonable at the chunk level. The ref doesn't exist at the pool level.
116
+
117
+ Before the fix, that hallucinated primary would reach Phase B and charge every real secondary (typically 4–8 refs) with a failed merge skip. After the fix, `mergePlans()` validates every primary ref against the loaded pool before execution:
118
+
119
+ ```typescript
120
+ const knownRefs = new Set(memories.map((m) => `memory:${m.name}`));
121
+ const { ops: allOps, warnings: mergeWarnings } = mergePlans(chunkOpsArrays, knownRefs);
122
+ ```
123
+
124
+ Real merge plans proceed. Hallucinated roots are dropped. The warning is distinguishable from the stale-DB warning, so health metrics can tell the two apart:
125
+
126
+ ```
127
+ mergePlans: primary memory:... not in loaded memory pool (LLM hallucination) — dropping op before execution.
128
+ ```
129
+
130
+ Both fixes eliminate wasted inference. On the 4060 Ti at 22.6s per chunk, a single hallucinated primary that would have charged 6 secondaries saves over 2 minutes of inference time per occurrence — time that can go toward real consolidation work instead.
131
+
132
+ ## Knowing It's Working
133
+
134
+ Running autonomously in the background only helps if you know when something goes wrong. `akm health` provides a structured view of recent improve activity:
135
+
136
+ ```sh
137
+ akm health --since 4h
138
+ akm health --since 24h --format text
139
+ ```
140
+
141
+ It surfaces run counts, skip reason breakdowns, consolidation outcomes, memory inference yield, and phase latencies in a single command. The same JSON output feeds automation.
142
+
143
+ For continuous monitoring, we built a cron task that posts a rolling 4-hour health report to Discord every hour:
144
+
145
+ ```yaml
146
+ # ~/akm/tasks/akm-health-report.yml
147
+ schedule: 0 * * * *
148
+ command: akm env run fwdslsh -- bash ~/akm/scripts/akm-health-discord.sh
149
+ enabled: true
150
+ ```
151
+
152
+ The script calls `akm health --since 4h` and `--since 8h`, computes deltas for trend context, and posts a Discord embed:
153
+
154
+ ```sh
155
+ akm tasks sync # register the cron; doclint:ignore (`tasks` was renamed to singular `task` in 0.9.0)
156
+ ```
157
+
158
+ The embed has three inline fields — Output (promoted, merged, MI yield), Failures (chunk failures, skip reason anomalies), and Latency (median, P95, previous-window comparison) — plus a Needs Attention section that only appears when something is actually off. The footer includes the hostname and timestamp so reports from multiple machines are distinguishable at a glance.
159
+
160
+ The result: a health check fires every 30 minutes from the pipeline, and a visibility report fires every hour to Discord. You see degradation before it accumulates.
161
+
162
+ ## The Full Picture
163
+
164
+ Here is what autonomous local-model memory curation looks like across a full day:
165
+
166
+ - **48 runs** completed without intervention
167
+ - **14,189 memories** reviewed, organized, and curated
168
+ - **1,361** promoted to the permanent stash
169
+ - **1.4 minute median** per consolidation pass on the faster GPU; under 5 minutes on the 4060 Ti
170
+ - **Zero API calls** — all inference runs locally on hardware you own
171
+ - **Hourly Discord reports** — no manual health checks needed
172
+
173
+ The hardware requirement to run this continuously is a mid-range gaming GPU. The model requirement is a 7–9B parameter instruction-tuned model quantized to 4–8 bits. Both are things a lot of developers already have.
174
+
175
+ The value is in what compounds. Each run makes the stash slightly more accurate, slightly more consolidated, slightly more consistent. After 48 runs, 14,000 memories have been through a curation pass that would have taken hours to do manually. After a week, the stash is a different kind of asset — not a pile of notes, but a continuously maintained knowledge base that your agent can rely on across sessions.
176
+
177
+ ---
178
+
179
+ `akm improve` is part of akm 0.8.x. The full pipeline configuration and local model setup docs are in the [configuration reference](../reference/configuration.md). Hardware requirements and LM Studio setup are covered in the [getting started guide](../guides/getting-started.md).