Health: a flow that cannot run says so, and the brain marks which neurons
A dependency loop is flagged on the canvas and was invisible everywhere else: /observability/summary answered "ok" with an empty problems list while the published flow could not run at all. It now reports the flows validation blocks, and the brain graph carries the reason on each neuron the issue names so the view built to find broken wiring can show it. Node errors stay counted once, as the nodes that failed to load, and an advisory like an unauthenticated webhook marks nothing — it is worth saying, but the flow still runs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XC2jX6Hdj7pxGGKzBTrbqB
This commit is contained in:
@@ -68,10 +68,56 @@ def test_the_summary_answers_even_when_degraded(
|
||||
assert response.status_code == 200
|
||||
body = response.json()
|
||||
assert body["status"] in {"ok", "degraded"}
|
||||
assert set(body["flows"]) == {"total", "running", "paused", "quarantined"}
|
||||
assert set(body["flows"]) == {
|
||||
"total",
|
||||
"running",
|
||||
"paused",
|
||||
"quarantined",
|
||||
"invalid",
|
||||
}
|
||||
assert "error" in body["nodes"]
|
||||
|
||||
|
||||
def test_a_flow_that_cannot_run_makes_the_summary_degraded(
|
||||
client: TestClient, superuser_token_headers: dict[str, str]
|
||||
) -> None:
|
||||
"""A loop on the canvas has to reach the health screen.
|
||||
|
||||
Validation runs on a build, not on this request, so what the engine already
|
||||
knows is what this reports — and reporting it is the whole point: a flow
|
||||
with a dependency loop cannot run, and the screen used to say "ok".
|
||||
"""
|
||||
from app.flow.pipeline import ValidationIssue
|
||||
|
||||
controller = client.app.state.flow_controller
|
||||
before = controller.issues
|
||||
controller.issues = [
|
||||
ValidationIssue(
|
||||
code="cycle",
|
||||
message="These nodes depend on each other in a loop",
|
||||
flow="looping",
|
||||
nodes=["looping.a", "looping.b"],
|
||||
),
|
||||
# Already counted as a node that failed to load, so not again here.
|
||||
ValidationIssue(
|
||||
code="node_error", message="boom", flow="broken", node="broken.x"
|
||||
),
|
||||
ValidationIssue(
|
||||
code="unauthenticated_hook", message="open", flow="hooky", node="hooky.h"
|
||||
),
|
||||
]
|
||||
try:
|
||||
body = client.get(f"{PREFIX}/summary", headers=superuser_token_headers).json()
|
||||
finally:
|
||||
controller.issues = before
|
||||
|
||||
assert body["status"] == "degraded"
|
||||
assert body["flows"]["invalid"] == 1
|
||||
assert any("looping" in problem for problem in body["problems"])
|
||||
assert not any("broken" in problem for problem in body["problems"])
|
||||
assert not any("hooky" in problem for problem in body["problems"])
|
||||
|
||||
|
||||
def test_the_history_reads_back(
|
||||
client: TestClient, superuser_token_headers: dict[str, str], db: Session
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user