Expand description
Global migration: backfill user-agent DEFINITIONS (with their content +
skills) from every channel’s per-version objects.db — and every dev/
branch DB — into the GLOBAL definition store, so EXISTING agents become
cross-channel without waiting for the next edit. Read-only on every scanned
SQLite.
Version-gated, re-runnable marker (not strictly one-shot): the
.migrated_definitions marker in the store root records the
MIGRATION_VERSION that last ran. A marker older than the current version
— including the legacy migrated text, which parses as version 0 — re-runs
the scan ONCE, so users whose earlier pass was incomplete recover
automatically on the next launch. Bump MIGRATION_VERSION whenever the
scan logic changes to trigger a one-time re-run for everyone.
On a re-run, an agent already in the global store is refreshed only when the scanned copy is strictly fresher than the global record (so a broken earlier pass’s stale/content-less copy is corrected) — never downgraded below what the live write-mirror has since advanced, and never resurrected if tombstoned. (codex P1 / reagent P2 #1391.)
Cross-channel agent persistence, P0.2d
(docs/specs/SPEC_CROSS_CHANNEL_AGENT_PERSISTENCE_2026-06-13.md).
Resilience mirrors scripts/import-agents.sh: a single unreadable / locked
/ old-schema objects.db is skipped with a warning, never aborting the
pass. The marker is written after a pass even if some DBs were skipped — a
transiently-skipped DB’s agents still go global on their next edit via the
live write-mirror (P0.2b), and a future MIGRATION_VERSION bump re-scans
everything — so nothing is permanently lost and the migration never loops
forever on a permanent old-schema failure.
Structs§
- DefMigrate
Stats - Outcome stats — surfaced in the srv log.
Constants§
- DEF_
COLUMNS 🔒 db_agent_definitionscolumns in the order the row mapper expects, paired with a default SQL literal used when a column is absent on an older DB. Substituting<default> AS <col>keeps the SELECT’s column count + order fixed (so index-basedrow.getstays valid) while tolerating schema drift.- MARKER 🔒
- MIGRATION_
VERSION 🔒 - Migration-logic version. Bump whenever the scan changes (new roots, schema
handling, etc.) so existing users re-run the migration ONCE: the marker
stores this number; a marker older than this re-runs. The pre-v2 marker
held the literal text
migrated, which parses as version 0 → re-runs, recovering everyone whose first pass was incomplete.
Functions§
- collect_
scan_ 🔒dbs - Every
…/data/db/objects.dbunderhome/channels/*/versions/*ANDhome/dev/<branch>[/<sub>]. The instance migration scans both (migrate.rs::enumerate_sources); the definition migration must too, or dev-branch agents (e.g. agents created viatask dev) never go global. - dir_
subdirs 🔒 - is_
missing_ 🔒table - True iff the error is SQLite “no such table” (a pre-v2 DB missing db_agent_content / db_agent_skills) — the only failure we treat as “no rows” rather than a reason to skip the DB.
- marker_
version 🔒 - Migration version recorded in the marker;
0when absent or unparseable (the legacymigratedtext → 0 → re-run). - max_ts 🔒
MAX(col)over a per-agent table;0when the table is missing (pre-v2) or there are no rows. Other errors propagate (→ DB skipped).- migrate_
definitions_ global_ once - Scan every channel AND dev-branch
objects.dbunderhomefor user agents and backfill them into the global definitionstore. Re-runs once perMIGRATION_VERSIONbump (marker instore.root()); read-only on every scanned SQLite, and tolerant of older schemas (missing columns). - present_
columns 🔒 - Column names present in
table(empty set if the table doesn’t exist —PRAGMA table_infoon a missing table yields no rows, not an error). - read_
content 🔒 - read_
skills 🔒 - read_
user_ 🔒definitions - Read all
is_seeded=0definitions fromdbwith their content + skills, each paired with a freshness timestamp for cross-copy winner selection. - tolerate_
missing_ 🔒table - write_
marker 🔒