Files
zeekayandHanzo Dev b497511c04 no hogs: stamphog and review_hog are stamp and review
Both are Django apps, and both pin `label` in apps.py — "stamp" and "review".
django_migrations keys a row on (app_label, name), and app_label comes from that
pin and not from the import path, so moving the directory does not orphan a
single migration. All six stay where they are, untouched.

  products/stamphog -> products/stamp     name = products.stamp.backend
  products/review_hog -> products/review  name = products.review.backend
  StamphogScene/ -> StampScene/, and stamphogSceneLogic.ts with it

189 files follow. An earlier attempt at this move failed twice for reasons worth
recording: `git mv A B` where B exists puts A INSIDE B, and a stray
products/stamp/node_modules from an abandoned run was enough to make B exist —
the app ended up nested two deep. And `git ls-files` does not list a file moved
with plain mv and not yet staged, so a pass over "every tracked file" silently
skips it; that is how StampScene.tsx kept importing ./stampSceneLogic after the
file beside it had been renamed back.

bin/check-imports-are-committed: all first-party imports across 15,843 files
resolve.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-09 10:18:18 -07:00

117 lines
2.9 KiB
Python

"""
Contract types for stamp.
Frozen dataclasses that define what this product exposes.
No Django imports. Used by facade as inputs/outputs.
Uses ``pydantic.dataclasses.dataclass`` rather than the stdlib
variant — same syntax, same ``is_dataclass()`` compatibility (so
``DataclassSerializer`` keeps working), but with runtime type
validation on construction.
"""
from datetime import datetime
from uuid import UUID
from pydantic import Field
from pydantic.dataclasses import dataclass
from .enums import ChannelResolutionSource, DigestRunStatus, ReviewRunStatus, ReviewVerdict
@dataclass(frozen=True)
class RepoConfigDTO:
"""A repository stamp is configured to review for a team."""
id: UUID
team_id: int
provider: str
repository: str
enabled: bool
installation_id: str
digest_enabled: bool = False
created_at: datetime | None = None
updated_at: datetime | None = None
@dataclass(frozen=True)
class PullRequestDTO:
"""A pull request stamp knows about, including merge state once it merges."""
id: UUID
team_id: int
repo_config_id: UUID
repository: str
pr_number: int
pr_url: str
title: str
author_login: str
head_branch: str
body_excerpt: str
additions: int
deletions: int
changed_files: int
audience_key: str
merge_commit_sha: str = ""
merged_at: datetime | None = None
digest_run_id: UUID | None = None
posted_comment_id: int | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
@dataclass(frozen=True)
class DigestChannelDTO:
"""A Slack destination for one digest audience."""
id: UUID
team_id: int
audience_key: str
slack_integration_id: int
slack_channel_id: str
slack_channel_name: str
enabled: bool
resolution_source: ChannelResolutionSource = ChannelResolutionSource.MANUAL
last_digest_at: datetime | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
@dataclass(frozen=True)
class DigestRunDTO:
"""One posted (or attempted) daily digest for a channel."""
id: UUID
team_id: int
digest_channel_id: UUID
status: DigestRunStatus
pr_count: int
summary: dict = Field(default_factory=dict)
slack_message_ts: str = ""
error: str = ""
created_at: datetime | None = None
posted_at: datetime | None = None
@dataclass(frozen=True)
class ReviewRunDTO:
"""A single stamp review attempt against a pull request."""
id: UUID
team_id: int
pull_request_id: UUID
# Convenience PR context sourced via the pull_request FK.
repository: str
pr_number: int
pr_url: str
head_sha: str
status: ReviewRunStatus
verdict: ReviewVerdict
delivery_id: str | None = None
gate_result: dict | None = None
output: dict = Field(default_factory=dict)
error: str = ""
created_at: datetime | None = None
updated_at: datetime | None = None
completed_at: datetime | None = None