""" ProjectState model for tracking current state of projects. Stores the current phase, progress, blockers, and next actions for each project to enable quick context retrieval when resuming work. """ from typing import TYPE_CHECKING, Optional from sqlalchemy import ForeignKey, Index, Integer, 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 ProjectState(Base, UUIDMixin, TimestampMixin): """ ProjectState model for tracking current state of projects. Stores the current phase, progress, blockers, next actions, and key information about a project's state. Each project has exactly one ProjectState record that is updated as the project progresses. Attributes: project_id: Foreign key to projects (required, unique - one state per project) current_phase: Current phase or stage of the project progress_percentage: Integer percentage of completion (0-100) blockers: JSON array of current blockers preventing progress next_actions: JSON array of next steps to take context_summary: Dense overview text of where the project currently stands key_files: JSON array of important file paths for this project important_decisions: JSON array of key decisions made for this project last_session_id: Foreign key to the last session that updated this state project: Relationship to Project model last_session: Relationship to Session model """ __tablename__ = "project_states" # Foreign keys project_id: Mapped[str] = mapped_column( String(36), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False, unique=True, doc="Foreign key to projects (required, unique - one state per project)" ) last_session_id: Mapped[Optional[str]] = mapped_column( String(36), ForeignKey("sessions.id", ondelete="SET NULL"), doc="Foreign key to the last session that updated this state" ) # State metadata current_phase: Mapped[Optional[str]] = mapped_column( String(100), doc="Current phase or stage of the project" ) progress_percentage: Mapped[int] = mapped_column( Integer, default=0, server_default="0", doc="Integer percentage of completion (0-100)" ) # State content blockers: Mapped[Optional[str]] = mapped_column( Text, doc="JSON array of current blockers preventing progress" ) next_actions: Mapped[Optional[str]] = mapped_column( Text, doc="JSON array of next steps to take" ) context_summary: Mapped[Optional[str]] = mapped_column( Text, doc="Dense overview text of where the project currently stands" ) key_files: Mapped[Optional[str]] = mapped_column( Text, doc="JSON array of important file paths for this project" ) important_decisions: Mapped[Optional[str]] = mapped_column( Text, doc="JSON array of key decisions made for this project" ) # Relationships project: Mapped["Project"] = relationship( "Project", doc="Relationship to Project model" ) last_session: Mapped[Optional["Session"]] = relationship( "Session", doc="Relationship to Session model" ) # Indexes __table_args__ = ( Index("idx_project_states_project", "project_id"), Index("idx_project_states_last_session", "last_session_id"), Index("idx_project_states_progress", "progress_percentage"), ) def __repr__(self) -> str: """String representation of the project state.""" return f""