• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

liqd / roots / 22072536647

16 Feb 2026 05:41PM UTC coverage: 42.093%. First build
22072536647

Pull #59

github

Pull Request #59: apps/summerization: Integrate Document Summary into Workflow

51 of 314 new or added lines in 7 files covered. (16.24%)

3564 of 8467 relevant lines covered (42.09%)

0.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.46
/apps/summarization/pydantic_models.py
1
"""Pydantic models for summarization responses."""
2

3
from typing import List
1✔
4
from typing import Literal
5
from typing import Optional
1✔
6

1✔
7
from pydantic import BaseModel
8
from pydantic import Field
9

1✔
10

11
class SummaryItem(BaseModel):
12
    """Response model for summarization."""
1✔
13

1✔
14
    title: str = Field(description="Title of the summary")
1✔
15
    summary: str = Field(description="The summary of the text or document")
16
    key_points: list[str] = Field(
17
        default_factory=list,
18
        description="Important points or keywords extracted from the text or document",
19
    )
20

1✔
21

22
class ModuleItem(BaseModel):
23
    """Response model for module summarization."""
1✔
24

1✔
25
    module_name: str = Field(description="Name of the module")
1✔
26
    summary: str = Field(description="Summary of the module")
27
    key_points: list[str] = Field(
28
        default_factory=list, description="Key points of the module"
1✔
29
    )
30
    phase_status: str = Field(
31
        description="Phase status: 'past' (in the past), 'active' (currently running), 'upcoming' (in the future)"
1✔
32
    )
33
    link: str = Field(description="Link to the module")
34

1✔
35

36
class SummaryResponse(BaseModel):
37
    """Response model for summarization."""
1✔
38

39
    summary_items: list[SummaryItem] = Field(
40
        default_factory=list,
41
        description=(
42
            "List of summary items. Each item contains: "
43
            "title, summary, key_points (list of important points)"
44
        ),
1✔
45
    )
46
    module_items: list[ModuleItem] = Field(
47
        default_factory=list,
48
        description=(
49
            "List of module items. Each item contains: "
50
            "module_name, summary, key_points (list of important points), "
51
            "phase_status (past/active/upcoming), link (URL to the module)"
52
        ),
53
    )
54

1✔
55

56
"""Pydantic models for summarization responses."""
57

1✔
58

59
# Debug sub-models
60
class Claim(BaseModel):
1✔
61
    """A claim extracted from the summary with evidence."""
1✔
62

1✔
63
    claim_text: str = Field(description="The claim text")
64
    evidence_type: Literal[
65
        "from_votes",
1✔
66
        "from_ratings",
67
        "from_open_answers",
68
        "from_comments",
1✔
69
        "from_base_text",
1✔
70
        "uncertain",
1✔
71
    ] = Field(description="Type of evidence supporting this claim")
72
    action: Literal["keep", "soften", "replace", "remove"] = Field(
73
        description="Action taken on this claim"
74
    )
1✔
75
    fix_hint: Optional[str] = Field(None, description="Hint for fixing the claim")
76

77

1✔
78
class QuantifierFix(BaseModel):
1✔
79
    """A fix for an uncertain quantifier."""
80

81
    original_phrase: str = Field(description="Original uncertain phrase")
82
    replacement: str = Field(description="Replacement phrase")
83
    reason: str = Field(description="Reason for the fix")
1✔
84

85

86
class Patch(BaseModel):
87
    """A patch applied to the summary."""
1✔
88

89
    patch_type: Literal["REPLACE", "REMOVE", "ADD_SENTENCE"] = Field(
90
        description="Type of patch applied"
1✔
91
    )
92
    target: str = Field(description="Target text to patch")
1✔
93
    replacement: Optional[str] = Field(
1✔
94
        None, description="Replacement text (for REPLACE/ADD)"
95
    )
1✔
96

97

98
class ModuleDebug(BaseModel):
99
    """Debug information for a module summary."""
100

1✔
101
    module_type: str = Field(description="Type of module")
102
    signals_snapshot: List[str] = Field(
103
        default_factory=list, description="Snapshot of signals at generation time"
104
    )
105
    draft_before_qa: str = Field(description="Draft summary before QA")
1✔
106
    claims: List[Claim] = Field(
107
        default_factory=list, description="Claims extracted from summary"
108
    )
109
    quantifier_fixes: List[QuantifierFix] = Field(
110
        default_factory=list, description="Fixes for uncertain quantifiers"
111
    )
1✔
112
    anchors: List[str] = Field(
113
        default_factory=list, description="Anchor points in the data"
114
    )
1✔
115
    coverage_gaps: List[str] = Field(
1✔
116
        default_factory=list, description="Identified gaps in coverage"
117
    )
1✔
118
    coverage_patch: Optional[str] = Field(
NEW
119
        None, description="Patch to fix coverage gaps"
×
120
    )
121
    patches: List[Patch] = Field(default_factory=list, description="Patches applied")
122
    after_qa: str = Field(description="Summary after QA process")
123
    diff_summary: Optional[str] = Field(None, description="Summary of changes made")
124
    qa_status: Literal["PASS", "FAIL"] = Field(description="QA status")
125

126

127
class ModuleFinal(BaseModel):
128
    """Final summary and bullets for a module."""
129

130
    summary: str = Field(description="Summary of the module's outcomes/activities")
131
    bullets: List[str] = Field(
NEW
132
        default_factory=list,
×
NEW
133
        description="Key points or main sentiments from the module",
×
134
    )
135

1✔
136

NEW
137
class PhaseModule(BaseModel):
×
NEW
138
    """Module within a phase section."""
×
NEW
139

×
140
    module_name: str = Field(description="Name of the module")
141
    module_id: int = Field(description="ID of the module")
142
    status: Literal["past", "current", "upcoming"] = Field(description="Module status")
1✔
143
    debug: Optional[ModuleDebug] = Field(None, description="Debug information")
144
    final: ModuleFinal = Field(description="Summary and key points for the module")
145

1✔
146

1✔
147
class PhaseSection(BaseModel):
148
    """A phase section containing modules."""
149

1✔
150
    modules: List[PhaseModule] = Field(
151
        default_factory=list, description="Modules in this phase"
152
    )
1✔
153

154

155
class Phases(BaseModel):
156
    """All phase sections."""
157

158
    past: PhaseSection = Field(default_factory=PhaseSection)
159
    current: PhaseSection = Field(default_factory=PhaseSection)
160
    upcoming: PhaseSection = Field(default_factory=PhaseSection)
161

162

163
class GeneralInfo(BaseModel):
164
    """General information about the project."""
165

166
    summary: str = Field(description="General summary of the entire project")
167
    goals: List[str] = Field(
168
        default_factory=list, description="Overall goals of the project"
169
    )
170

171

172
class ProjectSummaryResponse(BaseModel):
173
    """Response model for complete project summarization."""
174

175
    title: str = Field(default="Summary of participation")
176
    general_info: GeneralInfo = Field(description="General project information")
177
    phases: Phases = Field(description="All phase sections with their modules")
178

179

180
class DocumentInputItem(BaseModel):
181
    """Single document input item with handle and URL."""
182

183
    handle: str = Field(description="Unique identifier/handle for the document")
184
    url: str = Field(description="URL of the document")
185

186
    def is_image(self) -> bool:
187
        """Check if the URL points to an image file."""
188
        image_extensions = (
189
            ".jpg",
190
            ".jpeg",
191
            ".png",
192
            ".gif",
193
            ".webp",
194
            ".mpo",
195
            ".heif",
196
            ".avif",
197
            ".bmp",
198
            ".tiff",
199
            ".tif",
200
        )
201
        url_lower = self.url.lower()
202
        return any(url_lower.endswith(ext) for ext in image_extensions)
203

204
    def is_document(self) -> bool:
205
        """Check if the URL points to a document file (non-image)."""
206
        document_extensions = (".pdf", ".doc", ".docx", ".txt", ".rtf", ".odt")
207
        url_lower = self.url.lower()
208
        return any(url_lower.endswith(ext) for ext in document_extensions)
209

210

211
class DocumentSummaryItem(BaseModel):
212
    """Response model for a single document summary with handle."""
213

214
    handle: str = Field(description="Unique identifier/handle for the document")
215
    summary: str = Field(description="Summary of the document content")
216

217

218
class DocumentSummaryResponse(BaseModel):
219
    """Response model for multiple document summaries."""
220

221
    documents: list[DocumentSummaryItem] = Field(
222
        default_factory=list,
223
        description="List of document summaries, each with handle and summary",
224
    )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc