UNPKG

@kontextmind/kxm

Version:

KXM local-first multi-agent orchestration and operator dashboard

55 lines (46 loc) • 4.08 kB
# Migration and compatibility **KXM carries no migration path.** The product ships for a single operator, and the operator decision (recorded in [`plans/implementation-plan.md`](../../plans/implementation-plan.md)) is that older state is replaced, not converted. Old names are not accepted; old state is refused loudly. This page documents what that means at each boundary so no one re-adds a compatibility lane by inference. ## What happens to older input | Boundary | Behaviour | |---|---| | Project tree with legacy `.kxm/config` JSON | `loadKxmProject` fails closed with `legacy_state_unsupported`, one issue per legacy file. No receipt, plan, flag, or environment variable unlocks it. | | `kxm init` on such a tree | Reports `mode: "legacy"`, lists `legacyInputs`, performs **no writes**. Recovery is a fresh project directory plus the YAML definitions worth keeping. | | `kxm migrate` | Unknown command. It existed as `plan` / `apply` / `verify` for pre-KXM JSON and was deleted with this decision. | | SQLite store stamped with an older `user_version` | Hub stores and Runtime event stores are refused with `runtime_schema_outdated`. That refusal never advances `user_version`. Delete the state file and let the process that owns it recreate the store (`kxm hub start` for hub state, the Runtime for event stores). `kxm init` is **project-only** and rebuilds no database. The Runtime registry is the exception: schema 1 is copied to schema 2 in place, existing rows stay, and `lane_of` is null on those rows. Forward-only stamping of any other store is prohibited, because it turns a clean failure into a later query against a column that does not exist. | | Retired product and command names | Rejected by fail-closed brakes (lint + readiness tests), not aliased. | | Shared/off-scope Pi history | Never imported into a narrower run scope. A new physical session starts clean; durable facts come from Git, workflow evidence, artifacts, or promoted context. | | Historical run records | Never fabricated. Events whose real ordering was not observed stay absent rather than reconstructed into a finer-grained model. | ## What is *not* relaxed by this Deleting conversion code does not soften the guarantees around the state that does exist: - **Fresh installs must be complete.** Every table, index, and default that a store needs is declared in its current schema definition, so an empty store is valid without any upgrade step. - **Backups stay whole.** The hub state set is copied as documented in [Back up and restore KXM](../operations/backup-and-restore.md); a single `kxm.db` copy is not a backup. - **Out-of-range versions refuse without touching the file.** The stamp is read before anything that can modify the store, so a database this build refuses, older or newer, comes back byte-identical: neither its schema nor its `user_version` changes, and it is not converted to WAL as a side effect of being rejected. A store ahead of this build is refused without downgrade. The registry schema 1 to 2 copy is not a refusal: that file is rewritten, and every other older store is still refused untouched. - **Schema changes are additive-and-replace, not in-place,** except the Runtime registry's `lane_of` column. For every other store, land the new definition, delete the local state, and let the process that owns each store recreate it. `kxm hub start` recreates hub state. The Runtime recreates event stores. `kxm init` is project-only and rebuilds no database. Nothing else in the runtime may rewrite an existing store's shape. Opening a schema 1 registry copies its rows into schema 2 and leaves `lane_of` null. ## If this ever changes Re-introducing migration needs a written decision first, because the cost is not the converter — it is the permanent dual-read surface (legacy names staying loadable, receipts that unlock state, and a test matrix that must keep proving both sides). Any such proposal has to name the state it protects and who owns it; "someone might have an old directory" is not a reason on its own.