File size: 2,065 Bytes
559c2ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e6496c0
 
 
 
 
559c2ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""analysis/signals.py — shared signal types for the Analyst Edge layer.

These Pydantic models carry deterministically-computed evidence (verbatim
before/after text, counts, deltas) from the analysis modules to the LangGraph
agent and synthesis node. The LLM explains; the code supplies the figures.
"""
from __future__ import annotations

from typing import Literal, Optional
from pydantic import BaseModel, ConfigDict, Field


class QuarterDelta(BaseModel):
    """A verbatim text change detected between two consecutive filing periods."""
    model_config = ConfigDict(extra="ignore")

    kind: Literal[
        "risk_added",
        "risk_removed",
        "risk_reworded",
        "guidance_language_shift",
        "term_frequency",
        "kpi_dropped",
        # transcript drift kinds (analysis/tone_drift.py)
        "tone_trend",
        "topic_arc",
        "recurring_evasion",
        "topic_fade",
    ] = Field(description="Type of delta detected.")

    period_from: str = Field(description="Prior filing period, e.g. 'Q42025'.")
    period_to: str = Field(description="Current filing period, e.g. 'Q12026'.")

    before_text: str = Field(
        default="",
        description="Verbatim fragment from the prior period. Empty for risk_added.",
    )
    after_text: str = Field(
        default="",
        description="Verbatim fragment from the current period. Empty for risk_removed.",
    )

    computed_metric: str = Field(
        default="",
        description="A computed summary, e.g. '2→8 occurrences (+300%)' for term_frequency.",
    )

    source: Literal["10-K", "10-Q", "transcript"] = Field(
        default="10-Q",
        description="Filing type the delta was detected in.",
    )

    significance: Literal["HIGH", "MEDIUM", "LOW"] = Field(
        default="MEDIUM",
        description="Computed significance: HIGH for new risks or large frequency swings, etc.",
    )

    term: str = Field(
        default="",
        description="The term or risk label being tracked (for term_frequency / kpi_dropped).",
    )