real voluptuous 0.16.0 implements ``Marker.__eq__`` as ``self.schema ==
other`` — a field-name comparison with no class check, so
``Optional("x") == Required("x")`` is True (verified against the library
source, not just the audit note). The mirror compared class + field, which
kept two dict entries for one field: a ``Required(field, default=...)`` after
``Optional(field)`` LOOKED like it applied the default, while real voluptuous
keeps the first (defaultless) key object and silently drops it — the exact
t33 F-A failure mode the mirror exists to catch, i.e. the harness could mask
the bug it was built to see.
``Marker.__eq__`` is now the library's comparison and the contract tests gained
both pins: field-only equality (with equal hashes) and the mixed-marker
re-declaration that used to be masked. Reverting only ``__eq__`` makes those
two fail, which is the red proof recorded for t35.
Verified: uvx --with pytest-asyncio pytest tests -q → 276 passed, 1 skipped;
uvx ruff check custom_components tests → clean.
One home for the user-reported regressions, all driven end to end against the
scoped stub harness:
- TestVoluptuousMirrorContract pins tests/voluptuous_mirror.py itself (a
default on the declaration is visible; a later re-declaration cannot add one)
so the harness cannot silently go blind again.
- TestDiscoveryPrefill: the discovered address is the default of BOTH host
keys, the port default is 5555, the step announces "Discovered Shield at
<host>", a manual/seed flow claims no discovery, and the error re-render
keeps the prefill. Reads the rendered schema, not the stored attribute.
- TestNoDeadEndPairing: skip protocol → entry created (passive), skip ADB →
entry created (ADB intent kept for the Pair ADB button) with the real
async_setup_entry accepting both entries (no ConfigEntryNotReady), skip ADB
routes on to the protocol step, both normal pair paths still create the
entry, a host typed on a pairing form is accepted in place, and a missing
androidtvremote2 reports protocol_unavailable instead of raising.
- TestCopyContract: no copy points at "the previous step", the no_host errors
name the field and the discovery prefill, every error/abort key raised by
config_flow.py exists in both copy files, and every field rendered by the
user/adb_pair/protocol_pair/options forms has a label.
- TestStringsTranslationsParity: strings.json and translations/en.json expose
the same key tree.
- TestPassiveSetupNeverDemandsReadiness: async_setup_entry raises nothing.
Verified: uvx --with pytest-asyncio pytest tests -q → 274 passed, 1 skipped;
uvx --with pytest-asyncio --with androidtvremote2 pytest tests -q → 275 passed;
uvx ruff check custom_components tests → clean.