""" DecisionLog model for tracking important decisions made during work. Stores decisions with their rationale, alternatives considered, and impact to provide decision history and context for future work. """ from typing import TYPE_CHECKING, Optional from sqlalchemy import ForeignKey, Index, String, Text from sqlalchemy.orm import Mapped, mapped_column, relationship from .base import Base, TimestampMixin, UUIDMixin if TYPE_CHECKING: from .project import Project from .session import Session class DecisionLog(Base, UUIDMixin, TimestampMixin): """ DecisionLog model for tracking important decisions made during work. Stores decisions with their type, rationale, alternatives considered, and impact assessment. This provides a decision history that can be referenced in future conversations and work sessions. Attributes: decision_type: Type of decision (technical, architectural, process, security) decision_text: What was decided (the actual decision) rationale: Why this decision was made alternatives_considered: JSON array of other options that were considered impact: Impact level (low, medium, high, critical) project_id: Foreign key to projects (optional) session_id: Foreign key to sessions (optional) tags: JSON array of tags for retrieval and categorization project: Relationship to Project model session: Relationship to Session model """ __tablename__ = "decision_logs" # Foreign keys project_id: Mapped[Optional[str]] = mapped_column( String(36), ForeignKey("projects.id", ondelete="SET NULL"), doc="Foreign key to projects (optional)" ) session_id: Mapped[Optional[str]] = mapped_column( String(36), ForeignKey("sessions.id", ondelete="SET NULL"), doc="Foreign key to sessions (optional)" ) # Decision metadata decision_type: Mapped[str] = mapped_column( String(100), nullable=False, doc="Type of decision: technical, architectural, process, security" ) impact: Mapped[str] = mapped_column( String(50), default="medium", server_default="medium", doc="Impact level: low, medium, high, critical" ) # Decision content decision_text: Mapped[str] = mapped_column( Text, nullable=False, doc="What was decided (the actual decision)" ) rationale: Mapped[Optional[str]] = mapped_column( Text, doc="Why this decision was made" ) alternatives_considered: Mapped[Optional[str]] = mapped_column( Text, doc="JSON array of other options that were considered" ) # Retrieval metadata tags: Mapped[Optional[str]] = mapped_column( Text, doc="JSON array of tags for retrieval and categorization" ) # Relationships project: Mapped[Optional["Project"]] = relationship( "Project", doc="Relationship to Project model" ) session: Mapped[Optional["Session"]] = relationship( "Session", doc="Relationship to Session model" ) # Indexes __table_args__ = ( Index("idx_decision_logs_project", "project_id"), Index("idx_decision_logs_session", "session_id"), Index("idx_decision_logs_type", "decision_type"), Index("idx_decision_logs_impact", "impact"), ) def __repr__(self) -> str: """String representation of the decision log.""" decision_preview = self.decision_text[:50] + "..." if len(self.decision_text) > 50 else self.decision_text return f""