akm-cli 0.9.26-alpha.2 → 0.9.27-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 +294 -0
- package/dist/assets/hints/cli-hints-full.md +16 -10
- package/dist/assets/hints/cli-hints-short.md +5 -5
- package/dist/assets/prompts/consolidate-system.md +2 -2
- package/dist/assets/prompts/extract-session.md +2 -2
- package/dist/assets/stash-skeleton/README.md +4 -3
- package/dist/commands/feedback-cli.js +244 -43
- package/dist/commands/improve/consolidate/pair-pass.js +1 -1
- package/dist/commands/improve/consolidate.js +14 -4
- package/dist/commands/improve/distill.js +70 -7
- package/dist/commands/improve/extract-prompt.js +61 -39
- package/dist/commands/improve/extract.js +2 -1
- package/dist/commands/improve/loop-stages.js +16 -1
- package/dist/commands/improve/memory/memory-belief.js +1 -1
- package/dist/commands/improve/preparation.js +46 -0
- package/dist/commands/improve/reflect.js +51 -8
- package/dist/commands/improve/retrieval-gate.js +1 -1
- package/dist/commands/improve/session-asset.js +3 -2
- package/dist/commands/improve/stage.js +1 -1
- package/dist/commands/proposal/repository.js +22 -6
- package/dist/core/asset/akm-markdown.js +40 -16
- package/dist/core/asset/frontmatter.js +67 -7
- package/dist/core/config/config-schema.js +1 -1
- package/dist/core/config/config.js +0 -4
- package/dist/core/config/schema/feedback.js +2 -19
- package/dist/indexer/indexer.js +35 -19
- package/dist/integrations/harnesses/codex/agent-builder.js +23 -15
- package/dist/llm/client.js +44 -14
- package/dist/llm/memory-infer.js +1 -1
- package/dist/scripts/akm-migrate-node.js +26 -22
- package/dist/scripts/akm-migrate.js +26 -22
- package/dist/storage/repositories/index-entry-schema.js +20 -4
- package/dist/storage/repositories/index-fts-repository.js +44 -3
- package/dist/storage/repositories/index-schema.js +14 -8
- package/docs/reference/cli.md +36 -17
- package/docs/reference/configuration.md +12 -6
- package/docs/reference/data-and-telemetry.md +3 -3
- package/package.json +1 -1
- package/schemas/akm-config.json +0 -14
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,300 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.9.27-alpha.1] - 2026-10-06
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **A codex dispatch with an output schema no longer leaves a temp folder
|
|
14
|
+
behind.** Every build of the codex command for a request with a schema made a
|
|
15
|
+
new `akm-codex-schema-*` folder in the OS temp dir for `--output-schema` and
|
|
16
|
+
nothing ever removed it (the builder has no post-run hook, and the file is read
|
|
17
|
+
after it returns), so a machine whose `/tmp` is tmpfs held a folder in RAM per
|
|
18
|
+
dispatch until reboot. The schema is now written once to akm's cache dir, in a
|
|
19
|
+
file named by its hash: concurrent units dispatching the same schema share it,
|
|
20
|
+
a rewrite is an atomic rename of identical bytes, and the only residue is one
|
|
21
|
+
small file per distinct schema.
|
|
22
|
+
- **An index that has been updated ranks like a fresh index of the same files,
|
|
23
|
+
and `akm index --full` no longer doubles the full-text totals.** `entries_fts`
|
|
24
|
+
is contentless, and FTS5 cannot take a deleted row out of a contentless
|
|
25
|
+
table's BM25 totals (its row count, and the token counts the average document
|
|
26
|
+
length comes from). Every replaced or removed row left them one row too high:
|
|
27
|
+
40 notes read 40, then 41 after one edit, then 81 after `--full`, and a delete
|
|
28
|
+
never lowered them, so scores drifted away from what a fresh index gives.
|
|
29
|
+
SQLite has no command that recomputes them (`delete` and `rebuild` are refused
|
|
30
|
+
on a contentless table), so a delete that removes a row now stamps
|
|
31
|
+
`index_meta.ftsTotalsStale` in its own transaction, whichever process made it,
|
|
32
|
+
and the next `akm index` rebuilds the table from `entries` before it finishes:
|
|
33
|
+
about a second at 25,000 entries, and only when rows have left the table. A
|
|
34
|
+
row the write-path index replaced after an accepted proposal is settled the
|
|
35
|
+
same way, and an index that has already drifted is corrected by the first run
|
|
36
|
+
that replaces or removes a row.
|
|
37
|
+
- **`akm improve` runs against an API that rejects `chat_template_kwargs`,
|
|
38
|
+
OpenAI's among them.** Improve's reflect, consolidate and judge calls always
|
|
39
|
+
ask for thinking off, and the client sends that as
|
|
40
|
+
`chat_template_kwargs.enable_thinking` and a top-level `enable_thinking`. A
|
|
41
|
+
strict API answers 400 `Unknown parameter: 'chat_template_kwargs'`, the retry
|
|
42
|
+
without the response schema sent both fields again, and `akm improve judge`
|
|
43
|
+
reported `judge timeout/error — routed to review`. No engine setting could
|
|
44
|
+
stop it: the call sites override the engine's `enableThinking`, and
|
|
45
|
+
`extraParams` can only add fields. A 4xx that names either field is now
|
|
46
|
+
answered by one retry without both (which may in turn fall back without the
|
|
47
|
+
schema), and akm stops sending them to that endpoint and model for the rest
|
|
48
|
+
of the process, as it already does for `response_format`.
|
|
49
|
+
- **A lesson the model wrote without a `when_to_use` is no longer thrown away
|
|
50
|
+
silently by `akm proposal extract`.** The extract schema left `when_to_use`
|
|
51
|
+
optional while the parser dropped a lesson without one (or with one under 15
|
|
52
|
+
characters) and said nothing, so a model that followed the schema could
|
|
53
|
+
write a sound lesson that akm discarded and the session reported no
|
|
54
|
+
candidates: on akm-eval's extract eval qwen3.8-27b kept 3 of 11 expected
|
|
55
|
+
insights against 9 for gpt-oss-120b. Every property of the schema is now
|
|
56
|
+
required, `when_to_use` and `rationale_if_empty` included, with an empty
|
|
57
|
+
string for none (a memory or knowledge candidate needs no trigger, a
|
|
58
|
+
non-empty answer no rationale), which is also what a strict structured-output
|
|
59
|
+
provider needs; the prompt's output contract says the same. Any candidate the
|
|
60
|
+
contract still refuses, for this reason or another, is named in its session's
|
|
61
|
+
`warnings` as `<type>:<name> dropped: <reason>`.
|
|
62
|
+
- **Distill's response schemas are valid for a strict structured-output
|
|
63
|
+
provider.** The client sends a response schema `strict: true`, and OpenAI
|
|
64
|
+
refuses one whose objects leave a property out of `required`: `400 Invalid
|
|
65
|
+
schema for response_format 'akm_response': ... Missing 'tags'`. The lesson
|
|
66
|
+
schema left out `tags`, and the knowledge schema `tags` and `sources`, so
|
|
67
|
+
the first distill request on such a provider always failed. After a 4xx the
|
|
68
|
+
client retries once without the schema, but a gateway that answers the same
|
|
69
|
+
rejection with a 502 is not retried, and every distill call through it
|
|
70
|
+
failed; the workaround, `supportsJsonSchema: false`, loses the guidance that
|
|
71
|
+
keeps a model from leaving out `when_to_use`. Every property is now
|
|
72
|
+
required, and an empty array stands for none (distill already dropped an
|
|
73
|
+
empty `tags` or `sources`).
|
|
74
|
+
- **`akm improve` no longer reflects on an asset whose file a proposal would not
|
|
75
|
+
write, so accepting a reflect proposal no longer adds a second file.** A
|
|
76
|
+
skill's `references/a.md` is indexed as `knowledge/skills/<name>/references/a`,
|
|
77
|
+
but a proposal writes the path derived from that ref,
|
|
78
|
+
`knowledge/skills/<name>/references/a.md`. Nothing is there, so the proposal
|
|
79
|
+
was a `create`, and accepting it wrote a copy beside the skill's own file;
|
|
80
|
+
later proposals then revised the copy while the skill's file drifted. Reflect
|
|
81
|
+
now refuses before it calls the model, naming the file and the path a
|
|
82
|
+
proposal would write, and the loop records it as a skip (`unsupported_type`,
|
|
83
|
+
`file_outside_layout` in the `reflect_completed` event). This is the rule
|
|
84
|
+
0.9.26 added to `akm feedback --replace`. An asset that another bundle owns is
|
|
85
|
+
still refused by `createProposal` (#1000).
|
|
86
|
+
- **An index that 0.9.1 wrote no longer crashes akm.** Every `akm index` on it
|
|
87
|
+
exited 70 with `null is not an object (evaluating 'doc.xrefs')`, `akm migrate
|
|
88
|
+
apply` and `akm index --full` did not help, and `akm search` failed with
|
|
89
|
+
`null is not an object (evaluating 'item.entry.quality')`; the only way out
|
|
90
|
+
was moving `index.db` aside. That layout (20) keeps the transitional
|
|
91
|
+
`entry_key`, `dir_path`, `stash_dir`, `entry_json` and `entry_type` columns
|
|
92
|
+
that layout 21 removed, each NOT NULL, beside the current columns, and leaves
|
|
93
|
+
`document_json` NULL on every row. The table had every column akm checks for,
|
|
94
|
+
so it was taken for a current one: the links migration read the NULL
|
|
95
|
+
documents, and no insert could ever have succeeded (`NOT NULL constraint
|
|
96
|
+
failed: entries.entry_key`). akm now treats a table that still has a retired
|
|
97
|
+
column as older than layout 21, as the compat notes already said: the
|
|
98
|
+
writable opener recreates its entries-keyed tables (the LLM enrichment cache
|
|
99
|
+
is kept) and the next `akm index` re-walks every source, and a read rebuilds
|
|
100
|
+
inline. An index that a failed open already half-migrated (layout stamp still
|
|
101
|
+
20, `search_text` dropped, `asset_links` created) recovers the same way.
|
|
102
|
+
- **Two files that claim one ref no longer trade places in the index, and `akm
|
|
103
|
+
index` says so.** A skill's `references/a.md` and a note at
|
|
104
|
+
`knowledge/skills/x/references/a.md` are both the ref
|
|
105
|
+
`knowledge/skills/x/references/a`, and the index holds one row for it. The
|
|
106
|
+
first file a run persisted held it, so a full build followed the filesystem's
|
|
107
|
+
listing order (one bundle indexed on tmpfs and on ext4 held different files),
|
|
108
|
+
and the first incremental run after a full build handed the row to the other
|
|
109
|
+
file, because it drains only the directory that lost: with no file touched,
|
|
110
|
+
the row, its search entry and the text its vector is embedded from changed,
|
|
111
|
+
and the vector was dropped and recomputed. When a smaller-path file was added
|
|
112
|
+
later and then deleted, the ref also left the index until `--full`, although
|
|
113
|
+
its other file was still on disk. The file with the smaller path (code-point
|
|
114
|
+
order, as `akm show`'s refusal lists them) now holds the ref however the
|
|
115
|
+
directories are drained and the walk is ordered, a directory that gives a ref
|
|
116
|
+
up is drained again so the ref passes back when its holder goes, and each
|
|
117
|
+
pair is reported in the `warnings` of `akm index`, naming the file indexed
|
|
118
|
+
and the one skipped.
|
|
119
|
+
- **Consolidate's plan schema and the session summary schema are valid for a
|
|
120
|
+
strict structured-output provider, and a new response schema can no longer
|
|
121
|
+
skip the rule.** The client sends a response schema `strict: true`, and
|
|
122
|
+
OpenAI refuses one whose objects leave a property out of `required`. The
|
|
123
|
+
consolidate plan left out `description` and `confidence`, and the session
|
|
124
|
+
summary `tags`, so the first request of every plan and every summary to such
|
|
125
|
+
a provider was refused. The client then retries without the schema and
|
|
126
|
+
remembers that per connection (endpoint and model), not per schema, so one
|
|
127
|
+
invalid schema also switched the response schema off for every valid one
|
|
128
|
+
that followed on that connection. Every property of both is now required: an
|
|
129
|
+
empty `description` keeps the memory's own, a null `confidence` records none
|
|
130
|
+
and an empty `tags` array is no tags, which is how all three were already
|
|
131
|
+
read. A contract test runs every schema akm sends through the rule, so a
|
|
132
|
+
property added later without being required fails CI.
|
|
133
|
+
|
|
134
|
+
## [0.9.26] - 2026-10-05
|
|
135
|
+
|
|
136
|
+
The stable release of the 0.9.26 line: 0.9.26-alpha.1 and alpha.2, and the
|
|
137
|
+
changes in this section. When upgrading from 0.9.25:
|
|
138
|
+
|
|
139
|
+
- **Consolidate retires far fewer notes that hold something the kept note
|
|
140
|
+
lacks.** Its pair judge lists what each note alone holds and akm never
|
|
141
|
+
retires a note with anything listed; on 385 held-out pair proposals, 91% of
|
|
142
|
+
its retirements are safe, against 61% before. A duplicate that a second look
|
|
143
|
+
confirms is accepted by the triage drain (alpha.1).
|
|
144
|
+
- **Negative feedback can carry the fix:** `akm feedback --negative --replace
|
|
145
|
+
"<exact text>" --with "<corrected>" --source "<evidence>"` (alpha.2), and
|
|
146
|
+
`--outdated` or `--superseded-by <ref>` to mark a note's history. Either
|
|
147
|
+
becomes one `feedback` proposal for review.
|
|
148
|
+
- **Negative feedback is for wrong or stale content.** The hints and docs say
|
|
149
|
+
so; a note that did not fit the task records nothing. Each feedback event now
|
|
150
|
+
records the hash of the text it judged, and reflect marks feedback given on
|
|
151
|
+
an earlier version.
|
|
152
|
+
- **Distill no longer accepts a lesson unattended.** A lesson that passes its
|
|
153
|
+
judge waits for review instead of the drain, and distill skips a memory
|
|
154
|
+
flagged wrong since its last edit, one whose only feedback is a positive
|
|
155
|
+
without a reason, and a lesson that already exists.
|
|
156
|
+
- **Fixed:** a proposal no longer rewraps a note's frontmatter to add its
|
|
157
|
+
`type`, and accepting one stamps its provenance as lines of its own instead
|
|
158
|
+
of writing the frontmatter out again; a feedback fix for an asset outside the
|
|
159
|
+
bundle's layout is refused instead of queued at the wrong path.
|
|
160
|
+
- **Removed:** `akm feedback --failure-mode` and `feedback.allowedFailureModes`
|
|
161
|
+
(an old config still loads, naming the key once).
|
|
162
|
+
|
|
163
|
+
### Added
|
|
164
|
+
|
|
165
|
+
- **`akm feedback --negative --superseded-by <ref>` and `--outdated` mark an
|
|
166
|
+
asset's history, in the same single `feedback` proposal as any `--replace`
|
|
167
|
+
edits.** `--superseded-by` (another asset replaces this one) sets
|
|
168
|
+
`beliefState: superseded` and adds the ref to `supersededBy`; akm resolves it
|
|
169
|
+
through the index first, and it must be indexed and not the asset itself, or
|
|
170
|
+
nothing is recorded. The rules are those of `akm remember --supersedes`: an
|
|
171
|
+
asset that already says so is left as it is, `contradicted` and `archived`
|
|
172
|
+
stay, and a scalar `supersededBy` becomes a list. `--outdated` (the asset
|
|
173
|
+
describes a past state and nothing replaces it) sets `beliefState:
|
|
174
|
+
deprecated`, unless the asset already says superseded, contradicted or
|
|
175
|
+
archived. Like every fix, both are for negative feedback and need `--reason`
|
|
176
|
+
and `--source`; they apply to markdown assets and are not used together. akm
|
|
177
|
+
edits only the `beliefState` and `supersededBy` lines of the text, so
|
|
178
|
+
comments, quoting, key order and line endings stay (it writes the frontmatter
|
|
179
|
+
out again only when a line edit cannot follow how a key is spelled), and `fix`
|
|
180
|
+
in the command's output and in the feedback event says what was set.
|
|
181
|
+
|
|
182
|
+
### Changed
|
|
183
|
+
|
|
184
|
+
- **Each feedback event records the text it judged, and reflect marks feedback
|
|
185
|
+
given on an earlier version of it.** `akm feedback` adds `contentHash`, the
|
|
186
|
+
sha256 of the asset's body without its frontmatter as it stood when the
|
|
187
|
+
feedback was given, to the event and its usage row, for positive and negative
|
|
188
|
+
feedback. It is left out for an env or secret file, whose bytes akm never
|
|
189
|
+
reads, and when the file cannot be read. When reflect gathers an asset's
|
|
190
|
+
recent feedback, a line whose `contentHash` differs from the asset's current
|
|
191
|
+
body ends with ` (given on an earlier version of the text)`, so the model
|
|
192
|
+
knows the text changed since. A line without a `contentHash` (all feedback
|
|
193
|
+
recorded before this change) or with a matching one reads as before, and the
|
|
194
|
+
rest of the prompt is unchanged.
|
|
195
|
+
- **The shipped hints and docs say what negative feedback is for.** Record
|
|
196
|
+
`akm feedback --negative` only when an asset's content is wrong or stale, and
|
|
197
|
+
say what is wrong and what it should say. A note that simply did not fit the
|
|
198
|
+
task is not negative feedback: record nothing for it. Once the correct fact is
|
|
199
|
+
verified, attach the exact fix with `--replace`/`--with`/`--source`. Of the 195
|
|
200
|
+
negative reasons recorded in the last 30 days, 100 named no error in the note,
|
|
201
|
+
and 89 of those only said it did not fit the agent's task, which still lowered
|
|
202
|
+
the note's ranking and sent it to improve. The hints and the guides no longer
|
|
203
|
+
list "unhelpful" among the reasons to flag a note, and their example reasons
|
|
204
|
+
name a wrong fact instead of "wrong framework" or "incomplete-edge-cases". The
|
|
205
|
+
hints also say that an outdated note can be marked with `--outdated`, or
|
|
206
|
+
`--superseded-by <ref>` when another note replaces it.
|
|
207
|
+
- **Distill skips a memory that was flagged wrong and not edited since.** A
|
|
208
|
+
memory with negative feedback in the last 30 days on the text it still has is
|
|
209
|
+
no source for a lesson, so the improve loop skips distill for it: a
|
|
210
|
+
`distill-skipped` action with the reason "flagged wrong since its last edit"
|
|
211
|
+
and an `improve_skipped` event (`distill_flagged_wrong`). The attempt goes in
|
|
212
|
+
the improve ledger as `unchanged`, so the memory waits for newer feedback, and
|
|
213
|
+
reflect still plans it. Feedback records the hash of the body it judged
|
|
214
|
+
(`contentHash`), so a write that leaves the body alone, such as an inference
|
|
215
|
+
stamp or an accepted frontmatter repair, does not lift the flag; changing the
|
|
216
|
+
body does. Feedback recorded without a hash keeps the earlier test: it flags
|
|
217
|
+
the memory while it is newer than the file's last write (its modification
|
|
218
|
+
time, as in the retrieval scope's new-material test), so any later write ends
|
|
219
|
+
it. An explicit `akm improve <ref>` still distills it.
|
|
220
|
+
- **A distill proposal that passes the quality judge goes to review, not to the
|
|
221
|
+
drain.** The gate used to stamp a passing lesson (or knowledge promotion)
|
|
222
|
+
`staged`, and the triage drain accepted it on the next run with no one
|
|
223
|
+
looking. It is now minted `deferred` for a person: gate decision
|
|
224
|
+
`deferred`/`quality-gate` with the reason `distill-review`, carrying the
|
|
225
|
+
judge's per-criterion `scores` and `judgeReason`, so neither the drain nor its
|
|
226
|
+
judgment tier accepts it, and the improve ledger records `review_needed`. The
|
|
227
|
+
`distill_invoked` outcome is still `queued`. On 2026-10-05 the gate had
|
|
228
|
+
staged 12 lessons and 10 were bad (they restated the memory, claimed what it
|
|
229
|
+
does not say, or filed a dated status as a lesson); no judge score separated
|
|
230
|
+
them from the two good ones. A failed judgment behaves as before, and with
|
|
231
|
+
`processes.distill.qualityGate` off nothing is judged, so the proposal is
|
|
232
|
+
minted unstamped for the drain to decide.
|
|
233
|
+
- **Distill skips a memory whose only recent feedback is positive and says
|
|
234
|
+
nothing.** A bare `akm feedback --positive` records that a note helped, which
|
|
235
|
+
gives the writer nothing to distil, so it restated the memory: 10 of the 11
|
|
236
|
+
lessons made from a memory with only that kind of feedback were rejected (the
|
|
237
|
+
11th was good). When every feedback event in the last 30 days that counts as a
|
|
238
|
+
signal is positive with no reason and no note, the improve loop skips distill
|
|
239
|
+
for the memory: a `distill-skipped` action with the reason "only positive
|
|
240
|
+
feedback, without a reason" and an `improve_skipped` event
|
|
241
|
+
(`distill_positive_without_reason`). The attempt goes in the improve ledger as
|
|
242
|
+
`unchanged`, so the memory waits for newer feedback. A reason, a note or a
|
|
243
|
+
negative signal anywhere in the window lets it through, and an explicit
|
|
244
|
+
`akm improve <ref>` still distills it. Record `--reason` with a positive
|
|
245
|
+
signal to say what helped.
|
|
246
|
+
- **Distill no longer regenerates a lesson that already exists.** A lesson's ref
|
|
247
|
+
comes from its memory's name (`memories/deploy` gives
|
|
248
|
+
`lessons/memory-deploy-lesson`), so a second distill of the same memory
|
|
249
|
+
proposed the same ref, and accepting it replaced the lesson. All 5 such
|
|
250
|
+
overwrites recorded by the 2026-10-05 review were rejected. When the stash
|
|
251
|
+
the proposal is filed in already holds a file at the lesson ref, distill now
|
|
252
|
+
returns `skipped` with the reason `lesson_exists` (in the result and the
|
|
253
|
+
`distill_invoked` event) before any model call, mints no proposal and leaves
|
|
254
|
+
the memory untouched, and the improve loop records it in the ledger as
|
|
255
|
+
`unchanged`. A lesson of that name in another bundle does not count, since
|
|
256
|
+
the proposal would not replace it. To change a lesson, edit it.
|
|
257
|
+
|
|
258
|
+
### Removed
|
|
259
|
+
|
|
260
|
+
- **`akm feedback --failure-mode` and the `feedback.allowedFailureModes` config
|
|
261
|
+
key.** The flag labelled negative feedback `incorrect`, `outdated`,
|
|
262
|
+
`dangerous`, `incomplete` or `redundant`. None of the 195 negative feedback
|
|
263
|
+
events of the last 30 days set it, and nothing read it back. It now fails as an
|
|
264
|
+
unknown flag, and `akm feedback`'s output and the `improve_review_needed`
|
|
265
|
+
event no longer carry `failureMode`. A config that still sets
|
|
266
|
+
`feedback.allowedFailureModes` loads, names the key once as unknown, and
|
|
267
|
+
`akm migrate apply` drops it. Events recorded earlier keep their `failureMode`.
|
|
268
|
+
|
|
269
|
+
### Fixed
|
|
270
|
+
|
|
271
|
+
- **`akm feedback --replace` no longer queues a fix that accepting would turn
|
|
272
|
+
into a duplicate file.** A proposal writes the path computed from the ref's
|
|
273
|
+
type and name under the bundle's root, which is not where an asset indexed
|
|
274
|
+
outside that layout lives (a git bundle's `tasks/README.md` is
|
|
275
|
+
`knowledge/tasks/README`; a skill's `references/symptom-map.md` is
|
|
276
|
+
`knowledge/skills/<name>/references/symptom-map`). Accepting such a proposal
|
|
277
|
+
created a second file and left the real one unfixed. akm now refuses before
|
|
278
|
+
recording anything, naming the file and the path the proposal would write, and
|
|
279
|
+
says to edit the file directly. Plain negative feedback on these assets is
|
|
280
|
+
unaffected.
|
|
281
|
+
- **A proposal no longer rewraps, reorders or strips a note's frontmatter to
|
|
282
|
+
add or correct its `type`.** When a proposal's content had no `type:` or a
|
|
283
|
+
different one, akm re-serialized the whole frontmatter block, so the reviewer
|
|
284
|
+
of a one-line correction also saw long values rewrapped, keys reordered and
|
|
285
|
+
YAML comments dropped. In practice 40 of 70 one-line correction proposals did
|
|
286
|
+
this. akm now adds a missing `type:` (and `updated:`) as a line before the
|
|
287
|
+
closing `---`, or replaces the existing `type:` line where it stands, and
|
|
288
|
+
leaves every other byte as written, line endings and body included. It
|
|
289
|
+
re-serializes only when it cannot do that safely, such as a `type` value that
|
|
290
|
+
spans several lines. The same write path serves `akm remember`, `akm import`
|
|
291
|
+
and `akm workflow create`, so a note akm writes without a `type` now carries
|
|
292
|
+
it, and `updated`, as its last frontmatter lines instead of its first.
|
|
293
|
+
Accepting a proposal also stamps its provenance (`generated`, `verified`,
|
|
294
|
+
`provenance`) as lines of its own, the last of the frontmatter, instead of
|
|
295
|
+
writing the whole frontmatter out again; a staging run found the old stamp
|
|
296
|
+
rewrapping 3 of 16 accepted edits. Accept still turns CRLF into LF, and still
|
|
297
|
+
writes the frontmatter out again when it carries bookkeeping keys such as
|
|
298
|
+
`inferenceProcessed` from the live note into a proposal that lacks them.
|
|
299
|
+
- **`akm lint --fix` keeps a CRLF note's line endings** when it adds a missing
|
|
300
|
+
`updated:`. It used to rewrite the whole file to LF, so one added line showed
|
|
301
|
+
as every line changed.
|
|
302
|
+
|
|
9
303
|
## [0.9.26-alpha.2] - 2026-10-05
|
|
10
304
|
|
|
11
305
|
### Added
|
|
@@ -95,23 +95,29 @@ akm workflow create ship-release # Create a workflow asset in the
|
|
|
95
95
|
akm lint --type workflows # Parse and compile every .md/.yml workflow source; list every error
|
|
96
96
|
akm workflow run workflows/ship-release # Start or resume and execute the workflow
|
|
97
97
|
akm feedback skills/code-review --positive # Record that an asset helped (ranks it higher; no rewrite)
|
|
98
|
-
akm feedback agents/reviewer --negative --reason "
|
|
98
|
+
akm feedback agents/reviewer --negative --reason "says to run jest; the suite runs on vitest" # Content wrong or stale: lowers its ranking; improve may repair its frontmatter
|
|
99
99
|
akm feedback knowledge/opencode-server --negative --reason "the default port is 4096, not 8000" --replace "port 8000" --with "port 4096" --source "https://opencode.ai/docs/server/" # Queue an exact fix
|
|
100
100
|
akm feedback memories/deployment-notes --positive # Works for memories too
|
|
101
101
|
akm feedback env/prod --positive # Records env feedback without surfacing values
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
Use `akm feedback`
|
|
105
|
-
|
|
104
|
+
Use `akm feedback --positive` when an asset's content materially helps, so
|
|
105
|
+
future search ranking can learn from actual usage. Record negative feedback only
|
|
106
|
+
when the asset's content is wrong or stale, and say what is wrong and what it
|
|
107
|
+
should say.
|
|
106
108
|
`akm feedback <ref> --negative --reason "<what is wrong and what should change>"`
|
|
107
109
|
flags the asset: it ranks lower right away, and the next improve run may repair
|
|
108
|
-
its description, title or `when_to_use` from your reason.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
its description, title or `when_to_use` from your reason. A note that simply did
|
|
111
|
+
not fit your task is not negative feedback: record nothing for it. Improve does
|
|
112
|
+
not rewrite an asset's text: once you have verified the correct fact, attach the
|
|
113
|
+
exact fix with `--replace "<exact current text>" --with "<corrected text>"
|
|
114
|
+
--source "<URL, command or file>"`, which akm checks and queues as a proposal.
|
|
115
|
+
A note that is outdated can be marked with `--outdated`, or
|
|
116
|
+
`--superseded-by <ref>` when another note replaces it.
|
|
117
|
+
`--positive` records that an asset helped (it raises its ranking) and does not
|
|
118
|
+
trigger a rewrite; improve no longer rewrites assets from positive signals or on
|
|
119
|
+
a proactive cadence. An akm command that fails says nothing about the asset;
|
|
120
|
+
don't record it as feedback.
|
|
115
121
|
|
|
116
122
|
## LLM Wiki bundles
|
|
117
123
|
|
|
@@ -8,7 +8,7 @@ For any task, follow this loop:
|
|
|
8
8
|
1. `akm curate "<task>"` — find the best matching asset
|
|
9
9
|
2. `akm show <ref>` — read the schema (field names and structure)
|
|
10
10
|
3. Edit the workspace file using schema field names + task-specific values from your README
|
|
11
|
-
4. `akm feedback <ref> --positive` — record that the asset helped (it raises its ranking and does not trigger a rewrite)
|
|
11
|
+
4. `akm feedback <ref> --positive` — record that the asset helped (it raises its ranking and does not trigger a rewrite). Record negative feedback only when the asset's content is wrong or stale, and say what is wrong and what it should say. `akm feedback <ref> --negative --reason "<what is wrong and what should change>"` flags it: the next improve run may repair its description, title or `when_to_use` from your reason, but not its text. A note that simply did not fit your task is not negative feedback: record nothing for it. Once you have verified the correct fact, add the exact fix: `--replace "<exact current text>" --with "<corrected text>" --source "<URL, command or file>"`. A note that is outdated can be marked with `--outdated`, or `--superseded-by <ref>` when another note replaces it. A failed akm command (e.g. `akm show` erroring) is not feedback on the asset — don't record it.
|
|
12
12
|
|
|
13
13
|
For workflow tasks:
|
|
14
14
|
1. `akm show workflows/<name>` — inspect the procedure before executing it
|
|
@@ -40,7 +40,7 @@ akm proposal diff skills/akm-dream # Diff proposal by ref, UUID, or 8
|
|
|
40
40
|
akm proposal accept 7c115132 # Accept by UUID prefix
|
|
41
41
|
akm proposal reject skills/my-skill --reason "..." # Reject by ref
|
|
42
42
|
akm feedback <ref> --positive # Record that an asset helped (ranks it higher; no rewrite)
|
|
43
|
-
akm feedback <ref> --negative --reason "..." #
|
|
43
|
+
akm feedback <ref> --negative --reason "..." # Content wrong or stale: lowers its ranking; improve may repair its frontmatter
|
|
44
44
|
akm feedback <ref> --negative --reason "..." --replace "<exact text>" --with "<fix>" --source "<url|cmd|file>" # Queue an exact fix of its text
|
|
45
45
|
akm bundle add <ref> # Add a source (npm, GitHub, git, local dir)
|
|
46
46
|
akm clone <ref> # Copy an asset to the working bundle (optional --dest arg to clone to specific location)
|
|
@@ -65,9 +65,9 @@ akm search "<query>" --from registry # Search all registries (registry
|
|
|
65
65
|
| secret | A single sensitive value for AUTHENTICATION (token, key, cert); name only. Inject with `akm secret run <ref> <VAR> -- <cmd>`. |
|
|
66
66
|
| lesson | A distilled feedback lesson: `content` plus `action` (rendered from the `when_to_use` frontmatter). Read both before applying a related skill. Generated by the improve pipeline and promoted through the proposal queue. |
|
|
67
67
|
|
|
68
|
-
When an asset's content meaningfully helps, or proves wrong
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
When an asset's content meaningfully helps, or proves wrong or stale, record
|
|
69
|
+
that with `akm feedback` so future search ranking can learn from real usage.
|
|
70
|
+
Only negative feedback with a specific reason gets the asset reviewed and
|
|
71
71
|
fixed: improve no longer rewrites assets from positive signals or on a
|
|
72
72
|
proactive cadence. An akm command that fails says nothing about the asset;
|
|
73
73
|
don't record it as feedback.
|
|
@@ -7,10 +7,10 @@ Rules:
|
|
|
7
7
|
Return ONLY JSON (no prose, no code fences):
|
|
8
8
|
{
|
|
9
9
|
"operations": [
|
|
10
|
-
{ "op": "promote", "ref": "memories/<name>", "knowledgeRef": "knowledge/<suggested-slug>", "reason": "<brief reason>", "description": "<one sentence describing the new knowledge asset>", "confidence": 0.92 }
|
|
10
|
+
{ "op": "promote", "ref": "memories/<name>", "knowledgeRef": "knowledge/<suggested-slug>", "reason": "<brief reason>", "description": "<one sentence describing the new knowledge asset, or an empty string to keep the memory's own>", "confidence": 0.92 }
|
|
11
11
|
]
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
For every operation, emit a `confidence` field in [0, 1] expressing your certainty that the operation is correct and safe. Use 0.95+ only when evidence is unambiguous.
|
|
14
|
+
For every operation, emit a `confidence` field in [0, 1] expressing your certainty that the operation is correct and safe. Use 0.95+ only when evidence is unambiguous. Use `null` rather than guessing if you are uncertain.
|
|
15
15
|
|
|
16
16
|
When the merged content includes an `updated` frontmatter field, the value MUST be a real ISO date string (e.g. `updated: 2026-05-20`). NEVER emit `updated: today`, `updated: {today}`, `updated: {today: null}`, `updated: now`, or any other literal placeholder/template-variable. If you do not have a real source-of-truth date, OMIT the `updated` field entirely — the post-processor will not invent one for you.
|
|
@@ -48,13 +48,13 @@ Respond with EXACTLY one JSON object matching this shape:
|
|
|
48
48
|
"type": "memory" | "lesson" | "knowledge",
|
|
49
49
|
"name": "<kebab-case name, e.g. jwt-token; optionally under one kebab-case scope, e.g. auth/jwt-token>",
|
|
50
50
|
"description": "<one sentence 20-400 chars>",
|
|
51
|
-
"when_to_use": "<one sentence 15-400 chars;
|
|
51
|
+
"when_to_use": "<one sentence 15-400 chars for a lesson; an empty string for a memory or knowledge candidate>",
|
|
52
52
|
"body": "<markdown body, 200-3000 chars typical>",
|
|
53
53
|
"confidence": <number 0.0-1.0>,
|
|
54
54
|
"evidence": "<one-line pointer to the moment in the session>"
|
|
55
55
|
}
|
|
56
56
|
],
|
|
57
|
-
"rationale_if_empty": "<one sentence
|
|
57
|
+
"rationale_if_empty": "<one sentence when candidates is empty; an empty string otherwise>"
|
|
58
58
|
}
|
|
59
59
|
```
|
|
60
60
|
|
|
@@ -80,11 +80,12 @@ akm search "<query>" --type skill
|
|
|
80
80
|
# Mark an asset as helpful (raises its ranking; does not trigger a rewrite)
|
|
81
81
|
akm feedback <ref> --positive
|
|
82
82
|
|
|
83
|
-
# Flag an asset: it ranks lower, and the next
|
|
84
|
-
# description, title or when_to_use from your reason
|
|
83
|
+
# Flag an asset whose content is wrong or stale: it ranks lower, and the next
|
|
84
|
+
# improve run may repair its description, title or when_to_use from your reason.
|
|
85
|
+
# A note that simply did not fit your task gets no negative feedback.
|
|
85
86
|
akm feedback <ref> --negative --reason "<what is wrong and what should change>"
|
|
86
87
|
|
|
87
|
-
#
|
|
88
|
+
# Once you have verified the correct fact, attach the exact fix: it is checked and queued for review
|
|
88
89
|
akm feedback <ref> --negative --reason "<what is wrong>" --replace "<exact current text>" --with "<corrected text>" --source "<URL, command or file>"
|
|
89
90
|
|
|
90
91
|
# Capture a durable lesson or memory from the current session
|