Skip to content

Latest commit

 

History

History
307 lines (229 loc) · 11.6 KB

File metadata and controls

307 lines (229 loc) · 11.6 KB

Claude Code Instructions for HSEM

This document provides practical guidance for Claude Code (Claude-powered coding assistant) when working with the HSEM repository.

Note: This is a quick reference guide. For comprehensive rules, constraints, and standards, please refer to AGENTS.md.

Quick Start

  1. Read AGENTS.md first — Understand the project's constraints, security rules, and Home Assistant compliance requirements
  2. Verify Python 3.14 — Ensure you're using Python 3.14 (see .python-version)
  3. Create a feature branch — Use format: feat/<issue-number>-<description>
  4. Make focused changes — Solve one issue at a time
  5. Run quality checkstox -e lint, tox -e typing, tox -e quality, tox -e py314
  6. Submit PR for review — Do not merge without explicit permission

Core Principles

  1. One Issue Per Session

    • Focus on a single GitHub issue at a time
    • Do not combine multiple issues in one session
    • Reference issue number in commits and PR description
  2. Preserve Existing Behavior

    • Do not refactor unrelated code
    • Do not modify planner logic or safety features unless specifically requested
    • Do not reformat entire directories unless required for tooling setup
    • Keep changes focused and minimal
  3. Code Quality

    • Run tox -e lint before committing (isort + black + ruff format + ruff check)
    • Run tox -e typing after lint (mypy type checking)
    • Run tox -e quality after typing (pyright + vulture)
    • Run tox -e py314 to run tests with coverage before opening a PR
    • Include type hints for all public functions
    • Write docstrings for all public modules, classes, and functions
    • Write tests for new functionality
    • Follow PEP 8 and PEP 257
    • See CODE_QUALITY_STANDARDS.md for full standards and conventions

Utility Function Centralization Rule

CRITICAL: Check for Code Duplication FIRST

When implementing a utility or helper function:

  1. Search first: Check if similar functionality exists in utils/misc.py or other utils modules
  2. If used 2+ times: The function MUST live in utils, NOT in multiple modules
  3. Never duplicate: Create the function in the appropriate utils module, then import it everywhere
  4. DRY Principle: Do not repeat utility logic across multiple files

Example of WRONG approach (creates duplicates):

  • Create _convert_months_to_int() in flows/months.py
  • Create _convert_month_list_to_int() in working_mode_sensor.py
  • ❌ Result: Two functions doing the same thing in different places

Example of CORRECT approach:

  • Create convert_months_to_int() in utils/misc.py (centralized, public)
  • Import it in flows/months.py: from custom_components.hsem.utils.misc import convert_months_to_int
  • Import it in working_mode_sensor.py: from custom_components.hsem.utils.misc import convert_months_to_int
  • ✅ Result: Single source of truth, easier to maintain

Common mistake to avoid:

  • Don't create private versions (_function_name) in multiple modules thinking they're isolated
  • Private functions should still be centralized if used in 2+ places

Floating-Point Comparisons

Never use == or != to compare floating-point values.

  • In production code: use an epsilon guard instead of exact equality.
    • abs(x) > 1e-9 instead of x != 0
    • abs(a - b) < 1e-9 instead of a == b
  • In tests: always use pytest.approx() for any assertion involving float.
    • assert result == pytest.approx(0.0)
    • assert result == 0.0
  • Integer-valued comparisons (== 0 on a sum of int weights) are fine; only float literals and float-typed variables are subject to this rule.

Planner Specification Compliance (Mandatory)

Before touching any planner code, read docs/hsem-planner-spec.md — it is the single source of truth for planner semantics.

Rules:

  1. Read the spec first — applies to engine, cost function, SoC simulation, candidate generation, slot population, and safety gates.
  2. Verify consistency — every change must satisfy the invariants listed under Invariants for tests in the spec (energy balance, SoC bounds, cost identity, terminal-SoC accounting, safety gate behaviour).
  3. Update the spec when a change intentionally alters planner semantics. Spec and implementation must never diverge silently.
  4. Add or update tests covering the affected invariants for every planner change.
  5. Definition of Done for planner work: spec updated (if needed) + invariant tests passing.

Quick checklist before opening a planner PR:

  • docs/hsem-planner-spec.md read and understood
  • Energy balance holds for every slot
  • SoC stays within configured bounds
  • winner.cost == final_output.cost (no post-selection mutation)
  • Terminal SoC affects cost (emptying the battery is not free)
  • No-action baseline includes normal PV/battery self-consumption
  • Read-only / degraded / dry-run gates block hardware writes
  • Spec updated if semantics changed
  • Tests added or updated

Development Workflow

# 1. Ensure you're on Python 3.14
python --version  # Should show 3.14.x

# 2. Create a feature branch
git checkout -b feat/<issue-number>-<description>

# 3. Make your changes and write tests

# 4. Format and lint (REQUIRED)
tox -e lint
# 5. Type check (REQUIRED)
tox -e typing
# 6. Quality checks (REQUIRED)
tox -e quality
# 7. Run tests (REQUIRED)
tox -e py314

# 8. Verify changes
git status

# 9. Commit with conventional commit format
git commit -m "feat(scope): description - Fixes #<ISSUE_NUMBER>"

# 10. Push and create PR (do not merge)
git push origin feat/<issue-number>-<description>

# 11. If the PR already exists and you make further commits, update it
#     Write the body to a file first, then pass --body-file (shell-agnostic):
Set-Content -Path pr_body.md -Value @"
<markdown body here>
"@
gh pr edit <PR_NUMBER> --title "<type>(scope): updated title" --body-file pr_body.md
Remove-Item pr_body.md

Keeping an Open PR Up to Date

Whenever you push additional commits to a branch that already has an open PR:

  1. Update the PR title if the scope or description has changed.
  2. Update the PR body to reflect all changes made so far — new files, behaviour changes, additional tests, and any newly satisfied acceptance criteria.
  3. Tick off completed items in any checklist inside the PR description.
  4. Never leave the PR description stale after follow-up commits.
  5. Always write the PR body to a temporary file and use gh pr edit --body-file. Never pass a multiline body inline via --body "..." — this corrupts the content in PowerShell (produces instead of newlines and \x5c instead of backticks).

Home Assistant Compliance

Ensure your changes follow Home Assistant integration standards:

  • Architecture: Use config entries, setup/unload flows, and platform forwarding patterns
  • Entities: Implement entity model conventions (state, availability, device info, unique IDs, naming)
  • Data Updates: Use DataUpdateCoordinator for periodic polling when needed
  • Configuration: Maintain config_flow, diagnostics, and translations as needed
  • Quality: Target at least Silver quality, aim for Gold
  • Tests: Add tests for setup flows, coordinator behavior, and entity state handling

See AGENTS.mdHome Assistant Compliance section for detailed requirements.

Pre-commit Checklist

REQUIRED before every commit:

# Step 1: Format and lint (MUST be done — isort + black + ruff format + ruff check)
tox -e lint

# Step 2: Type checking
mypy custom_components tests

# Step 3: Quality checks (pyright + vulture)
tox -e quality

# Step 4: Run tests with coverage
tox -e py314

# Step 5: Verify no unintended changes
git status

# Step 6: Use pre-commit hooks (optional, but recommended)
pre-commit run --all-files

If any of these checks fail, fix them before committing. Do not submit a PR with formatting or linting issues.

Type Hints and Documentation

Always include type hints and docstrings:

def calculate_consumption_prediction(
    historical_data: list[float],
    weights: dict[str, float],
) -> float:
    """
    Calculate predicted consumption based on historical data and weights.

    Args:
        historical_data: List of historical consumption values in kWh.
        weights: Dictionary mapping time windows to weight factors.

    Returns:
        Predicted consumption value in kWh.

    Raises:
        ValueError: If historical_data is empty or weights contain invalid values.
    """
    if not historical_data:
        raise ValueError("historical_data cannot be empty")
    return sum(val * weights.get(str(i), 0) for i, val in enumerate(historical_data))

Python Version and Style

  • Target: Python 3.14 (required - see .python-version)
  • Syntax: Use modern Python 3.14+ syntax (union operator |, walrus operator, etc.)
  • Style: Follow PEP 8 and PEP 257 (enforced by ruff)
  • Formatting: Use f-strings for string formatting
  • Paths: Prefer pathlib over os.path
  • Type Annotations: Use explicit type hints in function signatures
  • Code Quality: Write code that passes ruff checks without warnings

Testing

Write tests for all new functions and features:

# Run all tests
pytest tests/

# Run with coverage
pytest tests/ --cov=hsem --cov-report=html

# Run specific test file
pytest tests/test_module.py

# Run specific test
pytest tests/test_module.py::test_function_name

Test guidelines:

  • Use pytest as the test framework
  • Place tests in the tests/ directory following the same structure as the source
  • Use meaningful test names that describe what is being tested
  • Test edge cases: missing data, unavailable entities, invalid values
  • Test async and concurrent operations for race conditions

What to Do

✅ Focus on the specific issue assigned ✅ Use Python 3.14 and pass all ruff quality checks ✅ Write clear, maintainable code with type hints ✅ Include tests for new features and behavior changes ✅ Format and lint code before every commit (ruff format . then ruff check . --fix) ✅ Ask for clarification if requirements are unclear ✅ Document complex logic with comments ✅ Keep commits atomic and focused ✅ Reference AGENTS.md for comprehensive rules

What to Avoid

❌ Submitting a PR without running tox -e lint, tox -e typing, tox -e quality, and tox -e py314 first ❌ Ignoring lint warnings or errors ❌ Using Python versions other than 3.14 ❌ Refactoring unrelated code ❌ Changing planner or safety features without explicit issue ❌ Reformatting code outside your changes ❌ Adding new dependencies without justification ❌ Changing logging levels or sensitive output ❌ Modifying configuration without issue requirement ❌ Committing secrets, API keys, or credentials ❌ Merging PRs without explicit permission

Security Considerations

  • Never commit credentials, API keys, or tokens
  • Never log sensitive information in plaintext
  • Load secrets from environment variables or secure storage
  • Document required environment variables
  • See AGENTS.mdSecurity Constraints for details

Need Help?

  • General rules and constraints: See AGENTS.md
  • Home Assistant requirements: See AGENTS.mdHome Assistant Compliance
  • Python version issues: Ensure you're using Python 3.14 from .python-version
  • Lint/format errors: Run tox -e lint to auto-fix most issues (isort, black, ruff format, ruff check)
  • Unclear requirements: Stop and ask for clarification before implementing
  • Design decisions: Refer to docs/ directory for architecture notes
  • Code quality: When in doubt, run the full pre-commit checklist