From 9993c47c70a275b6370c2c0cfa5f8c9101aa8929 Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Thu, 1 Oct 2026 21:23:58 +0100 Subject: [PATCH] fix: show cloud-observed workspace tests on board --- heart/dashboard.py | 9 ++++++--- tests/test_dashboard.py | 31 ++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/heart/dashboard.py b/heart/dashboard.py index 3d44de8..4b27423 100644 --- a/heart/dashboard.py +++ b/heart/dashboard.py @@ -72,7 +72,9 @@ # these are passed as ``unobserved`` so the board marks them honestly rather # than implying they are green. (Spec §2 "Cloud-safe caveat".) # -# Three families LEFT this tuple in #206. `import_time` and `unit_test_timing` +# Three families LEFT this tuple in #206, and cloud test-run evidence +# leaves it once the scheduled job ingests the workspace validation artifact. +# `import_time` and `unit_test_timing` # are now cloud-OBSERVED by ingestion: the libraries' own CI emits the # `unit-timings-` artifact and `heart/checks/unit_timings.py` writes exactly # these two summary files from it, so greying the rows on the cloud job would be @@ -86,7 +88,6 @@ "worktree_drift", "script_timing", "profiling_drift", - "test_run", "version_skew", ) @@ -130,7 +131,6 @@ def _repo_owners() -> dict: "worktree_drift": "task worktrees vs the active.md ledger (orphans, missing, dirty)", "script_timing": "workspace script runtimes vs their baselines", "profiling_drift": "pinned profiling results vs their baselines", - "test_run": "the latest full workspace test-run verdict", "version_skew": "workspace version floors vs the newest releases", } @@ -957,6 +957,9 @@ def build_board( if stale_n: details.append(f"{stale_n} stale parked script(s)") sections.append(Section("test_run", "Test run", st, summary, details)) + elif unobserved: + sections.append(Section("test_run", "Test run", UNOBS, + "test run status unknown (no report.json)", [])) # CI wall-clock, per-script smoke timings + the NO_RUN census (⏱) --------- # All three are CLOUD-observed (the Actions API + the contents API), so they are diff --git a/tests/test_dashboard.py b/tests/test_dashboard.py index b742f59..4330ba2 100644 --- a/tests/test_dashboard.py +++ b/tests/test_dashboard.py @@ -281,9 +281,11 @@ def test_cloud_marks_local_only_checks_unobserved(): board = dashboard.build_board(snap, make_verdict(), unobserved=dashboard.LOCAL_ONLY_FAMILIES, now=FRESH_NOW) by_key = {s.key: s for s in board.sections} - for fam in ("worktree_drift", "script_timing", "test_run", "version_skew"): + for fam in ("worktree_drift", "script_timing", "version_skew"): assert by_key[fam].state == dashboard.UNOBS assert "not observed here" in by_key[fam].summary + assert by_key["test_run"].state == dashboard.OK + assert "100p" in by_key["test_run"].summary # repo_state is folded into the library rows; those rows must not claim a # green working tree the cloud never saw. libs = by_key["libraries"] @@ -1805,3 +1807,30 @@ def test_rendered_copy_payloads_are_assistant_agnostic(verdict): page = dashboard.render(make_snapshot(), make_verdict(verdict), fmt="html", now=FRESH_NOW) assert_portable_copy_payloads(page) + + +def test_cloud_test_run_without_artifact_is_unobserved(): + snap = make_snapshot(test_run={}) + board = dashboard.build_board(snap, make_verdict("stale", 90), + unobserved=dashboard.LOCAL_ONLY_FAMILIES, now=FRESH_NOW) + section = next(s for s in board.sections if s.key == "test_run") + assert section.state == dashboard.UNOBS + assert "no report.json" in section.summary + + +def test_cloud_test_run_renders_failed_counts_and_no_invented_zeros(): + snap = make_snapshot(test_run={"ready": False, "counts_measured": True, + "passed": 1400, "failed": 1, "skipped": 120, + "run_label": "cloud#42"}) + board = dashboard.build_board(snap, make_verdict("yellow", 80), + unobserved=dashboard.LOCAL_ONLY_FAMILIES, now=FRESH_NOW) + section = next(s for s in board.sections if s.key == "test_run") + assert section.state == dashboard.FAIL + assert "1400p / 1f / 120s" in section.summary + + snap["test_run"] = {"ready": False, "run_label": "cloud#43", "source": "cloud"} + board = dashboard.build_board(snap, make_verdict("yellow", 80), + unobserved=dashboard.LOCAL_ONLY_FAMILIES, now=FRESH_NOW) + section = next(s for s in board.sections if s.key == "test_run") + assert "counts not ingested" in section.summary + assert "0p" not in section.summary