Skip to content

ltm: sub-model pathway/composite scores through an unscoreable (loud-skipped) or agg-routed edge silently multiply to 0 #768

@bpowers

Description

@bpowers

Summary

Sub-model PATHWAY scores ($⁚ltm⁚path⁚{port}⁚{idx}) and COMPOSITE scores ($⁚ltm⁚composite⁚{port}) silently multiply through a 0-stub whenever a pathway hop's link score is not emitted under the name the pathway product references. Two flavors of the same silent-stub mechanism are known:

Flavor 1: loud-skipped (unscoreable) edges

The #758 fix made dim-incompatible conservative link scores skip loudly: one Warning naming the edge, no link-score variable emitted, and enumerated/pinned LOOP scores through the edge are dropped via an unscoreable_edges set (src/simlin-engine/src/db/ltm/mod.rs, built at ~line 1300, consumed by traverses_unscoreable at ~1426 for detected loops at ~1444-1449 and pinned loops at ~1703, at commit 5c9c2d41 on branch ltm-fix-batch-2).

But pathway and composite scores whose chains multiply through such an edge are NOT dropped. The pathway product references the never-emitted link-score variable; the fragment compiler's scalar stub-dep for the missing name makes the product silently evaluate to 0 (the pre-existing #752/#683-family stub-dep behavior). The pathway/composite variables still emit, compile cleanly, and read 0 with no signal of their own.

Flavor 2: agg-routed edges resolve to an absent Bare name

The pathway emitter resolves each hop's link-score reference via resolve_link_score_name_for_loop (consumed at src/simlin-engine/src/db/ltm/mod.rs ~line 1984 at commit ff2d50d0 on branch ltm-shape-phase1). When neither the Bare nor a FixedIndex name was emitted, that resolver's documented fallback is to return the Bare canonical name anyway "and let the fragment compiler's stub-dep fallback fire".

An agg-routed edge -- one the reference-site IR routed ThroughAgg, e.g. a hop whose target reads the source through a reducer like out[R] = 1 + SUM(pop[R,*]) -- has no Bare-named link score at all. Its score is carried by the two agg-half names ({from}→$⁚ltm⁚agg⁚{n} and $⁚ltm⁚agg⁚{n}→{to}). So when such an edge appears as a hop inside a sub-model pathway, the resolver falls back to the absent Bare name and the pathway product silently multiplies through the 0-stub -- exactly the flavor-1 failure mode, with no Warning at all (the edge is scoreable; only the pathway-hop name resolution misses it).

This is pre-existing for every agg-routed edge: the comment block above the pathway emission (mod.rs ~lines 1952-1961 at ff2d50d0) documents this family -- pathway hops are resolved against already-emitted names precisely because "an input-port model with an edge like share[r] = SUM(x[*]) would reference the never-emitted Bare canonical name ... and the fragment compiler's stub-dep fallback would silently drop that pathway's contribution to the composite score" -- but the resolver only covers Bare/FixedIndex candidates, not the agg-half chain.

T6 note: the shape-expressiveness phase's retirement of the discovery-mode duplicate Bare score (commits cbb26d37/ff2d50d0, branch ltm-shape-phase1) moved the ALIASED ThroughAgg-PerElement family from "accidentally resolved via a double-counting duplicate Bare score" into this same pre-existing gap. That is the correct direction -- the duplicate was wrong and double-counted -- but the gap now covers that family too.

Why it matters

  • For flavor 1, the edge's single model-level Warning exists, so the degradation is no longer fully silent -- but nothing ties that warning to the pathway/composite variables, which look like legitimate computed scores reading 0. For flavor 2 there is no warning at all: the edge has a perfectly good agg-half score chain; only the pathway hop's name resolution misses it.
  • Module composite selection takes the max-abs across pathways: a genuinely-strong pathway that traverses the skipped or agg-routed edge contributes 0, so composite selection can silently prefer a wrong pathway, mis-scoring every parent-level loop that routes through the module via its composite.
  • Inconsistent contract: loop scores through a loud-skipped edge are dropped (correct, visible), and loop scores through an agg-routed edge correctly traverse the synthetic $⁚ltm⁚agg⁚{n} node -- but pathway/composite scores through the same edges are kept as silent zeros. The ltm: declined element-mapped sliced reducer emits a non-compiling scalar link score on the conservative path (loop scores stub to 0) #758 fix's "drop, don't zero" principle and the agg-routing machinery both stop at the module boundary.

Affected models

Severity low-medium overall, but the failure mode is the bad kind -- plausible-looking nonzero-adjacent output with a wrong winner.

Components affected

  • src/simlin-engine/src/db/ltm/mod.rs -- pathway var emission ($⁚ltm⁚path⁚{port}⁚{idx}, the enumerate_pathways_to_outputs consumers ~line 419-471, 1057) and composite emission; the per-hop resolve_link_score_name_for_loop call at ~1984 and the family-documenting comment at ~1952-1961 (at ff2d50d0); the unscoreable_edges set already exists here but is only threaded to loop-score consumers
  • src/simlin-engine/src/ltm_augment.rs -- resolve_link_score_name_for_loop (~line 3785 at ff2d50d0), whose Bare/FixedIndex candidate set has no agg-half awareness
  • src/simlin-engine/src/db.rs -- enumerate_pathways_to_outputs_with_truncation call site (~line 867) and the module composite/link helpers (~534-588)

Fix direction

Thread unscoreable/agg-routed awareness into pathway/composite emission so both flavors are handled:

  • Loud-skipped edges: a pathway whose chain includes an unscoreable edge should not emit (or should emit with its own Warning naming the pathway and the offending edge), so it cannot participate in max-abs composite selection; if all pathways for a port are dropped, the composite itself should be skipped loudly (which then routes parent-level consumers through the existing absent-composite guard from commit 193740cd / ltm: a generated reference to an absent cross-module LTM variable compiles cleanly and reads a silent constant 0 #683's territory).
  • Agg-routed edges: the hop is scoreable, so the fix is resolution, not dropping -- the pathway hop should resolve to the agg-half chain score(from→$⁚ltm⁚agg⁚{n}) * score($⁚ltm⁚agg⁚{n}→to) (mirroring how loop scores traverse the synthetic agg node) instead of falling back to the absent Bare name. This needs the pathway emitter to know which hops were agg-routed and which $⁚ltm⁚agg⁚{n} node carries each.

Note the sub-model's unscoreable_edges (and its agg-routing decisions) are computed during the sub-model's own LTM-variable pass; the pathway/composite emission needs access to that per-submodel information (or an equivalent re-derivation) at the point pathways are enumerated.

Tracking / related

Part of LTM tracking epic #488, module umbrella #274. Related but distinct:

Discovery context

Flavor 1 reported as a residual by the implementor during the GH #758 fix on branch ltm-fix-batch-2 (commit 5c9c2d41), 2026-06. Flavor 2 identified during T6 confirmation review of the LTM shape-expressiveness phase on branch ltm-shape-phase1 (commits cbb26d37/ff2d50d0), 2026-06.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ltmLoops that Matter (LTM) analysis subsystem

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions