You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
model_detected_loops (src/simlin-engine/src/db/analysis.rs, ~line 2082; post-#746 it reuses the scored loop builder) has no stateless gate. For stateless-but-cyclic model shapes it still REPORTS enumerated loops, while the scored surface (model_ltm_variables, src/simlin-engine/src/db/ltm/mod.rs) bails via its stateless early return and emits zero LTM variables -- so the reported loops are detected-but-never-scorable. And because the bail happens before pin processing, a SetLoopName pin over one of those (reported!) cycles is silently dropped with no diagnostic -- the #770 silence class, except here the user can see the loop in the detected surface, making the silence more surprising.
#749 fixed the parent-level-PREVIOUS instance of the surface disagreement. The remaining stateless-but-cyclic shapes post-#749:
(a) Instantaneous cycles through stockless PASSTHROUGH modules. The parent-level cycle is broken at the module boundary, so it is not a compile-time CircularDependency -- but there is no state anywhere in the model.
(b) MODULE-INTERNAL-PREVIOUS cycles. Deliberately uncounted by model_is_stateless so the detected and scored surfaces agree on what counts as state (see the sibling issue on module-internal PREVIOUS, filed in the same #749/#750 batch).
For both shapes: model_ltm_variables returns zero vars with no invalid-pin warnings, while model_detected_loops reports the enumerated loops.
Note this also narrows #770's mitigating-scope claim that "a stateless model with a CYCLE is a loud compile-time CircularDependency anyway": shapes (a) and (b) are stateless, cyclic, and compile cleanly, so the silent-pin-drop case is not limited to acyclic models.
Why it matters
Consistency: phantom structural reporting -- the detected surface presents loops the scoring pipeline will never score, with nothing telling the user why.
src/simlin-engine/src/db/ltm/pinned.rs (model_pinned_loops, unreachable on this path)
Possible approaches
Give model_detected_loops the same model_is_stateless gate, returning pins-only or empty, mirroring the scored surface's semantics (the two surfaces then agree that stateless models have no scoreable feedback); or
#770 (pin on a genuinely stateless model bypasses validation -- typo'd pin gets no invalid-pin warning) was closed as consolidated into this issue: both need the same warning mechanism on the same gate, and this issue's fix (a stateless gate or warning shared across the detected/pin surfaces) delivers #770's typo'd-pin warning as a side effect. The adjacent cleanup from #770's body also rides here: compile_ltm_implicit_var_fragment's dead _dep_graph parameter (db/ltm/compile.rs ~1683), which both callers compute and pass for nothing.
Problem
model_detected_loops(src/simlin-engine/src/db/analysis.rs, ~line 2082; post-#746 it reuses the scored loop builder) has no stateless gate. For stateless-but-cyclic model shapes it still REPORTS enumerated loops, while the scored surface (model_ltm_variables,src/simlin-engine/src/db/ltm/mod.rs) bails via its stateless early return and emits zero LTM variables -- so the reported loops are detected-but-never-scorable. And because the bail happens before pin processing, aSetLoopNamepin over one of those (reported!) cycles is silently dropped with no diagnostic -- the #770 silence class, except here the user can see the loop in the detected surface, making the silence more surprising.#749 fixed the parent-level-PREVIOUS instance of the surface disagreement. The remaining stateless-but-cyclic shapes post-#749:
(a) Instantaneous cycles through stockless PASSTHROUGH modules. The parent-level cycle is broken at the module boundary, so it is not a compile-time
CircularDependency-- but there is no state anywhere in the model.(b) MODULE-INTERNAL-PREVIOUS cycles. Deliberately uncounted by
model_is_statelessso the detected and scored surfaces agree on what counts as state (see the sibling issue on module-internal PREVIOUS, filed in the same #749/#750 batch).For both shapes:
model_ltm_variablesreturns zero vars with no invalid-pin warnings, whilemodel_detected_loopsreports the enumerated loops.Note this also narrows #770's mitigating-scope claim that "a stateless model with a CYCLE is a loud compile-time CircularDependency anyway": shapes (a) and (b) are stateless, cyclic, and compile cleanly, so the silent-pin-drop case is not limited to acyclic models.
Why it matters
result.invalidmachinery, ltm: pin on a genuinely stateless model bypasses validation -- typo'd pin gets no invalid-pin warning #770's framing); here it produces silence on a loop the tool itself reported.Components affected
src/simlin-engine/src/db/analysis.rs(model_detected_loops, no stateless early-out)src/simlin-engine/src/db/ltm/mod.rs(model_ltm_variablesstateless gate /model_is_stateless)src/simlin-engine/src/db/ltm/pinned.rs(model_pinned_loops, unreachable on this path)Possible approaches
model_detected_loopsthe samemodel_is_statelessgate, returning pins-only or empty, mirroring the scored surface's semantics (the two surfaces then agree that stateless models have no scoreable feedback); orEither way the resolution should be coordinated with #770 (same warning text/mechanism) so stateless pin handling is uniform.
Cross-references
model_detected_loopsonto the scored loop builder (no stateless gate added)How discovered
Identified as a residual during GH #749/#750 work on branch
ltm-fix-batch-2(commits69e84d8e/03a9ec1f), 2026-06.Absorbed #770
#770 (pin on a genuinely stateless model bypasses validation -- typo'd pin gets no invalid-pin warning) was closed as consolidated into this issue: both need the same warning mechanism on the same gate, and this issue's fix (a stateless gate or warning shared across the detected/pin surfaces) delivers #770's typo'd-pin warning as a side effect. The adjacent cleanup from #770's body also rides here:
compile_ltm_implicit_var_fragment's dead_dep_graphparameter (db/ltm/compile.rs~1683), which both callers compute and pass for nothing.