Skip to content

Retire claims that #55 and #93 outlived - #115

Merged
dfalster merged 1 commit into
masterfrom
fix/stale-cache-key-claims
Aug 20, 2026
Merged

Retire claims that #55 and #93 outlived#115
dfalster merged 1 commit into
masterfrom
fix/stale-cache-key-claims

Conversation

@dfalster

Copy link
Copy Markdown
Member

Four sites described the model as it was before two merged fixes.
The one that mattered is user-facing: fitting.Rmd told readers
that changing a trait and re-driving takes a temperature-cache
hit and silently reports the first vcmax it ever saw. #55 put
every input of the temperature block in the key, so it does not.
The advice to use set_traits() stands on the splines, the solved
operating point and the #25 checks instead.

Comments and prose only; both golden files bit-identical. The
closed_form/#93 divergence is recorded, not repaired -- see NEWS.

Four sites described the model as it was before two merged fixes.
The one that mattered is user-facing: fitting.Rmd told readers
that changing a trait and re-driving takes a temperature-cache
hit and silently reports the first vcmax it ever saw. #55 put
every input of the temperature block in the key, so it does not.
The advice to use set_traits() stands on the splines, the solved
operating point and the #25 checks instead.

Comments and prose only; both golden files bit-identical. The
closed_form/#93 divergence is recorded, not repaired -- see NEWS.
@dfalster

Copy link
Copy Markdown
Member Author

How these were found, since it is repeatable

Not by reading. By grepping for the specific false sentences two merged fixes had created, which is a different search from "look for stale comments":

grep -rn -e "atm_o2_kpa) alone" -e "atm_o2_kpa_) alone" \
         -e "atm_o2_kpa) and NOT on the traits" \
         -e "atm_o2_kpa_) and on nothing else" inst R src tests vignettes *.md .claude
grep -rn -e "clears lambda_" -e "cleared to NA by the constructor and by" ...
grep -rn -e "atm_vpd_ /" -e "divided by the air" ...

Six hits, of which two were false positives worth naming because they show what the grep cannot decide:

So the tense and the strikethrough carry the meaning, and a grep for the claim finds the history as well as the rot. Worth checking each hit rather than batch-editing.

The lambda_ sweep came back clean#109 had already caught all of those, including the two claims #93 wrote into the optimise_psi_stem_Sperry guard.

The one that actually mattered

vignettes/fitting.Rmd is user-facing, and it did not merely describe old behaviour — it warned against a safe pattern using a false mechanism:

the derived vcmax_, jmax_ and R_d_ live in a temperature cache keyed on (leaf_temp, atm_o2_kpa) and nothing else, so changing a trait and re-setting the drivers takes a cache hit and never recomputes them. A sweep written that way runs at the first vcmax it ever saw and reports plausible numbers throughout.

A reader who had already written a sweep that way would conclude their published numbers were garbage. Since #55 they are fine. The conclusion (use set_traits()) is unchanged and still correct — but for the splines, the solved operating point and the #25 checks, none of which any re-driving repairs. Kept a dated "Corrected in 0.5.0" note rather than deleting the old claim silently, so anyone who acted on the old warning can see that it moved.

The test comment was the subtle one

test_set_traits_matches_a_fresh_leaf has a sub-block introduced as "the specific trap, isolated", asserting that doubling vcmax_25 then re-driving doubles vcmax_ — "which it is only because set_traits invalidates the cache".

That reasoning is now unsound, and the assertion cannot detect it. With vcmax_25 in the key, the cache misses on the changed trait whether or not set_traits cleared anything, so the trap is closed twice over and the test passes either way. Its own comment even said "The SAME leaf_temp and atm_o2_kpa, which is what arms the cache" — arming now also requires the traits to be unchanged, and this block deliberately changes one.

Nothing is deleted: the assertion is still true and still worth having. What changed is that it now says which mechanism it can and cannot distinguish, and points at where each half is covered — test_temperature_params_invalidate_cache for the key, and the bit-exact comparisons above plus test_prescribed_lambda_survives_redriving for set_traits' clearing. This is the failure mode where a test keeps passing while the guarantee it documents has moved elsewhere.

Recorded, not repaired: closed_form.hpp

Every D in closed_form.hpp is atm_vpd_, because that is what Fick's law divided by when it was written. #93 moved the live model to vpd_leaf_, which on the energy-balance path is 3–4× the air's over Tair 25–45. Off that path they are equal by constructionset_leaf_vpd returns atm_vpd_ exactly — so the prescribed-temperature path is untouched.

Left as a documented divergence rather than substituted, for a reason worth stating: vpd_leaf_ depends on Tleaf, which depends on E, which is the quantity these expressions solve for in closed form. So the substitution is plausibly not a rename and the closed form may not stay closed. That is a numerics change to dormant, PM-untested code and wants its own issue, which I am filing.

Verification

Comments and prose only, so the interesting result is that nothing moved:

  • make -C tests/cpp from clean: 646 checks, 0 failures; operating_points.tsv 576/576 and primitives.tsv 544/544 bit-identical.
  • make -C tests/cpp bench builds, same checksum.
  • Full R suite green; gradient_golden.tsv worst relative difference 0.

The inst/RcppR6_classes.yml edit is a YAML comment, not a roxygen block — confirmed it appears in neither R/RcppR6.R nor man/, so no regeneration is required and none was done.

⚠️ The vignette is rendered by R CMD check, not by anything I ran locally; the two release jobs are what confirm it still knits.

@dfalster
dfalster merged commit 2850b6f into master Aug 20, 2026
7 checks passed
@dfalster
dfalster deleted the fix/stale-cache-key-claims branch August 20, 2026 03:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant