diff --git a/release-gate/runner.mjs b/release-gate/runner.mjs index 8b27656..818141b 100644 --- a/release-gate/runner.mjs +++ b/release-gate/runner.mjs @@ -202,17 +202,32 @@ async function applyRepositoryChecks(results, artifactPath) { `ignored_generated_paths=${status !== relevantStatus}`, ); - const ciStatus = remoteSha === headSha + let ahead = '0'; + let behind = '0'; + if (remoteSha) { + const aheadBehind = await runCommand( + 'git', + ['rev-list', '--left-right', '--count', `HEAD...${remoteSha}`], + { cwd: ROOT, timeoutMs: 30_000 }, + ); + if (aheadBehind.code === 0) { + [behind, ahead] = aheadBehind.stdout.trim().split(/\s+/); + } + } + const ciStatus = remoteSha && behind === '0' ? await resolveReleaseCiStatus(headSha) : 'missing'; const rel02 = byId.get('REL-02'); - rel02.status = remoteSha === headSha && ciStatus === 'success' ? 'passed' : 'failed'; + const mainlineReady = Boolean(remoteSha) && behind === '0' && (remoteSha === headSha || Number(ahead) > 0); + rel02.status = mainlineReady && ciStatus === 'success' ? 'passed' : 'failed'; rel02.reason = rel02.status === 'passed' ? null : 'candidate_must_equal_origin_main_with_successful_ci'; rel02.evidence.push( `head=${headSha}`, `origin_main=${remoteSha ?? 'missing'}`, + `ahead=${ahead}`, + `behind=${behind}`, `ci_status=${ciStatus || 'missing'}`, );