7.0 KiB
Code Review Findings — Story 3.4: Thermal Coupling Between Circuits
Story: 3-4-thermal-coupling-between-circuits.md
Reviewer: Adversarial Senior Developer (workflow)
Date: 2026-02-17
Git vs Story Discrepancies: 3 (files modified/untracked not in File List; solver crate untracked)
Summary
| Severity | Count |
|---|---|
| CRITICAL | 1 |
| HIGH | 1 |
| MEDIUM | 4 |
| LOW | 2 |
Total issues: 8
CRITICAL ISSUES
C1. Task marked [x] but not implemented — coupling residuals and Jacobian (AC#4)
Location: Story Tasks "Expose coupling residuals for solver (AC: #4)" — marked complete.
Evidence:
- Story requires:
coupling_residuals(state: &SystemState) -> Vec<f64>andcoupling_jacobian_entries()returning(row, col, partial_derivative)tuples. - Neither API exists in
crates/solver/src/system.rsorcrates/solver/src/coupling.rs. - AC#4 states: "When solver assembles residuals, coupling contributes additional residual equations" and "Jacobian includes coupling derivatives". The solver has no way to obtain coupling residuals or Jacobian entries.
Impact: Story 4.x (Solver) cannot consume thermal coupling in the solve loop. AC#4 is not implemented.
Recommendation: Implement coupling_residuals and coupling_jacobian_entries (or equivalent) on System or in a solver-facing module, or mark the task and AC#4 as partial and add follow-up tasks.
HIGH ISSUES
H1. Acceptance Criterion #4 not implemented
Criterion: "Given a defined thermal coupling, when solver assembles residuals, then coupling contributes additional residual equations and Jacobian includes coupling derivatives."
Evidence: No function in the codebase computes coupling residuals from SystemState or provides Jacobian entries for couplings. The story is marked as satisfying all ACs; AC#4 is MISSING.
Recommendation: Either implement the residual and Jacobian coupling API or update the story to reflect partial completion and add a follow-up story/task.
MEDIUM ISSUES
M1. Missing tracing::warn for circular dependency (Architecture Compliance)
Location: crates/solver/src/coupling.rs and finalize() path.
Evidence:
- Architecture Compliance in story: "tracing for circular dependency warnings:
tracing::warn!(\"Circular thermal coupling detected, simultaneous solving required\")". has_circular_dependencies()is implemented but never logs. No call totracing::warn!when circular dependencies are detected (e.g. infinalize()or when adding a coupling that creates a cycle).
Recommendation: In System::finalize(), after topology validation, call has_circular_dependencies(self.thermal_couplings()) and if true, emit tracing::warn!(...) as specified.
M2. Files changed but not in story File List
Evidence (git vs story):
- In git (modified or untracked) but not listed in Dev Agent Record → File List:
Cargo.toml(workspace root)_bmad-output/implementation-artifacts/sprint-status.yaml_bmad-output/planning-artifacts/epics.md_bmad-output/planning-artifacts/prd.md
- Entire
crates/solver/is untracked (??); story File List correctly lists solver files as new/modified, but sprint-status and planning-artifacts changes are not documented.
Recommendation: Either add the modified planning/artifacts files to the File List (if they were intentionally changed for this story) or note in Change Log that only code changes are claimed for 3.4.
M3. Integration test "test_coupling_residuals_basic" missing
Location: Story Testing Requirements — "Integration tests (system.rs or multi_circuit.rs): test_coupling_residuals_basic — 2 circuits with coupling, verify residual equation."
Evidence:
crates/solver/tests/multi_circuit.rsexists and has tests for multi-circuit topology and thermal coupling add/get, but no test that verifies "residual equation" for couplings.- Such a test cannot be fully implemented until
coupling_residualsexists; the story nonetheless claims the task "Tests" as done and lists this test.
Recommendation: Add a placeholder or skip test that documents the requirement, and implement the real test when coupling_residuals is added.
M4. finalize() does not run circular-dependency check or log
Location: Story Dev Notes — "Circular dependency detection at finalize time"; Architecture — "Coupling graph built once at finalize/build time."
Evidence:
System::finalize()callsvalidate_topology()only. It does not callhas_circular_dependencies(&self.thermal_couplings)nor log that simultaneous solving will be required.- Solver has no built-time signal that coupling groups / circular dependencies were detected.
Recommendation: In finalize(), after successful topology validation, if !self.thermal_couplings.is_empty() and has_circular_dependencies(self.thermal_couplings()), call tracing::warn!("Circular thermal coupling detected, simultaneous solving required") and optionally store a flag or coupling groups for the solver to use.
LOW ISSUES
L1. compute_coupling_heat returns f64 instead of NewType HeatTransfer
Location: crates/solver/src/coupling.rs — compute_coupling_heat() returns f64.
Evidence:
- Story Technical Requirements: "Returns HeatTransfer" and "HeatTransfer(pub f64)" in code block; Architecture: "Use ThermalConductance(pub f64), HeatTransfer(pub f64) for clarity" and "never bare f64 in public APIs."
entropyk_coredoes not defineHeatTransfer; the function returns rawf64. Semantics are correct; only the type-safety and documentation alignment are missing.
Recommendation: Add HeatTransfer(pub f64) to crates/core/src/types.rs (with Display/From/helpers) and change compute_coupling_heat to return HeatTransfer. Re-export from core and use in solver.
L2. NFR4 / no-allocation in solver loop vs Vec return
Location: Story and Architecture.
Evidence:
- Architecture: "No dynamic allocation in solver loop"; Story Dev Notes: "coupling_residuals() called in solver loop — must be fast (no allocation)."
- Story task proposes
coupling_residuals(state: &SystemState) -> Vec<f64>, which allocates every call.
Recommendation: When implementing coupling_residuals, prefer a signature that writes into a pre-allocated slice (e.g. fn coupling_residuals(&self, state: &SystemState, out: &mut [f64])) so the solver loop can reuse a single buffer and respect NFR4.
Checklist (validation)
- Story file loaded and parsed
- Git status/diff compared to story File List
- Acceptance Criteria checked against implementation
- Tasks marked [x] verified for actual completion
- Code quality and architecture compliance reviewed
- Test coverage vs story requirements checked
- Outcome: Changes applied (CRITICAL/HIGH/MEDIUM fixes applied 2026-02-17; story status → done)
Review completed. CRITICAL and HIGH issues fixed automatically; story status set to done.