akm docs

Migration notes for akm v0.9.17

Run this after upgrading:

akm migrate apply
akm task sync

akm migrate apply reads config.json through the normal load pipeline and writes its current shape back under a backup, dropping every retired key it finds -- run it with --dry-run first to see the exact list for your config. From 0.9.16, that includes index.graph., index.metadataEnhance, search.minScore, search.graphBoost., improve.utilityDecay.*, and a dozen smaller ones. None of them do anything any more -- leaving them in config.json is harmless until you run migrate apply, which drops them for good. It also deletes files nothing reads any more: 0.9.16's transaction journals ($DATA/txn/ and $DATA/txn-quarantine/), its maintenance barrier lock, and the maintenance-activities/ registry, which leaked an entry per process and reached 927 MB on one host. It also drops a leftover improve.strategies["graph-refresh"] override block, but not defaults.improveStrategy: "graph-refresh" itself -- if you set that, change it to a different strategy by hand, since graph-refresh now refuses outright, naming the retirement, rather than quietly running as a no-op. The shipped akm-graph-refresh-weekly task template is gone; remove or repoint any task that used it. Separately, akm search --no-project-context and akm proposal drain --policy/--max-diff-lines now fail as unknown flags; drop them from any script or task that still passes them.

The first akm index after upgrading migrates index.db to layout 26 in place -- for a 0.9.16 index this includes a one-time full-text rebuild it was already due for, so budget a few seconds for a 24k-entry index rather than a fraction of one. This also drops the LLM entity-graph tables -- the per-file entity/relation extraction that fed akm show's old related list is retired -- and ends with a VACUUM that reclaims the space both steps free; akm index has never VACUUMed index.db before, so this is the first time it happens at all, not a repeat of something 0.9.16 already did. Nothing is re-embedded by this migration.

Embeddings are a separate matter if you use a nomic-embed or E5 model: akm index now sends the model's own document template (nomic: "search_document: ", E5: "passage: ") instead of the raw text, which changes what gets embedded, so every entry re-embeds once on the next akm index. Qwen3, the BGE/mxbai/arctic family, and the default local model have no document template and keep their stored vectors untouched. Set embedding.documentTemplate: "" if you'd rather keep the old vectors than pay for a full re-embed. If you had index.metadataEnhance on before upgrading (it defaulted off), run akm index --full once afterward to replace the LLM-written descriptions it left behind with the plain deterministic ones -- an ordinary incremental akm index does not touch them.

The first akm task sync after upgrading rewrites every akm-managed scheduler row once, in place. Each row now sets its own AKM_BUNDLE_DIR (plus any AKM_CONFIG_DIR/AKM_DATA_DIR/AKM_CACHE_DIR/AKM_STATE_DIR the syncing shell had set explicitly) inline, instead of pointing at a --scheduler-context descriptor, and a crontab's PATH moves the same way, into a # akm:env block next to the task rows. The rewrite keeps each row's existing launcher and schedule -- it is reported as an update, never an add or a remove -- and rows written by 0.9.0 through 0.9.16 keep firing normally until that sync runs. Once akm task doctor lists no binding still pointing at a descriptor file, the old $DATA/tasks/context/ files can be deleted.

akm improve now reworks only what retrieval actually returned -- an asset a real search, curate, show, or feedback touched in the last 90 days -- plus material no improve stage has processed yet. The proactive-maintenance and high-salience lanes, and the memory consolidation judge, no longer reach into the unread tail of a stash; an asset left out this way shows up under a new retrieval gate in akm improve --dry-run and under akm health's not_retrieved skip reason, not silently.

Consolidation gets a second pass. It compares each new-or-changed memory, flat knowledge/ file, or lesson against its nearest neighbours, and where an LLM judge calls a pair duplicate, subsumed, or superseding, it mints a reviewed retire proposal for the losing side -- nothing is retired automatically. Review these like any other proposal: akm proposal list --generator consolidate-pair (or just akm proposal list, which flags one carrying continuity risk inline), show, diff, then accept or reject. Accepting one archives the losing file instead of deleting it, and akm proposal revert restores it exactly; archived files are only deleted 30 days after retirement, and only once git holds them clean and unmodified. Accepting a promotion (a consolidate promote proposal, by a person or by triage auto-promotion) now also archives the source memory it was promoted from, so a promotion no longer leaves a duplicate sitting next to the knowledge doc it produced.

akm proposal drain, and improve's own triage pre-pass, no longer take a policy. Both now accept only a proposal the quality judge passed on its exact content and reject an empty diff; everything else goes to processes.triage.judgment or waits for review -- including extract and consolidate proposals, which used to be auto-accepted on size alone under the personal-stash default.

akm show no longer has a related field. It lists an asset's links instead: the relations a bundle already declares -- cross-references, supersededBy, a .derived memory's parent, a wiki's citations, resolved page links, a workflow's or task's target -- grouped outgoing/incoming/unresolved, computed with no LLM call. Curate's support refs are drawn from the same links now, not from the retired entity graph.

akm info always exits 0 and always prints a report, even when something is wrong: an invalid config.json, a missing or unreadable bundle directory, or a locked/newer/corrupt index.db is named in the report (configError, bundleDirError, indexStats.unavailable) instead of failing the command or showing unexplained zeros. It also reports link counts per kind, including how many are unresolved.

Decide every pending retire proposal -- akm proposal accept or reject -- before downgrading to 0.9.16. Older releases predate the retire proposal shape entirely: akm proposal show/diff/drain exits 70 on one it doesn't recognize, 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 for the one proposal.

0.9.16 already refuses to open a newer-layout index.db outright (INDEX_SCHEMA_INCOMPATIBLE, naming the upgrade) and leaves the file untouched, so downgrading needs a fresh index: move index.db aside and run akm index --full under 0.9.16, which re-embeds everything from scratch.

A workflow run started under 0.9.17 freezes its plan as irVersion 6, which 0.9.16 does not understand and refuses to resume (WORKFLOW_IR_VERSION_UNSUPPORTED) -- let any in-flight workflow runs finish before downgrading, or plan to restart them fresh under 0.9.16.

The state.db migration that adds the improve ledger (028-improve-ledger) drops six tables 0.9.16 and earlier used (proposal_fingerprints and friends). Because it drops schema, the akm that runs it first copies the database to state.db.pre-028-improve-ledger.bak before making the change. That backup is a snapshot from the moment of upgrade -- restoring it to downgrade discards every proposal, event, and run state.db has recorded since, not just the ledger's own six tables, so treat it as a last resort rather than routine.