migrate_promote_template_sessions_v1

Function migrate_promote_template_sessions_v1 

Source
pub fn migrate_promote_template_sessions_v1(
    wstore: &Arc<WaveStore>,
    filestore: &Arc<FileStore>,
    _data_dir: &Path,
) -> TemplatePromoteStats
Expand description

Phase 1 two-tier picker migration: promote any seeded template that carries a session zone into a fresh user-owned definition, then move its :current + :archive:* zones onto the new definition_id.

Why this exists (Q1 = Option C in docs/specs/SPEC_AGENT_PICKER_TWO_TIER_2026_05_24.md): after the picker UI split, clicking a “template” card in the Templates section MUST create a new agent — not silently append to whatever session the user previously ran against that template directly (e.g. “Maks’s conversation” living at agent:claude:current). Without this migration the template card would either reattach to the existing session (broken — wrong intent) or be effectively non-functional. The migration moves any such pre-existing session out of the template namespace onto a new user-owned definition so the template is pristine post-migration.

Algorithm:

  1. List zone ids; partition the agent:<id>:current and agent:<id>:archive:* zones by definition id.
  2. For each definition id with at least one zone, look up the matching db_agent_definitions row.
    • Skip if missing (zone refers to a deleted definition).
    • Skip if is_seeded = 0 (already user-owned — no work).
    • Otherwise: clone the template into a new user definition (mirrors agent_def_create_from_template semantics).
  3. Pick the new name: most-recently-active named instance’s instance_name if any exists, else fall back to the template’s own name.
  4. Move every matching zone (:current + every :archive:*) from the old defId to the new defId via FileStore’s existing write-then-delete pattern.
  5. Repoint every db_agent_instances row that referenced the old defId to point at the new defId (preserves the continueOfInstanceId reattach flow).

Idempotency: the migration is self-gated on the data invariant (“no seeded def has a session zone”). It runs on every startup; when the invariant already holds the inner loop has zero iterations and returns the default stats in sub-ms. There used to be a marker-file gate (TEMPLATE_PROMOTE_MARKER_V1), but it produced an “early-marker” failure mode: a portable launched at v N had no seeded-def zones, set the marker, and on v N+1 startups (when seeded-def zones DID exist from prior real use) the marker caused the migration to skip. The 2026-05-24 rework dropped the marker check; this is safe because the seeded-def-with-zone invariant is detectable per-startup at constant cost. data_dir is retained for API compatibility.

Failure mode: per-template errors are logged + counted; we DO NOT abort startup. Errors that prevent a template from being promoted leave its zones in place; the next startup retries (no marker gate to block retry).