# Story 9.6: Amélioration Logging Validation Énergie

Status: done

**Epic:** 9 - Coherence Corrections (Post-Audit)  
**Priorité:** P2-IMPORTANTE  
**Estimation:** 1h  
**Dépendances:** Stories 9.3, 9.4, 9.5 (all done)

---

## Story

> En tant que développeur debuggant une simulation,  
> Je veux un avertissement explicite quand des composants sont ignorés dans la validation énergétique,  
> Afin d'identifier rapidement les implémentations manquantes.

---

## Contexte

L'audit de cohérence a révélé que `check_energy_balance()` utilise un logging de niveau DEBUG pour les composants skippés, ce qui les rend invisibles en configuration par défaut.

---

## Problème Actuel

```rust
// crates/solver/src/system.rs:1873-1879
_ => {
    components_skipped += 1;
    tracing::debug!(  // ← Niveau DEBUG, pas WARNING
        node_index = node_idx.index(),
        "Component lacks full energy transfer or enthalpy data - skipping energy balance check"
    );
}
```

**Conséquence** : Les développeurs ne sont pas avertis que certains composants sont ignorés dans la validation.

---

## Solution Proposée

### Changements

1. **Passer de DEBUG à WARN** pour les composants skippés
2. **Inclure le type du composant** dans le message
3. **Ajouter un résumé final** si des composants ont été skippés

### Implémentation

```rust
// crates/solver/src/system.rs

pub fn check_energy_balance(&self, state: &SystemState) -> Result<(), ValidationError> {
    let mut total_heat_in = Power::from_watts(0.0);
    let mut total_heat_out = Power::from_watts(0.0);
    let mut total_work_in = Power::from_watts(0.0);
    let mut total_work_out = Power::from_watts(0.0);
    let mut components_validated = 0;
    let mut components_skipped = 0;
    let mut skipped_components: Vec<String> = Vec::new();

    for node_idx in self.graph.node_indices() {
        let component = &self.graph[node_idx];
        
        let energy_transfers = component.energy_transfers(state);
        let mass_flows = component.port_mass_flows(state);
        let enthalpies = component.port_enthalpies(state);

        match (energy_transfers, mass_flows, enthalpies) {
            (Some((heat, work)), Ok(m_flows), Ok(h_flows)) if m_flows.len() == h_flows.len() => {
                // ... existing validation logic ...
                components_validated += 1;
            }
            _ => {
                components_skipped += 1;
                let component_info = format!(
                    "{} (type: {})",
                    component.name(),
                    std::any::type_name_of_val(component)
                        .split("::")
                        .last()
                        .unwrap_or("unknown")
                );
                skipped_components.push(component_info.clone());
                
                tracing::warn!(
                    component = %component_info,
                    node_index = node_idx.index(),
                    "Component lacks energy_transfers() or port_enthalpies() - SKIPPED in energy balance validation"
                );
            }
        }
    }

    // Résumé final si des composants ont été skippés
    if components_skipped > 0 {
        tracing::warn!(
            components_validated = components_validated,
            components_skipped = components_skipped,
            skipped = ?skipped_components,
            "Energy balance validation incomplete: {} component(s) skipped. \
             Implement energy_transfers() and port_enthalpies() for full validation.",
            components_skipped
        );
    }

    // ... rest of validation ...
}
```

---

## Fichiers à Modifier

| Fichier | Action |
|---------|--------|
| `crates/solver/src/system.rs` | Modifier `check_energy_balance()` |

---

## Critères d'Acceptation

- [x] Logging au niveau WARN (pas DEBUG)
- [x] Message inclut le nom et type du composant
- [x] Résumé final avec liste des composants skippés
- [x] Test que le warning est bien émis

---

## Tests Requis

```rust
#[cfg(test)]
mod tests {
    use super::*;
    use tracing::subscriber;
    use tracing_subscriber::layer::SubscriberExt;
    
    #[test]
    fn test_warn_emitted_for_skipped_component() {
        // Setup tracing capture
        let (layer, handle) = tracing_subscriber::layer::with_test_writer();
        let _guard = subscriber::set_default(tracing_subscriber::registry().with(layer));
        
        // Create system with component that lacks energy methods
        let mut system = System::new();
        // ... add component without energy_transfers() ...
        
        let state = SystemState::default();
        let _ = system.check_energy_balance(&state);
        
        // Verify warning was emitted
        let logs = handle.read();
        assert!(logs.contains("SKIPPED in energy balance validation"));
    }
}
```

---

## Exemple de Sortie

### Avant correction

```
DEBUG entropyk_solver::system: Component lacks full energy transfer or enthalpy data - skipping energy balance check node_index=2
```

### Après correction

```
WARN entropyk_solver::system: Component lacks energy_transfers() or port_enthalpies() - SKIPPED in energy balance validation component="EV-01 (type: ExpansionValve)" node_index=2
WARN entropyk_solver::system: Energy balance validation incomplete: 1 component(s) skipped. Implement energy_transfers() and port_enthalpies() for full validation. components_validated=4 components_skipped=1 skipped=["EV-01 (type: ExpansionValve)"]
```

---

## Dev Notes

### Architecture Patterns

- **Tracing crate**: The project uses `tracing` for structured logging with spans
- **Log levels**: DEBUG for detailed diagnostics, WARN for actionable issues
- **Pattern**: Use structured fields (`node_index = value`) for searchable logs

### Current Implementation Analysis

The current code at [`crates/solver/src/system.rs:1855-1861`](crates/solver/src/system.rs:1855):

```rust
_ => {
    components_skipped += 1;
    tracing::debug!(
        node_index = node_idx.index(),
        "Component lacks full energy transfer or enthalpy data - skipping energy balance check"
    );
}
```

**Key observations:**
1. Uses `tracing::debug!` - invisible with default `RUST_LOG=info`
2. Missing component type information
3. No summary at the end of validation

### Implementation Notes

1. **Getting component type**: Use `std::any::type_name_of_val(component)` (stabilized in Rust 1.76)
2. **Component name**: Access via `component.name()` method from `Component` trait
3. **Tracking skipped components**: Add `Vec<String>` to collect skipped component info

### Dependencies Status

| Story | Status | Notes |
|-------|--------|-------|
| 9-3 ExpansionValve Energy Methods | done | `ExpansionValve` now has `energy_transfers()` |
| 9-4 RefrigerantSource/RefrigerantSink Energy Methods | review | Implementation complete, pending review |
| 9-5 FlowSplitter/FlowMerger Energy Methods | ready-for-dev | Depends on this story |

**Note**: This story can be implemented independently - it improves logging regardless of whether other components have complete energy methods.

### Testing Strategy

1. **Unit test**: Create a mock component without energy methods, verify warning is emitted
2. **Integration test**: Run `check_energy_balance()` on a system with mixed components
3. **Manual verification**: Run with `RUST_LOG=warn` and verify warnings appear

### Project Structure Notes

- File to modify: `crates/solver/src/system.rs`
- Function: `check_energy_balance(&self, state: &StateSlice)`
- Line range: ~1855-1861 (the `_ =>` match arm)

### References

- [Coherence Audit Report](./coherence-audit-remediation-plan.md)
- [Story 7-2 Energy Balance Validation](./7-2-energy-balance-validation.md)
- [Rust tracing crate docs](https://docs.rs/tracing/latest/tracing/)
- [std::any::type_name_of_val](https://doc.rust-lang.org/std/any/fn.type_name_of_val.html)

---

## Dev Agent Record

### Agent Model Used

z-ai/glm-5:free

### Debug Log References

- Build succeeded with `cargo build --package entropyk-solver`
- All tests passed with `cargo test --package entropyk-solver`

### Completion Notes List

- **Implementation**: Modified `check_energy_balance()` in `crates/solver/src/system.rs` to:
  1. Use `tracing::warn!` instead of `tracing::debug!` for skipped components
  2. Include component signature and type name in the warning message using `component.signature()` and `std::any::type_name_of_val()`
  3. Track skipped components in a `Vec<String>` and emit a summary warning at the end if any components were skipped
- **Note**: Used `component.signature()` instead of `component.name()` because the `Component` trait doesn't have a `name()` method - `signature()` provides component identification information
- **Tests**: Added three unit tests with proper tracing capture using `tracing_subscriber`:
  - `test_energy_balance_warns_for_skipped_components`: Verifies warning is emitted with "SKIPPED in energy balance validation"
  - `test_energy_balance_includes_component_type_in_warning`: Verifies component type is included in warning
  - `test_energy_balance_summary_warning`: Verifies summary warning with "Energy balance validation incomplete"
- **Code Review Fix**: Added `tracing-subscriber` to dev-dependencies for proper log capture in tests
- All acceptance criteria satisfied

### File List

- `crates/solver/src/system.rs` (modified)
