Skip to content

Scripts

Every script runs in PowerShell 7 (pwsh) on Windows 11, and most also run on macOS. None installs system software. Get the same help in a terminal with Get-Help ./scripts/<name>.ps1 -Detailed.

Catches you up to the end of a lab by restoring the model from an upstream checkpoint tag.

Details

Use this when you want to skip a lab or start over from a known-good state.

  1. Stops if you have uncommitted changes. Commit or stash them first; the script won’t do it.
  2. Fetches the checkpoint tag from the upstream lab repo.
  3. Creates a new branch, lab/<checkpoint>-<timestamp>, from your current commit.
  4. Restores only fabric/ and lab/samples/ from the tag and stages the result.
  5. Creates the gitignored outputs the checkpoint implies (a local-baseline run, the sample assessment) when they don’t exist yet.

Your other files (instructions, agents, skills, prompts you wrote) are left alone. Close Power BI Desktop first, and reopen the project afterward.

ParameterMeaning
-Checkpointlab02-start, lab05-complete, lab06-complete, lab07-complete, lab08-complete, or lab09-complete.
-RemoteThe remote that points at the upstream lab repo. Default: upstream.
-ListList the checkpoints and exit.
Terminal window
pwsh ./scripts/lab/Restore-LabCheckpoint.ps1 -Checkpoint lab07-complete
pwsh ./scripts/lab/Restore-LabCheckpoint.ps1 -List

Runs the lab site locally at http://localhost:4321/ so you can read the labs offline or preview edits.

Details

Installs the site’s pinned Node packages with npm ci the first time, then starts the Astro dev server. Press Ctrl+C to stop it. Needs Node.js 20 or later.

ParameterMeaning
-BuildBuild the static site into site/dist and run the content checks instead of starting the server.
Terminal window
pwsh ./scripts/lab/Start-LabSite.ps1

Maintainers and upstream CI: checks that every checkpoint tag exists and passes its lab checks.

Details

For each checkpoint in lab/checkpoints.json, checks out the tag into a temporary worktree, creates the outputs a restore would create, runs the full validation, and runs the lab checks listed under verify. Aliases (baseline-v1, ai-ready-v1) must point at the same commit.

ParameterMeaning
-FetchFetch tags from this remote first, for example origin.
-AllowMissingReport missing tags as warnings instead of failures (useful before the first release).
Terminal window
pwsh ./scripts/lab/Test-CheckpointTags.ps1 -Fetch origin

Checks whether you finished a lab, and tells you what to fix and where on the lab site.

Details

Runs the checks for one lab from lab/checks.yaml. Each result is PASS, FAIL, WARN (an optional check failed), or SKIP (Windows-only check on another OS). Failures include a hint and a link to the step on the lab site. Exits 0 when every required check passes.

Lab 00 runs before the Python environment exists, so it uses scripts/Test-Prerequisites.ps1.

ParameterMeaning
-LabLab number, for example 7 or 07.
-OnlyRun only these check IDs, comma-separated.
-JsonPrint results as JSON.
Terminal window
pwsh ./scripts/lab/Test-LabProgress.ps1 -Lab 07

Copilot hook entry point on Windows. Forwards the hook payload to python -m pharmacy_demo hook.

Details

Referenced by .github/hooks/guardrails.json. Reads the JSON payload from stdin and passes it to the Python handler, which prints a decision (deny or ask) or nothing. If the repo’s .venv doesn’t exist yet, the hook does nothing and lets the tool call through, so a fresh clone still works before scripts/Initialize-DevEnvironment.ps1 has run.

ParameterMeaning
-HookEventsession-start, pre-tool-use, post-tool-use, or session-end.

Maintainers only: builds the reference/ai-ready branch and the checkpoint tags.

Details

Starting from a commit with the baseline model (normally the release commit on main):

  1. Tags it baseline-v1, checkpoint/lab02-start, and checkpoint/lab05-complete.
  2. In a temporary worktree on reference/ai-ready, commits one step per checkpoint: lab06 (sample assessment), lab07 (names), lab08 (relationships and measures), lab09 (AI metadata), generating each model stage with pharmacy_demo modelgen.
  3. Runs validation and the lab checks for every step before tagging it.
  4. Removes the worktree. Nothing is pushed unless you pass -Push.

The answers live only on reference/ai-ready and the tags, so learner copies made with Use this template don’t contain them.

ParameterMeaning
-SourceCommit to build from. Default: HEAD.
-ForceMove existing tags and reset reference/ai-ready.
-PushPush reference/ai-ready and all checkpoint tags to -Remote when done.
-RemoteRemote to push to. Default: origin.
Terminal window
pwsh ./scripts/maintainer/New-LabCheckpoints.ps1
pwsh ./scripts/maintainer/New-LabCheckpoints.ps1 -Force -Push

Compares two graded question runs and writes a Markdown before-and-after table.

ParameterMeaning
-BeforeRun label or path for the earlier run, for example local-baseline.
-AfterRun label or path for the later run, for example local-ai-ready.
-OutFileWhere to write the table. Default: out/question-comparison.md.
Terminal window
pwsh ./scripts/Compare-QuestionRuns.ps1 -Before local-baseline -After local-ai-ready
pwsh ./scripts/Compare-QuestionRuns.ps1 -Before sample-baseline -After sample-ai-ready

Prints the five business questions, their paraphrases, and the answer columns, without answers.

Details

This is the only way agents and learners should read the question set. The full file, evaluation/questions.yaml, also holds reference answers and is hidden from agents by the hooks.

ParameterMeaning
-JsonPrint the questions as JSON.
Terminal window
pwsh ./scripts/Get-BusinessQuestions.ps1

Grades a question run against the expected answers and writes the grade into the run file.

Details

A run file (evaluation/runs/<label>.json) holds the answers an agent or person gave to the five business questions. Each question scores 0, 1, or 2 using the rubric in evaluation/rubric.md.

ParameterMeaning
-RunA run label such as local-baseline, or a path to a run file.
-NoWritePrint the grade without updating the run file.
-JsonPrint the grade as JSON.
Terminal window
pwsh ./scripts/Grade-QuestionRun.ps1 -Run local-baseline

Creates the repo’s Python environment (.venv) and installs the pinned lab tools.

Details
  1. Finds Python 3.12+ (the py launcher on Windows, then python3 or python).
  2. Creates .venv in the repo root if it doesn’t exist.
  3. Installs tools/python/requirements-dev.txt with —require-hashes, then the pharmacy_demo package in editable mode.
  4. Optionally runs npm ci in site/ so you can preview the lab site locally.
  5. Runs the validation suite once.

It doesn’t install system software. Run scripts/Test-Prerequisites.ps1 first if you’re not sure what’s installed.

ParameterMeaning
-ForceDelete and recreate .venv.
-SiteAlso install the lab site’s Node packages (needs Node.js 20+).
Terminal window
pwsh ./scripts/Initialize-DevEnvironment.ps1

Runs the reference DAX for each business question against the model open in Power BI Desktop and checks the results against the expected answers (Windows only).

Details
  1. Finds the local Analysis Services instance that Power BI Desktop starts for an open model.
  2. Loads ADOMD.NET from .tools/adomd/. With -AllowDownload it downloads the pinned Microsoft.AnalysisServices.AdomdClient package from nuget.org first and checks its SHA-512.
  3. Runs each question’s reference DAX and grades the rows with the same grader the question runs use.
  4. Writes out/dax-tests.json with PASS or FAIL per question. The DAX itself isn’t printed.

The reference DAX uses the business names from Lab 08, so run this after Lab 08 with fabric/ContosoPharmacy.pbip open and refreshed.

ParameterMeaning
-PortThe Desktop Analysis Services port. Default: found from msmdsrv.port.txt (newest instance).
-AllowDownloadDownload ADOMD.NET from nuget.org into .tools/adomd/ if it isn’t there yet.
-OutFileWhere to write results. Default: out/dax-tests.json.
Terminal window
pwsh ./scripts/Invoke-DaxQuestionTests.ps1 -AllowDownload

Runs every validation step that doesn’t need a Fabric tenant or Power BI Desktop.

Details

Checks that the synthetic data matches the seed, the expected answers are current, the question and run files match their schemas, the TMDL lints clean, every report visual binds to a field that exists, and the repository hygiene rules pass (no PHI-like columns, identifiers, secrets, forbidden files, or dashes in prose). This is the same check CI runs on every pull request.

ParameterMeaning
-OnlyRun only these steps, comma-separated: data, expected, questions, runs, tmdl, bindings, customizations, hygiene.
-JsonPrint results as JSON.
-TestsAlso run the Python unit tests (pytest) and the Pester tests.
Terminal window
pwsh ./scripts/Invoke-Validation.ps1
pwsh ./scripts/Invoke-Validation.ps1 -Only tmdl,bindings

Regenerates the synthetic CSV files in data/generated/, or checks that they match the seed.

Details

The data is deterministic: the same seed always produces the same bytes on Windows, macOS, and Linux. Only change the data by changing tools/python/pharmacy_demo/datagen.py; then run this script and scripts/Update-ExpectedResults.ps1.

ParameterMeaning
-CheckDon’t write anything. Exit 1 if the committed files differ from the generator.
Terminal window
pwsh ./scripts/New-SyntheticData.ps1 -Check

Points C:\ContosoPharmacyDemo\data at this clone’s data\generated folder (Windows only).

Details

The semantic model reads the CSV files from the DataFolderPath parameter, which defaults to C:\ContosoPharmacyDemo\data. This script creates that path as a directory junction to data\generated in your clone, so the model works wherever you cloned the repo, including paths with spaces. Junctions don’t need administrator rights or Developer Mode.

If the path already exists as a junction it’s replaced. If it’s a real folder with files in it, the script stops and changes nothing.

ParameterMeaning
-PathWhere to create the link. Default: C:\ContosoPharmacyDemo\data. If you change it, also change DataFolderPath in Power BI Desktop (Transform data > Edit parameters).
-RemoveRemove the junction (and the parent folder if it’s empty). Your data isn’t touched.
Terminal window
pwsh ./scripts/Set-LocalDataLink.ps1
pwsh ./scripts/Set-LocalDataLink.ps1 -Remove

Lists where the semantic model breaks the team conventions in rules/*.yaml.

Details

Rules C01 to C15 cover names, descriptions, hidden keys, summarization, relationships, the date table, measures, display folders, and AI metadata flags. The baseline model breaks most of them on purpose. This is the deterministic check behind the model-assessor agent and Labs 07 to 09. By default it reports findings and exits 0; use -Strict to exit 1 when there are findings.

ParameterMeaning
-RuleOnly report these rule IDs, comma-separated, for example C01,C02.
-JsonPrint findings as JSON.
-MarkdownPrint findings as a Markdown table (Rule, Severity, Object, Finding, Fix).
-OutFileAlso write the Markdown table to this file.
-StrictExit 1 when there are findings.
Terminal window
pwsh ./scripts/Test-ModelConventions.ps1 -Rule C01

Checks that the tools the labs need are installed. Installs nothing.

Details

Reports each tool as PASS, FAIL, WARN (optional or old), or SKIP (not applicable on this OS), with the install command to run yourself. Exits 1 when a required tool is missing.

Required everywhere: PowerShell 7.4+, Git 2.40+, Python 3.12+, VS Code. Required on Windows: Power BI Desktop, Git core.longpaths. Optional: Node.js 20+ (lab site and Power BI Modeling MCP via npx), GitHub CLI, Copilot CLI.

ParameterMeaning
-JsonPrint results as JSON.
Terminal window
pwsh ./scripts/Test-Prerequisites.ps1

Checks that every field used by a report visual exists in the semantic model.

Details

Reads the PBIR visual.json files and the TMDL model, then lists visuals that point at a table, column, or measure that doesn’t exist (usually after a rename). Use the pbir-rebinding skill to fix what it finds.

ParameterMeaning
-JsonPrint problems as JSON.
Terminal window
pwsh ./scripts/Test-ReportBindings.ps1

Recomputes evaluation/expected/*.json from the synthetic CSVs with DuckDB, or checks them.

Details

The expected answers come from reference SQL that runs directly over the CSV files, so they never depend on the semantic model being right. Run this after regenerating the data.

ParameterMeaning
-CheckDon’t write anything. Exit 1 if the committed answers are out of date.
Terminal window
pwsh ./scripts/Update-ExpectedResults.ps1 -Check