Skill: Report Quality Validation (Final Reconciliation)
Purpose
Provide a structured verification methodology for the PBIR artifacts generated in Step 9, ensuring:
- syntactic correctness of PBIR files (
page.json,visual.json, schema, structure), and - semantic coherence between visual field bindings and the semantic model (TMDL tables, columns, measures, relationships).
This step is the final quality gate before opening the PBIP project in Power BI Desktop.
Prerequisites — MANDATORY
Before starting report quality validation:
- ✅ Step 9 completed and approved — PBIR page and visual files exist in
<ProjectName>/PBIP/<ProjectName>.Report/definition/pages/. - ✅ Report blueprint exists —
<ProjectName>/spec/report_blueprint.jsonon disk. - ✅ Semantic Model exists —
<ProjectName>/PBIP/<ProjectName>.SemanticModel/definition/contains valid TMDL files.
Input / Output
| Input | <ProjectName>/spec/report_blueprint.json, all TMDL files, PBIR page/visual files |
| Output | <ProjectName>/tests/report_validation_execution.md |
Performance Rule: Load the full PBIR payload into context only when strictly necessary. Run
.github/scripts/validate_pbir_report.py <ProjectName>for bulk validation first; inspect raw PBIR files individually only for targeted remediation.
CLI Rule: If the local
pbirCLI is available, it may be used for a fast local pre-check (pbir validate,pbir tree -v,pbir fields list,pbir filters list) but it does NOT replace the repository validator or the final report produced by this skill. Never runpbir setuphere. Always clear or replace the activepbirconnection first so commands target the current project report instead of a stale session.
Canonical pbir Pre-Check Patterns
Use these only as supplemental local validation helpers:
- Structural overview before deep validation:
pbir connect --clear
pbir connect "Sales.Report"
pbir tree "Sales.Report" -v
- Fast validation sweep:
pbir connect --clear
pbir connect "Sales.Report"
pbir validate "Sales.Report"
pbir validate "Sales.Report" --all
- Inspect bindings and report behavior quickly:
pbir connect --clear
pbir connect "Sales.Report"
pbir fields list "Sales.Report"
pbir filters list "Sales.Report"
- If the CLI is unavailable or its output is incomplete, continue directly with the repository validator and targeted PBIR inspection.
In scope: PBIR syntax and structural validation, visual binding cross-check, blueprint coherence, SVG measure review, Deneb visual review, design quality assessment, validation report with PASS/WARNING/FAIL outcomes. Out of scope: redesigning report UX, adding visuals/pages, changing business requirements, broad model redesign.
References — On Demand
Load these references when the validation involves the corresponding artifact type:
| Reference | Path | When to Load |
|---|---|---|
| SVG Review Checklist | references/svg-review-checklist.md |
Report contains SVG DAX measures (ImageUrl dataCategory) |
| Deneb Review Checklist | references/deneb-review-checklist.md |
Report contains Deneb custom visuals (deneb_deneb) |
| Report Design Review | references/report-design-review.md |
User requests design quality, complexity, or accessibility review |
Validation Methodology (MANDATORY)
Apply validation in this exact order to reduce false positives and speed root-cause identification:
Automated Bulk Validation Layer
- Run the shared validator script first to generate deterministic summary artifacts on disk.
- Use the generated Markdown and JSON summaries as the primary inspection surface.
- If useful for fast local triage, run
pbir validate "<Report.Report>"orpbir validate "<Report.Report>" --allbefore deep inspection, but treat it only as supplemental evidence. - Fall back to direct PBIR file reads only for targeted diagnosis.
Structural & Syntax Layer
- Validate file presence, JSON parseability, required schema properties, and folder hierarchy.
- Enforce property-placement rules:
visualContainerObjectsmust be insidevisual.drillFilterOtherVisualsmust be insidevisual.- visual-level filters must use top-level
filterConfig.filters, nevervisual.filters.
- Reject schema-foreign additional properties before semantic checks.
- Stop early on blocking syntax errors before semantic checks.
Semantic Binding Layer
- Validate every
EntityandPropertyused in PBIR against TMDL object registry. - Validate filter bindings and multi-table visuals against active relationship reachability.
- Validate every
Blueprint Consistency Layer
- Validate that generated pages/visuals/types/counts align with Step 8 blueprint intent.
- Flag mismatches as implementation drift (WARNING/FAIL based on impact).
Readiness Layer
- Consolidate issues with severity and actionable remediation order.
- Classify overlaps involving decorative
shapevisuals as WARNING unless they obscure interaction targets; keep non-decorative overlaps as FAIL. - Output deterministic report so results are reproducible across runs.
Step 10 Procedure
10.0 Run the Shared PBIR Validator (MANDATORY)
Run the repository-wide validator:
python .github/skills/report-quality-validation/scripts/validate_pbir_report.py <ProjectName>
Expected outputs:
<ProjectName>/tests/report_validation_execution.md<ProjectName>/tests/report_validation_execution.json
The agent MUST treat these generated files as the primary validation artifacts for Step 10.
If the validator fails to run:
- report the execution error,
- inspect only the minimum required PBIR files to diagnose the failure,
- and avoid opening large portions of the report definition unless necessary.
10.1 Build Validation Context
Load the three data sources needed for cross-validation:
A) Model Object Registry
Read all TMDL files and build the registry (same as Steps 7 and 9):
- Tables: All table names
- Columns: All column names per table (PascalCase)
- Measures: All measure names from
_Measures.tmdl(natural language with spaces) - Relationships: All relationship pairs
- Field parameter metadata: detect parameter tables, visible parameter columns, hidden metadata columns, and allowed target objects
- Context compatibility metadata: for measure-parameter visuals, collect allowed context dimensions from the blueprint and compare them with model reachability
B) Blueprint Registry
Parse report_blueprint.json and extract:
- Pages: List of
pageIdvalues and theirdisplayName - Visuals per page: Count of visuals per page, including slicers
- Fields used: All measure names and column references across all visuals
- Visual types: List of visual types used
C) PBIR File Registry
Use the validator outputs as the primary PBIR registry and inspect raw PBIR files only when needed. Extract or confirm:
- Page folders: List of folders in
pages/ - Visual folders per page: Count of visual subfolders in each page's
visuals/folder - Visual JSON content: Parse each
visual.jsonto extract:Entityreferences (table names)Propertyreferences (column/measure names)visualTypevaluesqueryState.<Role>.fieldParameters[]references (when present)filterConfig.filters[].fieldreferences (when present)- Title text
10.2 Cross-Reference Field Validation (CRITICAL)
Objective: Verify that every query or select in the visual.json files points to a column or measure that actually exists in the TMDL semantic model.
Checks to Perform
For EACH visual.json file:
Entity Validation: Every
SourceRef.Entityvalue MUST match a table name in the TMDL model.- PASS: Entity
"Dim_Date"exists astable Dim_Datein TMDL. - FAIL: Entity
"DateDimension"does not match any TMDL table name.
- PASS: Entity
Property Validation (Columns): Every
Column.Propertyvalue MUST match a column declared in the corresponding TMDL table file.- PASS: Property
"FiscalYear"exists ascolumn FiscalYearinDim_Date.tmdl. - FAIL: Property
"Fiscal Year"(with space) does not match PascalCase column name.
- PASS: Property
Property Validation (Measures): Every
Measure.Propertyvalue MUST match a measure declared in_Measures.tmdl.- PASS: Property
"Sales Amount FYTD"exists asmeasure 'Sales Amount FYTD'in_Measures.tmdl. - FAIL: Property
"SalesAmountFYTD"does not match the natural language measure name.
- PASS: Property
Relationship Reachability: For visuals that combine fields from multiple tables, verify that the tables are connected through active relationships in
relationships.tmdl.- WARNING: Visual uses fields from
Dim_AreaandFact_Sales, but no direct or indirect relationship exists.
- WARNING: Visual uses fields from
FilterConfig Validation: When
filterConfigis present, validatefilterConfig.filters[].fieldusing the same Entity/Property rules above.- PASS:
filterConfigreferences only valid columns/measures. - FAIL:
filterConfigcontains unknown field references.
- PASS:
Field Parameter Binding Validation: When a visual uses
queryState.<Role>.fieldParameters[], validate that:- the referenced parameter table exists in TMDL,
- the parameter display column exists,
- the target role also contains at least one concrete projection compatible with the current selection baseline,
- and the parameter table metadata on the model side is present.
Field Parameter Default Selection Validation: When a field-parameter slicer defines
visual.objects.general[].properties.filter, validate that the filter targets the hidden object-reference column and that the literal value matches one of the allowedNAMEOF(...)entries from the parameter table.Measure Parameter Context Validation: When a visual uses a measure parameter, validate that every non-parameter grouping field in the same visual is semantically safe for all selectable measures:
- the grouping dimension is reachable through active relationships from every fact table or measure lineage involved,
- the dimension is declared in the blueprint as an allowed context dimension,
- and the resulting filter context does not become partial or misleading for one or more selectable measures.
Output Format for Field Validation
## Field Cross-Reference Validation
| # | Page | Visual | Entity | Property | Type | Status | Details |
|---|------|--------|--------|----------|------|--------|---------|
| 1 | Page1 | visual_01 | _Measures | Sales Amount FYTD | Measure | ✅ PASS | Exists in _Measures.tmdl |
| 2 | Page1 | visual_02 | Dim_Date | FiscalYear | Column | ✅ PASS | Exists in Dim_Date.tmdl |
| 3 | Page1 | visual_03 | Dim_Area | Area Name | Column | ❌ FAIL | Column not found. Did you mean 'AreaName'? |
| 4 | Page2 | visual_01 | Dimension | Dimension | FieldParameter | ✅ PASS | Parameter table and display column exist |
10.3 Blueprint Compliance Validation
Objective: Verify that the number of pages and visuals created in PBIR matches exactly what was defined in report_blueprint.json.
Checks to Perform
Page Count: Number of page folders in PBIR = Number of pages in blueprint.
- PASS: Blueprint defines 2 pages, PBIR has 2 page folders.
- FAIL: Blueprint defines 3 pages, PBIR has 2 page folders —
Page3missing.
Page Names: Each page's
displayNameinpage.jsonmatches the blueprint'sdisplayName.- WARNING: Blueprint says
"Sales Overview",page.jsonsays"Sales_Overview".
- WARNING: Blueprint says
Visual Count per Page: Number of visual folders per page = Number of visuals + slicers defined in blueprint for that page.
- PASS: Blueprint defines 4 visuals + 2 slicers for Page1, PBIR has 6 visual folders.
- FAIL: Blueprint defines 5 visuals for Page2, PBIR has 3 visual folders — 2 missing.
Visual Types: Each visual's
visualTypeinvisual.jsonmatches the expected type from the blueprint (after mapping).- PASS: Blueprint says
"card", PBIR says"cardVisual". - PASS: Blueprint says
"clusteredBarChart", PBIR says"clusteredBarChart". - FAIL: Blueprint says
"line", PBIR says"clusteredColumnChart".
- PASS: Blueprint says
Measure Coverage: Every measure referenced in the blueprint's
visuals[].measures[]appears in at least onevisual.json.- WARNING: Measure
"Budget Amount FYTD"is in the blueprint but not found in any visual.
- WARNING: Measure
Output Format for Blueprint Compliance
## Blueprint Compliance Report
| # | Check | Expected | Actual | Status | Details |
|---|-------|----------|--------|--------|---------|
| 1 | Page Count | 2 | 2 | ✅ PASS | |
| 2 | Page1 Visual Count | 6 | 6 | ✅ PASS | 4 visuals + 2 slicers |
| 3 | Page2 Visual Count | 3 | 3 | ✅ PASS | |
| 4 | Measure Coverage | 12 | 12 | ✅ PASS | All measures mapped |
| 5 | Visual Type Match | All | All | ✅ PASS | |
10.4 Accessibility and Best Practice Validation
Objective: Verify basic accessibility, design quality, and performance best practices.
For comprehensive design review, load references/report-design-review.md which provides:
- The 3/30/300 rule for information hierarchy
- 12-point design checklist (titles, spacing, color, fonts, visual count, etc.)
- Chart type anti-patterns
- Visual complexity analysis (performance risk from PBIR structure)
- DAX query inference from visual field bindings
- Accessibility checklist (WCAG 2.1 AA, font sizes, contrast, tab order)
Standard Checks (always performed)
Visual Count per Page:
- PASS: Page has ≤ 8 visuals (including slicers).
- WARNING: Page has 9-12 visuals — may impact performance.
- FAIL: Page has > 12 visuals — will likely cause performance issues.
Title Presence:
- PASS: Visual title is present either via
visual.visualContainerObjects.titleor handled by default visual caption. - WARNING: Visual
visual_03onPage1has no explicit custom title configuration.
- PASS: Visual title is present either via
Slicer Cardinality:
- PASS: Slicers reference low-cardinality dimension columns (< 100 unique values).
- WARNING: Slicer on
Dim_Customer[CustomerName]may have high cardinality (100+ values).
Schema URLs:
- PASS: All JSON files reference valid Microsoft
$schemaURLs. - FAIL:
page.jsonis missing$schemaproperty.
- PASS: All JSON files reference valid Microsoft
Position Validation:
- PASS: All visuals fit within the page dimensions (width ≤ page width, height ≤ page height).
- WARNING: Visual
visual_05extends beyond page boundaries.
Duplicate Visual IDs:
- PASS: No duplicate
namevalues within a page. - FAIL: Two visuals share
name: "visual_01"on Page1.
- PASS: No duplicate
Output Format for Accessibility/Best Practice
## Accessibility & Best Practice Report
| # | Check | Page | Status | Details |
|---|-------|------|--------|---------|
| 1 | Visual count ≤ 8 | Page1 | ✅ PASS | 6 visuals |
| 2 | Visual count ≤ 8 | Page2 | ✅ PASS | 3 visuals |
| 3 | All titles present | Page1 | ✅ PASS | 6/6 have titles |
| 4 | No high-cardinality slicers | Page1 | ⚠️ WARNING | Slicer on CustomerName |
| 5 | Schema URLs valid | All | ✅ PASS | |
| 6 | Positions within bounds | All | ✅ PASS | |
| 7 | No duplicate IDs | All | ✅ PASS | |
10.5 SVG and Deneb Visual Validation (CONDITIONAL)
Apply when the report contains SVG measures or Deneb custom visuals.
SVG Measures
If any extension measure or model measure has dataCategory: ImageUrl or returns a data:image/svg+xml string:
- Load
references/svg-review-checklist.md - Apply the 10-point checklist to each SVG measure
- Assess design quality (complexity, coordinates, target visual)
- Report findings with PASS/FAIL per checklist item
Deneb Visuals
If any visual has visualType: "deneb_deneb" or references a Deneb custom visual:
- Load
references/deneb-review-checklist.md - Apply the 10-point spec checklist + 4-point PBIR integration checklist
- Assess design quality (chart type, colors, axes, text sizes)
- Report findings with PASS/FAIL per checklist item
10.6 Generate Validation Report
Combine all validation results into a single report file.
File: <ProjectName>/tests/report_validation_execution.md
Report Structure:
# Report Quality Validation — <ProjectName>
**Generated**: <ISO 8601 timestamp>
**Blueprint**: <ProjectName>/spec/report_blueprint.json
**Report Path**: <ProjectName>/PBIP/<ProjectName>.Report/definition/
## Overall Status: ✅ PASS / ⚠️ WARNINGS / ❌ FAIL
## Summary
- Pages validated: X/X
- Visuals validated: Y/Y
- Fields cross-referenced: Z/Z
- Warnings: W
- Errors: E
---
## 1. Field Cross-Reference Validation
<table from 10.2>
## 2. Blueprint Compliance
<table from 10.3>
## 3. Accessibility & Best Practices
<table from 10.4>
---
## Recommendations
<List of recommended fixes for any WARNING or FAIL items>
## Conclusion
<Final assessment: Ready for Power BI Desktop / Requires fixes>
Error Resolution
If FAIL items are found:
- Field not found: Correct the
visual.jsonfile to use the exact TMDL name. Apply the fix and re-validate. - Missing pages/visuals: Generate the missing PBIR files by re-running the relevant part of Step 9.
- Wrong visual type: Update the
visualTypein thevisual.jsonfile. - Schema issues: Add or correct the
$schemaURL in the affected JSON file.
The agent SHOULD propose auto-fixes for all FAIL items. Upon user approval, apply fixes and re-run validation.
When re-running validation after fixes:
- re-run the shared validator script first,
- compare the new summary against the previous summary,
- and read only the specific PBIR files implicated by any remaining FAIL or WARNING items.
Validation Gate — STOP
Before declaring Step 10 complete:
- Validation report has been saved to
<ProjectName>/tests/report_validation_execution.md - All FAIL items have been resolved (or acknowledged by the user)
- Overall status is ✅ PASS or ⚠️ WARNINGS (with user acceptance)
Save validation report to <ProjectName>/tests/report_validation_execution.md.
Final Deliverable
After validation approval, the user has a fully validated PBIP project:
- ✅ Semantic Model (TMDL) — validated
- ✅ Report Design (Blueprint) — validated
- ✅ Report Implementation (PBIR) — generated
- ✅ Report Quality — validated
The user can now open <ProjectName>/PBIP/<ProjectName>.pbip in Power BI Desktop, refresh data, and use the report.