fix(discovery): coherent progress reporting across every stage#458
Merged
Conversation
User-reported: progress UI broken at every stage (bar jumps backward, freezes, incoherent counter values, periods with no updates). Pipeline audit found four interacting defects, all fixed HA-side: 1. PROBING hole in discovery_progress_percent (bar DROPPED ~97% -> 10%). The reconciliation sets sub_phase=probing for its 5-15 s residue probe at the end of EVERY run; the percent property had no branch for it and fell through to the legacy fallback (10%). Now mapped into the finalizing weight band (~98.8%). 2. Coarse-phase regression during reconciliation. The three _update_discovery_state calls in _reconcile_post_discovery forced phase=pc_link — after a module scan the status sensor's state REGRESSED from module_scan to pc_link for the probe window (and fed the same legacy 10% fallback). The phase override is removed; the run's phase is kept. 3. Competing writers froze the inventory bar at '1/1'. The library emits inventory progress ONCE as a single unit (register_total=1, registers_sent=1); writing that through clobbered the live 0..92 frame counter maintained by _discovery_frame_callback, whose min(total=1, ...) then froze at 1 — bar pinned, message 'PC-Link inventory: 1/1 registers' for the whole phase. The progress handler now skips the register counters for the inventory sub-phase (frame callback owns them), and the sub-phase-transition zeroing excludes entry into inventory so the seeded total survives. 4. Frame counter counted during the identity phase. The same $2E frames keep flowing during identity (96 reads x N modules); the unconditional increment fought the library's authoritative per-module counters between on_progress emits (flicker/incoherent values). Counting is now gated on the inventory sub-phase, like the message already was (2.11.2). Tests: +4 regressions (probing percent full+module_scan scopes, inventory-emit clobber guard incl. transition zeroing, identity-phase counter gate); 1 test updated — it pinned the old identity-counting behaviour that fix 4 removes. 444 passed, ruff clean, mypy 100 (= baseline). https://claude.ai/code/session_01LH7yGDY8ttvZUVMVjfSNXj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the user-reported progress-UI breakage at every discovery stage (bar jumping backward, freezing, incoherent counters, periods without updates). A pipeline audit (library
_emit_progress→_handle_discovery_progress→discovery_progress_percent→ sensors) found four interacting defects — together they explain all four symptoms. All fixed HA-side; no library change needed.1. 🔴 The bar DROPPED ~97 % → 10 % at the end of every run
The reconciliation sets
sub_phase=probingfor its 5-15 s residue probe;discovery_progress_percenthad no branch for PROBING and fell through to the legacy 10 % fallback. Now mapped into the finalizing weight band (~98.8 %). (→ "bar jumps backward")2. 🔴 Coarse phase regressed during reconciliation
The three
_update_discovery_statecalls in_reconcile_post_discoveryforcedphase=pc_link— after a module scan the status sensor's state regressedmodule_scan → pc_linkfor the probe window, feeding the same 10 % fallback. Phase override removed; the run's phase is kept. (→ "incoherent values")3. 🟠 Competing writers froze the inventory bar at "1/1"
The library emits inventory progress once, as a single unit (
register_total=1, registers_sent=1); writing that through clobbered the live 0..92 frame counter from_discovery_frame_callback, whosemin(total=1, …)then froze — bar pinned, message "PC-Link inventory: 1/1 registers" for the whole phase. The progress handler now skips register counters during the inventory sub-phase (the frame callback owns them), and the transition-zeroing excludes entry into inventory so the seeded total survives. (→ "frozen bar" + "no updates")4. 🟠 Frame counter counted during the identity phase
The same
$2Eframes keep flowing during identity (96 reads × N modules); the unconditional increment fought the library's authoritative per-module counters betweenon_progressemits (flickering counts). Counting is now gated on the inventory sub-phase, like the message already was (2.11.2). (→ "incoherent values")Expected behaviour after this PR
pc_linkafter a module scan.Tests
+4 regressions (probing percent in both scopes, inventory-emit clobber guard incl. transition zeroing, identity-phase counter gate); 1 test updated — it pinned the old identity-counting behaviour that fix 4 intentionally removes.
444 passed,ruffclean,mypy100 (= baseline).https://claude.ai/code/session_01LH7yGDY8ttvZUVMVjfSNXj
Generated by Claude Code