Coverage for backend/django/diagnostics/failure_bundle.py: 100%
32 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-02-11 21:43 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-02-11 21:43 +0000
1"""Failure bundle types using Pydantic for validation and serialization in orchestrator."""
3from __future__ import annotations
5from typing import Optional
7from pydantic import BaseModel, Field, JsonValue
10class SolverMeta(BaseModel):
11 termination_condition: Optional[str] = None
12 solver_status: Optional[str] = None
13 exception: Optional[str] = None
16class VariableOutsideBounds(BaseModel):
17 """
18 A single variable reported outside bounds by DiagnosticsToolbox.
20 This is intentionally a small, stable schema: it’s meant to be evidence we
21 can show in the UI and use for lightweight suggestions. (output is roughly parsed based on outputs seen in docs )
22 """
24 name: str
25 value: float | str | None = None
26 lower: float | str | None = None
27 upper: float | str | None = None
28 reason: str = "fixed_outside_bounds"
31class StructuralSignals(BaseModel):
32 dof: Optional[int] = None
33 overconstrained: JsonValue | None = None
34 underconstrained: JsonValue | None = None
35 inconsistent_units: list[JsonValue] | None = None
38class NumericalSignals(BaseModel):
39 variables_outside_bounds: list[VariableOutsideBounds] | None = None
40 constraints_large_residuals: list[JsonValue] | None = None
41 scaling_warnings: list[JsonValue] | None = None
43class FailureBundle(BaseModel):
44 task_id: int
45 flowsheet_id: int
46 solve_index: Optional[int] = None
47 trigger: str = "solve_failure"
49 # Upstream payloads may omit solver metadata. Default it so `bundle.solver` is always present.
50 solver: SolverMeta = Field(default_factory=SolverMeta)
52 # Short, high-level error messages (if any). This is separate from `diagnostics_raw_text`.
53 eval_errors: Optional[list[str]] = None
55 # Raw DiagnosticsToolbox output as plain text (not structured JSON).
56 # Optional: some failure paths don't capture the toolbox report.
57 diagnostics_raw_text: Optional[str] = None
59 structural: StructuralSignals = Field(default_factory=StructuralSignals)
60 numerical: NumericalSignals = Field(default_factory=NumericalSignals)