Summary
generate_nonlinear_partial (src/simlin-engine/src/ltm_augment.rs) -- the MIN/MAX nested-binary and STDDEV unrolled-variance per-row source->agg partial builders -- is body-blind for non-bare reducer bodies. It substitutes the bare source elements into the analytic partial shape, ignoring any arithmetic inside the reducer argument, producing silent garbage link scores.
This is the NONLINEAR-arm sibling of #744. The #744 fix (commit 5a533bf6 on branch ltm-fix-batch-2) taught the LINEAR (SUM/MEAN) per-row partial to derive from the reducer BODY -- live row, frozen co-reduced rows and co-sources, via the pin_body_to_row / freeze_pinned_body machinery -- but the nonlinear arm still builds its MIN/MAX/STDDEV shapes from the bare elements.
Repro (confirmed empirically)
grow = 1 + MIN(pop[*] * 0.25)
emits the per-row partial
MIN(pop[north], PREVIOUS(pop[south]))
-- raw pop units compared against a 0.25-scaled aggregate -- producing garbage link scores of roughly 2884 on the probe fixture.
Why it matters
Medium severity: silent garbage link scores (and hence loop scores) for MIN/MAX/STDDEV reducers with ANY arithmetic inside the argument, e.g. MIN(cost[*] * weight). Bare bodies like MIN(pop[*]) remain correct (the #483 analytic partials are sound for those).
Component
src/simlin-engine/src/ltm_augment.rs (generate_nonlinear_partial: the MIN/MAX nested-binary builder and the STDDEV unrolled-variance builder)
Fix shape
Extend the #744 pin/freeze machinery (pin_body_to_row / freeze_pinned_body, built in 5a533bf6) so each term_for in the nonlinear builders is the row-pinned BODY rather than the bare element; bail to the documented delta-ratio fallback when the body is unpinnable -- the same contract the linear arm follows.
Cross-references (related, NOT duplicates)
Discovery context
Confirmed during GH #744 implementation on branch ltm-fix-batch-2 (commit 5a533bf6); the limitation is noted generically in generate_nonlinear_partial's rustdoc as of that commit, pending this issue number.
Summary
generate_nonlinear_partial(src/simlin-engine/src/ltm_augment.rs) -- the MIN/MAX nested-binary and STDDEV unrolled-variance per-row source->agg partial builders -- is body-blind for non-bare reducer bodies. It substitutes the bare source elements into the analytic partial shape, ignoring any arithmetic inside the reducer argument, producing silent garbage link scores.This is the NONLINEAR-arm sibling of #744. The #744 fix (commit
5a533bf6on branchltm-fix-batch-2) taught the LINEAR (SUM/MEAN) per-row partial to derive from the reducer BODY -- live row, frozen co-reduced rows and co-sources, via thepin_body_to_row/freeze_pinned_bodymachinery -- but the nonlinear arm still builds its MIN/MAX/STDDEV shapes from the bare elements.Repro (confirmed empirically)
emits the per-row partial
-- raw
popunits compared against a 0.25-scaled aggregate -- producing garbage link scores of roughly 2884 on the probe fixture.Why it matters
Medium severity: silent garbage link scores (and hence loop scores) for MIN/MAX/STDDEV reducers with ANY arithmetic inside the argument, e.g.
MIN(cost[*] * weight). Bare bodies likeMIN(pop[*])remain correct (the #483 analytic partials are sound for those).Component
src/simlin-engine/src/ltm_augment.rs(generate_nonlinear_partial: the MIN/MAX nested-binary builder and the STDDEV unrolled-variance builder)Fix shape
Extend the #744 pin/freeze machinery (
pin_body_to_row/freeze_pinned_body, built in5a533bf6) so eachterm_forin the nonlinear builders is the row-pinned BODY rather than the bare element; bail to the documented delta-ratio fallback when the body is unpinnable -- the same contract the linear arm follows.Cross-references (related, NOT duplicates)
Discovery context
Confirmed during GH #744 implementation on branch
ltm-fix-batch-2(commit5a533bf6); the limitation is noted generically ingenerate_nonlinear_partial's rustdoc as of that commit, pending this issue number.