# Pbi Verify Loop

> Visually verify Power BI report edits against a running Power BI Desktop instance. Refresh the canvas from disk, wait until rendering is stable (no guessed sleeps), screenshot the page, and optionally diff against a mockup. Use after ANY edit to PBIR visual.json / pages / theme when Desktop is open, and whenever the user asks to "check the report", "verify the change", "screenshot the page", or a mockup comparison is needed. Replaces hand-rolled refresh + Start-Sleep + screenshot loops.

- Skill: `insightfulanalytics/pbi-verify-loop` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add insightfulanalytics/pbi-verify-loop`
- Raw SKILL.md: https://api.skillmd.com/api/skills/insightfulanalytics/pbi-verify-loop/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: InsightfulAnalytics (https://skillmd.com/u/insightfulanalytics)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/insightfulanalytics/pbi-verify-loop

---


# PBI verify loop

One command replaces the `pbir desktop refresh` → `Start-Sleep <guess>` → `pbir desktop screenshot` cycle:

```bash
python "${CLAUDE_PLUGIN_ROOT}/skills/pbi-verify-loop/scripts/verify_page.py" \
  "MyReport.Report/ReportSection1.Page" -o "<scratchpad>/page.png"
```

The script refreshes the report from disk, then captures repeatedly (every 3s, up to 45s) until two consecutive screenshots are byte-identical. That is the "settled" signal. It prints JSON (`output`, `captures`, `stable`, `changed_from_baseline`) and exits 0 when stable, 2 on timeout (the last capture is still written, so inspect it anyway).

`changed_from_baseline` compares the final capture against a screenshot taken *before* the refresh, so a two-identical-captures loop cannot settle on the pre-edit canvas. `false` means the refresh produced a pixel-identical page: the edit may not have reached disk, or Desktop did not pick it up, so check that before reporting the change as verified. It is `null` under `--no-refresh`, where there is no baseline to compare against.

## Options

| Flag | Use |
|---|---|
| `--model` | Also re-apply the TMDL model (`refresh -m`); needed after model.tmdl/measure edits |
| `--no-refresh` | Just settle+capture (e.g. after the user changed something in Desktop) |
| `--compare mockup.png` | Diff final capture vs a reference; writes `<out>-vs-ref.png` side-by-side and reports `diff_ratio` + `diff_bbox` |
| `--region x,y,w,h` | Crop both images to a region before comparing (verify one visual, ignore the rest) |
| `--scale 1-3` | Render scale (default 2) |
| `--timeout` / `--interval` | Stability polling knobs (default 45s / 3s) |

## Workflow

1. Edit PBIR/TMDL files on disk (the `pbip` plugin's `tmdl` and `pbir-format` skills cover the hand-authoring rules and gotchas).
2. Run `pbir validate` if visual.json was touched.
3. Run this script; **Read the output PNG** and judge the change visually before telling the user it's done.
4. For mockup-driven work (Claude Design), pass `--compare` with the mockup and check `diff_ratio`, but always eyeball the side-by-side too; pixel diffs can't judge intent.

## Preconditions & gotchas

- Power BI Desktop must be running with the report open, and the preview feature **"external tool access to Power BI Desktop through secure local APIs"** enabled (Options → Preview features, restart Desktop). Check with `pbir desktop list`. If it errors or shows nothing, that preview is off: tell the user to enable it and restart Desktop rather than retrying. Where it stays off, `reports:desktop-screen-capture` screenshots the Desktop window directly, and where Desktop is unavailable at all, render the published report server-side with `ExportTo` (`fabric-cli:fabric-cli`, `references/reports.md`).
- **`pbir desktop list` first, always**: if the instance shows `Unsaved: yes`, a refresh reloads from disk and can clobber the user's unsaved in-Desktop tweaks, so use `--no-refresh` or ask them to save first.
- Page path form is `Report.Report/PageName.Page` (folder names from `definition/pages/`), not display names. Omit the page to capture the first page.
- Full-flag reference for `pbir desktop`: the `pbir-cli` skill's `references/cli-reference.md` (Desktop Operations section). Key gotchas: the screenshot output flag is `-o/--output` (there is no `--out`), and `--settle` applies only with `--all`.
- If the capture never stabilizes (exit 2), something is animating or Desktop is stuck refreshing. Check `pbir desktop list` for unsaved/busy state instead of raising the timeout blindly.

