akm-cli 0.9.31 → 0.10.261001-beta
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.
- package/CHANGELOG.md +409 -0
- package/STABILITY.md +99 -57
- package/dist/api-node.mjs +20 -0
- package/dist/api.d.ts +23 -0
- package/dist/api.js +45 -0
- package/dist/assets/hints/cli-hints-full.md +15 -29
- package/dist/assets/hints/cli-hints-short.md +2 -2
- package/dist/assets/improve-strategies/default.json +3 -3
- package/dist/assets/prompts/consolidate-pair.md +9 -7
- package/dist/assets/stash-skeleton/README.md +1 -1
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
- package/dist/cli/shared.js +31 -48
- package/dist/cli/unknown-flags.js +6 -43
- package/dist/cli.js +8 -34
- package/dist/commands/agent/contribute-cli.js +1 -1
- package/dist/commands/completions.js +1 -2
- package/dist/commands/config-cli.js +5 -28
- package/dist/commands/env/env-cli.js +5 -5
- package/dist/commands/env/secret-cli.js +2 -2
- package/dist/commands/feedback-cli.js +75 -49
- package/dist/commands/health/checks.js +41 -16
- package/dist/commands/health/plugin-staleness.js +52 -22
- package/dist/commands/improve/autonomy-gate.js +5 -3
- package/dist/commands/improve/consolidate/chunking.js +3 -10
- package/dist/commands/improve/consolidate/continuity-check.js +4 -4
- package/dist/commands/improve/consolidate/pair-pass.js +29 -10
- package/dist/commands/improve/consolidate.js +10 -65
- package/dist/commands/improve/distill/lesson-update.js +91 -0
- package/dist/commands/improve/distill-guards.js +1 -43
- package/dist/commands/improve/distill.js +148 -21
- package/dist/commands/improve/eligibility.js +14 -1
- package/dist/commands/improve/extract-cli.js +1 -1
- package/dist/commands/improve/extract-prompt.js +17 -7
- package/dist/commands/improve/extract.js +5 -7
- package/dist/commands/improve/improve-cli.js +92 -106
- package/dist/commands/improve/improve-strategies.js +8 -12
- package/dist/commands/improve/improve.js +134 -52
- package/dist/commands/improve/loop-stages.js +18 -5
- package/dist/commands/improve/planner.js +0 -1
- package/dist/commands/improve/preparation.js +40 -99
- package/dist/commands/improve/proactive-maintenance.js +2 -2
- package/dist/commands/improve/reflect-noise.js +3 -55
- package/dist/commands/improve/reflect.js +29 -34
- package/dist/commands/improve/retrieval-queries.js +37 -0
- package/dist/commands/improve/retrieval-scope.js +2 -2
- package/dist/commands/improve/salience.js +2 -9
- package/dist/commands/improve/session-asset.js +4 -1
- package/dist/commands/improve/stage.js +23 -12
- package/dist/commands/lint/index.js +5 -20
- package/dist/commands/observability-cli.js +3 -9
- package/dist/commands/proposal/drain.js +43 -6
- package/dist/commands/proposal/proposal-cli.js +11 -31
- package/dist/commands/proposal/repository.js +20 -14
- package/dist/commands/proposal/validators/proposal-quality-validators.js +0 -3
- package/dist/commands/read/knowledge.js +3 -3
- package/dist/commands/read/remember-cli.js +0 -13
- package/dist/commands/read/search-cli.js +29 -97
- package/dist/commands/read/search.js +0 -11
- package/dist/commands/read/show.js +0 -19
- package/dist/commands/sources/plugin-upgrade.js +164 -101
- package/dist/commands/sources/sources-cli.js +1 -15
- package/dist/commands/sources/stash-cli.js +6 -14
- package/dist/commands/tasks/tasks-cli.js +4 -115
- package/dist/commands/workflow/plan.js +11 -33
- package/dist/commands/workflow-cli.js +2 -7
- package/dist/core/adapter/adapter-ids.js +1 -2
- package/dist/core/adapter/adapters/agent-skills-adapter.js +0 -4
- package/dist/core/adapter/adapters/akm-adapter.js +9 -48
- package/dist/core/adapter/adapters/akm-lint.js +10 -26
- package/dist/core/adapter/adapters/akm-metadata.js +2 -72
- package/dist/core/adapter/adapters/akm-task-adapter.js +0 -5
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +9 -28
- package/dist/core/adapter/adapters/dotenv-adapter.js +1 -20
- package/dist/core/adapter/adapters/generic-files-adapter.js +0 -10
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +0 -4
- package/dist/core/adapter/adapters/tool-dir-shared.js +0 -24
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -4
- package/dist/core/adapter/recognize-match.js +3 -4
- package/dist/core/common.js +18 -2
- package/dist/core/config/config-schema.js +12 -15
- package/dist/core/config/config-types.js +6 -15
- package/dist/core/config/config-walker.js +6 -23
- package/dist/core/config/config.js +17 -80
- package/dist/core/config/engine-semantics.js +7 -3
- package/dist/core/config/schema/engines.js +7 -7
- package/dist/core/config/schema/improve-processes.js +10 -63
- package/dist/core/config/schema/improve.js +2 -21
- package/dist/core/config/schema/index-config.js +6 -39
- package/dist/core/env-secret-ref.js +2 -45
- package/dist/core/errors.js +1 -2
- package/dist/core/extra-params.js +2 -86
- package/dist/core/file-lock.js +2 -6
- package/dist/core/improve-result.js +13 -1
- package/dist/core/mutation-target.js +2 -2
- package/dist/core/paths.js +4 -0
- package/dist/core/recognition-util.js +4 -5
- package/dist/core/run-lock.js +1 -1
- package/dist/core/subprocess.js +49 -0
- package/dist/core/warn.js +21 -4
- package/dist/core/write-source.js +3 -3
- package/dist/execution/target-ref.js +1 -2
- package/dist/indexer/indexer.js +15 -6
- package/dist/indexer/passes/memory-inference.js +15 -6
- package/dist/indexer/search/db-search.js +49 -36
- package/dist/indexer/search/fts-query.js +0 -19
- package/dist/indexer/search/ranking.js +29 -1
- package/dist/indexer/usage/usage-events.js +21 -16
- package/dist/integrations/agent/engine-resolution.js +5 -2
- package/dist/integrations/agent/index.js +1 -1
- package/dist/integrations/agent/profiles.js +41 -98
- package/dist/integrations/agent/request-lowering.js +3 -3
- package/dist/integrations/harnesses/aider/index.js +5 -0
- package/dist/integrations/harnesses/amazonq/index.js +1 -0
- package/dist/integrations/harnesses/claude/config-import.js +2 -3
- package/dist/integrations/harnesses/claude/index.js +5 -0
- package/dist/integrations/harnesses/codex/index.js +1 -0
- package/dist/integrations/harnesses/copilot/index.js +1 -0
- package/dist/integrations/harnesses/gemini/index.js +1 -0
- package/dist/integrations/harnesses/index.js +18 -39
- package/dist/integrations/harnesses/opencode/agent-builder.js +60 -35
- package/dist/integrations/harnesses/opencode/config-import.js +121 -52
- package/dist/integrations/harnesses/opencode/index.js +22 -0
- package/dist/integrations/harnesses/opencode/plugin-layout.js +68 -0
- package/dist/integrations/harnesses/opencode/session-log-types.js +12 -0
- package/dist/integrations/harnesses/opencode/session-log-v1.js +72 -0
- package/dist/integrations/harnesses/opencode/session-log-v2.js +140 -0
- package/dist/integrations/harnesses/opencode/session-log.js +104 -115
- package/dist/integrations/harnesses/opencode/version.js +98 -0
- package/dist/integrations/harnesses/opencode-sdk/{harness.js → index.js} +5 -17
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +105 -206
- package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +199 -0
- package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +254 -0
- package/dist/integrations/harnesses/opencode-sdk/wire.js +66 -0
- package/dist/integrations/harnesses/openhands/index.js +1 -0
- package/dist/integrations/harnesses/pi/index.js +1 -0
- package/dist/integrations/harnesses/shared.js +2 -0
- package/dist/integrations/harnesses/types.js +2 -0
- package/dist/llm/client.js +41 -11
- package/dist/output/cli-hints.js +1 -1
- package/dist/output/context.js +10 -19
- package/dist/output/format-exempt.js +5 -8
- package/dist/output/shapes/helpers.js +1 -22
- package/dist/output/shapes/passthrough.js +0 -1
- package/dist/output/shapes.js +3 -31
- package/dist/output/stdout.js +5 -1
- package/dist/output/text/command-format.js +6 -1
- package/dist/output/text/workflow-format.js +4 -22
- package/dist/scripts/akm-migrate-node.js +15745 -16711
- package/dist/scripts/akm-migrate.js +16318 -17280
- package/dist/setup/detect.js +10 -4
- package/dist/setup/harness-config-import.js +5 -14
- package/dist/setup/setup.js +1 -1
- package/dist/setup/steps/tasks.js +12 -13
- package/dist/sources/providers/git-stash.js +94 -13
- package/dist/storage/repositories/index-utility-repository.js +2 -32
- package/dist/storage/repositories/index-vec-repository.js +4 -0
- package/dist/storage/repositories/task-history-repository.js +0 -5
- package/dist/storage/repositories/workflow-runs-repository.js +5 -15
- package/dist/tasks/embedded.js +2 -1
- package/dist/tasks/run/run-command-task.js +9 -1
- package/dist/tasks/run/run-workflow-task.js +4 -3
- package/dist/tasks/run/task-history.js +0 -2
- package/dist/tasks/run/task-log.js +38 -1
- package/dist/tasks/schedule-gates.js +39 -0
- package/dist/tasks/scheduler-binding.js +0 -16
- package/dist/tasks/scheduler-sync.js +3 -97
- package/dist/tasks/source/bounded-document.js +1 -1
- package/dist/tasks/source/task-source-v4.js +2 -12
- package/dist/tasks/task-run-reserved-flags.js +2 -31
- package/dist/workflows/authoring/authoring.js +6 -6
- package/dist/workflows/compile.js +8 -65
- package/dist/workflows/exec/child-workflow.js +22 -3
- package/dist/workflows/exec/native-executor.js +12 -147
- package/dist/workflows/exec/run-workflow.js +31 -103
- package/dist/workflows/exec/step-work.js +9 -178
- package/dist/workflows/exec/unit-dispatch.js +0 -10
- package/dist/workflows/freeze/environment.js +3 -44
- package/dist/workflows/freeze/freeze.js +8 -41
- package/dist/workflows/freeze/targets/child-workflow.js +27 -63
- package/dist/workflows/freeze/targets/command.js +2 -16
- package/dist/workflows/freeze/targets/shell.js +0 -2
- package/dist/workflows/freeze/task-bindings.js +2 -28
- package/dist/workflows/ir/params.js +12 -2
- package/dist/workflows/parser.js +82 -232
- package/dist/workflows/plan.js +1 -1
- package/dist/workflows/renderer.js +10 -19
- package/dist/workflows/runtime/run-plan.js +11 -53
- package/dist/workflows/runtime/runs.js +4 -27
- package/dist/workflows/source-files.js +12 -16
- package/dist/workflows/source-semantics.js +1 -93
- package/docs/README.md +1 -1
- package/docs/agents/README.md +3 -3
- package/docs/agents/agent-install.md +1 -1
- package/docs/architecture/0.10-process-rules.md +827 -0
- package/docs/architecture/adapters.md +17 -31
- package/docs/architecture/architecture.md +4 -5
- package/docs/architecture/improvement.md +115 -76
- package/docs/architecture/internals/improve-workflow.md +22 -16
- package/docs/architecture/internals/indexing.md +1 -1
- package/docs/architecture/internals/search.md +1 -2
- package/docs/architecture/internals/storage-locations.md +6 -6
- package/docs/architecture/persisted-data-compat.md +13 -4
- package/docs/architecture/specs/0.9.0-decisions.md +6 -2
- package/docs/architecture/specs/improve-collapse-churn-detector-design.md +2 -2
- package/docs/architecture/specs/workflow-format-unification.md +1 -6
- package/docs/architecture/testing/manual-testing-checklist.md +21 -30
- package/docs/architecture/testing/task-workflow-manual-tests.md +106 -203
- package/docs/architecture/testing/testing-workflow.md +1 -1
- package/docs/architecture/workflow-engine.md +5 -56
- package/docs/guides/author-workflows.md +39 -69
- package/docs/guides/bundles.md +3 -1
- package/docs/guides/capture-knowledge.md +1 -1
- package/docs/guides/claude-code-vs-akm-workflows.md +1 -2
- package/docs/guides/discover-and-load.md +4 -4
- package/docs/guides/getting-started.md +1 -1
- package/docs/guides/improve-the-library.md +10 -9
- package/docs/guides/recipes/headless-install.md +2 -2
- package/docs/guides/run-workflows.md +1 -1
- package/docs/guides/scheduling.md +9 -1
- package/docs/guides/use-with-any-agent.md +49 -4
- package/docs/integration/bundling-akm.md +7 -6
- package/docs/maintainers/curate-workmap.md +1 -2
- package/docs/maintainers/release-checklist.md +33 -1
- package/docs/migration/README.md +2 -0
- package/docs/migration/release-notes/0.10.0.md +201 -0
- package/docs/migration/release-notes/README.md +1 -0
- package/docs/migration/v0.9-to-v0.10.md +507 -0
- package/docs/posts/akm-command-tour.md +3 -3
- package/docs/product-surface.md +1 -1
- package/docs/reference/README.md +1 -0
- package/docs/reference/api.md +65 -0
- package/docs/reference/asset-types.md +3 -5
- package/docs/reference/bundle-types.md +2 -4
- package/docs/reference/cli.md +160 -188
- package/docs/reference/configuration.md +101 -20
- package/docs/reference/data-and-telemetry.md +2 -2
- package/docs/reference/env-and-secrets.md +2 -2
- package/docs/reference/supported-formats.md +3 -4
- package/docs/reference/tasks.md +12 -19
- package/docs/reference/website-sources.md +1 -1
- package/docs/reference/workflow-schema.md +89 -317
- package/docs/reference/workflows.md +20 -48
- package/package.json +12 -2
- package/schemas/akm-config.json +2 -243
- package/schemas/akm-task.json +2 -3
- package/schemas/akm-workflow.json +47 -84
- package/dist/assets/improve-strategies/catchup.json +0 -41
- package/dist/assets/improve-strategies/proactive-maintenance.json +0 -24
- package/dist/assets/improve-strategies/quick.json +0 -17
- package/dist/assets/improve-strategies/reflect-distill.json +0 -29
- package/dist/assets/improve-strategies/thorough.json +0 -49
- package/dist/assets/prompts/retrieval-relevance-judge.md +0 -6
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +0 -6
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +0 -4
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +0 -4
- package/dist/cli/retired-commands.js +0 -118
- package/dist/commands/improve/retrieval-gate.js +0 -132
- package/dist/commands/tasks/validate.js +0 -176
- package/dist/core/config/legacy-source-shape-shim.js +0 -117
- package/dist/indexer/feedback/utility-policy.js +0 -75
- package/dist/integrations/harnesses/ids.js +0 -28
- package/dist/tasks/source/task-source-v3-frozen.js +0 -424
- package/dist/tasks/source/task-to-v4.js +0 -863
- package/dist/workflows/exec/worktree.js +0 -372
- package/dist/workflows/freeze/child-output-references.js +0 -83
- package/dist/workflows/freeze/identity.js +0 -22
- package/dist/workflows/freeze/targets/script.js +0 -50
- package/dist/workflows/freeze/targets/task.js +0 -124
- package/dist/workflows/github-yaml.js +0 -506
- package/dist/workflows/runtime/run-outputs.js +0 -80
|
@@ -101,23 +101,21 @@ interface BundleAdapter {
|
|
|
101
101
|
// reading authored bytes or walking the bundle.
|
|
102
102
|
readCandidates?(c: BundleComponent, conceptId: string): Array<{ path: string; conceptId: string }>;
|
|
103
103
|
|
|
104
|
-
// OPTIONAL —
|
|
105
|
-
placeNew?(c: BundleComponent, conceptId: string): string; // where a new item would live
|
|
104
|
+
// OPTIONAL — discovery.
|
|
106
105
|
directoryList?(c: BundleComponent): string[]; // owned dirs; feeds git exact-path staging
|
|
107
106
|
looksLikeRoot?(root: string): boolean; // install-time probe
|
|
108
107
|
}
|
|
109
108
|
```
|
|
110
109
|
|
|
111
110
|
`recognize` and `validate` are required on every adapter; `index`,
|
|
112
|
-
`affectedItems`, `readCandidates`, `
|
|
111
|
+
`affectedItems`, `readCandidates`, `directoryList`, and
|
|
113
112
|
`looksLikeRoot` are optional capability methods. An adapter overriding `index()` must keep
|
|
114
113
|
`recognize()` coherent with it (conformance: `index()` == fold of
|
|
115
114
|
`recognize()` over the core walk) or declare component-level
|
|
116
115
|
incrementality.
|
|
117
116
|
|
|
118
|
-
`readCandidates` is intentionally distinct from
|
|
119
|
-
|
|
120
|
-
write-normalization policy. Read candidates preserve canonical directory
|
|
117
|
+
`readCandidates` is intentionally distinct from `extensions`: extensions are
|
|
118
|
+
non-exhaustive walk hints. Read candidates preserve canonical directory
|
|
121
119
|
manifests (for example `skills/<name>/SKILL.md`) so lookup, index-backed show, and workflow runtime share one
|
|
122
120
|
physical-owner decision. Each candidate carries its canonical concept identity,
|
|
123
121
|
so a byte-denying ownership probe never has to infer identity from the query.
|
|
@@ -145,30 +143,21 @@ concern.
|
|
|
145
143
|
|
|
146
144
|
---
|
|
147
145
|
|
|
148
|
-
##
|
|
146
|
+
## Placement
|
|
149
147
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
`
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
Placement for every existing bundle is already correct today — this is a
|
|
159
|
-
deliberately sequenced routing change, not unfinished behavior. It's
|
|
160
|
-
scoped out of 0.9.0 by
|
|
161
|
-
[D12](../architecture/specs/0.9.0-decisions.md#d12--bundleadapterplacenew-stays-unwired-until-010)
|
|
162
|
-
and deferred to 0.10; nothing user-visible changes in 0.10 for this alone.
|
|
163
|
-
See [STABILITY.md](../../STABILITY.md) ("On the horizon") for the
|
|
164
|
-
up-to-date status if this changes.
|
|
148
|
+
Adapters do not place new items. AKM-native writes resolve through AKM's own
|
|
149
|
+
flat type→directory placement table (`src/core/asset/asset-placement.ts`'s
|
|
150
|
+
`PLACEMENT_SPECS`), which is correct for akm-layout bundles — the only bundles
|
|
151
|
+
the write commands touch in practice. A per-adapter `placeNew()` existed
|
|
152
|
+
through 0.9 but nothing called it, and it was removed in 0.10. Supporting
|
|
153
|
+
writable bundles in another layout would need it back: see
|
|
154
|
+
[#1163](https://github.com/itlackey/akm/issues/1163).
|
|
165
155
|
|
|
166
156
|
---
|
|
167
157
|
|
|
168
158
|
## Write allowlists
|
|
169
159
|
|
|
170
|
-
|
|
171
|
-
write commands are allowed to touch at all** — that's decided today by a
|
|
160
|
+
Which bundles AKM-native write commands are allowed to touch at all is decided by a
|
|
172
161
|
small allowlist check, `assertAkmAssetWrite` (`src/core/write-source.ts`),
|
|
173
162
|
run before any write command touches the filesystem. It compares the target
|
|
174
163
|
bundle's detected (or configured) adapter id against an allowlist and throws
|
|
@@ -181,12 +170,10 @@ The default allowlist is `["akm"]`. Two command families widen it explicitly:
|
|
|
181
170
|
| `akm env create` / `env remove` / `secret set` | `dotenv` |
|
|
182
171
|
| `akm workflow create` | `akm-workflow` |
|
|
183
172
|
|
|
184
|
-
Every other adapter
|
|
185
|
-
`
|
|
186
|
-
`generic-files`) — is rejected by every AKM-native write command in 0.9.0.
|
|
173
|
+
Every other adapter (`agent-skills`, `claude`, `opencode`, `akm-task`,
|
|
174
|
+
`generic-files`, and so on) is rejected by every AKM-native write command.
|
|
187
175
|
`akm task add` in particular uses the *default* allowlist (`akm` only), so a
|
|
188
|
-
standalone `akm-task` bundle is read-only through AKM-native write commands
|
|
189
|
-
even though `akm-task`'s own `placeNew()` is implemented.
|
|
176
|
+
standalone `akm-task` bundle is read-only through AKM-native write commands.
|
|
190
177
|
|
|
191
178
|
Reading, searching, and `akm lint` are unaffected by this allowlist — only
|
|
192
179
|
creating, editing, or deleting through AKM's own commands is restricted.
|
|
@@ -197,8 +184,7 @@ This allowlist boundary is also where AKM's [execution
|
|
|
197
184
|
boundary](../guides/concepts.md) principle shows up on the write side: AKM
|
|
198
185
|
retrieves and validates every supported format, but it only lets its own
|
|
199
186
|
write commands mutate a narrow, explicitly-declared set of targets — it
|
|
200
|
-
does not widen write access to a format just because
|
|
201
|
-
happens to expose a `placeNew()` implementation.
|
|
187
|
+
does not widen write access to a format just because it can read it.
|
|
202
188
|
|
|
203
189
|
---
|
|
204
190
|
|
|
@@ -260,8 +260,7 @@ schema (`src/core/config/schema/sources-bundles.ts`).
|
|
|
260
260
|
refresh.
|
|
261
261
|
|
|
262
262
|
Write-target resolution (`resolveWriteTarget`) follows: an explicit
|
|
263
|
-
destination flag (`--bundle`
|
|
264
|
-
`import`/env/secret mutations) -> `config.defaultWriteTarget` -> working
|
|
263
|
+
destination flag (`--bundle`) -> `config.defaultWriteTarget` -> working
|
|
265
264
|
bundle (`defaultBundle`) -> `ConfigError`. The resolved target keeps the
|
|
266
265
|
optional configured selector separate from the stable `source.name`: APIs
|
|
267
266
|
that must re-resolve a destination use the selector, while durable refs and
|
|
@@ -299,8 +298,8 @@ whose proposal queue is read or adjudicated; it does not override the proposal's
|
|
|
299
298
|
write destination. Qualified proposals and unqualified proposals created in a
|
|
300
299
|
configured secondary queue record the destination source name and materialized
|
|
301
300
|
root. Diff, accept, and revert use that binding by default and reject an explicit
|
|
302
|
-
`--
|
|
303
|
-
an explicit `--
|
|
301
|
+
`--bundle` that resolves elsewhere. An unbound short proposal requires either
|
|
302
|
+
an explicit `--bundle` or an authenticated `--queue` context; it does not
|
|
304
303
|
inherit a default write target.
|
|
305
304
|
|
|
306
305
|
---
|
|
@@ -442,7 +441,7 @@ An explicit missing or incompatible engine is an error and never falls
|
|
|
442
441
|
through to another configured engine.
|
|
443
442
|
|
|
444
443
|
Task-v3 execution and durable workflow-v4 dispatch use this runtime boundary.
|
|
445
|
-
Markdown
|
|
444
|
+
Markdown workflows compile through source IR v1; new starts freeze
|
|
446
445
|
v4-family `irVersion: 5`. A stored plan that decodes runs whatever release
|
|
447
446
|
froze it; one that does not is marked abandoned and `akm workflow run <ref>`
|
|
448
447
|
starts afresh. Only a plan a newer akm froze is refused, naming the upgrade.
|
|
@@ -32,15 +32,16 @@ everything else routes through `akm proposal accept`.
|
|
|
32
32
|
|
|
33
33
|
## Components
|
|
34
34
|
|
|
35
|
-
- **Utility
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
- **Utility recompute** (`recomputeUtilityScores`, `src/indexer/indexer.ts`) —
|
|
36
|
+
the one place utility is computed from `usage_events`; `akm index` runs it
|
|
37
|
+
for every entry and `akm feedback` for the entry it touched.
|
|
38
38
|
- **Strategies** (`src/commands/improve/improve-strategies.ts`,
|
|
39
39
|
`src/assets/improve-strategies/*.json`) — named presets that decide which
|
|
40
40
|
improve processes run and with what engine/model/limits.
|
|
41
41
|
- **Autonomy gate** (`src/commands/improve/autonomy-gate.ts`) — downgrades
|
|
42
|
-
the handful of processes that would otherwise mutate assets without review
|
|
43
|
-
|
|
42
|
+
the handful of processes that would otherwise mutate assets without review
|
|
43
|
+
(memory inference, memory cleanup, and a judged triage promote), unless
|
|
44
|
+
`experimental.improveAutonomy` is explicitly set.
|
|
44
45
|
- **Reflect / distill / consolidate subprocesses** — the improve pipeline's
|
|
45
46
|
proposal generators, invoked per asset (reflect, distill) or across the
|
|
46
47
|
whole memory corpus (consolidate). See
|
|
@@ -49,7 +50,7 @@ everything else routes through `akm proposal accept`.
|
|
|
49
50
|
- **Proposal queue** (`state.db`) — written by `createProposal` (reflect,
|
|
50
51
|
distill, consolidate's promote operations, and the other proposal producers)
|
|
51
52
|
and by `createRetireProposal` (the pair pass's retire proposals).
|
|
52
|
-
- **Auto-sync** — the end-of-run commit/push step for git-backed bundles.
|
|
53
|
+
- **Auto-sync** — the pre-run sync and the end-of-run commit/push step for git-backed bundles.
|
|
53
54
|
- **Session extraction** (`akm proposal extract`) — a separate entry point
|
|
54
55
|
that mines coding-agent session transcripts for durable insights and queues
|
|
55
56
|
them the same way.
|
|
@@ -62,13 +63,16 @@ everything else routes through `akm proposal accept`.
|
|
|
62
63
|
`--negative --reason "<what is wrong and what should change>"` flags the
|
|
63
64
|
asset: the next improve run may repair its frontmatter from the reason.
|
|
64
65
|
`--replace`/`--with`/`--source` attach an exact fix of its text once the
|
|
65
|
-
agent has verified the correct fact, which akm checks at once
|
|
66
|
-
a `feedback` proposal.
|
|
66
|
+
agent has verified the correct fact, which akm checks and applies at once
|
|
67
|
+
through a `feedback` proposal it accepts on the spot (no review).
|
|
67
68
|
`--positive` records that the asset helped (it raises its ranking) and does
|
|
68
69
|
not trigger a rewrite.
|
|
69
|
-
2. The feedback event is appended to `state.db
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
2. The feedback event is appended to `state.db`. `akm search` and `akm curate`
|
|
71
|
+
count a user's recorded positives and negatives per asset and scale the
|
|
72
|
+
fused score by them (logarithmic in each count, the same for every asset),
|
|
73
|
+
so ranking moves at once with no reindex. The asset's utility score, which
|
|
74
|
+
improve and metrics read, is recomputed immediately by the same formula
|
|
75
|
+
`akm index` uses (below).
|
|
72
76
|
3. `akm improve` selects assets from the one bundle it writes to. A rewrite
|
|
73
77
|
(reflect) is planned only for an asset with negative feedback in the last
|
|
74
78
|
30 days that is newer than the stage's last attempt, or for an explicit ref;
|
|
@@ -80,10 +84,11 @@ everything else routes through `akm proposal accept`.
|
|
|
80
84
|
reason or note, which gives the writer nothing to distil (10 of the 11
|
|
81
85
|
lessons made from such memories were rejected). Unless
|
|
82
86
|
`--require-feedback-signal` is set, the
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
proactive-maintenance lane (where the strategy enables it, as `default`
|
|
88
|
+
does) adds the stable assets due for a revisit that the retrieval scope below
|
|
89
|
+
admits, and plans them with the feedback-bearing ones. At most `maxPerRun`
|
|
90
|
+
(15) assets are picked per run, an asset is due only if not reflected or
|
|
91
|
+
distilled for `dueDays` (30), and reflect's `limit` (25) bounds the run. It ranks the selected assets by salience, applies the limit, then
|
|
87
92
|
runs whichever processes the selected strategy enables against each one (see
|
|
88
93
|
[Improve Workflow](internals/improve-workflow.md#ledger-pre-filter-signal-delta)).
|
|
89
94
|
4. Reflect and distill each emit at most one proposal per asset per run;
|
|
@@ -119,36 +124,39 @@ everything else routes through `akm proposal accept`.
|
|
|
119
124
|
retires, go in the same commit. A commit that fails warns and the accept
|
|
120
125
|
stands.
|
|
121
126
|
8. For a git-backed bundle, `akm improve`'s end-of-run auto-sync commits the
|
|
122
|
-
rest of the run's changes as a single batch and pushes (see below).
|
|
127
|
+
rest of the run's changes as a single batch and pushes (see below). The run
|
|
128
|
+
began with the same sync, so it started from what other hosts had pushed.
|
|
129
|
+
|
|
123
130
|
|
|
124
131
|
## Current decisions
|
|
125
132
|
|
|
126
133
|
### Utility scoring
|
|
127
134
|
|
|
128
|
-
Utility
|
|
129
|
-
|
|
135
|
+
Utility has one formula and one implementation, `recomputeUtilityScores`
|
|
136
|
+
(`src/indexer/indexer.ts`), counting only user-attributed (`source='user'`)
|
|
137
|
+
events:
|
|
130
138
|
|
|
131
139
|
```text
|
|
132
|
-
|
|
133
|
-
nextUtil =
|
|
140
|
+
rate = max(selectRate, max(0, positives - negatives) / (positives + negatives))
|
|
141
|
+
nextUtil = prevUtil * 0.7^days + rate * (1 - 0.7^days)
|
|
134
142
|
```
|
|
135
143
|
|
|
136
|
-
`
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
+
`akm index` runs it for every entry. `akm feedback` runs the same function for
|
|
145
|
+
the one entry it touched, so the value it stores is the one the next index
|
|
146
|
+
would compute at that moment (a one-entry call skips the usage-event purge
|
|
147
|
+
and leaves the recompute watermark alone). `days` is the time since the last
|
|
148
|
+
full recompute, at least 1, so decay is time-proportional rather than tied to
|
|
149
|
+
index frequency. When a previously high-utility asset (utility >= 0.5) falls
|
|
150
|
+
below 0.5 after feedback, an `improve_review_needed` event is emitted. Usage
|
|
151
|
+
history (and the utility it drives) is preserved across schema resets and full
|
|
152
|
+
index rebuilds - see [Architecture: Utility Scoring](architecture.md#utility-scoring)
|
|
144
153
|
for the storage-level summary.
|
|
145
154
|
|
|
146
155
|
### Strategy inheritance
|
|
147
156
|
|
|
148
157
|
Improve presets live under `improve.strategies` (config) and the built-in
|
|
149
|
-
set: `default
|
|
150
|
-
`reflect-distill
|
|
151
|
-
(`src/assets/improve-strategies/*.json`). Selection
|
|
158
|
+
set: `default` and `consolidate` (`src/assets/improve-strategies/*.json`). The removed `quick`, `thorough`,
|
|
159
|
+
`catchup`, `reflect-distill` and `proactive-maintenance` still work as user-defined strategies. Selection
|
|
152
160
|
order is `--strategy`, then `defaults.improveStrategy`, then `default`.
|
|
153
161
|
|
|
154
162
|
Resolution is a two-step deep merge (`resolveImproveStrategy`): a named
|
|
@@ -157,16 +165,16 @@ any user-defined override for that same name (under `improve.strategies` in
|
|
|
157
165
|
config) is merged on top. So a strategy — built-in or user-defined — that
|
|
158
166
|
omits a field, or an entire process block, inherits it from `default`; an
|
|
159
167
|
explicit `enabled: true`/`false` in the more specific layer always wins. This
|
|
160
|
-
is why, for example, `proactiveMaintenance`
|
|
161
|
-
`
|
|
162
|
-
|
|
168
|
+
is why, for example, `proactiveMaintenance` is on in `default` and off in
|
|
169
|
+
`consolidate`, and a preset that doesn't mention it at all inherits the
|
|
170
|
+
`default` value. A user-defined strategy named `proactive-maintenance` (the name
|
|
171
|
+
of the retired built-in) resolves the same way, merged onto `default`.
|
|
163
172
|
|
|
164
173
|
### Retrieval scope
|
|
165
174
|
|
|
166
175
|
Improve reworks only what gets read (#986). Fresh feedback and an explicit ref
|
|
167
176
|
scope (`akm improve skills/x`) are usage evidence of their own. Every other
|
|
168
|
-
pick — the proactive-maintenance and
|
|
169
|
-
they pick), and the memories consolidation judges — must be in the retrieval
|
|
177
|
+
pick — the proactive-maintenance lane, and the memories consolidation judges — must be in the retrieval
|
|
170
178
|
scope (`src/commands/improve/retrieval-scope.ts`):
|
|
171
179
|
|
|
172
180
|
- **Retrieved:** a user-attributed `search`, `curate` or `show` returned the
|
|
@@ -207,7 +215,13 @@ Content passes only when **every** criterion scores 4 or more (a lesson's
|
|
|
207
215
|
grounding is judged apart, see
|
|
208
216
|
[distill](internals/improve-workflow.md#distill-akmdistill)); a mean of 3.5
|
|
209
217
|
passed it before. A verdict that does not pass is a review when its mean is 2.5
|
|
210
|
-
or more and a rejection below that.
|
|
218
|
+
or more and a rejection below that. Reflect narrows that band: a revision whose
|
|
219
|
+
mean is 3.5 or more is queued for a person (reason `judge-uncertain`, with the
|
|
220
|
+
`scores` and `judgeReason`) and records no rejection window, and a lower mean is
|
|
221
|
+
refused. On 113 reviewed frontmatter-only proposals (lab 27B Q2, the shipped
|
|
222
|
+
judge) the non-passing ones at 3.5 or more were 17 good and 9 bad, the rest 1
|
|
223
|
+
good and 2 bad; on 396 labelled body rewrites a mean below 3.5 was good 6 times
|
|
224
|
+
in 291 (the constant and its sources are in `src/commands/improve/reflect.ts`). The rubric and the rule were chosen on 90
|
|
211
225
|
labelled real rewrites, where judging on the mean let rewrites that only
|
|
212
226
|
reworded a correct asset through.
|
|
213
227
|
|
|
@@ -217,7 +231,10 @@ both stay on the proposal when the drain accepts it, so a later audit can read
|
|
|
217
231
|
why it passed (`akm proposal show --format json`). A distill pass is not staged:
|
|
218
232
|
the lesson or promotion is minted `deferred` for a person (reason
|
|
219
233
|
`distill-review`, same gate) with the same `scores` and `judgeReason`, and the
|
|
220
|
-
triage drain and its judgment tier leave it alone.
|
|
234
|
+
triage drain and its judgment tier leave it alone. A lesson that repeats an existing
|
|
235
|
+
lesson may instead be proposed as an update of that lesson (reason
|
|
236
|
+
`distill-update`, same gate), with only what the memory adds; the drain leaves
|
|
237
|
+
it for a person too. On 2026-10-05 the gate had
|
|
221
238
|
staged 12 lessons and 10 were bad (they restated the memory, claimed what it
|
|
222
239
|
does not say, or filed a dated status as a lesson), and no score separated them
|
|
223
240
|
from the two good ones. Reflect revises only an asset's
|
|
@@ -225,34 +242,34 @@ from the two good ones. Reflect revises only an asset's
|
|
|
225
242
|
those that fixed a frontmatter defect and left the body alone were good 24
|
|
226
243
|
times in 26, and those that also rewrote the body were bad 175 times in 224.
|
|
227
244
|
|
|
228
|
-
###
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
245
|
+
### Judgment tier: promotions only
|
|
246
|
+
|
|
247
|
+
The triage drain's judgment tier (`processes.triage.judgment`, off in every
|
|
248
|
+
built-in strategy) may accept only a consolidate promotion, a memory proposed as
|
|
249
|
+
a new knowledge note. A retirement or a reflect revision it would
|
|
250
|
+
accept is left for a person (`judgment-not-promotion`); it may still reject.
|
|
251
|
+
Measured on the nightly eval with `experimental.improveAutonomy` (#1132, #1094),
|
|
252
|
+
judging every kind solved 0.49 (gpt-5.6-terra) and 0.53 (qwen3.8-27b) of the
|
|
253
|
+
items, harmed 14 and 11, and changed 18 and 21 notes outside the planted set.
|
|
254
|
+
Judging promotions alone: precision 0.87, recall 0.78 and 4.8% of bad promotions
|
|
255
|
+
accepted on qwen3.8-27b; precision 1.0, recall 0.17 on gpt-5.6-terra.
|
|
256
|
+
|
|
257
|
+
### Proactive-lane proposals wait for a person
|
|
258
|
+
|
|
259
|
+
A proposal planned by the proactive-maintenance lane (`eligibilitySource:
|
|
260
|
+
"proactive"`, an asset with no feedback behind it) is never accepted by the
|
|
261
|
+
drain, whether a deterministic gate (a staged quality-judge pass), the judgment
|
|
262
|
+
tier or an accept staged by an earlier drain would take it. It is left for a
|
|
263
|
+
person with reason `proactive-needs-review`, and the judgment tier does not see
|
|
264
|
+
it. An empty diff is still rejected. Proposals driven by feedback (`signal-delta`,
|
|
265
|
+
`scope`) follow the one rule unchanged (#1147).
|
|
248
266
|
|
|
249
267
|
### Retirement continuity
|
|
250
268
|
|
|
251
269
|
Before the consolidate pair pass mints a `retire` proposal (rule R3,
|
|
252
270
|
`src/commands/improve/consolidate/continuity-check.ts`), it replays up to five
|
|
253
271
|
of the retired asset's own past `search`/`curate` queries
|
|
254
|
-
(`loadRetrievalQueries`,
|
|
255
|
-
for the retrieval regression gate — boilerplate, harness/tool envelopes,
|
|
272
|
+
(`loadRetrievalQueries`, `../retrieval-queries.ts` — boilerplate, harness/tool envelopes,
|
|
256
273
|
pastes and near-duplicates dropped before replay, S3a) through akm's own
|
|
257
274
|
search, in-process — the ranking a user actually gets, no LLM. For every
|
|
258
275
|
query where the retired asset ranked in the top 10, the successor must too
|
|
@@ -297,8 +314,7 @@ but nothing assigns or emits it any more.
|
|
|
297
314
|
### Dry-run planning boundary
|
|
298
315
|
|
|
299
316
|
Dry and live improve runs call the same selectors for signal-delta eligibility,
|
|
300
|
-
the
|
|
301
|
-
plan nothing), the retrieval scope, salience ranking, disk presence, and the
|
|
317
|
+
the proactive-maintenance lane, the retrieval scope, salience ranking, disk presence, and the
|
|
302
318
|
final cap, and resolve the bundle they plan the same way: `--bundle`, else
|
|
303
319
|
`defaultWriteTarget`, else the working bundle (`AKM_BUNDLE_DIR`, else
|
|
304
320
|
`defaultBundle`). Each invocation reports a best-effort observation assembled
|
|
@@ -337,13 +353,20 @@ equals `effective`. When the run is unbounded, `totalCeiling` is omitted.
|
|
|
337
353
|
candidates, validation, and proactive-maintenance selection are proposal-only
|
|
338
354
|
and never write assets directly regardless of this gate.
|
|
339
355
|
Three specific lanes *would* mutate assets without review and are downgraded
|
|
340
|
-
unless `experimental.improveAutonomy` is explicitly set to `true
|
|
356
|
+
unless `experimental.improveAutonomy` is explicitly set to `true` (the triage
|
|
357
|
+
lane only when its judgment tier is on; see below):
|
|
341
358
|
|
|
342
359
|
| Lane | What it does when enabled | With autonomy off |
|
|
343
360
|
| --- | --- | --- |
|
|
344
361
|
| `memoryInference` | Writes `.derived.md` children and rewrites parent frontmatter | disabled |
|
|
345
362
|
| memory cleanup | Belief-state frontmatter rewrites, archive moves | analyzed but not applied |
|
|
346
|
-
| `triage` `applyMode: "promote"` |
|
|
363
|
+
| `triage` `applyMode: "promote"` **with judgment on** | The judgment tier auto-accepts consolidate promotions into the bundle | downgraded to `queue` — triage still runs, it just does not auto-accept |
|
|
364
|
+
|
|
365
|
+
A deterministic-only `promote` (triage with judgment off) is not gated (#1143):
|
|
366
|
+
the `default` strategy drains the queue through the deterministic gates, up to
|
|
367
|
+
`maxAcceptsPerRun` (200) per run, with no opt-in. The nightly eval's baseline is
|
|
368
|
+
exactly this path (`proposal drain --promote` without judgment): 0.91 (terra) and
|
|
369
|
+
0.89 (qwen) of items solved, 0 to 1 harmed.
|
|
347
370
|
|
|
348
371
|
Every downgrade is reported, not silent: it warns on stderr, appends an
|
|
349
372
|
`improve_skipped` event with `reason: "autonomy_gated"`, and is counted in
|
|
@@ -358,18 +381,34 @@ explicit promote surface independent of this gate.
|
|
|
358
381
|
|
|
359
382
|
### Auto-sync
|
|
360
383
|
|
|
361
|
-
For git-backed bundles (detected by a `.git` directory), `akm improve`
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
the active strategy's `sync` setting.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
The sync
|
|
371
|
-
|
|
372
|
-
|
|
384
|
+
For git-backed bundles (detected by a `.git` directory), `akm improve` syncs
|
|
385
|
+
twice: once **before** the run and once at the end. Both are the same operation
|
|
386
|
+
as `akm sync` — fetch and merge the upstream, commit, and push if the bundle is
|
|
387
|
+
writable, per the active strategy's `sync` setting. A user-defined strategy can
|
|
388
|
+
turn sync off, so an interrupted run does not leave an uncommitted backlog.
|
|
389
|
+
`--no-sync` disables both for a single run; `--no-push` commits without pushing.
|
|
390
|
+
Strategy sync behavior is configured via the `sync` block under
|
|
391
|
+
`improve.strategies.<name>`.
|
|
392
|
+
|
|
393
|
+
The pre-run sync runs right after the run takes its lock and before the index
|
|
394
|
+
and plan stages, so they see what another host pushed. It stages what `akm sync`
|
|
395
|
+
stages (the managed paths, or the content subdirectory of a repo whose content
|
|
396
|
+
lives in one), which means pending hand edits there are committed (and pushed)
|
|
397
|
+
before the run starts, not mistaken for the run's own writes. It never aborts
|
|
398
|
+
the run: a merge that conflicts (aborted, local commit kept), a failed fetch, or
|
|
399
|
+
any other error is a warning, and the run continues on the local state. The
|
|
400
|
+
outcome is `preRunSync` on the result (same shape as `sync`) and a `stash_synced`
|
|
401
|
+
event with `phase: "pre-run"`. A dry run does not sync. Scheduled `core/improve`
|
|
402
|
+
and `akm-improve-consolidate` runs go through the same `akm improve` entry, so
|
|
403
|
+
they get it too.
|
|
404
|
+
|
|
405
|
+
The sync always commits the paths it is given. It then fetches the remote and
|
|
406
|
+
brings the upstream in (a fast-forward when it can, otherwise git's default
|
|
407
|
+
merge) before it pushes, so a second host that pushed first does not stop the
|
|
408
|
+
push. A branch it cannot push (no upstream branch, a failed fetch, or a merge
|
|
409
|
+
that conflicts, which is aborted with the local commit kept) only skips the push,
|
|
410
|
+
and the result says why: `sync.reason` reads `not pushed: ...`. A push the remote
|
|
411
|
+
refuses after the commit landed still reports `sync.committed: true`. A branch that is
|
|
373
412
|
ahead of its upstream, as it is after the accept commits above, is pushed with
|
|
374
413
|
the sync commit. A clean tree that is ahead is not pushed: the sync pushes what
|
|
375
414
|
it commits.
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
| `--limit` | `number` | Cap the number of assets processed, taken from the salience ranking, highest first (refs routed to distill only come last). |
|
|
14
14
|
| `--timeout-ms` | `number` | Wall-clock budget for the entire run. Default: 7 200 000 ms (2 hours). |
|
|
15
15
|
| `--skip-if-locked` | `boolean` | If another improve owns the whole-run lock, return an exit-0 no-op result before triage, indexing, events, or sync. Without the flag, contention is a transient error (`IMPROVE_LOCK_HELD`, exit 75). |
|
|
16
|
-
| `--require-feedback-signal` | `boolean` | Turn the
|
|
16
|
+
| `--require-feedback-signal` | `boolean` | Turn the proactive-maintenance lane off for the run, so only assets with recent feedback are planned. |
|
|
17
17
|
|
|
18
18
|
Injected function seams (`reflectFn`, `distillFn`, `ensureIndexFn`, `reindexFn`) replace production defaults in tests.
|
|
19
19
|
|
|
@@ -49,7 +49,7 @@ flowchart TD
|
|
|
49
49
|
P -- yes --> P1[Log failures; refs that still fail\nare excluded from selection]
|
|
50
50
|
P -- no --> L[Signal delta\nreflect: negative feedback, distill: any signal,\nnewer than the last ledger attempt\nand no hard ledger window]
|
|
51
51
|
P1 --> L
|
|
52
|
-
L --> L2[
|
|
52
|
+
L --> L2[Proactive maintenance lane:\nonly retrieved or new material,\nmaxPerRun picks, due after dueDays]
|
|
53
53
|
L2 --> M[scoreSalience\nsalience vector per ref: encoding, outcome, retrieval\nutility scores from SQLite seed the outcome term]
|
|
54
54
|
M --> N[Sort by salience rank DESC, no-op dampened\ndrop refs missing on disk\napply --limit if set]
|
|
55
55
|
N --> Q
|
|
@@ -100,7 +100,7 @@ flowchart TD
|
|
|
100
100
|
DISTILL_G -- no --> DISTILL_J{quality gate judge:\nreusable, non-redundancy, grounding}
|
|
101
101
|
DISTILL_J -- pass --> DISTILL_H[createProposal lessons/slug-lesson\nor knowledge/slug\nsource: distill, gate decision deferred\nappendEvent: outcome=queued]
|
|
102
102
|
DISTILL_J -- mean in the review band --> DISTILL_REVIEW[createProposal, gate decision deferred\nappendEvent: outcome=review_needed]
|
|
103
|
-
DISTILL_J -- any criterion 2 or below, or the mean too low --> DISTILL_REJECT[improve_ledger row, no proposal\nappendEvent: outcome=quality_rejected]
|
|
103
|
+
DISTILL_J -- any criterion 2 or below, or the mean too low --> DISTILL_REJECT[improve_ledger row, no proposal\nappendEvent: outcome=quality_rejected\nunless a repeated lesson gets an update proposal, step 10]
|
|
104
104
|
DISTILL_PROMOTE --> DISTILL_RETURN
|
|
105
105
|
DISTILL_SKIP --> DISTILL_RETURN
|
|
106
106
|
DISTILL_EXISTS --> DISTILL_RETURN
|
|
@@ -150,7 +150,7 @@ flowchart TD
|
|
|
150
150
|
PAIR_INIT --> PAIR_CAND[Candidates: k=5 nearest by stored vector,\nsame bundle + memory tier, cosine >= T_pair]
|
|
151
151
|
PAIR_CAND --> PAIR_JUDGE[One LLM call per pair:\nconsolidate-pair.md, 6-label schema]
|
|
152
152
|
PAIR_JUDGE --> PAIR_OUT{judge label}
|
|
153
|
-
PAIR_OUT -- duplicate / subsumed / supersedes --> PAIR_GUARDS[Guards:
|
|
153
|
+
PAIR_OUT -- duplicate / subsumed / supersedes --> PAIR_GUARDS[Guards: derived parent,\nrejected-pair match, same-run chain]
|
|
154
154
|
PAIR_GUARDS --> PAIR_CONTINUITY[Continuity check R3:\nreplay retired asset's own queries,\nflag continuityRisk, never block]
|
|
155
155
|
PAIR_CONTINUITY --> PAIR_PROPOSE[emitProposal: retire,\nsource: consolidate-pair]
|
|
156
156
|
PAIR_OUT -- overlap / unrelated / contradicts --> PAIR_NOACTION[judged_no_action\nno 7-day timer — content change only]
|
|
@@ -209,9 +209,8 @@ Reflect changes only an asset's `description`, `when_to_use` and title. The engi
|
|
|
209
209
|
contract instead.
|
|
210
210
|
6. Validate the reply with `parseSchemaReflectOutput` (`parseFramedReflectOutput` for the framed contract), which strips `<think>` blocks and code fences, then requires exactly the contract's fields: `confidence` and a `frontmatterPatch` of `description`, `when_to_use` and `title` (each a non-empty single-line string, or `null` for no change), plus `ref` when no target was given. A reply that fails gets one repair turn, shared across self-refine passes: the conversation so far, and a request to reformat the reply in the contract (`reflect-output-repair.md`). A reply still invalid fails with `parse_error` and queues nothing. A failed agent or SDK dispatch is reported as it ran, with its exit code and stderr.
|
|
211
211
|
7. Apply the patch (`applyReflectPatch`) to the source asset: its frontmatter with the non-null `description` and `when_to_use` set, and its body unchanged. A non-null `title` becomes a `# <title>` heading and one blank line at the top of the body, only when the body has no level-1 heading; otherwise it is ignored. A source that requires a `description` and has none gets one derived from its own text when the patch gave none (#636). A patch that changes nothing (every field `null`, or equal to the source's, and no `description` to derive) is the `no_change` outcome (`reflect_skipped_noop`), as is a source with no content to patch; a result that differs only cosmetically is `reflect_skipped_cosmetic`. Neither creates a proposal.
|
|
212
|
-
8. Quality gate (`processes.reflect.qualityGate`, on unless disabled): one judge call scores the revision against the source on **need**, **preservation** and **quality** ([Quality judge](../improvement.md#quality-judge)), and passes it only when every criterion scores 4 or more. A score that does not pass is refused (`quality_rejected`, no proposal). A judge that times out, errors or replies unparseably gives no verdict, and the proposal is deferred for review (`judge-error`, gate `quality-gate`). Before the judge, with the gate on or off, reflect refuses (`quality_rejected`, no proposal, no judge call; the rule is the event's `reflectDefect`) a revision that adds placeholder text (`placeholder_added`: "please confirm", "to be confirmed"; not `TODO`, `TBD` or `FIXME`), talks about its own edit (`meta_commentary_added`: "the feedback says", "this revision") or copies frontmatter into its body (`frontmatter_copied_into_body`: `sources:` or `updated:` lines outside code, a `sources` value). Each rule counts only what the revision adds to its source (`findReflectDefect`), and its wording is a list that `processes.reflect.defectFilter` replaces or, when empty, turns off ([Configuration](../../reference/configuration.md#strategies)).
|
|
213
|
-
9.
|
|
214
|
-
10. Write the proposal (`mintProposal`). A pass the judge passed is stamped `staged`, and the triage drain accepts it; with the gate off the proposal is minted unstamped for the drain to decide. One made with no judge configured (`no-judge-configured`) is deferred for review (gate `reflect`), and so is one whose judge gave no verdict (`judge-error`). The drain leaves every deferral for a person.
|
|
212
|
+
8. Quality gate (`processes.reflect.qualityGate`, on unless disabled): one judge call scores the revision against the source on **need**, **preservation** and **quality** ([Quality judge](../improvement.md#quality-judge)), and passes it only when every criterion scores 4 or more. A score that does not pass is refused (`quality_rejected`, no proposal) unless its mean is 3.5 or more: that is uncertain, not bad, and the proposal is deferred for a person (`judge-uncertain`, gate `quality-gate`, with the criterion `scores` and the judge's reason) and records no rejection window. A judge that times out, errors or replies unparseably gives no verdict, and the proposal is deferred for review too (`judge-error`, gate `quality-gate`). Before the judge, with the gate on or off, reflect refuses (`quality_rejected`, no proposal, no judge call; the rule is the event's `reflectDefect`) a revision that adds placeholder text (`placeholder_added`: "please confirm", "to be confirmed"; not `TODO`, `TBD` or `FIXME`), talks about its own edit (`meta_commentary_added`: "the feedback says", "this revision") or copies frontmatter into its body (`frontmatter_copied_into_body`: `sources:` or `updated:` lines outside code, a `sources` value). Each rule counts only what the revision adds to its source (`findReflectDefect`), and its wording is a list that `processes.reflect.defectFilter` replaces or, when empty, turns off ([Configuration](../../reference/configuration.md#strategies)).
|
|
213
|
+
9. Write the proposal (`mintProposal`). A pass the judge passed is stamped `staged`, and the triage drain accepts it; with the gate off the proposal is minted unstamped for the drain to decide. One made with no judge configured (`no-judge-configured`) is deferred for review (gate `reflect`), and so is one whose judge gave no verdict (`judge-error`) and one in the judge's uncertain band (`judge-uncertain`). `akm proposal list` shows the reason; the drain leaves every deferral for a person.
|
|
215
214
|
|
|
216
215
|
**What it writes:** one durable proposal row in `state.db`. It never writes asset files directly.
|
|
217
216
|
|
|
@@ -245,10 +244,17 @@ Reflect changes only an asset's `description`, `when_to_use` and title. The engi
|
|
|
245
244
|
- **Grounding** asks whether every cause, step, number, rule and limit in the lesson is stated by the source or its feedback; 4–5 when each is, 3 when one stretches what the source says, 1–2 when any is in neither, when the lesson drops a limit the source states, or when it is about another subject. It is not part of the mean.
|
|
246
245
|
- A criterion at 2 or below is `quality_rejected` whatever the mean is (the reason names the criterion: `grounding 2/5: …`). Otherwise the lesson passes when reusable and non-redundancy both score 4 or more, and a mean of those two of 2.5 or more is `review_needed`. A pass is also queued for a person (step 9), so the rejection is the only thing that keeps a lesson from a reviewer: on 2026-10-05 the old rubric (novelty, non-redundancy, and a grounding that scored 3 for a lesson that "goes beyond the source") passed 10 of the 17 bad lessons, because a lesson that adds to its memory scored as novel. The old novelty question was also the reason the judge rejected a faithful lesson of a lesson-worthy memory. A distill with no source to read (an unindexed ref distilled "from feedback signal alone") gives the judge an empty source, so its lesson is expected to be rejected.
|
|
247
246
|
- `quality_rejected` writes an `improve_ledger` row for the input (30-day distill rejection window) and a `distill_invoked` event carrying `score`, the per-criterion `criteria` and the `reason`. It mints no proposal.
|
|
248
|
-
- `review_needed` mints a pending proposal stamped `deferred` / `quality-gate` for a human; the triage drain leaves it alone. It is the outcome for a non-passing mean of 2.5 or more when no criterion is at 2 or below, a judge that times out
|
|
247
|
+
- `review_needed` mints a pending proposal stamped `deferred` / `quality-gate` for a human; the triage drain leaves it alone. It is the outcome for a non-passing mean of 2.5 or more when no criterion is at 2 or below, a judge that times out, returns something unparseable or incomplete, or is missing when the lesson or promotion is judged, and a heuristic lesson-quality finding (for example an invalid `description`), which is found before the judge is called.
|
|
249
248
|
9. Create proposal: `createProposal(stash, { ref: lessonRef, source: "distill", payload })` through `mintProposal`. A pass is minted `deferred` (gate `quality-gate`, reason `distill-review`) with the judge's per-criterion `scores` and `judgeReason`, for a person: the triage drain and its judgment tier leave it alone, and the improve ledger records `review_needed`. It is never `staged`. On 2026-10-05 the gate had staged 12 lessons and 10 were bad (they restated the memory, claimed what it does not say, or filed a dated status as a lesson); no judge score separated them from the two good ones. A promotion to knowledge that passes is deferred the same way. With `processes.distill.qualityGate` off nothing was judged, so the proposal is minted unstamped for the drain to decide.
|
|
250
249
|
10. Emit `distill_invoked` event with `outcome: "queued"`.
|
|
251
250
|
|
|
251
|
+
**Updating a lesson the memory repeats (#1090):** when the lesson repeats one the library holds, distill extends that lesson instead of only dropping the duplicate. It happens in two places, both with the quality gate on: the judge scored the writer's lesson 2 or below on non-redundancy (step 8), or the writer answered `NONE` (step 5). Either way the update is tried for the related lessons (among the top 3 nearby assets, as for the judge, in the bundle the proposal is filed in) that the writer's `reason`, or the judge's, names by ref or name, or for the only related lesson when it names none. One lesson among several that merely sit near the memory costs no call. A second call shows the writer the memory, its feedback and the candidate lessons' bodies, and asks it to pick the lesson that already states the memory's rule, list in `new_facts` each cause, step, number, limit or consequence the memory states and the lesson lacks (the memory's own incident retold is not one), and return that lesson's whole body with a line added for each; it answers `decision: "none"` when no listed lesson states the rule, when `new_facts` is empty (an update with none is not proposed), or when the memory contradicts a line. Then:
|
|
252
|
+
|
|
253
|
+
- Every existing body line must still be there (compared by words, in any case and spacing). A body that drops or rewords one is not proposed.
|
|
254
|
+
- The extended lesson (existing frontmatter and the whole new body) is judged as one lesson, in one call, by step 8's judge with an edit variant of its rubric: **reusable** and **grounding** read the whole lesson (a line is grounded when the memory, its feedback or the lesson being extended states it), and **non-redundancy** is asked of each added line against the lesson being extended: 1–2 when it only says again what the lesson says (its rule or cause in other words, or the same rule on an example from the memory), 4–5 when it states a fact the lesson lacks, however specific. The lesson being extended is shown to the judge as such, not as an asset the new lesson might repeat. Judging the added lines alone as a new lesson failed `reusable` for a lone fact, and no update passed. A body that adds no line is not proposed; anything short of a judge pass is not proposed.
|
|
255
|
+
- The update is a pending proposal on the existing lesson's ref (`source: distill`), the lesson's frontmatter unchanged except that the memory is added to `xrefs`. Its `beforeHash` is the lesson's as read, so accepting it after the lesson changed is refused as stale. It is minted `deferred` (gate `quality-gate`, reason `distill-update`) with the judge's `scores` and `judgeReason`, so the triage drain and its judgment tier leave it for a person. The result and the `distill_invoked` event are `queued` with `proposalRef` set to the lesson and `updatesExisting: true`.
|
|
256
|
+
- When nothing is proposed, the outcome is what it was before: `quality_rejected` with the judge's reason after a duplicate lesson, `skipped` / `nothing_reusable` after `NONE`.
|
|
257
|
+
|
|
252
258
|
**Lesson-ref derivation rule:** `lessons/<type>-<name>-lesson` where `<type>-<name>` is derived from the input ref with origin stripped and non-alphanumeric characters replaced by `-`. Example: `skills/deploy` → `lessons/skill-deploy-lesson`. A lesson already at that ref is never overwritten (see step 4).
|
|
253
259
|
|
|
254
260
|
**What it writes:** one durable proposal row in `state.db`. Never writes asset files directly.
|
|
@@ -378,8 +384,8 @@ duplicate, subsumed and superseding retirement, review-gated.
|
|
|
378
384
|
body characters.
|
|
379
385
|
4. **Outcome:** `duplicate`, `subsumed` and `supersedes` mint one `retire`
|
|
380
386
|
proposal (source `consolidate-pair`, its own generator — see below) for
|
|
381
|
-
the side that does not survive — never a
|
|
382
|
-
|
|
387
|
+
the side that does not survive — never a
|
|
388
|
+
`.derived` memory whose parent still exists, never across bundles,
|
|
383
389
|
never when either side already has a pending retire proposal (as the
|
|
384
390
|
retired ref or its successor), and never retiring or reusing as a
|
|
385
391
|
successor an asset already spent earlier in the SAME run (the durable
|
|
@@ -478,8 +484,8 @@ proposal.
|
|
|
478
484
|
|
|
479
485
|
Before the pair pass mints a `retire` proposal, it replays up to five of the
|
|
480
486
|
retired asset's own past `search`/`curate` queries
|
|
481
|
-
(`loadRetrievalQueries`, `src/commands/improve/retrieval-
|
|
482
|
-
|
|
487
|
+
(`loadRetrievalQueries`, `src/commands/improve/retrieval-queries.ts`:
|
|
488
|
+
`usableRetrievalQueries`
|
|
483
489
|
drops stash-README boilerplate and harness/tool envelopes
|
|
484
490
|
(`nonTaskInput`), pastes over 2,000 characters, and queries that are
|
|
485
491
|
duplicates once whitespace is collapsed, S3a) through akm's own search,
|
|
@@ -610,7 +616,7 @@ Two proposals can share the same `ref`; their UUID primary keys prevent collisio
|
|
|
610
616
|
|
|
611
617
|
## Scope restrictions
|
|
612
618
|
|
|
613
|
-
`akm improve` reads and writes one bundle, its write target: `--bundle`, else `defaultWriteTarget`, else the working bundle. The candidate set is that bundle's assets and nothing else, because every proposal is filed in the write target. An asset that another writable bundle owns is never planned: reflect would read it from its own bundle and the proposal would land in this one, either forking the asset as a `create` or overwriting this bundle's copy with content taken from the other's (#1000). A bare ref scope (`akm improve skills/x`) resolves inside the write target only, and distill's memory-to-knowledge promotion merges only with a doc that already exists there. To improve another writable bundle, select it with `--bundle team` or a bundle-qualified scope such as `team//skills/code-review`; a scheduled run therefore covers only its write target, and each other bundle needs its own scheduled `akm improve --bundle <name>` run. A dry run (`--dry-run
|
|
619
|
+
`akm improve` reads and writes one bundle, its write target: `--bundle`, else `defaultWriteTarget`, else the working bundle. The candidate set is that bundle's assets and nothing else, because every proposal is filed in the write target. An asset that another writable bundle owns is never planned: reflect would read it from its own bundle and the proposal would land in this one, either forking the asset as a `create` or overwriting this bundle's copy with content taken from the other's (#1000). A bare ref scope (`akm improve skills/x`) resolves inside the write target only, and distill's memory-to-knowledge promotion merges only with a doc that already exists there. To improve another writable bundle, select it with `--bundle team` or a bundle-qualified scope such as `team//skills/code-review`; a scheduled run therefore covers only its write target, and each other bundle needs its own scheduled `akm improve --bundle <name>` run. A dry run (`--dry-run`) resolves the bundle the way a live run does, with the working bundle starting from `AKM_BUNDLE_DIR` before `defaultBundle`, so it previews the bundle a live run improves. As a second line of defence, `createProposal` refuses a proposal whose `itemRef` names an asset owned by a different configured bundle than the queue's.
|
|
614
620
|
|
|
615
621
|
`akm improve` and `akm lint` only operate on writable bundle sources (sources with `writable: true`). Read-only sources (git, npm, website) are excluded from the candidate set before any other filtering; a read-only write target plans nothing.
|
|
616
622
|
|
|
@@ -622,12 +628,12 @@ Every stage reads the improve ledger (`improve_ledger` in `state.db`, one row pe
|
|
|
622
628
|
|
|
623
629
|
- A ref that passes reflect is planned for the loop. If it does not pass distill, distill is skipped for it (a `distill-skipped` action and an `improve_skipped` event with reason `distill_no_new_signal`).
|
|
624
630
|
- A ref that passes only distill, and is a distill candidate, is planned distill-only.
|
|
625
|
-
- A ref with no in-window feedback and no reflect window is left to the
|
|
626
|
-
- Every ref the loop does not take is counted in the plan's `signal` gate (or its `retrieval` gate, when the
|
|
631
|
+
- A ref with no in-window feedback and no reflect window is left to the proactive-maintenance lane, which picks only what retrieval returned or new material (see [Retrieval scope](../improvement.md#retrieval-scope)) and plans its picks with the feedback-bearing refs. The cap against a proposal flood: `maxPerRun` (15) picks per run, an asset due only after `dueDays` (30) without a reflect or distill, and reflect's `limit` (25).
|
|
632
|
+
- Every ref the loop does not take is counted in the plan's `signal` gate (or its `retrieval` gate, when the proactive lane could not pick it for lack of usage evidence) and reported once, in aggregate, as an `improve_skipped` event (`no_new_signal`, `not_retrieved`).
|
|
627
633
|
- A memory flagged wrong is not distilled: when a negative feedback in the 30-day window recorded the hash of the body it judged (`contentHash`, the `body` hash of `content-hash.ts`) and the file's body still has it, the loop skips distill for it (a `distill-skipped` action and an `improve_skipped` event with reason `distill_flagged_wrong`) and records the attempt in the ledger as `unchanged`, so the ref waits for newer feedback. Reflect still plans it. A write that leaves the body alone (an inference stamp, a frontmatter repair) does not lift the flag; changing the body does. Feedback recorded without a hash keeps the earlier test: it flags the memory while it is newer than the file's last write, whose modification time is the edit signal, as for the retrieval scope's new material.
|
|
628
634
|
- A memory whose only feedback in the 30-day window is positive without a reason or note (`hasOnlyBarePositiveFeedback` in `preparation.ts`) is not distilled either: the loop skips distill for it (a `distill-skipped` action with the reason "only positive feedback, without a reason" and an `improve_skipped` event with reason `distill_positive_without_reason`) and records the attempt in the ledger as `unchanged`, so it waits for newer feedback. A bare `--positive` only records that a note helped, which gives the writer nothing to distil: 10 of the 11 lessons made from such a memory were rejected on 2026-10-05, and the 11th was good. A reason, a note or a negative signal among the feedback, or an explicit ref scope, lets it through.
|
|
629
635
|
- A memory whose frontmatter says `beliefState: deprecated` or `superseded` (`isDeprecatedOrSuperseded` in `preparation.ts`) is not distilled either: the loop skips distill for it (a `distill-skipped` action with the reason "marked deprecated or superseded" and an `improve_skipped` event with reason `distill_deprecated_or_superseded`) and records the attempt in the ledger as `unchanged`. An explicit `--scope` ref still runs. `contradicted` is not skipped: it marks an open conflict, not a retired note.
|
|
630
|
-
- The loop's refs are ranked by salience (`scoreSalience` in `preparation.ts`, which also scores the
|
|
636
|
+
- The loop's refs are ranked by salience (`scoreSalience` in `preparation.ts`, which also scores the lane's picks and computes each vector with `computeSalience` from `salience.ts`): encoding, outcome, and retrieval frequency and recency, discounted for file size, with a ref that was repeatedly skipped as a no-op ranked lower. Refs missing on disk are dropped, and `--limit` cuts the list: reflect-path refs first, then distill-only refs.
|
|
631
637
|
|
|
632
638
|
An explicit ref scope bypasses every gate. Consolidation, extract and schema repair read their own ledger sources in their own stages.
|
|
633
639
|
|
|
@@ -429,7 +429,7 @@ so a layout change is applied in place rather than by discarding the index.
|
|
|
429
429
|
Durable workflow, task, proposal, event, and usage state in `state.db` is
|
|
430
430
|
never touched by these paths.
|
|
431
431
|
|
|
432
|
-
|
|
432
|
+
The workflow `.md` adapter compiles directly to source IR version 1.
|
|
433
433
|
The index stores only the ordinary normalized `entries` row and searchable
|
|
434
434
|
metadata derived from that IR. It does not cache a second workflow AST or an
|
|
435
435
|
executable plan. Starting a run recompiles the authored source once and freezes
|