Skip to content

Add CLAUDE.md with codebase guide for AI assistants - #89

Merged
JansenDevelopment merged 15 commits into
developfrom
claude/claude-md-docs-345gyl
Jul 12, 2026
Merged

JansenDevelopment merged 15 commits into
developfrom
claude/claude-md-docs-345gyl

Conversation

@JansenDevelopment

Copy link
Copy Markdown
Owner

Documents the integration architecture (control loop, modes, presence/away
delay, schedule helper, presence sensor, services, frontend cards), the
repository layout, development/test workflow, and key conventions and gotchas.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL

claude added 15 commits July 12, 2026 07:16
Documents the integration architecture (control loop, modes, presence/away
delay, schedule helper, presence sensor, services, frontend cards), the
repository layout, development/test workflow, and key conventions and gotchas.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
- tests: add homeassistant.util.dt and ServiceCall stubs to conftest so the
  integration imports under the test harness; reconcile _make_entity with the
  real SmartClimateEntity constructor (drop nonexistent auto_temp/schedule args
  and the stray _last_written_temperature attribute).
- tests: add pytest.ini (asyncio_mode = auto) so async tests run.
- ci: trigger on develop as well as main, and install pytest-asyncio so the
  async tests actually execute.
- lint: remove unused imports (climate.py callback, frontend.py DOMAIN) that
  were failing ruff.
- config: accept next_node in the YAML CONFIG_SCHEMA default_override_mode to
  match the config-flow UI options.
- docs: update CLAUDE.md to reflect the resolved state.

All 15 tests pass and ruff is clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
Runtime-configurable settings changed via the smart_climate.* services (and
the config/schedule cards that call them) were only mutating in-memory entity
attributes — nothing was written back to the config entry, so every setting
reverted on Home Assistant restart. auto_temperature and schedule were not even
read from the entry.

- Add CONF_AUTO_TEMPERATURE and CONF_SCHEDULE keys.
- Read auto_temperature and schedule from entry.data at construction so
  persisted values are restored on startup.
- Add a _persist() helper and call it from every runtime setter
  (auto/away temperature, away delay, interruptible, default override mode,
  schedule) so changes are written to config-entry storage via
  async_update_entry.
- Add tests/test_persistence.py covering write-back, restore-on-construct, and
  a set-then-rebuild round trip.

This makes the persistence behavior documented in the README actually work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
- Installation: document the HACS custom-repository flow (this integration is
  not in the HACS default store) plus a manual-install option, replacing the
  inaccurate "search the default store" steps.
- Configuration: list the actual config-flow fields (auto temperature is NOT a
  setup field); clarify that auto temperature and schedule are runtime-only and
  that the Configure dialog only changes the wrapped climate and home zone.
- Add a "How it works" overview.
- Add commented-out screenshot placeholders under each card and a dashboard
  suggestion (drop real images into an images/ folder to enable them).
- manifest.json: point documentation at the real repo
  (Smart-Climate-Controller, not ha-smart-climate).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
The wrapper now mirrors the wrapped device's capabilities and manages
setpoints per HVAC mode instead of assuming heat-only:

- hvac_modes mirror the wrapped device (so fan_only/dry/etc. pass through);
  min/max temp and target step also mirror the device (fixes the hardcoded
  5-25 range) with 5/35/0.5 fallbacks.
- _update_target_temperature reads the wrapped device's current HVAC mode:
  heat/auto use the heating setpoints + schedule; cool uses the new
  cool_auto/cool_away setpoints; off/fan_only/dry (and an unavailable wrapped
  entity) write no setpoint at all. This also fixes the previously
  documented-but-missing behavior where "off" kept receiving temperature writes.
- New cool_auto_temperature / cool_away_temperature settings: config-flow
  fields, YAML schema, set_cool_auto_temperature / set_cool_away_temperature
  services, extra-state attributes, and en/nl translations. Both persist to
  config-entry storage like the other runtime settings.
- Pass through fan mode (only advertised when the device supports it) and
  turn_on/turn_off; supported_features is derived from the wrapped device.
- Add tests/test_cooling.py (16 tests) covering setpoint family selection,
  no-write modes, capability mirroring, and cool-setpoint persistence.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
Expose every runtime setting as a standard Home Assistant entity so users get
history, automations, and native UI control without the custom cards:

- number: Home/Away temperature, Cooling Home/Away temperature, Away Delay,
  Default Override Duration.
- switch: Override Interruptible.
- select: Default Override Mode (timer/infinity/next_node).

Implementation:
- New entity_base.SmartClimateChildEntity mixin resolves the paired climate
  entity via the entity registry, subscribes to its state changes, reads values
  from its attributes, and writes back through the smart_climate.* services.
- Climate entity now publishes auto/away temperature, away-delay minutes, and
  default override mode/duration as state attributes so the helpers (and cards)
  have a source of truth.
- All entities (climate, presence sensor, helpers) share device_info so they
  group under one device.
- The duration number and mode select are coupled through
  set_default_override_mode (the backend sets both together), preserving the
  other value.
- Register number/switch/select platforms; add tests/test_helper_entities.py
  and conftest stubs for the new component modules.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
Update CLAUDE.md and README for the new features:
- CLAUDE.md: HVAC-mode-aware target resolution, capability mirroring, the
  helper-entity platforms + SmartClimateChildEntity, the cool_* setpoints in the
  constructor note, an "adding a runtime setting" recipe, and where-to-look rows.
- README: HVAC Modes now mirror the wrapped device (heat/cool/auto/off/fan_only/
  dry); cooling setpoints; the two new cooling services; and a Helper Entities
  section listing the number/switch/select controls.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
Design-first writeup (proposed, for review) covering the coordinator entity
model, the devices+roles data model and migration, per-node schedule band,
the pure decide/route control pipeline, room-temp sourcing, reported state,
overrides, and a phasing plan. Captures five open decisions for sign-off.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
Resolve the five open design questions:
- Config UX: raise the HA floor and model actuator devices as config subentries.
- Band reporting: a single target_temperature plus band attributes (no range).
- Hysteresis: configurable, default 0.3 C.
- Room temperature: selectable source (sensor / primary device / mean).
- Idle: never power a device off (kills airflow) — fan_only where supported,
  else a neutral setpoint.

Bump hacs.json minimum Home Assistant version to 2025.1.0 (adjust to the target
release at implementation time) to enable config subentries.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
Make explicit why no device can heat while another cools: a single global
intent per evaluation, the heat/cool deadband, and idle being non-conditioning.
Add a config + defensive validation rule (cool_limit >= heat_target + gap) and a
property-style invariant test to the plan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
Add the HA-independent control core the coordinator will run on:
- control.decide(): resolves one instance-wide intent (heat/cool/idle/off) from
  mode, room temp, and the heat/cool band, with hysteresis and single-target
  override handling; clamp_band() enforces cool >= heat + gap.
- control.plan_routes(): maps one decision to per-device commands by role;
  parks non-serving devices on fan_only (airflow) or off, never in the opposite
  mode — the structural guarantee against simultaneous heat+cool.
- schedule_helper.get_scheduled_band(): per-node (heat, cool_temp) resolution
  with fallbacks.
- const: device roles, temp-source options, coordinator config keys, defaults.
- Tests: decide/hysteresis/override, routing per role, the band, and a
  property-style invariant that no routing ever contains both heat and cool.
- Doc: correct the idle/park rule (fan_only else off, not a neutral setpoint).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
Rework SmartClimateEntity from a single-device mirror into a coordinator that
owns its HVAC mode and drives one or more actuator devices through the pure
control core:

- Build a devices list (role heat/cool/both), migrating a single
  wrapped_climate to one 'both' device; back-compat wrapped_climate attribute
  retained.
- Own hvac_mode (persisted) instead of mirroring; hvac_modes is the coordinator
  set [off, heat, cool, auto]; expose hvac_action from the current intent.
- _apply_control resolves the band (get_scheduled_band + presence), reads the
  room temperature via the selectable source (sensor/primary/mean), calls
  control.decide, and routes commands to devices with change-detection so no
  redundant service calls are issued.
- Aggregate min/max/step across devices; advertise FAN_MODE only when exactly
  one device supports it and delegate fan control to it; turn_on/off map to the
  coordinator mode.
- Subscribe to device + temperature-sensor changes; on first run adopt an
  unpersisted mode from the device so upgrades don't change behavior.
- Publish heat_target/cool_limit/intent/devices as attributes.
- Rewrite test_cooling.py as coordinator integration tests (mode routing,
  idle/off parking, change-detection, capability aggregation, migration).

72 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
- config_flow: initial flow seeds the first actuator device (entity + role) into
  the devices list; DeviceSubentryFlowHandler adds/edits further devices as
  config subentries; SmartClimateOptionsFlow sets the room-temp source, sensor,
  primary device, hysteresis, and integration-driven-auto toggle.
- climate: _build_devices merges device subentries + entry.data list + legacy
  wrapped migration (deduped); instance tunables read live via _conf()
  (entry.options over entry.data) so options apply without a reload.
- __init__: update listener reloads the entry only when the resolved device list
  changes, so routine setpoint persistence (entry.data) never triggers a reload.
- strings/en/nl: config, subentry, options, and selector translations.
- Tests for subentry merge, dedupe, and legacy migration (75 total).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
Add per-node cooling limits to the schedule card so users can draw the band the
auto mode follows, without any new card:

- A "❄ Cooling" header toggle (defaults on when the device can cool or the
  schedule already has cool limits; heat-only users see the card unchanged).
- Each node gains a second, blue cool-above handle; the idle band between the
  heat and cool lines is shaded. Drag either handle or edit both in the node
  panel; the card clamps the cool limit to >= heat + 1 C.
- Double-click adds a node with a default band; save writes explicit cool_temp
  on every node so the backend band is fully defined.
- Legend and hint updated; heat handles recoloured to match the heat line.

Backend get_scheduled_band already consumes node.cool_temp, so no server change.
JS passes an ESM syntax check; Python suite unaffected (75 pass).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcTv8j31cmKdhhzTrmdNqL
@JansenDevelopment
JansenDevelopment merged commit d2af46b into develop Jul 12, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants