From ed5f7ef6cc724c10f4f48a598921243c86564f66 Mon Sep 17 00:00:00 2001 From: m3taversal Date: Tue, 28 Apr 2026 16:19:08 +0100 Subject: [PATCH] fix(merge): correct audit-ref comment + add sentinel-drift warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two nits from Ganymede line-level review of 7741c1e: 1. Comment at lines 562-565 said --force-with-lease but code is plain --force. Comment now describes the actual behavior: bot-owned per-PR audit ref, intentional overwrite on stale refs from prior aborted attempts, no concurrent writer to lease against. 2. Sentinel-regex extraction in _merge_domain_queue dispatch had no graceful-failure log. If the _merge_no_ff_external success-message contract drifts and any of the three regexes (M, audit_ref, external PR #) miss, dispatch silently builds a comment with None values and writes audit_log JSON with null fields. Added a warning log when any regex misses — signal-only, doesn't gate the close path since the merge already succeeded. Branch: epimetheus/external-merge-flow-bug1 Parent: 7741c1e (Ship Msg 3 architecture review close) Diff: +11/-3, single file lib/merge.py Ganymede: 3-message protocol Msg 3 (nits applied, ball returned). Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/merge.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/merge.py b/lib/merge.py index d2eeb32..b9ff910 100644 --- a/lib/merge.py +++ b/lib/merge.py @@ -560,9 +560,9 @@ async def _merge_no_ff_external(branch: str) -> tuple[bool, str]: merge_sha = merge_sha.strip().split("\n")[0] # Push to synthetic audit ref _merged/{branch} (does not touch contributor's - # gh-pr-N/* branch). Force-with-lease against expected nothing — the audit - # ref is per-PR and shouldn't pre-exist on a fresh merge. If it does (rare: - # a prior failed attempt), force-push is fine since the ref is bot-owned. + # gh-pr-N/* branch). Plain --force: the audit ref is bot-owned and per-PR; + # if a prior aborted attempt left a stale ref, overwriting it is the + # intended behavior, and there's no concurrent writer to lease against. rc, out = await _git( "push", "--force", "origin", f"HEAD:refs/heads/{audit_ref}", cwd=worktree_path, timeout=30, @@ -969,6 +969,14 @@ async def _merge_domain_queue(conn, domain: str) -> tuple[int, int]: audit_ref = m_ref.group(1) if m_ref else None m_pr = re.search(r"external PR #(\d+)", pick_msg) gh_pr_num = m_pr.group(1) if m_pr else None + # Surface drift between dispatch and _merge_no_ff_external if the + # success-message contract changes. Merge already succeeded; this + # is signal-only, not a gate on the close path. + if not (m and m_ref and m_pr): + logger.warning( + "PR #%d sentinel parse incomplete: M=%s, audit_ref=%s, gh_pr=%s, msg=%r", + pr_num, bool(m), bool(m_ref), bool(m_pr), pick_msg, + ) leo_token = get_agent_token("leo") comment_body = (