phase: 34_radiance_llm_engine

Everything is verified and green. Final report:

**Phase 34 final verification pass — complete**

- Verified all 6 completed tasks' work against the live fleet and hermetic suite: `llm:radiance` job registered, `llm_engines()` registry drives 404 gate / history defaults / `/api/config` (additive, byte-identical gufo/vllm keys), radiance field map + `/stats` sidecar + 7-position spec curve, `/llm` strip/curve/rows.
- **Defect found & fixed (pre-existing, task 05):** the vLLM-only sentence "vLLM exposes no per-slot JSON…" rendered on the **radiance** panel (`slotSection`'s non-gufo branch). Fix: vLLM line gated to `engine === 'vllm'`; radiance's panel slot section renders nothing (its session home is the strip) — `page-llm.js` + the served-byte pin in `tests/test_api.py` (now asserts the radiance branch is empty and the sentence can't leak). Browser-verified; re-shot `data/logs/34-llm-radiance-rest.png` (the 4.5-min wait found no in-flight request, so the busy shot remains the earlier pass's — its strip rows still stand; only the panel text predates the fix).
- Tests: `uv run pytest` → **2031 passed, 19 skipped** (100%); `uv run pytest --cov` → **98.73%** (floor 94%; config 100%, llm 99%, collectors 98%, api 99%); `uv run ruff check src tests agent && uv run pyright` → clean; `node --check` OK; `uv pip list --outdated` → empty.
- `uv run pytest -m live --live` → **13 passed, 2 skipped** (vLLM unset — correct; live-write opt-in — correct); the read-only radiance test passed.
- Completion criteria: (1) engines `gufo`+`radiance`, `fleet.engines_live` 2, `config.llm.radiance.enabled` true — **pass (live curl)**; (2) unset → 404 no-dial + no job — **pass (spy-pinned, green)**; (3) fixtures present, both families (79 `radiance:` / 198 `vllm:` lines), drift pin — **pass**; (4) panel/curve/rows — **pass (re-shot rest screenshot)**; (5) live radiance test — **pass**; (6) suite/coverage/lint/`bash .agents/validate.sh` (exit 0) — **pass**; (7) docs — below; (8) gufo/vLLM behaviour unchanged — **pass (existing pins untouched)**.
- Documentation: **README.md** full review — env table, LLM-engines section, architecture diagram, capture-script and `/llm` section all name radiance correctly; no inconsistencies found, no changes needed. **AGENTS.md** — the three task-06 fixes (fleet line, route row, module bullets) are in place and all other statements match reality; no changes needed.
- Dev server healthy (`./scripts/dev-server.sh status`: all sources ok, `llm:radiance` answering); all changes left in the working tree for the harness.
- Next pending phase: none — 34 was the last phase in `todo/`.
This commit is contained in:
2026-11-01 18:53:46 -05:00
parent 86c8bf4992
commit 219d7a7c3b
77 changed files with 3517 additions and 149 deletions
+303 -12
View File
@@ -45,7 +45,9 @@ from dashboards.sources.disks import SMART_SERIES, DisksCollector, parse_disks_s
from dashboards.sources.host import HostCollector, parse_host_snapshot
from dashboards.sources.llm import (
HISTORY_METRICS,
engine_result,
parse_gufo_metrics,
parse_radiance_metrics,
parse_vllm_metrics,
)
from dashboards.store import RES_RAW, Event, Sample, SampleStore
@@ -937,6 +939,152 @@ def test_config_reports_the_window_the_llm_rates_are_actually_measured_over(
assert llm["rate_window_seconds"] == llm["interval_seconds"] == 2.0
# ---- the llm engine registry (phase 34 task 02) --------------------------- #
def test_config_serves_radiance_additively_beside_byte_identical_gufo_and_vllm(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
"""The additive pin: `radiance` joins the llm block as a third key, and nothing about
`gufo`/`vllm` moves — same keys, same shape, same order — while an unset radiance is
present as `enabled: false` (a key that appeared only when configured would be the
two-engine world leaking back into the API). The redaction is the one rule:
`RADIANCE_API_KEY` is the documented way to authenticate, and a token written into
the URL instead is stripped before it is served (invariant 6), like the other two.
"""
with build_client(tmp_path, monkeypatch) as plain:
before = plain.get("/api/config").json()["llm"]
with build_client(tmp_path, monkeypatch,
radiance_url="http://SEKRIT-RADIANCE-TOKEN@driveripper:8000",
radiance_api_key="radiance-key") as with_radiance:
after = with_radiance.get("/api/config").json()["llm"]
assert before["gufo"] == after["gufo"]
assert before["vllm"] == after["vllm"]
assert before["radiance"] == {"enabled": False, "base_url": "", "auth": False}
assert after["radiance"] == {"enabled": True, "base_url": "http://driveripper:8000",
"auth": True}
assert "SEKRIT-RADIANCE-TOKEN" not in json.dumps(after), "the URL token must not be served"
assert list(after) == ["gufo", "vllm", "radiance", "interval_seconds", "poll_ms",
"rate_window_seconds"], "the registry's stable order is the byte order"
def test_the_llm_404_gate_answers_from_the_registry_in_all_configurations(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
"""One engine configured — whichever of the three — is a configured source, and the
404 detail names all three variable names so the not-configured arm says the fix
for the whole world, not just the two it used to know."""
single: list[dict[str, Any]] = [{"gufo_url": "http://deskwork:8731"},
{"vllm_url": "http://vllm-box:8000"},
{"radiance_url": "http://driveripper:8000"}]
for overrides in single:
with build_client(tmp_path, monkeypatch, **overrides) as test_client:
response = test_client.get("/api/llm/snapshot")
assert response.status_code == 200, f"only {next(iter(overrides))} configured must not 404"
with build_client(tmp_path, monkeypatch) as test_client:
response = test_client.get("/api/llm/snapshot")
assert response.status_code == 404
body = response.json()
assert body["configured"] is False
for name in ("GUFO_BASE_URL", "VLLM_BASE_URL", "RADIANCE_BASE_URL"):
assert name in body["detail"], f"the not-configured arm must name {name}"
def test_llm_history_defaults_list_the_configured_engines_from_the_registry(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
"""The defaults are the registry's configured `key`s in registry order — `key` is the
history DB's host key samples are written under, not the display name — and an
unconfigured engine is not among them, so it is never requested and never dialled.
"""
with build_client(tmp_path, monkeypatch,
gufo_url="http://deskwork:8731",
radiance_url="http://driveripper:8000") as test_client:
body = test_client.get("/api/llm/history").json()
assert body["engines"] == ["gufo", "radiance"], "the vLLM entry is unconfigured and absent"
with build_client(tmp_path, monkeypatch) as test_client:
body = test_client.get("/api/llm/history").json()
assert body["engines"] == []
def test_summary_llm_enabled_follows_the_registry(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
with build_client(tmp_path, monkeypatch,
radiance_url="http://driveripper:8000") as test_client:
assert test_client.get("/api/summary").json()["llm"]["enabled"] is True
def test_an_unconfigured_radiance_never_becomes_a_job_that_could_look_broken(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
"""Invariant 3's shape, the `disks` precedent: no configured URL, no `llm:radiance`
job at all — so nothing dials a hostname the operator never installed, and no health
record exists to turn red. The job appears exactly when the URL does.
"""
with build_client(tmp_path, monkeypatch) as test_client:
keys = {row["key"] for row in test_client.get("/api/health").json()["sources"]}
assert not any(key.startswith("llm:") for key in keys)
with build_client(tmp_path, monkeypatch,
radiance_url="http://driveripper:8000") as test_client:
keys = {row["key"] for row in test_client.get("/api/health").json()["sources"]}
assert "llm:radiance" in keys
def _radiance_stats_doc() -> dict[str, Any]:
"""The verbatim /stats capture, its `#` header comment lines stripped."""
path = Path(__file__).resolve().parents[1] / "tests" / "fixtures" / "stats_radiance.json"
if not path.exists():
pytest.skip(f"missing fixture {path.name} — run scripts/capture-fixtures.sh --with-llm")
body = "\n".join(line for line in path.read_text().splitlines() if not line.startswith("#"))
return json.loads(body)
def test_radiance_payload_reaches_the_page_rows_and_rest(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, metrics_text) -> None:
"""The render path's input as the browser would receive it: the fixture /stats, through
the real `engine_result`, into the `llm:radiance` job — and `/api/llm/snapshot` hands
it to the page. At rest (the capture's own empty `requests[]`): the counts-otherwise
sentence, the whitelisted stats block, and `queue_cap` from the sidecar. A request in
flight: the rows verbatim under `sessions.list`. A dead sidecar: the metrics gauges
with their provenance said, and the cap `null`, never `0` (rule 2)."""
stats = _radiance_stats_doc()
rows = [{"id": 42, "model": "juggernaut", "state": "running",
"prompt_tokens": 1_200, "completed_tokens": 250}]
with build_client(tmp_path, monkeypatch, radiance_url=DEAD_URL) as test_client:
hub = test_client.app.state.ctx.hub # type: ignore[attr-defined]
job = hub.jobs["llm:radiance"]
job.state.payload = engine_result("radiance", "http://r:8000",
metrics_text("radiance"), RateEstimator(),
stats=stats, now=1.0).payload
rest = next(p for p in test_client.get("/api/llm/snapshot").json()["engines"]
if p["engine"] == "radiance")
assert rest["sessions"]["list"] == stats["requests"]
if not stats["requests"]:
assert "counts, not sessions" in rest["sessions"]["detail"]
assert rest["stats"]["version"] == "1.15.1"
assert isinstance(rest["stats"]["uptime_s"], int) and rest["stats"]["uptime_s"] >= 0, \
"uptime is the engine's own seconds — volatile between captures"
assert rest["stats"]["cards"][0]["vram_used"] == stats["cards"][0]["vram_used"]
assert rest["metrics"]["queue_cap"]["value"] == stats["queue_cap"]
assert len(rest["metrics"]["spec_positions"]) == 7
busy = {**stats, "requests": rows, "running": 1}
job.state.payload = engine_result("radiance", "http://r:8000",
metrics_text("radiance"), RateEstimator(),
stats=busy, now=1.0).payload
again = next(p for p in test_client.get("/api/llm/snapshot").json()["engines"]
if p["engine"] == "radiance")
assert again["sessions"]["list"] == rows, "the rows are not the verbatim passthrough"
assert again["sessions"]["source"] == "radiance /stats"
assert again["sessions"]["detail"] is None
job.state.payload = engine_result("radiance", "http://r:8000",
metrics_text("radiance"), RateEstimator(),
now=1.0).payload # stats=None: dead sidecar
dead = next(p for p in test_client.get("/api/llm/snapshot").json()["engines"]
if p["engine"] == "radiance")
assert dead["sessions"]["queue_cap"] is None, "null, not 0 — rule 2"
assert "gauges" in dead["sessions"]["detail"]
assert "stats" not in dead, "no stats block when the sidecar never answered"
assert dead["metrics"]["queue_cap"]["value"] is None
def wait_for_state(client: TestClient, path: str, *, timeout: float = 5.0) -> dict[str, Any]:
deadline = time.time() + timeout
while time.time() < deadline:
@@ -2995,8 +3143,11 @@ def test_every_llm_cell_carries_a_window_sparkline_with_percentile_feet(client)
assert name in js, f"{name} no longer feeds a foot line"
assert "p95 n/a" in js
assert 'data-foot' in js
# engine-scoped rows: gufo never grows a TTFT row, vLLM never a spec-accept row
assert "only: ['vllm']" in js and "only: ['gufo']" in js
# engine-scoped rows: gufo never grows a TTFT row, radiance joins the vLLM latency
# scope (the vLLM-shaped histograms this build carries, task 03) and spec acceptance
# (the gauge reuses gufo's key, the same 0-1 scale)
assert "only: ['vllm', 'radiance']" in js and "only: ['gufo', 'radiance']" in js
assert "only: ['gufo']" in js, "slots busy left its gufo scope"
scoped = js[js.index("function sparkCellsFor("):js.index("function enginePanel(")]
assert "cell.only" in scoped
assert "minSpan: cell.minSpan" in sparks, "cell minSpan never reaches the sparkline"
@@ -3061,7 +3212,8 @@ def test_llm_alarm_cells_exist_only_while_there_is_an_incident(client) -> None:
# publishes, and no row is printed in the strip *and* in the panel under it.
#: row key -> the cells `cellValue()` resolves it from (`sessions.*` is the gufo slot count,
#: which is not a metrics cell). The served `STRIP_ROWS` table must match these keys exactly.
#: `stats.*` radiance's /stats subset — neither is a metrics cell). The served `STRIP_ROWS`
#: table must match these keys exactly.
STRIP_ROW_PATHS: dict[str, tuple[str, ...]] = {
"prompt": ("prompt_tokens_per_second",),
"decode": ("decode_tokens_per_second",),
@@ -3072,6 +3224,10 @@ STRIP_ROW_PATHS: dict[str, tuple[str, ...]] = {
"cache_hit": ("prefix_cache_hit_ratio", "prompt_cache_hit_ratio"),
"spec_accept": ("spec_accept_rate",),
"queue_mean": ("request_queue_time_seconds__mean",),
"cap": ("queue_cap",),
"build": ("stats.version",),
"uptime": ("stats.uptime_s",),
"vram": ("stats.cards",),
"preemptions": ("num_preemptions_total",),
"device_lost": ("device_lost_total",),
}
@@ -3079,6 +3235,13 @@ STRIP_ROW_PATHS: dict[str, tuple[str, ...]] = {
#: rows that are incidents, not stats: absent where the engine does not count them.
ALARM_ROW_KEYS = ("preemptions", "device_lost")
#: (row key, engine) pairs the scope keeps even though **this capture** does not publish
#: the cell: the series is standard for the engine family, so another build fills it.
#: `queue_mean` on radiance — this build publishes no `request_queue_time_seconds` (the
#: vLLM-compat family is pinned in RADIANCE_OPTIONAL), so the row prints `n/a` by
#: absence, never back-filled. A row the engine could *never* fill is not shown at all.
DOCUMENTED_ABSENCE = {("queue_mean", "radiance")}
def _strip_rows(js: str) -> dict[str, str | None]:
"""The served `STRIP_ROWS` table: row key -> its `only` scope (`None` = every engine)."""
@@ -3150,10 +3313,13 @@ def test_llm_strip_card_is_one_card_per_engine_of_shared_vocabulary(client) -> N
def test_llm_strip_scopes_its_rows_to_the_engines_that_publish_them(client) -> None:
"""gufo gets slots and speculative decoding; vLLM gets running and queue time."""
"""gufo gets slots; vLLM and radiance get running and queue time; the radiance
strip's four own cells (cap / build / uptime / VRAM) are radiance's alone."""
rows = _strip_rows(client.get("/static/page-llm.js").text)
assert rows["slots_busy"] == "'gufo'" and rows["spec_accept"] == "'gufo'"
assert rows["running"] == "'vllm'" and rows["queue_mean"] == "'vllm'"
assert rows["slots_busy"] == "'gufo'" and rows["spec_accept"] == "'gufo', 'radiance'"
assert rows["running"] == "'vllm', 'radiance'" and rows["queue_mean"] == "'vllm', 'radiance'"
for key in ("cap", "build", "uptime", "vram"):
assert rows[key] == "'radiance'", f"the {key} row left its radiance scope"
assert rows["waiting"] is None and rows["cache_hit"] is None and rows["tokens_total"] is None
js = client.get("/static/page-llm.js").text
scoped = js[js.index("function stripRowsFor("):js.index("function stripCard(")]
@@ -3166,19 +3332,24 @@ def test_llm_strip_rows_name_cells_the_engines_publish(client, metrics_text) ->
`STRIP_ROW_PATHS` mirrors the JS table; every metric cell is checked against the
capture-parsed metrics of each engine that would render that row, so a rename in
`sources/llm.py` fails here instead of printing a permanent `n/a` in the browser, and a
row scoped to one engine cannot leak into the other's card.
row scoped to one engine cannot leak into the other's card. `DOCUMENTED_ABSENCE` is the
one exemption: a series standard for the engine family that this build's capture does
not publish (the row prints `n/a` by absence, never back-filled — the scope stays for
the builds that do).
"""
rows = _strip_rows(client.get("/static/page-llm.js").text)
assert set(rows) == set(STRIP_ROW_PATHS), \
f"the served strip rows drifted: {set(rows) ^ set(STRIP_ROW_PATHS)}"
parsed = {"gufo": parse_gufo_metrics(metrics_text("gufo")),
"vllm": parse_vllm_metrics(metrics_text("vllm"))}
"vllm": parse_vllm_metrics(metrics_text("vllm")),
"radiance": parse_radiance_metrics(metrics_text("radiance"))}
for key, only in rows.items():
paths = STRIP_ROW_PATHS[key]
if paths[0].startswith("sessions."):
if paths[0].startswith("sessions.") or paths[0].startswith("stats."):
continue # its own payload object; pinned on the JS below
shown = {engine: metrics for engine, metrics in parsed.items()
if not only or engine in only}
if (not only or engine in only)
and (key, engine) not in DOCUMENTED_ABSENCE}
present = [engine for engine in shown if any(path in shown[engine] for path in paths)]
if key in ALARM_ROW_KEYS:
# an alarm the engine does not count simply is not there: the chip renders only
@@ -3743,14 +3914,19 @@ def test_llm_vllm_panel_says_there_is_no_per_slot_json(client) -> None:
`sources/llm.py`'s `_sessions()` publishes counts for vLLM and says so in `detail`; the
panel turns that into the `llm_monitor` line, with the API's sentence as the tooltip. The
gate is the engine's name (`SLOT_ENGINES`), not `sessions.list.length`, so an engine that
has not answered yet still shows its label and the honest empty sentence.
has not answered yet still shows its label and the honest empty sentence. And the line
stays vLLM's: radiance's panel slot section is empty (its per-request rows live in the
strip), so a sentence naming vLLM on the radiance card is a line the engine never said.
"""
js = client.get("/static/page-llm.js").text
markup = _slot_markup(js)
branch = markup.split("if (SLOT_ENGINES.indexOf(engine) < 0) {")[1].split("}")[0]
branch = markup.split("if (engine === 'vllm') {")[1].split("}")[0]
assert 'class="slots-note" data-slots-note' in branch, "the vLLM line lost its element"
assert "NO_SLOT_JSON" in branch and "vLLM exposes no per-slot JSON" in js
assert '<div class="slots"' not in branch, "the vLLM panel grew a grid it cannot fill"
radiance_branch = markup.split("if (SLOT_ENGINES.indexOf(engine) < 0) {")[1].split("}")[0]
assert "return ''" in radiance_branch, "the radiance panel re-grew a slot section"
assert "NO_SLOT_JSON" not in radiance_branch, "the vLLM sentence leaked onto the radiance panel"
body = _slot_js(js)
assert body.startswith("function slotValue("), "the grid's code path moved"
assert "if (!grid) {" in body, "renderSlotGrid no longer leaves a panel with no grid alone"
@@ -3815,6 +3991,80 @@ def test_llm_charts_are_secondary_and_named(client) -> None:
assert "height: 110" in js and "height: 165" not in js
charts = js[js.index("function makeCharts("):js.index("function pointsFor(")]
assert charts.count("ariaLabel:") == 4, "an /llm chart lost its accessible name"
# the radiance strip's 7-bar spec curve (phase 34) joins the named list: `role="img"`
# and an `aria-label` computed from the payload's `spec_positions` — a label that
# cannot say which ratios it plots is not an accessible name, and an absent label
# fails here
curve = _code(client.get("/static/page-llm.js").text)
curve = curve[curve.index("function renderSpecCurve("):curve.index("function reqCellText(")]
assert 'role="img"' in curve, "the spec curve is an unlabelled plot"
assert 'aria-label="' in curve and "escapeHtml(label)" in curve, \
"the spec curve's label is not the computed one"
def test_the_radiance_spec_curve_is_neutral_and_built_from_the_payload(client) -> None:
"""Decision 4, pinned both ways: the 7-bar curve draws in the page's neutral ink,
reaches for no verdict token, and its label is computed from the payload — the
connector word turns on the first/last published ratio's order, and an absent
position stays absent rather than becoming a zero bar (rule 2)."""
js = _code(client.get("/static/page-llm.js").text)
curve = js[js.index("function renderSpecCurve("):js.index("function reqCellText(")]
assert "spec_positions" in curve, "the curve stopped reading the payload's positions"
assert "cssVar('--text-faint')" in curve, "the curve left the neutral ink"
assert "Math.min(1, row.ratio)" in curve, "a ratio above 1 would stretch a bar"
for token in ("--ok", "--warn", "--fail", "severity"):
assert token not in curve, f"the spec curve grew a verdict: {token}"
assert "falling to" in curve and "rising to" in curve and "holding at" in curve, \
"the connector word is not computed from the payload's order"
assert "Number.isFinite(row.ratio)" in curve, \
"a missing position must stay absent, not zeroed"
def test_radiance_strip_cells_print_na_never_zero_when_stats_never_answered(client) -> None:
"""A radiance payload without the /stats block: cap / build / uptime / vram print
`n/a`, never `0` — the null guards on the served path (a missing sidecar is an
absent number, rule 2), and the number formatter never sees a string value."""
js = _code(client.get("/static/page-llm.js").text)
value = js[js.index("function cellValue("):js.index("function p95Value(")]
assert "case 'cap':" in value and "get('queue_cap')" in value, \
"cap stopped reading the /stats passthrough the server degrades to null"
assert "stats && typeof stats.version === 'string'" in value, \
"build must be the engine's own string or null"
assert "Number.isFinite(stats.uptime_s)" in value and "duration(stats.uptime_s)" in value
assert "cards.find((c) => c && c.index === 0)" in value, "vram reads the wrong card"
assert "(used / GIB).toFixed(1)" in value and "2 ** 30" in js, \
"the one conversion is GiB = 2³⁰, labelled in the tip"
body = _strip_render_path(js)
assert "cellValue(engine, metrics, sessions, row.key, stats)" in body, \
"the radiance cells lost the payload's stats block"
assert "typeof value.value === 'string' ? value.value" in body, \
"a string value hits the number formatter"
def test_radiance_request_rows_render_as_is_and_the_rest_state_says_so(client) -> None:
"""The rows are the engine's own fields, as-is: the columns are the union of the
keys the rows publish (no invented key), a number prints only when it is a number,
anything else its string verbatim — and an empty list hides the table and puts the
API's own count-otherwise sentence in the note slot."""
js = _code(client.get("/static/page-llm.js").text)
card = js[js.index("function stripCard("):js.index("function renderStripCard(")]
assert 'data-spec-curve' in card and 'data-reqs' in card and 'data-reqs-note' in card, \
"the radiance card lost its curve / rows / note homes"
cell = js[js.index("function reqCellText("):js.index("function renderReqs(")]
assert "typeof value === 'number' && isFinite(value)" in cell, \
"a number prints only when it is a number"
assert "typeof value === 'string') return value" in cell, \
"anything else prints its string verbatim"
reqs = js[js.index("function renderReqs("):js.index("function makeCharts(")]
assert "sessions.list" in reqs and "Object.keys(row)" in reqs, \
"the columns are a hardcoded list again"
assert "indexOf(key) < 0" in reqs, "first-seen order must keep the rows as published"
assert "note.hidden = !sessions.detail" in reqs, \
"the rest state lost the API's own sentence"
assert "note.hidden = true" in reqs, "rows visible: the sentence must leave"
assert "table.title = sessions.source" in reqs, "the table's source left its tooltip"
# the gufo gate is untouched: the slot grid is gufo's, the radiance rows live in the strip
assert "SLOT_ENGINES = ['gufo']" in js
def test_llm_engine_panels_are_not_stretched_to_their_tallest_sibling(client) -> None:
@@ -4006,6 +4256,9 @@ def test_the_copy_the_operator_acts_on_survives_the_audit(client) -> None:
assert "smartmontools" in pages["/disks"] + scripts["page-disks.js"]
assert "disk group" in scripts["page-disks.js"]
assert "No engines configured" in pages["/llm"]
# the not-configured arm is actionable only if it names the variable for every engine
for name in ("GUFO_BASE_URL", "VLLM_BASE_URL", "RADIANCE_BASE_URL"):
assert name in pages["/llm"], f"/llm's empty state stopped naming {name}"
assert "No UPS reporting" in pages["/ups"]
assert "instcmds" in pages["/ups"], "the UPS setup note stopped naming the grant that matters"
assert "3493" in pages["/ups"], "the page stopped warning that upsd's port is not always 3493"
@@ -10087,6 +10340,44 @@ def test_a_card_disclosure_scrolls_what_it_reveals_at_every_width(client) -> Non
"at 1280 px, where it would then do nothing")
def test_the_radiance_reqs_table_scrolls_instead_of_stretching_its_card(client) -> None:
"""The radiance strip's request table must not grow the card to its min-content.
Measured on the live fleet (1280 px, two strip cards across, each 613 px): with a
request in flight the `.reqs` table — the union of the row's ten published keys —
sat at ~950 px of min-content, and because the strip body is a one-column grid
(`.strip > .card > .body`) with an implicit auto column, a grid item's automatic
minimum size is its content's min-content width, so the *column* grew to ~946 px.
Every row of the card laid out at 946 px inside a 613 px card: the value column of
each `dl.kv` row resolved to ~857 px, the right-aligned value span painted at
x≈1582 against a card edge at 1260, and `.card { overflow: hidden }` ate it — the
strip printed its labels with no values while the request row and the spec curve
(their own boxes) painted fine. `min-width: 0` is the first half: without it the
table's min-content still sets the column and nothing below can overflow. `overflow-x:
auto` is the second: the table reaches its last column by scrolling inside the card,
only where it is wider than the card (a table that fits paints no scrollbar —
horizontal only, no height cap, no vertical scrollport).
"""
reqs = _declarations(_css_section(_css(client), "engine slot grid"), ".reqs")
assert reqs.get("min-width") == "0", (
"the `.reqs` item may not be narrower than its table: without this the ten-column "
"request table's min-content grows the strip body's grid column and every value "
"cell of the card paints past the card, clipped by `.card { overflow: hidden }`")
assert reqs.get("overflow-x") == "auto", (
"the request table lost its sideways scroll inside the card — the columns beyond "
"the card edge are unreachable again")
for forbidden in ("max-height", "overflow-y", "overflow"):
assert forbidden not in reqs, (
f"the `.reqs` rule declares `{forbidden}`: this is a sideways scroll only — a "
"height cap or vertical scrollport here would hide rows the operator has not "
"chosen to hide")
# the strip body is the grid the item sits in: a one-column body is what the
# min-content growth acts on, so the fix is inert if the body stops being a grid
body = _declarations(_css_section(_css(client), "engine stats strip"), ".strip > .card > .body")
assert body.get("display") == "grid", (
"the strip body is not a one-column grid anymore — re-measure before touching `.reqs`")
def test_every_table_on_every_page_carries_the_class_the_rule_targets(client) -> None:
"""The mobile rule is class-level, so a `<table>` without `data` would silently not scroll.