mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
Initial implementation
This commit is contained in:
@@ -0,0 +1,573 @@
|
||||
"""Initial schema - all tables
|
||||
|
||||
Revision ID: 001_initial_schema
|
||||
Revises:
|
||||
Create Date: 2025-12-09
|
||||
|
||||
Creates all tables for the RoboCo AI Agents Company system:
|
||||
- agents: AI agent definitions and state
|
||||
- tasks: Work items with lifecycle management
|
||||
- channels: Communication channels
|
||||
- groups: Role-based groups within channels
|
||||
- sessions: Bounded message sessions
|
||||
- messages: Extracted messages
|
||||
- notifications: Formal notifications
|
||||
- journals: Agent personal logs
|
||||
- journal_entries: Individual log entries
|
||||
- handoffs: Documentation handoffs
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "001_initial_schema"
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ==========================================================================
|
||||
# AGENTS TABLE
|
||||
# ==========================================================================
|
||||
op.create_table(
|
||||
"agents",
|
||||
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
||||
sa.Column("name", sa.String(100), nullable=False),
|
||||
sa.Column("slug", sa.String(50), nullable=False, unique=True, index=True),
|
||||
sa.Column(
|
||||
"role",
|
||||
sa.Enum(
|
||||
"ceo",
|
||||
"product_owner",
|
||||
"head_marketing",
|
||||
"auditor",
|
||||
"main_pm",
|
||||
"cell_pm",
|
||||
"developer",
|
||||
"qa",
|
||||
"documenter",
|
||||
name="agentrole",
|
||||
),
|
||||
nullable=False,
|
||||
),
|
||||
sa.Column(
|
||||
"team",
|
||||
sa.Enum("backend", "frontend", "ux_ui", "board", name="team"),
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column(
|
||||
"status",
|
||||
sa.Enum("active", "idle", "offline", name="agentstatus"),
|
||||
nullable=False,
|
||||
server_default="offline",
|
||||
),
|
||||
sa.Column("current_task_id", postgresql.UUID(as_uuid=True), nullable=True),
|
||||
sa.Column("model_config", postgresql.JSON(), nullable=False),
|
||||
sa.Column("system_prompt", sa.Text(), nullable=False),
|
||||
sa.Column("capabilities", postgresql.ARRAY(sa.String()), server_default="{}"),
|
||||
sa.Column("permissions", postgresql.JSON(), server_default="{}"),
|
||||
sa.Column("metrics", postgresql.JSON(), server_default="{}"),
|
||||
sa.Column("journal_id", postgresql.UUID(as_uuid=True), nullable=True),
|
||||
sa.Column("description", sa.Text(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False, server_default=sa.func.now()),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
# TASKS TABLE
|
||||
# ==========================================================================
|
||||
op.create_table(
|
||||
"tasks",
|
||||
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
||||
sa.Column("title", sa.String(200), nullable=False),
|
||||
sa.Column("description", sa.Text(), nullable=False),
|
||||
sa.Column("acceptance_criteria", postgresql.ARRAY(sa.String()), nullable=False),
|
||||
sa.Column(
|
||||
"status",
|
||||
sa.Enum(
|
||||
"pending",
|
||||
"claimed",
|
||||
"in_progress",
|
||||
"blocked",
|
||||
"paused",
|
||||
"verifying",
|
||||
"needs_revision",
|
||||
"awaiting_qa",
|
||||
"awaiting_documentation",
|
||||
"completed",
|
||||
"cancelled",
|
||||
name="taskstatus",
|
||||
),
|
||||
nullable=False,
|
||||
server_default="pending",
|
||||
index=True,
|
||||
),
|
||||
sa.Column("priority", sa.Integer(), nullable=False, server_default="2"),
|
||||
sa.Column(
|
||||
"created_by",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("agents.id"),
|
||||
nullable=False,
|
||||
),
|
||||
sa.Column(
|
||||
"assigned_to",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("agents.id", ondelete="SET NULL"),
|
||||
nullable=True,
|
||||
index=True,
|
||||
),
|
||||
sa.Column(
|
||||
"team",
|
||||
sa.Enum("backend", "frontend", "ux_ui", "board", name="team", create_type=False),
|
||||
nullable=False,
|
||||
index=True,
|
||||
),
|
||||
sa.Column(
|
||||
"parent_task_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("tasks.id", ondelete="SET NULL"),
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column("dependency_ids", postgresql.ARRAY(postgresql.UUID(as_uuid=True)), server_default="{}"),
|
||||
sa.Column("blocker_ids", postgresql.ARRAY(postgresql.UUID(as_uuid=True)), server_default="{}"),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False, server_default=sa.func.now()),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("claimed_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("started_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("completed_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("target_date", sa.DateTime(), nullable=True),
|
||||
sa.Column("plan", postgresql.JSON(), nullable=True),
|
||||
sa.Column(
|
||||
"estimated_complexity",
|
||||
sa.Enum("low", "medium", "high", name="complexity"),
|
||||
nullable=False,
|
||||
server_default="medium",
|
||||
),
|
||||
sa.Column("execution_log", postgresql.JSON(), server_default="{}"),
|
||||
sa.Column("checkpoints", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("progress_updates", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("commits", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("documents", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("outputs", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("dev_notes", sa.Text(), nullable=True),
|
||||
sa.Column("qa_notes", sa.Text(), nullable=True),
|
||||
sa.Column("auditor_notes", sa.Text(), nullable=True),
|
||||
sa.Column("self_verified", sa.Boolean(), server_default="false"),
|
||||
sa.Column("qa_verified", sa.Boolean(), nullable=True),
|
||||
sa.Column("quick_context", sa.Text(), nullable=True),
|
||||
)
|
||||
|
||||
# Add foreign key for agents.current_task_id after tasks table exists
|
||||
op.create_foreign_key(
|
||||
"fk_agents_current_task",
|
||||
"agents",
|
||||
"tasks",
|
||||
["current_task_id"],
|
||||
["id"],
|
||||
ondelete="SET NULL",
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
# CHANNELS TABLE
|
||||
# ==========================================================================
|
||||
op.create_table(
|
||||
"channels",
|
||||
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
||||
sa.Column("name", sa.String(100), nullable=False),
|
||||
sa.Column("slug", sa.String(50), nullable=False, unique=True, index=True),
|
||||
sa.Column(
|
||||
"type",
|
||||
sa.Enum("cell", "cross_cell", "management", "special", name="channeltype"),
|
||||
nullable=False,
|
||||
),
|
||||
sa.Column("description", sa.Text(), nullable=True),
|
||||
sa.Column("topic", sa.String(500), nullable=True),
|
||||
sa.Column("members", postgresql.ARRAY(postgresql.UUID(as_uuid=True)), server_default="{}"),
|
||||
sa.Column("writers", postgresql.ARRAY(postgresql.UUID(as_uuid=True)), server_default="{}"),
|
||||
sa.Column("silent_observers", postgresql.ARRAY(postgresql.UUID(as_uuid=True)), server_default="{}"),
|
||||
sa.Column("is_archived", sa.Boolean(), server_default="false"),
|
||||
sa.Column("is_private", sa.Boolean(), server_default="false"),
|
||||
sa.Column("allow_threads", sa.Boolean(), server_default="true"),
|
||||
sa.Column("allow_reactions", sa.Boolean(), server_default="true"),
|
||||
sa.Column("message_retention_days", sa.Integer(), nullable=True, server_default="90"),
|
||||
sa.Column("max_message_length", sa.Integer(), server_default="10000"),
|
||||
sa.Column("message_count", sa.Integer(), server_default="0"),
|
||||
sa.Column("group_count", sa.Integer(), server_default="0"),
|
||||
sa.Column("last_activity", sa.DateTime(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False, server_default=sa.func.now()),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
# GROUPS TABLE
|
||||
# ==========================================================================
|
||||
op.create_table(
|
||||
"groups",
|
||||
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
||||
sa.Column("name", sa.String(100), nullable=False),
|
||||
sa.Column(
|
||||
"channel_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("channels.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
),
|
||||
sa.Column("allowed_roles", postgresql.ARRAY(sa.String()), server_default="{}"),
|
||||
sa.Column("hierarchy_level", sa.Integer(), server_default="4"),
|
||||
sa.Column("members", postgresql.ARRAY(postgresql.UUID(as_uuid=True)), server_default="{}"),
|
||||
sa.Column("is_active", sa.Boolean(), server_default="true"),
|
||||
sa.Column("active_session_id", postgresql.UUID(as_uuid=True), nullable=True),
|
||||
sa.Column("default_session_config", postgresql.JSON(), server_default="{}"),
|
||||
sa.Column("total_sessions", sa.Integer(), server_default="0"),
|
||||
sa.Column("total_messages", sa.Integer(), server_default="0"),
|
||||
sa.Column("last_activity", sa.DateTime(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False, server_default=sa.func.now()),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
# SESSIONS TABLE
|
||||
# ==========================================================================
|
||||
op.create_table(
|
||||
"sessions",
|
||||
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
||||
sa.Column(
|
||||
"group_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("groups.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
),
|
||||
sa.Column("max_time_window", sa.Interval(), nullable=True),
|
||||
sa.Column("max_message_count", sa.Integer(), nullable=True, server_default="100"),
|
||||
sa.Column("max_content_length", sa.Integer(), nullable=True, server_default="50000"),
|
||||
sa.Column("timeout_seconds", sa.Integer(), server_default="300"),
|
||||
sa.Column(
|
||||
"status",
|
||||
sa.Enum("active", "closed", "timed_out", name="sessionstatus"),
|
||||
nullable=False,
|
||||
server_default="active",
|
||||
index=True,
|
||||
),
|
||||
sa.Column("started_at", sa.DateTime(), nullable=False, server_default=sa.func.now()),
|
||||
sa.Column("last_activity_at", sa.DateTime(), nullable=False, server_default=sa.func.now()),
|
||||
sa.Column("closed_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("message_count", sa.Integer(), server_default="0"),
|
||||
sa.Column("total_content_length", sa.Integer(), server_default="0"),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False, server_default=sa.func.now()),
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
# MESSAGES TABLE
|
||||
# ==========================================================================
|
||||
op.create_table(
|
||||
"messages",
|
||||
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
||||
sa.Column(
|
||||
"agent_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("agents.id"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
),
|
||||
sa.Column(
|
||||
"channel_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("channels.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
),
|
||||
sa.Column(
|
||||
"group_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("groups.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
),
|
||||
sa.Column(
|
||||
"session_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("sessions.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
),
|
||||
sa.Column(
|
||||
"type",
|
||||
sa.Enum(
|
||||
"reasoning",
|
||||
"dialogue",
|
||||
"decision",
|
||||
"action",
|
||||
"blocker",
|
||||
"technical",
|
||||
name="messagetype",
|
||||
),
|
||||
nullable=False,
|
||||
index=True,
|
||||
),
|
||||
sa.Column("content", sa.Text(), nullable=False),
|
||||
sa.Column("content_length", sa.Integer(), nullable=False),
|
||||
sa.Column("is_reply", sa.Boolean(), server_default="false"),
|
||||
sa.Column(
|
||||
"reply_to",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("messages.id", ondelete="SET NULL"),
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column("mentions", postgresql.ARRAY(postgresql.UUID(as_uuid=True)), server_default="{}"),
|
||||
sa.Column(
|
||||
"task_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("tasks.id", ondelete="SET NULL"),
|
||||
nullable=True,
|
||||
index=True,
|
||||
),
|
||||
sa.Column("commit_ref", sa.String(40), nullable=True),
|
||||
sa.Column("timestamp", sa.DateTime(), nullable=False, server_default=sa.func.now(), index=True),
|
||||
sa.Column("confidence", sa.Float(), server_default="1.0"),
|
||||
sa.Column("raw_excerpt", sa.Text(), nullable=True),
|
||||
sa.Column("edited_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("edit_history", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False, server_default=sa.func.now()),
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
# NOTIFICATIONS TABLE
|
||||
# ==========================================================================
|
||||
op.create_table(
|
||||
"notifications",
|
||||
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
||||
sa.Column(
|
||||
"type",
|
||||
sa.Enum(
|
||||
"task_assignment",
|
||||
"priority_change",
|
||||
"blocker_escalation",
|
||||
"review_request",
|
||||
"documentation_request",
|
||||
"alert",
|
||||
"broadcast",
|
||||
name="notificationtype",
|
||||
),
|
||||
nullable=False,
|
||||
index=True,
|
||||
),
|
||||
sa.Column(
|
||||
"priority",
|
||||
sa.Enum("normal", "high", "urgent", name="notificationpriority"),
|
||||
nullable=False,
|
||||
server_default="normal",
|
||||
),
|
||||
sa.Column(
|
||||
"from_agent",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("agents.id"),
|
||||
nullable=False,
|
||||
),
|
||||
sa.Column("to_agents", postgresql.ARRAY(postgresql.UUID(as_uuid=True)), nullable=False),
|
||||
sa.Column("subject", sa.String(200), nullable=False),
|
||||
sa.Column("body", sa.Text(), nullable=False),
|
||||
sa.Column("requires_ack", sa.Boolean(), server_default="true"),
|
||||
sa.Column("acked_by", postgresql.ARRAY(postgresql.UUID(as_uuid=True)), server_default="{}"),
|
||||
sa.Column("acked_at", postgresql.JSON(), server_default="{}"),
|
||||
sa.Column(
|
||||
"related_task_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("tasks.id", ondelete="SET NULL"),
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column("related_message_ids", postgresql.ARRAY(postgresql.UUID(as_uuid=True)), server_default="{}"),
|
||||
sa.Column("timestamp", sa.DateTime(), nullable=False, server_default=sa.func.now(), index=True),
|
||||
sa.Column("expires_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("read_by", postgresql.ARRAY(postgresql.UUID(as_uuid=True)), server_default="{}"),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False, server_default=sa.func.now()),
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
# JOURNALS TABLE
|
||||
# ==========================================================================
|
||||
op.create_table(
|
||||
"journals",
|
||||
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
||||
sa.Column(
|
||||
"agent_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("agents.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
unique=True,
|
||||
),
|
||||
sa.Column("total_entries", sa.Integer(), server_default="0"),
|
||||
sa.Column("last_entry_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("latest_summary", sa.Text(), nullable=True),
|
||||
sa.Column("summary_updated_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("entries_by_type", postgresql.JSON(), server_default="{}"),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False, server_default=sa.func.now()),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
# JOURNAL ENTRIES TABLE
|
||||
# ==========================================================================
|
||||
op.create_table(
|
||||
"journal_entries",
|
||||
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
||||
sa.Column(
|
||||
"journal_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("journals.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
),
|
||||
sa.Column(
|
||||
"type",
|
||||
sa.Enum(
|
||||
"task_reflection",
|
||||
"decision_log",
|
||||
"learning",
|
||||
"struggle",
|
||||
"general",
|
||||
name="journalentrytype",
|
||||
),
|
||||
nullable=False,
|
||||
index=True,
|
||||
),
|
||||
sa.Column("title", sa.String(200), nullable=False),
|
||||
sa.Column("content", sa.Text(), nullable=False),
|
||||
sa.Column(
|
||||
"task_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("tasks.id", ondelete="SET NULL"),
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column(
|
||||
"session_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("sessions.id", ondelete="SET NULL"),
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column("timestamp", sa.DateTime(), nullable=False, server_default=sa.func.now(), index=True),
|
||||
sa.Column("tags", postgresql.ARRAY(sa.String()), server_default="{}"),
|
||||
sa.Column("sentiment", sa.String(50), nullable=True),
|
||||
sa.Column("is_private", sa.Boolean(), server_default="false"),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False, server_default=sa.func.now()),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
# HANDOFFS TABLE
|
||||
# ==========================================================================
|
||||
op.create_table(
|
||||
"handoffs",
|
||||
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
||||
sa.Column(
|
||||
"task_id",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("tasks.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
),
|
||||
sa.Column("summary", sa.Text(), nullable=False),
|
||||
sa.Column("new_functionality", postgresql.ARRAY(sa.String()), server_default="{}"),
|
||||
sa.Column("modified_behavior", postgresql.ARRAY(sa.String()), server_default="{}"),
|
||||
sa.Column("breaking_changes", postgresql.ARRAY(sa.String()), server_default="{}"),
|
||||
sa.Column("required_docs", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("optional_docs", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("commits", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("new_files", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("modified_files", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("key_conversations", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("code_samples", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("gotchas", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("related_docs", postgresql.ARRAY(sa.String()), server_default="{}"),
|
||||
sa.Column("changelog_entry", sa.Text(), nullable=True),
|
||||
sa.Column("key_learnings", postgresql.ARRAY(sa.String()), server_default="{}"),
|
||||
sa.Column("key_decisions", postgresql.JSON(), server_default="[]"),
|
||||
sa.Column("questions", postgresql.ARRAY(sa.String()), server_default="{}"),
|
||||
sa.Column("dev_notes_location", sa.String(500), nullable=True),
|
||||
sa.Column(
|
||||
"status",
|
||||
sa.Enum("pending", "claimed", "in_progress", "completed", name="handoffstatus"),
|
||||
nullable=False,
|
||||
server_default="pending",
|
||||
index=True,
|
||||
),
|
||||
sa.Column(
|
||||
"assigned_to",
|
||||
postgresql.UUID(as_uuid=True),
|
||||
sa.ForeignKey("agents.id", ondelete="SET NULL"),
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False, server_default=sa.func.now()),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("claimed_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("completed_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("documenter_notes", sa.Text(), nullable=True),
|
||||
sa.UniqueConstraint("task_id", name="uq_handoffs_task_id"),
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
# PERFORMANCE INDEXES
|
||||
# ==========================================================================
|
||||
|
||||
# Composite indexes for common queries
|
||||
op.create_index(
|
||||
"ix_tasks_team_status",
|
||||
"tasks",
|
||||
["team", "status"],
|
||||
)
|
||||
op.create_index(
|
||||
"ix_tasks_assigned_status",
|
||||
"tasks",
|
||||
["assigned_to", "status"],
|
||||
)
|
||||
op.create_index(
|
||||
"ix_messages_channel_timestamp",
|
||||
"messages",
|
||||
["channel_id", sa.text("timestamp DESC")],
|
||||
)
|
||||
op.create_index(
|
||||
"ix_notifications_to_timestamp",
|
||||
"notifications",
|
||||
[sa.text("timestamp DESC")],
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# Drop indexes
|
||||
op.drop_index("ix_notifications_to_timestamp", table_name="notifications")
|
||||
op.drop_index("ix_messages_channel_timestamp", table_name="messages")
|
||||
op.drop_index("ix_tasks_assigned_status", table_name="tasks")
|
||||
op.drop_index("ix_tasks_team_status", table_name="tasks")
|
||||
|
||||
# Drop tables in reverse order
|
||||
op.drop_table("handoffs")
|
||||
op.drop_table("journal_entries")
|
||||
op.drop_table("journals")
|
||||
op.drop_table("notifications")
|
||||
op.drop_table("messages")
|
||||
op.drop_table("sessions")
|
||||
op.drop_table("groups")
|
||||
op.drop_table("channels")
|
||||
|
||||
# Drop FK before dropping tasks
|
||||
op.drop_constraint("fk_agents_current_task", "agents", type_="foreignkey")
|
||||
|
||||
op.drop_table("tasks")
|
||||
op.drop_table("agents")
|
||||
|
||||
# Drop enums
|
||||
op.execute("DROP TYPE IF EXISTS handoffstatus")
|
||||
op.execute("DROP TYPE IF EXISTS journalentrytype")
|
||||
op.execute("DROP TYPE IF EXISTS notificationpriority")
|
||||
op.execute("DROP TYPE IF EXISTS notificationtype")
|
||||
op.execute("DROP TYPE IF EXISTS messagetype")
|
||||
op.execute("DROP TYPE IF EXISTS sessionstatus")
|
||||
op.execute("DROP TYPE IF EXISTS channeltype")
|
||||
op.execute("DROP TYPE IF EXISTS complexity")
|
||||
op.execute("DROP TYPE IF EXISTS taskstatus")
|
||||
op.execute("DROP TYPE IF EXISTS agentstatus")
|
||||
op.execute("DROP TYPE IF EXISTS team")
|
||||
op.execute("DROP TYPE IF EXISTS agentrole")
|
||||
Reference in New Issue
Block a user