スキル一覧に戻る
data-goblin

bpa-rules

by data-goblin

0🍴 0📅 2026年1月20日
GitHubで見るManusで実行

SKILL.md


name: bpa-rules description: This skill should be used when the user asks to "create a BPA rule", "write a Best Practice Analyzer rule", "improve a BPA expression", "fix expression for BPA", "analyze BPA annotations", "check model for best practices", "audit BPA rules", "discover BPA rules", "list all BPA rules", "validate BPA rules", or mentions Tabular Editor BPA rules. Provides guidance for creating, improving, auditing, and understanding Best Practice Analyzer rules for Power BI semantic models.

Best Practice Analyzer Rules

Expert guidance for creating and improving BPA (Best Practice Analyzer) rules for Tabular Editor and Power BI semantic models.

When to Use This Skill

Activate automatically when tasks involve:

  • Creating new BPA rules for semantic model validation
  • Improving or debugging BPA rule expressions
  • Writing FixExpression to auto-remediate rule violations
  • Understanding BPA annotations in TMDL files
  • Analyzing a semantic model against best practices
  • Converting ad-hoc checks into reusable BPA rules
  • Auditing or discovering all BPA rules across sources (built-in, URL, model, user, machine)

Critical

  • Always validate rule expressions before suggesting them
  • Test expressions against the target scope (Measure, Column, Table, etc.)
  • Ensure FixExpression does not cause data loss or break the model
  • Consider CompatibilityLevel when using newer TOM properties

Tabular Editor Compatibility

BPA rule files must follow specific formatting requirements for Tabular Editor to load them correctly. Files that don't follow these rules may show empty rule collections or fail to load entirely.

Line Endings (CRLF Required)

Tabular Editor on Windows requires Windows line endings (CRLF, \r\n). Files with Unix line endings (LF only) will fail to load or show empty rule collections.

To convert a file to CRLF:

# macOS/Linux
sed -i 's/$/\r/' rules.json

# Or use the validation script
python scripts/validate_rules.py --fix rules.json

File Paths

When adding rule files in Tabular Editor:

  • Use absolute paths (e.g., C:\BPARules\my-rules.json)
  • Avoid relative paths with ..\..\.. - TE may fail to resolve these
  • URLs work reliably (e.g., https://raw.githubusercontent.com/...)

JSON Format Requirements

No extra properties: TE's JSON parser is strict. Only use allowed fields:

  • ID, Name, Category, Description, Severity, Scope, Expression
  • FixExpression, CompatibilityLevel, Source, Remarks

Avoid these patterns:

// BAD: _comment fields not allowed
{ "_comment": "Section header", "ID": "RULE1", ... }

// BAD: Runtime fields (TE adds these, don't include them)
{ "ID": "RULE1", "ObjectCount": 0, "ErrorMessage": null, ... }

// GOOD: FixExpression can be null or omitted
{ "ID": "RULE1", "FixExpression": null, ... }
{ "ID": "RULE1", "Name": "...", "Severity": 2, "Scope": "Measure", "Expression": "..." }

Note: FixExpression: null is valid. ErrorMessage and ObjectCount are runtime fields that TE adds - do not include them in rule definitions.

Regex Expression Syntax

When using RegEx.IsMatch() in expressions:

No @ prefix: Do not use C# verbatim string prefix

// BAD: @ prefix not supported
RegEx.IsMatch(Expression, @"FILTER\s*\(\s*ALL")

// GOOD: Standard escaping
RegEx.IsMatch(Expression, "FILTER\\s*\\(\\s*ALL")

No RegexOptions parameter: TE doesn't support the options parameter

// BAD: RegexOptions not supported
RegEx.IsMatch(Name, "^DATE$", RegexOptions.IgnoreCase)

// GOOD: Use inline flag or pattern only
RegEx.IsMatch(Name, "(?i)^DATE$")
RegEx.IsMatch(Name, "^(DATE|date|Date)$")

Correct Scope Names

Use the exact scope names from the TOM enum. Common mistakes:

WrongCorrect
RoleModelRole
MemberModelRoleMember
ExpressionNamedExpression
DataSourceProviderDataSource or StructuredDataSource

Note: Column is valid as a backwards-compatible alias for DataColumn, CalculatedColumn, CalculatedTableColumn.

Validation Script

Use the validation script to check and fix TE compatibility issues:

# Check for issues
python scripts/validate_rules.py rules.json

# Auto-fix issues (CRLF, remove nulls, remove _comment)
python scripts/validate_rules.py --fix rules.json

The script checks:

  • Line endings (CRLF)
  • No _comment fields
  • No null values for optional fields
  • Valid scope names
  • Expression syntax warnings

About BPA rules

  • BPA rules define automatic tests for semantic models in Power BI and Fabric for QA/QC
  • BPA rules are used by Tabular Editor 2, 3, CLI, or Fabric notebooks
  • Rule expressions are defined in C# for Tabular Editor or Python for Fabric Notebooks
  • BPA rules are better defined and used by Tabular Editor because they are actionable with ability to ignore or fix, and they are integrated with the IDE

File Locations

BPA rules can exist in multiple locations (evaluated in order of priority):

LocationPath / SourceDescription
Built-in Best PracticesInternal to TE3Default rules bundled with Tabular Editor 3
URLAny valid URL (e.g., https://raw.githubusercontent.com/TabularEditor/BestPracticeRules/master/BPARules-standard.json)Remote rule collections loaded from web
Rules within current modelSee belowRules embedded in model metadata
Rules for local user%LocalAppData%\TabularEditor3\BPARules.jsonUser-specific rules on Windows
Rules on local machine%ProgramData%\TabularEditor3\BPARules.jsonMachine-wide rules for all users

Built-in Rules (TE3 Only)

Tabular Editor 3 includes built-in BPA rules embedded in the application. These are not stored as separate JSON files but are compiled into the DLLs.

Configuration: %LocalAppData%\TabularEditor3\Preferences.json

  • BuiltInBpaRules: "Enable" | "Disable" | "EnableWithWarnings"
  • DisabledBuiltInRuleIds: Array of rule IDs to disable

Built-in Rule IDs:

IDCategoryDescription
TE3_BUILT_IN_DATA_COLUMN_SOURCESchemaData column source validation
TE3_BUILT_IN_EXPRESSION_REQUIREDSchemaExpression required for calculated objects
TE3_BUILT_IN_AVOID_PROVIDER_PARTITIONS_STRUCTUREDData SourcesAvoid provider partitions with structured sources
TE3_BUILT_IN_SET_ISAVAILABLEINMDX_FALSEPerformanceSet IsAvailableInMdx to false for non-MDX columns
TE3_BUILT_IN_DATE_TABLE_EXISTSSchemaDate table should exist
TE3_BUILT_IN_MANY_TO_MANY_SINGLE_DIRECTIONRelationshipsMany-to-many should use single direction
TE3_BUILT_IN_RELATIONSHIP_SAME_DATATYPERelationshipsRelationship columns should have same data type
TE3_BUILT_IN_AVOID_INVALID_CHARACTERS_NAMESNamingAvoid invalid characters in names
TE3_BUILT_IN_AVOID_INVALID_CHARACTERS_DESCRIPTIONSMetadataAvoid invalid characters in descriptions
TE3_BUILT_IN_SET_ISAVAILABLEINMDX_TRUE_NECESSARYPerformanceSet IsAvailableInMdx true only when necessary
TE3_BUILT_IN_REMOVE_UNUSED_DATA_SOURCESMaintenanceRemove unused data sources
TE3_BUILT_IN_VISIBLE_TABLES_NO_DESCRIPTIONMetadataVisible tables should have descriptions
TE3_BUILT_IN_VISIBLE_COLUMNS_NO_DESCRIPTIONMetadataVisible columns should have descriptions
TE3_BUILT_IN_VISIBLE_MEASURES_NO_DESCRIPTIONMetadataVisible measures should have descriptions
TE3_BUILT_IN_VISIBLE_CALCULATION_GROUPS_NO_DESCRIPTIONMetadataVisible calculation groups should have descriptions
TE3_BUILT_IN_VISIBLE_UDF_NO_DESCRIPTIONMetadataVisible UDFs should have descriptions
TE3_BUILT_IN_PERSPECTIVES_NO_OBJECTSSchemaPerspectives should contain objects
TE3_BUILT_IN_CALCULATION_GROUPS_NO_ITEMSSchemaCalculation groups should have items
TE3_BUILT_IN_TRIM_OBJECT_NAMESNamingObject names should be trimmed
TE3_BUILT_IN_FORMAT_STRING_COLUMNSFormattingColumns should have format strings
TE3_BUILT_IN_TRANSLATE_DISPLAY_FOLDERSTranslationsDisplay folders should be translated
TE3_BUILT_IN_TRANSLATE_DESCRIPTIONSTranslationsDescriptions should be translated
TE3_BUILT_IN_TRANSLATE_VISIBLE_NAMESTranslationsVisible names should be translated
TE3_BUILT_IN_TRANSLATE_HIERARCHY_LEVELSTranslationsHierarchy levels should be translated
TE3_BUILT_IN_TRANSLATE_PERSPECTIVESTranslationsPerspectives should be translated
TE3_BUILT_IN_SPECIFY_APPLICATION_NAMEMetadataSpecify application name
TE3_BUILT_IN_POWERBI_LATEST_COMPATIBILITYCompatibilityUse latest Power BI compatibility level

Note: This list is extracted from TE3 v3.25.0 Preferences.json. Built-in rules are not documented separately by Tabular Editor.

Model-embedded rules can be stored in two formats:

FormatLocationSyntax
model.bim (JSON)model.annotations array{ "name": "BestPracticeAnalyzer", "value": "[{...rules...}]" }
TMDLmodel.tmdl fileannotation BestPracticeAnalyzer = [{...rules...}]

File format: All locations use the same JSON array format containing rule objects.

Priority: When the same rule ID exists in multiple locations, rules are merged with local rules taking precedence over remote/built-in rules.

Cross-Platform Access (macOS/Linux)

When working on macOS or Linux with Tabular Editor installed in a Windows VM:

Parallels on macOS:

/Users/<macUser>/Library/Parallels/Windows Disks/{VM-UUID}/[C] <DiskName>.hidden/

Full paths to BPA rules:

  • User-level: <ParallelsRoot>/Users/<WinUser>/AppData/Local/TabularEditor3/BPARules.json
  • Machine-level: <ParallelsRoot>/ProgramData/TabularEditor3/BPARules.json

Other platforms:

  • VMware Fusion - Check /Volumes/ for mounted Windows drives
  • WSL on Windows - /mnt/c/Users/<username>/AppData/Local/TabularEditor3/

Note: The VM must be running for the filesystem to be accessible. If paths appear empty, start the Windows VM first.

Quick Reference

Rule JSON Structure

BPA rules have the following fields:

FieldRequiredTypeDescription
IDYesstringUnique identifier for the rule (e.g., META_MEASURE_NO_DESC)
NameYesstringHuman-readable name displayed in UI
CategoryNostringRule grouping (e.g., Performance, DAX Expressions, Metadata)
DescriptionNostringExplanation of why the rule matters. Supports placeholders: %object%, %objectname%, %objecttype%
SeverityYesintPriority level: 1 (Low), 2 (Medium), 3 (High)
ScopeYesstringComma-separated list of object types the rule applies to
ExpressionYesstringDynamic LINQ expression evaluated against scoped objects; returns true for violations
FixExpressionNostringDynamic LINQ expression to auto-fix violations (e.g., IsHidden = true)
CompatibilityLevelNointMinimum model compatibility level required for the rule to apply
RemarksNostringAdditional notes or context about the rule
{
  "ID": "RULE_PREFIX_NAME",
  "Name": "Human-readable rule name",
  "Category": "Performance|Formatting|Metadata|DAX Expressions|Naming Conventions|Governance",
  "Description": "Explanation of why this rule matters for %objecttype% '%objectname%'",
  "Severity": 2,
  "Scope": "Measure, CalculatedColumn, Table",
  "Expression": "DynamicLINQ expression returning true for violations",
  "FixExpression": "PropertyName = Value",
  "CompatibilityLevel": 1200
}

Valid Scope Values

All valid scope values from the RuleScope enum (can be combined with commas):

ScopeTOM TypeDescription
ModelModelThe entire semantic model
TableTableRegular tables (excludes calculated tables)
CalculatedTableCalculatedTableTables defined by DAX expressions
MeasureMeasureDAX measures
DataColumnDataColumnColumns from data source
CalculatedColumnCalculatedColumnColumns defined by DAX
CalculatedTableColumnCalculatedTableColumnColumns in calculated tables
HierarchyHierarchyUser-defined hierarchies
LevelLevelHierarchy levels
RelationshipSingleColumnRelationshipTable relationships
PartitionPartitionTable partitions
PerspectivePerspectiveModel perspectives
CultureCultureTranslations/cultures
KPIKPIKey Performance Indicators
CalculationGroupCalculationGroupTableCalculation group tables
CalculationItemCalculationItemItems within calculation groups
ProviderDataSourceProviderDataSourceLegacy/provider data sources
StructuredDataSourceStructuredDataSourceM/Power Query data sources
NamedExpressionNamedExpressionShared M expressions
ModelRoleModelRoleSecurity roles
ModelRoleMemberModelRoleMemberMembers of security roles
TablePermissionTablePermissionRLS table permissions
VariationVariationColumn variations
CalendarCalendarCalendar/date tables
UserDefinedFunctionUserDefinedFunctionDAX user-defined functions

Backwards compatibility: Column expands to DataColumn, CalculatedColumn, CalculatedTableColumn; DataSource expands to ProviderDataSource

Severity Levels

LevelNameMeaning
1LowInformational suggestion, minor improvement
2MediumWarning, should fix for quality
3HighError, must fix for correctness

Compatibility Levels

The CompatibilityLevel field specifies the minimum model version required. Rules only apply if the model's compatibility level >= the rule's level.

LevelPlatformFeatures Introduced
1200AAS/SSAS 2016JSON metadata format, base TOM
1400AAS/SSAS 2017Detail rows, object-level security, ragged hierarchies
1500AAS/SSAS 2019Calculation groups
1560+Power BIPower BI-specific features begin
1600SQL Server 2022Enhanced AS features
1702Power BI / FabricCurrent Power BI compatibility level (dynamic format strings, field parameters, DAX UDFs, etc.)

Note: Power BI models use 1560+ with current level at 1702. Use Model.Database.CompatibilityLevel in expressions to check the model's level.

Category Prefixes

Common ID prefix conventions:

PrefixCategory
DAX_DAX Expressions
META_Metadata
PERF_Performance
NAME_Naming Conventions
LAYOUT_Model Layout
FORMAT_Formatting
ERR_Error Prevention
GOV_Governance
MAINT_Maintenance

Expression Syntax Overview

BPA expressions use Dynamic LINQ with access to TOM (Tabular Object Model) properties.

Basic Patterns

// String checks
string.IsNullOrWhitespace(Description)
Name.StartsWith("_")
Expression.Contains("CALCULATE")

// Boolean checks
IsHidden
not IsHidden
IsVisible and not HasAnnotations

// Numeric checks
ReferencedBy.Count = 0
Columns.Count > 100

// Collection checks
DependsOn.Any()
Columns.All(IsHidden)

Common Properties by Scope

Measure:

  • Expression, FormatString, DisplayFolder, Description
  • IsHidden, IsVisible, ReferencedBy, DependsOn

Column:

  • DataType, SourceColumn, FormatString, SummarizeBy
  • IsHidden, IsKey, IsNullable, SortByColumn

Table:

  • Columns, Measures, Partitions, IsHidden
  • CalculationGroup (for calc group tables)

For complete expression syntax, see references/expression-syntax.md.

TMDL Annotations

BPA rules can be embedded in TMDL files via annotations:

annotation BestPracticeAnalyzer = [{ "ID": "...", ... }]
annotation BestPracticeAnalyzer_IgnoreRules = {"RuleIDs":["RULE1","RULE2"]}
annotation BestPracticeAnalyzer_ExternalRuleFiles = ["https://..."]

For complete annotation patterns, see references/tmdl-annotations.md.

Workflow

Creating a New Rule

  1. Identify the best practice to enforce
  2. Determine the appropriate Scope
  3. Write the Expression to detect violations
  4. Optionally write a FixExpression for auto-remediation
  5. Test against sample models
  6. Add to rule collection

Improving an Existing Rule

  1. Understand the current rule's intent
  2. Identify false positives or missed cases
  3. Refine the Expression logic
  4. Verify FixExpression doesn't cause side effects
  5. Test thoroughly

Additional Resources

Reference Files

For detailed syntax and patterns, consult:

  • schema/bparules-schema.json - JSON Schema for validating BPA rule files (Draft-07) (temporary location)
  • references/rule-schema.md - Human-readable BPA rule field descriptions
  • references/expression-syntax.md - Dynamic LINQ expression syntax, TOM properties, Tokenize(), DependsOn, ReferencedBy
  • references/tmdl-annotations.md - BPA annotations in TMDL format

Example Files

Working examples in examples/:

  • examples/comprehensive-rules.json - 30+ production-ready rules across all categories
  • examples/model-with-bpa-annotations.tmdl - TMDL file showing all annotation patterns

Scripts

Utility scripts:

  • /scripts/bpa_rules_audit.py - Comprehensive BPA rules audit across all sources (built-in, URL, model, user, machine). Supports Windows, WSL, and macOS with Parallels. Outputs ASCII report and JSON export.
  • scripts/validate_rules.py - Validate BPA rule JSON files for schema compliance

Audit Script Usage:

# Basic audit
python scripts/bpa_rules_audit.py /path/to/model

# Export to JSON
python scripts/bpa_rules_audit.py /path/to/model --json output.json

# Quiet mode (summary only)
python scripts/bpa_rules_audit.py /path/to/model --quiet
  • /suggest-rule - Generate BPA rules from descriptions
  • bpa-expression-helper - Debug and improve BPA expressions

External References

Example Rules

Measure Without Description

{
  "ID": "META_MEASURE_NO_DESCRIPTION",
  "Name": "Measure has no description",
  "Category": "Metadata",
  "Description": "All measures should have descriptions for documentation.",
  "Severity": 2,
  "Scope": "Measure",
  "Expression": "string.IsNullOrWhitespace(Description)"
}

Hidden Unused Column

{
  "ID": "PERF_UNUSED_HIDDEN_COLUMN",
  "Name": "Remove hidden columns not used",
  "Category": "Performance",
  "Description": "Hidden columns with no references waste memory.",
  "Severity": 3,
  "Scope": "Column",
  "Expression": "IsHidden and ReferencedBy.Count = 0 and not UsedInRelationships.Any()",
  "FixExpression": "Delete()"
}

スコア

総合スコア

60/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です