Skip to content

engine: B1 element-level dependency resolution diverges the two cycle-gate paths (production db.rs vs test-harness model.rs:442) -- reconcile or remove System B post-C-LEARN #569

Description

@bpowers

Summary

simlin-engine has two independent dependency / cycle-gate code paths, and the B1 element-level-dependency-resolution fix (the C-LEARN hero-model effort on branch clearn-hero-model) is being deliberately scoped to only one of them, per reviewer sign-off. This will make the two paths diverge in what models they accept/reject for the element-level-recurrence acceptance class. This divergence is being explicitly deferred (it is not a C-LEARN blocker), and this issue is the tracking item the reviewer required as a condition of accepting the System-A-only scope.

The two paths

  • System A (production): compile_project_incremental (src/simlin-engine/src/db.rs:5954) -> assemble_module (db.rs:4983) -> model_dependency_graph (db.rs:5547, invoked at db.rs:~5004-5006). The whole-variable cycle / transitive-closure computation lives in model_dependency_graph_impl (db.rs:1134, see the cycle/transitive logic around db.rs:~1316). The has_cycle -> "model '...' has circular dependencies" gate is at db.rs:~5009-5016, surfaced as NotSimulatable at db.rs:~5966/5970. This is the path real compilation and simulation use (the salsa-tracked incremental path).

  • System B (test-harness path): the all_deps_inner recursion in src/simlin-engine/src/model.rs, with the CircularDependency gate at src/simlin-engine/src/model.rs:442. This path is reachable via some test utilities and is not the production salsa path.

These two paths independently compute dependency closures and independently decide whether a model has a cycle.

What B1 changes and why they will diverge

The B1 fix introduces element-level dependency resolution: a whole-variable SCC that is actually acyclic once dependencies are expanded per-element / per-subrange is no longer rejected as a cycle. B1 is being applied to System A only.

System B will remain on the old whole-variable-only behavior. Consequently, for the element-level-recurrence acceptance class, the two gates will disagree:

  • a model that compiles/simulates fine via System A (production) may still be rejected by System B (and, symmetrically, the inverse can occur), even though both are nominally answering the same question ("does this model have a dependency cycle?").

This is a latent correctness/consistency hazard: test utilities going through System B can accept or reject models differently from real compilation, which can mask or fabricate failures and erode trust in the test harness as a proxy for production behavior.

Why it matters

  • Correctness/consistency: two answers to "is this model simulatable?" for the same model is a trap. Tests that exercise System B no longer reliably predict production (System A) behavior for the element-recurrence class.
  • Maintainability: two parallel dependency-graph/cycle implementations must be kept mentally in sync with no enforcement; B1 widens the gap rather than narrowing it.
  • Developer experience: future contributors touching cycle detection must know which of the two paths they are affecting and that they have drifted apart.

Components affected

  • src/simlin-engine/src/db.rs -- System A: compile_project_incremental (~5954), assemble_module (~4983), model_dependency_graph (~5547) / model_dependency_graph_impl (~1134, cycle logic ~1316), cycle gate ~5009-5016, NotSimulatable ~5966/5970
  • src/simlin-engine/src/model.rs -- System B: all_deps_inner recursion, CircularDependency gate at line 442
  • The test utilities that route through the System B path

Possible approaches for resolution (post-C-LEARN)

  1. Reconcile System B with System A: apply the same element-level dependency resolution to the System B path so both gates accept/reject identically, OR
  2. Remove System B if redundant: if the System-B path exists only as a test-harness convenience that duplicates logic the production salsa path already provides, delete it and route those test utilities through System A (the production model_dependency_graph) so there is a single source of truth.

Either way the end state should be one dependency/cycle-gate implementation (or two provably-equivalent ones), not two that silently diverge.

Scope / priority

  • Deferred / post-C-LEARN tech debt. This is explicitly NOT a C-LEARN blocker.
  • The reviewer accepted the System-A-only scope for the C-LEARN B1 effort on the condition that this divergence be tracked separately; this issue fulfills that condition.

Discovery context

Identified during the C-LEARN hero-model work while designing the B1 element-level-dependency-resolution fix (whole-variable SCCs that are acyclic under per-element/subrange expansion), on branch clearn-hero-model. The System-A-only scope was accepted by the reviewer with this tracking item as a precondition.

Relationship to existing issues (all DISTINCT, not duplicates)

Activity

  1. bpowers commented on May 16, 2026

    @bpowers
    OwnerAuthor

    Duplicate of #568. Both were filed in parallel during the C-LEARN B1 effort for the same System-A (production salsa) vs System-B (model.rs:442 test-harness) cycle-gate divergence. #568 is the canonical tracking item cited in docs/clearn-investigation/B1-design.md O1 / reviewer-priors.md §13.3. Consolidating on #568.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions