using Microsoft.EntityFrameworkCore.Migrations; #nullable disable namespace ClaudeDo.Data.Migrations { /// public partial class RetireLegacyTaskStatus : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) { // manual / draft -> idle migrationBuilder.Sql("UPDATE tasks SET status = 'idle' WHERE status IN ('manual', 'draft');"); // planning -> idle + planning_phase=active migrationBuilder.Sql("UPDATE tasks SET status = 'idle', planning_phase = 'active' WHERE status = 'planning';"); // planned -> idle + planning_phase=finalized migrationBuilder.Sql("UPDATE tasks SET status = 'idle', planning_phase = 'finalized' WHERE status = 'planned';"); // waiting -> queued + blocked_by_task_id derived from sort_order chain. // SQLite 3.25+ supports window functions (LAG). migrationBuilder.Sql(@" WITH ordered AS ( SELECT id, LAG(id) OVER (PARTITION BY parent_task_id ORDER BY sort_order, created_at) AS prev_id FROM tasks WHERE status = 'waiting' ) UPDATE tasks SET status = 'queued', blocked_by_task_id = (SELECT prev_id FROM ordered WHERE ordered.id = tasks.id) WHERE id IN (SELECT id FROM ordered);"); } /// protected override void Down(MigrationBuilder migrationBuilder) { // Best-effort and lossy: cancelled is folded back into failed, // (idle, finalized) -> planned, (idle, active) -> planning, // queued + blocked_by_task_id != null -> waiting. // Manual/Draft distinction is unrecoverable — anything previously // 'manual' or 'draft' stays 'idle' on the way back. migrationBuilder.Sql("UPDATE tasks SET status = 'failed' WHERE status = 'cancelled';"); migrationBuilder.Sql("UPDATE tasks SET status = 'planned' WHERE status = 'idle' AND planning_phase = 'finalized';"); migrationBuilder.Sql("UPDATE tasks SET status = 'planning' WHERE status = 'idle' AND planning_phase = 'active';"); migrationBuilder.Sql("UPDATE tasks SET status = 'waiting', blocked_by_task_id = NULL WHERE status = 'queued' AND blocked_by_task_id IS NOT NULL;"); } } }