teleo-infrastructure/tests/test_merge.py
m3taversal 686ef3fd7f Replace rebase-retry with cherry-pick merge mechanism
- _cherry_pick_onto_main replaces _rebase_and_push: creates fresh branch
  from origin/main, cherry-picks extraction commits, force-pushes
- Eliminates ~23% merge failure rate from rebase race conditions
- Agent branch protection: PIPELINE_OWNED_PREFIXES filter in SQL prevents
  auto-merge of agent-owned branches (theseus/*, rio/*, etc.)
- Empty-commit handling: skips already-merged content gracefully
- Entity conflict auto-resolution preserved for cherry-pick path
- Post-pick evidence dedup runs as safety net (same as post-rebase)
- Separate fetch calls for main and branch (fixes long branch name issue)

Fixes: PRs #2141, #157, #2142, #2180 (agent branch orphaning)
Fixes: ~23% merge failure rate (rebase race condition)
Related: PRs #1751, #1752 (enrichment dedup shares root cause)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:18:26 +01:00

104 lines
3.4 KiB
Python

"""Tests for merge stage — pipeline ownership gate.
Note: cherry-pick mechanism tested on VPS (requires git repos + aiohttp).
These tests verify the ownership filter logic and SQL query behavior.
"""
import asyncio
import sqlite3
import unittest.mock as mock
import pytest
# Can't import lib.merge directly (aiohttp not installed locally).
# Test the ownership prefixes and SQL logic directly.
PIPELINE_OWNED_PREFIXES = ("extract/", "ingestion/", "epimetheus/", "reweave/", "fix/")
class TestPipelineOwnedPrefixes:
"""Verify the pipeline ownership gate correctly filters branches."""
def test_extraction_branches_are_pipeline_owned(self):
branches = [
"extract/2026-03-31-some-source",
"ingestion/2026-03-31-batch",
"epimetheus/merge-gate",
"reweave/2026-03-31",
"fix/dedup-evidence",
]
for branch in branches:
assert any(
branch.startswith(pfx) for pfx in PIPELINE_OWNED_PREFIXES
), f"{branch} should be pipeline-owned"
def test_agent_branches_are_not_pipeline_owned(self):
branches = [
"theseus/research-ai-alignment",
"rio/market-analysis",
"astra/space-claims",
"vida/health-extraction",
"clay/entertainment-review",
"leo/entity-update",
]
for branch in branches:
assert not any(
branch.startswith(pfx) for pfx in PIPELINE_OWNED_PREFIXES
), f"{branch} should NOT be pipeline-owned"
def test_bare_prefix_without_slash_is_not_owned(self):
"""Prefixes must include slash to prevent partial matches."""
assert not any(
"extraction-test".startswith(pfx) for pfx in PIPELINE_OWNED_PREFIXES
)
class TestOwnershipSqlFilter:
"""Test the SQL LIKE-based filtering that _claim_next_pr uses."""
def test_sql_like_filter_matches_pipeline_branches(self):
conn = sqlite3.connect(":memory:")
conn.execute("CREATE TABLE branches (name TEXT)")
branches = [
"extract/2026-03-31-test",
"theseus/research",
"reweave/2026-03-31",
"rio/market",
"fix/dedup",
"astra/space",
"ingestion/batch-1",
]
for b in branches:
conn.execute("INSERT INTO branches VALUES (?)", (b,))
prefix_clauses = " OR ".join(
f"name LIKE '{pfx}%'" for pfx in PIPELINE_OWNED_PREFIXES
)
rows = conn.execute(
f"SELECT name FROM branches WHERE {prefix_clauses}"
).fetchall()
matched = {r[0] for r in rows}
assert matched == {
"extract/2026-03-31-test",
"reweave/2026-03-31",
"fix/dedup",
"ingestion/batch-1",
}
# Agent branches must NOT match
assert "theseus/research" not in matched
assert "rio/market" not in matched
assert "astra/space" not in matched
def test_empty_table_returns_nothing(self):
conn = sqlite3.connect(":memory:")
conn.execute("CREATE TABLE branches (name TEXT)")
prefix_clauses = " OR ".join(
f"name LIKE '{pfx}%'" for pfx in PIPELINE_OWNED_PREFIXES
)
rows = conn.execute(
f"SELECT name FROM branches WHERE {prefix_clauses}"
).fetchall()
assert rows == []