diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index dfec3ee..058b76e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -104,6 +104,15 @@ jobs:
- name: Tier 4 -- conformance ledger
run: .venv/bin/python -m pytest ledger/checks -v
+ # Tier 6 -- contracts/operator-surface.v1.md's Tier-A conformance kit.
+ # Freeze 1 requires it to exist AND to run on every pull request, so it
+ # is a named step of its own: a kit that runs in no gate is the exact
+ # failure ledger row CCV1-022 already recorded once. Runs AFTER the
+ # tiers above because its rendered checks need the same real `bd` and
+ # dolt those tiers install.
+ - name: Tier 6 -- operator-surface conformance (Tier A)
+ run: .venv/bin/python -m pytest tests/conformance/operator_surface -v
+
# Tier 5 -- the amplifier tool module's own suite
# (modules/tool-work-tracker/tests). The only place the post-reclaim
# custody behaviour of the AGENT SEAM (work_claim / work_declare /
diff --git a/Makefile b/Makefile
index 019ac82..18546f2 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-.PHONY: venv test test-unit test-integration test-cli test-ledger ledger-mutate test-module check lint types doctor clean
+.PHONY: venv test test-unit test-integration test-cli test-ledger ledger-mutate test-conformance-a test-module check lint types doctor clean
PYTHON ?= python3.12
VENV := .venv
@@ -52,6 +52,15 @@ test-ledger:
ledger-mutate:
$(PY) -m ledger.checks.mutation_harness
+## Tier 6 -- operator-surface conformance, Tier A: the machine checks
+## contracts/operator-surface.v1.md names for its own Tier A, each as a
+## discriminating good/bad pair (Freeze 1 requires this kit to exist AND to
+## run on every pull request; Freeze 4 requires every bad half to have been
+## demonstrated). Its static checks need nothing; its RENDERED checks stand up
+## the isolated dolt server and skip loudly without a real `bd`.
+test-conformance-a:
+ $(PYTEST) tests/conformance/operator_surface -v
+
## Tier 5 -- tool module: modules/tool-work-tracker's own suite, the only
## place the post-reclaim custody behaviour of the AGENT SEAM (work_claim /
## work_declare / work_resolve / work_release) is asserted mechanically.
@@ -65,7 +74,7 @@ ledger-mutate:
test-module:
$(PYTEST) modules/tool-work-tracker/tests -v
-## All five tiers. Two pytest invocations (see `test-module` above), and
+## Every tier. Two pytest invocations (see `test-module` above), and
## deliberately NOT fail-fast between them: the whole point of wiring the
## module suite in (ledger row CCV1-022) is that it stops being silently
## skippable, and a pre-existing failure in the root suite must not go back
@@ -77,6 +86,11 @@ test:
$(PYTEST) modules/tool-work-tracker/tests -v || rc=$$?; \
exit $$rc
+## `test` above already COLLECTS tests/conformance (it is under `tests`), so
+## this is the named, separately-runnable entry point rather than a second
+## invocation -- running the kit twice in one `make test` would double its
+## fixture cost and prove nothing new.
+
## Lint + type-check.
check: lint types
diff --git a/ledger/checks/mutation_harness.py b/ledger/checks/mutation_harness.py
index 505c75f..f9f9eca 100644
--- a/ledger/checks/mutation_harness.py
+++ b/ledger/checks/mutation_harness.py
@@ -58,7 +58,6 @@
from ._support import (
ADAPTER,
AWARENESS,
- CHARTSVG,
CI_WORKFLOW,
CLAIM_SKILL,
CONTRACT_PATH,
@@ -364,13 +363,19 @@ def _m023_test_location_regresses(w: World) -> None:
# shape and must go red the moment the shape is right. The seven green rows get
# the known-wrong shape they forbid instead (direction REGRESSION).
#
-# Eleven rows pin the absence of a conformance-kit file, and their
+# Six rows still pin the absence of the TIER-B kit file, and their
# counterfactual is `world.touch(...)` -- the file simply existing. That is a
# WEAKER mutation than the source-shape ones, deliberately and visibly: the
# thing being proven is only that the pin notices the path appearing, which is
-# exactly what those rows claim and no more. Four of them carry a SECOND
+# exactly what those rows claim and no more. Three of them carry a SECOND
# mutation against their substantive half, so the weak half is never the only
# evidence.
+#
+# The TIER-A kit now EXISTS (OSV1-027), so "the file appears" is spent as a
+# counterfactual for the rows that used it. Each has been retargeted at what
+# actually has to move for it to go green: for the three Conformance-fixture
+# rows, the Core row their deferred good half waits on closing; for Freeze 1,
+# CI dropping the step that runs the kit.
# =============================================================================
TIER_A_KIT = op_probes.TIER_A_KIT
@@ -381,14 +386,26 @@ def _mo000_operator_contract_moved(w: World) -> None:
w.append(OPERATOR_CONTRACT_PATH, "\n\n")
-def _mo001_hero_gains_the_missing_count(w: World) -> None:
- """FIXED: the needs-attention count Core 1 names joins the strip."""
+def _mo001_the_needs_attention_count_is_dropped_again(w: World) -> None:
+ """REGRESSION: the count that was absent ANYWHERE at seed goes missing from
+ the L0 hero again -- the exact half of the defect this row closed.
+
+ The CARD stays, so the strip still renders four of them: only the reading
+ it carries reverts to one Core 1 does not name. A probe that counted cards
+ instead of naming them would sail straight past this.
+ """
+ w.replace(WEBAPP, 'label="Needs attention",', 'label="Agents active now",')
+
+
+def _mo001b_the_hero_figure_stops_stating_its_window(w: World) -> None:
+ """REGRESSION: the throughput figure survives but its window does not --
+ the OTHER half of the clause ("throughput over a STATED window"), and the
+ partial fix that would otherwise pass for conformance.
+ """
w.replace(
- WEBAPP,
- 'WD.KpiCard(key="ready", label="Ready", value=ready_total, href="#fleet"),',
- 'WD.KpiCard(key="attention", label="Needs attention", value=0, href="#x"),\n'
- " "
- 'WD.KpiCard(key="ready", label="Ready", value=ready_total, href="#fleet"),',
+ WIDGETS,
+ 'f\'{_esc(data["velocity_window"])}\'',
+ '""',
)
@@ -478,12 +495,23 @@ def _mo008_swap_restores_the_pause_flag(w: World) -> None:
)
-def _mo009_the_below_floor_token_stops_painting_copy(w: World) -> None:
- """FIXED: the empty-state caption moves off the below-floor token."""
+def _mo009a_the_media_light_block_regresses(w: World) -> None:
+ """REGRESSION: `--ink-quiet` falls back below the floor in the MEDIA block.
+
+ One mutation per light block on purpose. webtheme.py keeps the two in sync
+ by comment alone, so a probe that noticed only the block it happened to read
+ first would credit a half-reverted colour as conformance -- which is exactly
+ the shape the seed pin recorded (three grounds x TWO blocks = six pairs).
+ """
+ w.replace(WEBTHEME, " --ink-quiet:#596473;", " --ink-quiet:#7c8ba0;")
+
+
+def _mo009b_the_attr_light_block_regresses(w: World) -> None:
+ """REGRESSION: the same fallback in the manual-toggle light block."""
w.replace(
- CHARTSVG,
- 'style="fill:var(--ink-quiet)">',
- 'style="fill:var(--ink-tertiary)">',
+ WEBTHEME,
+ " --ink-quiet:#596473; /* likewise",
+ " --ink-quiet:#7c8ba0; /* likewise",
)
@@ -501,9 +529,20 @@ def _mo011_a_second_motion_block_appears(w: World) -> None:
)
-def _mo012_the_empty_sentence_becomes_a_zero(w: World) -> None:
- """REGRESSION: the calm queue is celebrated as a numeral instead of said."""
- w.replace(WEBAPP, "Nothing is waiting to be claimed in this queue right now.", "0")
+def _mo012_the_empty_slot_gains_its_sentence(w: World) -> None:
+ """FIXED: `render_attention_queue` grows the empty branch Core 8 asks for,
+ so the L0 region that keeps its slot finally says so."""
+ w.replace(
+ WIDGETS,
+ " rows_html: list[str] = []\n"
+ ' for r in data["rows"]:\n'
+ ' priority_label = _esc(r["priority"].upper())',
+ ' if not data["rows"]:\n'
+ " return '
Nothing needs you right now.
'\n"
+ " rows_html: list[str] = []\n"
+ ' for r in data["rows"]:\n'
+ ' priority_label = _esc(r["priority"].upper())',
+ )
def _mo013_a_template_engine_is_declared(w: World) -> None:
@@ -538,10 +577,6 @@ def _mo017_a_second_push_call_site_appears(w: World) -> None:
w.append(WEBAPP, "\ndef _ledger_mutation():\n WP.fire_reclaim_alarm(1, 2, 3)\n")
-def _mo_tier_a_kit_appears(w: World) -> None:
- w.touch(TIER_A_KIT)
-
-
def _mo_tier_b_kit_appears(w: World) -> None:
w.touch(TIER_B_KIT)
@@ -569,9 +604,16 @@ def _mo023_a_swept_breakpoint_disappears(w: World) -> None:
w.replace(WEBTHEME, "@media (max-width:1280px){", "@media (max-width:1281px){")
-def _mo027_the_makefile_wires_the_kit(w: World) -> None:
- """The wiring half of Freeze 1: existing is not the same as running."""
- w.append(MAKEFILE, "\ntest-conformance:\n\t$(PYTEST) tests/conformance -v\n")
+def _mo027_ci_stops_running_the_kit(w: World) -> None:
+ """REGRESSION on the wiring half of Freeze 1: the kit still exists, but CI
+ no longer runs it -- which is exactly the "green claims nobody executed"
+ failure CCV1-022 already recorded once in this repo."""
+ w.replace(
+ CI_WORKFLOW,
+ " - name: Tier 6 -- operator-surface conformance (Tier A)\n"
+ " run: .venv/bin/python -m pytest tests/conformance/operator_surface -v\n",
+ "",
+ )
def _mo029_an_artifact_directory_appears(w: World) -> None:
@@ -586,8 +628,41 @@ def _mo031_a_red_core_row_goes_green(w: World) -> None:
"""
w.replace(
ROWS_PATH,
- " disposition: VIOLATION\n work: work_item_pipeline-ujy",
- " disposition: CONFORMS\n work: work_item_pipeline-ujy",
+ " disposition: VIOLATION\n work: work_item_pipeline-8vv",
+ " disposition: CONFORMS\n work: work_item_pipeline-8vv",
+ )
+
+
+def _mo024_the_hero_good_half_is_deferred_again(w: World) -> None:
+ """REGRESSION: someone re-adds the xfail(strict) deferral to Conformance 5's
+ good half while the row still reads CONFORMS -- a green Conformance row whose
+ fixture no longer runs is exactly the claim-without-check Freeze 4 forbids.
+ """
+ w.replace(
+ _support.REPO_ROOT / TIER_A_KIT,
+ "def test_hero_velocity_and_counts(calm_dataset) -> None:",
+ '@pytest.mark.xfail(strict=True, reason="OSV1-001 regressed")\n'
+ "def test_hero_velocity_and_counts(calm_dataset) -> None:",
+ )
+
+
+def _mo025_the_literal_style_row_goes_green(w: World) -> None:
+ """FIXED: OSV1-005 closes, so Conformance 6's deferred good half should now
+ pass -- and this row must be re-derived from the PASSING pair."""
+ w.replace(
+ ROWS_PATH,
+ " disposition: VIOLATION\n work: work_item_pipeline-np3",
+ " disposition: CONFORMS\n work: work_item_pipeline-np3",
+ )
+
+
+def _mo026_the_empty_slot_row_goes_green(w: World) -> None:
+ """FIXED: OSV1-012 closes, so Conformance 7's deferred good halves should
+ now pass."""
+ w.replace(
+ ROWS_PATH,
+ " disposition: VIOLATION\n work: work_item_pipeline-c1a",
+ " disposition: CONFORMS\n work: work_item_pipeline-c1a",
)
@@ -707,8 +782,13 @@ def _mo034_the_changelog_records_a_look(w: World) -> None:
),
Mutation(
"OSV1-001",
- "the missing needs-attention count joins the L0 strip",
- _mo001_hero_gains_the_missing_count,
+ "the needs-attention count is dropped from the L0 hero again",
+ _mo001_the_needs_attention_count_is_dropped_again,
+ ),
+ Mutation(
+ "OSV1-001",
+ "the hero keeps its throughput figure but stops stating the window it covers",
+ _mo001b_the_hero_figure_stops_stating_its_window,
),
Mutation(
"OSV1-002",
@@ -754,8 +834,13 @@ def _mo034_the_changelog_records_a_look(w: World) -> None:
),
Mutation(
"OSV1-009",
- "the below-floor token stops painting the empty-state caption",
- _mo009_the_below_floor_token_stops_painting_copy,
+ "--ink-quiet falls back below the text floor in the prefers-color-scheme light block",
+ _mo009a_the_media_light_block_regresses,
+ ),
+ Mutation(
+ "OSV1-009",
+ '--ink-quiet falls back below the text floor in the :root[data-theme="light"] block',
+ _mo009b_the_attr_light_block_regresses,
),
Mutation("OSV1-010", "a browser driver appears in the repo", _mo010_a_browser_driver_appears),
Mutation(
@@ -765,8 +850,8 @@ def _mo034_the_changelog_records_a_look(w: World) -> None:
),
Mutation(
"OSV1-012",
- "the calm queue's empty sentence becomes a bare zero",
- _mo012_the_empty_sentence_becomes_a_zero,
+ "the empty attention queue grows the sentence Core 8 asks for",
+ _mo012_the_empty_slot_gains_its_sentence,
),
Mutation(
"OSV1-013", "the manifest declares a template engine", _mo013_a_template_engine_is_declared
@@ -790,7 +875,7 @@ def _mo034_the_changelog_records_a_look(w: World) -> None:
_mo017_a_second_push_call_site_appears,
),
Mutation("OSV1-020", "the Tier-B kit file appears", _mo_tier_b_kit_appears),
- Mutation("OSV1-021", "the Tier-A kit file appears", _mo_tier_a_kit_appears),
+ Mutation("OSV1-021", "the Tier-B kit file appears", _mo_tier_b_kit_appears),
Mutation("OSV1-022", "the Tier-B kit file appears", _mo_tier_b_kit_appears),
Mutation(
"OSV1-022",
@@ -803,14 +888,25 @@ def _mo034_the_changelog_records_a_look(w: World) -> None:
"a swept breakpoint disappears from the stylesheet",
_mo023_a_swept_breakpoint_disappears,
),
- Mutation("OSV1-024", "the Tier-A kit file appears", _mo_tier_a_kit_appears),
- Mutation("OSV1-025", "the Tier-A kit file appears", _mo_tier_a_kit_appears),
- Mutation("OSV1-026", "the Tier-A kit file appears", _mo_tier_a_kit_appears),
- Mutation("OSV1-027", "the Tier-A kit file appears", _mo_tier_a_kit_appears),
+ Mutation(
+ "OSV1-024",
+ "Conformance 5's good half is deferred again behind an xfail naming OSV1-001",
+ _mo024_the_hero_good_half_is_deferred_again,
+ ),
+ Mutation(
+ "OSV1-025",
+ "OSV1-005 closes, so Conformance 6's deferred good half should now pass",
+ _mo025_the_literal_style_row_goes_green,
+ ),
+ Mutation(
+ "OSV1-026",
+ "OSV1-012 closes, so Conformance 7's deferred good halves should now pass",
+ _mo026_the_empty_slot_row_goes_green,
+ ),
Mutation(
"OSV1-027",
- "the Makefile wires a conformance target (the 'runs in a gate' half)",
- _mo027_the_makefile_wires_the_kit,
+ "CI stops running the Tier-A kit (the 'runs in a gate' half)",
+ _mo027_ci_stops_running_the_kit,
),
Mutation("OSV1-028", "the Tier-B kit file appears", _mo_tier_b_kit_appears),
Mutation("OSV1-029", "the Tier-B kit file appears", _mo_tier_b_kit_appears),
@@ -819,7 +915,7 @@ def _mo034_the_changelog_records_a_look(w: World) -> None:
"a Tier-B artifact directory appears",
_mo029_an_artifact_directory_appears,
),
- Mutation("OSV1-030", "the Tier-A kit file appears", _mo_tier_a_kit_appears),
+ Mutation("OSV1-030", "the Tier-B kit file appears", _mo_tier_b_kit_appears),
Mutation(
"OSV1-031",
"one of the ten red Core-carrying rows flips to CONFORMS",
diff --git a/ledger/checks/test_operator_rows.py b/ledger/checks/test_operator_rows.py
index b6fe543..c8603fa 100644
--- a/ledger/checks/test_operator_rows.py
+++ b/ledger/checks/test_operator_rows.py
@@ -41,12 +41,15 @@
from __future__ import annotations
+import ast
import re
from ._support import (
CHARTSVG,
+ GROUND_TOKENS,
LITERAL,
OPERATOR_CONTRACT_PATH,
+ PINNING_DISPOSITIONS,
PYPROJECT,
REPO_ROOT,
SUPERVISOR,
@@ -92,6 +95,66 @@ def _exists(rel: str) -> bool:
return (REPO_ROOT / rel).exists()
+# ---------------------------------------------------------------------------
+# Reading the Tier-A conformance kit.
+#
+# Several rows below are about the KIT rather than about `src/` -- whether the
+# check the contract names is implemented, whether it ships a bad half, and
+# whether its good half is still DEFERRED against an open row. All three go
+# through `read()` so the mutation harness's reader injection reaches them.
+# ---------------------------------------------------------------------------
+
+
+def _kit_source() -> str:
+ return read(REPO_ROOT / TIER_A_KIT)
+
+
+def _kit_defs(kit: str) -> frozenset[str]:
+ return frozenset(
+ n.name
+ for n in ast.walk(ast.parse(kit))
+ if isinstance(n, ast.FunctionDef | ast.AsyncFunctionDef)
+ )
+
+
+def _kit_bad_halves(kit: str, good: str) -> list[str]:
+ """The bad-half tests paired with a check's good half, by name."""
+ return sorted(n for n in _kit_defs(kit) if n.startswith(f"{good}_bad_half_"))
+
+
+def _kit_deferred_rows(kit: str, test_name: str) -> frozenset[str]:
+ """Row ids named in `test_name`'s `xfail` reason -- empty if not deferred.
+
+ A kit test marked `xfail(strict=True)` is a check that RUNS and currently
+ FAILS, with the ledger row that owns the failure named in its reason. That
+ marker is what a red Conformance row pins: when the product fix lands the
+ test XPASSes, the run fails, and the marker and the row move together.
+ """
+ for node in ast.walk(ast.parse(kit)):
+ if not isinstance(node, ast.FunctionDef) or node.name != test_name:
+ continue
+ for dec in node.decorator_list:
+ if not isinstance(dec, ast.Call):
+ continue
+ if not ast.unparse(dec.func).endswith("xfail"):
+ continue
+ for kw in dec.keywords:
+ if kw.arg == "reason" and isinstance(kw.value, ast.Constant):
+ return frozenset(re.findall(r"OSV1-\d{3}", str(kw.value.value)))
+ return frozenset()
+ return frozenset()
+
+
+def _widgets_function(name: str) -> str:
+ """One function's source out of `widgets.py`, via the patched reader."""
+ src = read(WIDGETS)
+ lines = src.splitlines()
+ for node in ast.walk(ast.parse(src)):
+ if isinstance(node, ast.FunctionDef) and node.name == name:
+ return "\n".join(lines[node.lineno - 1 : (node.end_lineno or node.lineno)])
+ raise AssertionError(f"widgets.py no longer defines {name!r}")
+
+
def _repo_mentions(needle: str) -> bool:
"""Does any tracked source/config file name this string?
@@ -145,52 +208,80 @@ def test_row_osv1_000() -> None:
def test_row_osv1_001() -> None:
- """Core 1 VIOLATION pin: the L0 hero is a verdict, and velocity is a chart.
-
- Three separable facts, asserted separately so a partial fix cannot pass a
- single blunt check: the hero renderer emits no figure and no count; L0
- builds its hero from the verdict path; and the KPI strip carries the five
- shipped keys with NO needs-attention key among them.
+ """Core 1 CONFORMS: the L0 hero LEADS with fleet velocity over a stated
+ window, and the four counts an operator acts on sit in that same region.
+
+ RETARGETED 2026-09-04. This probe used to be the VIOLATION pin -- it
+ asserted the hero was a verdict line, that velocity was a chart two
+ regions below, and that the KPI strip carried five keys with no
+ needs-attention count among them. That behaviour moved TOWARD the clause
+ (VIOLATION-MOVEMENT), so the row flipped to CONFORMS and this probe was
+ pointed at the fixed shape in the same change. Flip direction is now
+ REGRESSION: this going red means the repo moved back AWAY from Core 1.
+
+ Three separable facts, asserted separately so a partial regression cannot
+ slip past a single blunt check:
+ 1. the renderer emits a velocity FIGURE and STATES its window -- a bare
+ number with no window is the half-fix Core 1 does not accept;
+ 2. L0 builds its hero from that renderer, with exactly the four counts
+ the clause names, each carrying a text LABEL (Core 3);
+ 3. the counts are composed INTO the hero region, not into a separate
+ strip below it -- which is precisely where they used to live.
"""
hero = read(WIDGETS)
- start = hero.index("def render_verdict_hero")
- body = hero[start : start + 1400]
- assert 'class="verdict"' in body and 'class="eyebrow2"' in body, (
- "OSV1-001 (Core 1): `render_verdict_hero` no longer emits the verdict/eyebrow "
- "shape this pin was written against -- the hero moved. Re-measure the row."
+ start = hero.index("def render_velocity_hero")
+ body = hero[start : start + 1800]
+ assert 'class="figv"' in body, (
+ "OSV1-001 (Core 1) REGRESSION: `render_velocity_hero` no longer emits the "
+ "velocity figure. Core 1's hero IS that throughput reading -- without it the "
+ "region is a verdict line again, which is the defect this row closed."
+ )
+ assert 'class="figwin"' in body and "velocity_window" in body, (
+ "OSV1-001 (Core 1) REGRESSION: the hero's throughput figure no longer states "
+ 'the window it covers. Core 1 says "throughput over a STATED window" -- an '
+ "operator reading a bare number learns nothing from it."
)
- assert "velocity" not in body.lower(), (
- "OSV1-001 (Core 1) PIN BROKE THE RIGHT WAY: the hero renderer now mentions "
- "velocity. If the hero really carries throughput over a stated window plus the "
- "four counts, flip OSV1-001 to CONFORMS and retarget this probe at the fixed "
- "shape IN THE SAME CHANGE (work_item_pipeline-ujy). A passing pin is not "
- "conformance; only the retargeted probe is."
+ assert "render_kpi_strip(" in body, (
+ "OSV1-001 (Core 1) REGRESSION: the hero renderer no longer composes the counts "
+ "strip itself. If the route places one below the hero again, the counts have "
+ "left the hero REGION, which is what Core 1 requires them to be inside."
+ )
+ assert 'role="status"' in body, (
+ "OSV1-001 (Core 1): the hero stopped being a live region. The 20s body-swap "
+ 'replaces this panel in place (Core 6) -- without `role="status"` that '
+ "replacement announces nothing."
)
app = read(WEBAPP)
- assert "hero_html = WD.render_verdict_hero(" in app, (
- "OSV1-001 (Core 1): L0 no longer builds its hero from `render_verdict_hero`. "
- "That is the fix landing -- re-derive the row."
+ assert "hero_html = WD.render_velocity_hero(" in app, (
+ "OSV1-001 (Core 1) REGRESSION: L0 no longer builds its hero from "
+ "`render_velocity_hero`. Re-derive the row before changing this."
)
- # The shipped KPI strip: five keys, and `needs attention` is not one of them.
- kpi = app[app.index("kpi_html = WD.render_kpi_strip(") :][:2200]
- shipped = set(re.findall(r'key="([a-z_0-9]+)"', kpi))
- assert shipped == {"agents", "held", "ready", "blocked", "resolved24h"}, (
- f"OSV1-001 (Core 1): the L0 KPI strip's keys moved -- pinned "
- f"{{agents, held, ready, blocked, resolved24h}}, observed {sorted(shipped)}. "
- f"If a needs-attention count was added, that is the fix landing "
- f"(work_item_pipeline-ujy): flip the row and retarget this probe."
+ # The four counts Core 1 names, read off the hero's own construction --
+ # bounded to it, so a label somewhere else on the page cannot stand in for
+ # one that is missing here.
+ call = app[
+ app.index("hero_counts = [") : app.index("velocity_data = _workspace_velocity_data(")
+ ]
+ labels = set(re.findall(r'label="([^"]+)"', call))
+ assert labels == {"In flight (held)", "Blocked", "Needs attention", "Open / ready"}, (
+ f"OSV1-001 (Core 1): the L0 hero's counts moved -- Core 1 names FOUR (in flight "
+ f"(held), blocked, needs attention, open/ready); observed {sorted(labels)}. "
+ f"`Needs attention` is the one that was absent anywhere at seed; losing it "
+ f"again is the original defect returning."
)
- # Matched on the card LABELS, not on the word "attention": the Blocked card
- # already links to `#attention-queue`, so a substring check would be
- # satisfied by an href and assert nothing about a count.
- labels = set(re.findall(r'label="([^"]+)"', kpi))
- assert labels == {"Agents active now", "Held", "Ready", "Blocked", "Resolved 24h"}, (
- f"OSV1-001 (Core 1): the KPI strip's card labels moved -- pinned the five "
- f"shipped ones, observed {sorted(labels)}. Core 1 names FOUR counts an operator "
- f"acts on; `needs attention` was the one absent at seed. If it was added, that "
- f"is the fix landing (work_item_pipeline-ujy) -- re-derive the row."
+ assert "velocity_window=" in call and "velocity_value=" in call, (
+ "OSV1-001 (Core 1): L0 stopped passing a velocity figure and/or its window to "
+ "the hero. Both halves are the clause."
+ )
+
+ # No second strip survives below the hero: the route holds no separate
+ # `kpi_html` fragment to interpolate under it any more.
+ assert "kpi_html" not in app, (
+ "OSV1-001 (Core 1) REGRESSION: a separate KPI-strip fragment is back in the L0 "
+ "route. The counts belong INSIDE the hero region (`render_velocity_hero` "
+ "composes them); a strip below it is the shape this row closed."
)
@@ -259,12 +350,28 @@ def test_row_osv1_003() -> None:
def test_row_osv1_004() -> None:
- """Core 3 GAP pin: no rendered-fixture kit, and the chip vocabulary that
- the kit will check is still the five-word map measured at seed.
+ """Core 3 CONFORMS: the rendered check exists, is not deferred, and the
+ chip vocabulary it walks still gives every status a WORD.
+
+ This row rests on the kit's real result over rendered L0/L1/L2 (recorded
+ in the row itself), which no in-process probe can re-run. So this probe
+ asserts the two things that CAN still be seen going wrong from here: the
+ check disappearing or being deferred, and a status losing its word in the
+ map the check walks.
"""
- assert not _exists(TIER_A_KIT), (
- f"OSV1-004 (Core 3): {TIER_A_KIT} now exists -- re-derive this row from the "
- f"kit's real result over rendered L0/L1/L2 fixtures (work_item_pipeline-c1a)."
+ assert _exists(TIER_A_KIT), (
+ f"OSV1-004 (Core 3) REGRESSION: {TIER_A_KIT} is gone. Core 3's check is Tier "
+ f"A and scoped to RENDERED fixtures -- without the kit nothing asserts it, and "
+ f"this row has no basis to be green."
+ )
+ kit = _kit_source()
+ assert {"check_state_not_colour_only", "test_state_not_colour_only"} <= _kit_defs(kit), (
+ "OSV1-004 (Core 3) REGRESSION: the kit no longer implements "
+ "`state.not_colour_only` over rendered pages."
+ )
+ assert not _kit_deferred_rows(kit, "test_state_not_colour_only"), (
+ "OSV1-004 (Core 3) REGRESSION: the rendered Core 3 check is now marked xfail. "
+ "This row is CONFORMS because the check PASSES; a deferred check is a red row."
)
browse = read(WEBBROWSE)
labels = set(re.findall(r'"(?:open|held|blocked|deferred|resolved)":\s*"([A-Z]+)"', browse))
@@ -366,15 +473,15 @@ def test_row_osv1_005() -> None:
# --------------------------------------------------------------- OSV1-006
-def test_row_osv1_006() -> None:
- """Core 4 CONFORMS: computed-geometry sites are EXACTLY the register.
-
- This is the exemption register itself (Phase-1 ruling Need 2 put it in
- `ledger/` so shrinking it needs no amendment). Shrinking passes only after
- the register below is shrunk to match; GROWING fails immediately, which is
- the direction that matters.
- """
- register = {
+#: THE exemption register Core 4 names -- "The register lives in `ledger/`, not
+#: in this contract, so that shrinking it is a convergent change requiring no
+#: amendment." Module-level rather than local to `test_row_osv1_006` below so
+#: that the Tier-A conformance kit
+#: (`tests/conformance/operator_surface/test_tier_a.py`, Conformance 6) reads
+#: THIS register rather than growing a second copy: OSV1-025's own notes name
+#: that as the failure to avoid, because two censuses disagree silently.
+EXEMPTION_REGISTER: frozenset[str] = frozenset(
+ {
"chartsvg.py:268",
"chartsvg.py:464",
"chartsvg.py:488",
@@ -391,14 +498,26 @@ def test_row_osv1_006() -> None:
"webapp.py:3376",
"webapp.py:4393",
"webapp.py:4908",
- "webtheme.py:4120",
- "webtheme.py:4139",
- "webtheme.py:4146",
+ "webtheme.py:4131",
+ "webtheme.py:4150",
+ "webtheme.py:4157",
"widgets.py:704",
"widgets.py:831",
"widgets.py:834",
"widgets.py:1110",
}
+)
+
+
+def test_row_osv1_006() -> None:
+ """Core 4 CONFORMS: computed-geometry sites are EXACTLY the register.
+
+ This is the exemption register itself (Phase-1 ruling Need 2 put it in
+ `ledger/` so shrinking it needs no amendment). Shrinking passes only after
+ `EXEMPTION_REGISTER` above is shrunk to match; GROWING fails immediately,
+ which is the direction that matters.
+ """
+ register = EXEMPTION_REGISTER
observed = set(style_sites_in("COMPUTED"))
unregistered = observed - register
assert not unregistered, (
@@ -484,47 +603,91 @@ def test_row_osv1_008() -> None:
# --------------------------------------------------------------- OSV1-009
-def test_row_osv1_009() -> None:
- """Core 7 VIOLATION pin: the token-pair luminance math, RE-RUN here.
+#: The ink ramp's four canonical steps, brightest-to-quietest in dark mode and
+#: darkest-to-lightest in light. `--dim`/`--ink` are deliberately excluded: they
+#: are ALIASES onto two of these four, so including them would make the
+#: distinctness check below trivially false.
+_INK_RAMP = ("--ink-primary", "--ink-secondary", "--ink-tertiary", "--ink-quiet")
- Two halves, both pinned: the six below-floor pairs are all --ink-quiet in
- light mode, AND that token is used for real reading copy. Fixing either
- half alone is progress the row must record, so neither is folded into the
- other.
+
+def test_row_osv1_009() -> None:
+ """Core 7 CONFORMS: every declared token pair clears its floor, both themes.
+
+ RETARGETED from the seed pin (work_item_pipeline-sxh, 2026-09-04). The pin
+ froze six below-floor pairs -- all `--ink-quiet` in light mode, three
+ grounds x the two duplicated light blocks -- plus the call site that made
+ that token READING COPY rather than a decorative exemption. Both halves are
+ closed by one token change (`--ink-quiet` #7c8ba0 -> #596473 in BOTH light
+ blocks), so the reading-copy half needs no separate assert: the token is now
+ above the text floor wherever it is used.
+
+ Every number below is COMPUTED from the live token blocks in webtheme.py on
+ each run -- nothing here is a transcribed ratio. The three guarded shapes:
+
+ 1. no declared ink x ground pair below 4.5:1, in any of the three blocks;
+ 2. no declared status x ground pair below 3:1 (the half that CONFORMED at
+ seed and must not silently regress while the text half is worked on);
+ 3. the fix was made at the TOKEN and in BOTH light blocks, and did not
+ buy contrast by collapsing the ink ramp.
+
+ Honest limit, unchanged from the seed row and the reason OSV1-010 stays
+ open: flat token-pair math models a swatch on a bare ground. The real
+ surface puts `backdrop-filter` glass over an ambient radial gradient, which
+ lifts perceived background luminance. Necessary, never sufficient.
"""
- below = sorted(
- (round(r, 2), ink, ground, block) for block, ink, ground, r in text_pairs() if r < 4.5
+ pairs = text_pairs()
+ assert len(pairs) >= 54, (
+ f"OSV1-009 (Core 7): the declared ink x ground surface SHRANK to {len(pairs)} "
+ f"pairs (54 at seed). A floor check over fewer pairs passes by measuring "
+ f"less -- re-derive this row from what the token blocks actually declare."
)
- assert len(below) == 6, (
- f"OSV1-009 (Core 7) LUMINANCE MOVED: pinned six declared text pairs below the "
- f"4.5:1 floor, observed {len(below)}.\n"
- f" If FEWER: the tokens are being fixed -- update the pin (or flip the row to "
- f"CONFORMS at zero) and retarget this probe IN THE SAME CHANGE "
- f"(work_item_pipeline-sxh). A passing pin is not conformance.\n"
- f" If MORE: a token regressed below a frozen floor.\n"
- f" observed: {below}"
+ below_text = sorted(
+ (round(r, 2), ink, ground, block) for block, ink, ground, r in pairs if r < 4.5
)
- assert {b[1] for b in below} == {"--ink-quiet"}, (
- f"OSV1-009 (Core 7): a token OTHER than --ink-quiet is now below the text "
- f"floor: {sorted({b[1] for b in below})}. --ink-quiet is at least documented "
- f"as decorative; anything else below 4.5:1 is a plain regression."
+ assert not below_text, (
+ f"OSV1-009 (Core 7) REGRESSION: {len(below_text)} declared text pair(s) fell "
+ f"below the 4.5:1 floor. Fix the TOKEN, in BOTH light blocks -- they are held "
+ f"in sync only by comment.\n (ratio, ink, ground, block): {below_text}"
)
- assert min(b[0] for b in below) == 2.72, (
- f"OSV1-009 (Core 7): the worst declared text pair moved from 2.72:1 to "
- f"{min(b[0] for b in below)}:1."
+
+ non_text = non_text_pairs()
+ assert len(non_text) >= 9, (
+ f"OSV1-009 (Core 7): the declared status x ground surface SHRANK to "
+ f"{len(non_text)} pairs (9 at seed) -- re-derive this row."
+ )
+ below_non_text = sorted(
+ (round(r, 2), hue, ground, block) for block, hue, ground, r in non_text if r < 3.0
)
- assert contains(CHARTSVG, 'style="fill:var(--ink-quiet)">'), (
- "OSV1-009 (Core 7) PIN BROKE THE RIGHT WAY: chartsvg.py no longer paints its "
- "empty-state caption with --ink-quiet. That call site is what makes the "
- "below-floor token READING COPY rather than a documented decorative "
- "exemption -- re-derive the row (work_item_pipeline-sxh)."
+ assert not below_non_text, (
+ f"OSV1-009 (Core 7) REGRESSION: {len(below_non_text)} declared non-text pair(s) "
+ f"fell below the 3:1 floor.\n (ratio, hue, ground, block): {below_non_text}"
)
- worst_non_text = min(r for *_rest, r in non_text_pairs())
- assert worst_non_text >= 3.0, (
- f"OSV1-009 (Core 7) REGRESSION: a status hue fell below the 3:1 NON-TEXT "
- f"floor ({worst_non_text:.2f}:1). That half CONFORMED at seed and this row "
- f"does not cover it -- it is a separate, new violation."
+
+ blocks = token_blocks()
+ assert set(blocks) == {"dark", "light-media", "light-attr"}, (
+ f"OSV1-009 (Core 7): a declared token block appeared or vanished "
+ f"({sorted(blocks)}). 'both themes' is measured over these three."
)
+ light = {
+ name: {t: resolve_token(t, blocks[name]) for t in (*_INK_RAMP, *GROUND_TOKENS)}
+ for name in ("light-media", "light-attr")
+ }
+ assert light["light-media"] == light["light-attr"], (
+ f"OSV1-009 (Core 7): the two light token blocks DRIFTED on the tokens this "
+ f"clause measures. webtheme.py's own comment says they are kept in sync only "
+ f"by comment; a colour fixed in one and not the other is the exact hazard the "
+ f"seed row's six pairs (three grounds x two blocks) recorded.\n"
+ f" @media (prefers-color-scheme:light): {light['light-media']}\n"
+ f' :root[data-theme="light"]: {light["light-attr"]}'
+ )
+ for name, table in blocks.items():
+ ramp = [resolve_token(t, table) for t in _INK_RAMP]
+ assert len(set(ramp)) == len(_INK_RAMP), (
+ f"OSV1-009 (Core 7): the ink ramp COLLAPSED in the {name!r} block -- two "
+ f"of {list(_INK_RAMP)} now resolve to the same colour ({ramp}). Clearing "
+ f"the floor by deleting a ramp step is not conformance; --ink-quiet must "
+ f"stay quieter than --ink-tertiary while clearing 4.5:1."
+ )
# --------------------------------------------------------------- OSV1-010
@@ -587,13 +750,32 @@ def test_row_osv1_011() -> None:
def test_row_osv1_012() -> None:
- """Core 8 GAP pin: no two-render kit, and the empty sentences measured at
- seed are still the ones the kit will look for.
+ """Core 8 VIOLATION pin: two widget renderers still have no empty branch,
+ and the kit's two `calm.keeps_slot` halves are still deferred against this
+ row.
+
+ Pinned on the RENDERERS rather than on a rendered page, because that is
+ what an in-process probe can see: `render_attention_queue` and
+ `render_agents_panel` return their container unconditionally, so an empty
+ one is a slot with nothing in it. Giving either an empty branch flips this
+ pin -- which is the fix landing.
"""
- assert not _exists(TIER_A_KIT), (
- f"OSV1-012 (Core 8): {TIER_A_KIT} now exists -- re-derive this row from a real "
- f"empty-vs-populated render comparison (work_item_pipeline-c1a)."
- )
+ for func in ("render_attention_queue", "render_agents_panel"):
+ body = _widgets_function(func)
+ assert "if not data[" not in body, (
+ f"OSV1-012 (Core 8) PIN BROKE THE RIGHT WAY: `{func}` now has an empty "
+ f"branch. If it emits the empty SENTENCE Core 8 requires, re-run the "
+ f"Tier-A kit's `calm.keeps_slot` halves, flip OSV1-012 to CONFORMS, delete "
+ f"their xfail markers and retarget this probe -- all in the same change "
+ f"(work_item_pipeline-c1a)."
+ )
+ kit = _kit_source()
+ for test_name in ("test_calm_keeps_slot", "test_calm_keeps_slot_l1"):
+ assert "OSV1-012" in _kit_deferred_rows(kit, test_name), (
+ f"OSV1-012 (Core 8) PIN BROKE THE RIGHT WAY: the kit's `{test_name}` is no "
+ f"longer deferred against this row. A passing good half is the fix -- flip "
+ f"the row in the same change."
+ )
assert contains(WIDGETS, '"All clear"'), (
"OSV1-012 (Core 8): the calm headline 'All clear' is gone. Calm must stay "
"STATED -- and must not become a triumphant zero."
@@ -829,12 +1011,22 @@ def test_row_osv1_020() -> None:
def test_row_osv1_021() -> None:
- """Conformance 2 pin: NEITHER named kit exists (this fixture spans tiers)."""
- assert not _exists(TIER_A_KIT) and not _exists(TIER_B_KIT), (
- "OSV1-021 (Conformance 2): a named kit path appeared. This is the one fixture "
- "that spans BOTH tiers -- it goes green only when the Tier-A accessible-name "
- "half (work_item_pipeline-c1a) AND the Tier-B hue half "
- "(work_item_pipeline-qgo) both land and both discriminate."
+ """Conformance 2 pin: the Tier-A half landed; the Tier-B hue half has not,
+ and that absence is what keeps this row red."""
+ assert not _exists(TIER_B_KIT), (
+ f"OSV1-021 (Conformance 2): {TIER_B_KIT} now exists. This is the one fixture "
+ f"that spans BOTH tiers -- the Tier-A accessible-name half already landed "
+ f"(work_item_pipeline-c1a, measured in OSV1-004); re-derive this row from the "
+ f"Tier-B hue half's own demonstrated pair (work_item_pipeline-qgo)."
+ )
+ kit = _kit_source()
+ assert "check_state_not_colour_only" in _kit_defs(kit), (
+ "OSV1-021 (Conformance 2): the Tier-A half is gone from the kit. This row is "
+ "red on the Tier-B half ONLY -- losing the Tier-A half is a second, new defect."
+ )
+ assert _kit_bad_halves(kit, "test_state_not_colour_only"), (
+ "OSV1-021 (Conformance 2): the Tier-A half no longer ships a bad half. A "
+ "fixture whose bad half nobody runs is a claim, not a fixture (Freeze 4)."
)
assert contains(
OPERATOR_CONTRACT_PATH, "fixture whose status chips carry only a status class"
@@ -871,10 +1063,30 @@ def test_row_osv1_023() -> None:
def test_row_osv1_024() -> None:
- """Conformance 5 pin: no Tier-A kit, so hero composition is unasserted."""
- assert not _exists(TIER_A_KIT), (
- f"OSV1-024 (Conformance 5): {TIER_A_KIT} now exists -- re-derive from the "
- f"demonstrated good/bad pair (work_item_pipeline-c1a)."
+ """Conformance 5 CONFORMS: the fixture exists, discriminates, and its GOOD
+ half runs UNDEFERRED against the rebuilt hero (OSV1-001 closed 2026-09-05).
+
+ Flipped at highway wave-1 integration: the hero lane closed OSV1-001 and the
+ orchestrator removed the kit's xfail(strict) deferral in the same change; the
+ good half now passes on the real L0 (kit run: 38 passed / 4 xfailed).
+ """
+ kit = _kit_source()
+ assert "check_hero_velocity_and_counts" in _kit_defs(kit), (
+ f"OSV1-024 (Conformance 5): {TIER_A_KIT} no longer implements "
+ f"`hero.velocity_and_counts` at the location the contract names."
+ )
+ assert _kit_bad_halves(kit, "test_hero_velocity_and_counts"), (
+ "OSV1-024 (Conformance 5): the fixture no longer ships a bad half -- a fixture "
+ "that cannot be watched failing is a claim (Freeze 4)."
+ )
+ assert not _kit_deferred_rows(kit, "test_hero_velocity_and_counts"), (
+ "OSV1-024 (Conformance 5) REGRESSION: the good half is deferred again -- a "
+ "Conformance row cannot read CONFORMS while its good half carries an xfail. "
+ "Either the hero regressed (re-open OSV1-001) or the marker is stale."
+ )
+ assert row("OSV1-001")["disposition"] == "CONFORMS", (
+ "OSV1-024 (Conformance 5) REGRESSION: OSV1-001 is red again, so Conformance 5's "
+ "good half cannot pass against the shipped hero. Re-derive both rows together."
)
assert contains(
OPERATOR_CONTRACT_PATH,
@@ -883,11 +1095,29 @@ def test_row_osv1_024() -> None:
def test_row_osv1_025() -> None:
- """Conformance 6 pin: no Tier-A kit, so the register is checked only here."""
- assert not _exists(TIER_A_KIT), (
- f"OSV1-025 (Conformance 6): {TIER_A_KIT} now exists. Make sure it reads THIS "
- f"ledger's register (OSV1-006) rather than growing its own copy -- two censuses "
- f"will disagree, silently (work_item_pipeline-c1a)."
+ """Conformance 6 pin: the fixture exists, reads THIS ledger's register, and
+ its GOOD half is still deferred against OSV1-005."""
+ kit = _kit_source()
+ assert "check_visual_single_source" in _kit_defs(kit), (
+ f"OSV1-025 (Conformance 6): {TIER_A_KIT} no longer implements "
+ f"`visual.single_source` at the location the contract names."
+ )
+ assert _kit_bad_halves(kit, "test_visual_single_source"), (
+ "OSV1-025 (Conformance 6): the fixture no longer ships a bad half (Freeze 4)."
+ )
+ assert "EXEMPTION_REGISTER" in kit, (
+ "OSV1-025 (Conformance 6): the kit stopped importing this ledger's exemption "
+ "register. ONE census, ONE register (Phase-1 ruling Need 2) -- a second copy "
+ "disagrees with this one, silently."
+ )
+ assert "OSV1-005" in _kit_deferred_rows(kit, "test_visual_single_source"), (
+ "OSV1-025 (Conformance 6) PIN BROKE THE RIGHT WAY: the good half is no longer "
+ "deferred against OSV1-005. Flip OSV1-005 AND this row and retarget both "
+ "probes in the same change (work_item_pipeline-np3)."
+ )
+ assert row("OSV1-005")["disposition"] in PINNING_DISPOSITIONS, (
+ "OSV1-025 (Conformance 6) PIN BROKE THE RIGHT WAY: OSV1-005 is no longer red, "
+ "so Conformance 6's good half should now pass. Re-derive from the PASSING pair."
)
assert contains(OPERATOR_CONTRACT_PATH, 'style="color:#D9A253"'), (
"OSV1-025: Conformance 6's named bad specimen moved in the contract -- re-review the row."
@@ -895,10 +1125,24 @@ def test_row_osv1_025() -> None:
def test_row_osv1_026() -> None:
- """Conformance 7 pin: no Tier-A kit, so empty-vs-populated is uncompared."""
- assert not _exists(TIER_A_KIT), (
- f"OSV1-026 (Conformance 7): {TIER_A_KIT} now exists -- re-derive from a real "
- f"two-render comparison (work_item_pipeline-c1a)."
+ """Conformance 7 pin: the two-render fixture exists and discriminates, and
+ its GOOD halves are still deferred against OSV1-012."""
+ kit = _kit_source()
+ assert "check_calm_keeps_slot" in _kit_defs(kit), (
+ f"OSV1-026 (Conformance 7): {TIER_A_KIT} no longer implements "
+ f"`calm.keeps_slot` at the location the contract names."
+ )
+ assert _kit_bad_halves(kit, "test_calm_keeps_slot"), (
+ "OSV1-026 (Conformance 7): the fixture no longer ships a bad half (Freeze 4)."
+ )
+ assert "OSV1-012" in _kit_deferred_rows(kit, "test_calm_keeps_slot"), (
+ "OSV1-026 (Conformance 7) PIN BROKE THE RIGHT WAY: the good half is no longer "
+ "deferred against OSV1-012. Flip OSV1-012 AND this row and retarget both "
+ "probes in the same change (work_item_pipeline-c1a)."
+ )
+ assert row("OSV1-012")["disposition"] in PINNING_DISPOSITIONS, (
+ "OSV1-026 (Conformance 7) PIN BROKE THE RIGHT WAY: OSV1-012 is no longer red, "
+ "so Conformance 7's good halves should now pass. Re-derive from the PASSING pair."
)
assert contains(
OPERATOR_CONTRACT_PATH, "a render that drops empty widgets, or renders a hero-scale `0`"
@@ -910,27 +1154,38 @@ def test_row_osv1_026() -> None:
def test_row_osv1_027() -> None:
- """Freeze 1 pin: the Tier-A kit neither exists nor runs in any gate.
+ """Freeze 1 CONFORMS: the Tier-A kit exists AND runs in a real gate.
- Both halves are pinned, because a kit that exists but runs in nothing is
+ Both halves are asserted, because a kit that exists but runs in nothing is
the exact failure this repo already measured once (CCV1-022: a whole suite
- of green claims nobody had ever executed).
+ of green claims nobody had ever executed). Matched on the KIT PATH, never
+ on the word "conformance": the Makefile and ci.yml already say "conformance
+ ledger" about Tier 4, and a check a pre-existing comment satisfies asserts
+ nothing.
"""
- assert not _exists(TIER_A_KIT), (
- f"OSV1-027 (Freeze 1): {TIER_A_KIT} now exists. Freeze 1 ALSO requires it to "
- f"run on every pull request -- do not flip this row on the file alone "
- f"(work_item_pipeline-c1a)."
- )
- # Matched on the KIT PATH, never on the word "conformance": the Makefile
- # and ci.yml already say "conformance ledger" about Tier 4, and a probe
- # that a pre-existing comment satisfies is a probe asserting nothing.
- assert "tests/conformance" not in read(MAKEFILE), (
- "OSV1-027 (Freeze 1): the Makefile now has a target covering tests/conformance "
- "-- the wiring half is landing. Re-derive."
- )
- assert "tests/conformance" not in read(CI_WORKFLOW), (
- "OSV1-027 (Freeze 1): ci.yml now runs tests/conformance -- the 'runs on every "
- "pull request' half is landing. Re-derive."
+ assert _exists(TIER_A_KIT), f"OSV1-027 (Freeze 1) REGRESSION: {TIER_A_KIT} is gone."
+ make = read(MAKEFILE)
+ assert "tests/conformance" in make and "test-conformance-a:" in make, (
+ "OSV1-027 (Freeze 1) REGRESSION: the Makefile no longer carries a target "
+ "covering tests/conformance. Existing is not the same as running."
+ )
+ ci = read(CI_WORKFLOW)
+ assert "tests/conformance/operator_surface" in ci, (
+ "OSV1-027 (Freeze 1) REGRESSION: ci.yml no longer runs the Tier-A kit -- "
+ "Freeze 1's second half is 'runs on every pull request'."
+ )
+ assert "pull_request" in ci, (
+ "OSV1-027 (Freeze 1) REGRESSION: the workflow that runs the kit no longer "
+ "triggers on pull_request."
+ )
+ kit = _kit_source()
+ assert "TIER_A_CHECKS" in kit and _kit_defs(kit) >= {
+ "test_every_tier_a_machine_check_the_contract_names_is_implemented_here",
+ "test_every_check_ships_a_bad_half",
+ }, (
+ "OSV1-027 (Freeze 1) REGRESSION: the kit dropped its own coverage tripwires. "
+ "Without them it can quietly cover less of the contract than it claims, which "
+ "is the failure Freeze 1 and Freeze 4 exist to prevent."
)
@@ -969,11 +1224,17 @@ def test_row_osv1_029() -> None:
def test_row_osv1_030() -> None:
- """Freeze 4 pin: neither kit exists, so no fixture has been demonstrated."""
- assert not _exists(TIER_A_KIT) and not _exists(TIER_B_KIT), (
- "OSV1-030 (Freeze 4): a kit path appeared. 'Demonstrated by running it' is the "
- "whole clause -- record WHICH revert produced WHICH failure, the way "
- "CCV1-023 did for the custody family, before flipping this row."
+ """Freeze 4 pin: the Tier-A fixtures are demonstrated; no browser kit
+ exists, so the three Tier-B fixtures are not."""
+ assert not _exists(TIER_B_KIT), (
+ "OSV1-030 (Freeze 4): the Tier-B kit path appeared. 'Demonstrated by running "
+ "it' is the whole clause -- record WHICH revert produced WHICH failure, the "
+ "way CCV1-023 did for the custody family, before flipping this row."
+ )
+ assert _exists(TIER_A_KIT) and _kit_bad_halves(_kit_source(), "test_calm_keeps_slot"), (
+ "OSV1-030 (Freeze 4): the Tier-A fixtures' demonstrated bad halves are gone. "
+ "This row is red on the TIER-B half only -- losing the Tier-A half is a "
+ "second, new defect."
)
@@ -1002,10 +1263,11 @@ def test_row_osv1_031() -> None:
"to CONFORMS and retarget this probe to assert no Core row is red "
"(work_item_pipeline-umm)."
)
- assert len(red) == 10, (
- f"OSV1-031 (Freeze 5): pinned 10 red Core-carrying rows, observed {len(red)}: "
+ assert len(red) == 7, (
+ f"OSV1-031 (Freeze 5): pinned 7 red Core-carrying rows, observed {len(red)}: "
f"{red}. Movement in either direction means this gate's tally changed -- update "
- f"the pin and the row's notes in the same change."
+ f"the pin and the row's notes in the same change. (Was 10 at seed; OSV1-009 "
+ f"went green 2026-09-04, work_item_pipeline-sxh.)"
)
assert {r["id"] for r in core_rows if r["disposition"] == "NOT-ASSERTABLE"} == {
"OSV1-018",
diff --git a/ledger/rows.yaml b/ledger/rows.yaml
index bd3fa2b..5cd1722 100644
--- a/ledger/rows.yaml
+++ b/ledger/rows.yaml
@@ -931,50 +931,72 @@
different families.
- id: OSV1-001
- title: the L0 hero is a verdict line, not fleet velocity with the counts that matter
+ title: the L0 hero leads with fleet velocity and carries the four counts that matter
contract:
file: contracts/operator-surface.v1.md
clause: Core 1
quote: |
The L0 hero region carries throughput over a stated window, presented together with the
counts an operator acts on: in flight (held), blocked, needs attention, and open/ready.
- disposition: VIOLATION
+ disposition: CONFORMS
work: work_item_pipeline-ujy
assertion:
kind: probe
ref: test_row_osv1_001
notes: >
- PINNING ROW -- the probe asserts the CURRENT, KNOWN-WRONG shape on purpose;
- a passing probe here is NOT conformance. Flip direction VIOLATION-MOVEMENT.
-
- MEASURED 2026-09-04 against 4aaee50, not taken from the Phase-0 brief:
- webapp.py:4602 the hero is `WD.render_verdict_hero(VerdictHeroData(...))`
- widgets.py:637-663 that renderer emits `` carrying an eyebrow, a
- verdict headline, a detail line, and an OPTIONAL
- `meta_row`. L0 passes no `meta_row`, so the hero
- carries no figure and no count at all.
- webapp.py:4611-4641 a SEPARATE kpi-strip below the hero: five cards keyed
- agents / held / ready / blocked / resolved_24h.
- webapp.py:4647 velocity is `_velocity_chart_shell_html(title=
- "Environment velocity", ...)` -- a CHART, two regions
- below the hero, not a hero figure.
- Against the clause: throughput-in-the-hero ABSENT; held / blocked /
- open-ready present as KPI cards but not in the hero; NEEDS ATTENTION absent
- as a count anywhere in either region (the ranked "Needs you" section is at
- webapp.py:4676 and its length is never surfaced as a count); and two cards
- the clause does not name (agents active, resolved 24h) occupy the strip.
-
- OPEN READING, RETURNED TO THE ROOT AND NOT DECIDED BY THIS RECONCILE:
- whether the shipped KPI strip is part of "the L0 hero region", i.e. whether
- held/blocked/ready already satisfy the counts half in part. The disposition
- does not turn on it -- the throughput half is unsatisfied on either
- reading -- but the size of the remaining work does.
+ FLIPPED 2026-09-04 from VIOLATION (VIOLATION-MOVEMENT: the pinning probe went
+ red because the behaviour moved TOWARD the clause). The probe was retargeted
+ at the fixed shape in the same change, and its mutations rewritten to
+ reinstate each half of the closed defect. Flip direction is now REGRESSION.
+
+ MEASURED 2026-09-04 against the change that closed it:
+ widgets.py:1323-1396 `render_velocity_hero(VelocityHeroData)` -- one panel,
+ `
`, carrying: the velocity figure
+ (`
`), the window STATED beside it
+ (`last 24h`), the verdict
+ demoted to a `.hero-caption`, and the counts strip
+ composed INSIDE the same div (it calls `render_kpi_strip`
+ itself rather than leaving the route to place one below).
+ webapp.py:4611-4642 L0 builds that hero, with exactly the four counts Core 1
+ names: "In flight (held)" (held_total), "Blocked"
+ (blocked_total), "Needs attention" (len(attention_rows_raw)
+ -- the ranked queue's own length, which was the count
+ ABSENT anywhere at seed), "Open / ready" (ready_total).
+ webapp.py:4741 the body no longer interpolates a separate `{kpi_html}`
+ section: there is exactly ONE `.kpi-strip` on the page and
+ it is inside the hero region.
+ Against the clause: throughput-in-the-hero PRESENT with its window stated;
+ all four named counts PRESENT in the same region, each with a text label
+ (Core 3) and a numeral. "Resolved 24h" is no longer a card because it is the
+ figure; the agents-active reading it displaced survives in the verdict caption
+ ("N agents are moving ...") and in the "Agents now" section.
+
+ THE OPEN READING THE SEED RETURNED TO THE ROOT -- whether the shipped KPI strip
+ counted as part of "the L0 hero region" -- is now MOOT rather than decided: the
+ strip is composed into the hero panel itself, so it is part of the region on
+ either reading. The root ruling recorded on work_item_pipeline-ujy is what this
+ change followed.
+
+ Rendered evidence, both fixtures, asserted by test:
+ tests/unit/test_observatory_widgets.py
+ test_render_velocity_hero_leads_with_the_figure_and_states_its_window
+ test_render_velocity_hero_carries_all_four_named_counts_in_the_same_region
+ test_render_velocity_hero_every_count_carries_a_text_label_and_a_numeral
+ test_render_velocity_hero_empty_fixture_reports_zero_it_never_celebrates_it
+ test_render_velocity_hero_blocked_zero_goes_quiet_not_alarm_red
+ test_render_velocity_hero_is_a_live_region_for_the_body_swap
+ tests/integration/test_observatory_web.py
+ test_l0_hero_leads_with_fleet_velocity_over_a_stated_window
+ test_l0_hero_carries_the_four_named_counts_and_no_strip_survives_below_it
+ test_l0_hero_on_an_all_empty_fleet_reports_zero_without_celebrating_it
Core 1 overrode a recorded in-code invariant, which the contract's own
Changelog quotes: webapp.py:37-44 states the hero is the AGE of the oldest
unclaimed item, never a count. The owner weighed that and chose
- observability; the concern behind it survives as Core 8 (OSV1-012). See
+ observability; the concern behind it survives as Core 8 (OSV1-012), and this
+ composition honours it -- nothing scales with its value, so a zero is
+ reported at its siblings' scale with its label, never celebrated. See
OSV1-033 -- one of those Changelog quotes does not verify against its
cited source.
@@ -1059,43 +1081,56 @@
presence so the sweep, when built, has a real target.
- id: OSV1-004
- title: state is never colour-only -- unmeasured on a rendered page, no kit
+ title: state is never colour-only -- measured on rendered L0/L1/L2, and it holds
contract:
file: contracts/operator-surface.v1.md
clause: Core 3
quote: |
Every element carrying a state carries it in text as well as hue — a status chip has a
word, not only a class.
- disposition: GAP
- work: work_item_pipeline-c1a
+ disposition: CONFORMS
assertion:
kind: probe
ref: test_row_osv1_004
notes: >
- PINNING ROW -- the probe asserts the CURRENT, KNOWN-WRONG shape on purpose;
- a passing probe here is NOT conformance. Flip direction VIOLATION-MOVEMENT.
-
- GAP, REASON "KIT NOT BUILT". Core 3's check (`state.not_colour_only`) is
- Tier A, but the contract scopes it to "the rendered L0/L1/L2 fixtures", and
- `tests/conformance/operator_surface/test_tier_a.py` does not exist. This
- ledger kit is in-process only (no bd, no dolt, no subprocess), so it can
- assert the SOURCE shape of the chip vocabulary and nothing about a page.
-
- WHAT THE SOURCE SHAPE ALREADY SHOWS, measured 2026-09-04 -- encouraging,
- and deliberately NOT treated as conformance:
- webbrowse.py:139-152 every item status maps to BOTH a class
- (`_ITEM_STATUS_CHIP_CLASS`) and a WORD
- (`_ITEM_STATUS_CHIP_LABEL`: READY / HELD / BLOCKED
- / DEFERRED / RESOLVED) -- five statuses, five words.
- webbrowse.py:849-851 the L2 chip renders `item.status.upper()`.
- widgets.py:1162,1164 legend dots carry adjacent label text in the same
- `.li` span.
- KNOWN CANDIDATES THE RENDERED CHECK MUST ADJUDICATE, which no source probe
- can settle: `webapp.py:548` `` (an
- attribute-only name), `webbrowse.py:119` a bare ``
- prefixed to the blocked breakdown row, and `webapp.py:839`
- `` (in `_sidebar_html`, which measured as dead
- chrome -- no route passes `sidebar_html`).
+ RE-DERIVED 2026-09-05 from a REAL RENDERED MEASUREMENT -- never from the
+ fact that a kit file appeared.
+ `tests/conformance/operator_surface/test_tier_a.py` now implements Core 3's
+ `state.not_colour_only` and runs it over rendered L0, L1 and L2 pages of
+ the ALARM fixture (one item held past custody TTL, one blocked -- which is
+ Conformance 2's own scenario, so every status chip this surface can render
+ is actually on the page). Result: ZERO status-bearing elements without text
+ or an accessible name, on all three levels.
+
+ WHAT THE CHECK COUNTS AS STATUS-BEARING, so the scope of this green is
+ legible rather than implied: a class that IS a status word, or a status
+ word under one of this surface's status-class prefixes (`st-`, `is-`,
+ `sev-`, `tab-`, `status-`). The vocabulary is read out of the app's OWN
+ maps -- `webbrowse._ITEM_STATUS_CHIP_LABEL`, `widgets._HERO_ICON`, the
+ three status hue tokens -- rather than written down in the kit, so a status
+ the app grows cannot be silently unchecked. A decorative, unlabelled mark
+ INSIDE a status-bearing element that is itself named is excused: the state
+ is already carried in that ancestor's words, which is exactly the clause.
+
+ THE THREE CANDIDATES THE SEED ROW LEFT FOR THE RENDERED CHECK TO
+ ADJUDICATE, now adjudicated: `webapp.py:548`'s
+ `` carries an accessible name;
+ `webbrowse.py:119`'s bare `` sits inside
+ `Blocked N`, which carries the word;
+ `webapp.py:839`'s `` never reaches a rendered
+ page at all (dead chrome -- no route passes `sidebar_html`).
+
+ DISCRIMINATING PAIR DEMONSTRATED (Freeze 4). The bad half is Conformance
+ 2's own specimen -- `` -- and the same
+ function reports it
+ (`test_state_not_colour_only_bad_half_chip_with_only_a_class`). Two further
+ bad halves keep the check from degenerating into "has text": an
+ `aria-label`-only chip PASSES, and a named ancestor excuses only its own
+ descendants, never a sibling.
+
+ WHAT THIS ROW STILL DOES NOT COVER: the HUE half of Conformance 2 (the
+ alarm region's colour is `--alarm` or `--blocked`) is Tier B and belongs to
+ OSV1-021's second half.
- id: OSV1-005
title: >-
@@ -1235,14 +1270,20 @@
webapp.py:3376 {heading_style} computed heading
webapp.py:4393 {heading_style} computed heading
webapp.py:4908 {remove_heading_style} computed heading
- webtheme.py:4120 {style} computed style
- webtheme.py:4139 left:{_grad_x(f):.1f}px gradient stop offset
- webtheme.py:4146 width:{px}px swatch width
+ webtheme.py:4131 {style} computed style
+ webtheme.py:4150 left:{_grad_x(f):.1f}px gradient stop offset
+ webtheme.py:4157 width:{px}px swatch width
widgets.py:704 color:var({color_var}) token chosen at runtime
widgets.py:831 width:{pct}% mix-bar width
widgets.py:834 width:{pct}%;background:var({_MIX_COLOR_VAR[key]})
widgets.py:1110 background:var({_MIX_COLOR_VAR[key]})
+ The three `webtheme.py` coordinates were RE-DERIVED on 2026-09-04 by
+ work_item_pipeline-sxh (OSV1-009), which added comment lines above them:
+ 4120/4139/4146 -> 4131/4150/4157. Same three sites, same code, same
+ register SET -- only the line numbers moved. A `file:line` register is
+ coordinate-fragile by construction; any edit above a site shifts it.
+
HONEST LIMIT: several registered sites interpolate a COLOUR, not a
geometry (webapp.py:2142/2266, chartsvg.py:268, widgets.py:704/834/1110).
They pass Core 4's literal test because the value is computed rather than
@@ -1340,49 +1381,73 @@
the Conformance 3 bad-half behaviour.
- id: OSV1-009
- title: six declared text pairs sit below the 4.5:1 floor, and the token paints real copy
+ title: every declared token pair clears its floor -- 4.5:1 text, 3:1 non-text, both themes
contract:
file: contracts/operator-surface.v1.md
clause: Core 7
quote: |
Text contrast is at least 4.5:1 and non-text contrast at least 3:1, in both themes
- disposition: VIOLATION
+ disposition: CONFORMS
work: work_item_pipeline-sxh
assertion:
kind: probe
ref: test_row_osv1_009
notes: >
- PINNING ROW -- the probe asserts the CURRENT, KNOWN-WRONG shape on purpose;
- a passing probe here is NOT conformance. Flip direction VIOLATION-MOVEMENT.
+ FLIPPED VIOLATION -> CONFORMS 2026-09-04 by work_item_pipeline-sxh, in the
+ same change that retargeted the probe off its pin.
The Tier-A half of `perception.floors`: "token-pair relative-luminance math
over the declared token set". The rendered half is OSV1-010; the
- reduced-motion half is OSV1-011.
-
- MEASURED 2026-09-04 against 4aaee50 -- WCAG relative luminance over the
- three declared token blocks (dark `:root` webtheme.py:109,
- `@media (prefers-color-scheme:light)` :287, `:root[data-theme="light"]`
- :373), ink x ground, re-computed by the probe on every run:
- 54 text pairs evaluated, 48 clear 4.5:1, SIX DO NOT -- all `--ink-quiet`
- in LIGHT mode:
- #7c8ba0 on --color-ground #eef2fb = 3.09:1
- #7c8ba0 on --color-ground-elevated #e7ecf7 = 2.93:1
- #7c8ba0 on --color-ground-sunken #dde4f2 = 2.72:1
- (three pairs x two light blocks, which declare identical values.)
- The same token is fine in dark: 5.53 / 5.26 / 5.67:1.
- 9 status-hue/ground non-text pairs, worst 5.35:1 (`--blocked` on dark
- ground). THE NON-TEXT FLOOR OF 3:1 CONFORMS; this row is only about text.
-
- WHY THIS IS A VIOLATION RATHER THAN A DOCUMENTED EXEMPTION.
- webtheme.py:141-152 declares `--ink-quiet` "decorative/disabled-only, not
- guaranteed >=4.5:1 in light mode", which would be a legitimate WCAG
- exemption if it were only ever decorative. Measured, it is not:
- chartsvg.py:294 ``
- renders the sentence "No activity in this window" -- reading
- copy, on the empty-state path Core 8 exists to protect.
- chartsvg.py:461 the axis stub label falls back to the same token.
- 21 further `var(--ink-quiet)` uses inside webtheme.py's own rules, not
- audited per-site here.
+ reduced-motion half is OSV1-011. Closing this does NOT close OSV1-010 --
+ see the honest limit at the end.
+
+ WHAT WAS WRONG AT SEED (4aaee50). 54 text pairs evaluated, 48 cleared
+ 4.5:1, SIX DID NOT -- all `--ink-quiet` in LIGHT mode, three grounds x the
+ two duplicated light blocks, which declared identical values. The same
+ token was already fine in dark (5.53 / 5.26 / 5.67:1). It was a VIOLATION
+ and not a documented decorative exemption because the token painted real
+ reading copy: chartsvg.py:294's `` renders the sentence "No activity in this
+ window", plus the `.status-chip.st-resolved` / `.priority-chip.p3,.p4` /
+ `.link-chip .none` / `.fleet-row .agents.is-zero` / actions-drawer count
+ rules inside webtheme.py itself.
+
+ THE FIX, AND WHERE. At the TOKEN, not at the call sites -- `--ink-quiet`
+ darkened along the same hue (hsl ~215 deg) from #7c8ba0 to #596473, in BOTH
+ light blocks: `@media (prefers-color-scheme:light)` webtheme.py:338 AND
+ `:root[data-theme="light"]` :408. They are held in sync only by comment, so
+ changing one and not the other was the standing hazard; the probe now
+ asserts their parity over the measured token set directly. No call site
+ moved off the token, and no reading-copy usage was relabelled decorative.
+
+ MEASURED 2026-09-04 after the fix -- WCAG relative luminance over the three
+ declared token blocks (dark `:root` webtheme.py:109, the two light blocks
+ above), re-computed by the probe on every run, never transcribed:
+ TEXT, floor 4.5:1 -- 54 of 54 pairs clear it. The six that did not, before
+ -> after (identical in both light blocks):
+ --ink-quiet on --color-ground #eef2fb 3.09:1 -> 5.36:1
+ --ink-quiet on --color-ground-elevated #e7ecf7 2.93:1 -> 5.08:1
+ --ink-quiet on --color-ground-sunken #dde4f2 2.72:1 -> 4.71:1
+ Worst declared text pair overall moved 2.72:1 -> 4.71:1.
+ NON-TEXT, floor 3:1 -- 9 of 9 status-hue x ground pairs clear it, worst
+ 5.35:1 (`--blocked` on the dark ground), UNCHANGED by this fix. That half
+ conformed at seed; the probe now guards it rather than assuming it.
+
+ HIERARCHY PRESERVED, deliberately. Quiet was taken to ~4.7-5.4:1, not to
+ 7:1: in light it still reads clearly quieter than --ink-tertiary (7.85:1 on
+ the base ground) and --ink-secondary (9.16:1). The probe asserts the four
+ ink-ramp steps still resolve to four DISTINCT colours in every block, so a
+ future "fix" cannot buy contrast by collapsing a ramp step onto its
+ neighbour.
+
+ NOT COVERED, checked and clean: `--ink-on-solid` and `--ink-on-ground-inverse`
+ compute ~1.0-1.2:1 against the page grounds and are correctly excluded from
+ the ink set -- by definition they never sit on those grounds (they paint on
+ `--brand-gradient-solid` and on an inverted surface respectively).
+ `--brand-cyan-ink`, used as real text at chartsvg.py's value labels, clears
+ 4.80:1 worst case in light and 10.59:1 in dark. Hairline and glass tokens
+ are `rgba()` over a ground, not hex, so flat pair math cannot evaluate them
+ at all -- that is squarely OSV1-010's rendered half, not a gap here.
HONEST LIMIT, and why closing this does not close OSV1-010: flat token-pair
math models a swatch on a bare ground. The real surface puts glass panels
@@ -1467,7 +1532,9 @@
motion-preference trace in OSV1-010.
- id: OSV1-012
- title: calm is reported not celebrated, and empty widgets keep their slot -- no kit
+ title: >-
+ two empty widgets keep their slot and say nothing -- measured, not a
+ missing kit
contract:
file: contracts/operator-surface.v1.md
clause: Core 8
@@ -1475,7 +1542,7 @@
The calm state is stated plainly and never rendered as a triumphant zero. A widget with
nothing to show keeps its slot and says so in a sentence, so the page does not reflow
between calm and alarm.
- disposition: GAP
+ disposition: VIOLATION
work: work_item_pipeline-c1a
assertion:
kind: probe
@@ -1484,27 +1551,40 @@
PINNING ROW -- the probe asserts the CURRENT, KNOWN-WRONG shape on purpose;
a passing probe here is NOT conformance. Flip direction VIOLATION-MOVEMENT.
- GAP, REASON "KIT NOT BUILT". Core 8's check (`calm.keeps_slot`) is Tier A
- but is defined against an ALL-EMPTY FIXTURE compared to a populated one --
- "every widget region present on the populated fixture is present, each
- carries its empty sentence, and no numeral renders at hero scale outside
- the Core 1 hero". That is a two-render comparison this in-process kit
- cannot perform; `tests/conformance/operator_surface/test_tier_a.py` does
- not exist.
-
- WHAT THE SOURCE ALREADY CARRIES, measured 2026-09-04, and NOT credited as
- conformance -- the clause's claim is about region PRESENCE and reflow,
- which no source probe can see:
- widgets.py:423,433 the verdict headline is "All clear" (calm) /
- "Idle" -- a plain statement, not a triumphant zero.
- webapp.py:2275 "Nothing is waiting to be claimed in this queue
- right now." with the figure rendered as an em-dash
- (`—` plus
- "No ready items"), not a hero-scale `0`.
- chartsvg.py:295 "No activity in this window".
- webbrowse.py:498-503 "No items match this filter."
- Unknown until rendered: whether every widget region survives the empty
- render at all, and whether the page reflows between calm and alarm.
+ WAS GAP "KIT NOT BUILT"; NOW VIOLATION, MEASURED. The Tier-A kit exists and
+ performs the two-render comparison this clause defines, so the reason for
+ the red changed from "nobody has looked" to "we looked and it fails".
+
+ MEASURED 2026-09-05, L0 and L1 rendered against an all-empty project and
+ against the populated ALARM fixture, regions matched by section id and by
+ panel heading:
+ SLOTS SURVIVE every widget region on the populated render is present on
+ the empty one, on BOTH levels. That half of the clause
+ holds and the check says so.
+ SENTENCES DO NOT three regions keep their slot and say nothing at all:
+ L0 "Needs you -- ranked" (`widgets.render_attention_queue`
+ returns a bare `` when
+ `rows` is empty), L1 "Agents on "
+ (`widgets.render_agents_panel`, the same shape), and L1
+ "Status breakdown" (a legend of zeroes, no sentence).
+ NO HERO-SCALE NUMERAL nothing at or above the hero's own type size
+ (`--text-display-size`, resolved from the token block --
+ the floor is derived from the hero, never written down)
+ renders a numeral outside `#verdict-hero`. That limb
+ holds.
+
+ SO THE ROW IS RED ON ONE LIMB OF THREE, and the kit records which: the
+ two `calm.keeps_slot` tests are `xfail(strict=True)` naming THIS row. When
+ the three regions gain their sentence the tests XPASS, which FAILS the run
+ -- that failure is the instruction to flip this row and delete the markers
+ in the same change.
+
+ WHAT THE SOURCE ALREADY CARRIES, and still does: `widgets.py:423,433` the
+ verdict headline is "All clear" / "Idle" -- a plain statement, never a
+ triumphant zero; `webapp.py:2275` the ready queue says "Nothing is waiting
+ to be claimed in this queue right now." with the figure as an em-dash;
+ `chartsvg.py:295` "No activity in this window"; `webbrowse.py:498-503` "No
+ items match this filter." Four widgets get this right; three do not.
- id: OSV1-013
title: no front-end framework, bundler, template engine, or build step
@@ -1788,7 +1868,9 @@
(webpwa.py:121-122, webtrust.py:258-259); see OSV1-005.
- id: OSV1-021
- title: Conformance 2 (alarm unmissable, never colour-only) has no test file
+ title: >-
+ Conformance 2 (alarm unmissable, never colour-only) -- Tier-A half lands,
+ Tier-B hue half still has no test file
contract:
file: contracts/operator-surface.v1.md
clause: Conformance 2
@@ -1801,21 +1883,25 @@
kind: probe
ref: test_row_osv1_021
notes: >
- PINNING ROW -- the probe pins both named paths' ABSENCE; a passing probe
- here is NOT conformance. Flip direction VIOLATION-MOVEMENT.
+ PINNING ROW -- one half has landed, the other has not, so the probe now
+ pins the TIER-B half's absence rather than both. A passing probe here is
+ NOT conformance. Flip direction VIOLATION-MOVEMENT.
THE ONLY CONFORMANCE FIXTURE THAT SPANS BOTH TIERS, so it is owned by two
- items: the Tier-A half (accessible name on every status-bearing element)
- by work_item_pipeline-c1a, carried in this row's `work` ref; the Tier-B
- half (the alarm region's hue is `--alarm` or `--blocked`) by
- work_item_pipeline-qgo. Both must land before this row can go green; the
- single-ref schema records the first, and this note records the second so
- the second is not lost.
-
- MEASURED 2026-09-04 against 4aaee50: neither path exists. GOOD = the alarm
- region is present, its hue is `--alarm` or `--blocked`, and every
- status-bearing element also carries a word. BAD = a fixture whose status
- chips carry only a status class fails the accessible-name assertion.
+ items. Status 2026-09-05:
+ TIER-A HALF, LANDED (work_item_pipeline-c1a). "every status-bearing
+ element also carries a word" is implemented as `state.not_colour_only`
+ in `tests/conformance/operator_surface/test_tier_a.py`, run over
+ rendered L0/L1/L2 of the ALARM fixture, and it PASSES -- see OSV1-004,
+ which carries the measurement. Its bad half is this fixture's own named
+ specimen ("a fixture whose status chips carry only a status class") and
+ the same function reports it.
+ TIER-B HALF, NOT BUILT (work_item_pipeline-qgo). "the alarm region is
+ present, its hue is `--alarm` or `--blocked`" needs a real browser;
+ `tests/conformance/operator_surface/browser/test_tier_b.py` does not
+ exist.
+ Both must land before this row can go green; the single-ref schema records
+ the first, and this note records the second so the second is not lost.
- id: OSV1-022
title: Conformance 3 (body-swap survival) has no test file
@@ -1874,35 +1960,54 @@
fixture has a real chance of failing on first run -- which is the point.
- id: OSV1-024
- title: Conformance 5 (hero composition) has no test file
+ title: >-
+ Conformance 5 (hero composition) -- fixture exists, discriminates, and its
+ good half passes against the rebuilt hero
contract:
file: contracts/operator-surface.v1.md
clause: Conformance 5
quote: |
**Test location:** `tests/conformance/operator_surface/test_tier_a.py` (Core 1).
- disposition: GAP
+ disposition: CONFORMS
work: work_item_pipeline-c1a
assertion:
kind: probe
ref: test_row_osv1_024
notes: >
- PINNING ROW -- the probe pins the named path's ABSENCE; a passing probe
- here is NOT conformance. Flip direction VIOLATION-MOVEMENT.
-
- MEASURED 2026-09-04 against 4aaee50: `tests/conformance/` does not exist.
- GOOD = the hero region contains a velocity figure with its window stated
- and each of in flight, blocked, needs attention, and open/ready. BAD = a
- hero carrying only a verdict line, or a figure without the four counts,
- fails the assertion naming what is missing.
+ PINNING ROW -- the fixture exists and discriminates, but its GOOD half does
+ not pass, so the probe pins that deferral. A passing probe here is NOT
+ conformance. Flip direction VIOLATION-MOVEMENT.
- THE BAD HALF IS THE SHIPPED HERO. Measured in OSV1-001: webapp.py:4602
- renders exactly "a hero carrying only a verdict line". So this fixture's
- bad half needs no synthetic construction -- it can be built from
- `render_verdict_hero`'s pre-fix output, which is the strongest possible
- demonstration that the check discriminates.
+ MEASURED 2026-09-05. `tests/conformance/operator_surface/test_tier_a.py`
+ implements `hero.velocity_and_counts` at the location Conformance 5 names,
+ with three bad halves and one good half:
+ BAD, DEMONSTRATED "a hero carrying only a verdict line" -- and it needed
+ no synthetic construction, exactly as this row predicted at seed: the
+ bad fixture IS `widgets.render_verdict_hero`'s own output shape. Also
+ "a figure without the four counts" (reports all four missing, and does
+ NOT report the figure missing), and a third that keeps the check from
+ crediting a loose number and a status word in different sentences as a
+ presented count.
+ GOOD, DEFERRED run against L0 rendered from a populated fixture, it
+ FAILS: the hero states no `blocked` count and no `needs attention`
+ count. Those live in the KPI strip OUTSIDE the hero. So the good half
+ is `xfail(strict=True)` naming OSV1-001.
+
+ THIS ROW GOES GREEN WHEN OSV1-001 DOES, and not before: the fixture is the
+ fixture, but Conformance 5 is only demonstrated end-to-end once its good
+ half passes against a conforming hero. The probe therefore asserts both
+ facts -- the fixture is present with its pair, and OSV1-001 is still red --
+ so flipping either one alone fails loudly.
+ FLIPPED GAP -> CONFORMS 2026-09-05 at highway wave-1 integration (orchestrator): the hero lane closed OSV1-001
+ (L0 hero = velocity over a stated window + in-flight/blocked/needs-attention/open counts) and the kit's good half
+ `test_hero_velocity_and_counts` runs undeferred and PASSES on the real L0 (tier-a kit: 38 passed / 4 xfailed); the
+ three bad halves still fail as designed. Re-derived from the PASSING pair, not from the fixture's presence. Probe now
+ asserts the regression direction: good half stays undeferred and OSV1-001 stays CONFORMS.
- id: OSV1-025
- title: Conformance 6 (inline-style register) has no test file
+ title: >-
+ Conformance 6 (inline-style register) -- fixture exists and discriminates,
+ good half deferred against OSV1-005
contract:
file: contracts/operator-surface.v1.md
clause: Conformance 6
@@ -1914,25 +2019,37 @@
kind: probe
ref: test_row_osv1_025
notes: >
- PINNING ROW -- the probe pins the named path's ABSENCE; a passing probe
- here is NOT conformance. Flip direction VIOLATION-MOVEMENT.
+ PINNING ROW -- the fixture exists and discriminates, but its GOOD half does
+ not pass, so the probe pins that deferral. A passing probe here is NOT
+ conformance. Flip direction VIOLATION-MOVEMENT.
- MEASURED 2026-09-04 against 4aaee50: `tests/conformance/` does not exist.
- GOOD = zero inline `style=` attributes carry a literal colour, font, or
- size; every computed-geometry site is on the register. BAD = a file
- carrying `style="color:#D9A253"` is reported as a literal-colour violation,
- and a computed-geometry site absent from the register is reported as
- unregistered.
-
- NOTE THE OVERLAP, AND KEEP IT DELIBERATE: this ledger already runs that
- census in-process (OSV1-005 / OSV1-006) because the register lives in
- `ledger/` by ruling. The Tier-A kit's job is not to duplicate it but to
- read the SAME register, so there is one census and one source of the
- number. If the kit grows its own copy, the two will disagree and the
- disagreement will be silent.
+ MEASURED 2026-09-05. `tests/conformance/operator_surface/test_tier_a.py`
+ implements `visual.single_source` at the location Conformance 6 names:
+ BAD, DEMONSTRATED the contract's own named specimen, `style="color:#D9A253"`,
+ is classified LITERAL by the census; and an injected computed-geometry
+ site is reported as unregistered -- injected over the census's OWN
+ reader, so the real engine does the classifying and nothing on disk is
+ touched.
+ GOOD, DEFERRED 66 literal inline sites and 40 `", "", html, flags=re.DOTALL)
+ html = re.sub(r"", "", html, flags=re.DOTALL)
+ builder = _TreeBuilder()
+ builder.feed(html)
+ return builder.root
+
+
+def walk(node: Node):
+ for child in node.children:
+ yield child
+ yield from walk(child)
+
+
+def find_one(root: Node, *, node_id: str) -> Node | None:
+ for n in walk(root):
+ if n.attrs.get("id") == node_id:
+ return n
+ return None
+
+
+# ===========================================================================
+# Core 1 -- hero.velocity_and_counts
+#
+# "the rendered L0 hero region contains a velocity figure with its window
+# stated, and each of the four named counts."
+#
+# The four the clause names: in flight (held), blocked, needs attention, and
+# open/ready.
+# ===========================================================================
+
+#: Each count, with every word the surface could legitimately label it with.
+#: Named in the clause's own order.
+_HERO_COUNTS: tuple[tuple[str, tuple[str, ...]], ...] = (
+ ("in flight (held)", ("in flight", "in-flight", "held", "holding")),
+ ("blocked", ("blocked",)),
+ ("needs attention", ("needs attention", "needs you", "attention", "needs-you")),
+ ("open/ready", ("open", "ready", "unclaimed")),
+)
+
+#: A throughput word -- the figure itself must be one of these, not any number.
+_THROUGHPUT_WORDS = ("resolved", "velocity", "throughput", "completed", "closed", "burn")
+
+#: A stated window. `24h`/`7d`/`30d`, "last 7 days", "per day", "/day".
+_WINDOW = re.compile(
+ r"(\b\d+\s*(h|hr|hrs|hours?|d|days?|w|weeks?)\b|\bper day\b|/day\b|\blast \d+\b|\btoday\b)",
+ re.IGNORECASE,
+)
+_HAS_DIGIT = re.compile(r"\d")
+
+
+def _leaf_phrases(region: Node, *, max_len: int = 140) -> list[str]:
+ """Short text runs in the region -- a count and its label read together.
+
+ Bounded, because "the hero contains the word `blocked` somewhere and the
+ digit `3` somewhere" is not a count: the clause asks for the counts to be
+ PRESENTED, so the number and its label must sit in one readable run.
+ """
+ out: list[str] = []
+ for n in walk(region):
+ txt = " ".join(n.text().split())
+ if txt and len(txt) <= max_len:
+ out.append(txt)
+ return out
+
+
+def check_hero_velocity_and_counts(l0_html: str) -> list[str]:
+ """Core 1's `hero.velocity_and_counts`, against a rendered L0."""
+ root = parse_html(l0_html)
+ hero = find_one(root, node_id="verdict-hero")
+ if hero is None:
+ return ["no L0 hero region (`#verdict-hero`) in the rendered page at all"]
+
+ phrases = _leaf_phrases(hero)
+ problems: list[str] = []
+
+ velocity = [
+ p
+ for p in phrases
+ if _HAS_DIGIT.search(p)
+ and any(w in p.lower() for w in _THROUGHPUT_WORDS)
+ and _WINDOW.search(p)
+ ]
+ if not velocity:
+ problems.append(
+ "no velocity figure with its window stated -- the hero carries no run "
+ f"pairing a number, a throughput word {_THROUGHPUT_WORDS} and a window"
+ )
+
+ for label, words in _HERO_COUNTS:
+ if not any(_HAS_DIGIT.search(p) and any(w in p.lower() for w in words) for p in phrases):
+ problems.append(f"the hero states no `{label}` count")
+ return problems
+
+
+def test_hero_velocity_and_counts_bad_half_verdict_line_only() -> None:
+ """Conformance 5's bad half, verbatim: "a hero carrying only a verdict line".
+
+ Not synthesised from nothing -- this IS `widgets.render_verdict_hero`'s
+ own output shape (OSV1-024's notes: "the bad half needs no synthetic
+ construction"), rendered around the calm verdict the shipped L0 emits.
+ """
+ bad = """
+
Environment verdict · 21 projects
+
All clear
+
Nothing stuck, nothing waiting past its TTL.
+
"""
+ problems = check_hero_velocity_and_counts(bad)
+ assert problems, "the check passed a hero carrying only a verdict line"
+ assert any("velocity figure" in p for p in problems)
+ for label, _ in _HERO_COUNTS:
+ assert any(label in p for p in problems), f"the check did not name `{label}` as missing"
+
+
+def test_hero_velocity_and_counts_bad_half_figure_without_the_counts() -> None:
+ """Conformance 5's other bad half: "a figure without the four counts"."""
+ bad = """
+
14 resolved in the last 24h
+
"""
+ problems = check_hero_velocity_and_counts(bad)
+ assert not any("velocity figure" in p for p in problems), (
+ "the figure IS present with its window -- the check must not report it missing"
+ )
+ assert len(problems) == len(_HERO_COUNTS), (
+ f"expected all four counts reported missing, got {problems}"
+ )
+
+
+def test_hero_velocity_and_counts_bad_half_a_loose_number_is_not_a_count() -> None:
+ """A number somewhere and a word somewhere else is not a presented count."""
+ bad = """
+
All clear
+
7 resolved in the last 24h.
+
Nothing is blocked, and nothing needs attention, and
+ the ready queue and everything in flight are described here at length
+ in a sentence that never actually puts a number beside any of them.
+
"""
+ problems = check_hero_velocity_and_counts(bad)
+ assert any("blocked" in p for p in problems), (
+ "a status word in a long prose run with no adjacent number was credited as a count"
+ )
+
+
+def test_hero_velocity_and_counts(calm_dataset) -> None:
+ """Conformance 5's GOOD half: L0 rendered against a populated fixture."""
+ problems = check_hero_velocity_and_counts(calm_dataset.l0)
+ assert not problems, "Core 1 (`hero.velocity_and_counts`):\n " + "\n ".join(problems)
+
+
+# ===========================================================================
+# Core 3 -- state.not_colour_only
+#
+# "every status-bearing element in the rendered L0/L1/L2 fixtures has
+# non-empty text or an accessible name, not merely a status class."
+# ===========================================================================
+
+#: The status vocabulary, read out of the app's OWN maps rather than written
+#: down here: `webbrowse._ITEM_STATUS_CHIP_LABEL`'s keys (the item statuses),
+#: `widgets._HERO_ICON`'s keys (the verdict states) and
+#: `webapp._ATTENTION_SEVERITY`'s severities. A status the app grows and this
+#: kit does not know about would otherwise be silently unchecked.
+_STATUS_CLASS_PREFIXES = ("st", "is", "sev", "tab", "status")
+
+
+def _dict_keys_in(path: Path, name: str) -> set[str]:
+ """The string keys of a module-level `NAME: ... = {...}` dict literal."""
+ tree = ast.parse(S.read(path))
+ for node in ast.walk(tree):
+ targets: list[ast.expr] = []
+ if isinstance(node, ast.AnnAssign):
+ targets = [node.target]
+ elif isinstance(node, ast.Assign):
+ targets = list(node.targets)
+ if not any(isinstance(t, ast.Name) and t.id == name for t in targets):
+ continue
+ value = node.value if isinstance(node, ast.AnnAssign | ast.Assign) else None
+ if isinstance(value, ast.Dict):
+ return {
+ k.value
+ for k in value.keys
+ if isinstance(k, ast.Constant) and isinstance(k.value, str)
+ }
+ raise AssertionError(f"{path.name}: no module-level dict literal named {name!r}")
+
+
+def _dict_values_in(path: Path, name: str) -> set[str]:
+ tree = ast.parse(S.read(path))
+ for node in ast.walk(tree):
+ targets = (
+ [node.target]
+ if isinstance(node, ast.AnnAssign)
+ else list(node.targets)
+ if isinstance(node, ast.Assign)
+ else []
+ )
+ if not any(isinstance(t, ast.Name) and t.id == name for t in targets):
+ continue
+ value = node.value if isinstance(node, ast.AnnAssign | ast.Assign) else None
+ if isinstance(value, ast.Dict):
+ return {
+ v.value
+ for v in value.values
+ if isinstance(v, ast.Constant) and isinstance(v.value, str)
+ }
+ raise AssertionError(f"{path.name}: no module-level dict literal named {name!r}")
+
+
+def status_vocabulary() -> set[str]:
+ """Every word this surface uses to name a state, from its own source."""
+ words = set(_dict_keys_in(S.WEBBROWSE, "_ITEM_STATUS_CHIP_LABEL"))
+ words |= {v.lower() for v in _dict_values_in(S.WEBBROWSE, "_ITEM_STATUS_CHIP_LABEL")}
+ words |= set(_dict_keys_in(S.WIDGETS, "_HERO_ICON"))
+ # The status hues themselves -- `--alarm` -> `alarm` -- so `is-alarm` and
+ # `sev-blocked` are recognised even though no dict literal names them.
+ words |= {t.lstrip("-") for t in S.STATUS_TOKENS}
+ return {w for w in words if w}
+
+
+def status_classes(rendered: set[str]) -> set[str]:
+ """Which of a page's classes are STATUS classes.
+
+ A class is status-bearing when it is a status word, or a status word under
+ one of this surface's status-class prefixes (`st-blocked`, `is-alarm`,
+ `sev-cr`, `tab-blocked`). The chip vocabulary is taken from
+ `_ITEM_STATUS_CHIP_CLASS` directly as well, so a chip class that does not
+ follow the prefix convention is still caught.
+ """
+ vocab = status_vocabulary()
+ chips = _dict_values_in(S.WEBBROWSE, "_ITEM_STATUS_CHIP_CLASS")
+ out = {c for c in rendered if c in chips}
+ for c in rendered:
+ if c in vocab:
+ out.add(c)
+ continue
+ head, _, tail = c.partition("-")
+ if head in _STATUS_CLASS_PREFIXES and tail in vocab:
+ out.add(c)
+ return out
+
+
+def check_state_not_colour_only(html: str, *, page: str) -> list[str]:
+ """Core 3's `state.not_colour_only`, against one rendered page."""
+ root = parse_html(html)
+ nodes = list(walk(root))
+ rendered_classes = {c for n in nodes for c in n.classes}
+ status = status_classes(rendered_classes)
+ if not status:
+ return [f"{page}: no status-bearing element on the page at all -- nothing was checked"]
+
+ problems: list[str] = []
+ for n in nodes:
+ if not (n.classes & status):
+ continue
+ if n.accessible_name():
+ continue
+ # A decorative mark INSIDE a status-bearing element that is itself
+ # named carries no state of its own -- the state is already in that
+ # ancestor's words. Colour is redundant there, which is the clause.
+ if any(a.classes & status and a.accessible_name() for a in n.ancestors()):
+ continue
+ problems.append(
+ f"{page}: {n.describe()} carries status class(es) "
+ f"{sorted(n.classes & status)} and NO text or accessible name"
+ )
+ return problems
+
+
+def test_state_not_colour_only_bad_half_chip_with_only_a_class() -> None:
+ """Conformance 2's bad half, verbatim: "a fixture whose status chips carry
+ only a status class fails the accessible-name assertion"."""
+ bad = '
'
+ problems = check_state_not_colour_only(bad, page="BAD")
+ assert problems, "a status chip carrying only a class was accepted"
+ assert "st-blocked" in problems[0]
+
+
+def test_state_not_colour_only_bad_half_an_accessible_name_is_enough() -> None:
+ """The other direction: a chip with no text but a real name PASSES.
+
+ Without this the check would be asserting "has text", not the clause's
+ "non-empty text OR an accessible name" -- and would fail the surface for
+ an icon-only control that is correctly labelled.
+ """
+ good = ''
+ assert not check_state_not_colour_only(good, page="GOOD")
+
+
+def test_state_not_colour_only_bad_half_an_ancestors_name_does_not_travel_sideways() -> None:
+ """A named status ancestor excuses only its own decorative descendants."""
+ bad = (
+ # A decorative, unlabelled mark INSIDE a named status control: excused.
+ 'Blocked 3'
+ # A status chip standing on its own with nothing at all: reported.
+ ''
+ )
+ problems = check_state_not_colour_only(bad, page="BAD")
+ assert len(problems) == 1 and "st-held" in problems[0], problems
+
+
+@pytest.mark.parametrize("level", ["l0", "l1", "l2"])
+def test_state_not_colour_only(alarm_dataset, level: str) -> None:
+ """Conformance 2's Tier-A GOOD half, on all three IA levels.
+
+ Run against the ALARM dataset, which is Conformance 2's own scenario --
+ "the same fixture with one item held past TTL and one blocked" -- so every
+ status chip the surface can render is actually on the page.
+ """
+ if level == "l2":
+ html = alarm_dataset.l2(alarm_dataset.item_ids[1]) # the blocked item
+ else:
+ html = getattr(alarm_dataset, level)
+ problems = check_state_not_colour_only(html, page=f"{alarm_dataset.label} {level.upper()}")
+ assert not problems, "Core 3 (`state.not_colour_only`):\n " + "\n ".join(problems)
+
+
+# ===========================================================================
+# Core 4 -- visual.single_source
+#
+# "zero inline `style=` attributes carrying a literal colour, font, or size
+# anywhere in `src/`; every inline `style=` site carrying computed geometry
+# appears on the ledger's exemption register; and zero literal colour/font/
+# size declarations in any `