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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136"""AutoCorrection model for safe automatic edits.
AutoCorrections replace the old Proposal model. They represent edits that are
safe to apply automatically (high confidence) without human review.
Key differences from Proposal:
- No status lifecycle (applied immediately or converted to ReviewItem)
- Requires high confidence (>0.95) for auto-application
- Links to single observation (not a list)
- Simpler search/replace fields (no nested SearchReplaceDiff)
"""
from datetime import UTC, datetime
from uuid import uuid4
from pydantic import BaseModel, ConfigDict, Field
class AutoCorrection(BaseModel):
"""A correction safe to apply automatically.
AutoCorrections are generated by specialized agents when they have
high confidence in a fix. They contain a search-replace edit that
can be applied without human review.
For lower-confidence fixes, agents generate ReviewItems instead.
Attributes:
id: UUID for this correction
observation_id: Links to the observation this fixes
search: Exact text to find in markdown
replace: Text to replace with (can be empty for deletion)
justification: Why this is safe to auto-apply (glass box)
confidence: Should be high (>0.95) for auto-corrections
applied: Whether this correction has been applied
applied_at: When the correction was applied
agent: Which agent generated this correction
page_num: Page number where the correction applies
Example:
>>> correction = AutoCorrection(
... observation_id="obs-123",
... search="## Introduction",
... replace="## 1. Introduction",
... justification="Adding section number to match document structure",
... confidence=0.98,
... agent="structure"
... )
"""
id: str = Field(
default_factory=lambda: str(uuid4()),
description="UUID for this correction"
)
observation_id: str = Field(
...,
description="Links to the observation this fixes"
)
# The edit operation
search: str = Field(
...,
min_length=1,
description="Exact text to find in markdown"
)
replace: str = Field(
...,
description="Text to replace with (can be empty for deletion)"
)
# Glass box transparency
justification: str = Field(
...,
min_length=1,
description="Why this is safe to auto-apply"
)
confidence: float = Field(
...,
ge=0.0,
le=1.0,
description="Should be high (>0.95) for auto-corrections"
)
# Application tracking
applied: bool = Field(
default=False,
description="Whether this correction has been applied"
)
applied_at: datetime | None = Field(
default=None,
description="When the correction was applied"
)
# Source tracking
agent: str = Field(
...,
description="Which agent generated this correction"
)
page_num: int | None = Field(
default=None,
description="Page number where the correction applies"
)
def mark_applied(self) -> None:
"""Mark this correction as applied.
Sets applied=True and records the current timestamp.
Raises:
ValueError: If correction is already applied
"""
if self.applied:
raise ValueError("Correction already applied")
self.applied = True
self.applied_at = datetime.now(UTC)
model_config = ConfigDict(
json_schema_extra={
"example": {
"id": "ac-550e8400-e29b-41d4-a716-446655440000",
"observation_id": "obs-550e8400-e29b-41d4-a716-446655440001",
"search": "## Introduction",
"replace": "## 1. Introduction",
"justification": "Adding section number to match document's numbered heading structure",
"confidence": 0.98,
"applied": False,
"applied_at": None,
"agent": "structure",
"page_num": 1
}
}
)
__all__ = ["AutoCorrection"]