"""seed turn runtime prompt releases Revision ID: 20260511_seed_turn_runtime_prompt_releases Revises: 20260507_add_qa_context_workspaces Create Date: 2026-05-11 """ from __future__ import annotations import os from alembic import op import sqlalchemy as sa revision = "20260511_seed_turn_runtime_prompt_releases" down_revision = "20260507_add_qa_context_workspaces" branch_labels = None depends_on = None PROMPT_KEYS = ( "PROMPT_PMFLOW_AI_TURN_GOAL_STATE_ASSESSOR", "PROMPT_PMFLOW_AI_TURN_STATE_ANSWER_SYNTHESIZER", ) SEED_NOTES = "Seeded by 20260511_seed_turn_runtime_prompt_releases" def _table_exists(bind, table_name: str) -> bool: return sa.inspect(bind).has_table(table_name) def _prompt_body(prompt_key: str) -> str: from app.config import ai_prompts return str(getattr(ai_prompts, prompt_key, "") or "").strip() def _seed_active_release(bind, *, tenant_id: int, prompt_key: str, body_snapshot: str) -> None: active = bind.execute( sa.text( """ SELECT id FROM prompt_releases WHERE tenant_id = :tenant_id AND prompt_key = :prompt_key AND status = 'active' LIMIT 1 """ ), {"tenant_id": tenant_id, "prompt_key": prompt_key}, ).first() if active is not None: return max_version = bind.execute( sa.text( """ SELECT MAX(version) FROM prompt_releases WHERE tenant_id = :tenant_id AND prompt_key = :prompt_key """ ), {"tenant_id": tenant_id, "prompt_key": prompt_key}, ).scalar() bind.execute( sa.text( """ INSERT INTO prompt_releases (tenant_id, prompt_key, version, body_snapshot, status, notes, created_by, activated_by, activated_at) VALUES (:tenant_id, :prompt_key, :version, :body_snapshot, 'active', :notes, NULL, NULL, :activated_at) """ ), { "tenant_id": tenant_id, "prompt_key": prompt_key, "version": int(max_version or 0) + 1, "body_snapshot": body_snapshot, "notes": SEED_NOTES, "activated_at": "2026-05-11T00:00:00", }, ) def upgrade() -> None: bind = op.get_bind() if not _table_exists(bind, "prompt_releases"): return tenant_id = int(os.getenv("PMFLOW_PLATFORM_RUNTIME_TENANT_ID", "1") or "1") for prompt_key in PROMPT_KEYS: body_snapshot = _prompt_body(prompt_key) if body_snapshot: _seed_active_release(bind, tenant_id=tenant_id, prompt_key=prompt_key, body_snapshot=body_snapshot) def downgrade() -> None: bind = op.get_bind() if not _table_exists(bind, "prompt_releases"): return tenant_id = int(os.getenv("PMFLOW_PLATFORM_RUNTIME_TENANT_ID", "1") or "1") bind.execute( sa.text( """ DELETE FROM prompt_releases WHERE tenant_id = :tenant_id AND prompt_key IN :prompt_keys AND notes = :notes """ ).bindparams(sa.bindparam("prompt_keys", expanding=True)), {"tenant_id": tenant_id, "prompt_keys": PROMPT_KEYS, "notes": SEED_NOTES}, )