docs(agents): add logging and documentation writing guidelines

Extended AGENTS.md with comprehensive patterns learned from period
calculation development and documentation rewrite.

Logging Guidelines:
- Added hierarchical indentation pattern (INDENT_L0-L5)
- Defined log level strategy (INFO=compact/scannable,
  DEBUG=detailed/hierarchical, WARNING=top-level)
- Added configuration context headers for complex calculations
- Documented per-day processing patterns
- Added note about logs as documentation foundation

User Documentation Quality:
- Added principles: clarity over completeness, visual examples,
  use-case driven structure, practical troubleshooting, progressive
  disclosure
- Added validation rules for code-documentation sync

Documentation Writing Strategy (new section):
- Live understanding vs. cold code analysis
- User feedback loop importance
- Log-driven documentation approach
- Concrete examples over abstract descriptions
- Context accumulation in long sessions
- Document the "why", not just the "what"

Impact: Future AI sessions can produce better logs (traceable logic
with visual hierarchy) and better documentation (user-focused with
concrete examples from live development).
This commit is contained in:
Julian Pawlowski 2025-11-11 21:20:06 +00:00
parent 95758ec40a
commit b191238df4

174
AGENTS.md
View file

@ -4,8 +4,8 @@ This is a **Home Assistant custom component** for Tibber electricity price data,
## Documentation Metadata ## Documentation Metadata
- **Last Major Update**: 2025-11-09 - **Last Major Update**: 2025-11-11
- **Last Architecture Review**: 2025-11-09 (Translation system restructured - selector translations now use `selector.{translation_key}.options.{value}` pattern) - **Last Architecture Review**: 2025-11-11 (Logging guidelines completely rewritten - hierarchical indentation, INFO/DEBUG/WARNING patterns, configuration context headers. User documentation quality principles added based on period-calculation.md rewrite. Documentation Writing Strategy added - explaining how live development + user feedback creates better docs than cold code analysis.)
- **Documentation Status**: ✅ Current (verified against codebase) - **Documentation Status**: ✅ Current (verified against codebase)
_Note: When proposing significant updates to this file, update the metadata above with the new date and brief description of changes._ _Note: When proposing significant updates to this file, update the metadata above with the new date and brief description of changes._
@ -1147,10 +1147,103 @@ We use **Ruff** (which replaces Black, Flake8, isort, and more) as our sole lint
**Logging guidelines:** **Logging guidelines:**
- Use lazy logging: `_LOGGER.debug("Message with %s", variable)` **Critical principle:** Logs must enable logic tracing without reading code. Each log message should make the current state and decision-making process crystal clear.
**Why good logging matters beyond debugging:**
- Clear logs become the foundation for good documentation (see "Documentation Writing Strategy")
- If you spend hours making logs explain the logic, that clarity transfers directly to user docs
- Logs show state transitions and decisions that users need to understand
- Pattern: Good hierarchical logs → Easy to extract examples and explanations for documentation
**Log Level Strategy:**
- **INFO Level** - User-facing results and high-level progress:
- Compact 1-line summaries (no multi-line blocks)
- Important results only (success/failure outcomes)
- No indentation (scannability)
- Example: `"Calculating BEST PRICE periods: relaxation=ON, target=2/day, flex=15.0%"`
- Example: `"Day 2025-11-11: Success after 1 relaxation phase (2 periods)"`
- **DEBUG Level** - Detailed execution trace:
- Full context headers with all relevant configuration
- Step-by-step progression through logic
- Hierarchical indentation to show call depth/logic structure
- Intermediate results and calculations
- Example: `" Day 2025-11-11: Found 1 baseline period (need 2)"`
- Example: `" Phase 1: flex 20.25% + original filters"`
- **WARNING Level** - Problems and unexpected states:
- Top-level important messages (no indentation)
- Clear indication of what went wrong
- Example: `"Day 2025-11-11: All relaxation phases exhausted, still only 1 period found"`
**Hierarchical Indentation Pattern:**
Use consistent indentation to show logical structure (DEBUG level only):
```python
# Define indentation constants at module level
INDENT_L0 = "" # Top-level (0 spaces)
INDENT_L1 = " " # Level 1 (2 spaces)
INDENT_L2 = " " # Level 2 (4 spaces)
INDENT_L3 = " " # Level 3 (6 spaces)
INDENT_L4 = " " # Level 4 (8 spaces)
INDENT_L5 = " "# Level 5 (10 spaces)
# Usage example showing logic hierarchy
_LOGGER.debug("%sCalculating periods for day %s", INDENT_L0, day_date)
_LOGGER.debug("%sBaseline: Found %d periods", INDENT_L1, baseline_count)
_LOGGER.debug("%sStarting relaxation...", INDENT_L1)
_LOGGER.debug("%sPhase 1: flex 20.25%%", INDENT_L2)
_LOGGER.debug("%sCandidate period: %s", INDENT_L3, period_str)
_LOGGER.debug("%sMerging with baseline...", INDENT_L3)
_LOGGER.debug("%sExtended baseline period from %s to %s", INDENT_L4, old_end, new_end)
```
**Why indentation?**
- Makes call stack and decision tree visible at a glance
- Enables quick problem localization (which phase/step failed?)
- Shows parent-child relationships between operations
- Distinguishes between sequential steps vs nested logic
**Configuration Context:**
When starting complex calculations, log the full decision context upfront (DEBUG level):
```python
_LOGGER.debug(
"%sConfiguration:\n"
"%s Relaxation: %s\n"
"%s Target: %d periods per day\n"
"%s Base flex: %.1f%%\n"
"%s Strategy: 4 flex levels × 4 filter combinations",
INDENT_L0,
INDENT_L0, "ENABLED" if enable_relaxation else "DISABLED",
INDENT_L0, min_periods,
INDENT_L0, base_flex,
INDENT_L0,
)
```
**Per-Day Processing:**
Complex logic that operates per-day should clearly show which day is being processed (DEBUG level):
```python
for day_date, day_intervals in intervals_by_day.items():
_LOGGER.debug("%sProcessing day %s", INDENT_L1, day_date)
# ... processing ...
_LOGGER.debug("%sDay %s: Found %d periods", INDENT_L1, day_date, count)
```
**General Rules:**
- Use lazy logging: `_LOGGER.debug("Message with %s", variable)` (never f-strings in log calls - Ruff G004)
- No periods at end of log messages - No periods at end of log messages
- No integration name in messages (added automatically) - No integration name in messages (added automatically by HA)
- Debug level for non-user-facing messages - Always include relevant identifiers (day, phase, period) for context
- Log BEFORE and AFTER state changes to show transitions
- Use consistent terminology (e.g., "baseline" vs "relaxed", "extended" vs "replaced")
**Function organization:** **Function organization:**
Public entry points → direct helpers (call order) → pure utilities. Prefix private helpers with `_`. Public entry points → direct helpers (call order) → pure utilities. Prefix private helpers with `_`.
@ -1205,6 +1298,77 @@ Public entry points → direct helpers (call order) → pure utilities. Prefix p
- Swedish/Norwegian: Already use informal address by default (no formal "Ni"/"De" in modern usage) - Swedish/Norwegian: Already use informal address by default (no formal "Ni"/"De" in modern usage)
- English: Already gender-neutral and appropriately informal - English: Already gender-neutral and appropriately informal
**User Documentation Quality:**
When writing or updating user-facing documentation (`docs/user/`), follow these principles learned from real user feedback:
- **Clarity over completeness**: Users want to understand concepts, not read technical specifications
- ✅ Good: "Relaxation automatically loosens filters until enough periods are found"
- ❌ Bad: "The relaxation algorithm implements a 4×4 matrix strategy with multiplicative flex increments"
- **Visual examples**: Use timeline diagrams, code blocks with comments, before/after comparisons
- ✅ Show what a "period" looks like on a 24-hour timeline
- ✅ Include automation examples with real entity names
- **Use-case driven**: Start with "what can I do with this?" not "how does it work internally"
- ✅ Structure: Quick Start → Common Scenarios → Configuration Guide → Advanced Topics
- ❌ Avoid: Starting with mathematical formulas or algorithm descriptions
- **Practical troubleshooting**: Address real problems users encounter
- ✅ "No periods found → Try: increase flex from 15% to 20%"
- ❌ Avoid: Generic "check your configuration" without specific guidance
- **Progressive disclosure**: Basic concepts first, advanced details later
- ✅ Main doc covers 80% use cases in simple terms
- ✅ Link to advanced/technical docs for edge cases
- ❌ Don't mix basic explanations with deep technical details
- **When code changed significantly**: Verify documentation still matches
- If relaxation strategy changed from 3 phases to 4×4 matrix → documentation MUST reflect this
- If metadata format changed → update all examples showing attributes
- If per-day independence was added → explain why some days relax differently
**Documentation Writing Strategy:**
Understanding **how** good documentation emerges is as important as knowing what makes it good:
- **Live Understanding vs. Code Analysis**
- ✅ **DO:** Write docs during/after active development
- When implementing complex logic, document it while the "why" is fresh
- Use real examples from debugging sessions (actual logs, real data)
- Document decisions as they're made, not after the fact
- ❌ **DON'T:** Write docs from cold code analysis
- Reading code shows "what", not "why"
- Missing context: Which alternatives were considered?
- No user perspective: What's actually confusing?
- **User Feedback Loop**
- Key insight: Documentation improves when users question it
- Pattern:
1. User asks: "Does this still match the code?"
2. AI realizes: "Oh, the 3-phase model is outdated"
3. Together we trace through real behavior
4. Documentation gets rewritten with correct mental model
- Why it works: User questions force critical thinking, real confusion points get addressed
- **Log-Driven Documentation**
- Observation: When logs explain logic clearly, documentation becomes easier
- Why: Logs show state transitions ("Baseline insufficient → Starting relaxation"), decisions ("Replaced period X with larger Y"), and are already written for humans
- Pattern: If you spent hours making logs clear → use that clarity in documentation too
- **Concrete Examples > Abstract Descriptions**
- ✅ **Good:** "Day 2025-11-11 found 2 periods at flex=12.0% +volatility_any (stopped early, no need to try higher flex)"
- ❌ **Bad:** "The relaxation algorithm uses a configurable threshold multiplier with filter combination strategies"
- Use real data from debug sessions, show actual attribute values, demonstrate with timeline diagrams
- **Context Accumulation in Long Sessions**
- Advantage: AI builds mental model incrementally, sees evolution of logic (not just final state), understands trade-offs
- Disadvantage of short sessions: Cold start every time, missing "why" context, documentation becomes spec-writing
- Lesson: Complex documentation benefits from focused, uninterrupted work with accumulated context
- **Document the "Why", Not Just the "What"**
- Every complex pattern should answer:
1. **What** does it do? (quick summary)
2. **Why** was it designed this way? (alternatives considered)
3. **How** does a user benefit? (practical impact)
4. **When** does it fail? (known limitations)
- Example: "Replacement Logic: Larger periods replace smaller overlapping ones because users want ONE long cheap period, not multiple short overlapping ones."
## Ruff Code Style Guidelines ## Ruff Code Style Guidelines
These rules ensure generated code passes `./scripts/lint` on first try. Ruff enforces these automatically. These rules ensure generated code passes `./scripts/lint` on first try. Ruff enforces these automatically.