Skip to content

git_state: no rule asserts that a ref shares a merge base with the default branch (proposed GS009) #868

Description

@arena-ai-coding-agent

Summary

lib/rules/git_state.ex runs GS001–GS008. None of them detects the invariant that failed on metadatastician/ziz on 2026-09-28: a ref with no merge base against the default branch.

Measured instance — arena/01a0d3a4-rsr-template-repo @ 121ebaeeb9b2543c119babae3fdc086bfd99f5e8:

git log -1 --format=%P   # (empty) -> root commit, no parent
gh api repos/metadatastician/ziz/compare/main...arena/01a0d3a4-rsr-template-repo
# -> HTTP 404 "No common ancestor between main and arena/01a0d3a4-rsr-template-repo."
  • The shared compare URL 404s, so the change could not be reviewed at all.
  • It could not be merged without --allow-unrelated-histories, which would have imported 478 files already present and reverted a dependabot bump.
  • 478 of its 479 files were byte-identical to main's. It was a session initialisation commit, not work.
  • No PR existed, and none could have: there is nothing to diff against.

Why the existing rules miss it

rule why it does not fire
GS003 branch divergence Compares the current branch against its own upstream — never the default branch — and requires ahead > 0 and behind > 0. On unrelated histories git rev-list --left-right --count HEAD...@{u} returns two arbitrary totals, so the one case where "diverged" is factually wrong is the one case the rule cannot name.
GS007 stale remote branches Advisory, and flags any non-main ref with equal weight. It renders a 1-commit abandoned orphan and a 100-commit branch with an open PR identically. Measured estate-wide: MetaManifold-WebUI had 4 branches that were content-identical to main (compare → files: 0) sitting alongside a branch backing an open PR. GS007 called all five the same thing.

Proposed rule

GS009 — a ref has no merge base with the default branch.

# empty output == no common ancestor
git merge-base origin/main <ref>

Severity: high where the ref also has no PR; advisory where a PR exists (an open PR on an unrelated branch is a workflow problem, not a defect in the change).

Note the test must be merge base, not ancestry. Squash-merging is the estate default, so a fully merged side branch is routinely not an ancestor of main once the squashed commit replaces it. git merge-base --is-ancestor would fire on every squash-merged branch; git merge-base returning empty fires on none of them and exactly one of the orphans.

Suggested refinement to GS007

Classify by PR state before reporting, so the cleanup instruction is actionable:

PR state content vs default disposition
merged identical prune — safe to delete
merged differs investigate
open — leave — live work
none — unmerged work — needs a decision
none — and no merge base → escalate (this class)

Acceptance criteria

AC1 — GS009 exists, fires on a synthetic unrelated-history branch, and does not fire on a squash-merged branch.

AC2 — GS007 separates "merged and content-identical → prunable" from "orphaned → escalate".

AC3 — No muting. Specifically: no exemption keyed on a branch-name prefix. A rule that ignored refs starting arena/ would have hidden this one entirely, and the estate's own arena/* refs are the observed instance of the class.

AC4 — The rule reports the measured fact (empty merge base), not an interpretation ("diverged"), so the finding stays true when the history shape is unexpected.

Provenance

Found while triaging an orphan branch on metadatastician/ziz. The branch was deleted and its (correct) diff re-landed with real history in metadatastician/ziz#2. Estate-wide footprint: 8 arena/* refs across 420 repos — 5 merged-and-identical (prunable), 3 backing open PRs.

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions