Skip to content

Faithfulness predicate: candidate trees can silently omit PR content #470

Description

@phall1

Reproduced by hand against lib/git_engine.ml's exact invocation, git 2.55.0.

Nothing in the design or the code asserts any relationship between the candidate tree and the PR diffs it claims to contain. The only guard is git merge-base --is-ancestor <recorded_base> <pr_head> (git_engine.ml:70-84).

Given a recorded merge base that is a proper ancestor of the PR head but newer than the true fork point:

  • the ancestry guard passes
  • merge-tree --write-tree exits 0
  • the candidate tree is missing one of the PR's two files
  • the commit is non-empty, so an empty-commit post-condition does not catch it

Invariant 1 ("the exact validated tree became main") remains technically true and completely uninformative: it constrains which tree landed, never what is in it.

Honest scope: on the happy path the merge base is computed as merge-base(head, target tip), which would not produce this. The finding is "nothing would catch a wrong base," not "this happens today." The realistic injection point is M1's planned metadata adapters for tools with synthetic bases (ghstack), which supply the base from tool metadata rather than computing it.

The fix — state and implement the predicate
For each PR i, every path in diff(merge_base_i -> head_i) must appear in diff(parent_i -> synthetic_i) or be identically present on the left side. A tree walk over changed paths only, run after construction and before requesting validation.

Adjacent post-conditions to add in the same place

  • Call git merge-base --all; refuse to build (or drop --merge-base) when it returns more than one OID — criss-cross merges currently pick one silently
  • Pass --attr-source explicitly; decide which tree's .gitattributes governs rather than silently falling back to naive text merge
  • Reject trees with case-folding or NFC/NFD path collisions
  • Drop --no-messages and capture the conflicted-file stage list

See docs/INVESTIGATION.md §6 Q3, §7 R1, §10.

Activity

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions