File size: 2,271 Bytes
13fe504
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
"""Table-store abstractions shared by warehouse-capable repair paths."""

from __future__ import annotations

from pathlib import Path
from typing import Protocol

from pydantic import BaseModel, ConfigDict, Field

from dataforge.detectors.base import Schema
from dataforge.repairers.base import ProposedFix
from dataforge.stores.patch_plan import PatchPlan
from dataforge.table import TableLike


class StoreApplyReceipt(BaseModel):
    """Receipt returned after a table-store patch plan is applied."""

    schema_version: str = "table_store_apply_receipt_v1"
    ok: bool
    txn_id: str | None = None
    backend: str
    target: str
    patch_plan_sha256: str = Field(pattern=r"^[0-9a-f]{64}$")
    post_state_sha256: str | None = Field(default=None, pattern=r"^[0-9a-f]{64}$")
    reason: str = Field(min_length=1)

    model_config = ConfigDict(strict=True, extra="forbid", frozen=True)


class StoreRevertReceipt(BaseModel):
    """Receipt returned after a table-store transaction rollback."""

    schema_version: str = "table_store_revert_receipt_v1"
    ok: bool
    txn_id: str
    backend: str
    target: str
    reason: str = Field(min_length=1)

    model_config = ConfigDict(strict=True, extra="forbid", frozen=True)


class TableStore(Protocol):
    """Minimal interface for backends that can host DataForge patch plans."""

    backend: str
    target: str
    relation: str
    row_identity_columns: tuple[str, ...]

    def read_table(self) -> TableLike:
        """Read the target relation into DataForge's string-preserving table surface."""

    def build_patch_plan(

        self,

        fixes: list[ProposedFix],

        *,

        schema: Schema | None,

        safety_verdict: str,

        touched_constraints: tuple[str, ...] = (),

        smt_obligations: tuple[str, ...] = (),

    ) -> PatchPlan:
        """Build a reversible patch plan for verified fixes."""

    def apply_patch_plan(

        self, plan: PatchPlan, *, state_root: Path | None = None

    ) -> StoreApplyReceipt:
        """Apply a patch plan through the backend transaction mechanism."""


class TableStoreError(RuntimeError):
    """Raised when a table-store operation cannot complete safely."""