AI-Readiness
The flagship tab. It grades the open model from A to F for how well AI consumers (Copilot, Q&A and Fabric data agents) can answer questions from it, then turns every gap into a fix you can apply. Available in the Studio and over MCP, on the same live model.
A model can render its reports perfectly and still fail an AI consumer, because Copilot and data agents read the things a chart never shows: descriptions, unambiguous names, synonyms, a linguistic schema, documented relationships and the Prep-for-AI settings. AI-Readiness scores exactly those properties and tells you which ones to fix first.
#In the Studio
The AI-Readiness tab opens on the scorecard: an overall grade and a score out of 100, the per-category scores, the coverage KPIs and any gating reason, then a prioritized findings list grouped Category to Rule to Items. Each finding carries a severity and a fix badge, and the ones with a deterministic fix are click-to-fix inline. A readiness-trend sparkline tracks the score as you work, and any finding can be right-clicked to reveal the object in the Model tree or copy its reference.
#Over MCP
Your own AI Assistant drives the same analyzer through three tools. Start with the cheap summary on a large model, then pull only the findings you intend to act on.
ai_readiness_summary # cheap overview: grade + per-category scores + counts
ai_readiness_scan category=Descriptions # full findings, filterable by category / severity
ai_readiness_scan severityMin=High
ai_readiness_scan_live # adds the live cardinality / Q&A-scale rules
ai_readiness_summary returns the grade, the per-category score / applicable / violations,
the coverage KPIs and the counts by severity and fix-kind without the (potentially large) findings list.
ai_readiness_scan returns the findings themselves, filtered by category,
severityMin or maxFindings (the score and counts are always for the full
model; only the returned list is filtered).
ai_readiness_scan_live is the same scan plus the rules that need live data: it reads
per-column distinct-value counts from the attached connection and applies the Q&A index rules, so the
scale and cardinality categories are graded too. It needs a live connection (connect_xmla or
connect_local) and stays read-only.
#The category scorecard
The overall grade is a weighted roll-up of scored categories such as Naming, Descriptions, Relationships, DataAgentConfig and BestPractice. Two hard gates sit above the arithmetic, because some problems are not "a few points off":
- A model that exceeds the documented Q&A scale ceiling is capped at a D
(rule
LIMIT-SCALE): beyond that ceiling, Copilot and Q&A start dropping values. - When more than half of your objects have no description, the score is capped at 69: an AI consumer cannot reason about fields it has no words for.
#Honest scoring: no fake 100s
Every rule scores only the population it actually evaluates. A foreign-key visibility rule scores foreign-key columns, not all columns, so a handful of violations among hundreds of unrelated fields cannot dilute to a near-perfect result. When a rule does not apply to your model at all, its applicable population is zero and it stays dormant: it drops out of the category average rather than inflating it. The design is dormant-or-dock. A category can only reflect real, applicable violations, never an always-pass 100.
#Findings and fixes
Every finding is tagged with how it is fixed, and every finding is fixable, either deterministically or by you (with grounding).
| Fix kind | What it means | How to apply it |
|---|---|---|
| SafeFix | A deterministic, low-risk change (hide a foreign-key column, set SummarizeBy to None on a key, set a geographic data category). | apply_fix for
one finding, or apply_safe_fixes for all of them in one undoable batch. |
| AiContent | Content only you can author well: a business description, a clearer name, synonyms, AI instructions. | get_fix_prompt for grounding, then
set_description / set_synonyms / set_ai_instructions /
enable_qna / set_ai_data_schema. |
| Proposal | A change that should be reviewed before it lands (for example a rename that report bindings may depend on). | Reviewed and approved in a change plan, never applied silently. |
To do the whole pass at once, make_model_ai_ready applies every deterministic safe fix and
then returns the new scorecard alongside a prioritized AI-content work queue, each item carrying the
finding plus grounding (the DAX, the owning table, sibling names) so the authored text is accurate. Work
the queue, then re-scan.
Scoring, findings and single fixes are free. The one-click bulk paths (apply_safe_fixes,
make_model_ai_ready) and model-wide rule-level waivers are Pro. See
Pro for what the bulk engine adds.
#Prove answers in Tests
A score tells you the model reads well; a test tells you how it actually answers. The Tests tab keeps a pack of real questions and grades the model's answers deterministically, with four plain outcomes: Right, Safely said it couldn't answer, Confidently wrong and Couldn't check. Confidently wrong is the outcome this exists to catch: the answer that looks right and is not, found before your users find it.
Questions come in three kinds. A value question runs a query and compares the result to a number you trust. A paraphrase question asks the same thing two ways and requires the answers to agree, which catches silent wrongness with no ground truth at all. A refusal question is one the model cannot answer: declining is the pass, and producing a confident number is exactly the failure being caught.
list_tests # saved model tests
run_tests # run the selected set and grade every result
list_test_runs # read prior results
save_test # save a reviewed regression test (Pro)
export_test_report # produce a shareable report
The grading is engine-run and deliberately high-precision: offline, an erroring query, a truncated comparison or a missing trusted answer all come back as Couldn't check, never a fabricated pass and never a fabricated failure. When a question fails, the result names the readiness rule that prevents that class of failure, so the fix is one step away. Your AI assistant is the natural author here: it proposes the questions and the DAX, and the engine does all the grading. Running questions is free; saving them into the replayable pack, which also powers the interview check available to workflow gates, is Pro.
The value grading is strict in the ways that matter with real numbers. A blank is never "close
enough" to zero, in either direction: an empty cell where a real figure belongs grades as confidently
wrong, and the literal BLANK records that the right answer is no value at all. Numbers
must match within a tolerance that stays tight at scale (one part in a billion, with an absolute floor
of one millionth), so a drift of fifty on a billion-scale total is caught rather than waved through.
And a question run without a trusted answer shows you the cleanly computed number so you can confirm
it and save it; it is never auto-trusted, because self-verification is not verification.
#Ready-made questions
You do not have to invent the pack from scratch. list_interview_seeds proposes
candidates from two deterministic sources. If the model carries verified answers from its Prep-for-AI
settings, each one becomes a candidate carrying its trigger question, the alternative phrasings and
the fields it references, so the answers your organisation has already blessed become regression
checks. And a built-in hard-question pack ships twelve model-agnostic templates drawn from the
question families AI most often gets confidently wrong: ranks with ties, year-to-date under a text
date attribute, rolling twelve-month distinct counts, the prior full period, share of the grand total,
semi-additive closing balances, same period last year, retention cohorts, weighted averages, totals
over an inactive relationship, blank versus zero, and whether the grand total actually adds up. A
template only instantiates when your model has the shapes it needs (a marked date table, a measure to
target); anything that cannot bind is listed as skipped, naming the exact missing piece. No candidate
ever arrives with a trusted answer attached: you run it, confirm the number, then save it. The
Tests tab shows each seeded question's provenance in plain words.
#At ship time
The pack also works at ship time: the deploy gate replays your saved questions and reports the tally as an advisory beside its blockers, calling out any question whose outcome changed since it was last asked. Advisory means advisory: the interview never blocks a deploy, a broken question store never breaks the gate, and offline the replay reports Couldn't check rather than a fabricated pass, and never overwrites the last real outcomes. The Deploy tab shows it as a plain line under the gate result.
#Model health, after every change
You should not have to re-run a scan to learn that an edit hurt the model. After every committed change, from either door, the engine works out what that change did to model health and surfaces it where the author is: a status-bar chip for you ("Model health: B → C. This change added 2 issues and affects 3 things."), and a terse health note appended to the tool result for the AI Assistant, read at the moment it can still fix what it just did.
The delta is scoped and honest: it reports the grade movement, the net-new findings on the objects the change touched (pre-existing problems are never re-blamed on your edit), and how many downstream objects the change reaches. Quiet changes stay quiet: nothing is shown unless the grade moved, a new warning landed, or something downstream is affected. Clicking the chip opens this tab. The ambient health check is a Pro feature, and without it nothing changes about how edits work.
#Waivers, honestly
Some findings are decisions, not defects ("we keep these unused columns on purpose").
waive_finding accepts a finding so it stops counting against the score, but honestly: a
reason is required, the waiver is recorded on the model with who and when, and the finding is still
surfaced (tagged waived, with its reason) while the scorecard reports a waived count. Waivers never lift
the hard gates. A per-instance waiver is free; waiving an entire rule model-wide is the Pro bulk lever.
list_waivers shows the audit trail and unwaive_finding reinstates one.
#Where the rules come from
The analyzer is built from a fact-checked Microsoft requirements catalogue. Version 1.0 reached the high-value, observable cutoff: a rule ships when the model exposes enough evidence to detect it precisely. Research rows that would require guesswork stay outside the score rather than creating weak findings.
Curious how real models score? We scanned 40 public semantic models and the median grade was an F. The full method and corpus are documented with the project.
#Write your own rules
The built-in ruleset is not the ceiling. The Custom rules panel on this tab lets you author readiness rules of your own: pick one of the existing categories, a severity and a scope, then write the violation predicate in the same expression language the Best Practice rules use (there is never a second language to learn). The New rule form starts you from templates, validates as you type through the engine's real parser, and shows a labelled test run against the open model before you save: how many objects the rule applies to, how many it flags, and the first few names, so you know exactly what you wrote before it counts. An "Ask the AI Assistant for help" button copies a ready-to-paste authoring prompt, so your assistant can draft the rule and the same validation judges it.
Custom rules score with the same honesty as the built-ins. An optional applies-to filter defines the population the rule evaluates, and a rule whose population is empty stays dormant: it never inflates its category. Custom rules can never override a built-in rule or create a hard gate, and a rule that breaks (an expression that no longer compiles, a hand-edited annotation) goes dormant and reports itself in a banner rather than silently skewing the score. Findings from your rules are tagged as custom, and waivers work on them unchanged. Authoring is free.
validate_rule kind="readiness" rules={...} # compile + test-run against the open model, nothing saved
load_readiness_rules rules=[...] # save onto the model (merge by id; undoable)
get_custom_rules # both kinds, plus the category and scope vocabularies
reset_readiness_rules # back to the built-ins only
Rules are stored on the model itself, so they travel with it: a teammate opening the same model
scores against the same rules. The Best Practice tab has
the same panel for BPA rules, and the one validate_rule operation previews both
kinds.
Semanticus