diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 17898f85ba54..9779e09f4797 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -6,6 +6,7 @@ - Start review comments with a short, one-sentence summary of the suggested fix. - Do not comment on code style, formatting or linting issues. +- When reviewing changes under `homeassistant/components/` or `tests/components/`, use the `ha-integration-knowledge` skill as the primary reference. - Flag comments that over-explain straightforward code, narrate the obvious, or read like AI commentary (multi-sentence justifications for a single line). - A Pull Request with a dependency version bump should only contain changes required for the version bump. If the PR includes other changes, request that they are removed from the PR. - Check that the PR description is complete and filled in according to the PR template included below. Every section and checklist item from the template must be present, except the `## Breaking change` section which is optional. No content from the template should be missing, except for HTML comments and Markdown link reference definitions (lines of the form `[name]: url`), which do not render and cannot be verified from the description. Even unchecked checkboxes or empty sections must be present. This is a hard requirement. diff --git a/.github/instructions/integrations.instructions.md b/.github/instructions/integrations.instructions.md deleted file mode 100644 index 420ca7d65b1a..000000000000 --- a/.github/instructions/integrations.instructions.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -applyTo: "homeassistant/components/**, tests/components/**" -excludeAgent: "cloud-agent" ---- - - - - -## File Locations -- **Integration code**: `./homeassistant/components//` -- **Integration tests**: `./tests/components//` - -## General guidelines - -- When looking for examples, prefer integrations with the platinum or gold quality scale level first. -- Polling intervals are NOT user-configurable. Never add scan_interval, update_interval, or polling frequency options to config flows or config entries. -- Do NOT allow users to set config entry names in config flows. Names are automatically generated or can be customized later in UI. Exception: helper integrations may allow custom names. -- For entity actions and entity services, avoid requesting redundant defensive checks for fields already enforced by Home Assistant validation schemas and entity filters; only request extra guards when values bypass validation or are transformed unsafely. -- When validation guarantees a key is present, prefer direct dictionary indexing (`data["key"]`) over `.get("key")` so invalid assumptions fail fast. -- Integrations should be thin wrappers. Protocol parsing, device state machines, or other domain logic belong in a separate PyPI library, not in the integration itself. If unsure, ask before inlining. -- Integrations should not implement fixes or workarounds for limitations in libraries. Instead, the library should be updated to fix the issue. - -The following platforms have extra guidelines: -- **Diagnostics**: [`platform-diagnostics.md`](platform-diagnostics.md) for diagnostic data collection -- **Repairs**: [`platform-repairs.md`](platform-repairs.md) for user-actionable repair issues - -## Entity platforms - -- Ensure `async_added_to_hass()` and `async_will_remove_from_hass()` have symmetrical behavior. For example, if a subscription is created in `async_added_to_hass()`, it should be unsubscribed in `async_will_remove_from_hass()`. Also, if something is torn down in `async_will_remove_from_hass()`, it should be set up in `async_added_to_hass()`. -- Entity base class (e.g. `SensorEntity`, `TrackerEntity`) provide a stable API for child classes to inherit from. Do not suggest redeclaring or duplicating attributes, properties, or methods the base class already provides, and do not add guards against the parent's behavior changing — rely on the base class instead. - -## Integration Quality Scale - -- When validating the quality scale rules, check them at https://developers.home-assistant.io/docs/core/integration-quality-scale/rules -- When implementing or reviewing an integration, always consider the quality scale rules, since they promote best practices. - -Template scale file: `./script/scaffold/templates/integration/integration/quality_scale.yaml` - -### How Rules Apply -1. **Check `manifest.json`**: Look for `"quality_scale"` key to determine integration level -2. **Bronze Rules**: Always required for any integration with quality scale -3. **Higher Tier Rules**: Only apply if integration targets that tier or higher -4. **Rule Status**: Check `quality_scale.yaml` in integration folder for: - - `done`: Rule implemented - - `exempt`: Rule doesn't apply (with reason in comment) - - `todo`: Rule needs implementation - - -## Testing Requirements - -- Tests should avoid interacting or mocking internal integration details. For more info, see https://developers.home-assistant.io/docs/development_testing/#writing-tests-for-integrations diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7496fcaffcdf..1d9a093a7e65 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -95,7 +95,7 @@ repos: pass_filenames: false language: script types: [text] - files: ^(AGENTS\.md|\.claude/skills/(?!github-pr-reviewer/).+/SKILL\.md|\.github/copilot-instructions\.md|script/gen_copilot_instructions\.py)$ + files: ^(AGENTS\.md|\.github/copilot-instructions\.md|script/gen_copilot_instructions\.py)$ - id: hassfest name: hassfest entry: script/run-in-env.sh python3 -m script.hassfest diff --git a/script/gen_copilot_instructions.py b/script/gen_copilot_instructions.py index 020d58252f8c..0383253c94b9 100755 --- a/script/gen_copilot_instructions.py +++ b/script/gen_copilot_instructions.py @@ -1,8 +1,5 @@ #!/usr/bin/env python3 -"""Generate .github/copilot-instructions.md from AGENTS.md and skills. - -Necessary until copilot can handle skills. -""" +"""Generate .github/copilot-instructions.md from AGENTS.md and the PR template.""" from pathlib import Path import sys @@ -13,10 +10,6 @@ GENERATED_MESSAGE = ( AGENTS_FILE = Path("AGENTS.md") OUTPUT_FILE = Path(".github/copilot-instructions.md") -INTEGRATION_SKILL_FILE = Path(".claude/skills/ha-integration-knowledge/SKILL.md") -INTEGRATION_PATH_SPECIFIC_OUTPUT_FILE = Path( - ".github/instructions/integrations.instructions.md" -) PR_TEMPLATE_FILE = Path(".github/PULL_REQUEST_TEMPLATE.md") COPILOT_SPECIFIC_INSTRUCTIONS = """ @@ -24,6 +17,7 @@ COPILOT_SPECIFIC_INSTRUCTIONS = """ - Start review comments with a short, one-sentence summary of the suggested fix. - Do not comment on code style, formatting or linting issues. +- When reviewing changes under `homeassistant/components/` or `tests/components/`, use the `ha-integration-knowledge` skill as the primary reference. - Flag comments that over-explain straightforward code, narrate the obvious, or read like AI commentary (multi-sentence justifications for a single line). - A Pull Request with a dependency version bump should only contain changes required for the version bump. If the PR includes other changes, request that they are removed from the PR. - Check that the PR description is complete and filled in according to the PR template included below. Every section and checklist item from the template must be present, except the `## Breaking change` section which is optional. No content from the template should be missing, except for HTML comments and Markdown link reference definitions (lines of the form `[name]: url`), which do not render and cannot be verified from the description. Even unchecked checkboxes or empty sections must be present. This is a hard requirement. @@ -37,41 +31,6 @@ The PR description must follow this template (from `.github/PULL_REQUEST_TEMPLAT ``` """ -INTEGRATION_PATH_SPECIFIC_INSTRUCTIONS = """--- -applyTo: "homeassistant/components/**, tests/components/**" -excludeAgent: "cloud-agent" ---- -""" - - -def _strip_frontmatter(text: str) -> str: - """Strip YAML frontmatter from the start of a markdown document.""" - if not text.startswith("---\n"): - return text - - end = text.find("\n---\n", 4) - if end == -1: - return text - - return text[end + len("\n---\n") :].lstrip("\n") - - -def generate_integration_path_specific_instructions() -> str: - """Generate instructions for integration paths.""" - if not INTEGRATION_SKILL_FILE.exists(): - print(f"Error: {INTEGRATION_SKILL_FILE} not found") - sys.exit(1) - - skill_content = _strip_frontmatter(INTEGRATION_SKILL_FILE.read_text()) - - return ( - INTEGRATION_PATH_SPECIFIC_INSTRUCTIONS - + "\n" - + GENERATED_MESSAGE - + "\n" - + skill_content - ) - def generate_output() -> str: """Generate the copilot-instructions.md content.""" @@ -119,22 +78,13 @@ def main(validate: bool = False) -> int: return 1 main_content = generate_output() - integration_path_specific_content = ( - generate_integration_path_specific_instructions() - ) if validate: check_file(OUTPUT_FILE, main_content) - check_file( - INTEGRATION_PATH_SPECIFIC_OUTPUT_FILE, integration_path_specific_content - ) return 0 OUTPUT_FILE.write_text(main_content) print(f"Generated {OUTPUT_FILE}") - - INTEGRATION_PATH_SPECIFIC_OUTPUT_FILE.write_text(integration_path_specific_content) - print(f"Generated {INTEGRATION_PATH_SPECIFIC_OUTPUT_FILE}") return 0