Skip to content

[Bug]: resolve_commit_state returns stale or deleted elements when a merge reaches a checkpoint #409

Open

Description

@antoineatstariongroup

What type of issue is this?

  • Bug report
  • Feature request

Prerequisites

  • I have written a descriptive issue title
  • I have verified that I am running the latest version of the SysML2.NET
  • I have searched open and closed issues to ensure it has not already been reported

Description

sysml2.resolve_commit_state and sysml2.resolve_element_at_commit (SysML2.NET.CodeGenerator/Templates/Uml/core-sql-schema.hbs, schema.generated.sql:1455-1591) take every row of every checkpoint the history walk reaches. They fall back to a checkpoint row only when the walk found no version of the element.

Defect, with merges that conform to §7.1.2. When the walk reaches two checkpoints, an element unchanged since before both is returned once per checkpoint. A self-join on checkpoint_state multiplies that again. Such an element is not a merge conflict, so the merge never restates it. The cadence policy in the §9 banner ("always at branch-fork bases") makes reaching two checkpoints the normal case for any merge.

Hardening, with merges that break §7.1.2. Systems Modeling API §7.1.2 requires a merge to restate every identity whose version differs between its parents, including one present in a single parent. If a merge omits that, the walk can reach an ancestor older than a checkpoint, and its version overrides the checkpoint row. The merge then resolves an element to an older version, or brings back an element deleted before the checkpoint. The schema does not enforce the restatement rule, so the resolver should still give a deterministic answer that matches the full fold.

Expected: resolving a commit gives the same result with or without checkpoints, and returns each identity at most once.

Fix:

  • Store tombstones in commit_checkpoint, so a checkpoint is a complete record of that commit's state.
  • Rank checkpoint rows and walked versions together, each by the created of the commit that wrote the version, and keep the newest per identity.
  • Apply the same change to resolve_element_at_commit and build_commit_checkpoint.
  • Add the conforming scenario below to SysML2.NET.CodeGenerator.Tests/Sql/schema.smoke.sql.

Steps to Reproduce

Commits R → Q → X → Y and R → Z, merged into M (parents Y, Z), each strictly newer than its parents. Element f: version f1 at R, f2 at Q. Element g: version g1 at R, tombstone at Q. Element h: version h1 at R, never changed.

Conforming merge (defect). M's change set restates the conflicts: f2 for f and a tombstone for g.

  1. SELECT sysml2.build_commit_checkpoint(p, X); and SELECT sysml2.build_commit_checkpoint(p, Z);
  2. SELECT identity_id, count(*) FROM sysml2.resolve_commit_state(p, M) GROUP BY 1; returns h 4 times.

Non-conforming merge (hardening). M restates nothing.

  1. Without any checkpoint, resolve_commit_state(p, M) returns f2, h1.
  2. After build_commit_checkpoint(p, X), it returns f1, g1, h1.

A prototype of the fix returns each identity once, matches the no-checkpoint result in both cases, and keeps schema.smoke.sql at 59/59 PASS.

System Configuration

  • SysML2.NET version: PR [ADD] Sql schema #344 (feat/sql-schema-and-more, d5a90f2), SysML2.NET.CodeGenerator
  • Environment (Operating system, version and so on): Windows 11, PostgreSQL 17 (Docker)
  • .NET Framework version: .NET 10
  • Additional information: none
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

    CodeGenerationa Code Generation taskbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions