|
| 1 | +# Climate Scheduler — Codebase Knowledge Index |
| 2 | + |
| 3 | +Generated from full end-to-end source reads of every module. |
| 4 | + |
| 5 | +## How to Use |
| 6 | + |
| 7 | +Each `KNOWLEDGE_*.md` file documents a single module with: |
| 8 | +- **Purpose**: What it does in the system |
| 9 | +- **Key Functions**: Signature, contract, mutations, calls, edge cases, test coverage |
| 10 | +- **Invariants**: Proven vs. assumed state invariants |
| 11 | +- **Contract Connections**: Links to CONTRACTS.md |
| 12 | +- **Known Bugs / Gaps**: Documented issues |
| 13 | +- **Cross-Module Dependencies**: What it imports and who imports it |
| 14 | + |
| 15 | +The `python_model.json` and `frontend_model.json` are machine-readable structural models |
| 16 | +extracted via AST/regex — function signatures, call graphs, class hierarchies, state mutations. |
| 17 | + |
| 18 | +## Knowledge Files |
| 19 | + |
| 20 | +### Python Backend |
| 21 | +| File | Module | Lines | Key Risks | |
| 22 | +|------|--------|-------|-----------| |
| 23 | +| KNOWLEDGE_const.md | const.py | 70 | Max temp mismatch (35 vs 30) | |
| 24 | +| KNOWLEDGE_init.md | __init__.py | 500 | Service unload gap, self-reload hack | |
| 25 | +| KNOWLEDGE_config_flow.md | config_flow.py | 140 | Minimal config surface | |
| 26 | +| KNOWLEDGE_storage.md | storage.py | 1881 | Migration clobbering, NaN/inf, missing method | |
| 27 | +| KNOWLEDGE_coordinator.md | coordinator.py | 1127 | Fan/swing/preset skipped in advance, day boundaries | |
| 28 | +| KNOWLEDGE_services.md | services.py | 1909 | async_clear_schedule bug, mixed schedule_id | |
| 29 | +| KNOWLEDGE_climate.md | climate.py | 590 | max_temp mismatch, schedule shape mismatch | |
| 30 | +| KNOWLEDGE_sensor.md | sensor.py | 480 | Direct _storage._data access | |
| 31 | +| KNOWLEDGE_switch.md | switch.py | 421 | preset_mode drops temperature, no-op refresh | |
| 32 | + |
| 33 | +### Frontend |
| 34 | +| File | Module | Lines | Key Risks | |
| 35 | +|------|--------|-------|-----------| |
| 36 | +| KNOWLEDGE_app_js.md | app.js | 7580 | Profile-edit leak, save-dropped, currentSchedule overwrite, dead code | |
| 37 | +| KNOWLEDGE_ha_api_js.md | ha-api.js | 673 | Silent error swallowing | |
| 38 | +| KNOWLEDGE_utils_js.md | utils.js | 186 | Pure utilities, low risk | |
| 39 | +| KNOWLEDGE_panel_js.md | panel.js | 599 | DOM shell, version check | |
| 40 | +| KNOWLEDGE_climate_dialog.md | climate-dialog.ts/.js | 1094 | noChange mutates stateObj | |
| 41 | +| KNOWLEDGE_keyframe_timeline.md | keyframe-timeline.ts/.js | 2348 | CSS named colors, double-draw | |
| 42 | +| KNOWLEDGE_climate_scheduler_card.md | card.ts/.js | 252 | Event type inconsistency | |
| 43 | +| KNOWLEDGE_panel_ts.md | panel.ts | 640 | No cleanup, XSS risk, innerHTML | |
| 44 | + |
| 45 | +### Structural Models (machine-readable) |
| 46 | +| File | Schema | Covers | |
| 47 | +|------|--------|--------| |
| 48 | +| python_model.json | climate-scheduler-python-model-v1 | All .py files: signatures, calls, mutations, classes | |
| 49 | +| frontend_model.json | climate-scheduler-frontend-model-v1 | All .ts/.js files: signatures, classes, events, service calls | |
| 50 | + |
| 51 | +## Extraction Tools |
| 52 | +| Tool | Purpose | |
| 53 | +|------|---------| |
| 54 | +| tools/extract_python_model.py | AST-based Python model extraction | |
| 55 | +| tools/extract_ts_js_model.py | Regex-based TS/JS model extraction | |
| 56 | + |
| 57 | +## Regeneration |
| 58 | + |
| 59 | +```bash |
| 60 | +mkdir -p knowledge |
| 61 | +python3 tools/extract_python_model.py --dir custom_components/climate_scheduler/ > knowledge/python_model.json |
| 62 | +python3 tools/extract_ts_js_model.py --dir src/ custom_components/climate_scheduler/frontend/ > knowledge/frontend_model.json |
| 63 | +``` |
| 64 | + |
| 65 | +Note: KNOWLEDGE files are curated by reading source end-to-end. They need manual review |
| 66 | +when code changes — the JSON models are auto-regenerable, the markdown is not. |
| 67 | + |
| 68 | +## Bug Summary (cross-module) |
| 69 | + |
| 70 | +1. **async_clear_schedule** — services.py:995 calls nonexistent method; partial fix with async_set_schedule(entity_id, []) |
| 71 | +2. **validate_node accepts NaN/inf** — storage.py lets float("NaN") and float("inf") through as temperatures |
| 72 | +3. **_sync_group_profile_views clobbers migrations** — runs on every save, overlays before migration data is complete |
| 73 | +4. **fan/swing/preset skipped during advance** — coordinator.py advance_to_next_node only applies modes in noChange branch |
| 74 | +5. **climate.py max_temp=35 vs const.py MAX_TEMP=30** — hardcoded override of the constant |
| 75 | +6. **climate.py schedule shape mismatch** — accesses schedules[day]["nodes"] but storage uses flat lists |
| 76 | +7. **switch.py preset_mode drops temperature** — node with both temp and preset_mode only applies preset |
| 77 | +8. **switch.py refresh is no-op** — _refresh_group_data can't call async from sync property |
| 78 | +9. **app.js profile-edit leak** — editing profile writes to currentSchedule, can leak on timeline switch |
| 79 | +10. **app.js save dropped** — single pendingSaveNeeded boolean, rapid saves can lose data |
| 80 | +11. **app.js currentSchedule overwrite** — editGroupSchedule/switchDay overwrite unsaved edits |
| 81 | +12. **app.js dead code in handleGraphChange** — thermostat immediate-update logic unreachable |
| 82 | +13. **__init__.py service unload gap** — 8 services registered but not unregistered on unload |
| 83 | +14. **coordinator.py cross-module coupling** — calls private storage._time_to_minutes directly |
| 84 | +15. **coordinator.py naive vs aware datetime** — datetime.fromisoformat vs dt_util.now() mismatch |
0 commit comments