# components/plant design backlog

Findings from reviewing `pot.py`'s water-bath model against real-plant
behavior (sim/real control mismatch reported by user), refreshed against
the current `delay`-line rewrite of `Pot`.

- [x] **Heat-loss term has wrong units.** Fixed by the `Pot` rewrite:
  `process()` now computes `p_loss = self.L * self.M * (self.temp -
  self.theta_amb)` in Watts and applies `self.temp += (self.delay.get()
  - p_loss) / (self.M * self.C) * self.dt` — the same `/(M*C)`
  normalization for both the gain and loss terms, instead of the old
  mismatched `leak = 1/self.M * self.L * (...)/ self.theta_amb`.

- [x] **Thermal lag modeled as single-pole lag, not transport delay.**
  Fixed: `Pot` no longer uses `HeatDiffusion`'s `alpha=dt/Td`
  exponential smoothing (that module was deleted). It now delays the
  input power through `plant/delay.py`'s `Delay` (true dead time)
  before integrating it, matching what this item recommended.

- [x] **`kn` is loaded but never applied.** Resolved differently than
  originally proposed: `kn` was removed from `Pot` entirely rather than
  wired up as plant-side measurement noise. Sensor noise is now
  modeled one layer up, in `TempSensorSim` (`temp_offset`/`variance`,
  wired from `brewpi.py`'s `TempSensorFactory.create(..., temp_offset=
  -0.15, variance=0.01)`), not in the plant model. Note: `config.json.templ`
  and `config.json.sim` still carry stale `Model.kn`/`Plant.kn` keys
  that nothing reads anymore — harmless but worth deleting (see
  `components/pid/TODO.md`'s config-validation item).

- [x] **`theta_amb` is hardcoded, not configured.** Fixed: added a
  top-level `ambient_temperature` key to `config.json`(`.templ`/`.sim`);
  `brewpi.py` reads it once and passes it to both the real `Pot` and
  (via a new `theta_amb` param) `temp_controller_smith.py`'s internal
  models, so the Smith predictor's model matches the real plant's
  assumed ambient instead of silently defaulting to 20. Real ambient
  temperature still isn't modeled as a *drifting* disturbance (it's a
  static config value, not a live sensor reading), so robustness to
  ambient drift remains untested — that part of the original concern
  stands.

- [ ] **No actuator/process realism.** Partially improved: `process()`
  now clamps `self.temp` to `min(100, ...)` (won't simulate past
  boiling), but there's still no heater power saturation enforced
  inside `Pot` itself (handled ad hoc in demo harnesses), no
  evaporation/lid heat loss, and no varying thermal mass `M` as volume
  changes (e.g. boil-off, adding water/grain) — `M` is a fixed
  constant for the whole simulation.

- [x] **Debug `print()`s left in `Pot.process()`.** Fixed: the
  unconditional `p_loss`/`theta_amb`/`temp` prints (leftover from the
  heat-loss-units fix) were removed.
