phase: 06_sharer_quality_presets
Build and Push Containers / test (push) Successful in 1m12s
Build and Push Containers / build-and-push-app (push) Successful in 9s

**Phase 06 — final verification pass: 100% green.**

- **Verified (all 6 tasks complete in working tree):** `#quality` select + `PRESETS` table; preset-driven capture request + `contentHint`; per-leg `legCap()`/`degradation` at both call sites; live `applyQuality()` with Overconstrained fallback + republish; `q` key cycle; `#stat-quality`/`#stat-codec` readouts; full e2e matrix (requests, committed params ×3, zero-cap, mid-share switch, unrescalable device, late-joiner first-offer, readout, `q`); realdisplay delivered-pixels `light` case. `test_sender_fidelity.py` **untouched and green** (regression canary).
- **Gates:** `uv run ruff check . && uv run ruff format --check .` → clean (32 files); `uv run pyright` → 0 errors; `uv run pytest` → **284 passed, 5 skipped (realdisplay-gated), coverage 95%** (93s); `MIRROR_REALDISPLAY=1 uv run pytest -m realdisplay` → **4 passed, 1 skipped** (no audio source on host — documented platform condition).
- **Completion criteria:** all 11 ✓ — sharp default reproduces old request; light ≤960×600@15fps/motion/round(cap×0.35)/maintain-framerate with moving viewer frames; mid-share re-prices with `peers.size` unchanged, no renegotiation, roster matches `getSettings()`; refused-rescale toasts "next share"; `q` cycles + toasts, text-field guard holds; readout exact + codec shape, both reset to `—` idle; realdisplay: light decoded ≤990px (measured 320×200), sharp clears `SHARP_FLOOR_PX`; no new env/wire/Python/asset; suite 100% green, coverage >90%.
- **Docs:** README.md reviewed in full against code — Quality table, `q` key, env-var table, routes (`/share`), kiosk commands, key table, doc paths all consistent; **no fixes needed**. AGENTS.md — verified, no stale statements, no changes. PLAN.md untouched (diff = 0).
- **Reported (per phase, not edited):** PLAN.md §6 line 204 still says "per-leg `maxBitrate` cap (default **12 Mbit/s**)" — code has defaulted to **25 Mbit/s** since phase 02; needs a user-approved one-line amendment.
- **Next pending phase:** none — 06 is the last phase in `todo/`; the roadmap is complete.
This commit is contained in:
2026-11-02 22:07:17 -05:00
parent f51d0fe9ae
commit 3f93481c54
44 changed files with 2107 additions and 54 deletions
+38 -6
View File
@@ -177,15 +177,47 @@ class TestClientScripts:
"a different bitrate silently"
)
def test_the_quality_options_are_the_three_presets(self):
"""`#quality` (mirror.html) and `PRESETS` (share.js) are one list in two places.
If the option values drift from the table keys, a preset the panel offers has
no row (or an orphan row the panel can never select), and `currentPreset()`
falls back to `sharp` instead of noticing: the sharer gets a wall they did not
ask for and nothing fails. One list, two places, one test that notices (the
same shape as the bitrate-default test)."""
html = (STATIC / "mirror.html").read_text()
select = re.search(r'<select id="quality"[^>]*>.*?</select>', html, re.S)
assert select, "mirror.html must render a #quality select"
options = set(re.findall(r'value="([A-Za-z0-9_-]+)"', select.group(0)))
source = (STATIC / "share.js").read_text()
table = re.search(r"const PRESETS = Object\.freeze\(\{(.*?)\}\);", source, re.S)
assert table, "share.js must define the PRESETS table"
# Top-level keys sit two spaces in; the fields inside a preset sit four
# spaces in, so anchoring on exactly two spaces selects the keys only.
keys = set(re.findall(r"^ ([a-z]+): \{$", table.group(1), re.M))
expected = {"sharp", "balanced", "light"}
assert options == expected, f"#quality offers {sorted(options)}, not {sorted(expected)}"
assert keys == expected, f"PRESETS keys are {sorted(keys)}, not {sorted(expected)}"
assert options == keys, "the select offers presets the table cannot resolve"
def test_sender_quality_is_reapplied_on_negotiation_and_connection(self):
"""`setParameters` is per-negotiation: a re-offer (a surface switch,
a viewer that re-joined) resets the encodings. The cap must therefore
be re-applied after `setLocalDescription` *and* when the leg becomes
`connected`. Both call sites are asserted so a future edit cannot drop
one and silently soften the wall."""
a viewer that re-joined) resets the encodings. The preset's cap and
degradation preference must therefore be re-applied after
`setLocalDescription` *and* when the leg becomes `connected`. Both
call sites are asserted so a future edit cannot drop one and silently
soften the wall. The preference itself stays a single, named
decision — the PRESETS table's `degradation` field, read at call
time — so a hardcoded literal at the call site would be a second,
drifting decision."""
source = (STATIC / "share.js").read_text()
assert source.count('"maintain-resolution"') == 1, (
"the degradation preference must be a single, named decision"
assert re.search(r'degradationPreference\s*=\s*"', source) is None, (
"a hardcoded degradation literal at a call site is a second decision"
)
assert "params.degradationPreference = PRESETS[currentPreset()].degradation" in source, (
"the preference is not read from the PRESETS table at call time"
)
assert "async function applySenderQuality" in source