akm-cli 0.9.18 → 0.9.19-alpha.1
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 +135 -0
- package/STABILITY.md +2 -1
- package/dist/assets/hints/cli-hints-full.md +4 -2
- package/dist/assets/hints/cli-hints-short.md +5 -3
- package/dist/assets/prompts/reflect-feedback-framing.md +1 -1
- package/dist/commands/feedback-cli.js +1 -1
- package/dist/commands/improve/consolidate/coverage.js +132 -0
- package/dist/commands/improve/consolidate/pair-pass.js +30 -20
- package/dist/commands/improve/consolidate.js +43 -10
- package/dist/commands/improve/distill.js +7 -3
- package/dist/commands/improve/eligibility.js +39 -9
- package/dist/commands/improve/improve-cli.js +9 -6
- package/dist/commands/improve/improve.js +13 -4
- package/dist/commands/improve/ledger.js +2 -2
- package/dist/commands/improve/loop-stages.js +2 -0
- package/dist/commands/improve/preparation.js +1 -1
- package/dist/commands/improve/reflect.js +1 -1
- package/dist/commands/improve/stage.js +38 -9
- package/dist/commands/proposal/diff-format.js +21 -0
- package/dist/commands/proposal/proposal-cli.js +48 -10
- package/dist/commands/proposal/proposal-types.js +11 -0
- package/dist/commands/proposal/proposal.js +60 -5
- package/dist/commands/proposal/repository.js +245 -17
- package/dist/commands/read/knowledge.js +13 -11
- package/dist/commands/read/remember-cli.js +7 -3
- package/dist/commands/sources/source-clone.js +1 -1
- package/dist/commands/tasks/tasks-cli.js +1 -1
- package/dist/commands/tasks/tasks.js +10 -3
- package/dist/core/mutation-target.js +8 -3
- package/dist/core/write-source.js +3 -2
- package/dist/indexer/usage/usage-events.js +2 -1
- package/dist/output/shapes/helpers.js +7 -0
- package/dist/output/shapes/passthrough.js +1 -0
- package/dist/output/shapes/proposal/reopen.js +14 -0
- package/dist/output/shapes.js +2 -0
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/proposal/proposal.js +3 -1
- package/dist/output/text/proposal-format.js +87 -32
- package/dist/scripts/akm-migrate-node.js +79 -23
- package/dist/scripts/akm-migrate.js +79 -23
- package/dist/storage/repositories/improve-ledger-repository.js +65 -6
- package/dist/storage/repositories/index-vec-repository.js +13 -8
- package/dist/storage/repositories/proposals-repository.js +23 -0
- package/dist/tasks/run/load-task.js +5 -1
- package/docs/migration/README.md +1 -0
- package/docs/migration/release-notes/0.9.19.md +134 -0
- package/docs/migration/release-notes/README.md +5 -0
- package/docs/migration/v0.8-to-v0.9.md +5 -1
- package/docs/reference/cli.md +189 -28
- package/docs/reference/configuration.md +9 -8
- package/docs/reference/data-and-telemetry.md +19 -14
- package/package.json +1 -1
package/docs/reference/cli.md
CHANGED
|
@@ -1610,7 +1610,7 @@ akm feedback skills/code-review --negative --reason "flaky" --tag slice:train --
|
|
|
1610
1610
|
| --- | --- |
|
|
1611
1611
|
| `--positive` | Record positive feedback (use when an asset was helpful) |
|
|
1612
1612
|
| `--negative` | Record negative feedback (use when an asset was not useful) |
|
|
1613
|
-
| `--reason` |
|
|
1613
|
+
| `--reason` | What was wrong with (or right about) the asset's content; not for `akm` command errors. Attached to the feedback event (required for negative feedback by default) |
|
|
1614
1614
|
| `--failure-mode` | Structured failure-mode taxonomy for negative feedback: `incorrect`, `outdated`, `dangerous`, `incomplete`, `redundant`. Stored alongside `--reason` in event metadata for the distill pipeline. |
|
|
1615
1615
|
| `--tag` | Tag to attach to the feedback (repeatable, e.g. `--tag slice:train --tag team:platform`) |
|
|
1616
1616
|
| `--applied-to <ref>` | Credit a `lessons/<name>` lesson that helped resolve this task. When combined with `--positive`, appends this feedback ref to the target lesson's `lessonStrength[]` frontmatter array (dedup, idempotent). A non-lesson target, or a missing `--positive`, produces a warning rather than silently doing nothing. |
|
|
@@ -2429,10 +2429,10 @@ akm improve report --since 7d # ...aggregated over every real run start
|
|
|
2429
2429
|
| `--task` | Optional extra guidance for this improvement pass |
|
|
2430
2430
|
| `--dry-run` | Show the schema-v2 result on stdout without creating config, data, state, cache, bundle, log, or result artifacts. Dry-run results are never persisted, including on errors or signals. |
|
|
2431
2431
|
| `--plan` | Alias for `--dry-run` (#947). Sets the exact same internal flag; no separate code path. Prefer this spelling when the goal is previewing `plan.processes` (resolved process -> engine -> model routing) rather than checking what would be written. |
|
|
2432
|
-
| `--bundle` | Select the
|
|
2433
|
-
| `--limit <n>` |
|
|
2432
|
+
| `--bundle` | Select the bundle the run improves and writes to (default: `defaultWriteTarget`, else the working bundle); only that bundle's assets are planned. When the ref scope is bundle-qualified, it must name the same bundle |
|
|
2433
|
+
| `--limit <n>` | Cap the refs the run processes, highest salience first (refs routed to distill only come last). Overrides the strategy's `processes.reflect.limit` and `limit` |
|
|
2434
2434
|
| `--timeout-ms <ms>` | Wall-clock budget for the run (default: `7200000` = 2 hours) |
|
|
2435
|
-
| `--require-feedback-signal` | Only process assets with recent feedback signals |
|
|
2435
|
+
| `--require-feedback-signal` | Only process assets with recent feedback signals: turns the fallback lanes (high salience, proactive maintenance) off for the run |
|
|
2436
2436
|
| `--strategy <name>` | Override the active improve strategy (a built-in or entry under `improve.strategies`) |
|
|
2437
2437
|
| `--json-to-stdout` | Also emit the full persisted JSON result on stdout for a live run. Without this flag, stdout stays empty. Dry-runs always emit their result and are never persisted. |
|
|
2438
2438
|
| `--skip-if-locked` | If another improve run already holds the lock, skip gracefully (exit 0) instead of failing with "already running" (exit 75, `TransientError`, code `IMPROVE_LOCK_HELD` — field follow-up to #948: two legitimate `improve` invocations colliding on this lock is ordinary, retryable contention, not a broken config file). Use for high-frequency scheduled runs so they don't pile up failures while a longer run is in progress. |
|
|
@@ -2446,6 +2446,17 @@ ref-scoped improvement. It owns the memory-cleanup and lesson-distillation
|
|
|
2446
2446
|
flow. A qualified scope such as `team//skills/code-review` selects that bundle;
|
|
2447
2447
|
a different explicit `--bundle` is a usage error.
|
|
2448
2448
|
|
|
2449
|
+
A run improves one bundle, the one it writes to, and plans only that bundle's
|
|
2450
|
+
assets: an asset that lives in another bundle is left alone even when that
|
|
2451
|
+
bundle is writable, and a bare ref scope (`akm improve skills/x`) resolves
|
|
2452
|
+
inside the write target only. To improve another bundle, name it
|
|
2453
|
+
(`akm improve --bundle team`, or `akm improve team//skills/code-review`). A
|
|
2454
|
+
scheduled `akm improve` therefore covers only its write target: schedule one
|
|
2455
|
+
`akm improve --bundle <name>` run per other bundle. `--dry-run` and `--plan`
|
|
2456
|
+
resolve the bundle the way a live run does (the working bundle starts from
|
|
2457
|
+
`AKM_BUNDLE_DIR`, then `defaultBundle`), so they preview the bundle a live run
|
|
2458
|
+
improves.
|
|
2459
|
+
|
|
2449
2460
|
Every stage records what it did with each asset in the improve ledger
|
|
2450
2461
|
(`improve_ledger` in `state.db`) and reads it before any model call: an asset
|
|
2451
2462
|
whose proposal was rejected waits 14 days (reflect), 30 days (distill) or 7
|
|
@@ -2453,10 +2464,25 @@ days (other stages) before it is tried again; an expired proposal waits one
|
|
|
2453
2464
|
day; an asset a stage looked at and left unchanged is revisited after 7 days,
|
|
2454
2465
|
or as soon as new feedback (or, for consolidation, an edit) arrives.
|
|
2455
2466
|
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2467
|
+
Consolidation's promotion of a memory into `knowledge/` is the exception to the
|
|
2468
|
+
7-day rule: once a promotion is accepted or rejected, its memory is not offered
|
|
2469
|
+
to the model again until its body changes, however long that takes. The ledger
|
|
2470
|
+
records the body hash the promotion was decided against and compares it with
|
|
2471
|
+
the memory's current body (frontmatter edits do not count), the same
|
|
2472
|
+
content-driven rule the consolidate pair pass uses. A promotion decided by an
|
|
2473
|
+
older release, which recorded no hash, keeps the old windows. Consolidation
|
|
2474
|
+
also does not promote a memory that `knowledge/` already covers: before it
|
|
2475
|
+
queues a promotion it compares the memory with the 20 `knowledge/` docs in its
|
|
2476
|
+
bundle nearest to it by stored vector, and skips the memory when one of them
|
|
2477
|
+
holds at least half of its distinct 5-word shingles (skip reason
|
|
2478
|
+
`dedup_covered_by_knowledge` in the result's `consolidation.skipReasons`). A
|
|
2479
|
+
covering doc that ranks lower than the 20th nearest goes unseen. With no stored
|
|
2480
|
+
vector (semantic search off, or the memory not indexed yet) that check does
|
|
2481
|
+
nothing and the exact slug and whole-body checks still apply.
|
|
2482
|
+
|
|
2483
|
+
No built-in strategy turns the improve-stage extract process on, and only
|
|
2484
|
+
`proactive-maintenance` turns proactive maintenance on. Use that strategy or
|
|
2485
|
+
set the selected strategy's process `enabled: true` to opt in. The stage toggle does not disable a direct
|
|
2460
2486
|
`akm proposal extract --type <harness>` or `akm proposal extract --auto`
|
|
2461
2487
|
invocation.
|
|
2462
2488
|
|
|
@@ -2464,9 +2490,10 @@ The maintenance pass run by `improve` also expires stale proposals: any pending
|
|
|
2464
2490
|
proposal older than the top-level `archiveRetentionDays` config key (default
|
|
2465
2491
|
**90**, not `improve.archiveRetentionDays`) is moved to the archive with the
|
|
2466
2492
|
reason `expired: no action within retention window` and a `proposal_expired`
|
|
2467
|
-
event is emitted
|
|
2468
|
-
|
|
2469
|
-
|
|
2493
|
+
event is emitted (a proposal put back by `akm proposal reopen` is counted
|
|
2494
|
+
from the reopen, not its original creation). Set `archiveRetentionDays` to `0`
|
|
2495
|
+
to disable expiration entirely. The total expired count surfaces in the improve
|
|
2496
|
+
result as `proposalsExpired`.
|
|
2470
2497
|
|
|
2471
2498
|
`improve` never promotes proposals on its own — there is no confidence gate.
|
|
2472
2499
|
Every generated proposal lands in the queue with a `pending` status
|
|
@@ -2475,9 +2502,17 @@ the drain engine. Reflect still emits a `confidence` score (0..1) in its JSON
|
|
|
2475
2502
|
response schema; it is recorded on the proposal for triage and ranking, but no
|
|
2476
2503
|
threshold auto-accepts anything.
|
|
2477
2504
|
|
|
2478
|
-
Selection
|
|
2479
|
-
|
|
2480
|
-
|
|
2505
|
+
Selection picks the refs with feedback (a signal or a note, in the last 30
|
|
2506
|
+
days) newer than the stage's last ledger attempt. Two fallback lanes add refs
|
|
2507
|
+
with no such feedback: high salience (content-scored refs at or above
|
|
2508
|
+
`improve.salience.salienceThreshold`, default `0.75`, that were never reflected,
|
|
2509
|
+
capped at 10% of the limit, at least one ref) and, in a strategy that enables
|
|
2510
|
+
`proactiveMaintenance`, refs due for a revisit. Both pick only refs in the
|
|
2511
|
+
[retrieval scope](https://github.com/itlackey/akm/blob/main/docs/architecture/improvement.md#retrieval-scope): returned by
|
|
2512
|
+
`search`, `curate` or `show`, or named by feedback, in the last 90 days, or new
|
|
2513
|
+
material no improve stage has processed. The picks are ranked by salience and
|
|
2514
|
+
cut to the limit; an explicit ref scope bypasses every gate. Use
|
|
2515
|
+
`--require-feedback-signal` to turn the fallback lanes off for the run.
|
|
2481
2516
|
|
|
2482
2517
|
When the active strategy enables a process (or the triage judgment engine)
|
|
2483
2518
|
whose engine or credential cannot be resolved in this process's environment,
|
|
@@ -2514,9 +2549,9 @@ ref in the requested scope. The `plan` object preserves both views: raw scope
|
|
|
2514
2549
|
size and per-gate removals, configured and effective caps, final ranked refs
|
|
2515
2550
|
and their selection lanes, proactive and consolidation statistics, stage
|
|
2516
2551
|
decisions, triage mode/caps, and `snapshot.status`/`snapshot.reason` for the
|
|
2517
|
-
read-side index boundary. `limits.effective` is the
|
|
2518
|
-
`limits.additiveReplayAllowance` is
|
|
2519
|
-
`limits.totalCeiling`
|
|
2552
|
+
read-side index boundary. `limits.effective` is the cap on the refs the run
|
|
2553
|
+
dispatches; the replay lane is retired, so `limits.additiveReplayAllowance` is
|
|
2554
|
+
always `0` and `limits.totalCeiling` equals the cap (omitted when the run is
|
|
2520
2555
|
unbounded). A missing or incompatible index is an explicit empty snapshot and
|
|
2521
2556
|
is not created or migrated. `plan.mode` is `estimate` and `plan.dispatch` is
|
|
2522
2557
|
`false`; live JSON results use the same projection with `mode: "execution"`.
|
|
@@ -2587,7 +2622,8 @@ which never make an attributable LLM call themselves) the active strategy
|
|
|
2587
2622
|
enabled but that ended the run with zero calls, each with a `reason` drawn
|
|
2588
2623
|
from the existing skip-reason vocabulary: `"engine_unavailable"` (also in
|
|
2589
2624
|
`skippedProcesses`), `"autonomy_gated"`, `"strategy_filtered_all_passes"`, a
|
|
2590
|
-
reflect/distill dominant skip reason (e.g. `"
|
|
2625
|
+
reflect/distill dominant skip reason (e.g. `"no_change"` for reflect,
|
|
2626
|
+
`"no new signal since last proposal"` for distill),
|
|
2591
2627
|
or `"no_signal"` as the fallback — never a fabricated category. The field is
|
|
2592
2628
|
omitted entirely when both would be empty. The same table is printed to
|
|
2593
2629
|
stderr (`[improve] usage report ...`) after every real run, independent of
|
|
@@ -2607,14 +2643,14 @@ support.
|
|
|
2607
2643
|
### proposal
|
|
2608
2644
|
|
|
2609
2645
|
Manage the proposal queue. The canonical grammar is `akm proposal <verb>`:
|
|
2610
|
-
`extract`, `new`, `list`, `show`, `diff`, `accept`, `reject`, `
|
|
2611
|
-
`drain`. Bare `akm proposal` is a usage error (exit 2) as of 0.9.0 — it used
|
|
2646
|
+
`extract`, `new`, `list`, `show`, `diff`, `accept`, `reject`, `reopen`,
|
|
2647
|
+
`revert`, `drain`. Bare `akm proposal` is a usage error (exit 2) as of 0.9.0 — it used
|
|
2612
2648
|
to behave as `akm proposal list`; name the verb. There are no flat-verb
|
|
2613
2649
|
spellings (`akm proposals`, `akm extract`, `akm propose`, `akm accept`, `akm
|
|
2614
2650
|
reject`, `akm diff`, `akm revert`) — use the `akm proposal <verb>` form.
|
|
2615
2651
|
|
|
2616
|
-
`list`, `show`, `diff`, `accept`, `reject`, and `revert` (and bulk
|
|
2617
|
-
reject) support `--queue <source>`. It selects the proposal queue stored for
|
|
2652
|
+
`list`, `show`, `diff`, `accept`, `reject`, `reopen`, and `revert` (and bulk
|
|
2653
|
+
accept/reject) support `--queue <source>`. It selects the proposal queue stored for
|
|
2618
2654
|
that configured writable source root; without it, commands use the primary
|
|
2619
2655
|
queue. Queue selection is not a destination override. `drain` does **not**
|
|
2620
2656
|
take `--queue` — it operates on the standing backlog via a policy, not a
|
|
@@ -2732,8 +2768,8 @@ akm proposal list --generator consolidate-pair
|
|
|
2732
2768
|
| `--generator <name>` | Filter by generator/source (e.g. `reflect`, `distill`, `consolidate-pair`) — the same value `accept`/`reject --generator` take |
|
|
2733
2769
|
|
|
2734
2770
|
Each retire proposal's `retirement.continuityRisk`, when present, also shows
|
|
2735
|
-
in the default listing (`⚠ continuity-risk` inline) and in
|
|
2736
|
-
|
|
2771
|
+
in the default listing (`⚠ continuity-risk` inline) and in the text output of
|
|
2772
|
+
`proposal show` and `proposal diff` (the specific failing/unverified queries) — see
|
|
2737
2773
|
[Retirement continuity](https://github.com/itlackey/akm/blob/main/docs/architecture/improvement.md#retirement-continuity).
|
|
2738
2774
|
|
|
2739
2775
|
Each proposal record carries an optional `confidence` field (0..1) emitted by
|
|
@@ -2774,7 +2810,7 @@ akm proposal accept --generator reflect --older-than 7 --dry-run # Preview a bu
|
|
|
2774
2810
|
| `--target <name>` | Write destination; must match the proposal's recorded target |
|
|
2775
2811
|
| `--generator <name>` | Bulk-accept all pending proposals from this generator (e.g. `reflect`, `distill`). Requires no positional id. |
|
|
2776
2812
|
| `--max-diff-lines` | When bulk-accepting, only accept proposals whose content is `<=` this many lines. Larger proposals are skipped. |
|
|
2777
|
-
| `--older-than` | When bulk-accepting, only accept proposals created more than this many days ago |
|
|
2813
|
+
| `--older-than` | When bulk-accepting, only accept proposals created (or last reopened) more than this many days ago |
|
|
2778
2814
|
| `--dry-run` | List proposals that would be bulk-accepted without accepting them |
|
|
2779
2815
|
| `-y`, `--yes` | Skip confirmation (required in non-interactive mode for bulk accept) |
|
|
2780
2816
|
|
|
@@ -2785,7 +2821,8 @@ Bulk-accept all pending proposals from one generator with `--generator <name>`
|
|
|
2785
2821
|
#### proposal reject
|
|
2786
2822
|
|
|
2787
2823
|
Reject a proposal and archive the reason. Accepts a full UUID, an 8-character
|
|
2788
|
-
UUID prefix, or an asset ref.
|
|
2824
|
+
UUID prefix, or an asset ref. [`akm proposal reopen`](#proposal-reopen) undoes a
|
|
2825
|
+
rejection.
|
|
2789
2826
|
|
|
2790
2827
|
```sh
|
|
2791
2828
|
akm proposal reject <id> --reason "duplicates existing workflow"
|
|
@@ -2802,13 +2839,95 @@ akm proposal reject --generator reflect --reason "noisy" --max-diff-lines 50 -y
|
|
|
2802
2839
|
| `--queue <source>` | Select the proposal queue by configured writable source name |
|
|
2803
2840
|
| `--generator <name>` | Bulk-reject all pending proposals from this generator (e.g. `reflect`, `distill`). Requires no positional id. |
|
|
2804
2841
|
| `--max-diff-lines` | When bulk-rejecting, only reject proposals whose content is `<=` this many lines. Larger proposals are skipped. |
|
|
2805
|
-
| `--older-than` | When bulk-rejecting, only reject proposals created more than this many days ago |
|
|
2842
|
+
| `--older-than` | When bulk-rejecting, only reject proposals created (or last reopened) more than this many days ago |
|
|
2806
2843
|
| `--dry-run` | List proposals that would be bulk-rejected without rejecting them |
|
|
2807
2844
|
| `-y`, `--yes` | Skip confirmation (required in non-interactive mode for bulk reject) |
|
|
2808
2845
|
|
|
2809
2846
|
Bulk-reject all pending proposals from one generator with `--generator <name>`
|
|
2810
2847
|
and no positional id. Bulk reject requires `-y`/`--yes` in non-interactive shells.
|
|
2811
2848
|
|
|
2849
|
+
#### proposal reopen
|
|
2850
|
+
|
|
2851
|
+
Undo a rejection: move rejected proposals back to `pending` so they can be
|
|
2852
|
+
reviewed again (a proposal that retention expiry archived is a rejected one
|
|
2853
|
+
too). A rejection is otherwise final. `accept` refuses anything that is not
|
|
2854
|
+
pending, and a rejected consolidate pair-pass retire proposal also keeps the
|
|
2855
|
+
pair pass from proposing that retirement again while both documents are
|
|
2856
|
+
unchanged.
|
|
2857
|
+
|
|
2858
|
+
```sh
|
|
2859
|
+
akm proposal reopen <id>
|
|
2860
|
+
akm proposal reopen <id> --reason "the diff was misrendered (#997)"
|
|
2861
|
+
akm proposal reopen <id> <id> <id> # several at once: all or none
|
|
2862
|
+
akm proposal reopen <id> --queue team-bundle
|
|
2863
|
+
# One id per call, and only the rejections whose reason says the diff was misread:
|
|
2864
|
+
akm proposal list --status rejected --generator consolidate-pair \
|
|
2865
|
+
--detail normal --format json \
|
|
2866
|
+
| jq -r '.proposals[] | select(.review.reason // "" | test("blank line"))
|
|
2867
|
+
| .id' \
|
|
2868
|
+
| xargs -r -n 1 akm proposal reopen --reason "diff was misrendered"
|
|
2869
|
+
```
|
|
2870
|
+
|
|
2871
|
+
| Flag | Description |
|
|
2872
|
+
| --- | --- |
|
|
2873
|
+
| `--reason <text>` | Why the rejection is being undone. Kept in the proposal's review history and the `proposal_reopened` event, and in its ledger row's detail when it has a row |
|
|
2874
|
+
| `--queue <source>` | Select the proposal queue by configured writable source name |
|
|
2875
|
+
|
|
2876
|
+
Takes full proposal ids: a UUID prefix only matches pending proposals, so it
|
|
2877
|
+
cannot name a rejected one (`akm proposal list --status rejected` prints the
|
|
2878
|
+
ids; add `--generator consolidate-pair` for the retire backlog). An asset ref
|
|
2879
|
+
also resolves, to the newest proposal for that ref, but only while none is
|
|
2880
|
+
pending, and it never reaches a retire proposal, which is named by its id.
|
|
2881
|
+
|
|
2882
|
+
Check a rejection's reason before reopening it. The default brief output of
|
|
2883
|
+
`akm proposal list` leaves it out; `--detail normal --format json` shows it as
|
|
2884
|
+
`review.reason`. Reopen only the rejections you want back, since a deliberate
|
|
2885
|
+
rejection would otherwise be undone with the rest. The pattern in the example,
|
|
2886
|
+
`test("blank line")`, matches the reason given in the 0.9.19 upgrade note (the
|
|
2887
|
+
diff read as a blank-line replacement); change it to yours. Pass one id per
|
|
2888
|
+
call (`xargs -n 1`) so a refusal skips only that proposal, and use `xargs -r`
|
|
2889
|
+
so GNU xargs does not run `reopen` with no id when nothing matches. A retire
|
|
2890
|
+
proposal refused because another pending retire proposal involves the same
|
|
2891
|
+
document can be reopened once that one is decided.
|
|
2892
|
+
|
|
2893
|
+
Reopening is refused, with the reason, when:
|
|
2894
|
+
|
|
2895
|
+
- the proposal is not `rejected` (it is pending, accepted or reverted);
|
|
2896
|
+
- its target changed since it was created, by the same rule `accept` applies,
|
|
2897
|
+
so a reopened proposal is never one `accept` would then refuse as stale: an
|
|
2898
|
+
update needs its target unchanged, a create needs the target still absent,
|
|
2899
|
+
and a retire proposal needs the successor to exist and both documents' body
|
|
2900
|
+
hashes to match the ones recorded when the pair was judged;
|
|
2901
|
+
- it is a retire proposal and another pending retire proposal already involves
|
|
2902
|
+
either of its two documents (the pair pass never has two at once, since
|
|
2903
|
+
accepting one would strand the other): decide that one first;
|
|
2904
|
+
- it was recorded before proposals carried their change envelope (very old
|
|
2905
|
+
archived rows).
|
|
2906
|
+
|
|
2907
|
+
With several ids nothing is reopened unless every one can be: the error lists
|
|
2908
|
+
each refusal (exit 2).
|
|
2909
|
+
|
|
2910
|
+
A reopened proposal is `pending` again with its `review` cleared. The rejection
|
|
2911
|
+
(its review, and any gate verdict that came with it) is appended to the
|
|
2912
|
+
proposal's `reviewHistory`, which `akm proposal show` prints as one line per
|
|
2913
|
+
reopen: `reopened: <when> (<reopen reason>), undoing rejected: <why> (<when>)`.
|
|
2914
|
+
The gate verdict is cleared so the drain treats the proposal as undecided,
|
|
2915
|
+
except a `deferred` one, the quality gate's hand-off to a person, which stays
|
|
2916
|
+
so the drain keeps leaving the proposal for that person.
|
|
2917
|
+
|
|
2918
|
+
A reopened retire proposal no longer counts as a settled pair for the pair
|
|
2919
|
+
pass, and while it is pending that pair is not proposed a second time. The
|
|
2920
|
+
proposal's `improve_ledger` row goes back to what the mint wrote (a retire
|
|
2921
|
+
proposal's mint writes none, so the row its rejection created is dropped).
|
|
2922
|
+
The age that retention expiry and `--older-than` see restarts at the reopen
|
|
2923
|
+
(retire proposals never expire), and a `proposal_reopened` event is appended.
|
|
2924
|
+
Accepting a reopened retire proposal archives the retired file exactly as for
|
|
2925
|
+
any retire proposal, and `akm proposal revert` restores it byte-exactly.
|
|
2926
|
+
|
|
2927
|
+
Output: for one id, the envelope `reject` returns (`ok`, `id`, `ref`, the
|
|
2928
|
+
proposal, and `reason`, here the reopen reason); for several ids,
|
|
2929
|
+
`{ reopened, results }` with one such envelope per proposal.
|
|
2930
|
+
|
|
2812
2931
|
#### proposal revert
|
|
2813
2932
|
|
|
2814
2933
|
Revert an accepted proposal by restoring the prior asset content from the
|
|
@@ -2854,6 +2973,41 @@ akm proposal diff <id> --target team-bundle # Must match a recorded target
|
|
|
2854
2973
|
`proposal accept` runs full validation before promoting. `proposal reject`
|
|
2855
2974
|
requires `--reason`.
|
|
2856
2975
|
|
|
2976
|
+
**A retire proposal** (the consolidate pair pass's `consolidate-pair`
|
|
2977
|
+
retirements) writes no content: accepting it archives the retired file under
|
|
2978
|
+
`.akm/memory-cleanup/archive/` (nothing is deleted), and `akm proposal revert`
|
|
2979
|
+
restores it byte-for-byte. Its diff shows just that, the retired file's lines as
|
|
2980
|
+
removals and nothing added, under a `retire` header. It does not present the
|
|
2981
|
+
file as replaced by a blank one, which is how earlier releases rendered it:
|
|
2982
|
+
|
|
2983
|
+
```
|
|
2984
|
+
$ akm proposal diff <id>
|
|
2985
|
+
# proposal <id> (retire: memories/old-note -> memories/new-note)
|
|
2986
|
+
retire.label: duplicate (cosine=0.986)
|
|
2987
|
+
retire.reason: Same durable facts, B adds nothing new.
|
|
2988
|
+
note: Accepting archives the retired file under .akm/memory-cleanup/archive/ (nothing is deleted); `akm proposal revert` restores it byte-exactly.
|
|
2989
|
+
--- stash//memories/old-note (existing)
|
|
2990
|
+
+++ /dev/null (retired: archived; successor memories/new-note)
|
|
2991
|
+
@@ 1,5 0,0 @@
|
|
2992
|
+
----
|
|
2993
|
+
-description: an old note
|
|
2994
|
+
----
|
|
2995
|
+
-The durable fact.
|
|
2996
|
+
-A second line.
|
|
2997
|
+
```
|
|
2998
|
+
|
|
2999
|
+
The JSON result carries three more fields for a retire proposal, and none of
|
|
3000
|
+
them on any other proposal: `op` (`"delete"`), `retirement`, and `note` (what
|
|
3001
|
+
accept and revert do to the file). `retirement` uses the keys `proposal show`
|
|
3002
|
+
reports the pair under: `retiredRef`, `successorRef`, `judgeLabel`,
|
|
3003
|
+
`judgeReason` (the judge's own text; the stored block's `reason` is the
|
|
3004
|
+
tombstone vocabulary and is not repeated), `cosine`, and `continuityRisk` when
|
|
3005
|
+
the retirement continuity check flagged the pair. The text output prints the
|
|
3006
|
+
same verdict lines `show` does, `continuityRisk` and its failing queries
|
|
3007
|
+
included, above the diff. `isNew` is always `false` for a retire proposal; when
|
|
3008
|
+
the retired file is already gone (retired, or removed by something else), the
|
|
3009
|
+
diff is only its two header lines, `--- <ref> (missing)` and the `+++` line.
|
|
3010
|
+
|
|
2857
3011
|
#### proposal drain
|
|
2858
3012
|
|
|
2859
3013
|
Drain the standing pending-proposal backlog instead of adjudicating proposals
|
|
@@ -2877,7 +3031,7 @@ akm proposal drain --strategy default --promote -y # Read the triage block from
|
|
|
2877
3031
|
| `--promote` | Promote (accept) judge-passed proposals. Default is queue mode — stage only, no writes to assets. |
|
|
2878
3032
|
| `--dry-run` | List what would be accepted/rejected/deferred, without writing |
|
|
2879
3033
|
| `--max-accepts` | Hard per-run accept ceiling; accepts beyond this are reported as `skippedByCap` |
|
|
2880
|
-
| `--older-than` | Only consider proposals created more than this many days ago |
|
|
3034
|
+
| `--older-than` | Only consider proposals created (or last reopened) more than this many days ago |
|
|
2881
3035
|
| `--judgment` | Explicitly enable the judgment tier for this standalone drain, including when the selected strategy says `judgment.enabled: false`; execution overrides still come from that strategy. Without this flag, strategy judgment config does not enable standalone drain judgment. A missing runner remains a no-op with a logged `triage_deferred` summary. |
|
|
2882
3036
|
| `-y`, `--yes` | Skip the confirmation prompt (required in non-interactive mode for promotion) |
|
|
2883
3037
|
|
|
@@ -2887,6 +3041,13 @@ akm proposal drain --strategy default --promote -y # Read the triage block from
|
|
|
2887
3041
|
forwarded into feedback metadata and consumed by improve/distill proposal
|
|
2888
3042
|
prompts. Negative feedback requires a reason by default.
|
|
2889
3043
|
|
|
3044
|
+
Write the reason about the asset's content. Reflect treats it as an unverified
|
|
3045
|
+
report to investigate, not a fact to insert, and is told to leave the section
|
|
3046
|
+
unchanged when the reason asks for information the asset lacks. Distill's
|
|
3047
|
+
quality gate rejects a lesson that is off-subject for the asset it was
|
|
3048
|
+
distilled from. A command that failed (`akm show` erroring on the ref, say)
|
|
3049
|
+
says nothing about the asset, so it is not a reason to record against it.
|
|
3050
|
+
|
|
2890
3051
|
### task
|
|
2891
3052
|
|
|
2892
3053
|
`akm task` is the scheduling surface for workflows, agent prompts, and
|
|
@@ -353,11 +353,11 @@ guidance. When enabled, engine selection is judgment → triage → strategy →
|
|
|
353
353
|
}
|
|
354
354
|
```
|
|
355
355
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
`
|
|
359
|
-
|
|
360
|
-
|
|
356
|
+
No shipped strategy turns improve-stage session extraction on.
|
|
357
|
+
`proactiveMaintenance` is on only in the `proactive-maintenance` preset; run
|
|
358
|
+
`akm improve --strategy proactive-maintenance` to use that opt-in preset.
|
|
359
|
+
Because strategies inherit from `default`, a preset that omits either process
|
|
360
|
+
also inherits the off value. User strategy overrides
|
|
361
361
|
are applied last, so an explicit `enabled: true` still opts the selected
|
|
362
362
|
strategy in.
|
|
363
363
|
|
|
@@ -608,9 +608,10 @@ independent of scope. `--scope` was removed in 0.9.0 with no alias; use
|
|
|
608
608
|
|
|
609
609
|
`archiveRetentionDays` (default `90` when unset) controls how long a pending
|
|
610
610
|
proposal is kept before `akm improve`'s maintenance pass archives it (status
|
|
611
|
-
`rejected`, reason `"expired: no action within retention window"
|
|
612
|
-
|
|
613
|
-
|
|
611
|
+
`rejected`, reason `"expired: no action within retention window"`; counted
|
|
612
|
+
from the last `akm proposal reopen`, if there was one) — `akm proposal` itself
|
|
613
|
+
has no archive/expire verb, though `akm proposal reopen` puts an expired
|
|
614
|
+
proposal back. Setting it to `0` or less disables expiry entirely.
|
|
614
615
|
|
|
615
616
|
## Registries
|
|
616
617
|
|
|
@@ -138,29 +138,29 @@ An append-only log of every mutating action you perform with AKM. Events are sto
|
|
|
138
138
|
**Full event type list.** `EventType` (`src/core/events.ts`) is an open
|
|
139
139
|
string union — new types can be added without a schema bump — so this is
|
|
140
140
|
the set of types the code actually emits at HEAD (verified against every
|
|
141
|
-
`appendEvent(...)` call site, 2026-
|
|
141
|
+
`appendEvent(...)` and `insertEventOnce(...)` call site, 2026-09-30), grouped by area:
|
|
142
142
|
|
|
143
143
|
*Asset lifecycle*
|
|
144
144
|
|
|
145
145
|
| Event type | When emitted | Key metadata fields |
|
|
146
146
|
|---|---|---|
|
|
147
|
-
| `add` | `akm bundle add <source>` | `
|
|
147
|
+
| `add` | `akm bundle add <source>` | `target`, `name`, `writable`; `provider` when given |
|
|
148
148
|
| `remove` | `akm bundle remove <source>` | `ref` |
|
|
149
|
-
| `update` | `akm bundle update [source]` | `
|
|
150
|
-
| `remember` | `akm remember <text>` | `ref` |
|
|
151
|
-
| `import` | `akm import <file>` | `ref` |
|
|
149
|
+
| `update` | `akm bundle update [source]` | `target`, `all`, `processed` |
|
|
150
|
+
| `remember` | `akm remember <text>` | `ref`, `path`, `force` |
|
|
151
|
+
| `import` | `akm import <file>` | `ref`, `source`, `path`, `force` |
|
|
152
152
|
| `rekey` | `scripts/rekey-asset-ref.ts` moved at least one row onto a renamed asset's new ref — nothing is emitted on a no-op re-run | `ref` (the new ref); metadata `{from, to, changed}` (row counts only) |
|
|
153
153
|
|
|
154
154
|
*Search, retrieval, sync*
|
|
155
155
|
|
|
156
156
|
| Event type | When emitted | Key metadata fields |
|
|
157
157
|
|---|---|---|
|
|
158
|
-
| `search` | `akm search <query>` | `query`, `
|
|
159
|
-
| `curate` | `akm curate <prompt>` | `query`, `
|
|
158
|
+
| `search` | `akm search <query>` | `query`, `hitCount`, `resultRefs`, `mode` |
|
|
159
|
+
| `curate` | `akm curate <prompt>` | `query`, `itemCount`, `itemRefs` |
|
|
160
160
|
| `show` | `akm show <ref>` | `ref`, `type`, `name` |
|
|
161
|
-
| `select` | `akm show` after a search returning the same ref | `ref`, `
|
|
162
|
-
| `feedback` | `akm feedback <ref>` | `signal` (positive/negative) |
|
|
163
|
-
| `sync` | `akm sync` | `
|
|
161
|
+
| `select` | `akm show` after a search returning the same ref | `ref`, `query`, `searchTs`, `rankPosition` |
|
|
162
|
+
| `feedback` | `akm feedback <ref>` | `signal` (positive/negative), `reason`, `failureMode`, `tags` |
|
|
163
|
+
| `sync` | `akm sync` | `name`, `message`, `ok` |
|
|
164
164
|
| `index_db_vacuumed` | `akm index` VACUUMed index.db, after an index layout migration or because more than half its pages were free | `pagesBefore`, `pagesAfter`, `freelistRatioBefore` |
|
|
165
165
|
| `stash_synced` | `akm improve`'s internal auto-sync pass (the `sync.push` feature), **distinct from** the `akm sync` command above | `committed`, `pushed`, `skipped`, `reason`, `attributed` (paths the run wrote and staged), `unattributed` (in-scope paths that went dirty during the run without the run writing them — left for their author) |
|
|
166
166
|
| `env_access` | `akm env run <name> -- <command>` (audit trail: key **names** only, values never recorded) | `ref`, `keys` |
|
|
@@ -172,6 +172,7 @@ the set of types the code actually emits at HEAD (verified against every
|
|
|
172
172
|
|---|---|---|
|
|
173
173
|
| `promoted` | `akm proposal accept <id>` | `ref` |
|
|
174
174
|
| `rejected` | `akm proposal reject <id>` | `ref` |
|
|
175
|
+
| `proposal_reopened` | `akm proposal reopen <id>` (a rejected proposal goes back to pending) | `ref`, `proposalId`, `source`, `reason` (when given) |
|
|
175
176
|
| `proposal_reverted` | `akm proposal revert <id>` (undoes a previously-accepted proposal, restores prior content) | `ref` |
|
|
176
177
|
| `proposal_expired` | A pending proposal aged past the retention window and was auto-expired | `ref` |
|
|
177
178
|
| `proposal_expiration_pass` | Summary emitted once per `akm improve` maintenance run after per-proposal `proposal_expired` events | expiry counts |
|
|
@@ -187,7 +188,7 @@ the set of types the code actually emits at HEAD (verified against every
|
|
|
187
188
|
| `improve_invoked` | Start of an `akm improve` run | `ref` (scope); `strategy`, `scope`, `dryRun`, `eligibleCount` |
|
|
188
189
|
| `improve_completed` | `akm improve` run finished | run stats |
|
|
189
190
|
| `improve_failed` | `akm improve` run errored | error |
|
|
190
|
-
| `improve_skipped` |
|
|
191
|
+
| `improve_skipped` | `akm improve` left a ref, a lane, or a group of refs 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`, `pool_below_min_size`, `consolidation_no_memory_updates`, `below_min_new_sessions`, `derived_memory_reflect_skipped`, `memory_distill_requires_feedback`); `count`, `remaining`, `strategy`, `lane` or `configKey` where they apply |
|
|
191
192
|
| `improve_lock_recovered` | Stale improve lock cleared at startup | |
|
|
192
193
|
| `improve_review_needed` | `akm feedback` pushed a high-utility asset's utility below the review threshold — a review-needed escalation is recorded (not a proposal, so it can't accidentally overwrite the asset) | `ref`, `previousUtility`, `nextUtility` |
|
|
193
194
|
| `reflect_invoked` | Start of reflect phase in `akm improve` | `ref`, engine |
|
|
@@ -201,6 +202,7 @@ the set of types the code actually emits at HEAD (verified against every
|
|
|
201
202
|
| `proactive_selected` | The proactive-maintenance selector runs (once per `akm improve` run) | `count`, `dueTotal`, `neverReflected` (aggregated) |
|
|
202
203
|
| `events_purged` | Old events deleted by improve maintenance (90-day default retention) | `purgedCount`, `retentionDays` |
|
|
203
204
|
| `improve_runs_purged` | Old `improve_runs` rows deleted by improve maintenance (same retention window as events) | `purgedCount`, `retentionDays` |
|
|
205
|
+
| `asset_state_gc` | Improve maintenance found `asset_salience`/`asset_outcome` rows that no longer resolve against the index (`pending`) or deleted them (`improve.stateGc.collect`); a run with neither emits nothing | `pending`, `collected`, `byTable` |
|
|
204
206
|
| `state_db_vacuumed` | state.db was VACUUMed after the retention purge because more than half its pages were free | `pagesBefore`, `pagesAfter`, `freelistRatioBefore` |
|
|
205
207
|
| `task_logs_purged` | Old scheduled-task log files purged by improve maintenance | |
|
|
206
208
|
|
|
@@ -280,12 +282,12 @@ an identity that production indexing omitted.
|
|
|
280
282
|
|
|
281
283
|
### 3. Proposals Table
|
|
282
284
|
|
|
283
|
-
The proposal queue: pending, accepted, and
|
|
285
|
+
The proposal queue: pending, accepted, rejected, and reverted improvement proposals for your bundle assets. Generated by `akm improve`, `akm proposal new`, and related proposal-producing flows.
|
|
284
286
|
|
|
285
287
|
Contents:
|
|
286
288
|
- Proposal UUID (primary key)
|
|
287
289
|
- Target asset ref
|
|
288
|
-
- Status (pending/accepted/rejected)
|
|
290
|
+
- Status (pending/accepted/rejected/reverted)
|
|
289
291
|
- Source (which process generated it — e.g. `reflect`, `distill`)
|
|
290
292
|
- Full proposal content (Markdown text)
|
|
291
293
|
- Created/updated timestamps
|
|
@@ -295,7 +297,10 @@ with each asset — one row per bundle, asset ref and stage: the outcome
|
|
|
295
297
|
(`proposed`, `accepted`, `rejected`, `quality_rejected`, `review_needed`,
|
|
296
298
|
`expired`, `unchanged`, `failed`, `judged_no_action`), when it was attempted,
|
|
297
299
|
and the earliest time the stage may try that asset again. It holds refs,
|
|
298
|
-
timestamps, a proposal id and a short reason — never asset content.
|
|
300
|
+
timestamps, a proposal id and a short reason — never asset content. A row whose
|
|
301
|
+
next attempt depends on the asset changing rather than on a clock (the
|
|
302
|
+
consolidate pair pass, and a consolidate promotion once accepted or rejected)
|
|
303
|
+
also holds a hash of the asset's body, and no earliest-retry time.
|
|
299
304
|
|
|
300
305
|
### 4. Task History Table
|
|
301
306
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akm-cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.19-alpha.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cursor.",
|
|
6
6
|
"keywords": [
|