Skip to main content

Offline, advisory DAX/model standards linter for Power BI semantic models: parses TMDL/.bim, checks measures and model structure against the team's DAX standards, and reports anything that doesn't match. Human report + machine JSON for the company agent. Never edits or blocks.

Project description

coop-dax-review

Offline, advisory DAX/model standards linter for our Power BI semantic models. It parses TMDL (and legacy .bim) models, builds a model catalog, checks measures and model structure against docs/standards.md (our DAX standards + Microsoft/Tabular best practices), and surfaces anything that doesn't match. It never edits or blocks — it only reports. Two outputs: a human console report and machine JSON for the company analytics agent.

Sibling tool to coop-sql-review — same architecture and contracts.

Install

pipx install coop-dax-review        # once on PyPI

Use pipx, not system pip, so the tool stays isolated from other CLIs (ms-fabric-cli, azure-cli) it might otherwise fight over shared pins. For local development:

python -m venv .venv && .venv/bin/pip install -e ".[dev]"

Usage

coop-dax-review check [MODEL_PATHS...] [--format text|json] [--min-severity error|warning|info] [--strict]
coop-dax-review rules                 # list every rule (id, severity, tier, agent?)
coop-dax-review --version
  • MODEL_PATHS point at a PBIP/TMDL model folder (*.SemanticModel/definition/...), any folder of .tmdl files, or a legacy .bim file. Directories are searched recursively; defaults to ..
  • Advisory: exit code is always 0. --strict is the opt-in CI gate — exit 2 when any finding remains at/above --min-severity.
  • --standards <path> overrides the bundled standards (e.g. point it at a canonical company standards file). Its sha256 travels in the JSON so the agent knows which standards a report used.
  • A rules.yml beside the standards file (or --config) can disable rules / override severities with no rebuild.
coop-dax-review check ./MyModel.SemanticModel
coop-dax-review check . --format json --strict --min-severity warning

What it checks

Run coop-dax-review rules for the live list. Deterministic rules (reported as findings):

Rule § Sev Flags
DAX-MEASURE-CATEGORY 1 warning measure not named [Category: Name]
DAX-MEASURE-NOT-PREFIXED 1 warning Table[X] where X is a measure (measures take no prefix)
DAX-COLUMN-PREFIXED 1 warning bare [X] where X is a column (columns need Table[X])
DAX-VAR-RETURN 2 info non-trivial measure with no VAR/RETURN structure
DAX-NO-NESTED-CALCULATE 3 warning CALCULATE nested inside CALCULATE
DAX-FILTER-TABLE-IN-CALCULATE 4 warning FILTER(<table>, <col> = ...) where a plain column filter suffices
DAX-SNOWFLAKE 6 info a table with relationships chained through it (snowflake link)
DAX-BIDI-RELATIONSHIP 7 warning a bidirectional cross-filter relationship
DAX-MARKED-DATE-TABLE 8 warning time-intelligence used but no marked Date table
DAX-MEASURE-IN-ITERATOR 9 info a measure referenced inside a row iterator (hidden context transition)
DAX-COMPLEX-NO-HEADER 12 info a complex measure (≥3 VARs) without a /* ... */ header
DAX-DIRECTLAKE-NO-CALC-COL 13 warning a calculated column in a Direct Lake model
DAX-USE-DIVIDE 14 warning the / operator where DIVIDE() should be used
DAX-FORMAT-STRING 15 warning a measure with no explicit formatString
DAX-NO-FLOAT-KEYS 16 info a relationship key column typed double
DAX-HIDE-FK-COLUMNS 17 info a visible foreign-key (relationship) column
DAX-KEY-SUMMARIZEBY-NONE 18 info a numeric key column that auto-aggregates (summarizeBy ≠ none)
DAX-DISPLAY-FOLDERS 19 info a measure-heavy table with no display folders

Agent-judgment rules — the tool detects the construct but emits to the JSON agent_review list (never an auto-finding), because the call needs intent the linter can't infer:

Rule § Judges
DAX-KEEPFILTERS-NEEDED 5 whether a CALCULATE boolean filter needs KEEPFILTERS
DAX-STAR-SCHEMA 6 whether a snowflake chain should be flattened to a star
DAX-CONTEXT-TRANSITION 9 whether an iterator's context transition is intended/correct
DAX-SIMPLE-FUNCTIONS 10 whether a CALCULATE-heavy measure could use simpler functions
DAX-VALIDATION 11 whether the §11 validation checklist was run for a non-trivial measure
DAX-IMPLICIT-MEASURE 20 whether a visible auto-aggregating numeric column should become an explicit measure

See RULES.md for the full taxonomy. docs/standards.md §14–§20 are adopted Microsoft/Tabular best practices (DIVIDE, format strings, key column types, hidden FKs, key summarizeBy, display folders, explicit measures); docs/standards-proposed-additions.md is the original candidate list.

Agent JSON contract

{
  "tool": "coop-dax-review", "version": "x.y.z",
  "standards": {"path": "...", "sha256": "..."},
  "findings": [{"rule_id":"...","severity":"warning","model":"Sales","file":"...","line":12,
                "object":"[Sales: Revenue YTD]","message":"...","standard_ref":"§3"}],
  "summary": {"error":0,"warning":2,"info":4},
  "agent_review": [{"rule_id":"...","object":"[...]","note":"...","standard_ref":"§5"}],
  "diagnostics": [{"severity":"warning","category":"parse_failed","file":"...","message":"..."}]
}

Project docs

  • SPEC.md — architecture, CLI, agent contract, milestones.
  • RULES.md — every standard mapped to a concrete check (deterministic vs agent-judgment).
  • docs/standards.md — the canonical DAX standards the linter checks against (bundled as package data).
  • CLAUDE.md — orientation for Claude Code sessions in this repo.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

coop_dax_review-0.1.0.tar.gz (47.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

coop_dax_review-0.1.0-py3-none-any.whl (70.7 kB view details)

Uploaded Python 3

File details

Details for the file coop_dax_review-0.1.0.tar.gz.

File metadata

  • Download URL: coop_dax_review-0.1.0.tar.gz
  • Upload date:
  • Size: 47.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for coop_dax_review-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0687a17c4fa6e3f1a479cc3aa6b78ad6ad4255623ad74ee28e1f99c1343e9d07
MD5 adb4f15c1f694da324c7ba0c51583f1b
BLAKE2b-256 eb1fc7ae070427a692434fec4705e074e9b5499621fffb42c69eb3bf69db5feb

See more details on using hashes here.

Provenance

The following attestation bundles were made for coop_dax_review-0.1.0.tar.gz:

Publisher: publish.yml on kabukisensei/coop-dax-review

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file coop_dax_review-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: coop_dax_review-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 70.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for coop_dax_review-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 482b1d764e3b32d17dd1ffce7b06c28da4a72926abf5c62cc90d9293ab8d021d
MD5 1e6ce7318e43ae808a772fb9aa72a487
BLAKE2b-256 e184f6e5bf95126c4b170e7b7daca9973fbf6470fc6cc6e108bc597822a03d3a

See more details on using hashes here.

Provenance

The following attestation bundles were made for coop_dax_review-0.1.0-py3-none-any.whl:

Publisher: publish.yml on kabukisensei/coop-dax-review

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page