# 06 — Consolidated Work-Item Backlog This document is the executable backlog for the contribution program. It consolidates every gap identified in the twelve per-integration audits (`docs/audits/*.md`) into discrete, PR-sized work items with acceptance criteria, dependency tags, sequencing order, and a cross-integration schedule. It is the single source of truth for "what we do next" — the audits explain *why*, this document defines *what* and *in what order*. All items inherit the global acceptance criteria in `docs/05-acceptance-criteria.md` (CI green, hassfest/mypy clean, codeowner review, PR ≤ ~500 changed LOC, no breaking changes without deprecation period). The criteria listed per item below are the item-specific additions on top of that baseline. --- ## 1. Conventions ### 1.1 Item IDs `-` using these prefixes: | Prefix | Integration | Prefix | Integration | |---|---|---|---| | TRN | transmission | SAM | samsungtv | | NUT | nut | BRO | broadlink | | DEN | denonavr | FRZ | fritz | | HAR | harmony | ONV | onvif | | KOD | kodi | YEE | yeelight | | DLN | dlna_dmr | ATV | androidtv | Upstream-library items use `-U` suffixed IDs (e.g. `KOD-U1`) because they land in a separate repository and on PyPI, not in `home-assistant/core`. ### 1.2 Lane classification Lanes group items by review profile so we can balance load on reviewers and codeowners (see `docs/04-community-engagement-plan.md` §3 for why this matters): | Lane | Name | Review profile | |---|---|---| | **T** | Typing & code health | Mechanical, low controversy, fast review | | **D** | Diagnostics & repairs | Low risk, additive, privacy review needed (redaction) | | **F** | Config / reauth / reconfigure flows | Medium risk, UX strings, needs translation awareness | | **N** | Entity naming & device model | User-visible, migration-sensitive, needs codeowner buy-in | | **Q** | Test coverage | Additive, no runtime change, easiest to merge | | **R** | Quality-scale record & docs | Trivially reviewable, must land *last* per integration | | **U** | Upstream library work | Separate repo, separate maintainer, release latency | ### 1.3 Size classes | Size | Changed LOC (approx.) | Expected effort | |---|---|---| | XS | < 100 | ≤ 0.5 day | | S | 100–300 | 1–2 days | | M | 300–500 | 2–4 days | | L | would exceed 500 | **must be split into a PR series**; tracked as the series, sized per part | ### 1.4 Dependency tags | Tag | Meaning | |---|---| | `upstream-first` | Blocked on a library change being merged **and released to PyPI**; the core PR must bump the requirement to the released version. | | `needs-device-tester` | Cannot be validated with mocks alone; requires a community member with physical hardware per the tester roster process (engagement plan §5). Tests in core are still mock-based; this tag covers *behavioral validation before merge*. | | `codeowner-signoff` | Requires explicit pre-agreement (issue or architecture discussion) with the listed CODEOWNER before opening the PR, not just review at PR time. | | `arch-discussion` | Requires a thread in home-assistant/architecture discussions before implementation. | | `blocked-by:` | Hard sequencing dependency on another backlog item. | | `translation-impact` | Adds/changes `strings.json`; must follow the string-freeze awareness rules (engagement plan §6: avoid landing new strings inside the week before a monthly release beta cut). | ### 1.5 Per-integration series order Unless an item says otherwise, items within an integration land in lane order **U → T → D → F → N → Q → R**: 1. Upstream first, because PyPI release latency is the longest pole. 2. Typing next — it is mechanical, builds reviewer trust, and makes every later diff cleaner. 3. Diagnostics before flows — diagnostics output is the cheapest debugging aid for everything after it. 4. Flows before naming — naming migrations generate user questions; we want reauth/reconfigure solid first so support load doesn't compound. 5. Tests are interleaved (every lane item ships its own tests) but the *coverage closure* item (Q) lands after the functional items so it measures the final shape. 6. The quality-scale record (R) is always last: it asserts the final state. --- ## 2. Master backlog table 78 items. Wave assignment is explained in §16. | ID | Lane | Size | Wave | Tags | |---|---|---|---|---| | TRN-01 | T | S | 1 | — | | TRN-02 | D | S | 1 | — | | TRN-03 | F | S | 2 | translation-impact | | TRN-04 | N | S | 3 | codeowner-signoff, translation-impact | | TRN-05 | Q | M | 4 | — | | TRN-06 | R | XS | 4 | blocked-by:TRN-05 | | NUT-01 | T | S | 1 | — | | NUT-02 | D | XS | 1 | — | | NUT-03 | F | S | 2 | translation-impact | | NUT-04 | N | M | 3 | translation-impact | | NUT-05 | D | S | 2 | translation-impact | | NUT-06 | Q | S | 4 | — | | NUT-07 | R | XS | 4 | blocked-by:NUT-06 | | DEN-U1 | U | M | 0 | upstream-first, needs-device-tester | | DEN-01 | T | S | 1 | — | | DEN-02 | D | S | 1 | — | | DEN-03 | F | S | 2 | translation-impact | | DEN-04 | N | M | 3 | codeowner-signoff, needs-device-tester, translation-impact | | DEN-05 | Q | M | 4 | — | | DEN-06 | R | XS | 4 | blocked-by:DEN-05 | | HAR-01 | T | S | 1 | — | | HAR-02 | D | S | 1 | — | | HAR-03 | F | S | 2 | translation-impact | | HAR-04 | N | S | 3 | codeowner-signoff, arch-discussion | | HAR-05 | Q | M | 4 | — | | HAR-06 | R | XS | 4 | blocked-by:HAR-05 | | KOD-U1 | U | S | 0 | upstream-first | | KOD-01 | T | M | 1 | blocked-by:KOD-U1 | | KOD-02 | D | S | 1 | — | | KOD-03 | F | M | 2 | translation-impact | | KOD-04 | N | S | 3 | codeowner-signoff, translation-impact | | KOD-05 | Q | L (2×M) | 4 | — | | KOD-06 | R | XS | 4 | blocked-by:KOD-05 | | DLN-01 | D | S | 1 | — | | DLN-02 | F | S | 2 | translation-impact | | DLN-03 | Q | S | 2 | — | | DLN-04 | R | XS | 2 | blocked-by:DLN-03 | | SAM-U1 | U | S | 0 | upstream-first, needs-device-tester | | SAM-01 | D | XS | 1 | — | | SAM-02 | T | S | 1 | — | | SAM-03 | F | S | 2 | translation-impact | | SAM-04 | Q | M | 2 | — | | SAM-05 | Q | S | 4 | blocked-by:SAM-U1 | | SAM-06 | R | XS | 4 | blocked-by:SAM-05 | | BRO-U1 | U | S | 0 | upstream-first | | BRO-01 | T | M | 1 | blocked-by:BRO-U1 | | BRO-02 | D | S | 1 | — | | BRO-03 | F | M | 2 | translation-impact | | BRO-04 | N | M | 3 | codeowner-signoff, needs-device-tester, translation-impact | | BRO-05 | Q | L (2×M) | 4 | — | | BRO-06 | D | S | 3 | translation-impact | | BRO-07 | R | XS | 4 | blocked-by:BRO-05 | | FRZ-01 | T | M | 1 | — | | FRZ-02 | Q | M | 2 | — | | FRZ-03 | F | S | 2 | translation-impact | | FRZ-04 | D | S | 1 | — | | FRZ-05 | N | S | 3 | translation-impact | | FRZ-06 | D | S | 3 | translation-impact | | FRZ-07 | R | XS | 4 | blocked-by:FRZ-02 | | ONV-U1 | U | M | 0 | upstream-first, needs-device-tester | | ONV-01 | D | S | 1 | — | | ONV-02 | T | M | 1 | arch-discussion | | ONV-03 | Q | L (2×M) | 2 | needs-device-tester | | ONV-04 | F | S | 2 | translation-impact | | ONV-05 | Q | S | 4 | blocked-by:ONV-U1 | | ONV-06 | R | XS | 4 | blocked-by:ONV-03 | | YEE-01 | T | S | 1 | — | | YEE-02 | D | S | 1 | — | | YEE-03 | Q | M | 2 | — | | YEE-04 | N | S | 3 | codeowner-signoff, translation-impact | | YEE-05 | F | S | 2 | translation-impact | | YEE-06 | R | XS | 4 | blocked-by:YEE-03 | | ATV-U1 | U | S | 0 | upstream-first | | ATV-01 | D | S | 1 | — | | ATV-02 | T | M | 1 | blocked-by:ATV-U1 | | ATV-03 | Q | M | 2 | — | | ATV-04 | F | S | 2 | translation-impact | | ATV-05 | N | S | 3 | codeowner-signoff, translation-impact | | ATV-06 | R | XS | 4 | blocked-by:ATV-03 | --- ## 3. transmission (TRN) Library: `transmission-rpc`. Audit: `docs/audits/transmission.md`. Series order: TRN-01 → 02 → 03 → 04 → 05 → 06. #### TRN-01 — Enable strict typing for the integration **Lane T · S · Wave 1** Scope: annotate the coordinator with proper generics (`DataUpdateCoordinator[TransmissionData]`), type all entity modules and service handlers, add `homeassistant.components.transmission.*` to `.strict-typing`. Acceptance criteria: - `mypy --strict` passes for the component with zero `type: ignore` additions (existing ignores may remain only with a linked upstream issue in a comment). - Coordinator data is a typed dataclass or `TypedDict`, not a bare dict. - No runtime behavior change; diff is annotations + structural typing only. #### TRN-02 — Diagnostics platform **Lane D · S · Wave 1** Scope: add `diagnostics.py` exposing daemon version, session stats, torrent counts by state, and configured options. Acceptance criteria: - `async_get_config_entry_diagnostics` implemented; output redacts host, username, password via `async_redact_data`. - Torrent names/hashes are **not** included (user content; privacy). - Diagnostics test asserts a full snapshot (syrupy) and asserts redacted keys are `**REDACTED**`. #### TRN-03 — Reconfigure flow **Lane F · S · Wave 2** Scope: add a reconfigure step so users can change host/port/SSL without deleting the entry; preserve entry `unique_id` semantics and reject reconfiguration that points at a different daemon. Acceptance criteria: - `async_step_reconfigure` implemented; aborts with `wrong_account`-style reason if the new endpoint's identity differs. - Existing reauth flow untouched and still covered by tests. - Config-flow test coverage remains 100%, including the new abort and error paths. #### TRN-04 — Entity naming: `has_entity_name` + translation keys **Lane N · S · Wave 3 · codeowner-signoff, translation-impact** Scope: migrate sensors/switches to `_attr_has_entity_name = True` with `translation_key` per entity; device name carries the instance name. Acceptance criteria: - All entity names sourced from `strings.json` `entity` section; no hard-coded English in Python. - Entity IDs of existing installs do not change (registry preserves them); item description in the PR explains this explicitly for reviewers. - Codeowner pre-agreement linked in the PR body. #### TRN-05 — Coverage closure **Lane Q · M · Wave 4** Scope: tests for switch on/off RPC calls, `add_torrent`/`remove_torrent`/`start_torrent`/`stop_torrent` services (success + error), coordinator failure → entities unavailable, recovery → available. Acceptance criteria: - Component coverage ≥ 95% overall; `config_flow.py` and `diagnostics.py` at 100%. - All service tests assert the exact RPC payload sent to the mocked client. - Unavailability round-trip test exists (fail → unavailable → recover → available with fresh data). #### TRN-06 — Quality-scale record + docs parity **Lane R · XS · Wave 4 · blocked-by:TRN-05** Acceptance criteria: - `quality_scale.yaml` added/updated with accurate `done`/`exempt` statuses and exemption comments. - Companion `home-assistant.io` PR updates the docs page (removal instructions, supported devices, troubleshooting) and is cross-linked. - hassfest quality-scale validation passes at the claimed tier (target: **silver**, per audit). --- ## 4. nut (NUT) Library: `aionut`. Audit: `docs/audits/nut.md`. Series order: NUT-01 → 02 → 05 → 03 → 04 → 06 → 07. #### NUT-01 — Strict typing **Lane T · S · Wave 1** Scope: complete annotations in `__init__.py`, `sensor.py`, `device_action.py`; add to `.strict-typing`. Acceptance criteria: - `mypy --strict` clean; sensor description mapping fully typed (no `Any` values). - No behavior change. #### NUT-02 — Diagnostics redaction audit **Lane D · XS · Wave 1** Scope: audit existing diagnostics output; ensure serial number, hostname, and credentials are redacted; add UPS variable dump (already mostly present) behind redaction list. Acceptance criteria: - Redaction list covers `serial`, host, username, password, and any `ups.*.id`-style identifiers found in the variable dump. - Snapshot test updated; redacted fields asserted. #### NUT-03 — Reconfigure flow + reauth hardening **Lane F · S · Wave 2 · translation-impact** Scope: add reconfigure step (host/port change); add tests for reauth triggered by authentication failure mid-session, not just at setup. Acceptance criteria: - Reconfigure rejects pointing the entry at a different UPS (identity check via device serial/`ups.id` where available). - Reauth flow test covers: trigger → form → bad creds → error → good creds → entry updated → reload. - Config flow coverage 100%. #### NUT-04 — Entity translations for the sensor catalogue **Lane N · M · Wave 3 · translation-impact** Scope: move the large NUT sensor-name catalogue to `strings.json` entity translations with `translation_key` per description; add icon translations where icons are static. Acceptance criteria: - Zero hard-coded English entity names remain in `sensor.py`. - `icons.json` carries static icons; no `icon` property returning constants remains. - PR split if > 500 LOC: part 1 = mechanism + top 30 sensors, part 2 = remainder. Each part independently green. #### NUT-05 — Repair issue for unsupported/legacy NUT server **Lane D · S · Wave 2 · translation-impact** Scope: raise a repairs issue (non-fixable, informational) when the connected NUT server reports a protocol/version below the supported floor, instead of silent degraded behavior. Acceptance criteria: - `ir.async_create_issue` raised with `severity=WARNING`, learn-more URL to docs, and deleted automatically when the condition clears. - Test covers issue creation and automatic deletion. #### NUT-06 — Coverage closure **Lane Q · S · Wave 4** Acceptance criteria: - ≥ 95% component coverage; availability and device-action tests included. #### NUT-07 — Quality-scale record + docs parity **Lane R · XS · Wave 4 · blocked-by:NUT-06** — same criteria pattern as TRN-06. Target tier: **gold** (per audit; NUT starts from a strong base). --- ## 5. denonavr (DEN) Library: `denonavr`. Audit: `docs/audits/denonavr.md`. Series order: DEN-U1 ∥ DEN-01 → DEN-02 → DEN-03 → DEN-04 → DEN-05 → DEN-06. (DEN-U1 runs in parallel from Wave 0; nothing in core is blocked on it except the release bump that rides along with DEN-05.) #### DEN-U1 — Upstream: telnet reconnect backoff & connection-loss callback reliability **Lane U · M · Wave 0 · upstream-first, needs-device-tester** Scope: in the `denonavr` library, fix the audit-identified gap where telnet event connections do not back off exponentially on receiver power-cycle, causing log spam; ensure the disconnect callback always fires so the integration can mark entities unavailable. Acceptance criteria: - Upstream PR merged and released on PyPI. - Reconnect uses capped exponential backoff; verified by library unit tests. - Two community testers (different receiver generations, per roster) confirm power-cycle behavior; tester confirmations linked in the PR. - Core follow-up: requirement bump PR referencing the release notes. #### DEN-01 — Strict typing **Lane T · S · Wave 1** Acceptance criteria: `mypy --strict` clean; receiver/zone wrapper types annotated; added to `.strict-typing`; no behavior change. #### DEN-02 — Diagnostics platform **Lane D · S · Wave 1** Scope: dump receiver model, firmware, zone configuration, current source list, telnet connection state. Acceptance criteria: serial number, MAC, and host redacted; snapshot test; per-zone state included so multi-zone bugs are debuggable from a diagnostics file alone. #### DEN-03 — Reconfigure flow **Lane F · S · Wave 2 · translation-impact** Scope: host change without entry deletion (receivers move IPs on DHCP frequently — top issue-tracker theme per audit). Acceptance criteria: - Reconfigure validates the new host serves the same receiver (serial/MAC match) and aborts otherwise. - Config flow coverage 100% including SSDP-discovery interaction with reconfigure. #### DEN-04 — Entity naming & zone device model **Lane N · M · Wave 3 · codeowner-signoff, needs-device-tester, translation-impact** Scope: `has_entity_name` migration; main zone entity becomes the device's primary entity (`_attr_name = None`), zone 2/3 entities named via translation keys; zones attached to the single receiver device with `via_device` semantics reviewed. Acceptance criteria: - Entity registry IDs preserved for existing installs; migration note in PR body. - One multi-zone tester confirms zone naming/grouping renders correctly in the UI; confirmation linked. - Codeowner pre-agreement linked. #### DEN-05 — Coverage closure **Lane Q · M · Wave 4** Scope: media_player tests with mocked `denonavr` (power, volume, source select, sound mode, telnet event → state push), unavailability round-trip; includes the requirement bump from DEN-U1. Acceptance criteria: ≥ 95% coverage; telnet-event push path explicitly tested (state updates without polling); requirement pinned to the DEN-U1 release. #### DEN-06 — Quality-scale record + docs parity **Lane R · XS · Wave 4 · blocked-by:DEN-05** — target tier: **silver** with documented gold exemptions. --- ## 6. harmony (HAR) Library: `aioharmony`. Audit: `docs/audits/harmony.md`. Product is discontinued hardware: all behavioral risk items default to conservative scoping; mock fidelity matters more than new capability. Series order: HAR-01 → 02 → 03 → 04 → 05 → 06. #### HAR-01 — Strict typing **Lane T · S · Wave 1** Acceptance criteria: `mypy --strict` clean for component; `.strict-typing` entry; no behavior change. #### HAR-02 — Diagnostics platform **Lane D · S · Wave 1** Scope: dump hub firmware, configured activities, device list (names + IDs), current activity. Acceptance criteria: remote IDs and hub network identifiers redacted; snapshot test; output sufficient to reproduce "activity not switching" reports without device access. #### HAR-03 — Reconfigure flow **Lane F · S · Wave 2 · translation-impact** Scope: host/IP change support (hubs on DHCP; #1 recurring issue theme per audit). Acceptance criteria: identity check against hub `remote_id`; abort on mismatch; config flow coverage 100%. #### HAR-04 — Legacy surface cleanup (deprecated YAML remnants / stale service schema) **Lane N · S · Wave 3 · codeowner-signoff, arch-discussion** Scope: per audit, complete the long-stalled removal of deprecated import/legacy configuration paths and align `change_channel`/`sync` service definitions with `services.yaml` + translations. Because the device is discontinued, the arch discussion proposes the minimal cleanup that does **not** strand existing users. Acceptance criteria: - Architecture discussion opened first and conclusion linked; codeowner agreement explicit. - Any removal follows the standard deprecation cycle (warning release N, removal ≥ N+6 months) — this item lands the *warning* phase only. - Repairs issue created for affected users with clear migration text. #### HAR-05 — Coverage closure **Lane Q · M · Wave 4** Scope: select-entity activity tests, remote send-command payload assertions, hub-offline round-trip, switch-platform deprecation path (if still present at execution time). Acceptance criteria: ≥ 95% coverage; every service asserts the exact `aioharmony` call payload. #### HAR-06 — Quality-scale record + docs parity **Lane R · XS · Wave 4 · blocked-by:HAR-05** — target tier: **silver**; docs gain an explicit "discontinued hardware" support-expectations section. --- ## 7. kodi (KOD) Library: `pykodi` (over `jsonrpc-async`/`jsonrpc-websocket`). Audit: `docs/audits/kodi.md`. Series order: KOD-U1 → KOD-01 → 02 → 03 → 04 → 05 → 06. #### KOD-U1 — Upstream: ship `py.typed` + annotations in pykodi **Lane U · S · Wave 0 · upstream-first** Scope: add type annotations to `pykodi`'s public surface and a `py.typed` marker; release. Acceptance criteria: upstream merged + PyPI release; public methods used by core (`call_method`, connection classes) fully annotated; core requirement bump PR follows. #### KOD-01 — Strict typing **Lane T · M · Wave 1 · blocked-by:KOD-U1** Scope: the media_player module is large; annotate it plus browse-media helpers; `.strict-typing` entry. Acceptance criteria: `mypy --strict` clean; the JSON-RPC result shapes used by the component expressed as `TypedDict`s; no behavior change. If KOD-U1's release slips past Wave 1, land with module-scoped overrides and convert in a follow-up XS PR (tracked, not silently dropped). #### KOD-02 — Diagnostics platform **Lane D · S · Wave 1** Scope: Kodi version, connection mode (HTTP vs WS), active player state, configured options. Acceptance criteria: credentials and host redacted; snapshot test. #### KOD-03 — Reauth + reconfigure flows **Lane F · M · Wave 2 · translation-impact** Scope: per audit, auth failures currently dead-end into setup-retry; add a proper reauth flow on 401, and a reconfigure step for host/port/SSL/WS-port changes. Acceptance criteria: - 401 during setup or runtime triggers reauth (not infinite retry); test proves no reauth-flow duplication on repeated failures. - Reconfigure validates same-instance identity via Kodi `System.GetProperties` UUID-equivalent where available; documented fallback otherwise. - Config flow coverage 100%. #### KOD-04 — Entity naming **Lane N · S · Wave 3 · codeowner-signoff, translation-impact** Scope: `has_entity_name`; media player as primary device entity (`_attr_name = None`). Acceptance criteria: registry IDs preserved; codeowner pre-agreement linked. #### KOD-05 — Coverage closure (PR series: 2 parts) **Lane Q · L = 2×M · Wave 4** Part 1: media_player command coverage — play/pause/stop/seek/volume/mute, `add_to_playlist` and `call_method` services with exact JSON-RPC payload assertions; WS push-update path. Part 2: browse_media tree tests (movies/TV/music/files roots, item resolution, error branches) and unavailability round-trips for both HTTP and WS modes. Acceptance criteria: each part independently green and ≤ M; combined component coverage ≥ 90% (large legacy module; 95% would force low-value churn — documented in the quality-scale record). #### KOD-06 — Quality-scale record + docs parity **Lane R · XS · Wave 4 · blocked-by:KOD-05** — target tier: **silver**. --- ## 8. dlna_dmr (DLN) Library: `async-upnp-client`. Audit: `docs/audits/dlna_dmr.md` — already the strongest of the twelve; backlog is deliberately small and finishes in Wave 2. Series order: DLN-01 → 02 → 03 → 04. #### DLN-01 — Diagnostics platform **Lane D · S · Wave 1** Scope: device description (model, manufacturer, services), subscription state, last event timestamps. Acceptance criteria: UDN partially redacted (keep last 4 chars for correlation), URLs stripped of host credentials; snapshot test. #### DLN-02 — Reconfigure flow for changed device location **Lane F · S · Wave 2 · translation-impact** Scope: allow updating the description URL when SSDP rediscovery hasn't caught a moved device. Acceptance criteria: identity check by UDN; abort on mismatch; SSDP-driven URL update path keeps working (regression test included); config flow coverage stays 100%. #### DLN-03 — Coverage closure: eventing failure paths **Lane Q · S · Wave 2** Scope: tests for subscription renewal failure → poll fallback, resubscribe success → push resumes, and notify-server unavailability. Acceptance criteria: ≥ 98% coverage; each fallback transition asserted via state, not just log output. #### DLN-04 — Quality-scale record: platinum claim **Lane R · XS · Wave 2 · blocked-by:DLN-03** Acceptance criteria: `quality_scale.yaml` asserts **platinum** with every rule `done` or justified-`exempt`; hassfest platinum validation passes; docs parity PR landed. This is the program's first platinum and the template for the rest. --- ## 9. samsungtv (SAM) Libraries: `samsungtvws`, `samsungctl`, `getmac`, `wakeonlan`. Audit: `docs/audits/samsungtv.md`. Series order: SAM-U1 ∥ SAM-01 → 02 → 03 → 04 → 05 → 06. #### SAM-U1 — Upstream: samsungtvws websocket session cleanup **Lane U · S · Wave 0 · upstream-first, needs-device-tester** Scope: fix the audit-identified leak where remote-control websocket sessions are not reliably closed on TV power-off, producing reconnect storms. Acceptance criteria: upstream merged + PyPI release; library test reproduces the leak pre-fix; one tester per TV generation (pre-2020 / 2020+ encrypted) confirms; core bump PR follows in SAM-05. #### SAM-01 — Diagnostics redaction audit **Lane D · XS · Wave 1** Scope: verify the existing diagnostics redact the auth **token**, MAC, serial, and device ID; add any missing keys; extend snapshot. Acceptance criteria: explicit test asserting `token` never appears in diagnostics output, including nested under entry data and runtime data. #### SAM-02 — Strict typing gap closure (bridge module) **Lane T · S · Wave 1** Scope: per audit, the bridge abstraction has `Any`-typed seams; tighten and add to `.strict-typing` if not present. Acceptance criteria: `mypy --strict` clean; bridge method signatures concrete; no behavior change. #### SAM-03 — Reconfigure flow **Lane F · S · Wave 2 · translation-impact** Scope: host change with identity verification via device `udn`/serial; preserves token. Acceptance criteria: token survives reconfigure (test asserts no re-prompt for authorization when the same TV is at a new IP); config flow coverage stays 100%. #### SAM-04 — Encrypted-model reauth & WoL failure-path tests **Lane Q · M · Wave 2** Scope: mock-based tests for the encrypted (H/J 2014–2015) reauth PIN flow edge cases and wake-on-LAN failure handling (no MAC known, send failure). Acceptance criteria: encrypted reauth covered for: wrong PIN, session expiry mid-flow, success; `turn_on` without MAC surfaces a proper `HomeAssistantError` with translation key, asserted in test. #### SAM-05 — Requirement bump + reconnect-storm regression test **Lane Q · S · Wave 4 · blocked-by:SAM-U1** Acceptance criteria: requirement bumped to the SAM-U1 release; regression test simulates TV power-off and asserts bounded reconnect attempts with backoff; tester confirmation linked. #### SAM-06 — Quality-scale record + docs parity **Lane R · XS · Wave 4 · blocked-by:SAM-05** — target tier: **gold**. --- ## 10. broadlink (BRO) Library: `broadlink` (python-broadlink). Audit: `docs/audits/broadlink.md`. Series order: BRO-U1 → BRO-01 → 02 → 03 → 06 → 04 → 05 → 07. #### BRO-U1 — Upstream: `py.typed` marker + public-surface annotations **Lane U · S · Wave 0 · upstream-first** Scope: python-broadlink has substantial annotations but no `py.typed`; add marker, fill gaps on the classes core uses (`rm`, `sp`, `a1`, `hello`, exceptions). Acceptance criteria: upstream merged + PyPI release; core bump rides with BRO-01. #### BRO-01 — Strict typing **Lane T · M · Wave 1 · blocked-by:BRO-U1** Scope: annotate `__init__.py`, `entity.py`, `remote.py`, `updater.py`; `.strict-typing` entry; includes BRO-U1 requirement bump. Acceptance criteria: `mypy --strict` clean; updater data structures typed; no behavior change. Same slip-contingency rule as KOD-01. #### BRO-02 — Diagnostics platform **Lane D · S · Wave 1** Scope: device type/model, firmware, configured platforms, learned-code store summary (counts per remote entity, not the codes). Acceptance criteria: MAC, host, and the device encryption key redacted; learned IR/RF codes excluded entirely (asserted by test); snapshot test. #### BRO-03 — Reauth + reconfigure flows **Lane F · M · Wave 2 · translation-impact** Scope: per audit, `AuthenticationError` mid-session leads to setup-retry loops; wire it to a reauth flow; add reconfigure for host changes with MAC-based identity check. Acceptance criteria: runtime auth failure → single reauth flow (dedup tested); reconfigure aborts on MAC mismatch; config flow coverage 100%. #### BRO-06 — Repairs: legacy code-storage format migration notice **Lane D · S · Wave 3 · translation-impact** Scope: detect pre-flatten storage format for learned codes (audit found dual-format handling scattered in `remote.py`); migrate on load, raise a fixable repairs issue only if migration finds corrupt entries. Acceptance criteria: migration is automatic and idempotent (test: old-format store → load → new format → reload → unchanged); corrupt-entry path raises a repairs issue listing affected command names; no user data loss in any tested path. #### BRO-04 — Entity naming migration **Lane N · M · Wave 3 · codeowner-signoff, needs-device-tester, translation-impact** Scope: `has_entity_name` across remote/switch/sensor/light platforms; device name from user-given entry title. Acceptance criteria: registry IDs preserved; one tester per device class (RM4, SP4, A1) confirms entity presentation; codeowner pre-agreement linked. #### BRO-05 — Coverage closure (PR series: 2 parts) **Lane Q · L = 2×M · Wave 4** Part 1: remote learn/send flows — learn IR, learn RF (two-step), send with b64 payload assertions, delete command, error branches (timeout, storage write failure). Part 2: updater/coordinator round-trips per device class, switch/light/sensor command payload assertions, unavailability behavior. Acceptance criteria: each part ≤ M and independently green; combined coverage ≥ 92% (large legacy surface; documented in record); learn-flow tests assert persistent-notification/UX side effects where the integration emits them. #### BRO-07 — Quality-scale record + docs parity **Lane R · XS · Wave 4 · blocked-by:BRO-05** — target tier: **silver**, with the storage-migration work called out as the gold-blocking remainder. --- ## 11. fritz (FRZ) Library: `fritzconnection`. Audit: `docs/audits/fritz.md`. Series order: FRZ-01 → FRZ-04 → FRZ-02 → FRZ-03 → FRZ-05 → FRZ-06 → FRZ-07. #### FRZ-01 — Strict typing of coordinator & entity modules **Lane T · M · Wave 1** Scope: per audit, `coordinator.py` carries loosely-typed device/mesh structures; introduce typed models (dataclasses) for tracked devices and mesh nodes; `.strict-typing` entry. Acceptance criteria: `mypy --strict` clean; no `dict[str, Any]` crossing module boundaries for device/mesh data; no behavior change. #### FRZ-04 — Diagnostics extension: mesh topology **Lane D · S · Wave 1** Scope: add mesh topology summary (node count, roles, link types) and feature-capability flags to diagnostics. Acceptance criteria: external IP, WAN identifiers, MACs, and hostnames redacted; snapshot test; output sufficient to triage mesh-tracking reports (top issue category per audit) without router access. #### FRZ-02 — Config-flow coverage to 100% incl. SSDP edges **Lane Q · M · Wave 2** Scope: close the audit-identified config-flow coverage holes: SSDP discovery of an already-configured box (IP changed), discovery during ongoing user flow, and error→retry→success sequences. Acceptance criteria: `config_flow.py` at 100%; SSDP-triggered host update on existing entries has an explicit regression test. #### FRZ-03 — Reconfigure flow + reauth hardening **Lane F · S · Wave 2 · translation-impact** Acceptance criteria: reconfigure with identity check (box serial via `DeviceInfo`); reauth dedup test (repeated 401s → one flow); coverage stays 100%. #### FRZ-05 — Translation keys for buttons/switches **Lane N · S · Wave 3 · translation-impact** Scope: move button (reboot, reconnect, firmware) and switch (deflection, Wi-Fi, profiles) names to entity translations; static icons to `icons.json`. Acceptance criteria: no hard-coded English entity names; dynamic per-profile/per-deflection names keep their dynamic suffix via `translation_placeholders`. #### FRZ-06 — Repairs: TR-064/UPnP misconfiguration detection **Lane D · S · Wave 3 · translation-impact** Scope: when setup fails because TR-064 is disabled on the box (distinct, detectable error per audit), raise a fixable repairs issue with enable-instructions instead of a generic retry. Acceptance criteria: issue raised with learn-more URL; auto-deleted once setup succeeds; `ConfigEntryNotReady` path retained for genuinely transient errors (test distinguishes the two). #### FRZ-07 — Quality-scale record + docs parity **Lane R · XS · Wave 4 · blocked-by:FRZ-02** — target tier: **gold**. --- ## 12. onvif (ONV) Library: `onvif-zeep-async` (over `zeep`). Audit: `docs/audits/onvif.md`. This is the highest-issue-volume integration of the twelve; the backlog leans hard on fixtures and event-pipeline testability. Series order: ONV-U1 ∥ ONV-02 → ONV-01 → ONV-04 → ONV-03 → ONV-05 → ONV-06. #### ONV-U1 — Upstream: vendor event-topic normalization **Lane U · M · Wave 0 · upstream-first, needs-device-tester** Scope: per audit, several high-volume bug reports trace to vendor-specific event topic strings the parser misses (Dahua/Hikvision/Reolink variants). Contribute normalization table + parsers upstream where the maintainer prefers them there; otherwise keep in core (decision recorded in the upstream issue first). Acceptance criteria: upstream issue opened with captured payload corpus (see ONV-03) and maintainer's placement decision recorded; if upstream: merged + released; if core: re-scoped into ONV-05 with the same payload-corpus tests; either way at least 3 vendor payload variants gain passing parse tests. #### ONV-02 — Typing strategy & implementation **Lane T · M · Wave 1 · arch-discussion** Scope: `zeep` is effectively untyped; the audit recommends thin typed wrapper protocols around the ONVIF services core touches rather than blanket ignores. Confirm approach in an architecture discussion (it sets precedent), then implement; `.strict-typing` entry. Acceptance criteria: arch-discussion link in PR; `mypy --strict` clean; wrapper protocols cover device-mgmt, media, events, PTZ services; no behavior change. #### ONV-01 — Diagnostics platform **Lane D · S · Wave 1** Scope: device capabilities, profiles, event-subscription mode (PullPoint vs webhook) and health, firmware. Acceptance criteria: credentials redacted everywhere **including inside service URLs** (userinfo stripping asserted by test); snapshot test. #### ONV-04 — Reauth hardening **Lane F · S · Wave 2 · translation-impact** Scope: 401/auth-fault during runtime (not just setup) triggers reauth; dedup; clock-skew auth failures (common ONVIF pathology per audit) produce a distinct repairs hint rather than a reauth loop. Acceptance criteria: runtime-401 → reauth test; clock-skew fault → repairs issue with NTP guidance, no reauth flow opened; config flow coverage 100%. #### ONV-03 — Event pipeline test corpus (PR series: 2 parts) **Lane Q · L = 2×M · Wave 2 · needs-device-tester** Scope: build a fixture corpus of real captured event payloads (testers from the roster capture PullPoint/webhook XML from Dahua, Hikvision, Axis, Reolink, Tapo devices — sanitized via a provided capture script) and test the parser + binary-sensor/sensor materialization against it. Part 1: capture tooling note in `docs/`, fixture format, parser tests for the first 3 vendors. Part 2: remaining vendors, webhook↔PullPoint fallback transition tests, subscription-renewal failure round-trip. Acceptance criteria: ≥ 5 vendor fixture sets committed (sanitized, license-clean); every fixture parses to asserted entity states; fallback transitions asserted via state; tester credits in PR body per engagement plan §5. #### ONV-05 — Vendor normalization landing + requirement bump **Lane Q · S · Wave 4 · blocked-by:ONV-U1** Acceptance criteria: per ONV-U1's placement decision, either the requirement bump + regression tests, or the in-core normalization table with corpus-driven tests; the three target vendor variants from real issue reports are closed-by-commit (issues linked). #### ONV-06 — Quality-scale record + docs parity **Lane R · XS · Wave 4 · blocked-by:ONV-03** — target tier: **silver** (gold blocked on documented exemptions around device heterogeneity; recorded honestly). --- ## 13. yeelight (YEE) Library: `yeelight` (python-yeelight). Audit: `docs/audits/yeelight.md`. Series order: YEE-01 → 02 → 03 → 05 → 04 → 06. #### YEE-01 — Strict typing **Lane T · S · Wave 1** Acceptance criteria: `mypy --strict` clean; `.strict-typing` entry; bulb capability/state structures typed; no behavior change. #### YEE-02 — Diagnostics platform **Lane D · S · Wave 1** Scope: model, firmware, capability set, music-mode state, nightlight support flag. Acceptance criteria: bulb ID partially redacted (keep last 4), host redacted; snapshot test. #### YEE-03 — Coverage: nightlight & music-mode paths **Lane Q · M · Wave 2** Scope: per audit the nightlight dual-entity logic and music-mode connection lifecycle are the two least-tested, most-reported areas. Acceptance criteria: nightlight on/off transitions asserted across both entities (main + nightlight) for supporting and non-supporting models; music-mode connect/teardown/failure paths tested; ≥ 95% coverage on `light.py` branch logic touched. #### YEE-05 — Reconfigure flow **Lane F · S · Wave 2 · translation-impact** Scope: host override for bulbs that discovery misses (VLAN/firewalled networks — recurring issue theme). Acceptance criteria: identity check by bulb ID; abort on mismatch; config flow coverage 100%. #### YEE-04 — Entity naming **Lane N · S · Wave 3 · codeowner-signoff, translation-impact** Scope: `has_entity_name`; main light as primary entity (`_attr_name = None`), nightlight entity gains a translation key. Acceptance criteria: registry IDs preserved; codeowner pre-agreement linked. #### YEE-06 — Quality-scale record + docs parity **Lane R · XS · Wave 4 · blocked-by:YEE-03** — target tier: **silver**. --- ## 14. androidtv (ATV) Libraries: `androidtv`, `adb-shell`. Audit: `docs/audits/androidtv.md`. Series order: ATV-U1 → ATV-01 → ATV-02 → ATV-03 → ATV-04 → ATV-05 → ATV-06. #### ATV-U1 — Upstream: `py.typed` for androidtv library **Lane U · S · Wave 0 · upstream-first** Scope: the `androidtv` package has annotations but no `py.typed`; add marker + fill public-surface gaps; release. Acceptance criteria: upstream merged + PyPI release; core bump rides with ATV-02. #### ATV-01 — Diagnostics: adbkey-safe output **Lane D · S · Wave 1** Scope: device properties (model, API level, installed-source apps list), connection mode (python ADB vs ADB-server), state-detection rule config. Acceptance criteria: explicit test that the ADB private key path content and the key itself can never appear in output; MAC/serial redacted; snapshot test. #### ATV-02 — Strict typing **Lane T · M · Wave 1 · blocked-by:ATV-U1** Acceptance criteria: `mypy --strict` clean; `.strict-typing` entry; includes ATV-U1 bump; same slip-contingency rule as KOD-01. #### ATV-03 — State-detection rule coverage **Lane Q · M · Wave 2** Scope: per audit, custom `state_detection_rules` parsing/validation and the resulting media_player state mapping are the dominant bug source; build a rule-fixture matrix. Acceptance criteria: invalid rule JSON → options-flow error with translation key (asserted); ≥ 10 rule fixtures mapping mocked `adb shell` output → asserted entity state; learn-more URL in the error. #### ATV-04 — Reconfigure flow **Lane F · S · Wave 2 · translation-impact** Scope: host change preserving the ADB key pairing. Acceptance criteria: identity check via device serial/`androidtv` unique ID; pairing survives (no re-auth prompt for same device, asserted); config flow coverage 100%. #### ATV-05 — Entity naming **Lane N · S · Wave 3 · codeowner-signoff, translation-impact** Acceptance criteria: `has_entity_name`; media player primary; registry IDs preserved; codeowner pre-agreement linked. #### ATV-06 — Quality-scale record + docs parity **Lane R · XS · Wave 4 · blocked-by:ATV-03** — target tier: **silver**. --- ## 15. Dependency views ### 15.1 Upstream-first items (longest poles — start all in Wave 0) | ID | Repo | Blocks | Latency risk | |---|---|---|---| | DEN-U1 | ol-iver/denonavr | DEN-05 (bump only) | Medium — active maintainer | | KOD-U1 | OnFreund/PyKodi | KOD-01 | **High — low-activity repo; contingency in KOD-01** | | SAM-U1 | xchwarze/samsung-tv-ws-api | SAM-05 | Medium | | BRO-U1 | mjg59/python-broadlink | BRO-01 | Medium — contingency in BRO-01 | | ONV-U1 | openvideolibs/python-onvif-zeep-async | ONV-05 | Medium — placement decision de-risks | | ATV-U1 | JeffLIrion/python-androidtv | ATV-02 | Medium — contingency in ATV-02 | Rule: every upstream item gets a tracking issue in our program board with a 4-week check-in cadence; if a release hasn't shipped within one wave of the merge, the named contingency in the blocked core item activates. ### 15.2 needs-device-tester roster demand | ID | Hardware needed | Testers | When | |---|---|---|---| | DEN-U1 | 2 Denon/Marantz receiver generations | 2 | Wave 0 | | DEN-04 | Multi-zone receiver | 1 | Wave 3 | | SAM-U1 | Pre-2020 + 2020+ Samsung TVs | 2 | Wave 0 | | BRO-04 | RM4, SP4, A1 devices | 3 (can overlap) | Wave 3 | | ONV-U1 / ONV-03 | Dahua, Hikvision, Axis, Reolink, Tapo cameras | 5 (payload capture only) | Waves 0–2 | Recruit per engagement plan §5 (forum + Discord call-for-testers, capture scripts, credit in PR bodies). ONV capture recruitment starts **immediately** at program kickoff because fixture collection gates the largest Q item. ### 15.3 codeowner-signoff items (pre-agreement before PR) TRN-04, DEN-04, HAR-04, KOD-04, BRO-04, YEE-04, ATV-05 — all entity-naming/device-model migrations, plus HAR-04's deprecation cleanup. Open all signoff issues at the **start of Wave 2** (one wave ahead of implementation) so silence-timeouts (engagement plan §4: 14 days, then escalate per ADR-0011 ownership norms) resolve before Wave 3 begins. ### 15.4 arch-discussion items - ONV-02 (typed-wrapper pattern over zeep — precedent-setting) — open at kickoff. - HAR-04 (deprecation path for discontinued-hardware integration surface) — open at Wave 1 start. --- ## 16. Cross-integration schedule Four execution waves after a Wave 0 ramp, ~16 weeks total at the staffing assumption from `docs/01-design-overview.md` (2 contributors). WIP limits — hard rules, not aspirations: - **≤ 2 open core PRs per integration** at any time (codeowner courtesy, engagement plan §3). - **≤ 6 open core PRs total** across the program. - **≤ 1 open `translation-impact` PR per integration**, never opened in the 7 days before a monthly beta cut. | Wave | Weeks | Theme | Items | |---|---|---|---| | **0** | 1–2 | Upstream kickoff + recruitment | DEN-U1, KOD-U1, SAM-U1, BRO-U1, ONV-U1, ATV-U1; ONV tester recruitment; arch discussion for ONV-02 | | **1** | 2–5 | Typing + diagnostics blitz (low-risk trust-building) | TRN-01/02, NUT-01/02, DEN-01/02, HAR-01/02, KOD-01/02, DLN-01, SAM-01/02, BRO-01/02, FRZ-01/04, ONV-01/02, YEE-01/02, ATV-01/02 | | **2** | 5–9 | Flows + early coverage; **dlna_dmr platinum lands** | TRN-03, NUT-03/05, DEN-03, HAR-03, KOD-03, DLN-02/03/04, SAM-03/04, BRO-03, FRZ-02/03, ONV-03/04, YEE-03/05, ATV-03/04; open all codeowner-signoff issues | | **3** | 9–12 | Naming migrations + repairs (highest user visibility, batched so support load is one wave, not four) | TRN-04, NUT-04, DEN-04, HAR-04, KOD-04, BRO-04/06, FRZ-05/06, YEE-04, ATV-05 | | **4** | 12–16 | Coverage closure + upstream-bump landings + quality-scale records | TRN-05/06, NUT-06/07, DEN-05/06, HAR-05/06, KOD-05/06, SAM-05/06, BRO-05/07, FRZ-07, ONV-05/06, YEE-06, ATV-06 | Scheduling mechanics: 1. **Stagger within waves by codeowner.** No two simultaneous PRs to the same codeowner where one person owns multiple targets; the board tracks codeowner, not just integration. 2. **dlna_dmr finishes first deliberately** (end of Wave 2): an early platinum is the program's credibility proof and the template PR set the remaining eleven reference. 3. **Wave gates.** A wave's items for an integration don't open until the prior wave's items for that integration are merged or explicitly parked with a recorded reason — prevents stacked-PR review burden. 4. **Release-cycle alignment.** Wave 3 (naming) lands early in a monthly cycle so changes ride a full beta; Wave 3 start aligns to the first week after a beta cut. 5. **Slippage policy.** If an upstream item slips past its contingency window, the blocked item executes its named fallback; nothing in Waves 1–3 waits on PyPI except KOD-01/BRO-01/ATV-02, each of which has an explicit override-and-follow-up contingency. 6. **Parking, not padding.** If an audit finding turns out to be already fixed by the community when an item opens (likely over 16 weeks — these are active integrations), the item is closed as `already-done`, recorded on the program ledger, and **not** replaced with invented work. --- ## 17. Program exit criteria The program (milestones #3+) is complete when: 1. Every non-parked item above is merged or closed `already-done` with evidence. 2. Twelve `quality_scale.yaml` records assert the target tiers (1 platinum, 3 gold, 8 silver) and hassfest validates each claim. 3. All six upstream contributions are merged, or declined-with-recorded-rationale and their core contingencies landed. 4. Zero open regressions attributed to program PRs older than 14 days. 5. The tester roster and fixture corpus (ONV) are documented well enough for community continuation without us. These map 1:1 onto the acceptance criteria framework in `docs/05-acceptance-criteria.md` §7 (program-level criteria) and will seed the milestone #3 execution tracker.