"""TDD — musehub_mcp_executor must not access commit_meta (dropped in migration 0020).""" from __future__ import annotations import pytest from muse.core.types import blob_id from datetime import datetime, timezone from sqlalchemy.ext.asyncio import AsyncSession from musehub.db.musehub_repo_models import MusehubBranch, MusehubCommit from musehub.db.musehub_social_models import MusehubProposal from tests.factories import create_repo def _utc() -> datetime: return datetime.now(tz=timezone.utc) async def _add_commit(session: AsyncSession, repo_id: str, seed: str, **kwargs) -> MusehubCommit: row = MusehubCommit( commit_id=blob_id(seed.encode()), repo_id=repo_id, branch="feat/mcp", parent_ids=[], message=f"feat: {seed}", author="gabriel", timestamp=_utc(), **kwargs, ) session.add(row) session.add(MusehubBranch( branch_id=blob_id(f"br-{seed}".encode()), repo_id=repo_id, name="feat/mcp", head_commit_id=row.commit_id, )) await session.commit() return row async def _add_proposal(session: AsyncSession, repo_id: str, seed: str) -> MusehubProposal: from musehub.core.genesis import compute_proposal_id proposal_id = blob_id(f"proposal-{seed}".encode()) row = MusehubProposal( proposal_id=proposal_id, proposal_number=1, repo_id=repo_id, title=f"proposal {seed}", body="", state="open", from_branch="feat/mcp", to_branch="dev", author="gabriel", created_at=_utc(), ) session.add(row) await session.commit() return row # --------------------------------------------------------------------------- # MCP1 — _extract_proposal_symbol_data does not crash on commit_meta # --------------------------------------------------------------------------- @pytest.mark.asyncio async def test_mcp1_extract_proposal_symbol_data_no_commit_meta( db_session: AsyncSession, ) -> None: """_extract_proposal_symbol_data must not raise AttributeError on commit_meta.""" from musehub.services.musehub_mcp_executor import _extract_proposal_symbol_data repo = await create_repo(db_session, owner="gabriel", visibility="public") await _add_commit( db_session, repo.repo_id, "mcp1-c1", agent_id="claude-code", model_id="claude-sonnet-4-6", signature="ed25519:abc", ) proposal = await _add_proposal(db_session, repo.repo_id, "mcp1") # Must not raise — returns None or a tuple result = await _extract_proposal_symbol_data(db_session, repo.repo_id, proposal.proposal_id) # None is acceptable (no commits on from_branch linked to proposal yet) assert result is None or isinstance(result, tuple)