turnstone/app/services/diagnose/models.py
pyr0ball d833febe77 refactor: convert diagnose module to package for multi-agent pipeline (issue #29)
- Move app/services/diagnose.py verbatim to app/services/diagnose/legacy.py
- Create app/services/diagnose/__init__.py with full implementation so that
  patch('app.services.diagnose._HAS_DATEPARSER') targets the correct namespace
  and all 303 existing tests continue to pass without modification
- Add app/services/diagnose/models.py with 5 pipeline dataclasses:
  EventCluster, TimelineResult, ClassifiedTimeline, Hypothesis, RankedHypothesis
- Add app/services/diagnose/pipeline.py with run_pipeline() stub (Task 6)
- Add MULTI_AGENT_ENABLED feature flag (off by default via env var)
- Zero behavior change; ruff clean

Closes: #29
2026-05-25 11:12:39 -07:00

61 lines
1.4 KiB
Python

"""Pipeline data types for the multi-agent diagnose pipeline."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Literal
SeverityLabel = Literal["CRITICAL", "ERROR", "WARN", "INFO", "DEBUG", "UNKNOWN"]
@dataclass
class EventCluster:
cluster_id: str
entries: list[str] # entry_id refs
start_iso: str | None
end_iso: str | None
duration_seconds: float
source_ids: list[str]
pattern_tags: list[str]
severity: SeverityLabel # highest severity from raw text
burst: bool
gap_before_seconds: float
representative_text: str
@dataclass
class TimelineResult:
clusters: list[EventCluster]
total_entries: int
window_start: str | None
window_end: str | None
gap_count: int
burst_count: int
dominant_sources: list[str]
@dataclass
class ClassifiedTimeline:
timeline: TimelineResult
cluster_severities: dict[str, SeverityLabel]
classifier_used: Literal["ml", "pattern_tags", "regex"]
model_id: str | None
@dataclass
class Hypothesis:
hypothesis_id: str
title: str
description: str
confidence: float
supporting_cluster_ids: list[str]
runbook_refs: list[str]
severity: SeverityLabel
@dataclass
class RankedHypothesis:
hypothesis: Hypothesis
novelty_score: float
similarity_to_known: float
suppress: bool
suppression_reason: str | None