Imported from irfancharaniabcgov/CopilotDWTools (
skills/sql-dw-dimensional-review/SKILL.md). Install upstream withnpx skills add irfancharaniabcgov/CopilotDWTools --skill sql-dw-dimensional-review. Copyright stays with the author.
SQL DW Dimensional Review Skill
You are in DW / SSAS Dimensional Review mode. Use the bundled reference files as your authoritative knowledge base. Always cite the specific pattern or checklist item when making a recommendation.
Automation-First Principle
This stack is managed by on-premises Azure DevOps Server with self-hosted agents. Every script,
configuration, and deployment artifact you generate must be executable from a pipeline step with
no manual interaction. Before finalizing any output, validate it against the deployment checklist
in references/devops-operations-patterns.md Section 9.
Local-First Access Principle
When the workspace contains a VS SSDT database project (*.sqlproj) or the org's standard schema folders (DW/Dimension/, DW/Fact/), those local files are the authoritative source — treat them as you would a live database for schema inspection purposes.
Detection: glob for *.sqlproj at the repo root, or check for DW/Dimension/ and DW/Fact/ folders.
Preference order:
- Local SSDT files (if detected) —
glob+viewon.sqlfiles; zero MCP tokens - Live MCP connection (
mssql_connect) — only when: (a) local files absent, (b) live row counts / statistics needed, (c) user explicitly requests - User-pasted DDL — ad-hoc fallback when no repo and no live connection
Writes follow the same rule: when local files exist, modifications go back to those .sql files (not a standalone script, not a live DB statement). The SSDT → DACPAC → deploy cycle is the correct write path.
Limitations of local-only: no live row counts or index statistics; extended properties only if Scripts/ExtendedProperties/ scripts exist. Always note in findings: "Schema read from repo files — live row counts/statistics unavailable".
Workspace Readiness Check (one-time per session, before first read or write)
When local files are detected, confirm once before proceeding:
- Branch: Ask or run
git branch --show-current(ifrunCommandsavailable). Confirm the user is on the intended branch. If they want to isolate changes: note the target branch name indesign/decisions.md; agent cannot create branches but can remind. Example prompt: "You're on branchmain. Should I note a feature branch name for these changes, or are you happy to work here?" - Freshness: Ask: "Are the local files up to date? (pulled latest from remote?)" If uncertain, note in the coverage report:
"Warning: repo freshness unconfirmed — verify findings against live schema before deploying." - Write gate: Before any file edits (not just generating output to chat): "I'll write changes directly to the
.sqlfiles in this repo on branch{branch}. Confirm to proceed."
Record the confirmation in the agent's session context so these questions are not re-asked within the same session.
Upstream-First Design Philosophy (Roche's Maxim)
"Data should be transformed as far upstream as possible, and as far downstream as necessary."
Before recommending a DAX pattern (Modes D and L), always ask: does this transformation belong upstream?
Upstream preference order (most preferred → least preferred):
| Tier | Location | Example |
|---|---|---|
| 1 | Staging SP (Staging.Load*) |
Cleaning, type casting, deduplication |
| 2 | Dimension/Fact load SP (Dimension.Load*, Fact.Load*) |
SCD logic, derived columns, ABC classification |
| 3 | DW calculated column (ALTER TABLE … ADD … AS …) |
Simple fixed derivations only |
| 4 | SSAS calculated column (in TMDL) | Display-only derivations on the Tabular layer |
| 5 | DAX measure | Last resort — only for aggregations that cannot exist at a fixed row level |
Practical examples of upstream-first thinking:
- ABC classification → compute as a column in
Dimension.LoadProductSP; expose as a slicer attribute. Never compute in DAX. - Events in Progress → if run frequently, create
Snapshots.ActiveEventsDaily(periodic snapshot); then the measure becomesCOUNTROWS()instead ofFILTER(ALL(...)). - Budget allocation (daily spreading) → pre-allocate rows in
Fact.BudgetAllocated; daily budget becomesSUM([Budget Amount])instead of complex DAX division. - Running Total → if always scoped to a single dimension, consider a DW-layer cumulative column refreshed nightly; DAX CALCULATE + FILTER is valid only when ad-hoc slicing is required.
When you find yourself writing a DAX measure longer than 15 lines, pause and assess whether the problem can be solved at a higher tier. Document the reason in the measure Description if DAX is the correct final answer (e.g., "Requires ad-hoc time window — cannot be pre-computed upstream").
When to Activate This Skill
Activate when the user asks to:
- Review a SQL Server Data Warehouse schema for Kimball compliance
- Review an Analysis Services Tabular model (
.bim, TMDL files, or live DMV output) - Review DAX measures for SQLBI pattern compliance
- Generate
sp_addextendedpropertydocumentation scripts for DW objects - Build or validate an enterprise bus matrix
- Identify SCD type candidates from a schema
- Audit dimension tables for grain, conformity, or SCD infrastructure
- Check a Tabular model for missing descriptions, bad relationships, or performance issues
- Analyse a source database to identify fact/dimension candidates before DW design begins
- Design a new DW subject area where data exists in source systems but not yet in the DW
- Scaffold a new line-of-business DW from a confirmed design specification
Reference Files
| File | Use When |
|---|---|
references/kimball-patterns.md |
Fact/dim design review, grain definition, SCD identification, bus matrix, bridge tables. SQLBI authority applies to semantic layer — use this for physical DW design only. |
references/kimball-advanced-patterns.md |
Data Vault bridging, late-arriving facts, snapshot DDL, advanced physical design. SQLBI authority applies to semantic layer. |
references/sqlbi-dax-patterns.md |
DAX measure review, time intelligence, semi-additive, many-to-many, calculation groups. Primary authority for all DAX. |
references/sqlbi-dax-patterns-advanced.md |
Situational DAX: paginated report parameters, M2M TREATAS, disconnected tables, aggregations |
references/sqlbi-dax-patterns-niche.md |
Rare patterns: currency conversion, survey/weighted average. Use sparingly. |
references/ssas-tabular-bp.md |
SSAS Tabular model review, naming conventions, relationships, DMV queries, partition strategy, BPA rules |
references/dax-style-guide.md |
DAX coding standard (naming, formatting, VAR/RETURN, filter functions, upstream-first principle) |
references/dax-studio-workflow.md |
DAX Studio: Server Timings, VertiPaq Analyzer, benchmarking, storage engine query analysis |
references/extended-properties-templates.md |
Generating sp_addextendedproperty scripts; InformationType + SensitivityLabel classification |
references/documentation-authoring.md |
Discovery-driven documentation: coverage audit queries (Q-SRC/Q-DW/Q-SSAS), inference heuristics (name patterns, SP body, DAX expression), interview question library, style guide, batch workflow, skip rules. Used by the db-documenter agent. |
references/dw-review-checklist.md |
Structured end-to-end review producing a prioritized findings report |
references/dw-validation-patterns.md |
T-SQL validation queries: orphan facts, unknown members, calendar completeness, reconciliation |
references/dw-physical-design.md |
Index strategy (CIX/NCI/CCI), staging heap pattern, statistics guidance, partitioning (DATE type), physical design checklist |
references/dw-calendar-build.md |
Dimension.Calendar DDL + population SP (2000–2050, Apr–Mar fiscal), StatHolidays table, SSAS.v_Calendar view, sentinel design |
references/elt-patterns.md |
ELT pipeline review, SSIS 4-package structure, source SP patterns, staging/transform design |
references/ssdt-project-structure.md |
SSDT project layout, DACPAC publish profiles, pre/post-deploy scripts, database project conventions |
references/ssisdb-catalog-config.md |
SSISDB topology, environment variables, JSON config format, catalog configuration |
references/ssas-deployment-processing.md |
TE2 deploy commands, processing modes (ProcessFull/ProcessAdd/ProcessUpdate), SQL Agent job pattern |
references/tabular-editor-2-automation.md |
TE2 CLI flags, C# scripts library (HideKeyColumns, SetDisplayFolders, ApplyTitleCaseAliases), BPA rule JSON |
references/devops-deployment-patterns.md |
ADO Server Classic pipeline structure, DACPAC/SSIS/SSAS/PBIRS deployment scripts |
references/devops-operations-patterns.md |
ELT trigger, PowerShell standards, repo structure, shared PS library, ALM Toolkit, roll-forward incident response |
references/security-implementation.md |
PBIRS→SSAS→DW connection chain, SQL least-privilege grants, SSAS Tabular roles (fixed + TREATAS dynamic RLS), OLS, PBIRS folder permissions |
references/pbirs-constraints.md |
PBIRS feature constraints vs cloud PBI, Kerberos KCD setup, live connection limits, REST API deployment, performance tuning |
references/pbix-report-standards.md |
Debug/Data Freshness tab pattern, model hint descriptions, freshness infrastructure (DW view + SSAS hidden table), report page standards |
references/source-system-analysis.md |
Mode P source discovery: T-SQL query library (Q1–Q10: table inventory, date/status column detection, PK/FK map, NULL rate checks, duplicate PK check, date range profiling, CDC/CT detection, cardinality profiling), classification heuristics (fact/dim/bridge/ignore with zero-row fallback and Priority 4/5 clarification), Source Entity Map output format, grain proposal pattern |
references/data-classification.md |
SQL Server 2019+ native ADD SENSITIVITY CLASSIFICATION, org taxonomy (Protected A/B/C), audit queries, SSDT deployment |
references/cloud-migration-portability.md |
On-prem → cloud portability matrix, patterns to prefer/avoid, PBIRS→PBI Service feature expansion, SSAS→Fabric transfer matrix, review checklist for portability assessment |
references/performance-end-to-end.md |
End-to-end performance guidance: DW load batch sizing → SSAS model shape/cardinality → DAX measure performance rules → report visual budget/query reduction/visual type selection → cross-layer diagnostic patterns → Performance Analyzer workflow → org SLAs |
Operating Modes
Mode A: DW Schema Review
Input — in preference order (see Local-First Access Principle above):
- Path 0 (preferred): SSDT project detected in workspace —
globonDW/Dimension/*.sql,DW/Fact/*.sql,DW/Staging/*.sql,DW/Internal/*.sql,DW/SSAS/*.sql; parseCREATE TABLE/CREATE OR ALTER PROCEDURE/CREATE VIEWDDL. Extended properties fromScripts/ExtendedProperties/if present. - Path 1: Live SQL Server connection (via ms-mssql.mssql MCP tools) — use when Path 0 unavailable or live row counts / statistics required.
- Path 2: User-pasted DDL / schema output — ad-hoc fallback. Process:
- Enumerate tables, classify each as Fact / Dimension / Bridge / Staging / Reference
- Run grain analysis: check FK structure, identify candidate grains
- Run SCD audit: check for SCD infrastructure columns
- Run surrogate key audit
- Run extended property coverage audit (use queries in
extended-properties-templates.md) - Produce bus matrix draft
- Produce findings report using checklist from
dw-review-checklist.md
Mode B: Tabular Model Review
Input:
- Option 1: User provides
.bimfile path or TMDL folder — read files directly - Option 2: User provides DMV query results — analyze output
- Option 3: User provides live SSAS connection — run DMV queries from
ssas-tabular-bp.mdProcess:
- Enumerate tables, measures, columns, relationships, partitions
- Validate naming conventions against
ssas-tabular-bp.md - Check relationship design (bidirectional, RLS, RI flags)
- Check role definitions against
security-implementation.mdSection 3 patterns (fixed vs dynamic, AD group membership, OLS) - Check measure quality against
sqlbi-dax-patterns.mdmeasure checklist - Check column encoding, hidden status, display folders
- Produce findings report using Section 3 of
dw-review-checklist.md
Mode C: Extended Properties Generation
Input: Schema name + object name + object type (table/column/view/SP) Process:
- If connected to live DB: query existing extended properties first (do not duplicate)
- Identify the appropriate template from
extended-properties-templates.md - Generate complete set of standard properties for the object type
- Use
IF EXISTS ... sp_updateextendedproperty ELSE sp_addextendedpropertyupsert pattern - Output ready-to-run T-SQL script
Mode D: DAX Measure Review
Input: One or more DAX measure expressions (pasted or from a file) Process:
- Identify the measure pattern type (time intelligence, semi-additive, ranking, etc.)
- Check against applicable patterns in
sqlbi-dax-patterns.md - Check measure quality checklist (DIVIDE, BLANK, VAR, format, description)
- Suggest corrected or improved version with explanation
Mode E: Bus Matrix Generation
Trigger: User asks for a bus matrix or enterprise integration map. Also automatically invoked by dw-report-designer.agent.md after Phase 6 (Dimensions) sign-off — the agent synthesises the bus matrix from interview answers rather than querying a live schema; Mode E's SQL query is used when augmenting against an existing DW.
Input (design-time): Confirmed fact tables + grains (Phase 3) and confirmed dimensions (Phase 6) from the dw-report-designer spec.
Input (existing DW): Local SSDT files (Path 0, preferred) — parse FK definitions from CREATE TABLE DDL in DW/Fact/*.sql. Fall back to live SQL Server connection only if SSDT files absent or FK constraints not defined in DDL.
Process:
- Enumerate all fact tables and their FK columns (from Phase 6 or live schema query)
- Map FK columns to their target dimension tables
- Produce markdown bus matrix table — format from
references/kimball-patterns.md §Enterprise Bus Matrix:- Rows = fact tables; Columns = Grain then dimensions (conformed dimensions first, bold; local dimensions last, labelled)
- ✓ where FK exists; blank where it does not
- Flag facts with no Calendar FK — 🔴 Critical
- Flag potential non-conformed dimensions (dimension used by only one fact — confirm whether it should be conformed) — 🟠 High
- For greenfield: present bus matrix to user for sign-off before any DDL is generated
Mode F: ELT Pipeline Review
Input: SSIS package design description, source SP code, staging schema, or transform SP code Process:
- Classify the pipeline architecture against the 4-package pattern in
elt-patterns.md - Check source SPs: parameterized
@StartDate/@EndDate,NOLOCK, no transforms - Check SSIS data flows: raw extract only (no derived columns, lookups, or expressions)
- Check staging tables:
Staging.{EntityName}naming, identity{EntityName}Key,_Source...natural keys, no presentation-layer FKs - Check transform/load SPs:
Dimension.Load{EntityName}for dimensions,Fact.Load{EntityName}for facts,Staging.Load{EntityName}for staging preparation - Check ELT control tables:
Internal.Lineage,Internal.IncrementalLoads,Internal.LastUpdatedSource, andInternal.ProcedureError - Check package structure: all child packages run tasks in parallel; Master_Orchestrator runs children in sequence
- Produce findings report with references to
elt-patterns.mdsections
Mode G: DevOps Deployment Review
Input: Classic pipeline configuration, PowerShell deployment scripts, SSIS project structure, or SSAS model deployment approach Process:
- Run the deployment checklist from
devops-operations-patterns.mdSection 9 - Identify hardcoded values, missing exit codes, non-idempotent patterns
- Flag any step that requires GUI/manual interaction
- Check pipeline stage ordering: DB → SSIS → SSAS → PBIX
- Check SSIS deployment uses project model + SSISDB environments (not package model)
- Check SSAS deployment uses Tabular Editor CLI (not VS GUI)
- Check PBIX upload includes data source update post-upload
- Produce findings report with references to
devops-deployment-patterns.mdanddevops-operations-patterns.mdsections
Mode H: DW Schema Scaffold
Trigger: Design spec confirmed (from dw-report-designer) OR user provides table requirements directly Input: Confirmed grain, list of dimensions and facts, SCD types, sensitivity labels Process:
- Generate SSDT-compatible SQL files for each table — one
.sqlfile per object using the flat repo layout defined indevops-operations-patterns.mdSection 8:DW/Dimension/[TableName].sql— with[{EntityName} Key],_Source...natural keys, and SCD columns where applicableDW/Fact/[TableName].sql— with[{Role} Date Key], dimension[{EntityName} Key]FKs, measures, and schema-qualified referencesDW/Staging/[TableName].sql— with[{EntityName} Key] IDENTITY, business attributes,_Source...natural keys, and[Lineage Key]DW/Internal/[TableName].sqlandDW/Internal/[ProcedureName].sql— lineage/control objects when a new source is being addedDW/SSAS/[ViewName].sql— one file per SSAS schema view
- Apply index definitions from
dw-physical-design.mdfor every generated table:- Fact tables: CIX on
[Date Key]+ NCI on each FK column (FILLFACTOR 80%) - Dimension tables: CIX on surrogate key + NCI on natural key; filtered NCI on
[Is Current Row] = 1for SCD Type 2 - Staging tables: heap (no CIX); comment that post-load NCI on natural key should be added by the load SP if MERGE performance requires it
- Fact tables: CIX on
- Generate post-deploy script for
sp_addextendedproperty(call Mode C for each object) - Generate
ADD SENSITIVITY CLASSIFICATIONstatements for Protected columns (call Mode C fromdata-classification.md) - Output as ready-to-add SSDT SQL files using the org schemas (
Dimension,Fact,Staging,Internal,SSAS) Conventions: Follow naming fromelt-patterns.mdandkimball-patterns.md; index naming fromdw-physical-design.mdSection 1; file/folder layout fromdevops-operations-patterns.mdSection 8
Mode I: SSAS Tabular Model Scaffold
Trigger: DW schema confirmed (Mode H output or existing DW tables) Input: DW table list, measures list, relationship map from spec Process:
- Generate TMDL files for each table:
- Table definition (columns, data types, source query or view)
- Import from
SSASschema views (views hide DW implementation details from the SSAS model) - Hidden
{EntityName}Keycolumns; visible_Source...and attribute columns
- Generate relationship definitions (always single-direction unless a bidirectional relationship is explicitly justified)
- Generate display folder structure (group measures by business area)
- Generate base measures with descriptions (SQLBI pattern stubs)
- Generate
[Last Processed {TableName}]as a hidden column on each table (required for the Debug tab) - Generate a
[_Debug]table for the Data Freshness tab - Output TMDL folder structure compatible with Tabular Editor 2 "Save as folder" (
TabularEditor.exe) - If RLS roles are required: generate role JSON stubs following
security-implementation.mdSection 3.2 pattern Reference:ssas-tabular-bp.mdfor all naming and structure conventions;security-implementation.mdfor role patterns
Mode J: Source Stored Procedure Generation
Trigger: New source tables identified in the spec Input: Source table DDL or live connection, confirmed columns to extract Process:
- Generate one DW load SP per staging entity:
[Staging].[Load{EntityName}] - SP signature follows the org load pattern and records
@LineageKeyin[Internal].[Lineage] - SP body loads into
[Staging].[{EntityName}], preserving source columns as_Source...keys and applying the org staging-table structure - Keep source extraction raw — no business transformations before the DW load pattern executes
- Add
SET NOCOUNT ON,SET XACT_ABORT ON, and org-standardTRY/CATCHhandling withInternal.RethrowError - For Salesforce sources: note that the KingswaySoft SSIS connector is required (no native SSIS connector exists for Salesforce); the SP pattern does not apply — document as an SSIS data flow instead
- Output as T-SQL scripts deployable to the DW database using the org schemas
Reference:
elt-patterns.mdfor the incremental load pattern and SP conventions
Mode K: SSIS Catalog Configuration
Trigger: New SSIS project being created, or adding new packages to an existing project Input: Source servers, target DW server, SSIS project name, environment name Process:
- Generate
ssis_catalog_configuration.jsonwith environment variable entries:ssis_param_LoadType=I(incremental)ssis_param_SourceDB,ssis_param_SourceServerssis_param_TargetDB,ssis_param_TargetServer- Token placeholders
#{variable_name}#for the ADO Replace Tokens task
- Document the 3-package parallel structure: Load Staging → Load Dimensions → Load Facts
- Document the Master_Orchestrator package calling child packages in sequence
- If Salesforce source: note KingswaySoft plugin requirement;
UsesDispositions='true'; removeSystem.prefix fromInt32data type in BIML - Output as JSON configuration plus pipeline task configuration documentation
Reference:
elt-patterns.mdfor SSIS project structure and environment variable conventions
Mode L: DAX Measure Generation
Trigger: SSAS model exists or is scaffolded (Mode I); measures list confirmed in spec Input: List of measure names, measure types (additive / semi-additive / non-additive), time intelligence requirements Process:
- For each measure: identify the appropriate SQLBI pattern from
sqlbi-dax-patterns.md - Generate the DAX expression using the correct pattern
- Apply standard measure quality rules:
- Use
DIVIDE()instead of/ - Use
VARfor complex multi-step expressions - Set the
Descriptionproperty - Set
FormatString - Wrap in
IF(HASONEVALUE(...), ..., BLANK())for non-additive measures where appropriate
- Use
- Group measures in display folders by business area
- Generate both the base measure and common time intelligence variants (YTD, Prior Year, YoY Variance)
- Output as TMDL measure definitions or as a Tabular Editor 2 (
TabularEditor.exe) script to add measures to an existing model
Mode M: ADO Classic Pipeline Config Generation
Trigger: New DW project being set up OR adding new deployment phases to an existing pipeline Input: Project name, SSIS project name, SSAS model name, environment list (UAT / PROD), server names Process:
- Generate the 5-phase release pipeline task configuration in documented format (Classic pipeline task format — not YAML):
- Phase 1 — Deploy DW DB: createSqlLogin → sqlpackage (DACPAC) → runsqlfile for source SPs
- Phase 2 — Deploy SSIS: SSIS marketplace task → Replace Tokens → Configure SSIS Catalog
- Phase 3 — Deploy SSAS: Schema Check → Deploy (both as Command Line tasks using
TabularEditor.exe) - Phase 4 — Run ELT and Process SSAS: single runDbaAgentJob call
- Phase 5 — Deploy Reports: PBIRS-deployPbixReports
- Generate the variable group entries needed (Tools group variables plus environment-specific variables)
- Generate the build pipeline task sequence (13 steps)
- Note: Tabular Editor 2 (
TabularEditor.exe) is free and already deployed toE:\Tools\TabularEditor\— always use the free Tabular Editor 2 executable; the paid Tabular Editor 3 is not available in this environment - Output as documented pipeline configuration matching the format in
devops-deployment-patterns.mdReference:devops-deployment-patterns.mdfor pipeline configuration patterns;devops-operations-patterns.mdfor PowerShell standards and shared script library
Mode N: Full DW Scaffold (Orchestrated Build)
Trigger: User says "build everything for [project name]", "full build", or invokes Mode N explicitly. Also activated by a signed-off spec from dw-report-designer.agent.md.
Prerequisites: The dw-report-designer.agent.md interview protocol must be completed first. The agent will have produced a requirements artifact containing: confirmed grain, confirmed dimensions, confirmed measures, confirmed bus matrix (signed off), report layout, and user sign-off. Mode N must refuse to proceed without a signed-off bus matrix.
Input: Complete design specification document from the interview protocol.
Dependency DAG (fixed execution order)
Mode N executes build modes in this order. Each step must complete and be validated before the next starts. (Mode-letter mapping reflects this skill's actual modes: H=DW Schema, J=Source SPs, K=SSIS Catalog, I=SSAS Tabular, L=DAX, M=ADO Pipeline.)
0. Mode E — Bus Matrix Validation (verify bus matrix from spec against live schema if DW exists;
confirm conformed dimensions; flag any ✓ gaps before DDL is generated)
↓ (produces: validated/updated Bus Matrix markdown artifact)
1. Mode H — DW Schema Scaffold (Dimension/Fact/Staging/Internal tables)
↓ (produces: DW + Staging CREATE TABLE scripts, SSAS schema views)
2. Mode J — Source Stored Procedure Generation
↓ (produces: Staging.Load*, Dimension.Load*, Fact.Load* SPs)
3. Mode K — SSIS Catalog Configuration
↓ (produces: ssis_catalog_configuration.json, package structure docs)
4. Mode I — SSAS Tabular Model Scaffold
↓ (produces: TMDL source files, relationships, hidden keys, _Debug table)
5. Mode L — DAX Measure Generation
↓ (produces: measures with Description, FormatString, DisplayFolder)
6. Mode M — ADO Classic Pipeline Config Generation
↓ (produces: 5-phase release pipeline, build pipeline, variable groups)
Modes H and J may run in parallel where outputs are independent (source SP extraction is decoupled from DW table DDL). All other steps are strictly sequential. No step may be skipped. If a prerequisite step output is missing, Mode N halts and reports which step failed.
Artifact handoffs between modes
Each mode produces a named artifact that the next mode consumes:
| Producer | Artifact | Consumer |
|---|---|---|
| Mode E | design/bus-matrix.md (signed-off bus matrix — create or update in-place) |
Mode H (table list + FK structure), Mode I (dimension relationships) |
| Mode H | DW/Dimension/[TableName].sql — one file per new Dimension table |
Mode J (SPs reference these tables) |
| Mode H | DW/Fact/[TableName].sql — one file per new Fact table |
Mode J |
| Mode H | DW/Staging/[TableName].sql — one file per new Staging table |
Mode J |
| Mode H | DW/Internal/[TableName].sql — one file per new Internal table |
Mode J |
| Mode H | DW/SSAS/[ViewName].sql — one file per new SSAS schema view |
Mode I (partition source view names) |
| Mode J | DW/Dimension/Load[EntityName].sql — one SP file per dimension entity |
Mode K (SSIS packages call these SPs) |
| Mode J | DW/Fact/Load[EntityName].sql — one SP file per fact entity |
Mode K, Mode I |
| Mode J | DW/Staging/Load[EntityName].sql — one SP file per staging entity |
Mode K |
| Mode K | SSIS/{ProjectName}_SSIS/ssis_catalog_configuration.json (create or update in-place) |
Mode M (pipeline deploys SSIS project + configures catalog) |
| Mode I | SSAS/{ModelName}/ (update existing TMDL — add tables/relationships, do not overwrite) |
Mode L (measures added to this model) |
| Mode L | Updated SSAS/{ModelName}/tables/[MeasureTable].tmdl |
Mode M (deployed via TE2 CLI) |
| Mode M | Build and deployment notes (pipeline definitions live in ADO Server UI, not in this repo) | User review |
Update-in-place rule for design artifacts
Design artifacts in design/ are living documents — updated in-place, never regenerated from scratch:
design/spec.md: Open the existing file; update only the section(s) affected by the current session. Do not touch sections that were not discussed.design/decisions.md: Update or add rows; never delete rows. If an answer changes, record the new answer in the Answer column and note the prior value in Notes.design/bus-matrix.md: Update the markdown table when fact tables or dimensions are added or changed. Add a change log entry with date and description.design/entity-map.md: Append new entities when Mode P is re-run; do not overwrite existing profiling data.design/glossary.md: Add new terms; update definitions only when a term is formally re-agreed with the user. Never remove terms — if a term is superseded, mark it as[deprecated — see: NewTerm].
Lazy creation: Do not create any design/ file until it has substantive content to write. The design/ folder itself may be created empty.
If a file does not exist, create it from the relevant template in the CopilotDWTools toolkit.
Idempotency rules
All generated scripts must be idempotent:
- Tables:
IF NOT EXISTS (SELECT 1 FROM sys.tables WHERE ...) CREATE TABLE ... - Views:
CREATE OR ALTER VIEW ... - Stored procedures:
CREATE OR ALTER PROCEDURE ... - Extended properties:
IF EXISTS ... sp_updateextendedproperty ELSE sp_addextendedpropertyupsert - SSAS model: deploy with ALM Toolkit / Tabular Editor 2 delta deployment — not full replace unless explicitly requested
- Pipeline tasks: must be re-runnable without state corruption
Validation gate between each step
After each mode completes, run the corresponding validation before proceeding:
- After Mode H: run Mode A (DW Schema Review) — must pass with no 🔴 CRITICAL findings; verify
LineageKey INT NULLcolumn present on staging tables - After Mode J: verify SP names follow
Schema.Load{Entity}convention; noSELECT *in SPs;SET NOCOUNT ONandSET XACT_ABORT ONpresent;TRY/CATCHwithInternal.RethrowErrorpresent - After Mode K: verify
ssis_catalog_configuration.jsonparses; all required environment variables present (ssis_param_LoadType,ssis_param_SourceDB,ssis_param_SourceServer,ssis_param_TargetDB,ssis_param_TargetServer); token placeholders use#{...}#format - After Mode I: verify TMDL parses (
TabularEditor.exe ... --check-for-errors); all relationships defined;[Last Processed {TableName}]and[_Debug]table present - After Mode L: run Mode D (DAX Review) — must pass with no 🔴 CRITICAL findings; every measure has
Description,FormatString, andDisplayFolder - After Mode M: verify pipeline Classic task stubs are syntactically valid; all PowerShell follows
devops-operations-patterns.mdSection 7 ([CmdletBinding()],$ErrorActionPreference = 'Stop',exit 0/1)
If a validation gate fails, Mode N:
- Reports the failing check(s) with severity
- Fixes the issue in the producing step
- Re-runs the validation gate
- Does NOT proceed to the next step until the gate passes
Output format
At the end of a successful Mode N run, produce a delivery summary:
## Mode N — Delivery Summary
### {Project Name}
| Artifact | Status | File / Location |
|---|---|---|
| Bus Matrix | ✅ Updated | `design/bus-matrix.md` |
| Design Spec | ✅ Updated | `design/spec.md` |
| Decisions Register | ✅ Updated | `design/decisions.md` |
| Glossary | ✅ Updated | `design/glossary.md` (only if terms were agreed) |
| Source Entity Map | ✅ Updated | `design/entity-map.md` |
| DW Dimension tables | ✅ Created/Updated | `DW/Dimension/[Table].sql` (one file per object) |
| DW Fact tables | ✅ Created/Updated | `DW/Fact/[Table].sql` (one file per object) |
| DW Staging tables | ✅ Created/Updated | `DW/Staging/[Table].sql` (one file per object) |
| SSAS schema views | ✅ Created/Updated | `DW/SSAS/[View].sql` (one file per object) |
| Dimension load SPs | ✅ Created/Updated | `DW/Dimension/Load[Entity].sql` (one file per SP) |
| Fact load SPs | ✅ Created/Updated | `DW/Fact/Load[Entity].sql` (one file per SP) |
| Staging load SPs | ✅ Created/Updated | `DW/Staging/Load[Entity].sql` (one file per SP) |
| SSIS Catalog Config | ✅ Created/Updated | `SSIS/{ProjectName}_SSIS/ssis_catalog_configuration.json` |
| SSAS Model (TMDL) | ✅ Updated | `SSAS/{ModelName}/` (patched, not replaced) |
| ADO Pipeline | ✅ Notes generated | Pipeline definitions live in ADO Server UI — see next steps |
### Validation results
- Mode A (DW Schema Review): ✅ No CRITICAL findings
- Mode D (DAX Review): ✅ No CRITICAL findings
- TMDL parse check (TE2 --check-for-errors): ✅ Pass
- Pipeline PowerShell standards check: ✅ Pass
### Next steps for developer
1. Review generated scripts in DEV environment
2. Deploy DW schema via SSDT publish to DEV
3. Open the SSIS project in Visual Studio and add the generated packages
4. Run SSIS packages against DEV source to populate staging
5. Execute load SPs in dependency order (Staging → Dimension → Fact)
6. Deploy SSAS model to DEV via Tabular Editor 2 CLI
7. Verify in DAX Studio (connect to DEV SSAS)
8. Promote to UAT via ADO Classic pipeline
Mode O: Physical Design Review
Trigger: User says "review indexes", "physical design review", "check indexing", or invokes Mode O explicitly.
Input: Live SQL Server connection (via ms-mssql.mssql MCP tools) OR user-pasted DDL / sys.indexes query output
Process:
- Enumerate all tables in the DW database and classify as Fact / Dimension / Staging / Internal
- For each Fact table:
- Check for CIX on DateKey; flag missing CIX as 🔴 CRITICAL
- Check for NCI on each FK column; flag each missing NCI as 🟠 HIGH
- Check FILLFACTOR; flag 100% on append-loaded tables as 🟡 MEDIUM
- Check row count; if > 1M rows flag CCI consideration as 🔵 LOW
- For each Dimension table:
- Check for CIX on surrogate key; flag missing as 🔴 CRITICAL
- Check for NCI on natural key; flag missing as 🟠 HIGH
- If SCD Type 2 columns present (
Is Current Row,Valid From,Valid To): check for filtered NCI on[Is Current Row] = 1; flag missing as 🟡 MEDIUM
- For each Staging table:
- Flag the presence of a CIX as 🟡 MEDIUM (anti-pattern — staging should be heap with post-load NCI)
- Check that natural key columns used in downstream MERGE have an NCI; flag missing as 🟡 MEDIUM
- Detect anti-patterns from
dw-physical-design.mdSection 6 - Recommend load/partition strategy based on actual row counts (reference:
performance-end-to-end.mdLayer 1 batch sizing table):- For each Fact table, compare row count against thresholds and recommend: full reload (< 5M), incremental watermark (5M–50M), or partition switching (> 50M / constrained window)
- For each Dimension table, check SCD type: Type 1 < 500K → full reload acceptable; Type 2 any size → must be incremental
- Default recommendation is always incremental watermark-based loading (
@StartDate/@EndDate) — only recommend full reload or partition switching when row counts justify it - Present concisely: "[Table]: [N] rows → [recommended strategy]."
- Produce findings report using severity codes
- Optionally generate remediation scripts (idempotent
CREATE INDEX … IF NOT EXISTSpattern) for all flagged items
Mode P: Source System Analysis
Trigger: User says "explore source", "analyse source database", "my data is in [SourceDB]", "I want to build a DW for [subject area]", or invokes Mode P explicitly. Also activated by dw-report-designer Phase 2 Step 3 for each source system named by the user.
Input: Source identifier + connection details. The shape of the input depends on the source type:
- SQL Server: server name + database name (+ optional filtered table list)
- CSV: one or more CSV files (the actual data, a header-only export, or a sample extract) + delimiter/quoting convention if non-standard
- Other (manual): user-provided plain-language description of entities, keys, and relationships
Path A — SQL Server (automated, full profiling)
- Connect to the source database using the
ms-mssql.mssqlMCP tool. - Run Q1–Q5 once across the full source database (or filtered table list if supplied):
- Q1 — Table Inventory with row counts and column counts
- Q2 — Date/status column detection (triage output before feeding Q7 — name patterns produce false positives)
- Q3 — Primary Key Map (flag
uniqueidentifierPKs as alternate-key candidates; generate INT surrogate in DW) - Q4 — FK Relationship Map (if zero rows returned database-wide, activate No FK Constraints handling)
- Q5 — Inbound/Outbound FK Count Summary
- Apply the classification heuristics from
references/source-system-analysis.mdto classify each table. - For each Fact candidate, run:
- Q6 — NULL Rate Check on FK and key columns (for tables > 10M rows, restrict to FK and date columns only)
- Q8 — Duplicate PK Check on the candidate natural key (duplicates = data quality issue; flag for ELT deduplication)
- For each Status/Type column flagged in Q2 (after human triage), run Q7 — Cardinality Profiling. Fewer than 20 distinct values → junk dimension candidate.
- For each date column on each Fact candidate, run Q9 — Date Range Profiling. Record
MIN/MAXdates — these drive Calendar dimension start date for Mode H. - Run Q10 — CDC/Change Tracking Detection once per source database. Record result; this drives the ELT incremental strategy for Mode K and Mode M.
- Produce the Source Entity Map using the output format in
references/source-system-analysis.md. - For each Fact candidate, propose a grain: "Based on
[Table], a natural grain is: one row per [PK description]. Does this match your reporting requirement?"
No FK constraints: When Q4 returns zero rows database-wide, apply implied FK detection — columns in high-row-count tables named [EntityName]ID / [EntityName]Key / [EntityName]Code whose names match PK column names in lower-row-count tables. Present these as inferred relationships in a separate section of the entity map, clearly labelled. Warn the user that these must be confirmed.
Path B — CSV (automated profiling)
Applies to direct flat-file feeds and CSV header/sample exports from any other source system (Salesforce, Oracle, PostgreSQL, MySQL, etc.). See references/source-system-analysis.md § "CSV Source Discovery" for the full procedure.
- Profile each CSV using the preferred tool for the row count: PowerShell
Import-Csvfor small-to-medium files (up to ~100k rows), or SQL Server bulk-load to a Staging table for larger files or when cross-file joins are needed. Python/pandas is not a default option in this Windows environment. - Derive the same outputs as Q1–Q9 (table inventory, date/status columns, PK candidates, inferred FKs, NULL rates, cardinality, duplicate PK check, date range profiling).
- Q10 (CDC) is not applicable — ask the user whether the CSV represents a one-time load, an incremental drop, or a full snapshot per delivery; record the answer for Mode K.
- All FK relationships derived from CSV are inferred and go into the "Inferred Relationships (low confidence)" section of the entity map.
Path C — Manual discovery (last resort)
Used only when the source is non-SQL and the user cannot provide a CSV export (e.g. legacy mainframe, proprietary API).
- Ask the user to describe each entity in plain language (table name, key fields, relationships).
- Build the entity map manually with confidence marked
low — no automated profiling. - Record the connector requirement for the eventual SSIS data flow.
Output: Structured Source Entity Map document saved to design/entity-map.md (append new entities if file already exists; never overwrite). Contents:
- Source type marker (SQL Server / CSV / Manual) + discovery confidence rating
- Fact candidates (rows, date columns, FK columns, grain proposal)
- Dimension candidates (rows, natural key, SCD potential)
- Reference/lookup tables and junk dimension candidates
- Source Change Detection summary (CDC/CT status from Q10, or CSV delivery cadence)
- Inferred relationships (always for CSV; for SQL Server only when no FK constraints)
- Ignored tables (with reason)
- Data quality flags (NULL rates from Q6, duplicate PK issues from Q8)
- Date range summary per Fact candidate (from Q9)
Consumer: Phase 2 of dw-report-designer.agent.md calls this mode for each named source system. The entity map feeds Phase 3 (grain confirmation), Phase 4 (measure candidates from numeric columns), and Phase 5 (dimension design) — do not repeat discovery questions already answered in the entity map.
Reference: references/source-system-analysis.md for all query text, CSV profiling procedure, classification heuristics, and output format.
- Always produce a severity-coded findings report (🔴 Critical / 🟠 High / 🟡 Medium / 🔵 Low) using the template in
dw-review-checklist.md - Always cite the specific Kimball pattern, SQLBI pattern, or checklist item for each finding
- For extended properties output: produce complete, ready-to-run T-SQL using the upsert pattern
- For bus matrix output: produce a markdown table with ✓ marks for confirmed relationships
- For ELT output: generate parameterized T-SQL SPs and Classic pipeline PowerShell task configurations, not GUI click instructions (not YAML unless user requests it)
- For deployment scripts: all PowerShell must follow the standards in
devops-operations-patterns.mdSection 7 —[CmdletBinding()],$ErrorActionPreference = 'Stop',exit 0/1 - Ask clarifying questions before assuming the grain of a fact table — grain definition requires domain knowledge
Interaction Style
- Be direct about design issues — use severity levels, not vague language
- When a schema shows SCD Type 2 candidates, always ask: "Are historical versions of this entity needed for reporting?"
- When reviewing DAX measures, always show the corrected version alongside the finding
- When generating extended properties, ask about business ownership, source system, and grain if not obvious from schema
Dependencies
This skill works best when the database-data-management:ms-sql-dba agent or ms-mssql.mssql MCP tools are available for live database connectivity. The skill can also work entirely from user-provided schema DDL, DMV output, or BIM/TMDL files.
Trusted External Sources
When referencing best practices, patterns, or guidance beyond the bundled reference files, these are the organisation's trusted authorities:
| Source | Authority For | URL |
|---|---|---|
| SQLBI (Marco Russo, Alberto Ferrari) | DAX patterns, Tabular model design, measure methodology, calculation groups | https://www.sqlbi.com/ |
| Guy in a Cube (Adam Saxton, Patrick LeBlanc) | Power BI best practices, service features, PBIRS, practical implementation, Fabric updates | https://www.youtube.com/@GuyInACube |
| Kimball Group | Dimensional modeling methodology, fact/dim design, bus matrix | https://www.kimballgroup.com/data-warehouse-business-intelligence-resources/kimball-techniques/ |
| Microsoft Learn | Official documentation for SQL Server, SSAS, Power BI, Fabric, ADF | https://learn.microsoft.com/ |
When these sources conflict with each other, prefer: SQLBI for DAX → Kimball for DW design → Microsoft Learn for product capabilities → Guy in a Cube for practical PBI guidance.