Expand description
Data migration framework.
Migrations are versioned steps that run once, either via agentmux-srv migrate
or in-process at startup via run_pending_migrations (called unconditionally;
fast-paths to Ok(0) when already current). The in-process path runs before
any store is opened for normal operation so that id_store always binds to a
fully-backfilled shared store.
Adding a migration: implement Migration, add it to REGISTRY, add a
file under this module. The ID must be unique and lexicographically ordered
(use the NNNN_slug convention). Retiring old migrations: remove from
REGISTRY once the minimum supported upgrade path passes the migration’s
origin version — the db_migrations row stays as a permanent record.
§No private marker files
db_migrations (plus a Migration::verify post-condition) is the sole
source of truth for “has this run” — SPEC_MIGRATION_SYSTEM_HARDENING_2026_08_03
Phase 2. A new migration must not introduce its own flag file, and no
migration may treat the mere existence of a marker as proof of
completion: that is the shape that left 0007’s target table empty
while its flag said “done” (§1.2, F1). The three legacy markers that
remain are evidence only — 0007’s and 0002’s helpers decide from the
data (consolidate_looks_incomplete, block_zones_look_incomplete) and
are content-idempotent, 0003’s helper ignores its marker and re-asserts
its invariant every run — and m0000_bootstrap consults them only
together with those content checks when stamping a pre-framework install.
§Migrations freeze copies of live logic on purpose
Some migrations carry verbatim copies of helpers that also exist in live
code: m0017_ambient_login_grandfather mirrors ~35 lines of
backend/blockcontroller/core.rs; m0020_agent_color_backfill and
m0021_backfill_agent_bundles mirror 25–30 lines each of
backend/storage/mcp_servers.rs and def_registry_mirror.rs. That is
deliberate, not accidental duplication. A migration must produce the same
rows on every machine it ever runs on, so it cannot call a live helper
whose behaviour a later release may change; the copy pins the logic as it
was at the migration’s origin version. Do not “deduplicate” a migration
against live code. When you copy logic into a new migration, say so next
to the copy — // frozen copy of <path>::<fn> as of <version> — so the
next reader can tell a freeze from a drift.
Re-exports§
pub use runner::count_pending_migrations;pub use runner::doctor_report_for_instance;pub use runner::run_migrate_command;pub use runner::run_pending_migrations;pub use runner::try_count_pending_migrations;pub use runner::PendingCountError;
Modules§
- m0000_
bootstrap 🔒 - Bootstrap: stamp all pre-framework migrations as applied for existing users.
- m0001_
legacy_ 🔒data_ dir - m0002_
block_ 🔒zones_ v1 - m0003_
template_ 🔒sessions_ v1 - m0004_
registry_ 🔒from_ sqlite - m0005_
registry_ 🔒source_ bases - m0006_
definitions_ 🔒global - m0007_
agents_ 🔒consolidate - m0008_
default_ 🔒bundle - Seed Default OAuth identity bundle from ambient credentials — historical.
- m0009_
transcript_ 🔒backfill - m0010_
session_ 🔒ids - m0011_
shared_ 🔒store_ backfill - m0012_
dedup_ 🔒identity_ accounts - Deduplicate identity accounts that share the same (provider, credential).
- m0013_
agent_ 🔒direct_ bindings - Backfill direct agent↔account links from bundle bindings — historical.
- m0014_
agent_ 🔒direct_ bindings_ rerun - Re-run the direct agent↔account link backfill to catch instances
launched in the gap between
m0013’s original run and the launch flow write-through landing (PR B1, #1950) — historical. - m0015_
seed_ 🔒starter_ skills - Seed the global Skills catalog (
db_skills, per-channel) with a curated starter set on fresh install. - m0016_
seed_ 🔒starter_ mcp_ servers - Seed the global MCP Servers catalog (
db_mcp_servers, per-channel) with a curated, credential-free starter set on fresh install. - m0017_
ambient_ 🔒login_ grandfather - Grandfather the layer-3
use_ambient_loginopt-in for pre-existing agents (spec §2.4 of SPEC_ACCOUNT_DELETE_DEAUTH_LAYERS_2_4_2026_07_14.md). - m0018_
ambient_ 🔒login_ registry - Grandfather
use_ambient_loginon the GLOBAL cross-channel definition registry (~/.agentmux/shared/agents/definitions/) — the sibling ofm0017_ambient_login_grandfather, which handles the per-channel SQLite projections. - m0019_
repair_ 🔒malformed_ secret_ ref - Repair
db_accounts.secret_refrows whose JSON was corrupted by an out-of-band edit of the shared store — found live: a raw Windows path pasted into the JSON string with its backslashes never escaped ({"backend":"oauth_config_dir","dir":"C:\Users\..."}, valid JSON needs\\per separator). Not reproducible from any write path in this codebase (Store::identity_upsertalwaysserde_json::to_strings correctly) — seeANALYSIS_ARMORY_STASH_CREDENTIAL_VISIBILITY_GAP_2026_08_04 (never committed to this repo)§7 for the full incident. - m0020_
agent_ 🔒color_ backfill - Backfill a display color (
agent_contentui:color) for every existing agent definition that doesn’t have one — the “generate a random color for all the existing agents” one-time script fromdocs/specs/SPEC_AGENT_COLOR_2026_08_08.md. - m0021_
backfill_ 🔒agent_ bundles - Backfill a dedicated ABF bundle for every existing agent definition that
doesn’t have one — the data-migration half of
docs/specs/ARCHITECTURE_MANDATORY_ABF_RETHINK_2026_08_14.md§3/§7: “every agent must have an ABF,” and, at the time, that ABF carried its own provider/model (readonly once set by a bundle-level guard). Since SPEC_AGENT_BUNDLE_FORMAT_V0_3_2026_10_05.md §3 the bundle carries no harness: the agent owns its provider, locked byapp_api::check_provider_unchanged, andm0035reconciles agents with the bundles this migration wrote. - m0022_
identity_ 🔒store_ links_ backfill - Backfill
db_agent_identity_links, plus adb_accountsfallback mirror (reagentx P0 review, added after this migration’s first version — seeidentity::resolver::inject::resolve_account’s own doc comment for why the mirror is needed even thoughdb_accountsitself stays onid_storeas the authoritative store), from every reachable store into the new, permanently-global identity store — seedocs/specs/SPEC_IDENTITY_STORE_SPLIT_2026_08_17.md. - m0023_
native_ 🔒memory_ versions_ backfill - Backfill
db_agent_native_memory_versionswith onesource: "agent_inferred"version per existingdb_agent_native_memoryrow — reagent P1 (re-review of PR #2674): the spec this migration completes (docs/specs/SPEC_MEMORY_VERSION_CONTROL_AND_ARMORY_AUDIT_2026_08_19.md§9 Rollout) explicitly calls for this backfill so history views aren’t empty for pre-existing memory on upgrade. Without it, an existing user’s first post-upgrade overwrite of a memory file records only the NEW content as version 1 — the prior live content (everything that file held before this feature shipped) is permanently unrecoverable viaMemoryRevert/MemoryDiff. - m0024_
native_ 🔒memory_ backfill_ from_ fs - Finish the job
m0023was meant to do, and repair the label it left behind —SPEC_MEMORY_VERSION_CONTROL_AND_ARMORY_AUDIT_2026_08_19.md§9 (rollout backfill) and §4.5 (drift detection). - m0025_
agents_ 🔒launch_ state_ backfill - Backfill
db_agents’ latest-launch state (schema v29:session_id,status,started_at,ended_at, andlast_block_idwhere still empty) from the legacydb_agent_instancesrows. - m0026_
registry_ 🔒agent_ id_ rekey - Re-key the named-agent registry from launch ids to agent ids.
- m0027_
agents_ 🔒workspace_ backfill - Backfill
db_agents.working_directorywith the workspace each agent actually ran in, taken from its latest legacydb_agent_instanceslaunch. - m0028_
agent_ 🔒child_ tables_ repoint_ fk - Re-point six agent-child tables’
agent_idforeign key fromdb_agent_definitions(id)todb_agents(id). - m0029_
drop_ 🔒legacy_ agent_ tables - Drop
db_agent_definitionsanddb_agent_instances— the two legacy tables the agent-concept consolidation retires. - m0030_
backfill_ 🔒bundle_ component_ refs - Backfill
db_bundle_skills_reffrom the inlinedb_bundles.skillsJSON column. - m0031_
carry_ 🔒skills_ and_ mcp_ servers_ to_ identity_ store - Carry each channel’s
db_skills/db_mcp_serversrows into the permanently-global identity store, which became authoritative for them in Phase 2a (IDENTITY_STORE_SCHEMA_VERSIONv6/v7 — seeSPEC_DURABLE_BINDINGS_2026_09_10.md§7 Phase 2). - m0032_
drop_ 🔒catalog_ fk_ from_ ref_ tables - Drop the
skill_id/mcp_idforeign key from all four skill/MCP ref tables (db_agent_skills_ref,db_agent_mcp_ref,db_bundle_skills_ref,db_bundle_mcp_ref), leaving every other constraint verbatim (the agent-level pair’sagent_id → db_agentsFK, everyPRIMARY KEY, all column types). - m0033_
narrow_ 🔒skill_ global_ uniqueness_ index - Narrow the global skill uniqueness index from
(name, skill_type)tonamealone, matching the invariantskill_upsert_unique_global’s own dup-check has always enforced — with a defensive dedup pass for any existing same-name/different-type pair the OLD, wider index let through. - m0034_
identity_ 🔒history_ backfill - One-time sweep for identity conversation history stranded before
ensure_history_link(SPEC_AGENT_IDENTITY_HISTORY_PERSISTENCE_PROTOCOL_2026_08_16.md, shipped in0007c6b64051e8/ PR #2605) existed to keep it linked into the always-globalshared/identities/<id>/<provider>/<subdir>/tree. - m0035_
agent_ 🔒owns_ its_ provider - Give every agent the provider it actually runs with, before the bundle
stops deciding it (
docs/specs/SPEC_AGENT_BUNDLE_FORMAT_V0_3_2026_10_05.md§3.3). - m0036_
drop_ 🔒bundle_ mcp - Bundles stop carrying MCP servers: they belong to Connectors
(
docs/specs/SPEC_BUNDLE_CONTENTS_MEMORY_NOT_MCP_2026_10_07.md§3.1, D3). - m0037_
retire_ 🔒old_ pane_ names - Rewrites the retired pane names in stored data, once, so the frontend and srv can drop the
shims that translated them on every read. The Armory (and the Trust Center before it) was
split into Connectors and Memory, the Knowledge pane was renamed Memory, and Remotes became a
section of Connectors (
SPEC_RETIRE_ARMORY_CONNECTORS_AND_KNOWLEDGE_PANES_2026_10_05.mdPhase 3,SPEC_RENAME_KNOWLEDGE_TO_MEMORY_2026_10_06.md,SPEC_REMOTES_INTO_CONNECTORS_2026_10_08.md). - runner 🔒
- Migration runner — invoked by
agentmux-srv migrate(a CLI subcommand, and the now-deadagentmux-launcher::srv_spawner::run_migratesubprocess path) and, separately, in-process at every srv boot viarun_pending_migrations.
Structs§
- Migration
Context - Context passed to every migration’s
up()call. - Migration
Error
Enums§
- Migration
Scope - Verify
Outcome - Result of an applied migration’s post-condition check
(
agentmux-srv migrate --verify, SPEC_MIGRATION_SYSTEM_HARDENING_2026_08_03 Phase 1).db_migrationsrecords only thatup()returnedOk— never that it wrote what it was meant to. A migration that can state its own effect as a cheap query implementsMigration::verify; the rest reportNotVerifiableand the doctor pass says so rather than guessing.
Statics§
- REGISTRY 🔒