Skip to main content

Module m0025_agents_launch_state_backfill

Module m0025_agents_launch_state_backfill 

Source
Expand description

Backfill db_agents’ latest-launch state (schema v29: session_id, status, started_at, ended_at, and last_block_id where still empty) from the legacy db_agent_instances rows.

Agent-concept consolidation, Phase 3b (SPEC_AGENT_ARCHITECTURE_2026_05_27.md): these four columns are what kept the legacy table alive — the recent-sessions picker, the pane close/reopen continuity write-back and the status-filtered instance list all read them from db_agent_instances. Once every consolidated row carries its own launch state, those reads can flip and the table can go.

Rule: for each projection key (the db_agents row an instance chain maps to — the chain head’s own id for a template launch, the user-clone definition’s id for a launch of a user agent) take the most recently created instance in the chain and copy its launch state, but only into a row whose launch state is still entirely default. That makes the migration idempotent and means it never overwrites state the dual-write has written since v29 shipped. Channel-scoped: each channel’s objects.db has its own rows.

Frozen copy of dual_write::agents_projection_key_for_inst’s rule (as of v29) — deliberately not a call into it, per this module’s “freeze copies of live logic” doc: dual_write is deleted when the legacy table is dropped, and this migration must keep producing the same rows on every machine it ever runs on.

Tolerates a store that has already dropped db_agent_instances (Phase 3c): nothing to backfill, Ok.

Structs§

BackfillStats 🔒
What the backfill did. projected counts template-launch chains whose consolidated row was missing and had to be created first; updated counts rows that received launch state.
LegacyInstance 🔒
The legacy instance columns the backfill reads.
M0025AgentsLaunchStateBackfill

Functions§

backfill_launch_state 🔒
The backfill proper, on an open connection.
frozen_repair_def_gaps 🔒
Frozen copy of agents_consolidate::repair_def_gaps as it existed when this migration was written (deleted from live code by the definition flip — nothing writes db_agent_definitions without also writing db_agents any more, so the gap this backfills can no longer open going forward; it can still exist on an install upgrading THROUGH this exact migration from a pre-flip version, which is what this migration must keep repairing on every machine it ever runs on). Backfill any db_agent_definitions row missing from db_agents. INSERT OR IGNORE, so idempotent. Returns the number of rows inserted.
project_template_launch_row 🔒
Create the consolidated row for a template-launch chain whose head has no db_agents row yet — the “Phase 3a stamped, db_agents partially populated” upgrade shape (codex P1 on #3075). Without this the UPDATE below affects zero rows, the migration is still recorded applied, and the chain’s session/status is unreachable once readers flip. Frozen copy of the consolidate pass-3 / dual-write head-INSERT column mapping as of v29, INSERT OR IGNORE so it can never clobber a row that appeared in between. Ok(false) when the definition itself is gone — nothing to project against (the legacy FK cascade would have removed such an instance; if it survived it is an orphan).
projection_key 🔒
Frozen copy of the v29 projection rule: walk parent_instance_id to the chain root; if the root’s definition is a user-clone (is_seeded = 0) the key is that definition’s id (the launch was folded into the def’s row), otherwise it is the root instance’s own id (a template launch is its own row). A missing definition counts as seeded, matching the COALESCE(d.is_seeded, 1) in the live helper. A chain whose parent pointer no longer resolves is rooted at the last instance that does.