The incremental chain was ~31k lines of generated Designer snapshots for a schema no shipped database steps through anymore. MigrateAndConfigure now baselines an existing DB onto the squashed id (pre-EF, or history ending at AddPrimeActionKind) and throws with a reinstall message for a mid-chain DB. MigrationBaselineTests covers all three paths with a real Migrate().
450 lines
24 KiB
C#
450 lines
24 KiB
C#
using System;
|
|
using Microsoft.EntityFrameworkCore.Migrations;
|
|
|
|
#nullable disable
|
|
|
|
namespace ClaudeDo.Data.Migrations
|
|
{
|
|
/// <inheritdoc />
|
|
public partial class InitialCreate : Migration
|
|
{
|
|
/// <inheritdoc />
|
|
protected override void Up(MigrationBuilder migrationBuilder)
|
|
{
|
|
migrationBuilder.CreateTable(
|
|
name: "app_settings",
|
|
columns: table => new
|
|
{
|
|
id = table.Column<int>(type: "INTEGER", nullable: false),
|
|
next_task_number = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 1),
|
|
default_claude_instructions = table.Column<string>(type: "TEXT", nullable: false, defaultValue: ""),
|
|
default_model = table.Column<string>(type: "TEXT", nullable: false, defaultValue: "sonnet"),
|
|
default_max_turns = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 40),
|
|
default_permission_mode = table.Column<string>(type: "TEXT", nullable: false, defaultValue: "bypassPermissions"),
|
|
max_turns_ceiling = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 80),
|
|
max_parallel_executions = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 1),
|
|
worktree_strategy = table.Column<string>(type: "TEXT", nullable: false, defaultValue: "sibling"),
|
|
central_worktree_root = table.Column<string>(type: "TEXT", nullable: true),
|
|
worktree_auto_cleanup_enabled = table.Column<bool>(type: "INTEGER", nullable: false, defaultValue: false),
|
|
worktree_auto_cleanup_days = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 7),
|
|
repo_import_folders = table.Column<string>(type: "TEXT", nullable: true),
|
|
report_excluded_paths = table.Column<string>(type: "TEXT", nullable: true),
|
|
standup_weekday = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 3),
|
|
daily_prep_max_tasks = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 5),
|
|
session_skills = table.Column<string>(type: "TEXT", nullable: true),
|
|
model_presets = table.Column<string>(type: "TEXT", nullable: true),
|
|
usage_gate_five_hour_pct = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 80),
|
|
usage_gate_seven_day_pct = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 90),
|
|
usage_throttle_five_hour_soft_pct = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 50),
|
|
usage_throttle_five_hour_hard_pct = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 65),
|
|
usage_throttle_seven_day_soft_pct = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 50),
|
|
usage_throttle_seven_day_hard_pct = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 65),
|
|
auto_continue_on_usage_limit = table.Column<bool>(type: "INTEGER", nullable: false, defaultValue: false)
|
|
},
|
|
constraints: table =>
|
|
{
|
|
table.PrimaryKey("PK_app_settings", x => x.id);
|
|
});
|
|
|
|
migrationBuilder.CreateTable(
|
|
name: "daily_notes",
|
|
columns: table => new
|
|
{
|
|
id = table.Column<string>(type: "TEXT", nullable: false),
|
|
note_date = table.Column<DateOnly>(type: "TEXT", nullable: false),
|
|
text = table.Column<string>(type: "TEXT", nullable: false),
|
|
sort_order = table.Column<int>(type: "INTEGER", nullable: false),
|
|
created_at = table.Column<DateTime>(type: "TEXT", nullable: false)
|
|
},
|
|
constraints: table =>
|
|
{
|
|
table.PrimaryKey("PK_daily_notes", x => x.id);
|
|
});
|
|
|
|
migrationBuilder.CreateTable(
|
|
name: "lists",
|
|
columns: table => new
|
|
{
|
|
id = table.Column<string>(type: "TEXT", nullable: false),
|
|
name = table.Column<string>(type: "TEXT", nullable: false),
|
|
created_at = table.Column<DateTime>(type: "TEXT", nullable: false),
|
|
working_dir = table.Column<string>(type: "TEXT", nullable: true),
|
|
default_commit_type = table.Column<string>(type: "TEXT", nullable: false, defaultValue: "chore"),
|
|
sort_order = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 0),
|
|
is_manual = table.Column<bool>(type: "INTEGER", nullable: false, defaultValue: false),
|
|
findings_tracked = table.Column<bool>(type: "INTEGER", nullable: false, defaultValue: false)
|
|
},
|
|
constraints: table =>
|
|
{
|
|
table.PrimaryKey("PK_lists", x => x.id);
|
|
});
|
|
|
|
migrationBuilder.CreateTable(
|
|
name: "prime_schedules",
|
|
columns: table => new
|
|
{
|
|
id = table.Column<Guid>(type: "TEXT", nullable: false),
|
|
days_of_week = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 31),
|
|
action_kind = table.Column<string>(type: "TEXT", nullable: false, defaultValue: "ping"),
|
|
time_of_day = table.Column<TimeSpan>(type: "TEXT", nullable: false),
|
|
enabled = table.Column<bool>(type: "INTEGER", nullable: false, defaultValue: true),
|
|
last_run_at = table.Column<DateTimeOffset>(type: "TEXT", nullable: true),
|
|
prompt_override = table.Column<string>(type: "TEXT", nullable: true),
|
|
created_at = table.Column<DateTimeOffset>(type: "TEXT", nullable: false)
|
|
},
|
|
constraints: table =>
|
|
{
|
|
table.PrimaryKey("PK_prime_schedules", x => x.id);
|
|
});
|
|
|
|
migrationBuilder.CreateTable(
|
|
name: "session_skills",
|
|
columns: table => new
|
|
{
|
|
name = table.Column<string>(type: "TEXT", nullable: false),
|
|
source_url = table.Column<string>(type: "TEXT", nullable: false),
|
|
pinned_ref = table.Column<string>(type: "TEXT", nullable: false),
|
|
subpath = table.Column<string>(type: "TEXT", nullable: false),
|
|
description = table.Column<string>(type: "TEXT", nullable: false),
|
|
added_at = table.Column<DateTimeOffset>(type: "TEXT", nullable: false)
|
|
},
|
|
constraints: table =>
|
|
{
|
|
table.PrimaryKey("PK_session_skills", x => x.name);
|
|
});
|
|
|
|
migrationBuilder.CreateTable(
|
|
name: "week_reports",
|
|
columns: table => new
|
|
{
|
|
id = table.Column<string>(type: "TEXT", nullable: false),
|
|
start_date = table.Column<DateOnly>(type: "TEXT", nullable: false),
|
|
end_date = table.Column<DateOnly>(type: "TEXT", nullable: false),
|
|
markdown = table.Column<string>(type: "TEXT", nullable: false),
|
|
generated_at = table.Column<DateTime>(type: "TEXT", nullable: false)
|
|
},
|
|
constraints: table =>
|
|
{
|
|
table.PrimaryKey("PK_week_reports", x => x.id);
|
|
});
|
|
|
|
migrationBuilder.CreateTable(
|
|
name: "list_config",
|
|
columns: table => new
|
|
{
|
|
list_id = table.Column<string>(type: "TEXT", nullable: false),
|
|
model = table.Column<string>(type: "TEXT", nullable: true),
|
|
system_prompt = table.Column<string>(type: "TEXT", nullable: true),
|
|
agent_path = table.Column<string>(type: "TEXT", nullable: true),
|
|
max_turns = table.Column<int>(type: "INTEGER", nullable: true),
|
|
session_skills = table.Column<string>(type: "TEXT", nullable: true),
|
|
verify_command = table.Column<string>(type: "TEXT", nullable: true),
|
|
serialize_on_file_overlap = table.Column<bool>(type: "INTEGER", nullable: false, defaultValue: false)
|
|
},
|
|
constraints: table =>
|
|
{
|
|
table.PrimaryKey("PK_list_config", x => x.list_id);
|
|
table.ForeignKey(
|
|
name: "FK_list_config_lists_list_id",
|
|
column: x => x.list_id,
|
|
principalTable: "lists",
|
|
principalColumn: "id",
|
|
onDelete: ReferentialAction.Cascade);
|
|
});
|
|
|
|
migrationBuilder.CreateTable(
|
|
name: "tasks",
|
|
columns: table => new
|
|
{
|
|
id = table.Column<string>(type: "TEXT", nullable: false),
|
|
number = table.Column<int>(type: "INTEGER", nullable: false),
|
|
list_id = table.Column<string>(type: "TEXT", nullable: false),
|
|
title = table.Column<string>(type: "TEXT", nullable: false),
|
|
description = table.Column<string>(type: "TEXT", nullable: true),
|
|
status = table.Column<string>(type: "TEXT", nullable: false),
|
|
planning_phase = table.Column<string>(type: "TEXT", nullable: false, defaultValue: "none"),
|
|
blocked_by_task_id = table.Column<string>(type: "TEXT", nullable: true),
|
|
depends_on_task_id = table.Column<string>(type: "TEXT", nullable: true),
|
|
scheduled_for = table.Column<DateTime>(type: "TEXT", nullable: true),
|
|
result = table.Column<string>(type: "TEXT", nullable: true),
|
|
review_feedback = table.Column<string>(type: "TEXT", nullable: true),
|
|
roadblock_count = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 0),
|
|
failure_reason = table.Column<string>(type: "TEXT", nullable: true),
|
|
failure_turns_used = table.Column<int>(type: "INTEGER", nullable: true),
|
|
failure_max_turns = table.Column<int>(type: "INTEGER", nullable: true),
|
|
usage_limit_auto_continued_at = table.Column<DateTime>(type: "TEXT", nullable: true),
|
|
log_path = table.Column<string>(type: "TEXT", nullable: true),
|
|
created_at = table.Column<DateTime>(type: "TEXT", nullable: false),
|
|
started_at = table.Column<DateTime>(type: "TEXT", nullable: true),
|
|
finished_at = table.Column<DateTime>(type: "TEXT", nullable: true),
|
|
commit_type = table.Column<string>(type: "TEXT", nullable: false, defaultValue: "chore"),
|
|
model = table.Column<string>(type: "TEXT", nullable: true),
|
|
system_prompt = table.Column<string>(type: "TEXT", nullable: true),
|
|
agent_path = table.Column<string>(type: "TEXT", nullable: true),
|
|
max_turns = table.Column<int>(type: "INTEGER", nullable: true),
|
|
is_starred = table.Column<bool>(type: "INTEGER", nullable: false, defaultValue: false),
|
|
is_my_day = table.Column<bool>(type: "INTEGER", nullable: false, defaultValue: false),
|
|
is_manual = table.Column<bool>(type: "INTEGER", nullable: false, defaultValue: false),
|
|
notes = table.Column<string>(type: "TEXT", nullable: true),
|
|
sort_order = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 0),
|
|
session_skills = table.Column<string>(type: "TEXT", nullable: true),
|
|
scope_globs = table.Column<string>(type: "TEXT", nullable: true),
|
|
handler_base_commit = table.Column<string>(type: "TEXT", nullable: true),
|
|
handler_head_commit = table.Column<string>(type: "TEXT", nullable: true),
|
|
interactive_session_id = table.Column<string>(type: "TEXT", nullable: true),
|
|
parent_task_id = table.Column<string>(type: "TEXT", nullable: true),
|
|
planning_session_id = table.Column<string>(type: "TEXT", nullable: true),
|
|
planning_session_token = table.Column<string>(type: "TEXT", nullable: true),
|
|
planning_finalized_at = table.Column<DateTime>(type: "TEXT", nullable: true),
|
|
created_by = table.Column<string>(type: "TEXT", nullable: true)
|
|
},
|
|
constraints: table =>
|
|
{
|
|
table.PrimaryKey("PK_tasks", x => x.id);
|
|
table.ForeignKey(
|
|
name: "FK_tasks_lists_list_id",
|
|
column: x => x.list_id,
|
|
principalTable: "lists",
|
|
principalColumn: "id",
|
|
onDelete: ReferentialAction.Cascade);
|
|
table.ForeignKey(
|
|
name: "FK_tasks_tasks_blocked_by_task_id",
|
|
column: x => x.blocked_by_task_id,
|
|
principalTable: "tasks",
|
|
principalColumn: "id",
|
|
onDelete: ReferentialAction.SetNull);
|
|
table.ForeignKey(
|
|
name: "FK_tasks_tasks_depends_on_task_id",
|
|
column: x => x.depends_on_task_id,
|
|
principalTable: "tasks",
|
|
principalColumn: "id",
|
|
onDelete: ReferentialAction.SetNull);
|
|
table.ForeignKey(
|
|
name: "FK_tasks_tasks_parent_task_id",
|
|
column: x => x.parent_task_id,
|
|
principalTable: "tasks",
|
|
principalColumn: "id",
|
|
onDelete: ReferentialAction.Restrict);
|
|
});
|
|
|
|
migrationBuilder.CreateTable(
|
|
name: "subtasks",
|
|
columns: table => new
|
|
{
|
|
id = table.Column<string>(type: "TEXT", nullable: false),
|
|
task_id = table.Column<string>(type: "TEXT", nullable: false),
|
|
title = table.Column<string>(type: "TEXT", nullable: false),
|
|
completed = table.Column<bool>(type: "INTEGER", nullable: false, defaultValue: false),
|
|
order_num = table.Column<int>(type: "INTEGER", nullable: false),
|
|
created_at = table.Column<DateTime>(type: "TEXT", nullable: false)
|
|
},
|
|
constraints: table =>
|
|
{
|
|
table.PrimaryKey("PK_subtasks", x => x.id);
|
|
table.ForeignKey(
|
|
name: "FK_subtasks_tasks_task_id",
|
|
column: x => x.task_id,
|
|
principalTable: "tasks",
|
|
principalColumn: "id",
|
|
onDelete: ReferentialAction.Cascade);
|
|
});
|
|
|
|
migrationBuilder.CreateTable(
|
|
name: "task_attachments",
|
|
columns: table => new
|
|
{
|
|
id = table.Column<string>(type: "TEXT", nullable: false),
|
|
task_id = table.Column<string>(type: "TEXT", nullable: false),
|
|
file_name = table.Column<string>(type: "TEXT", nullable: false),
|
|
byte_size = table.Column<long>(type: "INTEGER", nullable: false),
|
|
created_at = table.Column<DateTime>(type: "TEXT", nullable: false)
|
|
},
|
|
constraints: table =>
|
|
{
|
|
table.PrimaryKey("PK_task_attachments", x => x.id);
|
|
table.ForeignKey(
|
|
name: "FK_task_attachments_tasks_task_id",
|
|
column: x => x.task_id,
|
|
principalTable: "tasks",
|
|
principalColumn: "id",
|
|
onDelete: ReferentialAction.Cascade);
|
|
});
|
|
|
|
migrationBuilder.CreateTable(
|
|
name: "task_runs",
|
|
columns: table => new
|
|
{
|
|
id = table.Column<string>(type: "TEXT", nullable: false),
|
|
task_id = table.Column<string>(type: "TEXT", nullable: false),
|
|
run_number = table.Column<int>(type: "INTEGER", nullable: false),
|
|
session_id = table.Column<string>(type: "TEXT", nullable: true),
|
|
is_retry = table.Column<bool>(type: "INTEGER", nullable: false, defaultValue: false),
|
|
prompt = table.Column<string>(type: "TEXT", nullable: false),
|
|
result_markdown = table.Column<string>(type: "TEXT", nullable: true),
|
|
structured_output = table.Column<string>(type: "TEXT", nullable: true),
|
|
error_markdown = table.Column<string>(type: "TEXT", nullable: true),
|
|
exit_code = table.Column<int>(type: "INTEGER", nullable: true),
|
|
turn_count = table.Column<int>(type: "INTEGER", nullable: true),
|
|
tokens_in = table.Column<int>(type: "INTEGER", nullable: true),
|
|
tokens_out = table.Column<int>(type: "INTEGER", nullable: true),
|
|
cache_read_tokens = table.Column<int>(type: "INTEGER", nullable: true),
|
|
cache_write_tokens = table.Column<int>(type: "INTEGER", nullable: true),
|
|
log_path = table.Column<string>(type: "TEXT", nullable: true),
|
|
started_at = table.Column<DateTime>(type: "TEXT", nullable: true),
|
|
finished_at = table.Column<DateTime>(type: "TEXT", nullable: true),
|
|
model = table.Column<string>(type: "TEXT", nullable: true),
|
|
result_subtype = table.Column<string>(type: "TEXT", nullable: true),
|
|
terminal_reason = table.Column<string>(type: "TEXT", nullable: true),
|
|
errors = table.Column<string>(type: "TEXT", nullable: true)
|
|
},
|
|
constraints: table =>
|
|
{
|
|
table.PrimaryKey("PK_task_runs", x => x.id);
|
|
table.ForeignKey(
|
|
name: "FK_task_runs_tasks_task_id",
|
|
column: x => x.task_id,
|
|
principalTable: "tasks",
|
|
principalColumn: "id",
|
|
onDelete: ReferentialAction.Cascade);
|
|
});
|
|
|
|
migrationBuilder.CreateTable(
|
|
name: "worktrees",
|
|
columns: table => new
|
|
{
|
|
task_id = table.Column<string>(type: "TEXT", nullable: false),
|
|
path = table.Column<string>(type: "TEXT", nullable: false),
|
|
branch_name = table.Column<string>(type: "TEXT", nullable: false),
|
|
base_commit = table.Column<string>(type: "TEXT", nullable: false),
|
|
head_commit = table.Column<string>(type: "TEXT", nullable: true),
|
|
diff_stat = table.Column<string>(type: "TEXT", nullable: true),
|
|
merge_commit = table.Column<string>(type: "TEXT", nullable: true),
|
|
state = table.Column<string>(type: "TEXT", nullable: false, defaultValue: "active"),
|
|
created_at = table.Column<DateTime>(type: "TEXT", nullable: false)
|
|
},
|
|
constraints: table =>
|
|
{
|
|
table.PrimaryKey("PK_worktrees", x => x.task_id);
|
|
table.ForeignKey(
|
|
name: "FK_worktrees_tasks_task_id",
|
|
column: x => x.task_id,
|
|
principalTable: "tasks",
|
|
principalColumn: "id",
|
|
onDelete: ReferentialAction.Cascade);
|
|
});
|
|
|
|
migrationBuilder.InsertData(
|
|
table: "app_settings",
|
|
columns: new[] { "id", "central_worktree_root", "daily_prep_max_tasks", "default_claude_instructions", "default_max_turns", "default_model", "default_permission_mode", "max_parallel_executions", "max_turns_ceiling", "model_presets", "next_task_number", "repo_import_folders", "report_excluded_paths", "session_skills", "standup_weekday", "usage_gate_five_hour_pct", "usage_gate_seven_day_pct", "usage_throttle_five_hour_hard_pct", "usage_throttle_five_hour_soft_pct", "usage_throttle_seven_day_hard_pct", "usage_throttle_seven_day_soft_pct", "worktree_auto_cleanup_days", "worktree_strategy" },
|
|
values: new object[] { 1, null, 5, "", 40, "sonnet", "auto", 1, 80, null, 1, null, null, null, 3, 80, 90, 65, 50, 65, 50, 7, "sibling" });
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "IX_daily_notes_note_date",
|
|
table: "daily_notes",
|
|
column: "note_date");
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "idx_lists_sort",
|
|
table: "lists",
|
|
column: "sort_order");
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "idx_subtasks_task_id",
|
|
table: "subtasks",
|
|
column: "task_id");
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "idx_task_attachments_task_id",
|
|
table: "task_attachments",
|
|
column: "task_id");
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "idx_task_runs_task_id",
|
|
table: "task_runs",
|
|
column: "task_id");
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "idx_tasks_blocked_by",
|
|
table: "tasks",
|
|
column: "blocked_by_task_id");
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "idx_tasks_depends_on",
|
|
table: "tasks",
|
|
column: "depends_on_task_id");
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "idx_tasks_list_id",
|
|
table: "tasks",
|
|
column: "list_id");
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "idx_tasks_list_sort",
|
|
table: "tasks",
|
|
columns: new[] { "list_id", "sort_order" });
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "idx_tasks_number",
|
|
table: "tasks",
|
|
column: "number",
|
|
unique: true);
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "idx_tasks_parent_task_id",
|
|
table: "tasks",
|
|
column: "parent_task_id");
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "idx_tasks_status",
|
|
table: "tasks",
|
|
column: "status");
|
|
|
|
migrationBuilder.CreateIndex(
|
|
name: "IX_week_reports_start_date_end_date",
|
|
table: "week_reports",
|
|
columns: new[] { "start_date", "end_date" },
|
|
unique: true);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override void Down(MigrationBuilder migrationBuilder)
|
|
{
|
|
migrationBuilder.DropTable(
|
|
name: "app_settings");
|
|
|
|
migrationBuilder.DropTable(
|
|
name: "daily_notes");
|
|
|
|
migrationBuilder.DropTable(
|
|
name: "list_config");
|
|
|
|
migrationBuilder.DropTable(
|
|
name: "prime_schedules");
|
|
|
|
migrationBuilder.DropTable(
|
|
name: "session_skills");
|
|
|
|
migrationBuilder.DropTable(
|
|
name: "subtasks");
|
|
|
|
migrationBuilder.DropTable(
|
|
name: "task_attachments");
|
|
|
|
migrationBuilder.DropTable(
|
|
name: "task_runs");
|
|
|
|
migrationBuilder.DropTable(
|
|
name: "week_reports");
|
|
|
|
migrationBuilder.DropTable(
|
|
name: "worktrees");
|
|
|
|
migrationBuilder.DropTable(
|
|
name: "tasks");
|
|
|
|
migrationBuilder.DropTable(
|
|
name: "lists");
|
|
}
|
|
}
|
|
}
|