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.
- Read AGENTS.md first — Understand the project's constraints, security rules, and Home Assistant compliance requirements
- Verify Python 3.14 — Ensure you're using Python 3.14 (see
.python-version) - Create a feature branch — Use format:
feat/<issue-number>-<description> - Make focused changes — Solve one issue at a time
- Run quality checks —
tox -e lint,tox -e typing,tox -e quality,tox -e py314 - Submit PR for review — Do not merge without explicit permission
-
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
-
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
-
Code Quality
- Run
tox -e lintbefore committing (isort + black + ruff format + ruff check) - Run
tox -e typingafter lint (mypy type checking) - Run
tox -e qualityafter typing (pyright + vulture) - Run
tox -e py314to 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.mdfor full standards and conventions
- Run
CRITICAL: Check for Code Duplication FIRST
When implementing a utility or helper function:
- Search first: Check if similar functionality exists in
utils/misc.pyor other utils modules - If used 2+ times: The function MUST live in utils, NOT in multiple modules
- Never duplicate: Create the function in the appropriate utils module, then import it everywhere
- DRY Principle: Do not repeat utility logic across multiple files
Example of WRONG approach (creates duplicates):
- Create
_convert_months_to_int()inflows/months.py - Create
_convert_month_list_to_int()inworking_mode_sensor.py - ❌ Result: Two functions doing the same thing in different places
Example of CORRECT approach:
- Create
convert_months_to_int()inutils/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
Never use == or != to compare floating-point values.
- In production code: use an epsilon guard instead of exact equality.
abs(x) > 1e-9instead ofx != 0abs(a - b) < 1e-9instead ofa == b
- In tests: always use
pytest.approx()for any assertion involvingfloat.assert result == pytest.approx(0.0)✅assert result == 0.0❌
- Integer-valued comparisons (
== 0on a sum ofintweights) are fine; only float literals and float-typed variables are subject to this rule.
Before touching any planner code, read docs/hsem-planner-spec.md — it is the single source
of truth for planner semantics.
Rules:
- Read the spec first — applies to engine, cost function, SoC simulation, candidate generation, slot population, and safety gates.
- 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).
- Update the spec when a change intentionally alters planner semantics. Spec and implementation must never diverge silently.
- Add or update tests covering the affected invariants for every planner change.
- Definition of Done for planner work: spec updated (if needed) + invariant tests passing.
Quick checklist before opening a planner PR:
-
docs/hsem-planner-spec.mdread 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
# 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.mdWhenever you push additional commits to a branch that already has an open PR:
- Update the PR title if the scope or description has changed.
- Update the PR body to reflect all changes made so far — new files, behaviour changes, additional tests, and any newly satisfied acceptance criteria.
- Tick off completed items in any checklist inside the PR description.
- Never leave the PR description stale after follow-up commits.
- 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\x5cinstead of backticks).
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
DataUpdateCoordinatorfor 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.md → Home Assistant Compliance section for detailed requirements.
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-filesIf any of these checks fail, fix them before committing. Do not submit a PR with formatting or linting issues.
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))- 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
pathliboveros.path - Type Annotations: Use explicit type hints in function signatures
- Code Quality: Write code that passes ruff checks without warnings
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_nameTest 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
✅ 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
❌ 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
- 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.md→ Security Constraints for details
- General rules and constraints: See
AGENTS.md - Home Assistant requirements: See
AGENTS.md→ Home Assistant Compliance - Python version issues: Ensure you're using Python 3.14 from
.python-version - Lint/format errors: Run
tox -e lintto 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