v0.4.0 — one row per plant
measure_regions() — one row per plant. measure() treats the whole frame as one region, so a tray of seedlings was merged into a single object and every size trait described the group. Regions come from auto_grid or rect_grid, and the response carries an overlay with each region outlined and numbered. An empty cell is refused by name rather than reported as area = 0.0.
Traits checked against known geometry. An 80×80 square must measure 6400 px — arithmetic as the oracle, not a stored baseline.
Audit fixes. measure() reports the PlantCV version that produced the numbers. A fresh-subprocess test drives the tool layer end to end, covering the import-time global-state failure class that bit a sibling server while 27 of its tests stayed green.
Full detail in CHANGELOG.md.