v3.14.0-beta.10#172
Merged
Merged
Conversation
Schema updates since alpha.15: channel_number on all channels, channel_identity in config_entry, stale_session_recovery fields, last_poll_at (ISO), last_stub_body, rate_corrected/rate_uncorrected, tcp_latency_ms. Verified on production hardware 2026-05-29. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ookie pattern
Adds `inject_credential_cookie: bool` to `UrlTokenAuth` for firmware that
returns an empty auth response body and expects the client to synthesize
the credential cookie from btoa(user:pass) — replicating browser JS that
calls createCookie("credential", btoa(user+":"+pass)) after a successful
but body-less auth response.
- `auth.py`: add `inject_credential_cookie: bool = False` to `UrlTokenAuth`
- `url_token.py`: inject btoa credential as `cookie_name` cookie when field
is set and no body token was extracted; generalize modem-specific comment
- `http.py`: append session cookie names and basic_auth flag to the
LoginPageDetectedError warning — surfaces at WARNING without debug mode
- `modem-basic.yaml`: wire `inject_credential_cookie: true` for the SB8200
v6 client-side cookie auth pattern; correct notes to reflect actual flow
- `MODEM_YAML_SPEC.md`: document `inject_credential_cookie` field
- Tests: parameterize inject_credential_cookie cases; extract all inline
credential literals and token values to module-level constants; add
empty-body fixture; generalize fixture descriptions to patterns not models
Related to #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n url_token auth Adds intake pipeline awareness of the inject_credential_cookie pattern introduced in Core (bc464af). When analyze_har detects url_token auth with an empty response body and a credential cookie present in post-login requests but never issued via Set-Cookie, it now: - Emits a named WARNING for the empty auth response body - Runs _detect_client_side_cookie to identify the client-side origin cookie - Emits inject_credential_cookie: true + cookie_name in AuthDetail fields when the pattern is confirmed (confidence: low — btoa value unverifiable from sanitized HAR) Supporting changes: - _collect_server_cookie_names extracted to keep _detect_client_side_cookie within complexity budget - WARNING_PREFIX imported; unused has_content import removed - ONBOARDING_SPEC Phase 3 table: add row for client-side cookie origin pattern - Two fixtures cover the empty-body warning and full pattern detection cases Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cture Verified by @dggrzesiak on 3.14.0-beta.8 hardware (HW 2.02, SW V10.01.07, Comcast/Xfinity, 32 QAM + 1 OFDM DS + 4 ATDMA US locked, all signals nominal). Refreshes modem.verified.json; flips modem.yaml status awaiting_verification -> confirmed. Adds skills/ folder (modem-confirm, modem-intake, soak-analysis) with a VS Code open hook to sync into .claude/skills/. Adds comprehensive cSpell word list. Updates MODEM_INTAKE_WORKFLOW.md to include catalog README regeneration as Step 10 and renumbers confirmation steps to 13-16. Revises CLAUDE.md README rule to reflect skill-driven regeneration flow. Related to #104 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… value
The server returns a session token in the auth response body; browser JS
sets it as the credential cookie (createCookie("credential", result)).
Core now replicates this correctly. An empty auth response body is an
error — there is no btoa(user:pass) fallback.
- url_token.py: set cookie_name from body; fail if body is empty
- MODEM_YAML_SPEC.md: correct inject_credential_cookie description
- modem-basic.yaml: correct notes
- modem-basic.har: patch auth response body for golden file test
- modem-basic.expected.json: correct _about
- catalog_tools http.py: correct detection warning and docstring
- test_url_token.py: update tests; use "pw" not "password"
- test_form.py, test_form_nonce.py, test_form_pbkdf2.py, test_hnap.py:
use "pw" for mock server credential consistency
- catalog_reference.py: hard import Core display labels (no silent
fallback); fix comment; move import to top of file
- CHANGELOG.md: add [Unreleased] entry; correct beta.7 description
- README.md: regenerate (pre-existing badge label drift from venv/system
Python inconsistency, now resolved)
- CLAUDE.md: update regenerate instruction
Related to #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move feature/* trigger into validate.yaml (canonical HACS workflow) and remove the duplicate validate job from tests.yml. Drop the single-item Python matrix from the test job — pinned to 3.12 to match HA's supported floor, documented inline. Collapse the two pytest runs into one with coverage. Add job name and reference URL to hassfest.yml. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
XB7 firmware emits <th>Label</td> where the label cell is closed with </td> instead of </th>. html.parser (via BS4) nests the sibling <td> data cells inside the unclosed <th>, causing _build_label_map to see 1 cell per row and log "No data rows found in transposed table". Add loaders/html_normalize.py with _UNCLOSED_TH_RE and apply it in har.py and http.py before BS4 parsing, so all parsers receive well-formed input. Add a defense-in-depth fallback in _build_label_map for the nesting case with a comment explaining the dependency on html.parser behavior. Apply the same normalization in catalog_tools html_parsing.py so the intake pipeline handles the pattern too. Restore the XB7 HAR fixture with a complete auth flow (POST /check.jst -> 302 + real firmware HTML on GET /network_setup.jst) and regenerate the golden file from Eli's hardware data (34 DS + 5 US channels). Add paired unit fixtures: one exercises the BS4 nesting fallback directly; the other applies normalize_html() first and exercises the normal len(cells) >= 2 path. Remove the synthetic login-route fallback from test_harness/auth/form.py (contradicted the validate_har intake contract) and 12 unjustified # noqa: ARG001 suppressions across auth handlers and conftest files (ARG001 is not in the project ruff select list). Move cSpell word list from .vscode/settings.json to cspell.config.yaml with category comment groupings preserved. Add regression_output.txt to .gitignore (local stdout redirect, trend monitored via CI artifact). Add cspell.config.yaml to check-local-path-refs.sh exempt list (ignorePaths entries are glob patterns, not local path dependencies). Related to #107 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docsIfUpChannelType (DOCS-IF-MIB, RFC 4546) has no OFDMA value — it
covers SC-QAM types only (TDMA, ATDMA, S-CDMA). OFDMA upstream channels
are managed by DOCS-IF31-MIB which defines no channel type field. Both
XB6 and XB7 firmware render the inapplicable SC-QAM field ("TDMA") for
their OFDMA upstream channel, causing it to be classified as atdma.
Replace the Channel Type row mapping in both upstream parser.yaml
sections with a channel_type block derived from the Modulation field
(QAM -> atdma, OFDMA -> ofdma), matching the approach already used for
downstream. Regenerate golden files: XB6 ch7 and XB7 ch10 now carry
channel_type: ofdma. symbol_rate and the generic "OFDMA" modulation
label are correctly stripped by _strip_ofdm_fields since channel_type
is now properly classified.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cleans up multi-platform residue left over from an earlier attempt to support native Windows and dev container paths in parallel. - GETTING_STARTED.md: WSL2 + setup.sh is now the primary path; dev container moved to an optional section - welcome_message.txt: removed nonexistent setup.ps1 reference - next_steps.txt: fixed stale task names (Test: All, Test: Quick, HA: Start) and removed nonexistent make docker-start - extensions.json: add cSpell to workspace recommendations (was only in devcontainer); suppress Makefile Tools (C++ prompts) - settings.json: fix python.defaultInterpreterPath to point at the binary, not the venv directory - CLAUDE.md: add rule to audit task-name references when tasks.json changes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Verified by @esand on 3.14.0-beta.9 (HW 2.0, SW Prod_24.2_PD, 14 days 14h uptime, 34 DS + 5 US locked, all signals nominal). Refreshes modem.verified.json from their diagnostics; flips modem.yaml status awaiting_verification -> confirmed. Also corrects the BCM3390 duplication quirk note: channel 17 (primary QAM), not channel 10, mirrors ch_id 34 OFDM. Pattern now confirmed across two independent units. Also bundles: - XB6 HAR: updated fixture for beta.9 unclosed-th normalization fix - CLAUDE.md: fold rule 6a into 6, drop Contents table - Catalog README/AUDIT: regenerated Related to #2 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ation test gate
Downstream modulation map: "256 QAM" -> "QAM256" in parser.yaml.
Upstream: replace modulation-based channel_type derivation with a
direct Channel Type row extraction ("TDMA_AND_ATDMA"/"ATDMA" ->
"atdma", "TDMA" -> "ofdma"). Bare "QAM" has no canonical constellation
and cannot be mapped — reading channel_type directly from the HTML row
avoids the intermediate field entirely.
Updates modem.expected.json to reflect both changes.
Root cause: modem-confirm skill had no test step after the status
flip. test_confirmed_modem_golden_spec_conformance only runs for
confirmed modems, so it fires for the first time at confirmation.
Adds Step 15a to MODEM_INTAKE_WORKFLOW.md requiring catalog tests
before commit.
Related to #2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Require catalog tests after status flip (Step 15a) before committing. test_confirmed_modem_golden_spec_conformance only fires for confirmed modems and was missed in the XB7 confirmation. Mirrors the update already in MODEM_INTAKE_WORKFLOW.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ings Replaces ad-hoc allow rules with a principled three-section layout: allow (dev workflow + gh reads), deny (staging hard-block + storage credentials), ask (commit/push/rebase/gh writes). git staging moves from ask to deny so it cannot be approved accidentally. Each section has a _comment key explaining the rationale. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Single-session firmware enforces one active session on the admin interface. Without logout, the integration holds the session indefinitely, locking out browser access on port 80/443. GET /logout.html observed in contributor HAR (Issue #170). Core calls it after each poll via session.max_concurrent: 1 + actions.logout, then clears the session so the next poll re-authenticates from scratch. No other SB8200 variants are affected (max_concurrent defaults to 0). Related to #170 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When LOAD_AUTH or LOAD_INTEGRITY fires on a modem with session.max_concurrent: 1 and actions.logout configured, attempt a best-effort logout before clearing the session and retrying. Releases any stale server-side session (e.g. after an unclean HA restart) so the immediate re-authentication can succeed. The firmware's logout endpoint does not require credentials — the browser itself erases the cookie before calling it (confirmed via contributor HAR on SB8200 v6, Issue #170). The method does not touch session cookies; that remains clear_session()'s responsibility. Also fixes LogoutExecuted event firing before execute_action() completes; moved to the else branch so it reflects actual success. Updates ORCHESTRATION_SPEC, MODEM_YAML_SPEC, and RUNTIME_POLLING_SPEC to document both logout placements and retire the stale "post-poll only" claim. Adds TestAttemptLogoutBeforeRetry (5 cases) and two orchestrator ordering tests. Related to #170 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
LogoutExecuted now fires in the else branch (after execute_action succeeds), not before. The HA-level test was asserting both LogoutExecuted and LogoutFailed on exception — encoding the pre-existing log-before-action bug. Updated to assert LogoutFailed only and explicitly assert LogoutExecuted is absent on failure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
normalize_html() is called before BeautifulSoup at the loader input boundary but was absent from the spec. Added step 5 update and a follow-up paragraph (matching the SSL handling note style) describing the unclosed-<th> firmware fix. Also added five missing cspell words surfaced by the spec edit: Moto, cablemodem, cmstatus (modem firmware identifiers), fromstring (defusedxml method), artefacts (British spelling). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rsion-pinned prose Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…llowup) Replace stale [MODEL]-tag-pattern guidance in CODE_REVIEW.md and CLAUDE.md with pointers to LOGGING_SPEC.md, which is now the authoritative reference for the typed event taxonomy that shipped in P42 (01a8b2c / 269b601). Add cross-references in ORCHESTRATION_SPEC.md's two logging-contract paragraphs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the "alpha is a development concept only" sentence from RELEASING.md; the table already covers the two shipping tiers. Alpha distribution via branch tracking ended when zip_release:true landed on the default branch and was never replaced. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
pyyaml 6.0.0→6.0.2, requests 2.31.0→2.32.3, cryptography 41.0→44.0 match HA's package_constraints.txt pins. ruff 0.15.13→0.15.15 and black 24.0.0→26.5.1 in dev requirements. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…pointer Clarify Adding Modem Support as intent-based paths (request vs. implement) with a direct link to MODEM_INTAKE_WORKFLOW.md for hardware contributors. Add note that a Core gap report is the contribution — no implementation required. Add "Know the entity model boundary" to AI contribution rules — names the modem-data-only constraint and points to ARCHITECTURE_DECISIONS.md so AI-assisted contributors see it before proposing derived-analysis features. Surface skill portability: /modem-intake references in CONTRIBUTING.md and pull_request_template.md now include the skills/modem-intake.md path for contributors using non-Claude-Code AI tools. Replace generic Code Style bullets with a pointer to docs/CODE_REVIEW.md. chore(dev): broaden Bash allow rule, add jq and shell command guidance Simplify settings.json allow list to Bash(*) — per-command prefix rules were creating permission interrupts for legitimate dev operations. Update CLAUDE.md shell command generation rules: prefer jq for gh output parsing over python3 -c multiline; use fixed /tmp/claude_parse.py for complex logic that jq can't express. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a new service that finds recorder statistics with no registered entity — left behind by mode switches, channel rebonding (ID mode), or prefix changes. Default call returns a full comment-only preview of orphaned entity IDs. Call with execute: true to purge them all directly via HA's recorder API (async_clear_statistics), bypassing the Developer Tools YAML editor entirely. Adds execute tests including batch boundary (150 stats across two internal batches of 100) and a preview-only test that asserts the output contains no runnable YAML. Adds yaml.safe_load validation to all non-empty orphaned result cases. Updates TROUBLESHOOTING.md with the two-step workflow and fixes MD036/MD040 lint warnings. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Purge logs at WARNING (permanent, irreversible). Preview logs at DEBUG (read-only, noise at INFO level). Consistent with the logging pattern in generate_dashboard and convert_channel_identity handlers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…stics The service previews or purges depending on the execute flag, so "list_" was misleading. orphaned_statistics describes the subject without implying read-only. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
handle_list_orphaned renamed to handle_orphaned_statistics to match the factory. services.py module docstring updated to reflect that orphaned_statistics can purge (execute: true) — not preview-only. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
orphaned_statistics service (P32), logout-before-retry fix, SB8200 v6 Basic logout catalog fix, XB7 confirmation, XB7 modulation canonical form normalization. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The deferred path logs N entities but only counts data-dependent sensors; always-created sensors are registered separately at startup. Wording now matches the function name to avoid confusion when comparing against the normal-path "Created N sensor entities" total. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add troubleshooting entry to RELEASING.md for the "Expected — Waiting for status to be reported" symptom (ruleset string mismatch after a workflow job rename). Add corresponding rule to CLAUDE.md's CI job section so the ruleset update is part of any future job rename. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
orphaned_statisticsservice (P32): finds and optionally purges recorder statistics with no registered entity. Preview mode is safe;execute: truepurges permanently. Documented in TROUBLESHOOTING.md under "Ghost Statistics".Test plan
v3.14.0-beta.10on main, push🤖 Generated with Claude Code