from enum import Enum from typing import Optional from pydantic import BaseModel, Field, model_validator class ChangeOp(str, Enum): CREATE = "create" UPDATE = "update" DELETE = "delete" class ChangeItem(BaseModel): op: ChangeOp path: str = Field(min_length=1) base_hash: Optional[str] = None proposed_content: Optional[str] = None reason: str = Field(min_length=1, max_length=500) @model_validator(mode="after") def validate_op_fields(self) -> "ChangeItem": if self.op in (ChangeOp.UPDATE, ChangeOp.DELETE) and not self.base_hash: raise ValueError("base_hash is required for update/delete") if self.op in (ChangeOp.CREATE, ChangeOp.UPDATE) and self.proposed_content is None: raise ValueError("proposed_content is required for create/update") if self.op == ChangeOp.DELETE and self.proposed_content is not None: raise ValueError("proposed_content is forbidden for delete") return self class ChangeSetPayload(BaseModel): schema_version: str task_id: str changeset: list[ChangeItem]