akm-cli 0.9.31 → 0.10.26101002-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +265 -0
- package/STABILITY.md +79 -53
- 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 +13 -27
- package/dist/assets/hints/cli-hints-short.md +1 -1
- package/dist/assets/improve-strategies/default.json +3 -3
- package/dist/assets/prompts/consolidate-pair.md +9 -7
- 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/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/pair-pass.js +7 -1
- package/dist/commands/improve/consolidate.js +6 -35
- 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 +140 -20
- package/dist/commands/improve/eligibility.js +14 -1
- package/dist/commands/improve/extract-cli.js +1 -1
- package/dist/commands/improve/improve-cli.js +87 -102
- package/dist/commands/improve/improve-strategies.js +8 -12
- package/dist/commands/improve/improve.js +2 -2
- package/dist/commands/improve/loop-stages.js +0 -1
- 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 +3 -8
- package/dist/commands/improve/retrieval-scope.js +2 -2
- package/dist/commands/improve/salience.js +2 -9
- package/dist/commands/improve/stage.js +14 -9
- package/dist/commands/lint/index.js +5 -20
- package/dist/commands/observability-cli.js +3 -9
- package/dist/commands/proposal/drain.js +39 -6
- package/dist/commands/proposal/proposal-cli.js +11 -31
- package/dist/commands/proposal/repository.js +3 -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 +4 -12
- 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 +8 -61
- 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/improve-result.js +11 -1
- package/dist/core/mutation-target.js +2 -2
- package/dist/core/recognition-util.js +4 -5
- 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/search/db-search.js +4 -19
- package/dist/indexer/search/fts-query.js +0 -19
- 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 +228 -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 +13049 -14013
- package/dist/scripts/akm-migrate.js +16316 -17276
- 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/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/task-history.js +0 -2
- 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/adapters.md +17 -31
- package/docs/architecture/architecture.md +4 -5
- package/docs/architecture/improvement.md +52 -21
- package/docs/architecture/internals/improve-workflow.md +15 -8
- package/docs/architecture/internals/indexing.md +1 -1
- package/docs/architecture/internals/search.md +1 -2
- package/docs/architecture/internals/storage-locations.md +5 -5
- 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 +20 -29
- 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/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 +7 -7
- package/docs/guides/recipes/headless-install.md +2 -2
- package/docs/guides/run-workflows.md +1 -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 +30 -1
- 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 +129 -171
- package/docs/reference/configuration.md +84 -19
- package/docs/reference/data-and-telemetry.md +1 -1
- 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/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/tasks/validate.js +0 -176
- package/dist/core/config/legacy-source-shape-shim.js +0 -117
- 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
|
@@ -39,8 +39,9 @@ everything else routes through `akm proposal accept`.
|
|
|
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
|
|
@@ -80,10 +81,11 @@ everything else routes through `akm proposal accept`.
|
|
|
80
81
|
reason or note, which gives the writer nothing to distil (10 of the 11
|
|
81
82
|
lessons made from such memories were rejected). Unless
|
|
82
83
|
`--require-feedback-signal` is set, the
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
proactive-maintenance lane (where the strategy enables it, as `default`
|
|
85
|
+
does) adds the stable assets due for a revisit that the retrieval scope below
|
|
86
|
+
admits, and plans them with the feedback-bearing ones. At most `maxPerRun`
|
|
87
|
+
(15) assets are picked per run, an asset is due only if not reflected or
|
|
88
|
+
distilled for `dueDays` (30), and reflect's `limit` (25) bounds the run. It ranks the selected assets by salience, applies the limit, then
|
|
87
89
|
runs whichever processes the selected strategy enables against each one (see
|
|
88
90
|
[Improve Workflow](internals/improve-workflow.md#ledger-pre-filter-signal-delta)).
|
|
89
91
|
4. Reflect and distill each emit at most one proposal per asset per run;
|
|
@@ -146,9 +148,8 @@ for the storage-level summary.
|
|
|
146
148
|
### Strategy inheritance
|
|
147
149
|
|
|
148
150
|
Improve presets live under `improve.strategies` (config) and the built-in
|
|
149
|
-
set: `default
|
|
150
|
-
`reflect-distill
|
|
151
|
-
(`src/assets/improve-strategies/*.json`). Selection
|
|
151
|
+
set: `default` and `consolidate` (`src/assets/improve-strategies/*.json`). The removed `quick`, `thorough`,
|
|
152
|
+
`catchup`, `reflect-distill` and `proactive-maintenance` still work as user-defined strategies. Selection
|
|
152
153
|
order is `--strategy`, then `defaults.improveStrategy`, then `default`.
|
|
153
154
|
|
|
154
155
|
Resolution is a two-step deep merge (`resolveImproveStrategy`): a named
|
|
@@ -157,16 +158,16 @@ any user-defined override for that same name (under `improve.strategies` in
|
|
|
157
158
|
config) is merged on top. So a strategy — built-in or user-defined — that
|
|
158
159
|
omits a field, or an entire process block, inherits it from `default`; an
|
|
159
160
|
explicit `enabled: true`/`false` in the more specific layer always wins. This
|
|
160
|
-
is why, for example, `proactiveMaintenance`
|
|
161
|
-
`
|
|
162
|
-
|
|
161
|
+
is why, for example, `proactiveMaintenance` is on in `default` and off in
|
|
162
|
+
`consolidate`, and a preset that doesn't mention it at all inherits the
|
|
163
|
+
`default` value. A user-defined strategy named `proactive-maintenance` (the name
|
|
164
|
+
of the retired built-in) resolves the same way, merged onto `default`.
|
|
163
165
|
|
|
164
166
|
### Retrieval scope
|
|
165
167
|
|
|
166
168
|
Improve reworks only what gets read (#986). Fresh feedback and an explicit ref
|
|
167
169
|
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
|
|
170
|
+
pick — the proactive-maintenance lane, and the memories consolidation judges — must be in the retrieval
|
|
170
171
|
scope (`src/commands/improve/retrieval-scope.ts`):
|
|
171
172
|
|
|
172
173
|
- **Retrieved:** a user-attributed `search`, `curate` or `show` returned the
|
|
@@ -217,7 +218,10 @@ both stay on the proposal when the drain accepts it, so a later audit can read
|
|
|
217
218
|
why it passed (`akm proposal show --format json`). A distill pass is not staged:
|
|
218
219
|
the lesson or promotion is minted `deferred` for a person (reason
|
|
219
220
|
`distill-review`, same gate) with the same `scores` and `judgeReason`, and the
|
|
220
|
-
triage drain and its judgment tier leave it alone.
|
|
221
|
+
triage drain and its judgment tier leave it alone. A lesson that repeats an existing
|
|
222
|
+
lesson may instead be proposed as an update of that lesson (reason
|
|
223
|
+
`distill-update`, same gate), with only what the memory adds; the drain leaves
|
|
224
|
+
it for a person too. On 2026-10-05 the gate had
|
|
221
225
|
staged 12 lessons and 10 were bad (they restated the memory, claimed what it
|
|
222
226
|
does not say, or filed a dated status as a lesson), and no score separated them
|
|
223
227
|
from the two good ones. Reflect revises only an asset's
|
|
@@ -225,6 +229,28 @@ from the two good ones. Reflect revises only an asset's
|
|
|
225
229
|
those that fixed a frontmatter defect and left the body alone were good 24
|
|
226
230
|
times in 26, and those that also rewrote the body were bad 175 times in 224.
|
|
227
231
|
|
|
232
|
+
### Judgment tier: promotions only
|
|
233
|
+
|
|
234
|
+
The triage drain's judgment tier (`processes.triage.judgment`, off in every
|
|
235
|
+
built-in strategy) may accept only a consolidate promotion, a memory proposed as
|
|
236
|
+
a new knowledge note. A retirement, an exact fix or a reflect revision it would
|
|
237
|
+
accept is left for a person (`judgment-not-promotion`); it may still reject.
|
|
238
|
+
Measured on the nightly eval with `experimental.improveAutonomy` (#1132, #1094),
|
|
239
|
+
judging every kind solved 0.49 (gpt-5.6-terra) and 0.53 (qwen3.8-27b) of the
|
|
240
|
+
items, harmed 14 and 11, and changed 18 and 21 notes outside the planted set.
|
|
241
|
+
Judging promotions alone: precision 0.87, recall 0.78 and 4.8% of bad promotions
|
|
242
|
+
accepted on qwen3.8-27b; precision 1.0, recall 0.17 on gpt-5.6-terra.
|
|
243
|
+
|
|
244
|
+
### Proactive-lane proposals wait for a person
|
|
245
|
+
|
|
246
|
+
A proposal planned by the proactive-maintenance lane (`eligibilitySource:
|
|
247
|
+
"proactive"`, an asset with no feedback behind it) is never accepted by the
|
|
248
|
+
drain, whether a deterministic gate (a staged quality-judge pass), the judgment
|
|
249
|
+
tier or an accept staged by an earlier drain would take it. It is left for a
|
|
250
|
+
person with reason `proactive-needs-review`, and the judgment tier does not see
|
|
251
|
+
it. An empty diff is still rejected. Proposals driven by feedback (`signal-delta`,
|
|
252
|
+
`scope`) follow the one rule unchanged (#1147).
|
|
253
|
+
|
|
228
254
|
### Retrieval regression gate
|
|
229
255
|
|
|
230
256
|
Reflect refuses a revision of an existing asset that grades lower on the
|
|
@@ -297,8 +323,7 @@ but nothing assigns or emits it any more.
|
|
|
297
323
|
### Dry-run planning boundary
|
|
298
324
|
|
|
299
325
|
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
|
|
326
|
+
the proactive-maintenance lane, the retrieval scope, salience ranking, disk presence, and the
|
|
302
327
|
final cap, and resolve the bundle they plan the same way: `--bundle`, else
|
|
303
328
|
`defaultWriteTarget`, else the working bundle (`AKM_BUNDLE_DIR`, else
|
|
304
329
|
`defaultBundle`). Each invocation reports a best-effort observation assembled
|
|
@@ -337,13 +362,20 @@ equals `effective`. When the run is unbounded, `totalCeiling` is omitted.
|
|
|
337
362
|
candidates, validation, and proactive-maintenance selection are proposal-only
|
|
338
363
|
and never write assets directly regardless of this gate.
|
|
339
364
|
Three specific lanes *would* mutate assets without review and are downgraded
|
|
340
|
-
unless `experimental.improveAutonomy` is explicitly set to `true
|
|
365
|
+
unless `experimental.improveAutonomy` is explicitly set to `true` (the triage
|
|
366
|
+
lane only when its judgment tier is on; see below):
|
|
341
367
|
|
|
342
368
|
| Lane | What it does when enabled | With autonomy off |
|
|
343
369
|
| --- | --- | --- |
|
|
344
370
|
| `memoryInference` | Writes `.derived.md` children and rewrites parent frontmatter | disabled |
|
|
345
371
|
| memory cleanup | Belief-state frontmatter rewrites, archive moves | analyzed but not applied |
|
|
346
|
-
| `triage` `applyMode: "promote"` |
|
|
372
|
+
| `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 |
|
|
373
|
+
|
|
374
|
+
A deterministic-only `promote` (triage with judgment off) is not gated (#1143):
|
|
375
|
+
the `default` strategy drains the queue through the deterministic gates, up to
|
|
376
|
+
`maxAcceptsPerRun` (200) per run, with no opt-in. The nightly eval's baseline is
|
|
377
|
+
exactly this path (`proposal drain --promote` without judgment): 0.91 (terra) and
|
|
378
|
+
0.89 (qwen) of items solved, 0 to 1 harmed.
|
|
347
379
|
|
|
348
380
|
Every downgrade is reported, not silent: it warns on stderr, appends an
|
|
349
381
|
`improve_skipped` event with `reason: "autonomy_gated"`, and is counted in
|
|
@@ -361,8 +393,7 @@ explicit promote surface independent of this gate.
|
|
|
361
393
|
For git-backed bundles (detected by a `.git` directory), `akm improve`
|
|
362
394
|
automatically commits its changes as a single batch at the end of the run —
|
|
363
395
|
the same operation as `akm sync` — and pushes if the bundle is writable, per
|
|
364
|
-
the active strategy's `sync` setting.
|
|
365
|
-
`proactive-maintenance` strategies skip sync entirely, so an interrupted run
|
|
396
|
+
the active strategy's `sync` setting. A user-defined strategy can turn sync off, so an interrupted run
|
|
366
397
|
does not leave an uncommitted backlog. `--no-sync` disables sync for a single
|
|
367
398
|
run; `--no-push` commits without pushing. Strategy sync behavior is
|
|
368
399
|
configured via the `sync` block under `improve.strategies.<name>`.
|
|
@@ -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
|
|
@@ -245,10 +245,17 @@ Reflect changes only an asset's `description`, `when_to_use` and title. The engi
|
|
|
245
245
|
- **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
246
|
- 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
247
|
- `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 or returns something unparseable or incomplete,
|
|
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 or returns something unparseable or incomplete, and a heuristic lesson-quality finding (for example an invalid `description`), which is found before the judge is called.
|
|
249
249
|
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
250
|
10. Emit `distill_invoked` event with `outcome: "queued"`.
|
|
251
251
|
|
|
252
|
+
**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:
|
|
253
|
+
|
|
254
|
+
- 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.
|
|
255
|
+
- 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.
|
|
256
|
+
- 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`.
|
|
257
|
+
- 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`.
|
|
258
|
+
|
|
252
259
|
**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
260
|
|
|
254
261
|
**What it writes:** one durable proposal row in `state.db`. Never writes asset files directly.
|
|
@@ -610,7 +617,7 @@ Two proposals can share the same `ref`; their UUID primary keys prevent collisio
|
|
|
610
617
|
|
|
611
618
|
## Scope restrictions
|
|
612
619
|
|
|
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
|
|
620
|
+
`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
621
|
|
|
615
622
|
`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
623
|
|
|
@@ -622,12 +629,12 @@ Every stage reads the improve ledger (`improve_ledger` in `state.db`, one row pe
|
|
|
622
629
|
|
|
623
630
|
- 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
631
|
- 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
|
|
632
|
+
- 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).
|
|
633
|
+
- 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
634
|
- 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
635
|
- 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
636
|
- 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
|
|
637
|
+
- 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
638
|
|
|
632
639
|
An explicit ref scope bypasses every gate. Consolidation, extract and schema repair read their own ledger sources in their own stages.
|
|
633
640
|
|
|
@@ -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
|
|
@@ -223,11 +223,10 @@ By default (`--format json`, `--detail brief`), search emits minimal fields:
|
|
|
223
223
|
`--detail normal` emits `type`, `name`, `description`, `action`, `score`, and
|
|
224
224
|
`estimatedTokens`, plus optional warning, quality, or env-key fields.
|
|
225
225
|
`--detail full` adds `whyMatched`, `origin`, `path`, and timing data.
|
|
226
|
-
`--shape summary` returns metadata only (no content), under 200 tokens.
|
|
227
226
|
|
|
228
227
|
### Agent-optimized output
|
|
229
228
|
|
|
230
|
-
For each materialized local hit, `--
|
|
229
|
+
For each materialized local hit, `--detail agent` includes `name`, canonical
|
|
231
230
|
`ref`, `type`, absolute `path`, current-policy `editable`, `description`,
|
|
232
231
|
`action`, `score`, and optional `estimatedTokens`/env keys. `editHint` appears
|
|
233
232
|
only when `editable` is `false`. The hint is supplemental: `action` remains the
|
|
@@ -253,7 +253,7 @@ extension, so an install without `sqlite-vec` leaves the unread table in place.
|
|
|
253
253
|
|
|
254
254
|
#### Workflow source indexing
|
|
255
255
|
|
|
256
|
-
|
|
256
|
+
Workflow `.md` sources compile directly to source IR version 1.
|
|
257
257
|
The index stores the ordinary normalized `entries` row and metadata derived from
|
|
258
258
|
that IR; there is no workflow-specific AST cache or parallel persisted source
|
|
259
259
|
representation. Executable durable plans belong only to `state.db`.
|
|
@@ -503,7 +503,7 @@ Keys of `metadata_json`, each written only when the proposal has it:
|
|
|
503
503
|
| `gateDecision` | `{ outcome: auto-accepted\|deferred\|staged\|auto-rejected, reason, gate?, contentHash?, measured?, thresholds?, scores?, judgeReason?, decidedAt }`; `scores` (per criterion) and `judgeReason` are the quality judge's evidence on its `staged` pass (or on a distill pass it deferred for review as `distill-review`), and stay on the row when the drain accepts it; a reflect pass deferred as `body-edit` by an older release carries them too |
|
|
504
504
|
| `backupContent` | The target's content before promotion, for `revert` |
|
|
505
505
|
| `acceptedTarget` | `{ source, root, path, contentHash }`, where accepted content went |
|
|
506
|
-
| `eligibilitySource` | The improve lane that planned the asset: `signal-delta` or `scope`; `
|
|
506
|
+
| `eligibilitySource` | The improve lane that planned the asset: `signal-delta`, `proactive` or `scope`; `high-salience` only on rows an older release wrote, since that lane was removed |
|
|
507
507
|
| `promotionSource`, `promotionSourceHash` | A consolidate promotion's source memory and its raw body hash at mint: accept archives the memory only if the hash still matches, and once the promotion is decided the ledger holds the memory until its body changes |
|
|
508
508
|
| `retirement` | A `consolidate-pair` retire proposal's verdict: `retiredRef`, `successorRef`, `cosine`, `judgeLabel`, `judgeReason`, `onlyInRetired` and `onlyInSuccessor` (the judge's claim lists by role, each at most 20 x 200 chars; absent before they were recorded), `retiredContentHash`, `successorContentHash`, `reason`, and `continuityRisk` when the retirement continuity check flagged it |
|
|
509
509
|
| `retiredArchive` | `{ dirs }`, the archive directories of an accepted retirement, for `revert` |
|
|
@@ -632,7 +632,7 @@ The JSONL file at `$CACHE/events.jsonl` is no longer read or written by akm.
|
|
|
632
632
|
| `improve_invoked` | `akm improve`, live runs | `strategy`, `scope`, `dryRun`, `eligibleCount` |
|
|
633
633
|
| `improve_completed` | `akm improve`, end of a run | `strategy`, `plannedRefs`, per-mode and per-class action counts, memory-cleanup counts |
|
|
634
634
|
| `improve_failed` | `akm improve`, a run that crashed | `strategy`, `error` (redacted), `durationMs` |
|
|
635
|
-
| `improve_skipped` | `akm improve`: a ref, a lane, or a group of refs left out | `reason`: `no_new_signal`, `not_retrieved`, `distill_no_new_signal`, `budget_exhausted`, `budget_exhausted_batch`, `asset_missing_on_disk`, `strategy_filtered_all_passes`, `autonomy_gated`, `engine_unavailable`, `
|
|
635
|
+
| `improve_skipped` | `akm improve`: a ref, a lane, or a group of refs left out | `reason`: `no_new_signal`, `not_retrieved`, `distill_no_new_signal`, `budget_exhausted`, `budget_exhausted_batch`, `asset_missing_on_disk`, `strategy_filtered_all_passes`, `autonomy_gated`, `engine_unavailable`, `consolidation_no_memory_updates`, `below_min_new_sessions`, `derived_memory_reflect_skipped`, `memory_distill_requires_feedback`, `distill_flagged_wrong`, `distill_positive_without_reason`, `distill_deprecated_or_superseded`; with `count`, `remaining`, `strategy`, `lane` or `configKey` where they apply |
|
|
636
636
|
| `improve_lock_recovered` | `akm improve` reclaiming a stale run lock | `lockName`, `stalePid`, `lockedAt`, `recoveredAt`, `lockAgeMs`, `reason` |
|
|
637
637
|
| `improve_review_needed` | `akm feedback`, when a high-utility asset's utility drops below the review threshold | `previousUtility`, `nextUtility`, `reason` |
|
|
638
638
|
| `improve_reflect_outcome` | the improve loop, after each reflect call | `ok`, `durationMs`, `engine`, `reason` |
|
|
@@ -703,7 +703,7 @@ One line per memory belief-state transition: `{ appliedAt, ref, parentRef, fromS
|
|
|
703
703
|
|
|
704
704
|
All asset files live under `$STASH/` in type-specific subdirectories defined by the `PLACEMENT_SPECS` map in `src/core/asset/asset-placement.ts`:
|
|
705
705
|
|
|
706
|
-
The `workflows/` directory holds
|
|
706
|
+
The `workflows/` directory holds `.md` workflow sources. The
|
|
707
707
|
`tasks/` directory holds task source v4 `.yml` sources.
|
|
708
708
|
|
|
709
709
|
| Subdirectory | Asset Type | Format |
|
|
@@ -713,7 +713,7 @@ The `workflows/` directory holds peer `.md` and `.yml` workflow sources. The
|
|
|
713
713
|
| `agents/<name>.md` | agent | YAML-FM + Markdown |
|
|
714
714
|
| `knowledge/<name>.md` | knowledge | YAML-FM + Markdown |
|
|
715
715
|
| `instructions/<name>.md` | instruction | YAML-FM + Markdown |
|
|
716
|
-
| `workflows/<name>.md`
|
|
716
|
+
| `workflows/<name>.md` | workflow | Markdown source; compiles through source IR v1 |
|
|
717
717
|
| `scripts/<name>.<ext>` | script | sh / ts / js / ps1 etc. |
|
|
718
718
|
| `memories/<name>.md` | memory | YAML-FM + Markdown |
|
|
719
719
|
| `env/<name>.env` | env | `KEY=VALUE` pairs |
|
|
@@ -8,7 +8,16 @@ close each format is to that contract today.
|
|
|
8
8
|
|
|
9
9
|
## The contract
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**Version floor (0.10, #1091): 0.9.15.** A 0.10 reader owes data written by
|
|
12
|
+
0.9.15 or later, and nothing older. An install on an earlier release runs
|
|
13
|
+
`akm migrate apply` under akm 0.9.x first, then upgrades. A reader that meets a
|
|
14
|
+
shape older than the floor does not convert it: it refuses, with one message
|
|
15
|
+
naming `akm migrate apply` under akm 0.9.x (config: the retired
|
|
16
|
+
`stashDir`/`sources[]`/`installed[]` keys; `engines.*.extraParams` keys that
|
|
17
|
+
shadow a first-class field). A shape that 0.9.15 or later still wrote stays
|
|
18
|
+
readable; the rows below say which those are.
|
|
19
|
+
|
|
20
|
+
Above the floor, a reader must tolerate anything an earlier release wrote: convert the old
|
|
12
21
|
shape in memory, warn once, and name `akm migrate apply` as the on-disk
|
|
13
22
|
cleanup path — the migrator is where an explicit, backed-up rewrite happens,
|
|
14
23
|
never a precondition for reading. The only refusal a reader is allowed is data
|
|
@@ -27,11 +36,11 @@ and named once, round-trips through ordinary writes, and is dropped by
|
|
|
27
36
|
|
|
28
37
|
| Format | Where written | Version marker | Older data | Newer data | Gate |
|
|
29
38
|
| --- | --- | --- | --- | --- | --- |
|
|
30
|
-
| `config.json` | `src/core/config/config.ts` | `configVersion` field | `configVersion` is read, never gated on (`readConfigVersion`, `src/core/config/config.ts`): a missing field or `"0.9.0"` — the only value akm has shipped — loads silently, and any other value is named once and read as `0.9.0
|
|
39
|
+
| `config.json` | `src/core/config/config.ts` | `configVersion` field | `configVersion` is read, never gated on (`readConfigVersion`, `src/core/config/config.ts`): a missing field or `"0.9.0"` — the only value akm has shipped — loads silently, and any other value is named once and read as `0.9.0`. Below the 0.9.15 floor the file is refused, not converted: the retired `stashDir`/`sources[]`/`installed[]` layout fails validation (`AkmConfigSchema`, `src/core/config/config-schema.ts`) and an `extraParams` key that shadows a first-class engine field (`temperature`, `maxTokens`, `enableThinking`, `reasoningEffort`) is rejected by `validateExtraParams`, each telling the user to run `akm migrate apply` under akm 0.9.x or to set the field. A config with no `scheduler.enabled` (0.9.15 wrote none) is read as "keep what is installed": `akm task sync` adopts the akm-written scheduler rows as the list (`tests/integration/upgrade-rehearsal/`'s 0.9.15 origin). 0.9.16's `{kind, ref, sourceId}` `scheduler.enabled` entries are still read, as their `ref`, and written back as plain refs; `akm migrate apply`'s `configFile` step (`normalizeConfigFile`) persists that — `configVersion: "0.9.0"`, unknown keys dropped — to the file once, under a backup | Same as older: the value is named once and the file is read as `0.9.0`; there is no `UNSUPPORTED_CONFIG_VERSION` refusal. `akm health`'s `binary-config-skew` advisory (`src/commands/health/config-skew.ts`) is what says "a newer akm wrote this config, upgrade this install" | Upgrade rehearsal gate (`tests/integration/upgrade-rehearsal/`); `tests/config-v09.test.ts` |
|
|
31
40
|
| `state.db` | `src/core/state/migrations.ts` (append-only `MIGRATIONS` registry, applied by `src/storage/sqlite-migrations.ts`) | `schema_migrations` ledger table | `openStateDatabase` opens one connection (mkdir, open, standard pragmas), reads the ledger on it, and runs every migration not yet applied forward in one transaction; a missing/empty/table-less file is simply a fresh database. Before a migration that drops schema (`018-drop-dead-lane-schema`, `028-improve-ledger`; `STATE_MIGRATION_SAFETY_BY_ID`) runs against a database that already has migrations applied, the file is copied beside itself to `state.db.pre-<migration id>.bak` via `VACUUM INTO` on the same connection | An older binary opening a `state.db` migrated by a newer akm continues with the schema it knows and warns once (`warnNewerStateLedger`, `src/core/state-db.ts`); it does not refuse; only a ledger that diverges from this akm's registry is refused (`assertMigrationLedger`) | Upgrade rehearsal gate (`tests/integration/upgrade-rehearsal/`) |
|
|
32
41
|
| `index.db` | `src/storage/repositories/index-schema.ts` (`ensureSchema`; `index-entry-schema.ts` for the DDL and the layout constant) | `index_meta.version` = `CANONICAL_INDEX_DB_VERSION` (26), a layout marker | Readers (`openExistingDatabase` / `openReadonlyExistingDatabase`) serve it as-is and name `akm index` once (`checkIndexLayout`); the writable opener migrates in place — added columns via `ALTER TABLE`, a one-time FTS rebuild from `entries` for the layout-23 content-copy tables, and for layout 24 the drops of the sqlite-vec mirror `entries_vec` (when sqlite-vec loads; dropping a vec0 table needs it) and `entry_fragments_fts`, with `entries.search_text` hashed into `embed_hash` before the column is dropped so no vector is re-embedded, and for layout 25 the declared links (`asset_links`, #935) derived from each entry's stored `document_json` with no file read (only the directories holding workflows and tasks, whose targets no earlier layout stored, lose their incremental cursor and re-drain on the next `akm index`) — never dropping `embeddings`, `utility_scores*`, or `llm_enrichment_cache`. It drops the lazy-extraction queue `graph_extraction_queue`, retired in 0.9.17, and, on any layout, the LLM entity graph (`graph_meta`, `graph_files`, `graph_file_*`) and its `llm_enrichment_cache` rows, retired in 0.9.17-alpha.9 — an older release's `CREATE TABLE IF NOT EXISTS` recreates the graph tables (empty) if it ever opens this index again. It also deletes `llm_enrichment_cache` rows at the default `cache_variant` — the metadata-enhance pass, retired in 0.9.17-alpha.9 — on any layout; memory inference uses its own named variant and is unaffected. A migration leaves `index_meta.vacuumPending`, and the next `akm index` VACUUMs the freed pages. An `entries` table older than layout 21 has its entries-keyed tables recreated: one that lacks a column this release reads, or that still has a transitional column layout 21 removed (`entry_key`, `dir_path`, `stash_dir`, `entry_json`, `entry_type`), as the table 0.9.1 wrote does, with `document_json` empty on every row. A reader finds such a table unservable (`hasCurrentEntriesTable`), so a read rebuilds it inline. Only `SQLITE_CORRUPT` deletes and rebuilds the file (#865) | Refused by readers and the writable opener alike (`INDEX_SCHEMA_INCOMPATIBLE`, "Upgrade akm to use this index.", `newerIndexLayoutError`), leaving the file untouched: a newer layout may lack a column this akm reads, as layout 25 lacks `search_text` | `tests/integration/indexer/index-layout-migration.test.ts` (layout-23 and layout-24 fixtures); `tests/integration/previous-release-corpus.test.ts` (the layout-25 index 0.9.17-alpha.7 wrote, `index-v25.sql`, and the layout-20 index 0.9.1 wrote, `index-v20.sql`); `tests/integration/storage/index-generation-read-boundary.test.ts`; upgrade rehearsal gate (`tests/integration/upgrade-rehearsal/`) |
|
|
33
|
-
| Task source (`tasks/*.yml`) | `src/tasks/source/parse-task-source.ts` | `version: 4` (`TASK_SOURCE_V4_VERSION`) | **The named exception to the contract (#987): the runtime reads only v4.** `version: 2` or `version: 3` throws `TASK_SCHEMA_VERSION_UNSUPPORTED`, and a declared `version: 4` document whose `schedule[]` still carries 0.9.15's retired `enabled` key throws `TASK_SOURCE_INVALID`; both messages name `akm migrate apply`, the one place the conversion happens (`scripts/akm-migrate/migrate/task-files.ts`, planning every v2/v3/v4 file straight to v4 with the pure planner `
|
|
34
|
-
| Workflow IR (frozen plans) | `src/workflows/freeze/freeze.ts`, read back in `src/workflows/runtime/run-plan.ts` (`readRunPlan`, `decodeWorkflowPlan`) | `irVersion` (`WORKFLOW_PLAN_VERSION`, 6) on the plan and in `plan_ir_version`; `plan_hash` alongside | Every workflow compiles to one plan type. `decodeWorkflowPlan` reads the irVersion
|
|
42
|
+
| Task source (`tasks/*.yml`) | `src/tasks/source/parse-task-source.ts` | `version: 4` (`TASK_SOURCE_V4_VERSION`) | **The named exception to the contract (#987): the runtime reads only v4.** `version: 2` or `version: 3` throws `TASK_SCHEMA_VERSION_UNSUPPORTED`, and a declared `version: 4` document whose `schedule[]` still carries 0.9.15's retired `enabled` key throws `TASK_SOURCE_INVALID`; both messages name `akm migrate apply`, the one place the conversion happens (`scripts/akm-migrate/migrate/task-files.ts`, planning every v2/v3/v4 file straight to v4 with the pure planner `scripts/akm-migrate/migrate/task-to-v4.ts`, rewriting under a backup; `akm upgrade` runs it after an install). It covers every stash the runtime reads tasks from: each enabled configured bundle, and the stash `AKM_BUNDLE_DIR` selects when no bundle names it; the `akm-task` probe still recognizes a root of v2/v3 task files, so one without a recorded adapter is found. Every caller reports the refusal for that one file: `akm task sync` keeps reconciling every other task and leaves the file's installed row as it is | Any other `version` throws `TASK_SCHEMA_VERSION_UNSUPPORTED` naming `akm migrate apply` | Upgrade rehearsal gate (`tests/integration/upgrade-rehearsal/`); `tests/integration/previous-release-corpus.test.ts` (each older shape is refused at runtime and converted by the migrator) |
|
|
43
|
+
| Workflow IR (frozen plans) | `src/workflows/freeze/freeze.ts`, read back in `src/workflows/runtime/run-plan.ts` (`readRunPlan`, `decodeWorkflowPlan`) | `irVersion` (`WORKFLOW_PLAN_VERSION`, 6) on the plan and in `plan_ir_version`; `plan_hash` alongside | Every workflow compiles to one plan type. `decodeWorkflowPlan` reads the irVersion 5 shape 0.9.15 and 0.9.16 wrote (its `sourceReadSet` and host-identity fields included) as well as the current one, and keeps keys it does not know. Neither the version nor the hash gates a read: a stored plan that decodes runs whatever `irVersion` froze it, with one warning; one that cannot be decoded is abandoned by `akm workflow run` (status `failed`) with a message naming `akm workflow run <ref>` to start afresh — a status change, never an exception; `status`/`list`/`abandon` never read the plan | A newer akm's plan that still decodes runs the same way; one that does not decode is left untouched and refused with a message naming "Upgrade akm" (`readRunPlan`'s `newer`) | `tests/workflows/run-plan.test.ts`; `tests/integration/workflows/frozen-plan.test.ts` — the rehearsal builds no workflow run |
|
|
35
44
|
| Native scheduler rows (crontab, launchd plists, Task Scheduler) | `src/tasks/backends/cron.ts`, `launchd.ts`, `schtasks.ts`; the invocation grammar in `src/tasks/scheduler-invocation.ts` | The row's own invocation shape: current rows set their environment inline (a cron `VAR=value` prefix, a plist `EnvironmentVariables` entry, a PowerShell `$env:` assignment) — always `AKM_BUNDLE_DIR`, the syncing shell's working stash — and carry no `--scheduler-context`; 0.9.0 – 0.9.17-alpha.6 rows carry `--scheduler-context <descriptor>` holding the same values; older rows carry neither. A cron command over 1,000 bytes runs an akm wrapper script (`sh <log dir>/.akm-cron-wrapper-…sh`) that holds the same line | Every shape is listed and parsed (`parseScheduledInvocationArgv`; a spilled cron row from its wrapper script): a row inside akm's own `# akm:task` markers from before `--scheduler-context` (#881), and a `--scheduler-context` row, which keeps firing (the CLI applies its descriptor, below) until the next plain `akm task sync` rewrites it in place — an update that keeps the row's launcher and schedule, never an add or remove. The primary bundle proves a row by the `AKM_BUNDLE_DIR` it carries, inline or in its descriptor (#846); any other bundle owns rows by name. Rows that still carry the pre-0.9.17 workflow execution-evidence marker (`# akm:workflow-evidence` in the crontab, an `akm-workflow-evidence` plist comment or PowerShell literal) are listed like any other and rewritten once without it. Plain `akm task sync` keeps an installed row's own launcher (`installOptionsFor`, `src/tasks/scheduler-sync.ts`) and recomputes its environment; `akm task sync --rebind` repoints the launcher | A row inside akm's markers, `com.akm.task.` label namespace, or `\akm\` task folder whose argv this binary cannot parse (for example one a newer akm wrote) is not listed: sync leaves it alone unless an enabled source renders a row with the same native id, which then replaces it — the row is derived state and its source is the record. A crontab whose akm markers are malformed is refused unmodified (`parseBlocks`, `cron.ts`) | Upgrade rehearsal gate (`tests/integration/upgrade-rehearsal/`: the previous release's `--scheduler-context` rows fire under the candidate, then `task sync --dry-run` shows them only as updates); `tests/tasks-sync.test.ts` (`--scheduler-context` rows and spilled rows are updates, never adds) |
|
|
36
45
|
| Scheduler-context descriptor (`$DATA/tasks/context/<sha256>.json`, written by 0.9.0 – 0.9.17-alpha.6) | No longer written: a row carries its own environment (#987). Read by `src/tasks/scheduler-invocation.ts` (`readLegacySchedulerContext`) | `version: 1`; the environment key set | When a row that names one fires, the CLI reads the file as plain JSON and applies its `AKM_*_DIR` keys and, in one written before 0.9.17, `PATH`; nothing else about the file (name, mode, owner, link) is checked. Sync reads its `AKM_BUNDLE_DIR` to attribute the row. A plain `akm task sync` that reconciles the row rewrites it without the argument; a row a sync leaves as it is (its source failed, a `--bundle` sync did not cover it) keeps naming the file | A key this binary does not know is ignored. A file that is gone or is not JSON fails the run with `INVALID_CONFIG_FILE` naming `akm task sync`; sync cannot attribute such a row to the primary bundle and leaves it in place, and `akm task prune` reports it as `invalid-context` | `tests/tasks-scheduler-invocation.test.ts`; `tests/integration/scheduler-context-launcher.test.ts`; upgrade rehearsal gate (`tests/integration/upgrade-rehearsal/`) fires the previous release's rows under the candidate before and after its plain `task sync` |
|
|
37
46
|
| Proposal `metadata_json` | `src/storage/repositories/proposals-repository.ts` | No explicit version field; presence/absence of the `changes` key | Rows from before the `changes` key existed (~89% of archived rows on real installs) are treated as a known legacy gap — decoded with an empty change list rather than thrown (`proposals-repository.ts:47-56`). 0.9.17-alpha.9 adds a consolidate pair-pass `retire` proposal's `changes[0].op: "delete"` (no `after`, already a valid `FileChangeOp`) and its `retirement` / `retiredArchive` / `promotionSource` / `promotionSourceHash` metadata keys, plus the retirement continuity check's `retirement.continuityRisk` (rule R3, item 1) — a person can accept a proposal carrying it by id even though it is excluded from bulk accept; an older reader's `validatePresentMetadata` does not enumerate these keys, so it neither inspects nor rejects them — the row decodes with them silently absent, same as any other field an older release predates. 0.9.19 adds `reviewHistory` (the rejections `akm proposal reopen` undid, oldest first, each with its gate verdict) the same way: a proposal reopened by 0.9.19 and read by an older release is an ordinary pending proposal with its history absent, and that release drops the key if it rewrites the row. The quality judge's evidence, `scores` and `judgeReason`, is added inside the existing `gateDecision` object (Unreleased): an older reader's `validatePresentMetadata` checks only the gate fields it knows and carries the object through whole, so the evidence survives a rewrite by an older release unread. An older release also counts a pending proposal's age (retention expiry, `--older-than`) from `createdAt`, so after a downgrade a reopened proposal can expire at the next `akm improve` run (a retire proposal never expires), or be swept by a scheduled `--older-than` bulk action or drain | 0.9.17-alpha.8 and earlier predate the retire proposal shape entirely — they were never taught to read a delete-primary change with no `after`. `akm proposal show` / `diff` / `drain` exit 70 on one, and drain's own nightly pre-pass failing on the first pending retire proposal it meets stops that run's auto-promotion for the whole stash, not just that one proposal. **Downgrade gate:** every pending retire proposal must be accepted or rejected (`akm proposal accept` / `reject`) before downgrading to 0.9.17-alpha.8 or earlier — once decided it is archived, out of the pending set `show`/`diff`/`drain` iterate, and no longer trips this. **Gap** otherwise (no code-level guard; this is operator guidance only). Downgrading also revives the starvation the second review round's B1 fixed forward-only: 0.9.17-alpha.8's `retrieval-scope.ts` counts a `consolidate-pair` ledger row as processed, so the pair pass's own nightly attempts crowd new material back out of every other improve lane's scope, the same way they did before B1 — measured on the real bundle, two alpha.9 nights left only 341 of 2,183 new-only assets still in scope once read under alpha.8. **Gap** here too (the ledger `source` string carries no version of its own; operator guidance only — do not downgrade across a pair-pass run without expecting this). | `tests/proposal-repository-pure.test.ts` — unit only; the rehearsal builds no proposal |
|
|
@@ -34,7 +34,7 @@ removing a half-built surface over shipping it behind a label.
|
|
|
34
34
|
| D9 `--auto-accept` warn-and-ignore | **Shipped** (warns, and no longer poisons the scope positional) |
|
|
35
35
|
| D10 extract migration machinery | Partial (`akm-migrate` bin exists; code still in-repo) |
|
|
36
36
|
| D11 OKF foundational | Partial (the `okf` adapter has landed) |
|
|
37
|
-
| D12 `placeNew()` wiring | **
|
|
37
|
+
| D12 `placeNew()` wiring | **Dropped in 0.10** (method removed; see [#1163](https://github.com/itlackey/akm/issues/1163)) |
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
@@ -491,7 +491,11 @@ without changing AKM-native refs or classification.
|
|
|
491
491
|
|
|
492
492
|
## D12 — `BundleAdapter.placeNew()` stays unwired until 0.10
|
|
493
493
|
|
|
494
|
-
**Status:
|
|
494
|
+
**Status: DROPPED in 0.10 (owner decision 2026-10-10).** `placeNew()` and its
|
|
495
|
+
implementations were removed; nothing ever called them. Restoring per-adapter
|
|
496
|
+
placement is only needed for writable bundles in a non-akm layout, tracked in
|
|
497
|
+
[#1163](https://github.com/itlackey/akm/issues/1163). The text below is the
|
|
498
|
+
0.9.0 record. The interface declared `placeNew(c, conceptId)`
|
|
495
499
|
OPTIONAL (`src/core/adapter/bundle-adapter.ts`), and 8 of the built-in adapter
|
|
496
500
|
modules already implement it — `generic-files`, `akm`, `llm-wiki`,
|
|
497
501
|
`agent-skills`, `dotenv`, `akm-workflow`, `akm-task`, and the shared
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
> `scripts/refresh-canary-set.ts` were deleted with the improve ledger change
|
|
6
6
|
> (migration 028 drops the tables); recorded telemetry shows no alert ever fired. The
|
|
7
7
|
> generation and lexical-diversity merge checks, which never refused a merge,
|
|
8
|
-
> went with it
|
|
9
|
-
> `
|
|
8
|
+
> went with it, and so did the random-cluster injection
|
|
9
|
+
> (`consolidate.antiCollapse`, removed in 0.10, #1131). The history below is kept
|
|
10
10
|
> for reference.
|
|
11
11
|
>
|
|
12
12
|
> **Earlier status:** Partially implemented. The COLLAPSE alert class (§1, three
|
|
@@ -121,7 +121,7 @@ steps:
|
|
|
121
121
|
map:
|
|
122
122
|
over: steps.intake.output.issues
|
|
123
123
|
concurrency: 3
|
|
124
|
-
unit: {
|
|
124
|
+
unit: { retry: { max: 2, on: [timeout] } }
|
|
125
125
|
# `output` describes the REDUCER RESULT: the default `collect` reducer
|
|
126
126
|
# folds per-item unit results into an array.
|
|
127
127
|
output: { type: array }
|
|
@@ -131,11 +131,6 @@ steps:
|
|
|
131
131
|
- id: verdict
|
|
132
132
|
inputs: [steps.implement.output]
|
|
133
133
|
output: { type: object }
|
|
134
|
-
- id: pick-outcome
|
|
135
|
-
route:
|
|
136
|
-
input: steps.verdict.output.status
|
|
137
|
-
when: [{ match: clean, step: announce }]
|
|
138
|
-
default: escalate # both targets are LATER steps — routes are forward-only
|
|
139
134
|
- id: escalate
|
|
140
135
|
inputs: [steps.verdict.output]
|
|
141
136
|
- id: announce
|
|
@@ -231,13 +231,12 @@ akm() { bun "$REPO/src/cli.ts" "$@"; }
|
|
|
231
231
|
|
|
232
232
|
### 3.2 Verify isolation before mutation
|
|
233
233
|
|
|
234
|
-
`
|
|
235
|
-
exists.
|
|
234
|
+
`info` is read-only and works before config exists.
|
|
236
235
|
|
|
237
236
|
```sh
|
|
238
|
-
akm
|
|
237
|
+
akm info --format json >"$AKM_SANDBOX/paths.json"
|
|
239
238
|
jq -e --arg root "$AKM_SANDBOX/" \
|
|
240
|
-
'
|
|
239
|
+
'[.bundleDir, .configDir, .dataDir, .cacheDir, .stateDir] | all(startswith($root))' \
|
|
241
240
|
"$AKM_SANDBOX/paths.json"
|
|
242
241
|
```
|
|
243
242
|
|
|
@@ -370,7 +369,7 @@ Copy this only after exact ranking assertions:
|
|
|
370
369
|
cp -R "$REPO/tests/fixtures/manual-qa/bundle/." "$AKM_BUNDLE_DIR/"
|
|
371
370
|
akm index
|
|
372
371
|
akm show knowledge/qa-guide | jq -e '.name == "qa-guide"'
|
|
373
|
-
akm show workflows/typed-
|
|
372
|
+
akm show workflows/typed-params | jq -e '.type == "workflow"'
|
|
374
373
|
akm show tasks/manual-success | jq -e '.type == "task"'
|
|
375
374
|
```
|
|
376
375
|
|
|
@@ -536,7 +535,7 @@ for command in \
|
|
|
536
535
|
or `propose`.
|
|
537
536
|
- [ ] **[CORE]** Bare `akm` and `akm help` print the sectioned overview without
|
|
538
537
|
reading or rewriting invalid config.
|
|
539
|
-
- [ ] **[CORE]** `
|
|
538
|
+
- [ ] **[CORE]** `hints` and
|
|
540
539
|
`hints --detail brief` are nonempty and have the expected relative detail.
|
|
541
540
|
- [ ] **[LOCAL]** `help bundle|env|secret|workflow|task|proposal` agrees with the
|
|
542
541
|
corresponding `--help` command tree.
|
|
@@ -598,9 +597,8 @@ test ! -s "$AKM_SANDBOX/silent.out"
|
|
|
598
597
|
never materialize values.
|
|
599
598
|
- [ ] **[LOCAL]** Concurrent independent `config set` processes preserve both
|
|
600
599
|
changes or one fails cleanly; JSON stays valid and no temp file remains.
|
|
601
|
-
- [ ] **[LOCAL]** `config path
|
|
602
|
-
|
|
603
|
-
must warn explicitly. Silent ignoring is a failure.
|
|
600
|
+
- [ ] **[LOCAL]** Bare `config path` is a raw path primitive; if format/output
|
|
601
|
+
are ignored it must warn explicitly. Silent ignoring is a failure.
|
|
604
602
|
|
|
605
603
|
### 6.5 Help migration notes
|
|
606
604
|
|
|
@@ -810,9 +808,9 @@ grep -qi '<html' "$AKM_SANDBOX/info.html"
|
|
|
810
808
|
### 8.3 Shape, detail, and output destination
|
|
811
809
|
|
|
812
810
|
- [ ] **[CORE]** Brief/normal/full increase detail without identity drift.
|
|
813
|
-
- [ ] **[CORE]**
|
|
814
|
-
before side effects
|
|
815
|
-
- [ ] **[LOCAL]**
|
|
811
|
+
- [ ] **[CORE]** `--shape` is an unknown flag on every command: it exits `2`,
|
|
812
|
+
`UNKNOWN_FLAG`, before side effects.
|
|
813
|
+
- [ ] **[LOCAL]** `--detail agent` keeps action fields and strips non-action metadata.
|
|
816
814
|
- [ ] **[LOCAL]** `show --format md --output <file>` writes file, empty stdout.
|
|
817
815
|
- [ ] **[LOCAL]** Output replacement is atomic; unwritable/directory target does
|
|
818
816
|
not truncate existing content.
|
|
@@ -837,7 +835,7 @@ expect_error 1 ASSET_NOT_FOUND show skills/does-not-exist
|
|
|
837
835
|
expect_error 2 UNKNOWN_FLAG info --totally-bogus
|
|
838
836
|
expect_error 2 INVALID_FORMAT_VALUE info --format xml
|
|
839
837
|
expect_error 2 INVALID_DETAIL_VALUE info --detail maximum
|
|
840
|
-
expect_error 2
|
|
838
|
+
expect_error 2 UNKNOWN_FLAG search docker --shape agent
|
|
841
839
|
expect_error 2 MISSING_REQUIRED_ARGUMENT help migrate
|
|
842
840
|
expect_error 2 INVALID_FLAG_VALUE completions --shell zsh
|
|
843
841
|
```
|
|
@@ -1618,7 +1616,7 @@ akm lint --type workflows --fail-on-flagged
|
|
|
1618
1616
|
|
|
1619
1617
|
- [ ] **CORE** Create-print emits raw valid Markdown and writes nothing.
|
|
1620
1618
|
- [ ] **CORE** Create-from writes/indexes valid workflow with preamble and exact sections.
|
|
1621
|
-
- [ ] **LOCAL** Flat name plus safe path creates hierarchy; slash/traversal/duplicate step/missing section/
|
|
1619
|
+
- [ ] **LOCAL** Flat name plus safe path creates hierarchy; slash/traversal/duplicate step/missing section/invalid params fail before write.
|
|
1622
1620
|
- [ ] **LOCAL** Existing workflow requires force plus from/reset; force alone fails.
|
|
1623
1621
|
- [ ] **LOCAL** Lint catches structure without rewriting valid prose.
|
|
1624
1622
|
- [ ] **CORE** A schema keyword outside the enforced subset (`format`, `pattern`,
|
|
@@ -1638,11 +1636,11 @@ akm lint --type workflows --fail-on-flagged
|
|
|
1638
1636
|
|
|
1639
1637
|
### 14.2 Typed params and partial run without an engine call
|
|
1640
1638
|
|
|
1641
|
-
The `typed-
|
|
1639
|
+
The `typed-params` fixture's first step is an exec unit (no engine). `--max-steps 1`
|
|
1642
1640
|
tests parameter parsing and durable run creation without agent/LLM dispatch.
|
|
1643
1641
|
|
|
1644
1642
|
```sh
|
|
1645
|
-
akm workflow run workflows/typed-
|
|
1643
|
+
akm workflow run workflows/typed-params \
|
|
1646
1644
|
--include_processes=true --count 2 \
|
|
1647
1645
|
--labels api --labels worker --max-steps 1 \
|
|
1648
1646
|
> "$AKM_SANDBOX/typed-run.json"
|
|
@@ -1664,7 +1662,7 @@ jq -e '
|
|
|
1664
1662
|
- [ ] **LOCAL** Params supplied to active run fail because creation-only.
|
|
1665
1663
|
- [ ] **LOCAL** Invalid max-steps values fail; bounded partial exits `0`, remains active.
|
|
1666
1664
|
- [ ] **LOCAL** `--max-steps` counts **finished spine steps**: a step's whole
|
|
1667
|
-
bounded gate loop counts as one
|
|
1665
|
+
bounded gate loop counts as one.
|
|
1668
1666
|
It does not bound the dispatches inside a single step's gate loop — pair
|
|
1669
1667
|
it with `budget.max_units` when that is what you need capped.
|
|
1670
1668
|
|
|
@@ -1672,8 +1670,8 @@ jq -e '
|
|
|
1672
1670
|
|
|
1673
1671
|
```sh
|
|
1674
1672
|
akm workflow status "$QA_RUN_ID"
|
|
1675
|
-
akm workflow status workflows/typed-
|
|
1676
|
-
akm workflow list --active --ref workflows/typed-
|
|
1673
|
+
akm workflow status workflows/typed-params
|
|
1674
|
+
akm workflow list --active --ref workflows/typed-params
|
|
1677
1675
|
akm workflow status "$QA_RUN_ID" --units
|
|
1678
1676
|
akm workflow abandon "$QA_RUN_ID"
|
|
1679
1677
|
akm workflow resume "$QA_RUN_ID"
|
|
@@ -1826,7 +1824,7 @@ Environment scope and context:
|
|
|
1826
1824
|
**before** the spawn, naming the variable, rather than surfacing a raw
|
|
1827
1825
|
`E2BIG`.
|
|
1828
1826
|
|
|
1829
|
-
`cwd
|
|
1827
|
+
`cwd`:
|
|
1830
1828
|
|
|
1831
1829
|
- [ ] **LOCAL** `cwd` is relative and contained: absolute paths, drive letters,
|
|
1832
1830
|
`~`, and `..` **segments** are rejected by the parser *and* the
|
|
@@ -1834,13 +1832,6 @@ Environment scope and context:
|
|
|
1834
1832
|
base (symlinks included) immediately before the spawn.
|
|
1835
1833
|
- [ ] **LOCAL** A directory whose *name* merely begins with dots (`..data`) is a
|
|
1836
1834
|
legal contained `cwd` and must **not** fail `exec_cwd_escape`.
|
|
1837
|
-
- [ ] **LOCAL** Under `isolation: worktree` each unit gets a fresh detached
|
|
1838
|
-
worktree; a clean one is gone once the step resolves, a dirty one is
|
|
1839
|
-
retained and its path logged.
|
|
1840
|
-
- [ ] **LOCAL** When a dirty leftover is moved aside and the worktree then fails
|
|
1841
|
-
to mint, the failure still reports **where the preserved work went**.
|
|
1842
|
-
- [ ] **DESTRUCTIVE** The stale-worktree sweep removes abandoned trees after
|
|
1843
|
-
seven days but leaves a tree that is still in use by a live run.
|
|
1844
1835
|
|
|
1845
1836
|
Gates, retry, and reuse:
|
|
1846
1837
|
|
|
@@ -2196,7 +2187,7 @@ akm improve skills/k8s-deploy \
|
|
|
2196
2187
|
- [ ] **AI** Lock contention without skip is a transient error, exit `75` (`IMPROVE_LOCK_HELD`); `--skip-if-locked` exits `0`, reports `skipped.reason:"lock-held"`, and emits no `improve_invoked`.
|
|
2197
2188
|
- [ ] **AI** Stale lock is reclaimed with an observable recovery event; active lock is never stolen.
|
|
2198
2189
|
- [ ] **AI** Timeout/SIGINT/SIGTERM/SIGHUP persist one terminated run with redacted reason and release locks/children.
|
|
2199
|
-
- [ ] **AI** Default/
|
|
2190
|
+
- [ ] **AI** Default/consolidate/proactive-maintenance strategies enable exactly documented processes. Autonomy-gated mutations remain off without explicit experimental opt-in.
|
|
2200
2191
|
- [ ] **AI** No sync/push occurs under explicit flags; git publication is tested separately only against disposable remote.
|
|
2201
2192
|
- [ ] **AI** Credential/prompt/session values are absent from improve result, state DB, proposal provenance, health report, event stream, and logs.
|
|
2202
2193
|
|
|
@@ -3073,7 +3064,7 @@ and not a substitute for the full check.
|
|
|
3073
3064
|
| Sources/registry/write-source | provider/write/publication suites, controlled service; LIVE git/npm/HTTPS when lifecycle changed |
|
|
3074
3065
|
| Storage/migration/transactions | crash/concurrency/property/published-upgrade gates, section 19, destructive rehearsal for cutover changes |
|
|
3075
3066
|
| Workflow | workflow unit/integration, gate fake agents, slow expansion, crash/contention when scheduler changed |
|
|
3076
|
-
| Workflow exec units / subprocess capture | section 14.5 end to end on an engine-less install
|
|
3067
|
+
| Workflow exec units / subprocess capture | section 14.5 end to end on an engine-less install; any capture, timeout, or process-group change also runs the agent spawn suites, which share that subprocess layer |
|
|
3077
3068
|
| Workflow child environment / allowlist | section 14.5 environment gates plus section 11; a change to the shared floor is native Windows, not Linux emulation |
|
|
3078
3069
|
| Task/scheduler | task suites, Linux standalone; native macOS/Windows for backend/quoting/binding; published upgrade for schema changes |
|
|
3079
3070
|
| Env/secret/security path/archive/network | env/secret plus traversal/SSRF/archive/redaction/dangerous-key suites, section 20 |
|