[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6F67E5REQHDB0QF3EVWMQJV":3,"skill-same:01M6F67E5REQHDB0QF3EVWMQJV":74},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":42,"linkOnly":43,"markdownContent":44,"markdownBody":45,"frontMatter":46,"refName":51,"commitSha":52,"skillDirectory":53,"forksCount":54,"repositoryHtmlUrl":55,"repositoryHomepageUrl":6,"ownerHtmlUrl":56,"ownerBlogUrl":57,"ownerDescription":58,"updatedAt":59,"install":60,"resources":73},"01M6F67E5REQHDB0QF3EVWMQJV","databricks-migration-deep-dive",null,"Execute comprehensive platform migrations to Databricks from legacy systems.\nUse when migrating from on-premises Hadoop, other cloud platforms,\nor legacy data warehouses to Databricks.\nTrigger with phrases like \"migrate to databricks\", \"hadoop migration\",\n\"snowflake to databricks\", \"legacy migration\", \"data warehouse migration\".","Dicklesworthstone\u002Fpi_agent_rust","Dicklesworthstone","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F35050222?v=4","01M6CG26AR942CSVMN1M5E3DSE","Jeff Emanuel","01M6CG26EPP71PSHW1VDS71121",1991,"MIT","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fdatabricks-pack\u002Fskills\u002Fdatabricks-migration-deep-dive\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41],"databricks","deep dive","databricks migration deep dive","deep","migration","databricks migration","hadoop","when","warehouse","snowflake","with","trigger","io","platform","Bash","migrations","Legacy","data","use","edit","write","read","migrate","2026-11-10 10:12:30",false,"---\nname: databricks-migration-deep-dive\ndescription: |\n  Execute comprehensive platform migrations to Databricks from legacy systems.\n  Use when migrating from on-premises Hadoop, other cloud platforms,\n  or legacy data warehouses to Databricks.\n  Trigger with phrases like \"migrate to databricks\", \"hadoop migration\",\n  \"snowflake to databricks\", \"legacy migration\", \"data warehouse migration\".\nallowed-tools: Read, Write, Edit, Bash(databricks:*), Grep\nversion: 1.0.0\nlicense: MIT\nauthor: Jeremy Longshore \u003Cjeremy@intentsolutions.io>\n---\n\n# Databricks Migration Deep Dive\n\n## Overview\nComprehensive migration strategies for moving to Databricks from legacy systems.\n\n## Prerequisites\n- Access to source and target systems\n- Understanding of current data architecture\n- Migration timeline and requirements\n- Stakeholder alignment\n\n## Migration Patterns\n\n| Source System | Migration Pattern | Complexity | Timeline |\n|--------------|-------------------|------------|----------|\n| On-prem Hadoop | Lift-and-shift + modernize | High | 6-12 months |\n| Snowflake | Parallel run + cutover | Medium | 3-6 months |\n| AWS Redshift | ETL rewrite + data copy | Medium | 3-6 months |\n| Azure Synapse | Delta Lake conversion | Low | 1-3 months |\n| Legacy DW (Oracle\u002FTeradata) | Full rebuild | High | 12-18 months |\n\n## Instructions\n\n### Step 1: Discovery and Assessment\n\n```python\n# scripts\u002Fmigration_assessment.py\nfrom dataclasses import dataclass\nfrom typing import List, Dict\nimport pandas as pd\n\n@dataclass\nclass SourceTableInfo:\n    \"\"\"Information about source table for migration planning.\"\"\"\n    database: str\n    schema: str\n    table: str\n    row_count: int\n    size_gb: float\n    column_count: int\n    partition_columns: List[str]\n    dependencies: List[str]\n    access_frequency: str  # high, medium, low\n    data_classification: str  # pii, confidential, public\n\ndef assess_hadoop_cluster(spark, hive_metastore: str) -> List[SourceTableInfo]:\n    \"\"\"\n    Assess Hadoop\u002FHive cluster for migration planning.\n\n    Returns inventory of all tables with metadata.\n    \"\"\"\n    tables = []\n\n    # Get all databases\n    databases = spark.sql(\"SHOW DATABASES\").collect()\n\n    for db_row in databases:\n        db = db_row.databaseName\n        if db in ['default', 'sys']:  # Skip system DBs\n            continue\n\n        # Get tables in database\n        spark.sql(f\"USE {db}\")\n        table_list = spark.sql(\"SHOW TABLES\").collect()\n\n        for table_row in table_list:\n            table_name = table_row.tableName\n\n            try:\n                # Get table details\n                desc = spark.sql(f\"DESCRIBE EXTENDED {db}.{table_name}\")\n                detail_df = desc.toPandas()\n\n                # Extract partition info\n                partition_cols = []\n                in_partition_section = False\n                for _, row in detail_df.iterrows():\n                    if row['col_name'] == '# Partition Information':\n                        in_partition_section = True\n                    elif in_partition_section and row['col_name'] and not row['col_name'].startswith('#'):\n                        partition_cols.append(row['col_name'])\n\n                # Get row count and size\n                stats = spark.sql(f\"DESCRIBE EXTENDED {db}.{table_name}\")\n                # Parse statistics from DESCRIBE output\n\n                tables.append(SourceTableInfo(\n                    database=db,\n                    schema=db,\n                    table=table_name,\n                    row_count=0,  # Would query actual count\n                    size_gb=0,  # From statistics\n                    column_count=len(detail_df),\n                    partition_columns=partition_cols,\n                    dependencies=[],  # Would analyze queries\n                    access_frequency='medium',\n                    data_classification='internal',\n                ))\n\n            except Exception as e:\n                print(f\"Error processing {db}.{table_name}: {e}\")\n\n    return tables\n\ndef generate_migration_plan(tables: List[SourceTableInfo]) -> pd.DataFrame:\n    \"\"\"Generate migration plan with prioritization.\"\"\"\n    plan_data = []\n\n    for table in tables:\n        # Calculate complexity score\n        complexity = 0\n        complexity += 1 if table.size_gb > 100 else 0\n        complexity += 1 if len(table.partition_columns) > 2 else 0\n        complexity += 1 if len(table.dependencies) > 5 else 0\n        complexity += 2 if table.data_classification == 'pii' else 0\n\n        # Calculate priority\n        priority = 0\n        priority += 3 if table.access_frequency == 'high' else 1\n        priority += 2 if table.data_classification == 'pii' else 0\n\n        plan_data.append({\n            'source_table': f\"{table.database}.{table.table}\",\n            'target_table': f\"migrated.{table.schema}.{table.table}\",\n            'size_gb': table.size_gb,\n            'complexity_score': complexity,\n            'priority_score': priority,\n            'estimated_hours': max(1, table.size_gb \u002F 10 + complexity * 2),\n            'migration_wave': 1 if priority > 3 else (2 if priority > 1 else 3),\n        })\n\n    return pd.DataFrame(plan_data).sort_values(['migration_wave', 'priority_score'], ascending=[True, False])\n```\n\n### Step 2: Schema Migration\n\n```python\n# scripts\u002Fschema_migration.py\nfrom pyspark.sql import SparkSession\nfrom pyspark.sql.types import *\n\ndef convert_hive_to_delta_schema(spark: SparkSession, hive_table: str) -> StructType:\n    \"\"\"\n    Convert Hive table schema to Delta Lake compatible schema.\n\n    Handles type conversions and incompatibilities.\n    \"\"\"\n    hive_schema = spark.table(hive_table).schema\n\n    # Type mappings for problematic types\n    type_conversions = {\n        'decimal(38,0)': DecimalType(38, 10),  # Add scale\n        'char': StringType(),\n        'varchar': StringType(),\n        'tinyint': IntegerType(),  # Delta doesn't have tinyint\n    }\n\n    new_fields = []\n    for field in hive_schema.fields:\n        new_type = field.dataType\n        type_str = str(field.dataType).lower()\n\n        for pattern, replacement in type_conversions.items():\n            if pattern in type_str:\n                new_type = replacement\n                break\n\n        new_fields.append(StructField(\n            field.name,\n            new_type,\n            field.nullable,\n            field.metadata\n        ))\n\n    return StructType(new_fields)\n\ndef migrate_table_schema(\n    spark: SparkSession,\n    source_table: str,\n    target_table: str,\n    catalog: str = \"migrated\",\n) -> dict:\n    \"\"\"\n    Migrate table schema from Hive to Delta Lake.\n\n    Returns migration result with any schema changes.\n    \"\"\"\n    # Get source schema\n    source_df = spark.table(source_table)\n    source_schema = source_df.schema\n\n    # Convert schema\n    target_schema = convert_hive_to_delta_schema(spark, source_table)\n\n    # Create target table\n    schema_ddl = \", \".join([\n        f\"`{f.name}` {f.dataType.simpleString()}\"\n        for f in target_schema.fields\n    ])\n\n    spark.sql(f\"\"\"\n        CREATE TABLE IF NOT EXISTS {catalog}.{target_table} (\n            {schema_ddl}\n        )\n        USING DELTA\n        TBLPROPERTIES (\n            'delta.autoOptimize.optimizeWrite' = 'true',\n            'delta.autoOptimize.autoCompact' = 'true'\n        )\n    \"\"\")\n\n    # Track schema changes\n    changes = []\n    for i, (src, tgt) in enumerate(zip(source_schema.fields, target_schema.fields)):\n        if str(src.dataType) != str(tgt.dataType):\n            changes.append({\n                'column': src.name,\n                'source_type': str(src.dataType),\n                'target_type': str(tgt.dataType),\n            })\n\n    return {\n        'source_table': source_table,\n        'target_table': f\"{catalog}.{target_table}\",\n        'column_count': len(target_schema.fields),\n        'schema_changes': changes,\n    }\n```\n\n### Step 3: Data Migration\n\n```python\n# scripts\u002Fdata_migration.py\nfrom pyspark.sql import SparkSession, DataFrame\nfrom datetime import datetime\nimport time\n\nclass DataMigrator:\n    \"\"\"Handle data migration from legacy systems to Delta Lake.\"\"\"\n\n    def __init__(self, spark: SparkSession, target_catalog: str):\n        self.spark = spark\n        self.target_catalog = target_catalog\n\n    def migrate_table(\n        self,\n        source_table: str,\n        target_table: str,\n        batch_size: int = 1000000,\n        partition_columns: list[str] = None,\n        incremental_column: str = None,\n    ) -> dict:\n        \"\"\"\n        Migrate table data with batching and checkpointing.\n\n        Args:\n            source_table: Source table (Hive, JDBC, etc.)\n            target_table: Target Delta table\n            batch_size: Rows per batch\n            partition_columns: Columns for partitioning\n            incremental_column: Column for incremental loads\n\n        Returns:\n            Migration statistics\n        \"\"\"\n        start_time = time.time()\n        stats = {\n            'source_table': source_table,\n            'target_table': f\"{self.target_catalog}.{target_table}\",\n            'batches': 0,\n            'total_rows': 0,\n            'errors': [],\n        }\n\n        # Get source data\n        source_df = self.spark.table(source_table)\n\n        # For large tables, process in batches by partition\n        if partition_columns and len(partition_columns) > 0:\n            # Get distinct partition values\n            partitions = source_df.select(partition_columns).distinct().collect()\n\n            for partition_row in partitions:\n                # Build filter condition\n                conditions = [\n                    f\"{col} = '{partition_row[col]}'\"\n                    for col in partition_columns\n                ]\n                filter_expr = \" AND \".join(conditions)\n\n                batch_df = source_df.filter(filter_expr)\n                self._write_batch(batch_df, target_table, partition_columns)\n                stats['batches'] += 1\n                stats['total_rows'] += batch_df.count()\n\n        else:\n            # Single batch for small tables\n            self._write_batch(source_df, target_table, partition_columns)\n            stats['batches'] = 1\n            stats['total_rows'] = source_df.count()\n\n        stats['duration_seconds'] = time.time() - start_time\n        stats['rows_per_second'] = stats['total_rows'] \u002F stats['duration_seconds']\n\n        return stats\n\n    def _write_batch(\n        self,\n        df: DataFrame,\n        target_table: str,\n        partition_columns: list[str] = None,\n    ):\n        \"\"\"Write a batch to Delta table.\"\"\"\n        writer = df.write.format(\"delta\").mode(\"append\")\n\n        if partition_columns:\n            writer = writer.partitionBy(*partition_columns)\n\n        writer.saveAsTable(f\"{self.target_catalog}.{target_table}\")\n\n    def validate_migration(\n        self,\n        source_table: str,\n        target_table: str,\n    ) -> dict:\n        \"\"\"Validate migrated data matches source.\"\"\"\n        source_df = self.spark.table(source_table)\n        target_df = self.spark.table(f\"{self.target_catalog}.{target_table}\")\n\n        validation = {\n            'source_count': source_df.count(),\n            'target_count': target_df.count(),\n            'count_match': False,\n            'schema_match': False,\n            'sample_match': False,\n        }\n\n        # Count validation\n        validation['count_match'] = (\n            validation['source_count'] == validation['target_count']\n        )\n\n        # Schema validation (column names)\n        source_cols = set(source_df.columns)\n        target_cols = set(target_df.columns)\n        validation['schema_match'] = source_cols == target_cols\n\n        # Sample data validation\n        source_sample = source_df.limit(100).toPandas()\n        target_sample = target_df.limit(100).toPandas()\n        # Compare samples (simplified)\n        validation['sample_match'] = len(source_sample) == len(target_sample)\n\n        return validation\n```\n\n### Step 4: ETL\u002FPipeline Migration\n\n```python\n# scripts\u002Fpipeline_migration.py\n\ndef convert_spark_job_to_databricks(\n    source_code: str,\n    source_type: str = \"spark-submit\",\n) -> str:\n    \"\"\"\n    Convert legacy Spark job to Databricks job.\n\n    Handles common patterns from spark-submit, Oozie, Airflow.\n    \"\"\"\n    # Common replacements\n    replacements = {\n        # SparkSession changes\n        'SparkSession.builder.master(\"yarn\")': 'SparkSession.builder',\n        '.master(\"local[*]\")': '',\n\n        # Path changes\n        'hdfs:\u002F\u002Fnamenode:8020\u002F': '\u002Fmnt\u002Fdata\u002F',\n        's3a:\u002F\u002F': 's3:\u002F\u002F',\n\n        # Hive changes\n        '.enableHiveSupport()': '',  # Unity Catalog handles this\n        'hive_metastore.': '',  # Direct table access\n\n        # Config changes\n        '.config(\"spark.sql.warehouse.dir\"': '# Removed: .config(\"spark.sql.warehouse.dir\"',\n    }\n\n    converted = source_code\n    for old, new in replacements.items():\n        converted = converted.replace(old, new)\n\n    # Add Databricks-specific imports\n    header = '''\n# Converted for Databricks\n# Original source: {source_type}\n# Conversion date: {date}\n\nfrom pyspark.sql import SparkSession\n\n# SparkSession is pre-configured in Databricks\nspark = SparkSession.builder.getOrCreate()\n'''.format(source_type=source_type, date=datetime.now().isoformat())\n\n    return header + converted\n\n# Convert Oozie workflow to Databricks job\ndef convert_oozie_to_databricks_job(oozie_xml: str) -> dict:\n    \"\"\"Convert Oozie workflow XML to Databricks job definition.\"\"\"\n    import xml.etree.ElementTree as ET\n\n    root = ET.fromstring(oozie_xml)\n\n    tasks = []\n    for action in root.findall('.\u002F\u002Faction'):\n        action_name = action.get('name')\n\n        # Handle different action types\n        spark_action = action.find('spark')\n        if spark_action is not None:\n            jar = spark_action.find('jar').text\n            main_class = spark_action.find('class').text\n\n            tasks.append({\n                'task_key': action_name,\n                'spark_jar_task': {\n                    'main_class_name': main_class,\n                    'parameters': [],\n                },\n                'libraries': [{'jar': jar}],\n            })\n\n        shell_action = action.find('shell')\n        if shell_action is not None:\n            # Convert to notebook task or skip\n            pass\n\n    # Build job definition\n    job_definition = {\n        'name': f\"migrated-{root.get('name')}\",\n        'tasks': tasks,\n        'job_clusters': [{\n            'job_cluster_key': 'migration_cluster',\n            'new_cluster': {\n                'spark_version': '14.3.x-scala2.12',\n                'node_type_id': 'Standard_DS3_v2',\n                'num_workers': 2,\n            }\n        }],\n    }\n\n    return job_definition\n```\n\n### Step 5: Cutover Planning\n\n```python\n# scripts\u002Fcutover_plan.py\nfrom dataclasses import dataclass\nfrom datetime import datetime, timedelta\nfrom typing import List\n\n@dataclass\nclass CutoverStep:\n    \"\"\"Individual step in cutover plan.\"\"\"\n    order: int\n    name: str\n    duration_minutes: int\n    owner: str\n    rollback_procedure: str\n    verification: str\n\ndef generate_cutover_plan(\n    migration_wave: int,\n    tables: List[str],\n    cutover_date: datetime,\n) -> List[CutoverStep]:\n    \"\"\"Generate detailed cutover plan.\"\"\"\n\n    steps = [\n        CutoverStep(\n            order=1,\n            name=\"Pre-cutover validation\",\n            duration_minutes=60,\n            owner=\"Data Engineer\",\n            rollback_procedure=\"N\u002FA - no changes made\",\n            verification=\"Run validation queries on all tables\",\n        ),\n        CutoverStep(\n            order=2,\n            name=\"Disable source data pipelines\",\n            duration_minutes=15,\n            owner=\"Platform Admin\",\n            rollback_procedure=\"Re-enable pipelines in source system\",\n            verification=\"Verify no new data in source\",\n        ),\n        CutoverStep(\n            order=3,\n            name=\"Final incremental sync\",\n            duration_minutes=120,\n            owner=\"Data Engineer\",\n            rollback_procedure=\"N\u002FA\",\n            verification=\"Row counts match source\",\n        ),\n        CutoverStep(\n            order=4,\n            name=\"Enable Databricks pipelines\",\n            duration_minutes=30,\n            owner=\"Data Engineer\",\n            rollback_procedure=\"Disable Databricks pipelines, re-enable source\",\n            verification=\"Jobs running successfully\",\n        ),\n        CutoverStep(\n            order=5,\n            name=\"Update downstream applications\",\n            duration_minutes=60,\n            owner=\"Application Team\",\n            rollback_procedure=\"Revert connection strings\",\n            verification=\"Applications reading from Databricks\",\n        ),\n        CutoverStep(\n            order=6,\n            name=\"Monitor and validate\",\n            duration_minutes=240,\n            owner=\"Data Engineer\",\n            rollback_procedure=\"Execute full rollback if issues\",\n            verification=\"All metrics within acceptable range\",\n        ),\n    ]\n\n    # Calculate timings\n    current_time = cutover_date\n    for step in steps:\n        step.start_time = current_time\n        step.end_time = current_time + timedelta(minutes=step.duration_minutes)\n        current_time = step.end_time\n\n    return steps\n```\n\n## Output\n- Migration assessment complete\n- Schema migration automated\n- Data migration pipeline ready\n- ETL conversion scripts\n- Cutover plan documented\n\n## Error Handling\n| Issue | Cause | Solution |\n|-------|-------|----------|\n| Schema incompatibility | Unsupported types | Use type conversion mappings |\n| Data loss | Truncation | Validate counts at each step |\n| Performance issues | Large tables | Use partitioned migration |\n| Dependency conflicts | Wrong migration order | Analyze dependencies first |\n\n## Examples\n\n### Quick Migration Validation\n```sql\n-- Compare source and target counts\nSELECT\n    'source' as system, COUNT(*) as row_count\nFROM hive_metastore.db.table\nUNION ALL\nSELECT\n    'target' as system, COUNT(*) as row_count\nFROM migrated.db.table;\n```\n\n## Resources\n- [Databricks Migration Guide](https:\u002F\u002Fdocs.databricks.com\u002Fmigration\u002Findex.html)\n- [Delta Lake Migration](https:\u002F\u002Fdocs.databricks.com\u002Fdelta\u002Fmigration.html)\n- [Unity Catalog Migration](https:\u002F\u002Fdocs.databricks.com\u002Fdata-governance\u002Funity-catalog\u002Fmigrate.html)\n\n## Completion\nThis skill pack provides comprehensive coverage for Databricks platform operations.\n","# Databricks Migration Deep Dive\n\n## Overview\nComprehensive migration strategies for moving to Databricks from legacy systems.\n\n## Prerequisites\n- Access to source and target systems\n- Understanding of current data architecture\n- Migration timeline and requirements\n- Stakeholder alignment\n\n## Migration Patterns\n\n| Source System | Migration Pattern | Complexity | Timeline |\n|--------------|-------------------|------------|----------|\n| On-prem Hadoop | Lift-and-shift + modernize | High | 6-12 months |\n| Snowflake | Parallel run + cutover | Medium | 3-6 months |\n| AWS Redshift | ETL rewrite + data copy | Medium | 3-6 months |\n| Azure Synapse | Delta Lake conversion | Low | 1-3 months |\n| Legacy DW (Oracle\u002FTeradata) | Full rebuild | High | 12-18 months |\n\n## Instructions\n\n### Step 1: Discovery and Assessment\n\n```python\n# scripts\u002Fmigration_assessment.py\nfrom dataclasses import dataclass\nfrom typing import List, Dict\nimport pandas as pd\n\n@dataclass\nclass SourceTableInfo:\n    \"\"\"Information about source table for migration planning.\"\"\"\n    database: str\n    schema: str\n    table: str\n    row_count: int\n    size_gb: float\n    column_count: int\n    partition_columns: List[str]\n    dependencies: List[str]\n    access_frequency: str  # high, medium, low\n    data_classification: str  # pii, confidential, public\n\ndef assess_hadoop_cluster(spark, hive_metastore: str) -> List[SourceTableInfo]:\n    \"\"\"\n    Assess Hadoop\u002FHive cluster for migration planning.\n\n    Returns inventory of all tables with metadata.\n    \"\"\"\n    tables = []\n\n    # Get all databases\n    databases = spark.sql(\"SHOW DATABASES\").collect()\n\n    for db_row in databases:\n        db = db_row.databaseName\n        if db in ['default', 'sys']:  # Skip system DBs\n            continue\n\n        # Get tables in database\n        spark.sql(f\"USE {db}\")\n        table_list = spark.sql(\"SHOW TABLES\").collect()\n\n        for table_row in table_list:\n            table_name = table_row.tableName\n\n            try:\n                # Get table details\n                desc = spark.sql(f\"DESCRIBE EXTENDED {db}.{table_name}\")\n                detail_df = desc.toPandas()\n\n                # Extract partition info\n                partition_cols = []\n                in_partition_section = False\n                for _, row in detail_df.iterrows():\n                    if row['col_name'] == '# Partition Information':\n                        in_partition_section = True\n                    elif in_partition_section and row['col_name'] and not row['col_name'].startswith('#'):\n                        partition_cols.append(row['col_name'])\n\n                # Get row count and size\n                stats = spark.sql(f\"DESCRIBE EXTENDED {db}.{table_name}\")\n                # Parse statistics from DESCRIBE output\n\n                tables.append(SourceTableInfo(\n                    database=db,\n                    schema=db,\n                    table=table_name,\n                    row_count=0,  # Would query actual count\n                    size_gb=0,  # From statistics\n                    column_count=len(detail_df),\n                    partition_columns=partition_cols,\n                    dependencies=[],  # Would analyze queries\n                    access_frequency='medium',\n                    data_classification='internal',\n                ))\n\n            except Exception as e:\n                print(f\"Error processing {db}.{table_name}: {e}\")\n\n    return tables\n\ndef generate_migration_plan(tables: List[SourceTableInfo]) -> pd.DataFrame:\n    \"\"\"Generate migration plan with prioritization.\"\"\"\n    plan_data = []\n\n    for table in tables:\n        # Calculate complexity score\n        complexity = 0\n        complexity += 1 if table.size_gb > 100 else 0\n        complexity += 1 if len(table.partition_columns) > 2 else 0\n        complexity += 1 if len(table.dependencies) > 5 else 0\n        complexity += 2 if table.data_classification == 'pii' else 0\n\n        # Calculate priority\n        priority = 0\n        priority += 3 if table.access_frequency == 'high' else 1\n        priority += 2 if table.data_classification == 'pii' else 0\n\n        plan_data.append({\n            'source_table': f\"{table.database}.{table.table}\",\n            'target_table': f\"migrated.{table.schema}.{table.table}\",\n            'size_gb': table.size_gb,\n            'complexity_score': complexity,\n            'priority_score': priority,\n            'estimated_hours': max(1, table.size_gb \u002F 10 + complexity * 2),\n            'migration_wave': 1 if priority > 3 else (2 if priority > 1 else 3),\n        })\n\n    return pd.DataFrame(plan_data).sort_values(['migration_wave', 'priority_score'], ascending=[True, False])\n```\n\n### Step 2: Schema Migration\n\n```python\n# scripts\u002Fschema_migration.py\nfrom pyspark.sql import SparkSession\nfrom pyspark.sql.types import *\n\ndef convert_hive_to_delta_schema(spark: SparkSession, hive_table: str) -> StructType:\n    \"\"\"\n    Convert Hive table schema to Delta Lake compatible schema.\n\n    Handles type conversions and incompatibilities.\n    \"\"\"\n    hive_schema = spark.table(hive_table).schema\n\n    # Type mappings for problematic types\n    type_conversions = {\n        'decimal(38,0)': DecimalType(38, 10),  # Add scale\n        'char': StringType(),\n        'varchar': StringType(),\n        'tinyint': IntegerType(),  # Delta doesn't have tinyint\n    }\n\n    new_fields = []\n    for field in hive_schema.fields:\n        new_type = field.dataType\n        type_str = str(field.dataType).lower()\n\n        for pattern, replacement in type_conversions.items():\n            if pattern in type_str:\n                new_type = replacement\n                break\n\n        new_fields.append(StructField(\n            field.name,\n            new_type,\n            field.nullable,\n            field.metadata\n        ))\n\n    return StructType(new_fields)\n\ndef migrate_table_schema(\n    spark: SparkSession,\n    source_table: str,\n    target_table: str,\n    catalog: str = \"migrated\",\n) -> dict:\n    \"\"\"\n    Migrate table schema from Hive to Delta Lake.\n\n    Returns migration result with any schema changes.\n    \"\"\"\n    # Get source schema\n    source_df = spark.table(source_table)\n    source_schema = source_df.schema\n\n    # Convert schema\n    target_schema = convert_hive_to_delta_schema(spark, source_table)\n\n    # Create target table\n    schema_ddl = \", \".join([\n        f\"`{f.name}` {f.dataType.simpleString()}\"\n        for f in target_schema.fields\n    ])\n\n    spark.sql(f\"\"\"\n        CREATE TABLE IF NOT EXISTS {catalog}.{target_table} (\n            {schema_ddl}\n        )\n        USING DELTA\n        TBLPROPERTIES (\n            'delta.autoOptimize.optimizeWrite' = 'true',\n            'delta.autoOptimize.autoCompact' = 'true'\n        )\n    \"\"\")\n\n    # Track schema changes\n    changes = []\n    for i, (src, tgt) in enumerate(zip(source_schema.fields, target_schema.fields)):\n        if str(src.dataType) != str(tgt.dataType):\n            changes.append({\n                'column': src.name,\n                'source_type': str(src.dataType),\n                'target_type': str(tgt.dataType),\n            })\n\n    return {\n        'source_table': source_table,\n        'target_table': f\"{catalog}.{target_table}\",\n        'column_count': len(target_schema.fields),\n        'schema_changes': changes,\n    }\n```\n\n### Step 3: Data Migration\n\n```python\n# scripts\u002Fdata_migration.py\nfrom pyspark.sql import SparkSession, DataFrame\nfrom datetime import datetime\nimport time\n\nclass DataMigrator:\n    \"\"\"Handle data migration from legacy systems to Delta Lake.\"\"\"\n\n    def __init__(self, spark: SparkSession, target_catalog: str):\n        self.spark = spark\n        self.target_catalog = target_catalog\n\n    def migrate_table(\n        self,\n        source_table: str,\n        target_table: str,\n        batch_size: int = 1000000,\n        partition_columns: list[str] = None,\n        incremental_column: str = None,\n    ) -> dict:\n        \"\"\"\n        Migrate table data with batching and checkpointing.\n\n        Args:\n            source_table: Source table (Hive, JDBC, etc.)\n            target_table: Target Delta table\n            batch_size: Rows per batch\n            partition_columns: Columns for partitioning\n            incremental_column: Column for incremental loads\n\n        Returns:\n            Migration statistics\n        \"\"\"\n        start_time = time.time()\n        stats = {\n            'source_table': source_table,\n            'target_table': f\"{self.target_catalog}.{target_table}\",\n            'batches': 0,\n            'total_rows': 0,\n            'errors': [],\n        }\n\n        # Get source data\n        source_df = self.spark.table(source_table)\n\n        # For large tables, process in batches by partition\n        if partition_columns and len(partition_columns) > 0:\n            # Get distinct partition values\n            partitions = source_df.select(partition_columns).distinct().collect()\n\n            for partition_row in partitions:\n                # Build filter condition\n                conditions = [\n                    f\"{col} = '{partition_row[col]}'\"\n                    for col in partition_columns\n                ]\n                filter_expr = \" AND \".join(conditions)\n\n                batch_df = source_df.filter(filter_expr)\n                self._write_batch(batch_df, target_table, partition_columns)\n                stats['batches'] += 1\n                stats['total_rows'] += batch_df.count()\n\n        else:\n            # Single batch for small tables\n            self._write_batch(source_df, target_table, partition_columns)\n            stats['batches'] = 1\n            stats['total_rows'] = source_df.count()\n\n        stats['duration_seconds'] = time.time() - start_time\n        stats['rows_per_second'] = stats['total_rows'] \u002F stats['duration_seconds']\n\n        return stats\n\n    def _write_batch(\n        self,\n        df: DataFrame,\n        target_table: str,\n        partition_columns: list[str] = None,\n    ):\n        \"\"\"Write a batch to Delta table.\"\"\"\n        writer = df.write.format(\"delta\").mode(\"append\")\n\n        if partition_columns:\n            writer = writer.partitionBy(*partition_columns)\n\n        writer.saveAsTable(f\"{self.target_catalog}.{target_table}\")\n\n    def validate_migration(\n        self,\n        source_table: str,\n        target_table: str,\n    ) -> dict:\n        \"\"\"Validate migrated data matches source.\"\"\"\n        source_df = self.spark.table(source_table)\n        target_df = self.spark.table(f\"{self.target_catalog}.{target_table}\")\n\n        validation = {\n            'source_count': source_df.count(),\n            'target_count': target_df.count(),\n            'count_match': False,\n            'schema_match': False,\n            'sample_match': False,\n        }\n\n        # Count validation\n        validation['count_match'] = (\n            validation['source_count'] == validation['target_count']\n        )\n\n        # Schema validation (column names)\n        source_cols = set(source_df.columns)\n        target_cols = set(target_df.columns)\n        validation['schema_match'] = source_cols == target_cols\n\n        # Sample data validation\n        source_sample = source_df.limit(100).toPandas()\n        target_sample = target_df.limit(100).toPandas()\n        # Compare samples (simplified)\n        validation['sample_match'] = len(source_sample) == len(target_sample)\n\n        return validation\n```\n\n### Step 4: ETL\u002FPipeline Migration\n\n```python\n# scripts\u002Fpipeline_migration.py\n\ndef convert_spark_job_to_databricks(\n    source_code: str,\n    source_type: str = \"spark-submit\",\n) -> str:\n    \"\"\"\n    Convert legacy Spark job to Databricks job.\n\n    Handles common patterns from spark-submit, Oozie, Airflow.\n    \"\"\"\n    # Common replacements\n    replacements = {\n        # SparkSession changes\n        'SparkSession.builder.master(\"yarn\")': 'SparkSession.builder',\n        '.master(\"local[*]\")': '',\n\n        # Path changes\n        'hdfs:\u002F\u002Fnamenode:8020\u002F': '\u002Fmnt\u002Fdata\u002F',\n        's3a:\u002F\u002F': 's3:\u002F\u002F',\n\n        # Hive changes\n        '.enableHiveSupport()': '',  # Unity Catalog handles this\n        'hive_metastore.': '',  # Direct table access\n\n        # Config changes\n        '.config(\"spark.sql.warehouse.dir\"': '# Removed: .config(\"spark.sql.warehouse.dir\"',\n    }\n\n    converted = source_code\n    for old, new in replacements.items():\n        converted = converted.replace(old, new)\n\n    # Add Databricks-specific imports\n    header = '''\n# Converted for Databricks\n# Original source: {source_type}\n# Conversion date: {date}\n\nfrom pyspark.sql import SparkSession\n\n# SparkSession is pre-configured in Databricks\nspark = SparkSession.builder.getOrCreate()\n'''.format(source_type=source_type, date=datetime.now().isoformat())\n\n    return header + converted\n\n# Convert Oozie workflow to Databricks job\ndef convert_oozie_to_databricks_job(oozie_xml: str) -> dict:\n    \"\"\"Convert Oozie workflow XML to Databricks job definition.\"\"\"\n    import xml.etree.ElementTree as ET\n\n    root = ET.fromstring(oozie_xml)\n\n    tasks = []\n    for action in root.findall('.\u002F\u002Faction'):\n        action_name = action.get('name')\n\n        # Handle different action types\n        spark_action = action.find('spark')\n        if spark_action is not None:\n            jar = spark_action.find('jar').text\n            main_class = spark_action.find('class').text\n\n            tasks.append({\n                'task_key': action_name,\n                'spark_jar_task': {\n                    'main_class_name': main_class,\n                    'parameters': [],\n                },\n                'libraries': [{'jar': jar}],\n            })\n\n        shell_action = action.find('shell')\n        if shell_action is not None:\n            # Convert to notebook task or skip\n            pass\n\n    # Build job definition\n    job_definition = {\n        'name': f\"migrated-{root.get('name')}\",\n        'tasks': tasks,\n        'job_clusters': [{\n            'job_cluster_key': 'migration_cluster',\n            'new_cluster': {\n                'spark_version': '14.3.x-scala2.12',\n                'node_type_id': 'Standard_DS3_v2',\n                'num_workers': 2,\n            }\n        }],\n    }\n\n    return job_definition\n```\n\n### Step 5: Cutover Planning\n\n```python\n# scripts\u002Fcutover_plan.py\nfrom dataclasses import dataclass\nfrom datetime import datetime, timedelta\nfrom typing import List\n\n@dataclass\nclass CutoverStep:\n    \"\"\"Individual step in cutover plan.\"\"\"\n    order: int\n    name: str\n    duration_minutes: int\n    owner: str\n    rollback_procedure: str\n    verification: str\n\ndef generate_cutover_plan(\n    migration_wave: int,\n    tables: List[str],\n    cutover_date: datetime,\n) -> List[CutoverStep]:\n    \"\"\"Generate detailed cutover plan.\"\"\"\n\n    steps = [\n        CutoverStep(\n            order=1,\n            name=\"Pre-cutover validation\",\n            duration_minutes=60,\n            owner=\"Data Engineer\",\n            rollback_procedure=\"N\u002FA - no changes made\",\n            verification=\"Run validation queries on all tables\",\n        ),\n        CutoverStep(\n            order=2,\n            name=\"Disable source data pipelines\",\n            duration_minutes=15,\n            owner=\"Platform Admin\",\n            rollback_procedure=\"Re-enable pipelines in source system\",\n            verification=\"Verify no new data in source\",\n        ),\n        CutoverStep(\n            order=3,\n            name=\"Final incremental sync\",\n            duration_minutes=120,\n            owner=\"Data Engineer\",\n            rollback_procedure=\"N\u002FA\",\n            verification=\"Row counts match source\",\n        ),\n        CutoverStep(\n            order=4,\n            name=\"Enable Databricks pipelines\",\n            duration_minutes=30,\n            owner=\"Data Engineer\",\n            rollback_procedure=\"Disable Databricks pipelines, re-enable source\",\n            verification=\"Jobs running successfully\",\n        ),\n        CutoverStep(\n            order=5,\n            name=\"Update downstream applications\",\n            duration_minutes=60,\n            owner=\"Application Team\",\n            rollback_procedure=\"Revert connection strings\",\n            verification=\"Applications reading from Databricks\",\n        ),\n        CutoverStep(\n            order=6,\n            name=\"Monitor and validate\",\n            duration_minutes=240,\n            owner=\"Data Engineer\",\n            rollback_procedure=\"Execute full rollback if issues\",\n            verification=\"All metrics within acceptable range\",\n        ),\n    ]\n\n    # Calculate timings\n    current_time = cutover_date\n    for step in steps:\n        step.start_time = current_time\n        step.end_time = current_time + timedelta(minutes=step.duration_minutes)\n        current_time = step.end_time\n\n    return steps\n```\n\n## Output\n- Migration assessment complete\n- Schema migration automated\n- Data migration pipeline ready\n- ETL conversion scripts\n- Cutover plan documented\n\n## Error Handling\n| Issue | Cause | Solution |\n|-------|-------|----------|\n| Schema incompatibility | Unsupported types | Use type conversion mappings |\n| Data loss | Truncation | Validate counts at each step |\n| Performance issues | Large tables | Use partitioned migration |\n| Dependency conflicts | Wrong migration order | Analyze dependencies first |\n\n## Examples\n\n### Quick Migration Validation\n```sql\n-- Compare source and target counts\nSELECT\n    'source' as system, COUNT(*) as row_count\nFROM hive_metastore.db.table\nUNION ALL\nSELECT\n    'target' as system, COUNT(*) as row_count\nFROM migrated.db.table;\n```\n\n## Resources\n- [Databricks Migration Guide](https:\u002F\u002Fdocs.databricks.com\u002Fmigration\u002Findex.html)\n- [Delta Lake Migration](https:\u002F\u002Fdocs.databricks.com\u002Fdelta\u002Fmigration.html)\n- [Unity Catalog Migration](https:\u002F\u002Fdocs.databricks.com\u002Fdata-governance\u002Funity-catalog\u002Fmigrate.html)\n\n## Completion\nThis skill pack provides comprehensive coverage for Databricks platform operations.\n",{"name":5,"author":47,"license":15,"version":48,"description":49,"allowed-tools":50},"Jeremy Longshore \u003Cjeremy@intentsolutions.io>","1.0.0","Execute comprehensive platform migrations to Databricks from legacy systems.\nUse when migrating from on-premises Hadoop, other cloud platforms,\nor legacy data warehouses to Databricks.\nTrigger with phrases like \"migrate to databricks\", \"hadoop migration\",\n\"snowflake to databricks\", \"legacy migration\", \"data warehouse migration\".\n","Read, Write, Edit, Bash(databricks:*), Grep","main","90b50ed0778745a80fd5bfb13b1843d45b9e82f7","tests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fdatabricks-pack\u002Fskills\u002Fdatabricks-migration-deep-dive",234,"https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust","https:\u002F\u002Fgithub.com\u002FDicklesworthstone","https:\u002F\u002Fwww.jeffreyemanuel.com\u002F","Building in NY","2026-11-13 11:50:27",{"source":8,"skillName":5,"commands":61,"prompt":71,"zipAvailable":72},[62,65,68],{"tool":63,"command":64},"npx","npx skills add Dicklesworthstone\u002Fpi_agent_rust --skill databricks-migration-deep-dive",{"tool":66,"command":67},"bunx","bunx skills add Dicklesworthstone\u002Fpi_agent_rust --skill databricks-migration-deep-dive",{"tool":69,"command":70},"pnpm","pnpm dlx skills add Dicklesworthstone\u002Fpi_agent_rust --skill databricks-migration-deep-dive","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fdatabricks-pack\u002Fskills\u002Fdatabricks-migration-deep-dive\u002FSKILL.md",true,[],[75,115,139,164,191,213],{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":79,"licenseFileUrl":80,"sourceHtmlUrl":81,"categories":82,"keywords":88,"publishedAt":42},"01M6FEGPPK0ZTKCCM0R3E3KS33","web-artifacts-builder","Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn\u002Fui). Use for complex artifacts requiring state management, routing, or shadcn\u002Fui components - not for simple single-file HTML\u002FJSX artifacts.","Apache-2.0","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Futilities\u002Fweb-artifacts-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Futilities\u002Fweb-artifacts-builder\u002FSKILL.md",[83],{"categoryNo":84,"categoryName":85,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,37,107,108,109,110,111,112,113,114],"web artifacts builder","web","artifacts","artifacts builder","builder","frontend","css","components","react","component","routing","state management","state","shadcn","file","ui","Tools","Tailwind","html","single-file","simple","ui components","multi","for","jsx","suite",{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":79,"licenseFileUrl":119,"sourceHtmlUrl":120,"categories":121,"keywords":126,"publishedAt":42},"01M6FEE9VTK1W4GY21AKREJXRG","webapp-testing","Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fsecurity\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fsecurity\u002Fwebapp-testing\u002FSKILL.md",[122,125],{"categoryNo":123,"categoryName":124,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":84,"categoryName":85,"taxonomyType":86,"taxonomyTypeDesc":87},[127,128,129,94,130,131,90,132,133,134,104,135,136,137,138,29,112],"testing","webapp testing","webapp","screenshots","playwright","debugging","toolkit","browser","logs","applications","behavior","local",{"skillNo":140,"name":141,"nameZh":6,"description":142,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":143,"sourceHtmlUrl":144,"categories":145,"keywords":146,"publishedAt":42},"01M6FE20F7ZTQBFWKF4MPJ2SBX","neuropixels-analysis","Neuropixels neural recording analysis. Load SpikeGLX\u002FOpenEphys data, preprocess, motion correction, Kilosort4 spike sorting, quality metrics, Allen\u002FIBL curation, AI-assisted visual analysis, for Neuropixels 1.0\u002F2.0 extracellular electrophysiology. Use when working with neural recordings, spike sorting, extracellular electrophysiology, or when the user mentions Neuropixels, SpikeGLX, Open Ephys, Kilosort, quality metrics, or unit curation.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fneuropixels-analysis\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fneuropixels-analysis\u002FSKILL.md",[],[147,148,149,150,36,151,152,153,37,154,155,156,157,158,159,160,29,161,162,163,112,26],"analysis","neuropixels analysis","spike","metrics","open","quality","user","recordings","Neural","motion","visual","quality metrics","unit","sorting","curation","recording","load",{"skillNo":165,"name":166,"nameZh":6,"description":167,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":79,"licenseFileUrl":168,"sourceHtmlUrl":169,"categories":170,"keywords":174,"publishedAt":42},"01M6FDP0PDK6F1GGX395C7625Z","skill-creator","Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fskill-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fskill-creator\u002FSKILL.md",[171],{"categoryNo":172,"categoryName":173,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000023","Skill与智能体开发",[175,176,177,178,179,180,181,182,183,184,185,186,187,188,29,112,189,26,190],"skill creator","creator","workflows","create","update","capabilities","knowledge","tool","integrations","specialized","guide","new skill","existing skill","users","Existing","new",{"skillNo":192,"name":193,"nameZh":6,"description":194,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":195,"sourceHtmlUrl":196,"categories":197,"keywords":199,"publishedAt":42},"01M6FDM8Y7VK7NYG9SM7QPA3PW","notebooklm","Use this skill to query your Google NotebookLM notebooks directly from Claude Code for source-grounded, citation-backed answers from Gemini. Browser automation, library management, persistent auth. Drastically reduced hallucinations through document-only responses.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fnotebooklm\u002FLICENSE","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fnotebooklm\u002FSKILL.md",[198],{"categoryNo":172,"categoryName":173,"taxonomyType":86,"taxonomyTypeDesc":87},[193,200,201,202,203,204,205,134,206,207,37,208,209,210,211,112,212],"google","browser automation","gemini","automation","auth","code","library","management","only","document","query","Citation","source",{"skillNo":214,"name":215,"nameZh":6,"description":216,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":79,"licenseFileUrl":217,"sourceHtmlUrl":218,"categories":219,"keywords":226,"publishedAt":42},"01M6FDHPXE10J3XGTCH5HBHS1M","slack-gif-creator","Knowledge and utilities for creating animated GIFs optimized for Slack. Provides constraints, validation tools, and animation concepts. Use when users request animated GIFs for Slack like \"make me a GIF of X doing Y for Slack.\"","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fenterprise-communication\u002Fslack-gif-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fenterprise-communication\u002Fslack-gif-creator\u002FSKILL.md",[220,223],{"categoryNo":221,"categoryName":222,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000005","邮件与沟通",{"categoryNo":224,"categoryName":225,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000016","图像与多媒体",[227,228,229,176,230,105,231,232,181,37,233,188,234,235,236,112,237,26],"slack gif creator","slack","gif","validation","constraints","Animation","me","make","Utilities","concepts","request"]