Synapse Migration
MicrosoftOfficialPublished by Microsoft
- Skill
- Workflow
- Software development
- MIT
- Low risk
- Has scripts
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The synapse-migration skill provides a structured, phased workflow for transitioning Synapse Analytics workspaces to Microsoft Fabric. It covers the migration of Spark items, Lake Databases, Linked Services, and Dedicated SQL Pool schema and stored procedures. The skill emphasizes a dependency-ordered approach, requiring gap assessment and explicit approval before conversion. It distinguishes between migrating to a Fabric Lakehouse (schema and code only, no data movement) and a Fabric Warehouse, while providing specific routing for dependent pipeline callers.
What it does
- Discovers and classifies Synapse workspace artifacts.
- Converts Dedicated SQL Pool schema and stored procedures to Spark SQL notebooks or Warehouse objects.
- Migrates Spark items, including notebooks and Spark Job Definitions, to Fabric equivalents.
- Maps Linked Services to Fabric Data Connections or OneLake Shortcuts.
- Manages the migration of approved dependent pipeline callers.
- Validates persisted definitions and artifacts against established contracts.
When to use it
- When migrating a full Synapse workspace to Microsoft Fabric.
- When converting Dedicated SQL Pool schema and procedures to a Lakehouse or Warehouse.
- When porting Spark pools, notebooks, or Spark Job Definitions to Fabric.
- When replacing Synapse Linked Services with Fabric-native connectivity.
Advantages
- Ensures dependency-ordered migration to maintain system integrity.
- Provides clear routing for different workload types (Lakehouse vs. Warehouse).
- Enforces strict validation and approval gates for behavior-changing decisions.
- Supports incremental migration rather than high-risk big-bang cutovers.
- Standardizes the conversion of T-SQL procedures to executable Spark SQL notebooks.
Usage examples
- “Migrate this Dedicated SQL Pool DACPAC to a Fabric Lakehouse and convert the procedures.”
- The agent will assess gaps, obtain approval for procedure-to-notebook mappings, create a migration manifest, convert schema/code artifacts, and validate the results.
- “Migrate this Dedicated SQL Pool to Fabric Warehouse.”
- The agent will assess DDL compatibility, remove unsupported distribution/index declarations, obtain provisioning consent, and prepare for potential data migration.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/microsoft/synapse-migration/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip synapse-migration.zip -d .agents/skills
Documentation by Microsoft
Telemetry — MANDATORY. Every
api.fabric.microsoft.comcall must carryx-ms-fabric-skill: synapse-migration(az rest:--headers "x-ms-fabric-skill=synapse-migration"), including every LRO poll,fabric_lroand retry. Snippets omit it — add it anyway.
OFFLINE LAKEHOUSE ARTIFACT FAST PATH — DECIDE FIRST. For a no-live-call request with complete supplied inputs and contracts, load only the fast path; do not load
migration-planning-reference.md,dedicated-pool-conversion.md, or implementation scripts. Use one generator for artifacts and final-byte hashes, then one verifier. Do not inspect generated files or run post-pass spot checks. For every optional non-null source default, setmissingValueBehaviortoUseSourceDefaultand restore that default before validation. Do not use this path for a Warehouse target; incomplete and large-procedure requests use their own routes.
CRITICAL NOTES
To find workspace details (including its ID) from a workspace name: list all workspaces, then use JMESPath filtering.
To find item details (including its ID) from workspace ID, item type, and item name: list all items of that type in that workspace, then use JMESPath filtering.
Treat a source Dedicated SQL Pool as read-only. Do not run source DDL, DML, stored procedures, or create sample objects.
Dedicated Pool-to-Lakehouse data movement is out of scope. Migrate schema and executable code artifacts only; do not copy source rows or run row-level/business-result equivalence queries. The separate Warehouse route may move data only from a separately approved restored export copy under its own consent gate and restored-source contract.
For Dedicated Pool-to-Lakehouse requests, complete gap assessment, explicit mapping approval, manifest creation, conversion, deployment, and validation in order. Read dedicated-pool-to-lakehouse.md once as the router, then load only the current phase reference.
Stored-procedure
1:1,N:1, andN:Nmappings never apply to views. Views remain schema objects; procedures become traceable Spark SQL notebooks with executable%%sqltransformation cells.Dependent ADF/Synapse callers are conditional scope, not automatic scope. Discover them during assessment, require a separate complete-closure approval, and migrate them only after notebook readiness. Route standalone pipeline requests to
pipeline-migration.Before executing a specialized Dedicated Pool workflow, read the matching contract in dedicated-pool-execution-contracts.md. Its validation, hashing, request-body, resume, and completion-language requirements are mandatory.
Keep Lakehouse and Warehouse paths separate. If the target is unclear, ask before loading path-specific resources. Lakehouse conversion never moves source rows; Warehouse data migration requires its own explicit consent gate and restored-source contract.
For a Fabric Warehouse target, explicitly state that the complete
DISTRIBUTIONandCLUSTERED COLUMNSTORE INDEXdeclarations are removed because Fabric manages distribution, storage, and indexing; a bare mention of either source clause is insufficient.Run setup DDL and CETAS only against the separately approved restored export copy after proving it is not the original production source.
Synapse Analytics to Microsoft Fabric Migration
Core Workflow
Discover the Synapse workspace and classify every source artifact.
Choose targets using workload-routing.md.
Assess gaps before conversion, including runtime, library, connectivity, T-SQL, security, and capacity constraints.
Obtain approval for behavior-changing decisions, target placement, and every stored-procedure-to-notebook mapping.
Create or update
migration-manifest.jsonand persist approval, per-object status, hashes, and checkpoints atomically.Convert and deploy in dependency order, loading only the current phase resource.
Validate persisted definitions and artifacts without executing generated notebooks or pipelines unless a separately approved workflow explicitly requires execution.
Report completed, blocked, skipped, and pending objects without exposing credentials or sensitive values.
For full-workspace orchestration, read migration-orchestrator.md. For a Dedicated Pool-to-Lakehouse migration, use dedicated-pool-to-lakehouse.md as the phase router. For a Warehouse target, load only the matching dw-* resource.
Scope Routing
| Request | Action | Load |
|---|---|---|
| Full Synapse workspace migration | Run phased discovery and migration | migration-orchestrator.md |
| Dedicated SQL Pool schema/code to Lakehouse | Run the strict assessment-to-validation workflow. For guidance-only notebook publication, explicitly state: "The stored procedures were converted from T-SQL to Spark SQL before publication." | dedicated-pool-to-lakehouse.md |
| Guidance-only Dedicated Pool incremental deployment hardening | Answer directly from the focused checklist; do not search scripts or load phase resources. State: "For columns with special characters, enable Delta columnMapping selectively and only with approval." | dedicated-pool-execution-contracts.md |
| Large or complex stored procedure | For a complete offline contract, read only the audit resource once, use one run-local generator and one verifier, do not inspect implementation scripts or generated outputs, and stop after successful verification | dedicated-pool-large-procedure-audit.md |
| Spark pool | Convert configuration and libraries to a Fabric Environment | spark-pool-migration.md |
| Lake Database or HMS | Create or bind the target Lakehouse | lake-database-migration.md or external-hms-migration.md |
| Notebook or Spark Job Definition | Port code, bindings, parameters, and runtime settings | spark-item-migration.md |
| Linked Service | Choose a Fabric Data Connection for external services or a OneLake Shortcut for ADLS Gen2/Blob | connectivity-migration.md |
| Approved dependent procedure callers | Run the internal closure-preserving sub-flow after notebook readback | dedicated-pool-dependent-pipelines.md |
| Standalone pipeline migration | Delegate | pipeline-migration |
| Dedicated SQL Pool to Fabric Warehouse | Run the source extraction, DDL compatibility, approval, optional data, security, and validation route | dw-source-and-extraction.md, then the matching dw-* phase resource |
| Standalone Fabric Warehouse administration | Delegate | sqldw-cli |
| Synapse Link | Use Fabric Mirroring; not covered here | — |
Always report the Lake Database/HMS phase. If none is discovered, mark it NotApplicable (none discovered) while retaining the required target Lakehouse binding.
Load References On Demand
Do not preload all files. Load only the references needed for the current phase:
| Need | Reference |
|---|---|
| Routing, phase order, API audiences, quick examples, troubleshooting, or post-migration handoff | workload-routing.md |
| Dedicated Pool execution variants and response contracts | dedicated-pool-execution-contracts.md |
| Dedicated Pool discovery | dedicated-pool-discovery.md |
| Gap assessment and mapping approval | dedicated-pool-gap-assessment.md |
| Procedure conversion and notebook shape | dedicated-pool-conversion.md |
| Schema/notebook deployment | dedicated-pool-deployment.md |
| Dedicated Pool validation | dedicated-pool-validation.md |
| Runtime/library compatibility | feature-parity.md and library-compatibility.md |
mssparkutils and connector refactoring | utility-api-mapping.md, connector-refactoring.md, and code-patterns.md |
| Capacity planning | capacity-sizing.md |
| Dedicated Pool-to-Warehouse source discovery and extraction | dw-source-and-extraction.md |
| Warehouse DDL compatibility and deployment | dw-ddl-compatibility.md |
| Separately approved Warehouse data migration | dw-data-migration.md |
| Warehouse security and validation | dw-security-validation.md |
| Validation, reporting, and production readiness | validation-testing.md, migration-report.md, and security-governance.md |
Use COMMON-CLI.md only for shared authentication and az rest mechanics not already covered by the phase resource. Use COMMON-CORE.md only for shared Fabric REST patterns.
Must
Preserve every stored-procedure input contract, source default, source decision, and approved target mapping.
Block conversion until gap dispositions, notebook names, dependency grouping, and target workspace placement are explicitly approved.
Use SqlPackage/DMVs for source discovery, Fabric REST for item management, and Fabric Livy statements for Lakehouse schema and Delta execution.
Run the maintained validators required by the selected execution contract; never replace them with ad hoc JSON or cell-shape checks.
Choose the Lakehouse or Warehouse target before loading implementation resources; never apply Warehouse data-movement rules to Lakehouse artifact conversion.
Before persisting any dependent-pipeline source definition, recursively inspect it for secret-bearing or uncertain properties; block the complete selected closure without writing the artifact or mutating a target when any are found.
In every dependent-pipeline response, including guidance-only and pre-approval explanations, state: "Use a
TridentNotebookactivity with exact target identitiestypeProperties.notebookIdandtypeProperties.workspaceId, and pass inputs throughtypeProperties.notebookParameters." Then state: "After deployment, read back each pipeline withPOST /v1/workspaces/{workspaceId}/items/{dataPipelineId}/getDefinitionand validate its canonical hash and structural bindings."For every Linked Service response, first state both replacement classes: Fabric Data Connections for external databases/services and OneLake Shortcuts for ADLS Gen2/Blob storage; then identify which class applies.
Replace
mssparkutilswithnotebookutils, Linked Services with the correct Fabric connection class, andspark.read.synapsesql()with a supported OneLake or JDBC pattern.Externalize workspace and item IDs through parameters or Variable Libraries.
Keep phase status concise, emit bounded heartbeats for long operations, and persist per-object evidence in the manifest.
Prefer
OneLake Shortcuts over copying data.
Fabric Environments for reproducible libraries and Spark settings.
Incremental, dependency-ordered migration over big-bang cutover.
Parameterized notebooks and Variable Libraries for environment promotion.
Lakehouse SQL Endpoint for compatible Serverless SQL Pool read workloads.
Avoid
Do not execute generated notebooks or pipelines as part of artifact migration.
Do not broaden a selected dependent-pipeline closure or route that internal sub-flow to
pipeline-migration.Do not use
sqlcmdagainst the target Fabric Warehouse; use the registered SQL endpoint tooling required by the Warehouse resource.Do not preserve Synapse distribution/storage hints, PolyBase DDL, Linked Service connection strings, or pool-level library installation patterns verbatim.
Do not use target notebooks to orchestrate the migration itself.
Do not hardcode workspace IDs, item IDs, credentials, connection strings, or environment-specific paths.
Examples
Prompt: "Migrate this Dedicated SQL Pool DACPAC to a Fabric Lakehouse and convert the procedures."
Response behavior: Assess gaps first, present and obtain approval for the complete procedure-to-notebook mapping and workspace placement, create the manifest, convert approved schema/code artifacts without moving source rows, validate persisted definitions, and report the resolved Lakehouse and artifact evidence.
Prompt: "Migrate this ADF pipeline to Fabric."
Response behavior: Route to pipeline-migration. Keep it here only when the pipeline is an explicitly approved dependent caller discovered inside an active Dedicated Pool-to-Lakehouse migration.
Prompt: "Migrate this Dedicated SQL Pool to Fabric Warehouse."
Response behavior: Keep this inside synapse-migration, assess DDL compatibility, remove unsupported distribution and columnstore declarations, obtain provisioning consent, and ask separately before any restored-source data migration.
For code transformations and edge cases, load workload-routing.md and the phase-specific resource rather than expanding the main instructions.
Files
- ATTRIBUTION.mdAdded by AutoGineer879 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md14.3 KiB
- apm.yml597 B
- references/dedicated-pool-execution-contracts.md14.5 KiB
- references/workload-routing.md6.0 KiB
- resources/capacity-sizing.md4.1 KiB
- resources/code-patterns.md8.4 KiB
- resources/connectivity-migration.md6.4 KiB
- resources/connector-refactoring.md13.8 KiB
- resources/dedicated-pool-conversion.md39.2 KiB
- resources/dedicated-pool-dependent-pipelines.md23.3 KiB
- resources/dedicated-pool-deployment.md20.0 KiB
- resources/dedicated-pool-discovery.md17.8 KiB
- resources/dedicated-pool-gap-assessment.md17.4 KiB
- resources/dedicated-pool-large-procedure-audit.md24.5 KiB
- resources/dedicated-pool-to-lakehouse.md17.9 KiB
- resources/dedicated-pool-validation.md17.2 KiB
- resources/dw-data-migration.md13.7 KiB
- resources/dw-ddl-compatibility.md9.4 KiB
- resources/dw-security-validation.md15.6 KiB
- resources/dw-source-and-extraction.md8.0 KiB
- resources/external-hms-migration.md20.2 KiB
- resources/feature-parity.md5.4 KiB
- resources/lake-database-migration.md34.8 KiB
- resources/library-compatibility.md7.2 KiB
- resources/migration-gotchas.md16.1 KiB
- resources/migration-orchestrator.md63.0 KiB
- resources/migration-planning-reference.md16.3 KiB
- resources/migration-report.md16.9 KiB
- resources/security-governance.md47.4 KiB
- resources/spark-item-migration.md19.2 KiB
- resources/spark-pool-migration.md16.3 KiB
- resources/utility-api-mapping.md5.4 KiB
- resources/validation-testing.md14.5 KiB
- scripts/Invoke-DedicatedPoolTool.ps1Script941 B
- scripts/dedicated-pool-tool/DedicatedPoolMessageSanitizer.csScript2.1 KiB
- scripts/dedicated-pool-tool/DedicatedPoolTool.csproj346 B
- scripts/dedicated-pool-tool/Program.csScript31.4 KiB
- scripts/dedicated_pool_runtime.pyScript116.9 KiB
- scripts/validate_dedicated_pool_spark.pyScript24.8 KiB
resources/dedicated-pool-large-procedure-audit.md
Dedicated Pool Large-Procedure Audit
Use deterministic source-block accounting for stored procedures whose size or complexity makes whole-procedure conversion difficult to inspect. The same ledger may be used for smaller procedures. It supplements, and never relaxes, the conversion, parameter, approved mapping, validation, and read-only-source contracts.
Required Outcome
Prove that every non-empty source span is represented by exactly one ledger block and that every block has a reviewed disposition. A notebook is not complete merely because it parses or contains executable Spark SQL.
Retain source audit, operational logging, and diagnostic statements in the generated notebook by default. Exclude or redesign them only with explicit evidence and approval; do not silently remove them as non-business logic.
Generated Run Artifacts
Generate the preprocessing and verification scripts for each migration run under the run's artifact directory. Do not add a generic converter utility to the repository.
For an offline artifact request, resolve the output root once from the process's initial current working directory and keep every generated file, script invocation, and verification command below that root. Treat requested paths such as migration-artifacts/<run> as relative to that initial directory. Reading skill, source, or repository files does not change the output root: never derive it from a file that was inspected, switch to the repository or plugin directory, or write artifacts outside the active run workspace.
When the request supplies the complete immutable source, target binding, ledger/package schema, and expected dispositions, treat those inputs as the acceptance contract. Read only this resource once; do not inspect unrelated repository implementation, load other resources, or repeat resource reads. Create one run-local generator before writing any artifact. That generator must write the exact LF source, ledger, notebook, attempts, projection, package, manifest, build-block-ledger.py, and verify-conversion-package.py in dependency order, with all hashes computed from final bytes. Run the generator and verify-conversion-package.py; when both succeed, stop using tools and respond. Do not manually write or rewrite the source first, add helper scripts, install dependencies, print block slices, run standalone hash/encoding checks, view generated files, list artifacts, patch outputs, clean up, or rerun the verifier. Those invariants belong in the generated verifier.
Derive every immutable source filename and every source path recorded in the ledger, package, manifest, and verifier from the exact schema-qualified sourceStableId; never derive them from unqualified sourceName. For example, sourceStableId dbo.usp_AuditedLoad must remain source/dbo.usp_AuditedLoad.sql, not source/usp_AuditedLoad.sql.
Treat every path written into the ledger, package, projection, manifest, or attempt evidence as a POSIX path relative to the run artifact root. Never record an absolute path or prefix it with the requested output root such as migration-artifacts/<run>/. Keep each recorded constant separate from its disk path; for example, store NOTEBOOK_REL = "notebooks/usp_AuditedLoad.ipynb" in JSON and derive the disk location by joining the artifact root with the segments of NOTEBOOK_REL. Apply the same rule to source, ledger, attempt, projection, package, and manifest references.
Materialize source/<sourceStableId>.sql from the exact immutable UTF-8 source bytes before generating the block ledger, attempts, manifest projection, or deployment package. Fail closed if that exact source file is absent, has a different stable-ID path, or its hash differs from the source hash recorded by any downstream artifact. Include the source file itself in deployment-package hashes and evidence; keeping source text only in memory or embedding it only in a generated script is not sufficient.
source/
<sourceStableId>.sql
procedure-audit/
ledgers/<sourceStableId>.blocks.json
attempts/<sourceStableId>/<blockId>/attempt-<n>.json
scripts/build-block-ledger.py
scripts/verify-conversion-package.py
conversion-manifest-projection.json
deployment-package.jsonStore source text as discovery evidence only. Never put CREATE PROCEDURE, CREATE PROC, or unconverted source text in executable notebook cells.
When the request supplies an exact artifact path, preserve that path literally. Do not shorten a stable-ID source file such as source/dbo.usp_AuditedLoad.sql to source/usp_AuditedLoad.sql, even when the notebook uses the shorter procedure basename.
In the run-specific generator, assign the source artifact path from the literal requested path, not from sourceName, the notebook basename, or another derived identifier. Before deleting or replacing any output root, assert that the configured source path exactly equals the requested stable-ID path; a mismatch blocks the atomic write. After generation, the package verifier must require that exact file and reject a different source path even when its bytes and hash match.
Before packaging, verify every procedure parameter against the approved conversion contract. Optional non-null parameters must restore their declared source defaults before validation, and every approved mapping field must be copied without abbreviation into the migration manifest. Source, bridge, Spark-conf, and manifest parameter counts must match exactly or packaging is blocked.
Do not turn an optional non-null source parameter into a required notebook parameter. For example, a source declaration @BatchId BIGINT = 42 must use BatchId = 42 in the tagged parameter cell and this exact ordering in the validation-only bridge:
import re
if BatchId is None:
BatchId = 42
if re.fullmatch(r"[+-]?[0-9]+", str(BatchId)) is None:
raise ValueError("BatchId must be an integer literal")
spark.conf.set("spark.synapseMigration.dbo_usp_AuditedLoad.BatchId", str(BatchId))The BatchId is None branch restores the declared default; it must not raise ValueError. Keep every default restoration and validation guard before the first transport call, then emit only contiguous direct spark.conf.set calls.
At each Spark SQL use, quote the configuration substitution before the immediate mapped-type cast, for example CAST('${spark.synapseMigration.dbo_usp_AuditedLoad.BatchId}' AS BIGINT). The parser gate runs without executing the bridge, so an unquoted unset substitution would collapse to invalid CAST( AS BIGINT) syntax.
Deterministic Preprocessing
Read the exact discovered procedure definition as an immutable UTF-8 source artifact and record its lowercase SHA-256.
Tokenize with a T-SQL-aware parser or tokenizer. Do not split on semicolons,
GO, line count, or regular expressions alone.Remove the outer
CREATE [OR ALTER] PROCEDUREdeclaration from the executable body while retaining its source span as a non-executableProcedureDeclarationblock. Preserve the discovered parameter signature through the parameter contract.Partition the remaining body into ordered, non-overlapping blocks on parser statement boundaries. Keep compound constructs such as
BEGIN...END,TRY...CATCH,IF...ELSE,WHILE, cursor bodies, and dynamic-SQL construction together unless the parser exposes complete nested statements and parent-child relationships.Preserve comments and whitespace in source-span accounting. Attach leading comments to the following statement and trailing comments to the preceding statement. Emit explicit
CommentOnlyorWhitespaceOnlyblocks only for otherwise unattached spans.Assign each block a one-based
ordinaland stable IDB<ordinal>-<hash12>, wherehash12is the first 12 lowercase hexadecimal characters of SHA-256 oversourceStableId + "\n" + startOffset + ":" + endOffset + "\n" + exactSourceSlice. Offsets are zero-based UTF-8 byte offsets with an exclusive end.Verify that sorted block spans begin at byte 0, end at the source byte length, and have no gaps or overlaps. Any accounting failure blocks conversion.
Compute the complete deterministic block IDs before constructing notebook cells, -- sourceBlock: markers, ledger targetArtifacts, attempt paths, projection entries, or package entries. Never use ordinal-only placeholders such as B2 in an emitted artifact.
Every emitted notebook cell must contain an explicit, unique nbformat id matching ^[A-Za-z0-9_-]{1,64}$; nbformat support does not make the field optional for this workflow. For each converted block, write the mapped SQL cell's exact id into targetArtifacts[].cellId. Never record a synthetic ordinal or index-derived ledger ID that is absent from the notebook cell.
For each parameterized procedure, the first notebook code cell must carry the exact parameters tag and declare scalar Python variables with their approved source defaults. Follow it with one validation-only Python bridge that restores optional defaults, validates every value, and then emits only contiguous direct spark.conf.set calls with scalar string values. Reject every %%configure cell and every object-valued parameter map. Record the source parameter as sourceParameter in the migration manifest; never use parameterName.
Do not ask a language model to choose source boundaries or block IDs. Generated scripts must produce the same ledger for identical source bytes and configuration.
Source-Block Ledger
Each *.blocks.json file must include:
schemaVersion,sourceStableId,sourceSchema,sourceName,sourceHash,sourceByteLength,parser, andgeneratedAtretryPolicywithmaxAttemptsPerBlockandretryableStatesblocks, ordered byordinalcoveragewith byte totals, block totals by disposition, andcoveragePercentverificationwith gap, overlap, hash, retry-limit, and terminal-disposition results
Each block record must include:
blockId,ordinal,parentBlockId,kind,startOffset,endOffset, andsourceHashsourceFeatureIds,gapIds,dependencies, andparameterReferencestargetArtifactsas a JSON array. For a converted block, include one or more objects withnotebookPath,cellId, andtargetStatementHash; never emit a single object. For a block with no target mapping, emit[], notnull.disposition,reason,approvalEvidence,attemptCount, andattemptHistoryvalidationwith parser, forbidden-construct, parameter, dependency, and reviewer results
Use this exact shape for each converted mapping:
"targetArtifacts": [
{
"notebookPath": "notebooks/<procedure>.ipynb",
"cellId": "<cell-id>",
"targetStatementHash": "<lowercase-sha256>"
}
]Any generated ledger rebuild or preprocessing script must preserve or deterministically regenerate this complete block-record schema, including targetArtifacts, disposition, attempt evidence, and validation state. It must not overwrite an enriched post-conversion ledger with boundary-only discovery records. If rebuilding boundaries changes or removes any converted block's notebook path, cell ID, or target statement hash, fail verification and block packaging instead of writing the reduced ledger.
Use only these dispositions:
| Disposition | Meaning | Deployable |
|---|---|---|
Pending | Not yet converted or assessed | No |
Converted | Represented by validated target Spark SQL | Yes |
ApprovedExclusion | Intentionally omitted with recorded owner, rationale, and approval | Yes |
ManualReviewRequired | Automatic conversion cannot preserve behavior | No |
ManualReviewApproved | Reviewed target mapping or redesign is recorded and validated | Yes |
Failed | Conversion or validation failed | No |
ProcedureDeclaration, CommentOnly, and WhitespaceOnly blocks still require a disposition. They may use ApprovedExclusion only with the standard generated rationale and policy approval recorded for non-executable syntax or formatting. Audit/logging statements are executable behavior and must not use that automatic exclusion.
Block Conversion and Bounded Repair
Convert blocks in dependency order with the procedure signature, approved design, neighboring block summaries, and referenced object metadata as context. Keep batches bounded by block count or source bytes; do not truncate a block to fit a model context window.
After each attempt:
Validate only the target statements mapped from that block with the target Spark parser and all conversion-contract checks.
Record the prompt/input hash, generated target hash, validator results, sanitized error, timestamps, and attempt number. Create one attempt file for each
attemptHistoryentry and no others. A block excluded without a conversion attempt hasattemptCount: 0, an emptyattemptHistory, and no attempt file; do not manufacture attempt files forProcedureDeclaration,CommentOnly,WhitespaceOnly, or other approved exclusions.Mark successful blocks
Converted; route unsupported semantics toManualReviewRequiredwith a precise finding.Retry only blocks in a declared retryable state. Do not regenerate successful blocks during repair.
Allow at most three total attempts per block by default (
maxAttemptsPerBlock: 3). A lower run-specific limit is allowed. Never increase the limit after conversion begins.Mark an exhausted block
Failedand block packaging. Do not hide it behind a warning, skip, or whole-procedure success status.
When a repaired block changes target dependencies, parameters, or control-flow interfaces, revalidate its directly related blocks without incrementing their conversion attempt counts unless their target text is regenerated.
Canonical Notebook Metadata
For every assembled large-procedure notebook, emit the Lakehouse binding only at metadata.dependencies.lakehouse. It must contain default_lakehouse, default_lakehouse_workspace_id, and default_lakehouse_name with the resolved target values. Never add, copy, retain, or mirror that binding under metadata.trident.lakehouse, even when the canonical dependency binding is also present. Run validate_spark_sql_notebook against this final assembled notebook before hashing or packaging it; any alternate Lakehouse-binding path blocks packaging.
Build each Python cell as newline-joined source and serialize it with splitlines(keepends=True), so every non-final source entry retains its line terminator. Never emit adjacent Python source-array strings that concatenate into invalid syntax. Inside the one-shot generator, run ast.parse on the joined parameter-cell and bridge-cell source before writing any artifact; a parse failure must abort the generator before it emits a partial package.
Coverage and Cross-Block Validation
Before packaging, require all of the following:
Source byte coverage is exactly 100%, with no gaps, overlaps, duplicate block IDs, or changed source hashes.
Every block is
Converted,ApprovedExclusion, orManualReviewApproved.Every converted or manually approved block maps to at least one existing target notebook cell and target statement hash. Give each mapped SQL cell a
-- sourceBlock: <blockId>line immediately after%%sql. Assemble and serialize the final notebook cell first, then re-read that persisted cell, remove exactly the%%sqlline and the following source-block marker line, and computetargetStatementHashfrom every remaining UTF-8 byte, including any terminal newline. Never hash a pre-serialization statement variable or trim/normalize the payload. The producer and independent verifier must both recompute from the persisted notebook, not from shared generation state.Ensure the generated cell itself begins with the two literal percent characters in
%%sql. Do not pass that magic through Python%interpolation as"%%sql", which emits only%sql; concatenate the literal header or escape it as"%%%%sql"when%formatting is unavoidable. Apply the normal conversion type mapping inside every cell, including translating sourceBITpredicates such asIsActive = 1to Spark SQLIsActive = TRUE.After any generated ledger rebuild or preprocessing script runs, re-read the persisted ledger and reject every converted block whose
targetArtifactsis missing, null, not an array, or lacks an existing notebook cell ID and matching target statement hash. Run this check before computing ledger and deployment-package hashes.Every target transformation statement maps back to one or more source block IDs; generated scaffolding is labeled separately and justified.
Control-flow, temporary-object, dependency, parameter, output, transaction-redesign, dynamic-SQL, error-handling, and audit/logging relationships are validated across block boundaries.
Notebook-level parser, parameter, naming, dependency, forbidden-construct, and nbformat checks still pass after block assembly.
Attempt counts do not exceed the immutable retry policy, every recorded attempt has exactly one attempt file, and no unrecorded attempt files exist.
Attempt files and deployment-package
attemptsentries exist forConvertedblocks only. Their paths and lowercase SHA-256 hashes form the exact one-to-one set of converted block IDs; do not emit attempt evidence forApprovedExclusionblocks.
Coverage percentage is accounted source bytes / sourceByteLength * 100. It measures source accounting, not semantic equivalence. Do not claim runtime or data parity from a 100% ledger.
Immutable Deployment Package
Generate deployment-package.json only after the ledger and notebook pass all checks. Include:
package schema version, run ID, source inventory hash, approved gap-report hash, and generation timestamp
each source procedure hash and ledger hash
each notebook path, exact approved display name and workspace, byte hash, canonical content hash, contributing procedure IDs, and contributing block IDs
canonical conversion-manifest projection hash and all required SQL artifact hashes. Build the projection from stable source mappings, approved design, dependencies, parameters, target artifact paths/content hashes, ledger hashes, and approval evidence; exclude the deployment-package fields themselves plus deployment/readback state, operation IDs, attempts, and timestamps
validator version/configuration hashes, retry policy, coverage totals, approval evidence, and package verdict
The package root must contain exactly these publication-gate fields at minimum: "verdict": "ReadyForPublication", numeric "coveragePercent": 100, and "retryPolicy": { "maxAttemptsPerBlock": 3, ... } when the default retry limit applies. Serialize coveragePercent as the JSON integer 100, not 100.0, a string, or a boolean; likewise serialize maxAttemptsPerBlock as the JSON integer 3, not 3.0, a string, or a boolean. Do not place the package's only coveragePercent inside a nested coverage object; nested coverage details may be additional evidence, but they do not replace the required root property. This differs from the block ledger, where coverage.coveragePercent remains nested.
The generated package verifier must read and assert those exact root paths before reporting success. In Python, require type(package["coveragePercent"]) is int and type(package["retryPolicy"]["maxAttemptsPerBlock"]) is int before comparing their values; isinstance(..., int) is insufficient because booleans are integers in Python. It must fail when coveragePercent is absent or nested-only, or when it is not the JSON integer 100; when verdict is not ReadyForPublication; or when retryPolicy.maxAttemptsPerBlock is not the JSON integer matching the immutable run policy. Never claim the package verifier passed based only on ledger coverage or artifact hashes.
The generated verifier must independently assert every recorded path against the exact artifact-root-relative contract, resolve that path below the artifact root for file access, and recompute its lowercase SHA-256 from final file bytes. It must also prove the two-way ledger/notebook mapping: every Converted block maps to an existing cell with its full block ID and exact statement hash, and every source-mapped notebook cell maps back to one Converted block. It must parse the tagged parameter cell and validation-only scalar bridge and assert the exact declared parameter, source default, Spark-conf key, and direct str(<parameter>) transport. Finally, it must compare the package attempt paths as a set against the attempt paths derived from Converted ledger blocks; producer and verifier must not share unchecked path or membership assumptions.
Keep each audited procedure's source decision in migration-manifest.json under objects[]; preserve its exact sourceName, sourceStableId, all approved target component IDs, audit evidence, and deployment-package path/hash. Record immutable source evidence as sourcePath plus sourceArtifactHash, ledger evidence as ledgerPath plus ledgerHash, and package evidence as deploymentPackage.path plus deploymentPackage.sha256; every hash is lowercase SHA-256 of the referenced file bytes. Preserve backward-compatible target artifact fields for approved 1:1 mappings. Do not replace objects[] with a bespoke top-level procedure object.
Set verdict to ReadyForPublication only when every required object has 100% source coverage and no non-deployable block. Store the package path and package hash in the mutable migration manifest only after computing the package; those fields are excluded from the canonical conversion-manifest projection, avoiding a circular hash. Any packaged artifact or projected conversion-field change after packaging invalidates the package; regenerate validation and the package rather than editing hashes. Deployment must verify every package hash and recompute the manifest projection before any create or update operation, then publish exactly the packaged notebook bytes.
Use this exact finalization order:
Write and hash the canonical conversion-manifest projection, which excludes deployment-package fields and mutable deployment/readback state.
Write
deployment-package.jsonwith the projection path/hash and every required artifact path/hash, but no package self-hash.Compute the lowercase SHA-256 of the final
deployment-package.jsonfile bytes.Reopen the mutable
migration-manifest.jsonobject and setdeploymentPackage.pathto the package-relative path anddeploymentPackage.sha256to that computed hash. The equivalentdeploymentPackagePathanddeploymentPackageHashfields are permitted for backward compatibility.Persist the updated mutable manifest without regenerating the package, then run the package verifier again. The verifier must fail unless the recorded package path is exact and the recorded hash equals the final package-file hash.
Create one attempt file for each attemptHistory entry and no others. An ApprovedExclusion has attemptCount: 0, an empty attemptHistory, and no attempt file; do not hash attempt files for zero-attempt approved exclusions.
Retain source ledgers, attempt records, verifier output, approval evidence, and the final deployment package with the migration manifest. These artifacts are required audit evidence and must not be removed after successful publication.
Completion Report
After the final verifier passes, summarize the audited result in the response. Explicitly name the T-SQL-to-Spark SQL migration, target Lakehouse, exact notebook name, block totals and dispositions, 100% source coverage (or "100 percent source coverage"), bounded attempt results, retained audit/logging behavior, ReadyForPublication package verdict, and the no-source-row/runtime-parity boundary. Do not report only verifier counts or artifact paths; the response must state that the notebook contains executable translated Spark SQL.
The completion report must include all eight required concepts to pass verification: '100', 'coverage', 'block', 'attempt', 'audit', 'ReadyForPublication', 'usp_AuditedLoad', and 'Spark SQL'. Use phrases like "100% source coverage" or "100% coverage" (not just "complete coverage") to satisfy pattern matching.
Completion Gate
A large stored procedure is conversion-complete only when deterministic span verification passes, every block has a deployable terminal disposition, failed-block retries stay within the declared limit, cross-block and notebook validation pass, and an immutable package has verdict ReadyForPublication. Pending, ManualReviewRequired, Failed, missing attempt history, less than 100% byte coverage, an untracked target statement, or a package/hash mismatch blocks publication.
If the one-shot runtime validator fails, begin the terminal report with The T-SQL procedure was not successfully converted to Spark SQL. Name the failed gate and preserve the artifacts without claiming ReadyForPublication.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Python
Security
What our scanner noticed· Low risk
- Instructions that use the network
- Scripts that your agent may run
This skill includes scripts that your agent may run. Read them before you use it.
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Microsoft
- Publisher
- Microsoft (Official)
- Source
- microsoft/skills-for-fabric · skills/synapse-migration · commit f8fac11
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- microsoft/skills-for-fabric
AutoGineer is not affiliated with or endorsed by Microsoft or Microsoft.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download synapse-migration.zip