from __future__ import annotations import re import uuid from typing import Literal from pydantic import BaseModel, Field, field_validator from api.schemas.task import TaskRead from api.schemas.workplan import WorkplanRead from api.schemas.workplan_dependency import WorkplanDependencyRead class RepositoryProjectionReconcile(BaseModel): expected_commit: str acknowledge_retirements: bool = False @field_validator("expected_commit") @classmethod def validate_commit(cls, value: str) -> str: value = value.strip().lower() if not re.fullmatch(r"[0-9a-f]{40}", value): raise ValueError("expected_commit must be a full 40-character Git SHA") return value class RepositoryProjectionSnapshot(BaseModel): """One bounded read of a repository's complete work-record projection.""" schema_version: Literal["state-hub.repository-projection-snapshot.v1"] = Field( validation_alias="schema", serialization_alias="schema", ) repo_slug: str repo_id: uuid.UUID workplans: list[WorkplanRead] tasks: list[TaskRead] dependencies: list[WorkplanDependencyRead]