forked from cardosofelipe/fast-next-template
fix(backend): regenerate Syndarix migration to match models
Completely rewrote migration 0004 to match current model definitions: - Added issue_type ENUM (epic, story, task, bug) - Fixed sprint_status ENUM to include in_review - Fixed all table columns to match models exactly - Fixed all indexes and constraints 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
Revision ID: 0004
|
Revision ID: 0004
|
||||||
Revises: 0003
|
Revises: 0003
|
||||||
Create Date: 2025-12-30
|
Create Date: 2025-12-31
|
||||||
|
|
||||||
This migration creates the core Syndarix domain tables:
|
This migration creates the core Syndarix domain tables:
|
||||||
- projects: Client engagement projects
|
- projects: Client engagement projects
|
||||||
- agent_types: Agent template configurations
|
- agent_types: Agent template configurations
|
||||||
- agent_instances: Spawned agent instances assigned to projects
|
- agent_instances: Spawned agent instances assigned to projects
|
||||||
- issues: Work items (stories, tasks, bugs)
|
|
||||||
- sprints: Sprint containers for issues
|
- sprints: Sprint containers for issues
|
||||||
|
- issues: Work items (epics, stories, tasks, bugs)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from collections.abc import Sequence
|
from collections.abc import Sequence
|
||||||
@@ -28,7 +28,9 @@ depends_on: str | Sequence[str] | None = None
|
|||||||
def upgrade() -> None:
|
def upgrade() -> None:
|
||||||
"""Create Syndarix domain tables."""
|
"""Create Syndarix domain tables."""
|
||||||
|
|
||||||
# Create ENUM types first
|
# =========================================================================
|
||||||
|
# Create ENUM types
|
||||||
|
# =========================================================================
|
||||||
op.execute(
|
op.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TYPE autonomy_level AS ENUM (
|
CREATE TYPE autonomy_level AS ENUM (
|
||||||
@@ -64,24 +66,24 @@ def upgrade() -> None:
|
|||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
op.execute(
|
||||||
|
"""
|
||||||
|
CREATE TYPE issue_type AS ENUM (
|
||||||
|
'epic', 'story', 'task', 'bug'
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
)
|
||||||
op.execute(
|
op.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TYPE issue_status AS ENUM (
|
CREATE TYPE issue_status AS ENUM (
|
||||||
'open', 'in_progress', 'in_review', 'closed', 'blocked'
|
'open', 'in_progress', 'in_review', 'blocked', 'closed'
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
op.execute(
|
op.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TYPE issue_priority AS ENUM (
|
CREATE TYPE issue_priority AS ENUM (
|
||||||
'critical', 'high', 'medium', 'low'
|
'low', 'medium', 'high', 'critical'
|
||||||
)
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
op.execute(
|
|
||||||
"""
|
|
||||||
CREATE TYPE external_tracker_type AS ENUM (
|
|
||||||
'gitea', 'github', 'gitlab', 'jira'
|
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@@ -95,12 +97,14 @@ def upgrade() -> None:
|
|||||||
op.execute(
|
op.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TYPE sprint_status AS ENUM (
|
CREATE TYPE sprint_status AS ENUM (
|
||||||
'planned', 'active', 'completed', 'cancelled'
|
'planned', 'active', 'in_review', 'completed', 'cancelled'
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
# Create projects table
|
# Create projects table
|
||||||
|
# =========================================================================
|
||||||
op.create_table(
|
op.create_table(
|
||||||
"projects",
|
"projects",
|
||||||
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||||
@@ -152,7 +156,10 @@ def upgrade() -> None:
|
|||||||
server_default="auto",
|
server_default="auto",
|
||||||
),
|
),
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"settings", postgresql.JSONB(astext_type=sa.Text()), nullable=False, server_default="{}"
|
"settings",
|
||||||
|
postgresql.JSONB(astext_type=sa.Text()),
|
||||||
|
nullable=False,
|
||||||
|
server_default="{}",
|
||||||
),
|
),
|
||||||
sa.Column("owner_id", postgresql.UUID(as_uuid=True), nullable=True),
|
sa.Column("owner_id", postgresql.UUID(as_uuid=True), nullable=True),
|
||||||
sa.Column(
|
sa.Column(
|
||||||
@@ -168,11 +175,10 @@ def upgrade() -> None:
|
|||||||
server_default=sa.text("now()"),
|
server_default=sa.text("now()"),
|
||||||
),
|
),
|
||||||
sa.PrimaryKeyConstraint("id"),
|
sa.PrimaryKeyConstraint("id"),
|
||||||
sa.ForeignKeyConstraint(
|
sa.ForeignKeyConstraint(["owner_id"], ["users.id"], ondelete="SET NULL"),
|
||||||
["owner_id"], ["users.id"], ondelete="SET NULL"
|
|
||||||
),
|
|
||||||
sa.UniqueConstraint("slug"),
|
sa.UniqueConstraint("slug"),
|
||||||
)
|
)
|
||||||
|
# Single column indexes
|
||||||
op.create_index("ix_projects_name", "projects", ["name"])
|
op.create_index("ix_projects_name", "projects", ["name"])
|
||||||
op.create_index("ix_projects_slug", "projects", ["slug"])
|
op.create_index("ix_projects_slug", "projects", ["slug"])
|
||||||
op.create_index("ix_projects_status", "projects", ["status"])
|
op.create_index("ix_projects_status", "projects", ["status"])
|
||||||
@@ -180,6 +186,7 @@ def upgrade() -> None:
|
|||||||
op.create_index("ix_projects_complexity", "projects", ["complexity"])
|
op.create_index("ix_projects_complexity", "projects", ["complexity"])
|
||||||
op.create_index("ix_projects_client_mode", "projects", ["client_mode"])
|
op.create_index("ix_projects_client_mode", "projects", ["client_mode"])
|
||||||
op.create_index("ix_projects_owner_id", "projects", ["owner_id"])
|
op.create_index("ix_projects_owner_id", "projects", ["owner_id"])
|
||||||
|
# Composite indexes
|
||||||
op.create_index("ix_projects_slug_status", "projects", ["slug", "status"])
|
op.create_index("ix_projects_slug_status", "projects", ["slug", "status"])
|
||||||
op.create_index("ix_projects_owner_status", "projects", ["owner_id", "status"])
|
op.create_index("ix_projects_owner_status", "projects", ["owner_id", "status"])
|
||||||
op.create_index(
|
op.create_index(
|
||||||
@@ -189,13 +196,25 @@ def upgrade() -> None:
|
|||||||
"ix_projects_complexity_status", "projects", ["complexity", "status"]
|
"ix_projects_complexity_status", "projects", ["complexity", "status"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
# Create agent_types table
|
# Create agent_types table
|
||||||
|
# =========================================================================
|
||||||
op.create_table(
|
op.create_table(
|
||||||
"agent_types",
|
"agent_types",
|
||||||
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||||
sa.Column("name", sa.String(100), nullable=False),
|
sa.Column("name", sa.String(255), nullable=False),
|
||||||
sa.Column("slug", sa.String(100), nullable=False),
|
sa.Column("slug", sa.String(255), nullable=False),
|
||||||
sa.Column("description", sa.Text(), nullable=True),
|
sa.Column("description", sa.Text(), nullable=True),
|
||||||
|
# Areas of expertise (e.g., ["python", "fastapi", "databases"])
|
||||||
|
sa.Column(
|
||||||
|
"expertise",
|
||||||
|
postgresql.JSONB(astext_type=sa.Text()),
|
||||||
|
nullable=False,
|
||||||
|
server_default="[]",
|
||||||
|
),
|
||||||
|
# System prompt defining personality and behavior (required)
|
||||||
|
sa.Column("personality_prompt", sa.Text(), nullable=False),
|
||||||
|
# LLM model configuration
|
||||||
sa.Column("primary_model", sa.String(100), nullable=False),
|
sa.Column("primary_model", sa.String(100), nullable=False),
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"fallback_models",
|
"fallback_models",
|
||||||
@@ -203,16 +222,23 @@ def upgrade() -> None:
|
|||||||
nullable=False,
|
nullable=False,
|
||||||
server_default="[]",
|
server_default="[]",
|
||||||
),
|
),
|
||||||
sa.Column("system_prompt", sa.Text(), nullable=True),
|
# Model parameters (temperature, max_tokens, etc.)
|
||||||
sa.Column("personality_prompt", sa.Text(), nullable=True),
|
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"capabilities",
|
"model_params",
|
||||||
|
postgresql.JSONB(astext_type=sa.Text()),
|
||||||
|
nullable=False,
|
||||||
|
server_default="{}",
|
||||||
|
),
|
||||||
|
# MCP servers this agent can connect to
|
||||||
|
sa.Column(
|
||||||
|
"mcp_servers",
|
||||||
postgresql.JSONB(astext_type=sa.Text()),
|
postgresql.JSONB(astext_type=sa.Text()),
|
||||||
nullable=False,
|
nullable=False,
|
||||||
server_default="[]",
|
server_default="[]",
|
||||||
),
|
),
|
||||||
|
# Tool permissions configuration
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"default_config",
|
"tool_permissions",
|
||||||
postgresql.JSONB(astext_type=sa.Text()),
|
postgresql.JSONB(astext_type=sa.Text()),
|
||||||
nullable=False,
|
nullable=False,
|
||||||
server_default="{}",
|
server_default="{}",
|
||||||
@@ -233,12 +259,17 @@ def upgrade() -> None:
|
|||||||
sa.PrimaryKeyConstraint("id"),
|
sa.PrimaryKeyConstraint("id"),
|
||||||
sa.UniqueConstraint("slug"),
|
sa.UniqueConstraint("slug"),
|
||||||
)
|
)
|
||||||
|
# Single column indexes
|
||||||
op.create_index("ix_agent_types_name", "agent_types", ["name"])
|
op.create_index("ix_agent_types_name", "agent_types", ["name"])
|
||||||
op.create_index("ix_agent_types_slug", "agent_types", ["slug"])
|
op.create_index("ix_agent_types_slug", "agent_types", ["slug"])
|
||||||
op.create_index("ix_agent_types_is_active", "agent_types", ["is_active"])
|
op.create_index("ix_agent_types_is_active", "agent_types", ["is_active"])
|
||||||
op.create_index("ix_agent_types_primary_model", "agent_types", ["primary_model"])
|
# Composite indexes
|
||||||
|
op.create_index("ix_agent_types_slug_active", "agent_types", ["slug", "is_active"])
|
||||||
|
op.create_index("ix_agent_types_name_active", "agent_types", ["name", "is_active"])
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
# Create agent_instances table
|
# Create agent_instances table
|
||||||
|
# =========================================================================
|
||||||
op.create_table(
|
op.create_table(
|
||||||
"agent_instances",
|
"agent_instances",
|
||||||
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||||
@@ -260,17 +291,28 @@ def upgrade() -> None:
|
|||||||
server_default="idle",
|
server_default="idle",
|
||||||
),
|
),
|
||||||
sa.Column("current_task", sa.Text(), nullable=True),
|
sa.Column("current_task", sa.Text(), nullable=True),
|
||||||
|
# Short-term memory (conversation context, recent decisions)
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"config_overrides",
|
"short_term_memory",
|
||||||
postgresql.JSONB(astext_type=sa.Text()),
|
postgresql.JSONB(astext_type=sa.Text()),
|
||||||
nullable=False,
|
nullable=False,
|
||||||
server_default="{}",
|
server_default="{}",
|
||||||
),
|
),
|
||||||
|
# Reference to long-term memory in vector store
|
||||||
|
sa.Column("long_term_memory_ref", sa.String(500), nullable=True),
|
||||||
|
# Session ID for active MCP connections
|
||||||
|
sa.Column("session_id", sa.String(255), nullable=True),
|
||||||
|
# Activity tracking
|
||||||
|
sa.Column("last_activity_at", sa.DateTime(timezone=True), nullable=True),
|
||||||
|
sa.Column("terminated_at", sa.DateTime(timezone=True), nullable=True),
|
||||||
|
# Usage metrics
|
||||||
|
sa.Column("tasks_completed", sa.Integer(), nullable=False, server_default="0"),
|
||||||
|
sa.Column("tokens_used", sa.BigInteger(), nullable=False, server_default="0"),
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"metadata",
|
"cost_incurred",
|
||||||
postgresql.JSONB(astext_type=sa.Text()),
|
sa.Numeric(precision=10, scale=4),
|
||||||
nullable=False,
|
nullable=False,
|
||||||
server_default="{}",
|
server_default="0",
|
||||||
),
|
),
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"created_at",
|
"created_at",
|
||||||
@@ -290,12 +332,21 @@ def upgrade() -> None:
|
|||||||
),
|
),
|
||||||
sa.ForeignKeyConstraint(["project_id"], ["projects.id"], ondelete="CASCADE"),
|
sa.ForeignKeyConstraint(["project_id"], ["projects.id"], ondelete="CASCADE"),
|
||||||
)
|
)
|
||||||
|
# Single column indexes
|
||||||
op.create_index("ix_agent_instances_name", "agent_instances", ["name"])
|
op.create_index("ix_agent_instances_name", "agent_instances", ["name"])
|
||||||
op.create_index("ix_agent_instances_status", "agent_instances", ["status"])
|
op.create_index("ix_agent_instances_status", "agent_instances", ["status"])
|
||||||
op.create_index(
|
op.create_index(
|
||||||
"ix_agent_instances_agent_type_id", "agent_instances", ["agent_type_id"]
|
"ix_agent_instances_agent_type_id", "agent_instances", ["agent_type_id"]
|
||||||
)
|
)
|
||||||
op.create_index("ix_agent_instances_project_id", "agent_instances", ["project_id"])
|
op.create_index("ix_agent_instances_project_id", "agent_instances", ["project_id"])
|
||||||
|
op.create_index("ix_agent_instances_session_id", "agent_instances", ["session_id"])
|
||||||
|
op.create_index(
|
||||||
|
"ix_agent_instances_last_activity_at", "agent_instances", ["last_activity_at"]
|
||||||
|
)
|
||||||
|
op.create_index(
|
||||||
|
"ix_agent_instances_terminated_at", "agent_instances", ["terminated_at"]
|
||||||
|
)
|
||||||
|
# Composite indexes
|
||||||
op.create_index(
|
op.create_index(
|
||||||
"ix_agent_instances_project_status",
|
"ix_agent_instances_project_status",
|
||||||
"agent_instances",
|
"agent_instances",
|
||||||
@@ -306,22 +357,30 @@ def upgrade() -> None:
|
|||||||
"agent_instances",
|
"agent_instances",
|
||||||
["agent_type_id", "status"],
|
["agent_type_id", "status"],
|
||||||
)
|
)
|
||||||
|
op.create_index(
|
||||||
|
"ix_agent_instances_project_type",
|
||||||
|
"agent_instances",
|
||||||
|
["project_id", "agent_type_id"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
# Create sprints table (before issues for FK reference)
|
# Create sprints table (before issues for FK reference)
|
||||||
|
# =========================================================================
|
||||||
op.create_table(
|
op.create_table(
|
||||||
"sprints",
|
"sprints",
|
||||||
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||||
sa.Column("project_id", postgresql.UUID(as_uuid=True), nullable=False),
|
sa.Column("project_id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||||
sa.Column("name", sa.String(100), nullable=False),
|
sa.Column("name", sa.String(255), nullable=False),
|
||||||
sa.Column("number", sa.Integer(), nullable=False),
|
sa.Column("number", sa.Integer(), nullable=False),
|
||||||
sa.Column("goal", sa.Text(), nullable=True),
|
sa.Column("goal", sa.Text(), nullable=True),
|
||||||
sa.Column("start_date", sa.Date(), nullable=True),
|
sa.Column("start_date", sa.Date(), nullable=False),
|
||||||
sa.Column("end_date", sa.Date(), nullable=True),
|
sa.Column("end_date", sa.Date(), nullable=False),
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"status",
|
"status",
|
||||||
sa.Enum(
|
sa.Enum(
|
||||||
"planned",
|
"planned",
|
||||||
"active",
|
"active",
|
||||||
|
"in_review",
|
||||||
"completed",
|
"completed",
|
||||||
"cancelled",
|
"cancelled",
|
||||||
name="sprint_status",
|
name="sprint_status",
|
||||||
@@ -348,29 +407,53 @@ def upgrade() -> None:
|
|||||||
sa.ForeignKeyConstraint(["project_id"], ["projects.id"], ondelete="CASCADE"),
|
sa.ForeignKeyConstraint(["project_id"], ["projects.id"], ondelete="CASCADE"),
|
||||||
sa.UniqueConstraint("project_id", "number", name="uq_sprint_project_number"),
|
sa.UniqueConstraint("project_id", "number", name="uq_sprint_project_number"),
|
||||||
)
|
)
|
||||||
op.create_index("ix_sprints_name", "sprints", ["name"])
|
# Single column indexes
|
||||||
op.create_index("ix_sprints_number", "sprints", ["number"])
|
|
||||||
op.create_index("ix_sprints_status", "sprints", ["status"])
|
|
||||||
op.create_index("ix_sprints_project_id", "sprints", ["project_id"])
|
op.create_index("ix_sprints_project_id", "sprints", ["project_id"])
|
||||||
|
op.create_index("ix_sprints_status", "sprints", ["status"])
|
||||||
|
op.create_index("ix_sprints_start_date", "sprints", ["start_date"])
|
||||||
|
op.create_index("ix_sprints_end_date", "sprints", ["end_date"])
|
||||||
|
# Composite indexes
|
||||||
op.create_index("ix_sprints_project_status", "sprints", ["project_id", "status"])
|
op.create_index("ix_sprints_project_status", "sprints", ["project_id", "status"])
|
||||||
|
op.create_index("ix_sprints_project_number", "sprints", ["project_id", "number"])
|
||||||
|
op.create_index("ix_sprints_date_range", "sprints", ["start_date", "end_date"])
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
# Create issues table
|
# Create issues table
|
||||||
|
# =========================================================================
|
||||||
op.create_table(
|
op.create_table(
|
||||||
"issues",
|
"issues",
|
||||||
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||||
sa.Column("project_id", postgresql.UUID(as_uuid=True), nullable=False),
|
sa.Column("project_id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||||
sa.Column("sprint_id", postgresql.UUID(as_uuid=True), nullable=True),
|
# Parent issue for hierarchy (Epic -> Story -> Task)
|
||||||
sa.Column("assigned_agent_id", postgresql.UUID(as_uuid=True), nullable=True),
|
sa.Column("parent_id", postgresql.UUID(as_uuid=True), nullable=True),
|
||||||
|
# Issue type (epic, story, task, bug)
|
||||||
|
sa.Column(
|
||||||
|
"type",
|
||||||
|
sa.Enum(
|
||||||
|
"epic",
|
||||||
|
"story",
|
||||||
|
"task",
|
||||||
|
"bug",
|
||||||
|
name="issue_type",
|
||||||
|
create_type=False,
|
||||||
|
),
|
||||||
|
nullable=False,
|
||||||
|
server_default="task",
|
||||||
|
),
|
||||||
|
# Reporter (who created this issue)
|
||||||
|
sa.Column("reporter_id", postgresql.UUID(as_uuid=True), nullable=True),
|
||||||
|
# Issue content
|
||||||
sa.Column("title", sa.String(500), nullable=False),
|
sa.Column("title", sa.String(500), nullable=False),
|
||||||
sa.Column("description", sa.Text(), nullable=True),
|
sa.Column("body", sa.Text(), nullable=False, server_default=""),
|
||||||
|
# Status and priority
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"status",
|
"status",
|
||||||
sa.Enum(
|
sa.Enum(
|
||||||
"open",
|
"open",
|
||||||
"in_progress",
|
"in_progress",
|
||||||
"in_review",
|
"in_review",
|
||||||
"closed",
|
|
||||||
"blocked",
|
"blocked",
|
||||||
|
"closed",
|
||||||
name="issue_status",
|
name="issue_status",
|
||||||
create_type=False,
|
create_type=False,
|
||||||
),
|
),
|
||||||
@@ -380,33 +463,37 @@ def upgrade() -> None:
|
|||||||
sa.Column(
|
sa.Column(
|
||||||
"priority",
|
"priority",
|
||||||
sa.Enum(
|
sa.Enum(
|
||||||
"critical", "high", "medium", "low", name="issue_priority", create_type=False
|
"low",
|
||||||
|
"medium",
|
||||||
|
"high",
|
||||||
|
"critical",
|
||||||
|
name="issue_priority",
|
||||||
|
create_type=False,
|
||||||
),
|
),
|
||||||
nullable=False,
|
nullable=False,
|
||||||
server_default="medium",
|
server_default="medium",
|
||||||
),
|
),
|
||||||
sa.Column("story_points", sa.Integer(), nullable=True),
|
# Labels for categorization
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"labels",
|
"labels",
|
||||||
postgresql.JSONB(astext_type=sa.Text()),
|
postgresql.JSONB(astext_type=sa.Text()),
|
||||||
nullable=False,
|
nullable=False,
|
||||||
server_default="[]",
|
server_default="[]",
|
||||||
),
|
),
|
||||||
sa.Column(
|
# Assignment - agent or human (mutually exclusive)
|
||||||
"external_tracker",
|
sa.Column("assigned_agent_id", postgresql.UUID(as_uuid=True), nullable=True),
|
||||||
sa.Enum(
|
sa.Column("human_assignee", sa.String(255), nullable=True),
|
||||||
"gitea",
|
# Sprint association
|
||||||
"github",
|
sa.Column("sprint_id", postgresql.UUID(as_uuid=True), nullable=True),
|
||||||
"gitlab",
|
# Estimation
|
||||||
"jira",
|
sa.Column("story_points", sa.Integer(), nullable=True),
|
||||||
name="external_tracker_type",
|
sa.Column("due_date", sa.Date(), nullable=True),
|
||||||
create_type=False,
|
# External tracker integration (String for flexibility)
|
||||||
),
|
sa.Column("external_tracker_type", sa.String(50), nullable=True),
|
||||||
nullable=True,
|
sa.Column("external_issue_id", sa.String(255), nullable=True),
|
||||||
),
|
sa.Column("remote_url", sa.String(1000), nullable=True),
|
||||||
sa.Column("external_id", sa.String(255), nullable=True),
|
sa.Column("external_issue_number", sa.Integer(), nullable=True),
|
||||||
sa.Column("external_url", sa.String(2048), nullable=True),
|
# Sync status
|
||||||
sa.Column("external_number", sa.Integer(), nullable=True),
|
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"sync_status",
|
"sync_status",
|
||||||
sa.Enum(
|
sa.Enum(
|
||||||
@@ -417,15 +504,13 @@ def upgrade() -> None:
|
|||||||
name="sync_status",
|
name="sync_status",
|
||||||
create_type=False,
|
create_type=False,
|
||||||
),
|
),
|
||||||
nullable=True,
|
nullable=False,
|
||||||
|
server_default="synced",
|
||||||
),
|
),
|
||||||
sa.Column("last_synced_at", sa.DateTime(timezone=True), nullable=True),
|
sa.Column("last_synced_at", sa.DateTime(timezone=True), nullable=True),
|
||||||
sa.Column(
|
sa.Column("external_updated_at", sa.DateTime(timezone=True), nullable=True),
|
||||||
"metadata",
|
# Lifecycle
|
||||||
postgresql.JSONB(astext_type=sa.Text()),
|
sa.Column("closed_at", sa.DateTime(timezone=True), nullable=True),
|
||||||
nullable=False,
|
|
||||||
server_default="{}",
|
|
||||||
),
|
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"created_at",
|
"created_at",
|
||||||
sa.DateTime(timezone=True),
|
sa.DateTime(timezone=True),
|
||||||
@@ -440,29 +525,43 @@ def upgrade() -> None:
|
|||||||
),
|
),
|
||||||
sa.PrimaryKeyConstraint("id"),
|
sa.PrimaryKeyConstraint("id"),
|
||||||
sa.ForeignKeyConstraint(["project_id"], ["projects.id"], ondelete="CASCADE"),
|
sa.ForeignKeyConstraint(["project_id"], ["projects.id"], ondelete="CASCADE"),
|
||||||
|
sa.ForeignKeyConstraint(
|
||||||
|
["parent_id"], ["issues.id"], ondelete="CASCADE"
|
||||||
|
),
|
||||||
sa.ForeignKeyConstraint(["sprint_id"], ["sprints.id"], ondelete="SET NULL"),
|
sa.ForeignKeyConstraint(["sprint_id"], ["sprints.id"], ondelete="SET NULL"),
|
||||||
sa.ForeignKeyConstraint(
|
sa.ForeignKeyConstraint(
|
||||||
["assigned_agent_id"], ["agent_instances.id"], ondelete="SET NULL"
|
["assigned_agent_id"], ["agent_instances.id"], ondelete="SET NULL"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
op.create_index("ix_issues_title", "issues", ["title"])
|
# Single column indexes
|
||||||
|
op.create_index("ix_issues_project_id", "issues", ["project_id"])
|
||||||
|
op.create_index("ix_issues_parent_id", "issues", ["parent_id"])
|
||||||
|
op.create_index("ix_issues_type", "issues", ["type"])
|
||||||
|
op.create_index("ix_issues_reporter_id", "issues", ["reporter_id"])
|
||||||
op.create_index("ix_issues_status", "issues", ["status"])
|
op.create_index("ix_issues_status", "issues", ["status"])
|
||||||
op.create_index("ix_issues_priority", "issues", ["priority"])
|
op.create_index("ix_issues_priority", "issues", ["priority"])
|
||||||
op.create_index("ix_issues_project_id", "issues", ["project_id"])
|
|
||||||
op.create_index("ix_issues_sprint_id", "issues", ["sprint_id"])
|
|
||||||
op.create_index("ix_issues_assigned_agent_id", "issues", ["assigned_agent_id"])
|
op.create_index("ix_issues_assigned_agent_id", "issues", ["assigned_agent_id"])
|
||||||
op.create_index("ix_issues_external_tracker", "issues", ["external_tracker"])
|
op.create_index("ix_issues_human_assignee", "issues", ["human_assignee"])
|
||||||
|
op.create_index("ix_issues_sprint_id", "issues", ["sprint_id"])
|
||||||
|
op.create_index("ix_issues_due_date", "issues", ["due_date"])
|
||||||
|
op.create_index("ix_issues_external_tracker_type", "issues", ["external_tracker_type"])
|
||||||
op.create_index("ix_issues_sync_status", "issues", ["sync_status"])
|
op.create_index("ix_issues_sync_status", "issues", ["sync_status"])
|
||||||
|
op.create_index("ix_issues_closed_at", "issues", ["closed_at"])
|
||||||
|
# Composite indexes
|
||||||
op.create_index("ix_issues_project_status", "issues", ["project_id", "status"])
|
op.create_index("ix_issues_project_status", "issues", ["project_id", "status"])
|
||||||
|
op.create_index("ix_issues_project_priority", "issues", ["project_id", "priority"])
|
||||||
|
op.create_index("ix_issues_project_sprint", "issues", ["project_id", "sprint_id"])
|
||||||
|
op.create_index("ix_issues_project_type", "issues", ["project_id", "type"])
|
||||||
|
op.create_index("ix_issues_project_agent", "issues", ["project_id", "assigned_agent_id"])
|
||||||
op.create_index(
|
op.create_index(
|
||||||
"ix_issues_project_status_priority",
|
"ix_issues_project_status_priority",
|
||||||
"issues",
|
"issues",
|
||||||
["project_id", "status", "priority"],
|
["project_id", "status", "priority"],
|
||||||
)
|
)
|
||||||
op.create_index(
|
op.create_index(
|
||||||
"ix_issues_external",
|
"ix_issues_external_tracker_id",
|
||||||
"issues",
|
"issues",
|
||||||
["project_id", "external_tracker", "external_id"],
|
["external_tracker_type", "external_issue_id"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -478,9 +577,9 @@ def downgrade() -> None:
|
|||||||
# Drop ENUM types
|
# Drop ENUM types
|
||||||
op.execute("DROP TYPE IF EXISTS sprint_status")
|
op.execute("DROP TYPE IF EXISTS sprint_status")
|
||||||
op.execute("DROP TYPE IF EXISTS sync_status")
|
op.execute("DROP TYPE IF EXISTS sync_status")
|
||||||
op.execute("DROP TYPE IF EXISTS external_tracker_type")
|
|
||||||
op.execute("DROP TYPE IF EXISTS issue_priority")
|
op.execute("DROP TYPE IF EXISTS issue_priority")
|
||||||
op.execute("DROP TYPE IF EXISTS issue_status")
|
op.execute("DROP TYPE IF EXISTS issue_status")
|
||||||
|
op.execute("DROP TYPE IF EXISTS issue_type")
|
||||||
op.execute("DROP TYPE IF EXISTS agent_status")
|
op.execute("DROP TYPE IF EXISTS agent_status")
|
||||||
op.execute("DROP TYPE IF EXISTS client_mode")
|
op.execute("DROP TYPE IF EXISTS client_mode")
|
||||||
op.execute("DROP TYPE IF EXISTS project_complexity")
|
op.execute("DROP TYPE IF EXISTS project_complexity")
|
||||||
|
|||||||
Reference in New Issue
Block a user