feat: extend operational investigation workflows
Generic Container CI/CD / test-build-publish (push) Successful in 3m53s
Server CI/CD v2 / build-test-publish-and-deploy (push) Successful in 3m52s

This commit is contained in:
2026-10-30 17:30:19 +08:00
parent 63af998045
commit 05183aff93
82 changed files with 4644 additions and 330 deletions
+22 -1
View File
@@ -7,7 +7,7 @@ from pathlib import Path
from typing import Annotated, Any, Literal
from jsonschema import Draft7Validator
from pydantic import BaseModel, ConfigDict, Field, model_validator
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_serializer, model_validator
_catalog = json.loads(
(Path(__file__).resolve().parents[3] / "contracts/answer-ui-catalog.json").read_text()
@@ -34,9 +34,24 @@ class AnswerUiSpec(UiModel):
class AnswerUiBlock(UiModel):
version: Literal["answer-ui@1"]
block_id: Key
phase: Literal["process", "final"] | None = None
fallback_text: Annotated[str, Field(min_length=1, max_length=4000)]
spec: AnswerUiSpec
@field_validator("phase", mode="before")
@classmethod
def validate_explicit_phase(cls, value):
if value is None:
raise ValueError("UI phase must be process or final when supplied")
return value
@model_serializer(mode="wrap")
def serialize_optional_phase(self, handler):
data = handler(self)
if self.phase is None:
data.pop("phase", None)
return data
@model_validator(mode="after")
def validate_components(self):
spec = self.spec
@@ -83,6 +98,12 @@ class ReportUiBlock(UiModel):
block: AnswerUiBlock
evidence_refs: list[Annotated[str, Field(min_length=1, max_length=128)]] = Field(min_length=1, max_length=100)
@model_validator(mode="after")
def validate_report_phase(self):
if self.block.phase == "process":
raise ValueError("Report UI blocks must contain final results")
return self
def validate_report_ui_blocks(blocks: list[ReportUiBlock], evidence_refs: list[str]) -> None:
ids = [item.block.block_id for item in blocks]