{"version":3,"term":{"cols":200,"rows":39,"type":"xterm-256color","version":"xterm.js(6.1.0-beta.197)","theme":{"fg":"#cccccc","bg":"#181818","palette":"#000000:#cd3131:#0dbc79:#e5e510:#2472c8:#bc3fbc:#11a8cd:#e5e5e5:#666666:#f14c4c:#23d18b:#f5f543:#3b8eea:#d670d6:#29b8db:#e5e5e5"}},"timestamp":1777688337,"idle_time_limit":1.5,"command":"bash docs/demo.sh","env":{"SHELL":"/bin/zsh"}}
[0.027, "o", "\u001b[3J\u001b[H\u001b[2J"]
[0.000, "o", "HassCheck — local quality signals for HA custom integrations\r\n------------------------------------------------------------\r\n"]
[2.007, "o", "$ "]
[0.000, "o", "u"]
[0.060, "o", "v"]
[0.055, "o", " "]
[0.057, "o", "r"]
[0.056, "o", "u"]
[0.058, "o", "n"]
[0.053, "o", " "]
[0.047, "o", "h"]
[0.051, "o", "a"]
[0.052, "o", "s"]
[0.053, "o", "s"]
[0.048, "o", "c"]
[0.051, "o", "h"]
[0.054, "o", "e"]
[0.055, "o", "c"]
[0.053, "o", "k"]
[0.052, "o", " "]
[0.052, "o", "c"]
[0.053, "o", "h"]
[0.055, "o", "e"]
[0.054, "o", "c"]
[0.055, "o", "k"]
[0.060, "o", " "]
[0.053, "o", "-"]
[0.052, "o", "-"]
[0.052, "o", "p"]
[0.049, "o", "a"]
[0.053, "o", "t"]
[0.054, "o", "h"]
[0.052, "o", " "]
[0.054, "o", "/"]
[0.055, "o", "v"]
[0.055, "o", "a"]
[0.056, "o", "r"]
[0.052, "o", "/"]
[0.056, "o", "f"]
[0.055, "o", "o"]
[0.056, "o", "l"]
[0.054, "o", "d"]
[0.054, "o", "e"]
[0.055, "o", "r"]
[0.052, "o", "s"]
[0.052, "o", "/"]
[0.053, "o", "5"]
[0.054, "o", "7"]
[0.055, "o", "/"]
[0.055, "o", "d"]
[0.056, "o", "x"]
[0.052, "o", "5"]
[0.055, "o", "4"]
[0.052, "o", "q"]
[0.051, "o", "b"]
[0.052, "o", "g"]
[0.054, "o", "x"]
[0.052, "o", "1"]
[0.052, "o", "s"]
[0.054, "o", "5"]
[0.063, "o", "9"]
[0.057, "o", "b"]
[0.060, "o", "7"]
[0.059, "o", "x"]
[0.053, "o", "b"]
[0.053, "o", "z"]
[0.053, "o", "s"]
[0.050, "o", "c"]
[0.051, "o", "3"]
[0.049, "o", "l"]
[0.055, "o", "c"]
[0.060, "o", "6"]
[0.057, "o", "w"]
[0.051, "o", "0"]
[0.060, "o", "0"]
[0.057, "o", "0"]
[0.058, "o", "0"]
[0.058, "o", "g"]
[0.062, "o", "n"]
[0.057, "o", "/"]
[0.061, "o", "T"]
[0.054, "o", "/"]
[0.056, "o", "h"]
[0.057, "o", "a"]
[0.055, "o", "s"]
[0.052, "o", "s"]
[0.057, "o", "c"]
[0.059, "o", "h"]
[0.055, "o", "e"]
[0.053, "o", "c"]
[0.053, "o", "k"]
[0.053, "o", "-"]
[0.054, "o", "d"]
[0.051, "o", "e"]
[0.054, "o", "m"]
[0.060, "o", "o"]
[0.058, "o", "."]
[0.055, "o", "X"]
[0.059, "o", "X"]
[0.058, "o", "X"]
[0.057, "o", "X"]
[0.060, "o", "X"]
[0.060, "o", "X"]
[0.052, "o", "."]
[0.053, "o", "M"]
[0.055, "o", "w"]
[0.053, "o", "J"]
[0.054, "o", "e"]
[0.051, "o", "6"]
[0.054, "o", "G"]
[0.056, "o", "8"]
[0.053, "o", "G"]
[0.057, "o", "a"]
[0.055, "o", "D"]
[0.056, "o", "\r\n"]
[0.970, "o", "\u001b[37m⠙\u001b[0m \u001b[2m                                                                                                                                                                                                      \u001b[0m\r\u001b[2K\u001b[37m⠙\u001b[0m \u001b[2mResolving dependencies...                                                                                                                                                                             \u001b[0m"]
[0.008, "o", "\r\u001b[2K"]
[0.002, "o", "\u001b[37m⠋\u001b[0m \u001b[2mResolving dependencies...                                                                                                                                                                             \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠙\u001b[0m \u001b[2mResolving dependencies...                                                                                                                                                                             \u001b[0m"]
[0.004, "o", "\r\u001b[2K"]
[0.000, "o", "\u001b[37m⠋\u001b[0m \u001b[2mResolving dependencies...                                                                                                                                                                             \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠙\u001b[0m \u001b[2mResolving dependencies...                                                                                                                                                                             \u001b[0m"]
[0.008, "o", "\r\u001b[2K\u001b[37m⠙\u001b[0m \u001b[2mhasscheck==0.11.0                                                                                                                                                                                     \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠙\u001b[0m \u001b[2mhasscheck==0.11.0                                                                                                                                                                                     \u001b[0m"]
[0.197, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mhasscheck==0.11.0                                                                                                                                                                                     \u001b[0m"]
[0.019, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mhttpx==0.28.1                                                                                                                                                                                         \u001b[0m"]
[0.006, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mpackaging==26.2                                                                                                                                                                                       \u001b[0m\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mpydantic==2.13.3                                                                                                                                                                                      \u001b[0m"]
[0.084, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mpydantic-core==2.46.3                                                                                                                                                                                 \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mpyyaml==6.0.3                                                                                                                                                                                         \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mrich==15.0.0                                                                                                                                                                                          \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mtyper==0.25.1                                                                                                                                                                                         \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mpre-commit==4.6.0                                                                                                                                                                                     \u001b[0m"]
[0.001, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mpytest==9.0.3                                                                                                                                                                                         \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mruff==0.15.12                                                                                                                                                                                         \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2manyio==4.13.0                                                                                                                                                                                         \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mcertifi==2026.4.22                                                                                                                                                                                    \u001b[0m\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mhttpcore==1.0.9                                                                                                                                                                                       \u001b[0m\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2midna==3.13                                                                                                                                                                                            \u001b[0m\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mannotated-types==0.7.0                                                                                                                                                                                \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mtyping-extensions==4.15.0                                                                                                                                                                             \u001b[0m"]
[0.001, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mtyping-extensions==4.15.0                                                                                                                                                                             \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mtyping-inspection==0.4.2                                                                                                                                                                              \u001b[0m"]
[0.055, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mmarkdown-it-py==4.0.0                                                                                                                                                                                 \u001b[0m"]
[0.012, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mpygments==2.20.0                                                                                                                                                                                      \u001b[0m"]
[0.001, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mannotated-doc==0.0.4                                                                                                                                                                                  \u001b[0m"]
[0.000, "o", "\r\u001b[2K\u001b[37m⠹\u001b[0m \u001b[2mclick==8.3.3                                                                                                                                                                                          \u001b[0m"]
[0.026, "o", "\r\u001b[2K\u001b[37m⠸\u001b[0m \u001b[2mh11==0.16.0                                                                                                                                                                                           \u001b[0m"]
[0.042, "o", "\r\u001b[2K\u001b[37m⠸\u001b[0m \u001b[2m                                                                                                                                                                                                      \u001b[0m\r\u001b[2K"]
[0.451, "o", "\u001b[1mHassCheck Summary\u001b[0m\r\n"]
[0.000, "o", "\r\n"]
[0.001, "o", "Diagnostics/Repairs: \u001b[1;36m1\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m3\u001b[0m\r\n"]
[0.000, "o", "Docs/Support: \u001b[1;36m1\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m6\u001b[0m\r\n"]
[0.000, "o", "HACS Structure: \u001b[1;36m1\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m3\u001b[0m\r\n"]
[0.000, "o", "Maintenance: \u001b[1;36m0\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m1\u001b[0m\r\n"]
[0.000, "o", "Maintenance Signals: \u001b[1;36m0\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m1\u001b[0m\r\n"]
[0.000, "o", "Manifest Metadata: \u001b[1;36m10\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m14\u001b[0m\r\n"]
[0.000, "o", "Modern HA Patterns: \u001b[1;36m2\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m9\u001b[0m\r\n"]
[0.000, "o", "Tests/CI: \u001b[1;36m0\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m2\u001b[0m\r\n"]
[0.000, "o", "\r\n"]
[0.000, "o", "Overall: Informational only\r\n"]
[0.000, "o", "Security Review: Not performed\r\n"]
[0.000, "o", "Official HA Tier: Not assigned\r\n"]
[0.000, "o", "HACS Acceptance: Not guaranteed\r\n"]
[0.000, "o", "\r\n"]
[0.007, "o", "\u001b[3m                                                                                                Findings                                                                                                \u001b[0m\r\n┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\r\n┃\u001b[1m \u001b[0m\u001b[1mStatus \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mRule                                     \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mMessage                                                                                   "]
[0.000, "o", "                                                    \u001b[0m\u001b[1m \u001b[0m┃\r\n┡━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩\r\n│ ✅ PASS │ hacs.custom_components.exists             │ Repository contains a custom_components directory.                                                                                             │\r\n│ ⚠️ WARN │ hacs.file.parseable                       │ hacs.json is missing. HACS metadata cannot be inspected yet.               "]
[0.000, "o", "                                                                    │\r\n│ ⚠️ WARN │ brand.icon.exists                         │ Integration does not include brand/icon.png. HACS and Home Assistant brand image support cannot be fully inspected.                            │\r\n│ ✅ PASS │ manifest.exists                           │ Integration manifest exists.                                                                                                                   │\r\n│ ✅ PASS │ manifest.domain.exists                    │ manifest.json defines a domain.                                                                                                                │\r\n│ ✅ PASS │ manifest.name.exists                      │ manifest.json defines a name.                                                                                                                  │\r\n│ ✅ PASS │ manifest.version.exists                   │ manifest.json defines a version.         "]
[0.000, "o", "                                                                                                      │\r\n│ ✅ PASS │ manifest.documentation.exists             │ manifest.json defines documentation.                                                                                                           │\r\n│ ✅ PASS │ manifest.issue_tracker.exists             │ manifest.json defines an issue tracker.                                                                                                        │\r\n│ ✅ PASS │ manifest.codeowners.exists                │ manifest.json defines at least one code owner.                                                                                                 │\r\n│ ❌ FAIL │ manifest.domain.matches_directory         │ manifest.json domain \"wrong_domain\" does not match integration directory \"demo_bad\".                                                           │\r\n│ ✅ PASS │ manifest.iot_class.exists                 │ manifest.j"]
[0.000, "o", "son declares iot_class.                                                                                                              │\r\n│ ❌ FAIL │ manifest.iot_class.valid                  │ manifest.json iot_class \"not_a_valid_class\" is not a recognized value (expected one of: assumed_state, calculated, cloud_polling, cloud_push,  │\r\n│         │                                           │ local_polling, local_push).                                                                                                                    │\r\n│ ⚠️ WARN │ manifest.integration_type.exists          │ manifest.json does not declare integration_type; recommended for Home Assistant integrations.                                                  │\r\n│ ➖ N/A  │ manifest.integration_type.valid           │ manifest.json does not declare integration_type; value validation is skipped.                                                                  │\r\n│ ✅ PASS │ manifest.requirements.i"]
[0.000, "o", "s_list             │ manifest.requirements is a JSON array.                                                                                                         │\r\n│ ✅ PASS │ manifest.requirements.entries_well_formed │ All manifest.requirements entries are valid PEP 508 specifiers.                                                                                │\r\n│ ⚠️ WARN │ manifest.requirements.no_git_or_url_specs │ manifest.requirements contains non-PyPI install specs: git+https://github.com/example/lib.git. Use PyPI package names to ensure installability │\r\n│         │                                           │ via HACS and pip.                                                                                                                              │\r\n│ ⚠️ WARN │ config_flow.user_step.exists              │ config_flow.py does not define async_step_user; users cannot start setup from the UI.                                                          │\r\n│ "]
[0.000, "o", "✅ PASS │ config_flow.file.exists                   │ Integration includes config_flow.py.                                                                                                           │\r\n│ ✅ PASS │ config_flow.manifest_flag_consistent      │ config_flow.py exists and manifest.json sets config_flow: true.                                                                                │\r\n│ ⚠️ WARN │ config_flow.reauth_step.exists            │ config_flow.py does not define async_step_reauth or async_step_reauth_confirm; reauthentication is not supported.                              │\r\n│ ⚠️ WARN │ config_flow.reconfigure_step.exists       │ config_flow.py does not define async_step_reconfigure; users cannot update settings from the UI.                                               │\r\n│ ⚠️ WARN │ config_flow.unique_id.set                 │ config_flow.py does not call async_set_unique_id; duplicate config entries may occur.                           "]
[0.000, "o", "                               │\r\n│ ⚠️ WARN │ config_flow.connection_test               │ No connection test detected in config_flow.py. Discovery-flow steps (async_step_user, async_step_zeroconf, etc.) appear to only call flow      │\r\n│         │                                           │ plumbing methods.                                                                                                                              │\r\n│ ✅ PASS │ diagnostics.file.exists                   │ Integration includes diagnostics.py.                                                                                                           │\r\n│ ⚠️ WARN │ diagnostics.redaction.used                │ diagnostics returns entry.data without redaction — likely exposes secrets; use async_redact_data.                                              │\r\n│ ⚠️ WARN │ repairs.file.exists                       │ Integration does not include repairs.py; user-fixable repair flows cann"]
[0.000, "o", "ot be inspected.                                                        │\r\n│ ✅ PASS │ docs.readme.exists                        │ Repository contains README.md.                                                                                                                 │\r\n│ ⚠️ WARN │ docs.installation.exists                  │ README does not appear to contain a readme installation section section (no heading matching: hacs, install, installation, manual install,     │\r\n│         │                                           │ manual installation).                                                                                                                          │\r\n│ ⚠️ WARN │ docs.configuration.exists                 │ README does not appear to contain a readme configuration section section (no heading matching: configuration, configure, options, setup).      │\r\n│ ⚠️ WARN │ docs.troubleshooting.exists               │ README does not appear to contai"]
[0.000, "o", "n a readme troubleshooting section section (no heading matching: debug, faq, known issues, known limitations,  │\r\n│         │                                           │ support, troubleshoot, troubleshooting).                                                                                                       │\r\n│ ⚠️ WARN │ docs.removal.exists                       │ README does not appear to contain a readme removal section section (no heading matching: removal, remove, uninstall, uninstalling).            │\r\n│ ⚠️ WARN │ docs.privacy.exists                       │ README does not appear to contain a readme privacy section section (no heading matching: cloud, data, local, privacy, telemetry).              │\r\n│ ⚠️ WARN │ repo.license.exists                       │ Repository does not contain a recognized license file.                                                                                         │\r\n│ ⚠️ WARN │ tests.folder.exists                 "]
[0.000, "o", "      │ Repository does not contain a tests directory; automated test coverage cannot be inspected.                                                    │\r\n│ ➖ N/A  │ tests.config_flow.detected                │ no tests/ folder; tests.folder.exists owns this signal.                                                                                        │\r\n│ ➖ N/A  │ tests.setup_entry.detected                │ no tests/ folder; tests.folder.exists owns this signal.                                                                                        │\r\n│ ➖ N/A  │ tests.unload.detected                     │ no tests/ folder; tests.folder.exists owns this signal.                                                                                        │\r\n│ ⚠️ WARN │ ci.github_actions.exists                  │ Repository does not contain a GitHub Actions workflow file.                                                                                    │\r\n│ ⚠️ WARN │"]
[0.000, "o", " init.async_setup_entry.defined            │ __init__.py does not define async_setup_entry; the integration may not support config entries.                                                 │\r\n│ ⚠️ WARN │ init.runtime_data.used                    │ __init__.py does not use entry.runtime_data; consider migrating from hass.data to entry.runtime_data.                                          │\r\n│ ➖ N/A  │ entity.unique_id.set                      │ No entity platform files found in the integration directory.                                                                                   │\r\n│ ➖ N/A  │ entity.has_entity_name.set                │ No entity platform files found in the integration directory.                                                                                   │\r\n│ ➖ N/A  │ entity.device_info.set                    │ No entity platform files found in the integration directory.                                                                      "]
[0.000, "o", "             │\r\n│ ➖ N/A  │ maintenance.recent_commit.detected        │ repository is not a git checkout (no .git directory)                                                                                           │\r\n│ ➖ N/A  │ maintenance.recent_release.detected       │ repository is not a git checkout (no .git directory)                                                                                           │\r\n│ ⚠️ WARN │ maintenance.changelog.exists              │ Repository does not contain a recognized changelog file (CHANGELOG.md, CHANGELOG, HISTORY.md, HISTORY, RELEASES.md, NEWS.md).                  │\r\n└─────────┴───────────────────────────────────────────┴────────────────────────────────────────────────────────────────────"]
[0.000, "o", "────────────────────────────────────────────────────────────────────────────┘\r\n"]
[0.001, "o", "\r\n"]
[0.000, "o", "\u001b[1mFix suggestions\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mhacs.file.parseable\u001b[0m\r\n"]
[0.000, "o", "    Add a repository-level hacs.json file, even if it starts as an empty JSON object.\r\n"]
[0.000, "o", "  \u001b[1mbrand.icon.exists\u001b[0m\r\n"]
[0.000, "o", "    Add custom_components/\u001b[1m<\u001b[0m\u001b[1;95mdomain\u001b[0m\u001b[1m>\u001b[0m\u001b[35m/brand/\u001b[0m\u001b[95micon.png.\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mmanifest.domain.matches_directory\u001b[0m\r\n"]
[0.000, "o", "    Rename the integration directory or update manifest.domain so both use the same stable domain.\r\n"]
[0.000, "o", "  \u001b[1mmanifest.iot_class.valid\u001b[0m\r\n"]
[0.000, "o", "    Set iot_class to one of: assumed_state, calculated, cloud_polling, cloud_push, local_polling, local_push.\r\n"]
[0.001, "o", "  \u001b[1mmanifest.integration_type.exists\u001b[0m\r\n"]
[0.000, "o", "    Add an integration_type field to manifest.json.\r\n"]
[0.000, "o", "  \u001b[1mmanifest.integration_type.valid\u001b[0m\r\n"]
[0.000, "o", "    Add an integration_type field to manifest.json.\r\n"]
[0.000, "o", "  \u001b[1mmanifest.requirements.no_git_or_url_specs\u001b[0m\r\n"]
[0.000, "o", "    Replace git/URL specs with published PyPI package names.\r\n"]
[0.000, "o", "  \u001b[1mconfig_flow.user_step.exists\u001b[0m\r\n"]
[0.000, "o", "    Add async_step_user to your ConfigFlow class in config_flow.py.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_config_flow_handler/#defining-the-flow\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mconfig_flow.reauth_step.exists\u001b[0m\r\n"]
[0.001, "o", "    Add async_step_reauth \u001b[1m(\u001b[0mand optionally async_step_reauth_confirm\u001b[1m)\u001b[0m to your ConfigFlow class.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_config_flow_handler/#reauthentication\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mconfig_flow.reconfigure_step.exists\u001b[0m\r\n"]
[0.000, "o", "    Add async_step_reconfigure to your ConfigFlow class.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_config_flow_handler/#reconfigure\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mconfig_flow.unique_id.set\u001b[0m\r\n"]
[0.000, "o", "    Call \u001b[1;35mself.async_set_unique_id\u001b[0m\u001b[1m(\u001b[0m\u001b[1m<\u001b[0m\u001b[1;95mdevice-identifier\u001b[0m\u001b[1m>\u001b[0m\u001b[1m)\u001b[0m before creating the entry.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_config_flow_handler/#unique-ids\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mconfig_flow.connection_test\u001b[0m\r\n"]
[0.000, "o", "    Add a connection test \u001b[1m(\u001b[0me.g. await \u001b[1;35mvalidate_input\u001b[0m\u001b[1m(\u001b[0mhass, data\u001b[1m)\u001b[0m\u001b[1m)\u001b[0m inside async_step_user.\r\n"]
[0.001, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_config_flow_handler/#defining-the-flow\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mdiagnostics.redaction.used\u001b[0m\r\n"]
[0.000, "o", "    Use async_redact_data or a local redaction helper before returning entry data.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/core/integration/diagnostics/\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mrepairs.file.exists\u001b[0m\r\n"]
[0.000, "o", "    Add repairs.py when the integration has user-fixable repair scenarios.\r\n"]
[0.000, "o", "    Run: hasscheck scaffold repairs\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/core/integration/repairs/\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mdocs.installation.exists\u001b[0m\r\n"]
[0.000, "o", "    Add an Installation section to README.md covering HACS and/or manual installation steps.\r\n"]
[0.000, "o", "  \u001b[1mdocs.configuration.exists\u001b[0m\r\n"]
[0.001, "o", "    Add a Configuration section to README.md describing available options and setup steps.\r\n"]
[0.000, "o", "  \u001b[1mdocs.troubleshooting.exists\u001b[0m\r\n"]
[0.000, "o", "    Add a Troubleshooting or FAQ section to README.md with known issues and debug steps.\r\n"]
[0.000, "o", "  \u001b[1mdocs.removal.exists\u001b[0m\r\n"]
[0.000, "o", "    Add a Removal or Uninstall section to README.md with steps to cleanly remove the integration.\r\n"]
[0.000, "o", "  \u001b[1mdocs.privacy.exists\u001b[0m\r\n"]
[0.000, "o", "    Add a Privacy or Data section to README.md describing what data the integration collects or sends.\r\n"]
[0.000, "o", "  \u001b[1mrepo.license.exists\u001b[0m\r\n"]
[0.000, "o", "    Add a repository license file such as LICENSE.\r\n"]
[0.000, "o", "  \u001b[1mtests.folder.exists\u001b[0m\r\n"]
[0.001, "o", "    Add a tests/ directory with pytest-based integration tests.\r\n  \u001b[1mci.github_actions.exists\u001b[0m\r\n"]
[0.000, "o", "    Add a .github/workflows/*.yml workflow that runs tests.\r\n"]
[0.000, "o", "    Run: hasscheck scaffold github-action\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://docs.github.com/actions/using-workflows/about-workflows\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1minit.async_setup_entry.defined\u001b[0m\r\n"]
[0.000, "o", "    Add \u001b[1;35masync_setup_entry\u001b[0m\u001b[1m(\u001b[0mhass, entry\u001b[1m)\u001b[0m to __init__.py.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_index/#an-example\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1minit.runtime_data.used\u001b[0m\r\n"]
[0.000, "o", "    Replace hass.data\u001b[1m[\u001b[0mDOMAIN\u001b[1m]\u001b[0m with entry.runtime_data = \u001b[1m<\u001b[0m\u001b[1;95myour\u001b[0m\u001b[39m object\u001b[0m\u001b[1m>\u001b[0m.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_index/#runtime_data\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mmaintenance.changelog.exists\u001b[0m\r\n"]
[0.001, "o", "    Add a CHANGELOG.md at the repository root describing changes per version.\r\n"]
[3.028, "o", "$ "]
[0.000, "o", "u"]
[0.056, "o", "v"]
[0.054, "o", " "]
[0.053, "o", "r"]
[0.057, "o", "u"]
[0.055, "o", "n"]
[0.056, "o", " "]
[0.058, "o", "h"]
[0.055, "o", "a"]
[0.052, "o", "s"]
[0.057, "o", "s"]
[0.056, "o", "c"]
[0.052, "o", "h"]
[0.057, "o", "e"]
[0.055, "o", "c"]
[0.056, "o", "k"]
[0.056, "o", " "]
[0.056, "o", "e"]
[0.057, "o", "x"]
[0.054, "o", "p"]
[0.052, "o", "l"]
[0.055, "o", "a"]
[0.052, "o", "i"]
[0.059, "o", "n"]
[0.056, "o", " "]
[0.057, "o", "m"]
[0.051, "o", "a"]
[0.073, "o", "n"]
[0.053, "o", "i"]
[0.054, "o", "f"]
[0.050, "o", "e"]
[0.055, "o", "s"]
[0.057, "o", "t"]
[0.058, "o", "."]
[0.055, "o", "d"]
[0.049, "o", "o"]
[0.050, "o", "m"]
[0.054, "o", "a"]
[0.061, "o", "i"]
[0.051, "o", "n"]
[0.055, "o", "."]
[0.053, "o", "m"]
[0.052, "o", "a"]
[0.053, "o", "t"]
[0.054, "o", "c"]
[0.055, "o", "h"]
[0.053, "o", "e"]
[0.059, "o", "s"]
[0.056, "o", "_"]
[0.059, "o", "d"]
[0.056, "o", "i"]
[0.056, "o", "r"]
[0.056, "o", "e"]
[0.058, "o", "c"]
[0.055, "o", "t"]
[0.053, "o", "o"]
[0.061, "o", "r"]
[0.058, "o", "y"]
[0.053, "o", "\r\n"]
[1.003, "o", "\u001b[1mmanifest.domain.matches_directory\u001b[0m\r\n"]
[0.000, "o", "Version: \u001b[1;36m1.0\u001b[0m.\u001b[1;36m0\u001b[0m\r\n"]
[0.000, "o", "Category: manifest_metadata\r\n"]
[0.000, "o", "Severity: required\r\n"]
[0.001, "o", "Overridable: false\r\n"]
[0.000, "o", "Why: The manifest domain must match the name of the integration directory under custom_components/. A mismatch causes Home Assistant to silently misidentify the integration, breaking HACS discovery \r\nand core platform loading. Note: this rule cannot be overridden via hasscheck.yaml.\r\n"]
[0.000, "o", "Source: \u001b[4;94mhttps://developers.home-assistant.io/docs/creating_integration_manifest\u001b[0m\r\n"]
[3.036, "o", "$ "]
[0.000, "o", "u"]
[0.055, "o", "v"]
[0.057, "o", " "]
[0.059, "o", "r"]
[0.053, "o", "u"]
[0.053, "o", "n"]
[0.057, "o", " "]
[0.061, "o", "h"]
[0.059, "o", "a"]
[0.061, "o", "s"]
[0.058, "o", "s"]
[0.054, "o", "c"]
[0.059, "o", "h"]
[0.058, "o", "e"]
[0.055, "o", "c"]
[0.060, "o", "k"]
[0.052, "o", " "]
[0.058, "o", "s"]
[0.053, "o", "c"]
[0.055, "o", "a"]
[0.055, "o", "f"]
[0.055, "o", "f"]
[0.058, "o", "o"]
[0.054, "o", "l"]
[0.055, "o", "d"]
[0.058, "o", " "]
[0.052, "o", "d"]
[0.052, "o", "i"]
[0.053, "o", "a"]
[0.055, "o", "g"]
[0.059, "o", "n"]
[0.060, "o", "o"]
[0.058, "o", "s"]
[0.057, "o", "t"]
[0.058, "o", "i"]
[0.055, "o", "c"]
[0.055, "o", "s"]
[0.055, "o", " "]
[0.057, "o", "-"]
[0.060, "o", "-"]
[0.057, "o", "p"]
[0.059, "o", "a"]
[0.056, "o", "t"]
[0.049, "o", "h"]
[0.060, "o", " "]
[0.058, "o", "/"]
[0.056, "o", "v"]
[0.058, "o", "a"]
[0.060, "o", "r"]
[0.061, "o", "/"]
[0.056, "o", "f"]
[0.059, "o", "o"]
[0.059, "o", "l"]
[0.059, "o", "d"]
[0.059, "o", "e"]
[0.052, "o", "r"]
[0.057, "o", "s"]
[0.058, "o", "/"]
[0.055, "o", "5"]
[0.052, "o", "7"]
[0.059, "o", "/"]
[0.059, "o", "d"]
[0.060, "o", "x"]
[0.063, "o", "5"]
[0.056, "o", "4"]
[0.053, "o", "q"]
[0.056, "o", "b"]
[0.053, "o", "g"]
[0.057, "o", "x"]
[0.056, "o", "1"]
[0.054, "o", "s"]
[0.052, "o", "5"]
[0.058, "o", "9"]
[0.053, "o", "b"]
[0.054, "o", "7"]
[0.054, "o", "x"]
[0.054, "o", "b"]
[0.060, "o", "z"]
[0.057, "o", "s"]
[0.060, "o", "c"]
[0.058, "o", "3"]
[0.055, "o", "l"]
[0.061, "o", "c"]
[0.054, "o", "6"]
[0.058, "o", "w"]
[0.050, "o", "0"]
[0.052, "o", "0"]
[0.053, "o", "0"]
[0.054, "o", "0"]
[0.054, "o", "g"]
[0.061, "o", "n"]
[0.061, "o", "/"]
[0.059, "o", "T"]
[0.060, "o", "/"]
[0.060, "o", "h"]
[0.061, "o", "a"]
[0.054, "o", "s"]
[0.060, "o", "s"]
[0.054, "o", "c"]
[0.058, "o", "h"]
[0.058, "o", "e"]
[0.057, "o", "c"]
[0.056, "o", "k"]
[0.060, "o", "-"]
[0.057, "o", "d"]
[0.051, "o", "e"]
[0.057, "o", "m"]
[0.058, "o", "o"]
[0.061, "o", "."]
[0.059, "o", "X"]
[0.061, "o", "X"]
[0.061, "o", "X"]
[0.057, "o", "X"]
[0.059, "o", "X"]
[0.053, "o", "X"]
[0.050, "o", "."]
[0.050, "o", "M"]
[0.049, "o", "w"]
[0.051, "o", "J"]
[0.050, "o", "e"]
[0.055, "o", "6"]
[0.057, "o", "G"]
[0.055, "o", "8"]
[0.053, "o", "G"]
[0.055, "o", "a"]
[0.055, "o", "D"]
[0.052, "o", " "]
[0.057, "o", "-"]
[0.052, "o", "-"]
[0.056, "o", "d"]
[0.052, "o", "r"]
[0.054, "o", "y"]
[0.056, "o", "-"]
[0.056, "o", "r"]
[0.057, "o", "u"]
[0.055, "o", "n"]
[0.055, "o", "\r\n"]
[0.999, "o", "\u001b[2mDomain:\u001b[0m demo_bad\r\n# Generated by hasscheck — review before committing.\r\n# Docs: https://developers.home-assistant.io/docs/core/integration/diagnostics/\r\nfrom __future__ import annotations\r\n\r\nfrom typing import Any\r\n\r\nfrom homeassistant.config_entries import ConfigEntry\r\nfrom homeassistant.core import HomeAssistant\r\n\r\n# Add any keys that should be redacted from diagnostics output.\r\n# Common sensitive fields: API keys, tokens, passwords, location data.\r\n#\r\n# Upgrade path: replace redact_data() below with the official HA helper:\r\n#   from homeassistant.components.diagnostics import async_redact_data\r\n# and call: async_redact_data(dict(entry.data), TO_REDACT)\r\nTO_REDACT: list[str] = [\r\n    \"api_key\",\r\n    \"password\",\r\n    \"token\",\r\n    \"latitude\",\r\n    \"longitude\",\r\n]\r\n\r\n\r\nasync def async_get_config_entry_diagnostics(\r\n    hass: HomeAssistant,\r\n    entry: ConfigEntry,\r\n) -> dict[str, Any]:\r\n    \"\"\"Return diagnostics for a config entry.\"\"\"\r\n    return {\r\n        \"entry\": redact_data(dict(entry.data), TO_"]
[0.000, "o", "REDACT),\r\n        \"options\": redact_data(dict(entry.options), TO_REDACT),\r\n    }\r\n\r\n\r\ndef redact_data(data: dict[str, Any], to_redact: list[str]) -> dict[str, Any]:\r\n    \"\"\"Redact sensitive data from a dict.\"\"\"\r\n    redacted = dict(data)\r\n    for key in to_redact:\r\n        if key in redacted:\r\n            redacted[key] = \"**REDACTED**\"\r\n    return redacted\r\n\r\n"]
[3.030, "o", "$ "]
[0.000, "o", "u"]
[0.054, "o", "v"]
[0.057, "o", " "]
[0.061, "o", "r"]
[0.059, "o", "u"]
[0.058, "o", "n"]
[0.057, "o", " "]
[0.057, "o", "h"]
[0.060, "o", "a"]
[0.060, "o", "s"]
[0.053, "o", "s"]
[0.055, "o", "c"]
[0.054, "o", "h"]
[0.055, "o", "e"]
[0.057, "o", "c"]
[0.060, "o", "k"]
[0.055, "o", " "]
[0.055, "o", "s"]
[0.052, "o", "c"]
[0.055, "o", "a"]
[0.057, "o", "f"]
[0.052, "o", "f"]
[0.053, "o", "o"]
[0.058, "o", "l"]
[0.056, "o", "d"]
[0.054, "o", " "]
[0.053, "o", "d"]
[0.053, "o", "i"]
[0.056, "o", "a"]
[0.057, "o", "g"]
[0.057, "o", "n"]
[0.052, "o", "o"]
[0.059, "o", "s"]
[0.054, "o", "t"]
[0.054, "o", "i"]
[0.051, "o", "c"]
[0.057, "o", "s"]
[0.054, "o", " "]
[0.056, "o", "-"]
[0.057, "o", "-"]
[0.060, "o", "p"]
[0.057, "o", "a"]
[0.051, "o", "t"]
[0.057, "o", "h"]
[0.057, "o", " "]
[0.053, "o", "/"]
[0.053, "o", "v"]
[0.055, "o", "a"]
[0.056, "o", "r"]
[0.057, "o", "/"]
[0.053, "o", "f"]
[0.055, "o", "o"]
[0.057, "o", "l"]
[0.055, "o", "d"]
[0.055, "o", "e"]
[0.054, "o", "r"]
[0.061, "o", "s"]
[0.052, "o", "/"]
[0.053, "o", "5"]
[0.052, "o", "7"]
[0.054, "o", "/"]
[0.056, "o", "d"]
[0.053, "o", "x"]
[0.059, "o", "5"]
[0.051, "o", "4"]
[0.054, "o", "q"]
[0.056, "o", "b"]
[0.053, "o", "g"]
[0.055, "o", "x"]
[0.062, "o", "1"]
[0.054, "o", "s"]
[0.057, "o", "5"]
[0.052, "o", "9"]
[0.052, "o", "b"]
[0.057, "o", "7"]
[0.060, "o", "x"]
[0.055, "o", "b"]
[0.056, "o", "z"]
[0.060, "o", "s"]
[0.055, "o", "c"]
[0.055, "o", "3"]
[0.058, "o", "l"]
[0.056, "o", "c"]
[0.052, "o", "6"]
[0.057, "o", "w"]
[0.056, "o", "0"]
[0.053, "o", "0"]
[0.048, "o", "0"]
[0.053, "o", "0"]
[0.051, "o", "g"]
[0.052, "o", "n"]
[0.052, "o", "/"]
[0.056, "o", "T"]
[0.058, "o", "/"]
[0.058, "o", "h"]
[0.055, "o", "a"]
[0.053, "o", "s"]
[0.058, "o", "s"]
[0.054, "o", "c"]
[0.052, "o", "h"]
[0.059, "o", "e"]
[0.059, "o", "c"]
[0.053, "o", "k"]
[0.052, "o", "-"]
[0.055, "o", "d"]
[0.056, "o", "e"]
[0.056, "o", "m"]
[0.054, "o", "o"]
[0.059, "o", "."]
[0.053, "o", "X"]
[0.056, "o", "X"]
[0.057, "o", "X"]
[0.061, "o", "X"]
[0.059, "o", "X"]
[0.053, "o", "X"]
[0.059, "o", "."]
[0.056, "o", "M"]
[0.057, "o", "w"]
[0.053, "o", "J"]
[0.053, "o", "e"]
[0.056, "o", "6"]
[0.057, "o", "G"]
[0.056, "o", "8"]
[0.060, "o", "G"]
[0.056, "o", "a"]
[0.057, "o", "D"]
[0.052, "o", " "]
[0.056, "o", "-"]
[0.058, "o", "-"]
[0.059, "o", "f"]
[0.054, "o", "o"]
[0.056, "o", "r"]
[0.060, "o", "c"]
[0.056, "o", "e"]
[0.056, "o", "\r\n"]
[1.018, "o", "\u001b[2mDomain:\u001b[0m demo_bad\r\n"]
[0.000, "o", "\u001b[32mCreated:\u001b[0m \u001b[35m/private/var/folders/57/dx54qbgx1s59b7xbzsc3lc6w0000gn/T/hasscheck-demo.XXXXXX.MwJe6G8GaD/custom_components/demo_bad/\u001b[0m\u001b[95mdiagnostics.py\u001b[0m\r\n"]
[3.034, "o", "$ "]
[0.000, "o", "u"]
[0.055, "o", "v"]
[0.055, "o", " "]
[0.052, "o", "r"]
[0.055, "o", "u"]
[0.059, "o", "n"]
[0.057, "o", " "]
[0.057, "o", "h"]
[0.058, "o", "a"]
[0.062, "o", "s"]
[0.055, "o", "s"]
[0.052, "o", "c"]
[0.050, "o", "h"]
[0.053, "o", "e"]
[0.060, "o", "c"]
[0.059, "o", "k"]
[0.062, "o", " "]
[0.057, "o", "c"]
[0.058, "o", "h"]
[0.056, "o", "e"]
[0.049, "o", "c"]
[0.054, "o", "k"]
[0.051, "o", " "]
[0.057, "o", "-"]
[0.062, "o", "-"]
[0.056, "o", "p"]
[0.057, "o", "a"]
[0.056, "o", "t"]
[0.057, "o", "h"]
[0.067, "o", " "]
[0.060, "o", "/"]
[0.054, "o", "v"]
[0.054, "o", "a"]
[0.059, "o", "r"]
[0.057, "o", "/"]
[0.064, "o", "f"]
[0.059, "o", "o"]
[0.060, "o", "l"]
[0.053, "o", "d"]
[0.051, "o", "e"]
[0.053, "o", "r"]
[0.048, "o", "s"]
[0.053, "o", "/"]
[0.052, "o", "5"]
[0.058, "o", "7"]
[0.061, "o", "/"]
[0.052, "o", "d"]
[0.056, "o", "x"]
[0.054, "o", "5"]
[0.052, "o", "4"]
[0.054, "o", "q"]
[0.050, "o", "b"]
[0.055, "o", "g"]
[0.054, "o", "x"]
[0.051, "o", "1"]
[0.053, "o", "s"]
[0.053, "o", "5"]
[0.053, "o", "9"]
[0.059, "o", "b"]
[0.053, "o", "7"]
[0.053, "o", "x"]
[0.053, "o", "b"]
[0.054, "o", "z"]
[0.057, "o", "s"]
[0.055, "o", "c"]
[0.058, "o", "3"]
[0.056, "o", "l"]
[0.052, "o", "c"]
[0.056, "o", "6"]
[0.056, "o", "w"]
[0.055, "o", "0"]
[0.055, "o", "0"]
[0.057, "o", "0"]
[0.054, "o", "0"]
[0.054, "o", "g"]
[0.058, "o", "n"]
[0.062, "o", "/"]
[0.062, "o", "T"]
[0.057, "o", "/"]
[0.063, "o", "h"]
[0.057, "o", "a"]
[0.051, "o", "s"]
[0.059, "o", "s"]
[0.061, "o", "c"]
[0.058, "o", "h"]
[0.057, "o", "e"]
[0.059, "o", "c"]
[0.049, "o", "k"]
[0.052, "o", "-"]
[0.056, "o", "d"]
[0.061, "o", "e"]
[0.060, "o", "m"]
[0.059, "o", "o"]
[0.056, "o", "."]
[0.058, "o", "X"]
[0.060, "o", "X"]
[0.054, "o", "X"]
[0.057, "o", "X"]
[0.056, "o", "X"]
[0.056, "o", "X"]
[0.056, "o", "."]
[0.053, "o", "M"]
[0.053, "o", "w"]
[0.055, "o", "J"]
[0.057, "o", "e"]
[0.057, "o", "6"]
[0.058, "o", "G"]
[0.054, "o", "8"]
[0.055, "o", "G"]
[0.055, "o", "a"]
[0.058, "o", "D"]
[0.059, "o", "\r\n"]
[1.032, "o", "\u001b[1mHassCheck Summary\u001b[0m\r\n"]
[0.000, "o", "\r\n"]
[0.000, "o", "Diagnostics/Repairs: \u001b[1;36m2\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m3\u001b[0m\r\n"]
[0.000, "o", "Docs/Support: \u001b[1;36m1\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m6\u001b[0m\r\n"]
[0.000, "o", "HACS Structure: \u001b[1;36m1\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m3\u001b[0m\r\n"]
[0.000, "o", "Maintenance: \u001b[1;36m0\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m1\u001b[0m\r\n"]
[0.000, "o", "Maintenance Signals: \u001b[1;36m0\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m1\u001b[0m\r\n"]
[0.000, "o", "Manifest Metadata: \u001b[1;36m10\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m14\u001b[0m\r\n"]
[0.000, "o", "Modern HA Patterns: \u001b[1;36m2\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m9\u001b[0m\r\n"]
[0.000, "o", "Tests/CI: \u001b[1;36m0\u001b[0m \u001b[35m/\u001b[0m \u001b[1;36m2\u001b[0m\r\n"]
[0.000, "o", "\r\n"]
[0.000, "o", "Overall: Informational only\r\n"]
[0.001, "o", "Security Review: Not performed\r\n"]
[0.000, "o", "Official HA Tier: Not assigned\r\n"]
[0.000, "o", "HACS Acceptance: Not guaranteed\r\n"]
[0.000, "o", "\r\n"]
[0.007, "o", "\u001b[3m                                                                                                Findings                                                                                                \u001b[0m\r\n┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\r\n┃\u001b[1m \u001b[0m\u001b[1mStatus \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mRule                                     \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mMessage                                                                                   "]
[0.000, "o", "                                                    \u001b[0m\u001b[1m \u001b[0m┃\r\n┡━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩\r\n│ ✅ PASS │ hacs.custom_components.exists             │ Repository contains a custom_components directory.                                                                                             │\r\n│ ⚠️ WARN │ hacs.file.parseable                       │ hacs.json is missing. HACS metadata cannot be inspected yet.               "]
[0.000, "o", "                                                                    │\r\n│ ⚠️ WARN │ brand.icon.exists                         │ Integration does not include brand/icon.png. HACS and Home Assistant brand image support cannot be fully inspected.                            │\r\n│ ✅ PASS │ manifest.exists                           │ Integration manifest exists.                                                                                                                   │\r\n│ ✅ PASS │ manifest.domain.exists                    │ manifest.json defines a domain.                                                                                                                │\r\n│ ✅ PASS │ manifest.name.exists                      │ manifest.json defines a name.                                                                                                                  │\r\n│ ✅ PASS │ manifest.version.exists                   │ manifest.json defines a version.         "]
[0.000, "o", "                                                                                                      │\r\n│ ✅ PASS │ manifest.documentation.exists             │ manifest.json defines documentation.                                                                                                           │\r\n│ ✅ PASS │ manifest.issue_tracker.exists             │ manifest.json defines an issue tracker.                                                                                                        │\r\n│ ✅ PASS │ manifest.codeowners.exists                │ manifest.json defines at least one code owner.                                                                                                 │\r\n│ ❌ FAIL │ manifest.domain.matches_directory         │ manifest.json domain \"wrong_domain\" does not match integration directory \"demo_bad\".                                                           │\r\n│ ✅ PASS │ manifest.iot_class.exists                 │ manifest.j"]
[0.000, "o", "son declares iot_class.                                                                                                              │\r\n│ ❌ FAIL │ manifest.iot_class.valid                  │ manifest.json iot_class \"not_a_valid_class\" is not a recognized value (expected one of: assumed_state, calculated, cloud_polling, cloud_push,  │\r\n│         │                                           │ local_polling, local_push).                                                                                                                    │\r\n│ ⚠️ WARN │ manifest.integration_type.exists          │ manifest.json does not declare integration_type; recommended for Home Assistant integrations.                                                  │\r\n│ ➖ N/A  │ manifest.integration_type.valid           │ manifest.json does not declare integration_type; value validation is skipped.                                                                  │\r\n│ ✅ PASS │ manifest.requirements.i"]
[0.000, "o", "s_list             │ manifest.requirements is a JSON array.                                                                                                         │\r\n│ ✅ PASS │ manifest.requirements.entries_well_formed │ All manifest.requirements entries are valid PEP 508 specifiers.                                                                                │\r\n│ ⚠️ WARN │ manifest.requirements.no_git_or_url_specs │ manifest.requirements contains non-PyPI install specs: git+https://github.com/example/lib.git. Use PyPI package names to ensure installability │\r\n│         │                                           │ via HACS and pip.                                                                                                                              │\r\n│ ⚠️ WARN │ config_flow.user_step.exists              │ config_flow.py does not define async_step_user; users cannot start setup from the UI.                                                          │\r\n│ "]
[0.000, "o", "✅ PASS │ config_flow.file.exists                   │ Integration includes config_flow.py.                                                                                                           │\r\n│ ✅ PASS │ config_flow.manifest_flag_consistent      │ config_flow.py exists and manifest.json sets config_flow: true.                                                                                │\r\n│ ⚠️ WARN │ config_flow.reauth_step.exists            │ config_flow.py does not define async_step_reauth or async_step_reauth_confirm; reauthentication is not supported.                              │\r\n│ ⚠️ WARN │ config_flow.reconfigure_step.exists       │ config_flow.py does not define async_step_reconfigure; users cannot update settings from the UI.                                               │\r\n│ ⚠️ WARN │ config_flow.unique_id.set                 │ config_flow.py does not call async_set_unique_id; duplicate config entries may occur.                           "]
[0.000, "o", "                               │\r\n│ ⚠️ WARN │ config_flow.connection_test               │ No connection test detected in config_flow.py. Discovery-flow steps (async_step_user, async_step_zeroconf, etc.) appear to only call flow      │\r\n│         │                                           │ plumbing methods.                                                                                                                              │\r\n│ ✅ PASS │ diagnostics.file.exists                   │ Integration includes diagnostics.py.                                                                                                           │\r\n│ ✅ PASS │ diagnostics.redaction.used                │ diagnostics.py uses a recognized redaction pattern.                                                                                            │\r\n│ ⚠️ WARN │ repairs.file.exists                       │ Integration does not include repairs.py; user-fixable repair flows cannot be"]
[0.000, "o", " inspected.                                                        │\r\n│ ✅ PASS │ docs.readme.exists                        │ Repository contains README.md.                                                                                                                 │\r\n│ ⚠️ WARN │ docs.installation.exists                  │ README does not appear to contain a readme installation section section (no heading matching: hacs, install, installation, manual install,     │\r\n│         │                                           │ manual installation).                                                                                                                          │\r\n│ ⚠️ WARN │ docs.configuration.exists                 │ README does not appear to contain a readme configuration section section (no heading matching: configuration, configure, options, setup).      │\r\n│ ⚠️ WARN │ docs.troubleshooting.exists               │ README does not appear to contain a r"]
[0.000, "o", "eadme troubleshooting section section (no heading matching: debug, faq, known issues, known limitations,  │\r\n│         │                                           │ support, troubleshoot, troubleshooting).                                                                                                       │\r\n│ ⚠️ WARN │ docs.removal.exists                       │ README does not appear to contain a readme removal section section (no heading matching: removal, remove, uninstall, uninstalling).            │\r\n│ ⚠️ WARN │ docs.privacy.exists                       │ README does not appear to contain a readme privacy section section (no heading matching: cloud, data, local, privacy, telemetry).              │\r\n│ ⚠️ WARN │ repo.license.exists                       │ Repository does not contain a recognized license file.                                                                                         │\r\n│ ⚠️ WARN │ tests.folder.exists                      "]
[0.000, "o", " │ Repository does not contain a tests directory; automated test coverage cannot be inspected.                                                    │\r\n│ ➖ N/A  │ tests.config_flow.detected                │ no tests/ folder; tests.folder.exists owns this signal.                                                                                        │\r\n│ ➖ N/A  │ tests.setup_entry.detected                │ no tests/ folder; tests.folder.exists owns this signal.                                                                                        │\r\n│ ➖ N/A  │ tests.unload.detected                     │ no tests/ folder; tests.folder.exists owns this signal.                                                                                        │\r\n│ ⚠️ WARN │ ci.github_actions.exists                  │ Repository does not contain a GitHub Actions workflow file.                                                                                    │\r\n│ ⚠️ WARN │ init"]
[0.000, "o", ".async_setup_entry.defined            │ __init__.py does not define async_setup_entry; the integration may not support config entries.                                                 │\r\n│ ⚠️ WARN │ init.runtime_data.used                    │ __init__.py does not use entry.runtime_data; consider migrating from hass.data to entry.runtime_data.                                          │\r\n│ ➖ N/A  │ entity.unique_id.set                      │ No entity platform files found in the integration directory.                                                                                   │\r\n│ ➖ N/A  │ entity.has_entity_name.set                │ No entity platform files found in the integration directory.                                                                                   │\r\n│ ➖ N/A  │ entity.device_info.set                    │ No entity platform files found in the integration directory.                                                                           "]
[0.000, "o", "        │\r\n│ ➖ N/A  │ maintenance.recent_commit.detected        │ repository is not a git checkout (no .git directory)                                                                                           │\r\n│ ➖ N/A  │ maintenance.recent_release.detected       │ repository is not a git checkout (no .git directory)                                                                                           │\r\n│ ⚠️ WARN │ maintenance.changelog.exists              │ Repository does not contain a recognized changelog file (CHANGELOG.md, CHANGELOG, HISTORY.md, HISTORY, RELEASES.md, NEWS.md).                  │\r\n└─────────┴───────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────"]
[0.000, "o", "──────────────────────────────────────────────────────────────────────────┘\r\n"]
[0.000, "o", "\r\n"]
[0.000, "o", "\u001b[1mFix suggestions\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mhacs.file.parseable\u001b[0m\r\n"]
[0.000, "o", "    Add a repository-level hacs.json file, even if it starts as an empty JSON object.\r\n"]
[0.001, "o", "  \u001b[1mbrand.icon.exists\u001b[0m\r\n"]
[0.000, "o", "    Add custom_components/\u001b[1m<\u001b[0m\u001b[1;95mdomain\u001b[0m\u001b[1m>\u001b[0m\u001b[35m/brand/\u001b[0m\u001b[95micon.png.\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mmanifest.domain.matches_directory\u001b[0m\r\n"]
[0.000, "o", "    Rename the integration directory or update manifest.domain so both use the same stable domain.\r\n"]
[0.000, "o", "  \u001b[1mmanifest.iot_class.valid\u001b[0m\r\n"]
[0.000, "o", "    Set iot_class to one of: assumed_state, calculated, cloud_polling, cloud_push, local_polling, local_push.\r\n"]
[0.001, "o", "  \u001b[1mmanifest.integration_type.exists\u001b[0m\r\n"]
[0.000, "o", "    Add an integration_type field to manifest.json.\r\n"]
[0.000, "o", "  \u001b[1mmanifest.integration_type.valid\u001b[0m\r\n"]
[0.000, "o", "    Add an integration_type field to manifest.json.\r\n"]
[0.000, "o", "  \u001b[1mmanifest.requirements.no_git_or_url_specs\u001b[0m\r\n"]
[0.000, "o", "    Replace git/URL specs with published PyPI package names.\r\n"]
[0.000, "o", "  \u001b[1mconfig_flow.user_step.exists\u001b[0m\r\n"]
[0.000, "o", "    Add async_step_user to your ConfigFlow class in config_flow.py.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_config_flow_handler/#defining-the-flow\u001b[0m\r\n"]
[0.001, "o", "  \u001b[1mconfig_flow.reauth_step.exists\u001b[0m\r\n"]
[0.000, "o", "    Add async_step_reauth \u001b[1m(\u001b[0mand optionally async_step_reauth_confirm\u001b[1m)\u001b[0m to your ConfigFlow class.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_config_flow_handler/#reauthentication\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mconfig_flow.reconfigure_step.exists\u001b[0m\r\n"]
[0.000, "o", "    Add async_step_reconfigure to your ConfigFlow class.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_config_flow_handler/#reconfigure\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mconfig_flow.unique_id.set\u001b[0m\r\n"]
[0.000, "o", "    Call \u001b[1;35mself.async_set_unique_id\u001b[0m\u001b[1m(\u001b[0m\u001b[1m<\u001b[0m\u001b[1;95mdevice-identifier\u001b[0m\u001b[1m>\u001b[0m\u001b[1m)\u001b[0m before creating the entry.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_config_flow_handler/#unique-ids\u001b[0m\r\n"]
[0.001, "o", "  \u001b[1mconfig_flow.connection_test\u001b[0m\r\n"]
[0.000, "o", "    Add a connection test \u001b[1m(\u001b[0me.g. await \u001b[1;35mvalidate_input\u001b[0m\u001b[1m(\u001b[0mhass, data\u001b[1m)\u001b[0m\u001b[1m)\u001b[0m inside async_step_user.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_config_flow_handler/#defining-the-flow\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mrepairs.file.exists\u001b[0m\r\n"]
[0.000, "o", "    Add repairs.py when the integration has user-fixable repair scenarios.\r\n"]
[0.000, "o", "    Run: hasscheck scaffold repairs\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/core/integration/repairs/\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mdocs.installation.exists\u001b[0m\r\n"]
[0.000, "o", "    Add an Installation section to README.md covering HACS and/or manual installation steps.\r\n"]
[0.000, "o", "  \u001b[1mdocs.configuration.exists\u001b[0m\r\n"]
[0.001, "o", "    Add a Configuration section to README.md describing available options and setup steps.\r\n"]
[0.000, "o", "  \u001b[1mdocs.troubleshooting.exists\u001b[0m\r\n"]
[0.000, "o", "    Add a Troubleshooting or FAQ section to README.md with known issues and debug steps.\r\n"]
[0.000, "o", "  \u001b[1mdocs.removal.exists\u001b[0m\r\n"]
[0.000, "o", "    Add a Removal or Uninstall section to README.md with steps to cleanly remove the integration.\r\n"]
[0.000, "o", "  \u001b[1mdocs.privacy.exists\u001b[0m\r\n"]
[0.000, "o", "    Add a Privacy or Data section to README.md describing what data the integration collects or sends.\r\n"]
[0.000, "o", "  \u001b[1mrepo.license.exists\u001b[0m\r\n"]
[0.000, "o", "    Add a repository license file such as LICENSE.\r\n"]
[0.000, "o", "  \u001b[1mtests.folder.exists\u001b[0m\r\n"]
[0.000, "o", "    Add a tests/ directory with pytest-based integration tests.\r\n"]
[0.001, "o", "  \u001b[1mci.github_actions.exists\u001b[0m\r\n"]
[0.000, "o", "    Add a .github/workflows/*.yml workflow that runs tests.\r\n"]
[0.000, "o", "    Run: hasscheck scaffold github-action\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://docs.github.com/actions/using-workflows/about-workflows\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1minit.async_setup_entry.defined\u001b[0m\r\n"]
[0.000, "o", "    Add \u001b[1;35masync_setup_entry\u001b[0m\u001b[1m(\u001b[0mhass, entry\u001b[1m)\u001b[0m to __init__.py.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_index/#an-example\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1minit.runtime_data.used\u001b[0m\r\n"]
[0.000, "o", "    Replace hass.data\u001b[1m[\u001b[0mDOMAIN\u001b[1m]\u001b[0m with entry.runtime_data = \u001b[1m<\u001b[0m\u001b[1;95myour\u001b[0m\u001b[39m object\u001b[0m\u001b[1m>\u001b[0m.\r\n"]
[0.000, "o", "    Docs: \u001b[4;94mhttps://developers.home-assistant.io/docs/config_entries_index/#runtime_data\u001b[0m\r\n"]
[0.000, "o", "  \u001b[1mmaintenance.changelog.exists\u001b[0m\r\n"]
[0.001, "o", "    Add a CHANGELOG.md at the repository root describing changes per version.\r\n"]
[3.038, "o", "\r\nDone. See docs/demo.md for the full walkthrough.\r\n"]
[2.522, "x", "0"]
