Contents — find the section you need
A normal EC can still require a hold
The recovered-solution guide separated sanitation and treatment history from EC and pH. This guide connects the two ledgers without merging them. The nutrient ledger tracks volume, component mass, EC, pH and temperature. The sanitation ledger tracks source, isolation, tests, treatment and residual checks.
UVM Extension explains that circulating nutrient solution connects surfaces across a system and can spread a problem. It also recommends tracking water quality over time together with filtration or treatment and hygiene. The UVM resource supports treating “chemical conditions fit” and “sanitation conditions complete” as separate predicates.
Keep two ledgers instead of one status field
| Ledger | Examples | Update trigger | Error prevented |
|---|---|---|---|
| Nutrient/water | Volume, component mass, EC, pH, temperature | Addition, drain, uptake, measurement | Reconstructing mass from concentration alone |
| Sanitation/treatment | Source, isolation ID, test, treatment, residual | Recovery, anomaly, cleaning, treatment completion | Returning matching-EC liquid unconditionally |
The same timestamp does not make them the same measurement. A ten-litre loss says nothing about microbial condition. A treatment record does not prove that the liquid avoided a new contamination path afterward.
Require four conditions before a reuse candidate
Use these synthetic conditions for a candidate:
- Nutrient volume and component mass are finite and their difference is within the chosen tolerance.
- The recovered lot has an isolation record.
- Required sanitation tests and treatment-residual checks are complete.
- The sample is fresh enough and the destination loop is specified.
If any condition is missing, return HOLD or REJECT; do not mix another liquid to make the ledger balance. UVM notes that surfaces touched by circulating water can become food-contact surfaces, so changing the destination does not reset sanitation state.
Classify a synthetic record with two ledgers
from math import isfinite
def decision(chem, hygiene):
if chem.get("volume_l", 0) <= 0 or chem.get("mass_mg", 0) < 0:
return "REJECT"
if not all(isfinite(float(chem.get(k, float("nan"))))
for k in ("volume_l", "mass_mg", "ec")):
return "REJECT"
if not hygiene.get("lot_id") or not hygiene.get("isolated"):
return "HOLD"
if not hygiene.get("test_passed") or not hygiene.get("residual_checked"):
return "HOLD"
if hygiene.get("age_h", 999) > 2:
return "HOLD"
return "REUSE_CANDIDATE"
cases = [
({"volume_l": 10, "mass_mg": 800, "ec": 1.4},
{"lot_id": "R-01", "isolated": True, "test_passed": True,
"residual_checked": True, "age_h": 1}),
({"volume_l": 10, "mass_mg": 800, "ec": 1.4},
{"lot_id": "R-02", "isolated": True, "test_passed": False,
"residual_checked": True, "age_h": 1}),
({"volume_l": 0, "mass_mg": 800, "ec": 1.4},
{"lot_id": "R-03", "isolated": True, "test_passed": True,
"residual_checked": True, "age_h": 1}),
]
print([decision(c, h) for c, h in cases])
The output is ['REUSE_CANDIDATE', 'HOLD', 'REJECT']. This is a classification sent to a later approval step, not a reuse command.
Keep both ledgers open after reuse
Add the returned volume to nutrient accounting and link lot ID, treatment record and destination to the sanitation ledger. Do not infer treatment success from EC or level changes after return. If an anomaly appears, retain enough linkage to trace the last recovered lot and shared plumbing.
These four conditions do not replace legal release decisions, pathogen assays or treatment-product selection. Next comes traceability and isolation when multiple recovered lots are mixed.

Comments
Please log in to post a comment
No comments yet.