highway(operator-surface) wave 2: Tier-B browser conformance kit + Core 10 fixes (bounded L1 query, theme persists) + integration - #83
Merged
Conversation
…dg3) Two Core 10 anti-goals of contracts/operator-surface.v1.md, closed together because they are the same promise from two directions: a view must not ask for an unbounded read, and a view must not hold state that dies on refresh. OSV1-015 -- the unbounded query (work_item_pipeline-8vv) `project_view` called `bd.list(..., limit=0)` -- bd's own "unlimited" -- on a page that re-renders every 20 seconds, so every open tab re-materialised the whole item set three times a minute. It now passes `_L1_ITEM_QUERY_LIMIT + 1` (500, the repo's existing `LIST_MAX_LIMIT` ceiling, and exactly ten of this view's own pages). The `+ 1` is the one-past-the-window probe: it establishes whether more rows exist as a fact rather than inferring it from a full window. A bound is a truncation, so the view confesses it: `_truncation_note_html` renders "Showing 50 of 500+ items - read capped at 500 ..." when the ceiling binds, and never dresses a bounded window as a measured total. The L2 detail page's `bd.activity(item.id)` inherited its bound from the seam's default; it now states it (`limit=A.HISTORY_LIMIT`). Audit of every adapter read reachable from a GET handler: 4 calls, all now explicit. OSV1-016 -- the theme that died on refresh (work_item_pipeline-dg3) `wtSetTheme` set an attribute and remembered nothing, so a chosen Light came back Dark on the next load. It now persists to `localStorage` under `webtheme.THEME_STORAGE_KEY` -- one declaration, shared by the writer and the reader -- and `webtheme.theme_boot_js()` resolves it in `<head>`, before the body paints, so there is no flash. Stored choice first, then `prefers-color-scheme`, then the server's `data-theme="dark"` default, which the resolver only ever REPLACES (PR #55 stays fixed). Apply and persist are split: `wtApplyTheme` never writes, so the sync call that re-derives the toggle's `aria-pressed` after each 20s body swap cannot freeze a first visit's OS preference into a choice nobody made. Tests tests/unit/test_view_query_bounds.py -- static audit of every bounded adapter read reachable from a GET handler; confirmed red against `limit=0`, against a removed `limit=`, and against the inherited-default activity call. tests/unit/test_theme_persistence.py -- executes the emitted scripts under node against a fake DOM and does the real round trip (load, click Light, reload, assert Light); confirmed red against removing either half. Plus L1 route tests for the cap and its absence. Ledger OSV1-015 and OSV1-016 flipped VIOLATION -> CONFORMS with evidence, probes retargeted from pins to invariants in the same change, mutations inverted to the regression direction (+1 new one). `pytest ledger/checks` 60 passed; `make ledger-mutate` 54/54 proven. Cross-lane, unavoidable, flagged for the integrator: OSV1-031's red-row tally 10 -> 8, and the line-anchored specimens in OSV1-005/-006 re-anchored where this change shifted them (same specimens, new line numbers).
…rtifact-backed, discriminating (Freeze 2/3/4)
The Tier-B half of `contracts/operator-surface.v1.md` now exists, runs a
pinned chromium against a live app over isolated fixture data, emits JSON
artifacts the tests re-check themselves, and runs as its own CI tier.
WHAT LANDED
tests/conformance/operator_surface/browser/test_tier_b.py
the file the contract names by path in Conformance 1-4 and Freeze 2.
Four checks under their contract names: `calm.zero_alarm_pixels`,
`state.not_colour_only` (rendered half), `swap.survives`,
`perception.floors`. 52 pass, 35 xfail(strict) against named ledger rows,
0 fail; ~105s end to end.
_png.py dependency-free PNG decode + colour histogram, so a pixel
sweep is a number this repo computed
_probe.py the in-page JS that measures contrast, target boxes, overflow,
motion and live regions, plus the pure-Python re-checks
_artifacts.py the artifact envelope, and the committed run summary
conftest.py app on 127.0.0.1:0 over the inherited isolated dolt server,
a separate workspace per scenario, pinned chromium
THE RULE THE KIT RUNS UNDER (Freeze 3): measure -> write -> read back ->
assert. No assertion rests on a value that only lived in a local variable,
and none rests on a screenshot. Screenshots are saved as evidence for a
human's Freeze 8 look and nothing reads them.
EVERY FIXTURE DISCRIMINATES (Freeze 4) -- eight bad halves, all RUN:
an injected --alarm chip, the contract's own retired #D9A253 region, a
genuinely-blocked fixture, status chips stripped to a class, a naive
whole-body innerHTML replacement, the same with a forced reflow, a 900px
element at 430px, and the recorded --ink-quiet/--ground pair (with a
dark-mode control, so a probe that always said "below floor" would fail).
WHAT THE BROWSER ACTUALLY FOUND -- chromium 148.0.7778.0 / playwright 1.60.0
Core 2 a calm L1 paints 97 --blocked pixels with nothing blocked
(legend swatch, live dot, danger-button border). L0 is clean.
Core 6 one of four survivals holds. Scroll survives; the open <details>
does not (no <details> on this surface carries an id, so
restoreState has zero targets); the pause CONTROL does not; and
there is no live region to preserve at all.
Core 7 L0 text contrast clean, L1/L2 not (.status-chip.st-resolved reads
3.13:1 dark / 2.26:1 light); 26 of 35 interactive controls on L0
under 44px, including the pause control itself at 26x26; control
borders and icon strokes below 3:1. Reduced motion PASSES.
TWO CONTRACT WORDINGS MEASURED NON-DISCRIMINATING, recorded not reinterpreted:
Conformance 4's `scrollWidth == clientWidth` cannot fire while html/body carry
`overflow-x: clip` (a 900px element at 430px moves it not at all), so the kit
emits an element-level reading too; and Conformance 3's literal bad half does
not lose the scroll offset on chromium 148, so a reflow variant carries that
half.
LEDGER -- rows re-derived from the emitted numbers, never from a file
appearing. OSV1-003/-008/-010 GAP -> VIOLATION (now measured, not unmeasured);
OSV1-020/-022/-023/-028/-029 GAP -> CONFORMS; OSV1-021 and -030 stay GAP for
their Tier-A halves. Every probe re-reads LAST_RUN.json, the kit's committed
run summary, so the ledger checks browser-produced numbers for itself instead
of trusting the browser tier's green. `pytest ledger/checks -q` 60 passed;
`make ledger-mutate` 56/56 proven.
WIRING: `make playwright-install`, `make test-conformance-b`, and a CI step
"Tier 7 -- operator-surface conformance (Tier B, browser)" that installs
chromium and uploads the artifacts. Deselected everywhere else by
`-m "not tier_b"` in addopts -- deselected, not --ignore'd, so a kit that
stops importing fails the fast tiers loudly.
OUT OF SCOPE, NAMED: `test_row_osv1_027`'s pin (Freeze 1, another lane's row)
was NARROWED, not moved -- it asserted no `tests/conformance` path appears in
the Makefile/CI at all, which the Tier-B wiring now legitimately trips. The
Tier-B path is excluded before the check, leaving its original question
(is Tier-A wiring landing?) intact. Disposition unchanged.
…Tier-B kit A second full `make test-conformance-b` from a clean artifact directory: 52 passed, 35 xfailed, 0 failed. Every number the ledger asserts on came back byte-identical -- the calm sweep's 97 --blocked pixels on L1, L0's clean 0/0, L1's 3-dark/5-light text failures, L0's 26-of-35 undersized controls, both bad halves' discrimination. The ONLY drift between the two runs is the `--watch` bucket in light mode (5402 -> 5239 and friends), which nothing asserts on: Core 2 says only `--alarm` and `--blocked` carry status meaning, so `--watch` is swept and recorded for context and deliberately not scored. The drift is antialiasing against a slightly different sub-pixel layout between runs, and it is exactly the reason a status-hue sweep is scored on the two reserved hues rather than on "how much colour is on the page".
…1-006 register re-measured on the merged tree, _mo031 anchor moved off the now-green OSV1-015
…FORMS with both halves landed; Freeze 4 re-derived VIOLATION from a run of the merged tree; harness mutations merged; OSV1-031 re-counted
Six conflicted files resolved as a UNION, never a pick-a-side:
* Makefile -- .PHONY is the union of both target lists; both target blocks
kept (test-conformance-a in `test`'s reach, playwright-install and
test-conformance-b deliberately outside it). No duplicate targets.
* tests/conformance/{,operator_surface/}__init__.py -- the Tier-A lane's
longer docstrings, each folding in one sentence placing Tier B in
`browser/` as its own `tier_b`-marked tier.
* mutation_harness.py -- both lanes' mutation functions, and the Mutation
list merged rather than chosen. Every "the OTHER tier's kit file appears"
pin-direction mutation is spent (both kits exist now) and was replaced by
the regression- or fix-direction mutation each lane wrote. Two mutations
were dropped because the direction they push no longer exists on the
merged probe, each proven dead by the harness itself rather than assumed:
_mo008_swap_restores_the_pause_flag (the merged OSV1-008 probe reads the
Tier-B run summary, so the source-shape counterfactual "probe still PASSED
under the counterfactual") and both _mo_tier_*_kit_appears helpers.
* test_operator_rows.py -- imports keep `ast` AND `json`; OSV1-009 keeps the
contrast lane's retargeted CONFORMS probe; OSV1-027 keeps the tier-b
lane's narrowing (the Tier-B path is stripped before the Tier-A wiring is
checked) turned round to the CONFORMS direction it now needs.
* rows.yaml -- both lanes' dated LANDED paragraphs kept on every row that
carried one; no pinning-row sentence left on a CONFORMS row.
Rows re-derived, each from evidence rather than from a file appearing:
* OSV1-021 (Conformance 2) GAP -> CONFORMS. The only fixture spanning both
tiers; each lane pinned the other half's absence and both halves are now
present. Probe asserts both, in the CONFORMS direction: the Tier-A check
exists, ships its bad half and is NOT deferred, and the Tier-B hue and
wordless readings hold. Red again if either half stops holding.
* OSV1-030 (Freeze 4) GAP -> VIOLATION, NOT the CONFORMS this integration
set out to write. Both kits landed, but `make test-conformance-b` on the
MERGED tree measures Conformance 4's contrast bad half at 5.36:1 in light
-- above the 4.5:1 floor -- where the committed run recorded 3.09:1. The
bad half injects the LIVE `--ink-quiet`/`--ground` pair, and the contrast
lane closed OSV1-009 in wave 1 by moving that token, so the specimen the
clause names no longer exists here. Neither lane could see it: each
measured against a base without the other's change. 13 of the 14 fixture
arms still demonstrate; this row is red for the fourteenth.
* OSV1-031 (Freeze 5) re-counted: still FIVE red Core-carrying rows, so the
pin does not move -- but all five now read VIOLATION and none GAP, because
tier-b-kit re-derived Core 2, 6 and 7's browser halves from a real run.
Neither OSV1-021 nor OSV1-030 is Core-carrying, so neither moves it.
Verified on this tree: pytest ledger/checks 60 passed; make ledger-mutate
proven 58/58 (15 pinning across 11 pinning probes); ruff clean; pyright 0
errors. Recorded in OSV1-030's notes rather than absorbed: three further
merged-tree movements (reduced motion 0 -> 6 running animations, live
regions 0 -> 1, L0 controls 35 -> 34) that need the Tier-B run re-recorded
by a lane, and two Tier-A bad halves that have failed since 1713b30 because
the core10 lane's fixes removed the shipped code they used as a specimen.
…mance 4; Tier-B run re-recorded on the merged tree; OSV1-003/008/010/011/023/030 re-derived (reduced-motion is a measured settling transient, not a violation)
Three fixtures stopped naming a defect when the wave-2 lanes met, because each
borrowed the SHIPPED code as its bad specimen and the product was fixed under
it. All three now fabricate their own bad input:
Tier A, Core 10 `unbounded_view_queries` / `unpersisted_view_state` take an
optional {module: source} map; the bad halves feed a
fabricated view (one `limit=0` read, one with no limit) and
a fabricated script module (a theme setter that persists
nothing beside a density setter that does), each with a
fixed twin as its control. The good halves still assert the
real tree.
Tier B, C4 `INJECT_BELOW_FLOOR_PAIR_JS` injects a LITERAL below-floor
pair (#9aa3b2 on #eef2fb, 2.27:1) plus a LITERAL control
(#1b2430, 13.96:1), asserted in opposite directions in BOTH
themes. It used to inject the live --ink-quiet/--ground
tokens and measured 5.36:1 once the contrast lane moved the
token.
LAST_RUN.json re-recorded on this tree (chromium 148.0.7778.0 / playwright
1.60.0); three consecutive runs agree on every field the ledger asserts. Rows
re-derived from the new numbers: OSV1-003 (L0 sweep area 2 850 560 -> 2 813 440
px, verdicts unchanged), OSV1-008 (live regions before the swap 0 -> 1 on L0 --
the rebuilt hero's role=status -- and it does NOT survive; L1 still 0),
OSV1-010 (L0 controls 35 -> 34, L1 light text 5 -> 4, non-text 17/82 -> 16/79),
OSV1-023 (contrast arm re-derived onto the literal pair + control),
OSV1-030 (VIOLATION -> CONFORMS: all fourteen fixture arms run and bite).
OSV1-011 stays CONFORMS, re-derived rather than flipped. The 6 running
animations the integration brief reported as a product defect are a SETTLING
TRANSIENT, measured: they are `background-color` CSSTransitions of
--duration-fast (120ms) created while the page loads, and the kit sampled
exactly 120ms after applying the preference -- racing the animation it was
measuring, which is why a different 1-3 of 9 scenarios failed on every run. A
direct 0/120/300/700/1500/3000ms sweep caught one first sample at currentTime
116.67 of 120 and zero from 120ms on, everywhere. The kit now polls until the
page is quiescent (`_settled_motion`) and records the instant-of-change
reading beside it as `motion_at_preference_change`; MOTION_JS names each
animation's target path, property and currentTime. OSV1-011's probe re-reads
the settled count for all 18 renders (0 everywhere) instead of resting on the
static one-@media-block check alone.
Gates: ruff check + format clean; pyright 0 errors; pytest ledger/checks 60
passed; make ledger-mutate 60/60 proven, none unproven; test-conformance-a 38
passed / 4 xfailed / 0 failed; test-conformance-b 52 passed / 35 xfailed / 0
failed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two more lanes of the
hw-operator-surfacehighway plus the integration work their union required.tests/conformance/operator_surface/browser/— real-browser conformance kit: pinned playwright 1.60.0 / chromium 148.0.7778.0, app on an ephemeral loopback port over isolated fixture data, every assertion reads back a JSON artifact (pixel sweeps, computed contrast, bounding boxes, post-swap DOM, motion trace) — never a "looks right" verdict;make playwright-install+make test-conformance-b(opt-in locally) + CI Tier 7; a durableLAST_RUN.jsonthe ledger probes re-read--blockedpx on a calm page; the swap drops the live region; 4 light-mode text pairs fail rendered); 020/022/023 CONFORMSLIST_MAX_LIMIT+1 one-past-the-window probe; the view CONFESSES the bound); every adapter read reachable from a GET handler passes an explicit limit; the theme choice persists (localStorageunderwebtheme.THEME_STORAGE_KEY, applied in<head>before first paint,prefers-color-schemewhen nothing stored)Integration (orchestrator commits):
LAST_RUN.jsonre-recorded on the merged tree (3 runs, byte-identical on every asserted field). A suspected "6 animations run underprefers-reduced-motion" turned out to be the kit racing a 120 ms transition it had just triggered — fixed in the kit (poll to quiescence), not filed against the product; OSV1-011 stays CONFORMS with a browser half (0 in all 18 renders).Verified on the union:
pytest ledger/checks60 ·make ledger-mutate60/60 · Tier-A 38 passed / 4 xfailed / 0 failed · Tier-B 52 passed / 35 xfailed / 0 failed (×3) · pyright 0 · ruff clean · unit+integration 1325 passed (2 port-pair flakes pass in isolation). OSV1 tally → 23 CONFORMS / 5 VIOLATION / 5 GAP / 3 N-A. The inline-style migration (np3) follows.🤖 Generated with Amplifier