Problem
LTM augmentation synthesizes link-score / loop-score / partial-equation fragments and compiles them alongside the user's model. Historically, a fragment that failed to compile was silently stubbed to a constant 0, producing quietly wrong loop scores. That defect class recurred repeatedly: #738, #741, #758, #759, and most recently #751 -- a live silent stub where 4 fragment-failure warnings hid all-zero scores behind a fixture that only asserted loop-ID prefixes. Each instance was found by review archaeology, not by CI.
The fixes so far make failures loud at runtime (model_ltm_fragment_diagnostics, the unscoreable_edges loud-skip/loop-drop invariant from PR #775) and add per-fixture zero-warning assertions. But nothing systematically generates novel shapes and checks that every emitted fragment compiles -- so the next shape-space corner (subscript form x reducer kind x module boundary x scoring surface is combinatorial) will again only be caught if a hand-written fixture happens to cover it.
Proposal
An invariant harness that, over a generated model corpus, compiles EVERY emitted LTM synthetic fragment and fails on any fragment-compile failure:
Why it matters
Epic #488's Strategy section names this the top prevention candidate: "Prevention beats archaeology. Extend the generated-corpus invariants (the element_graph_proptest pattern) so new defect classes fail in CI instead of being filed from review; an every-emitted-fragment-compiles harness is the top candidate." It would have caught the entire #738/#741/#758/#759 silent-stub family at birth, and the #751 live stub. It directly defends the epic's standing "no silent wrong numbers" invariant going forward.
Components
Context
Identified during the LTM burn-down strategy work (epic #488) and explicitly deferred by the shape-expressiveness design plan (docs/design-plans/2026-06-11-ltm-shape-expressiveness.md) with a mandate to file at landing time. Filed per that mandate.
Problem
LTM augmentation synthesizes link-score / loop-score / partial-equation fragments and compiles them alongside the user's model. Historically, a fragment that failed to compile was silently stubbed to a constant 0, producing quietly wrong loop scores. That defect class recurred repeatedly: #738, #741, #758, #759, and most recently #751 -- a live silent stub where 4 fragment-failure warnings hid all-zero scores behind a fixture that only asserted loop-ID prefixes. Each instance was found by review archaeology, not by CI.
The fixes so far make failures loud at runtime (
model_ltm_fragment_diagnostics, theunscoreable_edgesloud-skip/loop-drop invariant from PR #775) and add per-fixture zero-warning assertions. But nothing systematically generates novel shapes and checks that every emitted fragment compiles -- so the next shape-space corner (subscript form x reducer kind x module boundary x scoring surface is combinatorial) will again only be caught if a hand-written fixture happens to cover it.Proposal
An invariant harness that, over a generated model corpus, compiles EVERY emitted LTM synthetic fragment and fails on any fragment-compile failure:
element_graph_proptestmodel-generation strategy (src/simlin-engine/src/db/element_graph_proptest.rs) as the corpus template; extend it toward the shape axes that have bitten (mixed-arity reducers, module boundaries, mapped/subrange dims, multi-reducer targets).model_ltm_fragment_diagnosticsis empty -- or that every warning is one of the documented loud-degradation classes (e.g. the ltm: declined element-mapped sliced reducer emits a non-compiling scalar link score on the conservative path (loop scores stub to 0) #758/ltm: arrayed-owner Pinned/subset broadcast reduce slice loud-skipped; needs the PerElement broadcast rule on variable-backed owners #777/ltm: PartialEquationError link-score skips don't drop dependent loop scores via unscoreable_edges #780 unscoreable families). The harness must distinguish "documented loud skip" from "fragment that should have compiled".#[ignore]d lane (like the C-LEARN#[ignore]gates insrc/simlin-engine/tests/integration/simulate.rs), run in CI on a schedule or pre-merge. Per-generated-case LTM compilation is a full salsa compile per case, which blows the seconds-per-test debug budget -- that is exactly why this was deferred out of the shape-expressiveness Phase 1 (docs/design-plans/2026-06-11-ltm-shape-expressiveness.md, "Test strategy": "follow-up, not Phase 1 ... File the harness as its own issue at landing time"). See also ci: add a release-mode lane so C-LEARN-scale tests can be un-ignored #657 (release-mode CI lane), a natural host.Why it matters
Epic #488's Strategy section names this the top prevention candidate: "Prevention beats archaeology. Extend the generated-corpus invariants (the
element_graph_proptestpattern) so new defect classes fail in CI instead of being filed from review; an every-emitted-fragment-compiles harness is the top candidate." It would have caught the entire #738/#741/#758/#759 silent-stub family at birth, and the #751 live stub. It directly defends the epic's standing "no silent wrong numbers" invariant going forward.Components
src/simlin-engine/src/db/element_graph_proptest.rs(generator to reuse/extend)src/simlin-engineLTM augmentation +model_ltm_fragment_diagnosticsContext
Identified during the LTM burn-down strategy work (epic #488) and explicitly deferred by the shape-expressiveness design plan (
docs/design-plans/2026-06-11-ltm-shape-expressiveness.md) with a mandate to file at landing time. Filed per that mandate.