---
context: phase
phase: 01-unify-duplicated-discovery-loops
task: 5
total_tasks: 5
status: in_progress
last_updated: 2026-06-12T16:21:56.006Z
---

## Critical Anti-Patterns

| Pattern | Description | Severity | Prevention Mechanism |
|---------|-------------|----------|---------------------|
| asyncio.Lock across event loops | Replacing the flag-and-poll guard in `DeviceConnection.open()` with `asyncio.Lock` broke 35 tests — a Lock binds to the first loop that awaits it, and connections are closed/reopened across per-test loops. Discovered and reverted during the /simplify session. | advisory | The constraint is documented in a comment in `src/lifx/network/connection.py` `__init__`; do not "simplify" that guard again |
| Trusting stale IDE diagnostics | IDE Pyright diagnostics lagged edits all session (phantom "struct is not defined", "time not accessed"). | advisory | Only `uv run pyright` output is authoritative; never act on IDE diagnostic noise without verifying |
| Commit-scope collision | `01-xx` commit scopes exist from BOTH the archived v1.0 ceiling milestone (2026-06-12) and this discovery phase (2026-06-13 planning). | advisory | When grepping git history for this phase's commits, match on content/date, not scope alone |

**Severity values:** `blocking` — resuming agent must pass understanding check before proceeding. `advisory` — important context, does not gate resumption.

<current_state>
Phase 1 (Unify duplicated discovery loops): all 5 plans EXECUTED with green gates
(2504 passed / pyright 0 / ruff clean at wave 3 close). The execute-phase pipeline is paused
INSIDE the code-review fix pass: 01-REVIEW.md (1 Critical, 5 Warning, 7 Info; committed
`b1862d2`) is being remediated by a fixer that died with this session. Fix commits already
landed: CR-01 `f6cb654` (drop size-invalid datagrams), WR-01 `560699a` (reject all-zeros
serial), WR-02 `77a3f38` (mDNS idle-reset per D-04). WR-03/WR-04/WR-05 are unfinished —
there are UNCOMMITTED edits in `src/lifx/network/discovery.py` (likely WR-03 docstring /
WR-04 port truthfulness, mid-edit). 01-REVIEW-FIX.md does NOT exist yet.

The execute-phase run was `1 --auto --no-transition` (chained from discuss → plan). The
auto-advance chain flags are SET (`workflow._auto_chain_active=true`, `auto_advance=true`).
Worktrees were auto-degraded to sequential main-tree execution (#683: HEAD diverged from
origin/HEAD — unpushed local commits).
</current_state>

<completed_work>

Completed this session (chronological):
- /simplify (UDP transport mechanics) → committed `2f6404a`; spawned this phase
- Phase 1 added to roadmap (`ae0a0a0`), discussed (01-CONTEXT.md, D-01..D-12, `b2562f4`),
  researched + validated + pattern-mapped, planned (5 plans, checker PASSED, `899cf38`)
- Plan 01-01: IdleDeadline + tests — `43c507c`..`75103d8`
- Plan 01-04: receive_many deprecation + test — `fc624dc`..`8d43963`
- Plan 01-02: discovery unification — `7f21ab1`, `07dc874`, `4dd0712`
- Plan 01-03: mDNS adoption + typed exceptions — `ce3c827`, `036e221`
- Plan 01-05: error-test rewrite (D-10/D-11) — `dbdf418`, `0982b98`
- Code review (standard, 8 files) — 01-REVIEW.md committed `b1862d2`
- Fix pass (partial): CR-01 `f6cb654`, WR-01 `560699a`, WR-02 `77a3f38`
</completed_work>

<remaining_work>

- Fix pass completion: WR-03 (fix `_discover_with_packet` docstring: async-generator usage,
  snake_case payload keys), WR-04 (make `DiscoveryResponse.port` truthful — use `addr[1]` OR
  fix docstring + find_by_label's use at api.py:1027; pick smaller truthful change),
  WR-05 (deprecation message must point at PUBLIC alternatives + `.. deprecated::` needs
  version — current 1.2, removal v2.0). Triage the uncommitted discovery.py edit first.
- Write + commit 01-REVIEW-FIX.md (finding → disposition → commit table; note the
  pyproject `typeCheckingMode=standard` vs CLAUDE.md "strict" observation for the maintainer)
- Full gates: `uv run --frozen pytest -q` / `uv run pyright` / `uv run ruff check .`
- Execute-phase tail: regression gate (full suite re-run suffices), schema-drift gate
  (no ORM — passes trivially), codebase-drift gate (non-blocking), spawn gsd-verifier
  (model sonnet) → VERIFICATION.md, then `gsd-tools query phase.complete 1`, commit
  tracking, emit PHASE COMPLETE (--no-transition: do NOT run transition.md)
- Post-completion suggestion owed to user: `/gsd-secure-phase 1` (security enforcement on,
  no SECURITY.md yet)
</remaining_work>

<decisions_made>

- Ran the code-review fix pass BEFORE the verifier (CR-01 violated the documented DoS
  contract on the now-single discovery path; user rule "don't ignore a problem" + v1.0
  REVIEW-FIX precedent)
- Fixer constraints pinned to locked D-01..D-12; CR-01 direction = drop-and-continue
  malformed datagrams inside the shared loop; pyproject typeCheckingMode untouched
- Sequential main-tree execution (worktree base-check #683 degrade) — sequential executors
  updated STATE/ROADMAP themselves
</decisions_made>

<blockers>
- Background gsd-code-fixer died with the session mid-WR-03/04/05: reconcile via
  `git status` + `git log --oneline -10` + absence of 01-REVIEW-FIX.md before any new work
</blockers>

## Required Reading (in order)
1. `.planning/phases/01-unify-duplicated-discovery-loops/01-REVIEW.md` — the findings being fixed; WR-03/04/05 specs live here
2. `.planning/phases/01-unify-duplicated-discovery-loops/01-CONTEXT.md` — locked decisions D-01..D-12 the fixes must not contradict
3. `git status` + `git diff src/lifx/network/discovery.py` — the fixer's uncommitted mid-edit
4. `.planning/HANDOFF.json` — structured state mirror of this file

## Infrastructure State
- No servers/watchers running. Embedded emulator runs in-process per test session only.
- git: branch `main`, ~20 local commits ahead of origin (unpushed); one uncommitted file
  (`src/lifx/network/discovery.py`, fixer mid-edit)
- GSD config: `workflow._auto_chain_active=true` — next /gsd-execute-phase or /gsd-plan-phase
  invocation will auto-advance; clear with
  `gsd-tools query config-set workflow._auto_chain_active false` if manual control is wanted

<context>
This phase is the direct product of the /simplify review of UDP transport mechanics earlier
today (2026-06-13): discover_devices duplicated _discover_with_packet with drifted DoS
validation. The unification is DONE and green; what remains is purely the review-fix tail
and the verification/completion ceremony. The review's Critical (CR-01) was pre-existing but
became load-bearing once the loops unified — its fix (f6cb654) plus WR-01/WR-02 are already
in. The remaining three warnings are small (docstrings, port field truthfulness, deprecation
message wording). Expect the verifier to pass once gates are green; then phase.complete and
the PHASE COMPLETE return (no transition — parent chain ended with this phase).
</context>

<next_action>
Start with: `git status` and `git diff src/lifx/network/discovery.py` — decide whether the
fixer's uncommitted WR-03/WR-04 edit is complete enough to keep (finish + commit as
`fix(01): WR-03 ...`) or to discard and redo from 01-REVIEW.md. Then WR-05, REVIEW-FIX.md,
full gates, and the execute-phase tail (verifier → phase.complete → PHASE COMPLETE).
</next_action>
