mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
feat(alembic): B2 drop unused pm_approvals Task column
Smoke run analysis initially flagged three Task fields as unused (pm_approvals, quick_context, proactive_context). A follow-up audit found quick_context (stores original_developer marker + doc notes + PR creator + escalation notes) and proactive_context (RAG injection) are actively used. Only pm_approvals is truly orphaned. Migration 014 drops pm_approvals; downgrade() recreates it if ever needed. The two false-positive fields stay untouched. Spec ref: docs/superpowers/specs/2026-05-12-post-smoke-3-fixes-design.md section B2 (re-scoped 2026-05-12).
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
"""Drop unused Task column pm_approvals.
|
||||
|
||||
Smoke run analysis (2026-05-12) initially flagged three Task fields
|
||||
as unused: pm_approvals, quick_context, proactive_context. A follow-up
|
||||
audit found quick_context and proactive_context are actively written
|
||||
(original_developer marker, doc_notes, PR creator tags; RAG context
|
||||
injection respectively). Only pm_approvals is truly orphaned — zero
|
||||
writers, only model + schema declarations as readers.
|
||||
|
||||
Revision ID: 014_drop_pm_approvals
|
||||
Revises: 013_drop_role_enum
|
||||
Create Date: 2026-05-12
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
revision = "014_drop_pm_approvals"
|
||||
down_revision = "013_drop_role_enum"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.drop_column("tasks", "pm_approvals")
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.add_column(
|
||||
"tasks",
|
||||
sa.Column("pm_approvals", sa.JSON, nullable=False, server_default="{}"),
|
||||
)
|
||||
@@ -269,9 +269,6 @@ class TaskResponse(BaseModel):
|
||||
docs_complete: bool = False # Documenter has finished
|
||||
pr_created: bool = False # Developer has created PR
|
||||
|
||||
# PM Approval Tracking (for AWAITING_PM_REVIEW phase)
|
||||
pm_approvals: dict[str, bool] = {} # e.g. {'main_pm': True, 'cell_pm': True}
|
||||
|
||||
# Ownership
|
||||
team: Team
|
||||
created_by: UUID
|
||||
@@ -622,7 +619,6 @@ def task_to_response(task: "TaskTable") -> TaskResponse:
|
||||
),
|
||||
docs_complete=task.docs_complete,
|
||||
pr_created=task.pr_created,
|
||||
pm_approvals=task.pm_approvals or {},
|
||||
team=task.team,
|
||||
created_by=require_uuid(task.created_by),
|
||||
assigned_to=to_python_uuid(task.assigned_to),
|
||||
|
||||
@@ -196,9 +196,6 @@ class TaskTable(Base):
|
||||
docs_complete: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||||
pr_created: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||||
|
||||
# PM Approval Tracking (for AWAITING_PM_REVIEW phase)
|
||||
pm_approvals: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict)
|
||||
|
||||
# Ownership
|
||||
created_by: Mapped[UUID] = mapped_column(
|
||||
UUID(as_uuid=True), ForeignKey("agents.id"), nullable=False
|
||||
|
||||
@@ -190,12 +190,6 @@ class Task(TimestampMixin):
|
||||
docs_complete: bool = Field(default=False, description="Documenter has finished")
|
||||
pr_created: bool = Field(default=False, description="Developer has created PR")
|
||||
|
||||
# PM Approval Tracking (for AWAITING_PM_REVIEW phase)
|
||||
pm_approvals: dict[str, bool] = Field(
|
||||
default_factory=dict,
|
||||
description="PM approvals: {'main_pm': True, 'cell_pm': True}",
|
||||
)
|
||||
|
||||
# Ownership
|
||||
created_by: UUID = Field(..., description="Agent who created the task")
|
||||
assigned_to: UUID | None = Field(
|
||||
@@ -370,7 +364,6 @@ class TaskUpdate(RobocoBase):
|
||||
pr_url: str | None = None
|
||||
docs_complete: bool | None = None
|
||||
pr_created: bool | None = None
|
||||
pm_approvals: dict[str, bool] | None = None
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
||||
@@ -346,7 +346,6 @@ async def smoke_test_batch(db_session: AsyncSession) -> AsyncIterator[list[UUID]
|
||||
pr_url="https://github.com/example/smoke/pull/1",
|
||||
docs_complete=True,
|
||||
pr_created=True,
|
||||
pm_approvals={"cell_pm": str(pm_agent.id)},
|
||||
created_by=system_agent.id,
|
||||
assigned_to=dev_agent.id,
|
||||
team=Team.BACKEND,
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
"""Wave B2 (2026-05-12, re-scoped): migration 014 drops pm_approvals.
|
||||
|
||||
Original spec proposed dropping three Task columns; investigation found
|
||||
quick_context and proactive_context are actively used (original_developer
|
||||
tracking, RAG context). Only pm_approvals is truly orphaned.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import text
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pm_approvals_dropped(db_session) -> None: # type: ignore[no-untyped-def]
|
||||
"""pm_approvals column is gone from the tasks table."""
|
||||
result = await db_session.execute(
|
||||
text(
|
||||
"SELECT column_name FROM information_schema.columns "
|
||||
"WHERE table_name = 'tasks' AND column_name = 'pm_approvals'"
|
||||
)
|
||||
)
|
||||
rows = list(result)
|
||||
assert rows == [], "pm_approvals column should have been dropped"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_quick_context_and_proactive_context_remain(db_session) -> None: # type: ignore[no-untyped-def]
|
||||
"""quick_context and proactive_context MUST remain — they're actively used."""
|
||||
result = await db_session.execute(
|
||||
text(
|
||||
"SELECT column_name FROM information_schema.columns "
|
||||
"WHERE table_name = 'tasks' "
|
||||
"AND column_name IN ('quick_context', 'proactive_context')"
|
||||
)
|
||||
)
|
||||
rows = {r[0] for r in result}
|
||||
assert "quick_context" in rows, (
|
||||
"quick_context must remain (original_developer + audit)"
|
||||
)
|
||||
assert "proactive_context" in rows, "proactive_context must remain (RAG injection)"
|
||||
@@ -276,7 +276,6 @@ def _stub_task(*, with_project: bool = False) -> SimpleNamespace:
|
||||
project=(SimpleNamespace(slug="proj-1") if with_project else None),
|
||||
docs_complete=False,
|
||||
pr_created=False,
|
||||
pm_approvals={},
|
||||
team=Team.BACKEND,
|
||||
created_by=uuid4(),
|
||||
assigned_to=None,
|
||||
|
||||
@@ -259,7 +259,6 @@ async def test_submit_for_qa_writes_audit_with_dev_agent_id(
|
||||
pr_url="https://github.com/example/audit-test/pull/99",
|
||||
docs_complete=False,
|
||||
pr_created=True,
|
||||
pm_approvals={},
|
||||
created_by=system_uuid,
|
||||
assigned_to=dev_uuid,
|
||||
claimed_by=dev_uuid,
|
||||
|
||||
Reference in New Issue
Block a user