Summary
In discovery mode, the input -> module link score for a loop that traverses a multi-output-port submodel can be the wrong polarity (inverted sign) relative to the exhaustive-mode score for the same loop. This is not merely an approximation or a cross-process nondeterminism gap (cf. #680); it is a deterministic sign error on the structural interpretation of a loop, and discovery is the mode that large / auto-flipped models fall into.
Root cause
PR #684 added a per-exit-port pathway-selection override (compute_module_link_overrides in src/simlin-engine/src/db/ltm/mod.rs) so that, in exhaustive mode, a loop through a multi-output module scores against the pathway ending at the exit port the loop actually traverses. That override is keyed by (loop_id, link_index) and threaded into the loop-score equation builder.
Discovery mode emits no loop-score variables (loops are ranked post-simulation by the strongest-path search), so there is nothing to override. The base input -> module link score in discovery mode is therefore the composite, which max-abs-selects across ALL output ports. For single-dependency exit ports every pathway normalizes to magnitude exactly 1, so the >= first-index tie-break picks an arbitrary port -- which may be a different port than the one the loop traverses, and that port can have the opposite sign.
The design doc (docs/design/ltm--loops-that-matter.md, "Discovery-mode asymmetry", ~line 474) currently frames this as a "paper-faithful per-edge approximation" / "asymmetry", which understates the consequence: the resulting score can be the wrong sign, not just a less-precise magnitude.
Empirical repro
A submodel exposing two outputs:
pos = input * 0.02
neg = -input
A parent with a feedback loop that reads m·pos, and a side variable that reads m·neg:
- Exhaustive raw loop score = +1.0 (correct: reinforcing).
- Discovery
signal -> m link score = -1.0 (the composite selected the neg exit port), inverting the loop's polarity.
Why it matters
Polarity is the primary structural story LTM tells a modeler ("this is a reinforcing loop" vs. "balancing loop"). A flipped sign on a loop through a multi-output submodel can mislead structural interpretation, and discovery is exactly the regime large/auto-flipped models run in -- so this is not confined to a rare edge. Correctness, not just precision, of a user-facing label.
Component(s) affected
src/simlin-engine/src/db/ltm/mod.rs (compute_module_link_overrides, discovery vs. exhaustive link-score path)
src/simlin-engine/src/db/ltm/loops.rs (composite / per-exit-port pathway selection feeding the discovery search graph)
docs/design/ltm--loops-that-matter.md (the "Discovery-mode asymmetry" section that frames this as an approximation)
Possible approaches
- Emit per-exit-port
via link-score aliases in discovery mode too, and key the discovery search graph's module edges by exit port, so the strongest-path search traverses the pathway matching the port it actually reads (parity with the exhaustive per-exit-port override).
- At minimum, elevate the design-doc wording from "asymmetry" / "approximation" to "discovery mode can report the wrong polarity for a loop through a multi-output module", so the limitation is not understated.
- Add a regression fixture (the
pos/neg submodel above) asserting discovery and exhaustive agree on the sign of the loop through the multi-output module.
Relationship to existing issues
Context
Identified during a deep LTM review (2026-06-03), empirically reproduced. Tracking epic: #488.
Summary
In discovery mode, the
input -> modulelink score for a loop that traverses a multi-output-port submodel can be the wrong polarity (inverted sign) relative to the exhaustive-mode score for the same loop. This is not merely an approximation or a cross-process nondeterminism gap (cf. #680); it is a deterministic sign error on the structural interpretation of a loop, and discovery is the mode that large / auto-flipped models fall into.Root cause
PR #684 added a per-exit-port pathway-selection override (
compute_module_link_overridesinsrc/simlin-engine/src/db/ltm/mod.rs) so that, in exhaustive mode, a loop through a multi-output module scores against the pathway ending at the exit port the loop actually traverses. That override is keyed by(loop_id, link_index)and threaded into the loop-score equation builder.Discovery mode emits no loop-score variables (loops are ranked post-simulation by the strongest-path search), so there is nothing to override. The base
input -> modulelink score in discovery mode is therefore the composite, whichmax-abs-selects across ALL output ports. For single-dependency exit ports every pathway normalizes to magnitude exactly 1, so the>=first-index tie-break picks an arbitrary port -- which may be a different port than the one the loop traverses, and that port can have the opposite sign.The design doc (
docs/design/ltm--loops-that-matter.md, "Discovery-mode asymmetry", ~line 474) currently frames this as a "paper-faithful per-edge approximation" / "asymmetry", which understates the consequence: the resulting score can be the wrong sign, not just a less-precise magnitude.Empirical repro
A submodel exposing two outputs:
pos = input * 0.02neg = -inputA parent with a feedback loop that reads
m·pos, and a side variable that readsm·neg:signal -> mlink score = -1.0 (the composite selected thenegexit port), inverting the loop's polarity.Why it matters
Polarity is the primary structural story LTM tells a modeler ("this is a reinforcing loop" vs. "balancing loop"). A flipped sign on a loop through a multi-output submodel can mislead structural interpretation, and discovery is exactly the regime large/auto-flipped models run in -- so this is not confined to a rare edge. Correctness, not just precision, of a user-facing label.
Component(s) affected
src/simlin-engine/src/db/ltm/mod.rs(compute_module_link_overrides, discovery vs. exhaustive link-score path)src/simlin-engine/src/db/ltm/loops.rs(composite / per-exit-port pathway selection feeding the discovery search graph)docs/design/ltm--loops-that-matter.md(the "Discovery-mode asymmetry" section that frames this as an approximation)Possible approaches
vialink-score aliases in discovery mode too, and key the discovery search graph's module edges by exit port, so the strongest-path search traverses the pathway matching the port it actually reads (parity with the exhaustive per-exit-port override).pos/negsubmodel above) asserting discovery and exhaustive agree on the sign of the loop through the multi-output module.Relationship to existing issues
Context
Identified during a deep LTM review (2026-06-03), empirically reproduced. Tracking epic: #488.