forked from cardosofelipe/pragma-stack
fix(models): use enum values instead of names for PostgreSQL
Add values_callable to all enum columns so SQLAlchemy serializes using the enum's .value (lowercase) instead of .name (uppercase). PostgreSQL enum types defined in migrations use lowercase values. Fixes: invalid input value for enum autonomy_level: "MILESTONE" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -62,7 +62,11 @@ class AgentInstance(Base, UUIDMixin, TimestampMixin):
|
|||||||
|
|
||||||
# Status tracking
|
# Status tracking
|
||||||
status: Column[AgentStatus] = Column(
|
status: Column[AgentStatus] = Column(
|
||||||
Enum(AgentStatus, name="agent_status"),
|
Enum(
|
||||||
|
AgentStatus,
|
||||||
|
name="agent_status",
|
||||||
|
values_callable=lambda x: [e.value for e in x],
|
||||||
|
),
|
||||||
default=AgentStatus.IDLE,
|
default=AgentStatus.IDLE,
|
||||||
nullable=False,
|
nullable=False,
|
||||||
index=True,
|
index=True,
|
||||||
|
|||||||
@@ -59,7 +59,9 @@ class Issue(Base, UUIDMixin, TimestampMixin):
|
|||||||
|
|
||||||
# Issue type (Epic, Story, Task, Bug)
|
# Issue type (Epic, Story, Task, Bug)
|
||||||
type: Column[IssueType] = Column(
|
type: Column[IssueType] = Column(
|
||||||
Enum(IssueType, name="issue_type"),
|
Enum(
|
||||||
|
IssueType, name="issue_type", values_callable=lambda x: [e.value for e in x]
|
||||||
|
),
|
||||||
default=IssueType.TASK,
|
default=IssueType.TASK,
|
||||||
nullable=False,
|
nullable=False,
|
||||||
index=True,
|
index=True,
|
||||||
@@ -78,14 +80,22 @@ class Issue(Base, UUIDMixin, TimestampMixin):
|
|||||||
|
|
||||||
# Status and priority
|
# Status and priority
|
||||||
status: Column[IssueStatus] = Column(
|
status: Column[IssueStatus] = Column(
|
||||||
Enum(IssueStatus, name="issue_status"),
|
Enum(
|
||||||
|
IssueStatus,
|
||||||
|
name="issue_status",
|
||||||
|
values_callable=lambda x: [e.value for e in x],
|
||||||
|
),
|
||||||
default=IssueStatus.OPEN,
|
default=IssueStatus.OPEN,
|
||||||
nullable=False,
|
nullable=False,
|
||||||
index=True,
|
index=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
priority: Column[IssuePriority] = Column(
|
priority: Column[IssuePriority] = Column(
|
||||||
Enum(IssuePriority, name="issue_priority"),
|
Enum(
|
||||||
|
IssuePriority,
|
||||||
|
name="issue_priority",
|
||||||
|
values_callable=lambda x: [e.value for e in x],
|
||||||
|
),
|
||||||
default=IssuePriority.MEDIUM,
|
default=IssuePriority.MEDIUM,
|
||||||
nullable=False,
|
nullable=False,
|
||||||
index=True,
|
index=True,
|
||||||
@@ -132,7 +142,11 @@ class Issue(Base, UUIDMixin, TimestampMixin):
|
|||||||
|
|
||||||
# Sync status with external tracker
|
# Sync status with external tracker
|
||||||
sync_status: Column[SyncStatus] = Column(
|
sync_status: Column[SyncStatus] = Column(
|
||||||
Enum(SyncStatus, name="sync_status"),
|
Enum(
|
||||||
|
SyncStatus,
|
||||||
|
name="sync_status",
|
||||||
|
values_callable=lambda x: [e.value for e in x],
|
||||||
|
),
|
||||||
default=SyncStatus.SYNCED,
|
default=SyncStatus.SYNCED,
|
||||||
nullable=False,
|
nullable=False,
|
||||||
# Note: Index defined in __table_args__ as ix_issues_sync_status
|
# Note: Index defined in __table_args__ as ix_issues_sync_status
|
||||||
|
|||||||
@@ -35,28 +35,44 @@ class Project(Base, UUIDMixin, TimestampMixin):
|
|||||||
description = Column(Text, nullable=True)
|
description = Column(Text, nullable=True)
|
||||||
|
|
||||||
autonomy_level: Column[AutonomyLevel] = Column(
|
autonomy_level: Column[AutonomyLevel] = Column(
|
||||||
Enum(AutonomyLevel, name="autonomy_level"),
|
Enum(
|
||||||
|
AutonomyLevel,
|
||||||
|
name="autonomy_level",
|
||||||
|
values_callable=lambda x: [e.value for e in x],
|
||||||
|
),
|
||||||
default=AutonomyLevel.MILESTONE,
|
default=AutonomyLevel.MILESTONE,
|
||||||
nullable=False,
|
nullable=False,
|
||||||
index=True,
|
index=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
status: Column[ProjectStatus] = Column(
|
status: Column[ProjectStatus] = Column(
|
||||||
Enum(ProjectStatus, name="project_status"),
|
Enum(
|
||||||
|
ProjectStatus,
|
||||||
|
name="project_status",
|
||||||
|
values_callable=lambda x: [e.value for e in x],
|
||||||
|
),
|
||||||
default=ProjectStatus.ACTIVE,
|
default=ProjectStatus.ACTIVE,
|
||||||
nullable=False,
|
nullable=False,
|
||||||
index=True,
|
index=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
complexity: Column[ProjectComplexity] = Column(
|
complexity: Column[ProjectComplexity] = Column(
|
||||||
Enum(ProjectComplexity, name="project_complexity"),
|
Enum(
|
||||||
|
ProjectComplexity,
|
||||||
|
name="project_complexity",
|
||||||
|
values_callable=lambda x: [e.value for e in x],
|
||||||
|
),
|
||||||
default=ProjectComplexity.MEDIUM,
|
default=ProjectComplexity.MEDIUM,
|
||||||
nullable=False,
|
nullable=False,
|
||||||
index=True,
|
index=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
client_mode: Column[ClientMode] = Column(
|
client_mode: Column[ClientMode] = Column(
|
||||||
Enum(ClientMode, name="client_mode"),
|
Enum(
|
||||||
|
ClientMode,
|
||||||
|
name="client_mode",
|
||||||
|
values_callable=lambda x: [e.value for e in x],
|
||||||
|
),
|
||||||
default=ClientMode.AUTO,
|
default=ClientMode.AUTO,
|
||||||
nullable=False,
|
nullable=False,
|
||||||
index=True,
|
index=True,
|
||||||
|
|||||||
@@ -57,7 +57,11 @@ class Sprint(Base, UUIDMixin, TimestampMixin):
|
|||||||
|
|
||||||
# Status
|
# Status
|
||||||
status: Column[SprintStatus] = Column(
|
status: Column[SprintStatus] = Column(
|
||||||
Enum(SprintStatus, name="sprint_status"),
|
Enum(
|
||||||
|
SprintStatus,
|
||||||
|
name="sprint_status",
|
||||||
|
values_callable=lambda x: [e.value for e in x],
|
||||||
|
),
|
||||||
default=SprintStatus.PLANNED,
|
default=SprintStatus.PLANNED,
|
||||||
nullable=False,
|
nullable=False,
|
||||||
index=True,
|
index=True,
|
||||||
|
|||||||
Reference in New Issue
Block a user