# Implementation Plan: Full Review — Critical Fixes

**Track ID:** review-critical_20260318
**Spec:** [spec.md](./spec.md)
**Created:** 2026-03-18
**Status:** [x] Complete

## Overview

Fix all Critical (P0) and small-effort High (P1) findings from the comprehensive code review. Organized into three phases: CI/CD gates first (highest risk), then protocol/correctness fixes, then code style and asyncio cleanup. Each phase is independently verifiable.

---

## Phase 1: CI/CD Release Gate Fixes

Prevent bad releases from shipping to PyPI. Two one-line changes to `ci.yml`.

### Tasks

- [x] Task 1.1: Add test job trigger on `main` push OR tighten release `if:` to exclude `needs.test.result == 'skipped'` (CICD-H1)
- [x] Task 1.2: Add `needs.generated-files.result == 'success'` to release `if:` expression (CICD-H2)
- [x] Task 1.3: Pin `pypa/gh-action-pypi-publish` to full commit SHA (CICD-M2)
- [x] Task 1.4: Run benchmarks and save as `review-critical_20260318-Phase1`: `uv run pytest tests/benchmarks/ -m benchmark --no-cov --benchmark-save=review-critical_20260318-Phase1`

### Verification

- [x] Confirm release job `if:` expression requires all three conditions: quality ✓, generated-files ✓, test ✓ (no `skipped` allowed)
- [x] Confirm all action uses in `ci.yml` are pinned to SHA

---

## Phase 2: Protocol & Correctness Fixes

Fix bugs that affect protocol correctness and API contracts.

### Tasks

- [x] Task 2.1: Write test asserting `MultiZoneEffect.direction` setter produces exactly 8 parameters (T-C1 — test first per TDD policy)
- [x] Task 2.2: Fix `MultiZoneEffect.direction` setter — change 9-element list to 8-element list (`multizone.py:130`) (CQ-M3)
- [x] Task 2.3: Write test asserting `get_color_zones()` updates state exactly once, not twice (T-C2)
- [x] Task 2.4: Remove duplicated state update block from `get_color_zones()` (`multizone.py:364-368`) (CQ-C1)
- [x] Task 2.5: Remove duplicated state update block from `get_extended_color_zones()` (`multizone.py:461-465`) (CQ-C1)
- [x] Task 2.6: Fix `animator.py:121` — replace `random.randint(1, 0xFFFFFFFF)` with `allocate_source()` (CQ-M9, SEC-L1)
- [x] Task 2.7: Fix `api.py:802` — correct `discover_mdns()` return type to `AsyncGenerator[Device, None]` (AR-M2, D-H1)
- [x] Task 2.8: Fix `light.py:1029-1032` — add `from e` to exception re-raises to preserve traceback (CQ-M7)
- [x] Task 2.9: Run benchmarks and save as `review-critical_20260318-Phase2`: `uv run pytest tests/benchmarks/ -m benchmark --no-cov --benchmark-save=review-critical_20260318-Phase2`

### Verification

- [x] `uv run pytest tests/test_devices/test_multizone.py -v` — 28/28 passed including new direction test
- [x] `uv run pyright` — 0 errors, 0 warnings, 0 information
- [x] `uv run ruff check .` — all checks passed

---

## Phase 3: Asyncio & Import Pattern Cleanup

Fix asyncio anti-patterns and import convention violations across the device and network layers.

### Tasks

- [x] Task 3.1: Replace `__import__("time").time()` with `time.time()` in `base.py:832,921` — add `import time` at module top if not present (CQ-H1)
- [x] Task 3.2: Replace `__import__("time").time()` with `time.time()` in `multizone.py:362,368,459,465,765` (CQ-H1)
- [x] Task 3.3: Replace `__import__("time").time()` with `time.time()` in `light.py:146` (CQ-H1)
- [x] Task 3.4: Replace `time.time()` with `time.monotonic()` for all elapsed-time and timeout measurements in `discovery.py` (16 occurrences) — leave `first_seen` field as `time.time` since it's a wall-clock timestamp (BP-M2, PERF-L5)
- [x] Task 3.5: Replace `dir()` loop in `_discover_with_packet` with `get_packet_class(header.pkt_type)` (`discovery.py:309-324`) (CQ-H2, PERF-M1)
- [x] Task 3.6: Add `_LOGGER.warning({...})` to `error_received` in `transport.py:39-42` (CQ-M8, SEC-L2)
- [x] Task 3.7: Add `maxsize=1000` to `asyncio.Queue()` in `transport.py:28`; add try/except `QueueFull` in `datagram_received` to drop packets when full (SEC-M1)
- [x] Task 3.8: Run benchmarks and save as `review-critical_20260318-Phase3`: `uv run pytest tests/benchmarks/ -m benchmark --no-cov --benchmark-save=review-critical_20260318-Phase3`

### Verification

- [x] `uv run --frozen pytest` — 2436 tests pass
- [x] `uv run ruff format .` — 201 files unchanged
- [x] `uv run ruff check .` — all checks passed
- [x] `uv run pyright` — 0 errors, 0 warnings, 0 information

---

## Final Verification

- [x] All acceptance criteria in spec.md met
- [x] `uv run --frozen pytest` — 2436 tests pass
- [x] `uv run pyright` — 0 errors
- [x] `uv run ruff format . && uv run ruff check .` — clean
- [x] CI release gate correctly requires test success (verified: line 214 of ci.yml)
- [x] Ready for review

---

_Generated by Conductor. Tasks will be marked [~] in progress and [x] complete._
