"""phase1_intel_tables Adds 11 new normalized intel tables and extends musehub_symbol_intel with two new columns (last_commit_id, op) for Phase 1 of issue #8. New tables: musehub_intel_coupling — co-changing file pairs musehub_intel_entangle — symbol entanglement pairs musehub_intel_dead — dead-code candidates musehub_intel_blast_risk — composite pre-release risk per symbol musehub_intel_stable — long-stable symbols musehub_intel_velocity — module growth velocity musehub_intel_clones — duplicate code clusters musehub_intel_type — per-symbol type health musehub_intel_api_surface — public API surface entries musehub_intel_languages — language breakdown per push musehub_intel_refactor_events — detected refactoring events Extended columns on musehub_symbol_intel: last_commit_id VARCHAR(128) — most recent commit that touched this symbol op VARCHAR(16) — latest op (add/modify/delete) Revision ID: 0004 Revises: 0003 Create Date: 2026-05-02 00:00:00.000000+00:00 """ from __future__ import annotations from typing import Sequence, Union import sqlalchemy as sa from alembic import op revision: str = '0004' down_revision: Union[str, None] = '0003' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: # Extend musehub_symbol_intel op.add_column('musehub_symbol_intel', sa.Column('last_commit_id', sa.String(128), nullable=True)) op.add_column('musehub_symbol_intel', sa.Column('op', sa.String(16), nullable=True)) op.create_table( 'musehub_intel_coupling', sa.Column('repo_id', sa.String(128), sa.ForeignKey('musehub_repos.repo_id', ondelete='CASCADE'), primary_key=True, nullable=False), sa.Column('file_a', sa.String(512), primary_key=True, nullable=False), sa.Column('file_b', sa.String(512), primary_key=True, nullable=False), sa.Column('co_changes', sa.Integer, nullable=False, server_default='0'), sa.Column('ref', sa.String(128), nullable=False), ) op.create_index('ix_intel_coupling_repo', 'musehub_intel_coupling', ['repo_id']) op.create_table( 'musehub_intel_entangle', sa.Column('repo_id', sa.String(128), sa.ForeignKey('musehub_repos.repo_id', ondelete='CASCADE'), primary_key=True, nullable=False), sa.Column('symbol_a', sa.String(512), primary_key=True, nullable=False), sa.Column('symbol_b', sa.String(512), primary_key=True, nullable=False), sa.Column('co_change_rate', sa.Float, nullable=False, server_default='0.0'), sa.Column('co_changes', sa.Integer, nullable=False, server_default='0'), sa.Column('structurally_linked', sa.Boolean, nullable=False, server_default='false'), sa.Column('ref', sa.String(128), nullable=False), ) op.create_index('ix_intel_entangle_repo', 'musehub_intel_entangle', ['repo_id']) op.create_table( 'musehub_intel_dead', sa.Column('repo_id', sa.String(128), sa.ForeignKey('musehub_repos.repo_id', ondelete='CASCADE'), primary_key=True, nullable=False), sa.Column('address', sa.String(512), primary_key=True, nullable=False), sa.Column('kind', sa.String(64), nullable=False), sa.Column('confidence', sa.String(16), nullable=False, server_default='medium'), sa.Column('reason', sa.Text, nullable=True), sa.Column('ref', sa.String(128), nullable=False), ) op.create_index('ix_intel_dead_repo', 'musehub_intel_dead', ['repo_id']) op.create_table( 'musehub_intel_blast_risk', sa.Column('repo_id', sa.String(128), sa.ForeignKey('musehub_repos.repo_id', ondelete='CASCADE'), primary_key=True, nullable=False), sa.Column('address', sa.String(512), primary_key=True, nullable=False), sa.Column('kind', sa.String(64), nullable=False), sa.Column('risk', sa.String(16), nullable=False, server_default='low'), sa.Column('risk_score', sa.Integer, nullable=False, server_default='0'), sa.Column('impact_score', sa.Float, nullable=False, server_default='0.0'), sa.Column('churn_score', sa.Float, nullable=False, server_default='0.0'), sa.Column('test_gap_score', sa.Float, nullable=False, server_default='0.0'), sa.Column('coupling_score', sa.Float, nullable=False, server_default='0.0'), sa.Column('ref', sa.String(128), nullable=False), ) op.create_index('ix_intel_blast_risk_repo', 'musehub_intel_blast_risk', ['repo_id']) op.create_table( 'musehub_intel_stable', sa.Column('repo_id', sa.String(128), sa.ForeignKey('musehub_repos.repo_id', ondelete='CASCADE'), primary_key=True, nullable=False), sa.Column('address', sa.String(512), primary_key=True, nullable=False), sa.Column('days_stable', sa.Integer, nullable=False, server_default='0'), sa.Column('since_start', sa.Boolean, nullable=False, server_default='false'), sa.Column('ref', sa.String(128), nullable=False), ) op.create_index('ix_intel_stable_repo', 'musehub_intel_stable', ['repo_id']) op.create_table( 'musehub_intel_velocity', sa.Column('repo_id', sa.String(128), sa.ForeignKey('musehub_repos.repo_id', ondelete='CASCADE'), primary_key=True, nullable=False), sa.Column('module', sa.String(512), primary_key=True, nullable=False), sa.Column('added', sa.Integer, nullable=False, server_default='0'), sa.Column('removed', sa.Integer, nullable=False, server_default='0'), sa.Column('net', sa.Integer, nullable=False, server_default='0'), sa.Column('modified', sa.Integer, nullable=False, server_default='0'), sa.Column('active_commits', sa.Integer, nullable=False, server_default='0'), sa.Column('prior_added', sa.Integer, nullable=False, server_default='0'), sa.Column('prior_net', sa.Integer, nullable=False, server_default='0'), sa.Column('acceleration', sa.Float, nullable=False, server_default='0.0'), sa.Column('stagnant_commits', sa.Integer, nullable=False, server_default='0'), sa.Column('ref', sa.String(128), nullable=False), ) op.create_index('ix_intel_velocity_repo', 'musehub_intel_velocity', ['repo_id']) op.create_table( 'musehub_intel_clones', sa.Column('repo_id', sa.String(128), sa.ForeignKey('musehub_repos.repo_id', ondelete='CASCADE'), primary_key=True, nullable=False), sa.Column('cluster_hash', sa.String(128), primary_key=True, nullable=False), sa.Column('tier', sa.String(32), nullable=False), sa.Column('member_count', sa.Integer, nullable=False, server_default='0'), sa.Column('members_json', sa.Text, nullable=False, server_default='[]'), sa.Column('ref', sa.String(128), nullable=False), ) op.create_index('ix_intel_clones_repo', 'musehub_intel_clones', ['repo_id']) op.create_table( 'musehub_intel_type', sa.Column('repo_id', sa.String(128), sa.ForeignKey('musehub_repos.repo_id', ondelete='CASCADE'), primary_key=True, nullable=False), sa.Column('address', sa.String(512), primary_key=True, nullable=False), sa.Column('kind', sa.String(64), nullable=False), sa.Column('return_is_any', sa.Boolean, nullable=False, server_default='false'), sa.Column('params_total', sa.Integer, nullable=False, server_default='0'), sa.Column('params_annotated', sa.Integer, nullable=False, server_default='0'), sa.Column('params_with_any', sa.Integer, nullable=False, server_default='0'), sa.Column('type_score', sa.Float, nullable=False, server_default='0.0'), sa.Column('ref', sa.String(128), nullable=False), ) op.create_index('ix_intel_type_repo', 'musehub_intel_type', ['repo_id']) op.create_table( 'musehub_intel_api_surface', sa.Column('repo_id', sa.String(128), sa.ForeignKey('musehub_repos.repo_id', ondelete='CASCADE'), primary_key=True, nullable=False), sa.Column('address', sa.String(512), primary_key=True, nullable=False), sa.Column('kind', sa.String(64), nullable=False), sa.Column('signature_id', sa.String(128), nullable=True), sa.Column('visibility', sa.String(32), nullable=False, server_default='public'), sa.Column('ref', sa.String(128), nullable=False), ) op.create_index('ix_intel_api_surface_repo', 'musehub_intel_api_surface', ['repo_id']) op.create_table( 'musehub_intel_languages', sa.Column('repo_id', sa.String(128), sa.ForeignKey('musehub_repos.repo_id', ondelete='CASCADE'), primary_key=True, nullable=False), sa.Column('language', sa.String(128), primary_key=True, nullable=False), sa.Column('symbol_count', sa.Integer, nullable=False, server_default='0'), sa.Column('file_count', sa.Integer, nullable=False, server_default='0'), sa.Column('pct', sa.Float, nullable=False, server_default='0.0'), sa.Column('ref', sa.String(128), nullable=False), ) op.create_index('ix_intel_languages_repo', 'musehub_intel_languages', ['repo_id']) op.create_table( 'musehub_intel_refactor_events', sa.Column('event_id', sa.String(128), primary_key=True, nullable=False), sa.Column('repo_id', sa.String(128), sa.ForeignKey('musehub_repos.repo_id', ondelete='CASCADE'), nullable=False), sa.Column('kind', sa.String(64), nullable=False), sa.Column('address', sa.String(512), nullable=False), sa.Column('detail', sa.Text, nullable=True), sa.Column('commit_id', sa.String(128), nullable=False), sa.Column('committed_at', sa.DateTime(timezone=True), nullable=False), ) op.create_index('ix_intel_refactor_events_repo', 'musehub_intel_refactor_events', ['repo_id']) op.create_index('ix_intel_refactor_events_commit', 'musehub_intel_refactor_events', ['commit_id']) def downgrade() -> None: op.drop_table('musehub_intel_refactor_events') op.drop_table('musehub_intel_languages') op.drop_table('musehub_intel_api_surface') op.drop_table('musehub_intel_type') op.drop_table('musehub_intel_clones') op.drop_table('musehub_intel_velocity') op.drop_table('musehub_intel_stable') op.drop_table('musehub_intel_blast_risk') op.drop_table('musehub_intel_dead') op.drop_table('musehub_intel_entangle') op.drop_table('musehub_intel_coupling') op.drop_column('musehub_symbol_intel', 'op') op.drop_column('musehub_symbol_intel', 'last_commit_id')