feat(investigations): add event impact and work-order feedback flows

Add isolated burst and pollution impact evidence, parallel work-order workflows, persisted notifications and graph updates.

Checkpoint current code. Known follow-ups remain for large pollution result previews and graceful geometry failure.
This commit is contained in:
2026-11-14 15:14:02 +08:00
parent 471ad92a47
commit 2e4f6cb93b
49 changed files with 1826 additions and 93 deletions
@@ -85,6 +85,25 @@ async def investigation():
return task, repository, service, evidence.evidence_id
@pytest.mark.anyio
async def test_pollution_charts_validate_quality_values_and_keep_their_own_workflow():
from app.services.scada_presentation_coverage import add_targets, applies, ScadaObservations, verify_chart
task, repository, _, evidence_id = await investigation()
task["workflow"] = "water_pollution"
evidence = repository.evidence[evidence_id]
for device in evidence["data_snapshot"]["data"]["data"]["devices"]:
device.update(device_type="quality", measurement_unit="mg/L")
value = chart(devices=[DEVICES[0]])
value["scada"].update(metric="quality", unit="mg/L")
assert applies(task)
verified = verify_chart(task, value, [evidence], [evidence_id])
assert verified["metric"] == "quality" and verified["gaps"] == []
observations = ScadaObservations(task, [evidence])
assert add_targets(None, [DEVICES[0]], observations)["targets"] == [DEVICES[0]]
task["handling_context"] = {"phase": "field_review"}
assert not applies(task)
def coverage(comparison_devices):
slots = [(START + timedelta(minutes=15 * i)).isoformat() for i in range(13)]
common = {"coverage": {device: {"covered": slots} for device in DEVICES}, "metric": "flow", "window_start": START.isoformat(), "window_end": END.isoformat(), "gaps": []}