bi-superpowers 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +31 -0
- package/.claude-plugin/plugin.json +34 -0
- package/.claude-plugin/skill-manifest.json +79 -0
- package/.mcp.json +13 -0
- package/.plugin/plugin.json +14 -0
- package/LICENSE +21 -0
- package/README.md +849 -0
- package/bin/build-plugin.js +97 -0
- package/bin/cli.js +891 -0
- package/bin/commands/autoupdate.js +128 -0
- package/bin/commands/build-desktop.js +368 -0
- package/bin/commands/create-from-template.js +165 -0
- package/bin/commands/diff.js +435 -0
- package/bin/commands/install.js +542 -0
- package/bin/commands/lint.js +441 -0
- package/bin/commands/mcp-setup.js +255 -0
- package/bin/commands/session-update.js +204 -0
- package/bin/commands/smoke-test.js +20 -0
- package/bin/commands/uninstall.js +611 -0
- package/bin/commands/update-check.js +427 -0
- package/bin/commands/validate-cases.js +264 -0
- package/bin/commands/validate-projects.js +426 -0
- package/bin/commands/watch.js +251 -0
- package/bin/lib/agents.js +62 -0
- package/bin/lib/base-template-smoke.js +299 -0
- package/bin/lib/claude-hooks.js +160 -0
- package/bin/lib/generators/claude-plugin.js +529 -0
- package/bin/lib/generators/index.js +116 -0
- package/bin/lib/generators/shared.js +257 -0
- package/bin/lib/mcp-config.js +835 -0
- package/bin/lib/microsoft-mcp.js +206 -0
- package/bin/lib/powerbi-mcp-session.js +140 -0
- package/bin/lib/skills.js +164 -0
- package/bin/lib/template-scaffold.js +366 -0
- package/bin/mcp/powerbi-modeling-launcher.js +42 -0
- package/bin/postinstall.js +50 -0
- package/bin/utils/mcp-detect.js +346 -0
- package/bin/utils/tui.js +314 -0
- package/commands/bi-connect.md +520 -0
- package/commands/bi-dax.md +464 -0
- package/commands/bi-kickoff.md +550 -0
- package/commands/bi-modeling.md +485 -0
- package/commands/bi-performance.md +521 -0
- package/commands/bi-powerquery.md +229 -0
- package/commands/bi-refactor.md +249 -0
- package/commands/bi-scorecard.md +268 -0
- package/commands/bi-start.md +272 -0
- package/config.example.json +23 -0
- package/config.json +23 -0
- package/desktop-extension/manifest.json +30 -0
- package/desktop-extension/package.json +10 -0
- package/desktop-extension/server.js +137 -0
- package/package.json +94 -0
- package/skills/bi-connect/SKILL.md +522 -0
- package/skills/bi-connect/scripts/update-check.js +427 -0
- package/skills/bi-dax/SKILL.md +466 -0
- package/skills/bi-dax/scripts/update-check.js +427 -0
- package/skills/bi-kickoff/SKILL.md +552 -0
- package/skills/bi-kickoff/references/flow.html +78 -0
- package/skills/bi-kickoff/references/flow.md +62 -0
- package/skills/bi-kickoff/scripts/update-check.js +427 -0
- package/skills/bi-modeling/SKILL.md +487 -0
- package/skills/bi-modeling/scripts/update-check.js +427 -0
- package/skills/bi-performance/SKILL.md +523 -0
- package/skills/bi-performance/scripts/install-tabular-editor.ps1 +159 -0
- package/skills/bi-performance/scripts/run-bpa.ps1 +265 -0
- package/skills/bi-performance/scripts/update-check.js +427 -0
- package/skills/bi-powerquery/SKILL.md +231 -0
- package/skills/bi-powerquery/references/base-template-data-contract.md +323 -0
- package/skills/bi-powerquery/references/power-query-standards.md +74 -0
- package/skills/bi-powerquery/scripts/new-powerquery-staging.ps1 +371 -0
- package/skills/bi-powerquery/scripts/test-powerquery-contract.ps1 +225 -0
- package/skills/bi-powerquery/scripts/update-check.js +427 -0
- package/skills/bi-refactor/SKILL.md +251 -0
- package/skills/bi-refactor/references/flow.md +27 -0
- package/skills/bi-refactor/scripts/update-check.js +427 -0
- package/skills/bi-scorecard/SKILL.md +270 -0
- package/skills/bi-scorecard/examples/base-template-scorecard-overlay.json +82 -0
- package/skills/bi-scorecard/scripts/new-scorecard-blueprint-from-base-template.ps1 +124 -0
- package/skills/bi-scorecard/scripts/powerbi-goal-status-rules-api.ps1 +39 -0
- package/skills/bi-scorecard/scripts/powerbi-goal-values-api.ps1 +48 -0
- package/skills/bi-scorecard/scripts/powerbi-goals-api.ps1 +68 -0
- package/skills/bi-scorecard/scripts/powerbi-rest-common.ps1 +197 -0
- package/skills/bi-scorecard/scripts/powerbi-scorecards-api.ps1 +53 -0
- package/skills/bi-scorecard/scripts/update-check.js +427 -0
- package/skills/bi-start/SKILL.md +274 -0
- package/skills/bi-start/scripts/update-check.js +427 -0
- package/src/content/base.md +197 -0
- package/src/content/mcp-requirements.json +57 -0
- package/src/content/routing.md +201 -0
- package/src/content/skills/bi-connect.md +493 -0
- package/src/content/skills/bi-dax.md +437 -0
- package/src/content/skills/bi-kickoff/SKILL.md +523 -0
- package/src/content/skills/bi-kickoff/references/flow.html +78 -0
- package/src/content/skills/bi-kickoff/references/flow.md +62 -0
- package/src/content/skills/bi-modeling.md +458 -0
- package/src/content/skills/bi-performance/SKILL.md +494 -0
- package/src/content/skills/bi-performance/scripts/install-tabular-editor.ps1 +159 -0
- package/src/content/skills/bi-performance/scripts/run-bpa.ps1 +265 -0
- package/src/content/skills/bi-powerquery/SKILL.md +202 -0
- package/src/content/skills/bi-powerquery/references/base-template-data-contract.md +323 -0
- package/src/content/skills/bi-powerquery/references/power-query-standards.md +74 -0
- package/src/content/skills/bi-powerquery/scripts/new-powerquery-staging.ps1 +371 -0
- package/src/content/skills/bi-powerquery/scripts/test-powerquery-contract.ps1 +225 -0
- package/src/content/skills/bi-refactor/SKILL.md +222 -0
- package/src/content/skills/bi-refactor/references/flow.md +27 -0
- package/src/content/skills/bi-scorecard/SKILL.md +241 -0
- package/src/content/skills/bi-scorecard/examples/base-template-scorecard-blueprint.expected.json +105 -0
- package/src/content/skills/bi-scorecard/examples/base-template-scorecard-overlay.json +82 -0
- package/src/content/skills/bi-scorecard/scripts/new-scorecard-blueprint-from-base-template.ps1 +124 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-goal-status-rules-api.ps1 +39 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-goal-values-api.ps1 +48 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-goals-api.ps1 +68 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-rest-common.ps1 +197 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-scorecards-api.ps1 +53 -0
- package/src/content/skills/bi-start.md +266 -0
- package/templates/base-template/AGENTS.md +33 -0
- package/templates/base-template/base-template.Report/.platform +11 -0
- package/templates/base-template/base-template.Report/StaticResources/RegisteredResources/BISuperpowers.json +3888 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BaseThemes/CY18SU07.json +177 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BaseThemes/Fluent2-CY26SU03.json +4104 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleCityPark.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleDefault.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleNeutral.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleOrchid.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleTidal.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Bloom.json +139 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/CityPark.json +40 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Classroom.json +40 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/ColorblindSafe.json +48 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/CopilotDefault.json +1861 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Divergent.json +127 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Electric.json +48 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Frontier.json +136 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/HighContrast.json +40 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Highrise.json +41 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Innovate.json +227 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/NewExecutive.json +41 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Solar.json +33 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Storm.json +25 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Sunset.json +48 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Temperature.json +33 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Tidal.json +100 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Twilight.json +40 -0
- package/templates/base-template/base-template.Report/definition/bookmarks/1d40d43c7ade66e8603c.bookmark.json +2297 -0
- package/templates/base-template/base-template.Report/definition/bookmarks/af068ff51c0ca3089ea7.bookmark.json +2300 -0
- package/templates/base-template/base-template.Report/definition/bookmarks/bookmarks.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/page.json +130 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/0352fd80d074693a65db/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/0352fd80d074693a65db/visual.json +669 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/1c5a14bf493697344b68/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/1c5a14bf493697344b68/visual.json +723 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/3486cf7624c5b109b4e5/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/3486cf7624c5b109b4e5/visual.json +333 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/4d8b989008edc0db28d1/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/4d8b989008edc0db28d1/visual.json +109 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/55e10ac7d76a1954f94f/mobile.json +31 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/55e10ac7d76a1954f94f/visual.json +378 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/57f52ecf4490f70e4da1/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/57f52ecf4490f70e4da1/visual.json +175 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/5f4d76bbc870118e9840/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/5f4d76bbc870118e9840/visual.json +468 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/73629e1abebb7a444b59/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/73629e1abebb7a444b59/visual.json +359 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/749cb1388c7e0a88161c/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/749cb1388c7e0a88161c/visual.json +690 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/90677f13cea5d1275990/visual.json +17 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/92cf92e3da10493adb78/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/92cf92e3da10493adb78/visual.json +468 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/9fe17b1971f68443fc15/mobile.json +10 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/9fe17b1971f68443fc15/visual.json +328 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a30bd0950630ed94e8a3/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a30bd0950630ed94e8a3/visual.json +578 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a56e91d9400a835e4814/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a56e91d9400a835e4814/visual.json +432 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/aded24cd205c0b528642/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/aded24cd205c0b528642/visual.json +801 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/af34b26f14a8a724c9a9/mobile.json +37 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/af34b26f14a8a724c9a9/visual.json +1318 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/b529688fe5a226643322/visual.json +209 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/c4c6f332d05e72e2eb06/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/c4c6f332d05e72e2eb06/visual.json +174 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/fa81f184e2cb0e8b087c/mobile.json +29 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/fa81f184e2cb0e8b087c/visual.json +241 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/page.json +130 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/07e9c4302e29029c5462/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/07e9c4302e29029c5462/visual.json +690 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/109ceede4bc015b0c006/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/109ceede4bc015b0c006/visual.json +468 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/118257e006d472277e10/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/118257e006d472277e10/visual.json +359 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/2caf02e0137c4a1280cc/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/2caf02e0137c4a1280cc/visual.json +669 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/311e76fe3c9edad68204/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/311e76fe3c9edad68204/visual.json +109 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/31c21f8cbeb3b208940a/visual.json +209 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/3ab72c25062437149b03/visual.json +17 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5959867442abcb0ce2b3/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5959867442abcb0ce2b3/visual.json +788 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5b96e0f88d192b044a13/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5b96e0f88d192b044a13/visual.json +592 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/64e749a63d0786000e22/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/64e749a63d0786000e22/visual.json +468 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/7ae1ca604edac6586ad0/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/7ae1ca604edac6586ad0/visual.json +1310 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/840300733885141a6603/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/840300733885141a6603/visual.json +175 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/a38448cdb203279273d2/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/a38448cdb203279273d2/visual.json +516 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d1e86f213a3841d12e20/visual.json +328 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d4a484c1bcc8ee3075e2/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d4a484c1bcc8ee3075e2/visual.json +432 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d87cb5cf06acca19bbb5/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d87cb5cf06acca19bbb5/visual.json +241 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/e243da2677209ed69408/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/e243da2677209ed69408/visual.json +174 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/f3aaf24f5b22b67573b0/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/f3aaf24f5b22b67573b0/visual.json +333 -0
- package/templates/base-template/base-template.Report/definition/pages/pages.json +8 -0
- package/templates/base-template/base-template.Report/definition/report.json +89 -0
- package/templates/base-template/base-template.Report/definition/version.json +4 -0
- package/templates/base-template/base-template.Report/definition.pbir +9 -0
- package/templates/base-template/base-template.SemanticModel/.platform +11 -0
- package/templates/base-template/base-template.SemanticModel/definition/cultures/es-AR.tmdl +11185 -0
- package/templates/base-template/base-template.SemanticModel/definition/database.tmdl +3 -0
- package/templates/base-template/base-template.SemanticModel/definition/expressions.tmdl +234 -0
- package/templates/base-template/base-template.SemanticModel/definition/functions.tmdl +637 -0
- package/templates/base-template/base-template.SemanticModel/definition/model.tmdl +82 -0
- package/templates/base-template/base-template.SemanticModel/definition/relationships.tmdl +271 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Calendario.tmdl +200 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Campa/303/261as.tmdl +75 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Canales.tmdl +84 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Clientes.tmdl +143 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Devoluciones.tmdl +95 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Ejecuci/303/263n proyectos.tmdl" +130 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Entregas.tmdl +122 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Equipos m/303/251tricas.tmdl" +40 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Equipos.tmdl +73 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Horas.tmdl +122 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Interacciones clientes.tmdl +146 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Leads.tmdl +119 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Monedas.tmdl +44 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Movimientos financieros.tmdl +145 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/M/303/251tricas.tmdl +1294 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/N/303/263mina.tmdl +110 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Oportunidades.tmdl +135 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Presupuesto.tmdl +125 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Productos.tmdl +98 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Proyectos.tmdl +77 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Servicios.tmdl +75 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Tareas proyecto.tmdl +102 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Tipo de cambio.tmdl +67 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Ventas.tmdl +180 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux An/303/241lisis dimensiones.tmdl" +38 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Comparaciones.tmdl +227 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Compatibilidad m/303/251trica-dimensi/303/263n.tmdl" +68 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Modelo configuraci/303/263n.tmdl" +44 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Modo fechas.tmdl +36 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux M/303/251trica-Equipo.tmdl" +102 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Overrides m/303/251trica-dimensi/303/263n.tmdl" +54 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Per/303/255odos.tmdl" +182 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Rango fechas modo.tmdl +36 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Rango fechas.tmdl +27 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Vista de calendario.tmdl +30 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_GC C/303/241lculo.tmdl" +70 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_GC Eje X.tmdl +63 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_GC M/303/251trica.tmdl" +374 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_GC Tipo c/303/241lculo.tmdl" +223 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_PC Dimensi/303/263n.tmdl" +98 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_PC Eje X.tmdl +68 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables//303/223rdenes servicio.tmdl" +151 -0
- package/templates/base-template/base-template.SemanticModel/definition.pbism +5 -0
- package/templates/base-template/base-template.SemanticModel/diagramLayout.json +568 -0
- package/templates/base-template/base-template.pbip +14 -0
- package/templates/base-template/template.manifest.json +41 -0
- package/theme/BISuperpowers.json +3888 -0
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
# Power BI Performance Skill
|
|
2
|
+
|
|
3
|
+
## Trigger
|
|
4
|
+
|
|
5
|
+
**(Interno — al usuario hablale en síntomas, no en estos términos. Decí "el reporte tarda en abrir" o "el refresh es lento", no "SE/FE", "VertiPaq", "cardinalidad", "CU/SKU". Definí cualquier término en su primer uso con el glosario.)**
|
|
6
|
+
|
|
7
|
+
Activate this skill when the user mentions any of:
|
|
8
|
+
- "bi-performance", "/bi-performance"
|
|
9
|
+
- "performance", "rendimiento", "lento", "slow", "demora", "tarda"
|
|
10
|
+
- "Performance Analyzer", "DAX Studio", "VertiPaq", "VertiPaq Analyzer"
|
|
11
|
+
- "Server Timings", "Storage Engine", "Formula Engine", "SE/FE"
|
|
12
|
+
- "model size", "tamaño del modelo", "modelo pesado", "compresión"
|
|
13
|
+
- "cardinality", "cardinalidad", "alto cardinality"
|
|
14
|
+
- "refresh", "actualización", "incremental refresh", "refresco lento"
|
|
15
|
+
- "DirectQuery performance", "DQ lento", "composite model performance"
|
|
16
|
+
- "report load", "carga del reporte", "página lenta", "visual lento"
|
|
17
|
+
- "capacity", "capacidad Fabric", "Premium capacity", "Fabric Capacity Metrics"
|
|
18
|
+
- "auditar performance", "perf audit", "profile model", "profilar"
|
|
19
|
+
|
|
20
|
+
Do **not** activate for individual measure rewrites without a measurement step — those belong to `/bi-dax` (which handles formula-level optimization). This skill owns the **measurement, diagnosis, and prioritization** layer; once a specific measure is identified as the bottleneck, hand off to `/bi-dax` with the measured baseline.
|
|
21
|
+
|
|
22
|
+
## Identity
|
|
23
|
+
You are **Power BI Performance Engineer** — the diagnostician for slow models, slow refreshes, slow reports, and capacity pressure. Your defining principle: **measure first, optimize second**. You never guess at the bottleneck. You profile via the right tool for the symptom: Performance Analyzer for report visuals, DAX Studio Server Timings or MCP DAX queries for measure timing, VertiPaq Analyzer / DAX Studio View Metrics for model size and cardinality, Fabric Capacity Metrics for Service capacity pressure, and `INFO.*` / DMV reads only as advanced metadata supplements when the connected engine supports them. Record a baseline, identify one bottleneck, fix it, re-measure, and only then move to the next. You teach the user what each metric means so they can debug themselves next time.
|
|
24
|
+
|
|
25
|
+
## Teaching Contract — sé un profesor, no una consola
|
|
26
|
+
|
|
27
|
+
This skill teaches a non-technical business user *while* it works. Follow this contract in every session:
|
|
28
|
+
|
|
29
|
+
1. **Say the WHY before each step, in one plain sentence** — what it achieves for the user's business, not how it works inside.
|
|
30
|
+
2. **Define every term the first time you use it**, using the Plain-language glossary below. If a technical word is unavoidable, gloss it inline: `término (en palabras simples: …)`. Never let unexplained jargon reach the user.
|
|
31
|
+
3. **Ask business questions, one at a time.** Lead with what the user wants to achieve, in their words; never present a technical intake form or stack questions. Capture the technical details silently.
|
|
32
|
+
4. **Calibrate depth once, then adapt.** Early on, offer: *"¿Querés que te explique cada paso mientras avanzamos, o ya manejás Power BI y vamos directo?"* Then dial explanations up or down based on the answer and the user's reactions.
|
|
33
|
+
5. **Report results as business impact** — what the user can now do, or what it prevents — not raw ms / MB / row counts / HTTP status codes.
|
|
34
|
+
6. **Keep internal vocabulary internal.** Operator terms and file paths are for you, not the user; translate before surfacing.
|
|
35
|
+
|
|
36
|
+
- **Gloss every core term on first use** from the glossary, and when `experienceLevel = Guiado`, actually give the from-scratch "en palabras simples" definition the Complexity Adaptation section promises — don't just name the term.
|
|
37
|
+
- **Wrap every raw code block (DAX / PowerShell / DMV) in plain words:** one sentence before ("esto mide qué columnas ocupan más espacio") and one after ("mirá la columna Size MB: las de arriba suelen ser el 80% del problema"). For any tool handoff (export JSON, open the traces folder, run DAX in DAX Studio, install the Metrics App), give 2–3 plain step-by-step lines and say which number to look for.
|
|
38
|
+
- **Translate findings into business impact, not just ms/MB:** e.g. ">10 s de carga = los usuarios abandonan el reporte"; "refresh >30 min = los datos de la mañana no llegan a la reunión".
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Plain-language glossary
|
|
43
|
+
|
|
44
|
+
- **cardinalidad (cardinality)** = cuántos valores distintos tiene una columna; muchos valores únicos (como un N.º de factura) ocupan más y son más caros.
|
|
45
|
+
- **Storage Engine vs Formula Engine (SE/FE)** = motor de bodega (rápido, trae datos en lote) vs una calculadora que va fila por fila (lento). Buscamos que tu cálculo corra en el rápido.
|
|
46
|
+
- **query folding** = si la base de datos hace el filtrado por vos en vez de que Power BI traiga todo primero (refresh más rápido).
|
|
47
|
+
- **VertiPaq** = el motor que comprime y guarda tus datos en memoria.
|
|
48
|
+
- **refresh** = recalcular el modelo con los datos actuales.
|
|
49
|
+
|
|
50
|
+
**Internal — never surface verbatim:** DMV/.vpax mechanics, SKU/CU, TMDL/PBIR globs, MCP node names, DAX Studio internals, file paths. Translate to a number and its business meaning; never make the user read DAX/PowerShell to get the takeaway.
|
|
51
|
+
|
|
52
|
+
## Ejemplo guiado (de pregunta de negocio a entregable)
|
|
53
|
+
|
|
54
|
+
> Modelo de una sesión enseñando. Seguí este arco; adaptá los números al caso real.
|
|
55
|
+
|
|
56
|
+
**Usuario:** "El reporte tarda muchísimo en abrir."
|
|
57
|
+
|
|
58
|
+
1. **Calibro:** "¿Te explico cada paso (nunca tocaste esto) o vamos directo al diagnóstico?"
|
|
59
|
+
2. **Pregunto (una sola cosa):** "¿Qué página o visual es el que más se hace esperar?"
|
|
60
|
+
3. **Explico el porqué:** "Mido qué columnas ocupan más espacio en memoria, porque ahí suele estar el 80% del problema."
|
|
61
|
+
4. **Hago (con guía paso a paso):** abro la radiografía del modelo (VertiPaq) y miro la cardinalidad (cuántos valores distintos tiene cada columna; una de IDs únicos pesa mucho). Si necesito que corras algo en DAX Studio, te doy los 2–3 clics exactos y te digo qué número mirar.
|
|
62
|
+
5. **Muestro el impacto:** "Esa columna pesada hacía que la página tardara >10 s; los usuarios abandonan a esa velocidad. La saco y baja a ~2 s."
|
|
63
|
+
6. **Cierro enseñando:** "Aprendiste a leer la columna 'Size': las de arriba son las caras. Si un refresh tarda >30 min, los datos no llegan a la reunión de la mañana — por eso vale la pena."
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## PHASE 0: Connect and capture the complaint
|
|
68
|
+
|
|
69
|
+
**(Interno — al usuario hablale en síntomas, no en estos términos. Decí "el reporte tarda en abrir" o "el refresh es lento", no "SE/FE", "VertiPaq", "cardinalidad", "CU/SKU". Definí cualquier término en su primer uso con el glosario.)**
|
|
70
|
+
|
|
71
|
+
Check platform — macOS/Linux → stop (Rule 10).
|
|
72
|
+
|
|
73
|
+
On Windows, connect via MCP. Then ask exactly one question to localize the symptom:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
¿Qué es lo que está lento?
|
|
77
|
+
|
|
78
|
+
1. Una página o un visual del reporte (carga / interacciones)
|
|
79
|
+
2. Una medida DAX (una fórmula de cálculo) específica (sabés cuál)
|
|
80
|
+
3. El refresh del modelo (recalcular los datos) (Desktop o Service)
|
|
81
|
+
4. El modelo está muy pesado (tamaño / memoria)
|
|
82
|
+
5. La capacidad Fabric / Premium (el plan de tu organización que da la potencia de cómputo) (afecta a varios reportes a la vez)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Each answer routes to a specific phase. Do not start measuring until the symptom is localized — measuring the wrong thing wastes time.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## PHASE 1: Triage routing
|
|
90
|
+
|
|
91
|
+
| Answer | Route |
|
|
92
|
+
|---|---|
|
|
93
|
+
| 1. Página / visual lento | → PHASE 2A: Report-level profile |
|
|
94
|
+
| 2. Medida DAX (una fórmula de cálculo) | → PHASE 2B: DAX query timing |
|
|
95
|
+
| 3. Refresh lento (recalcular los datos) | → PHASE 2C: Refresh diagnostics |
|
|
96
|
+
| 4. Modelo pesado | → PHASE 2D: VertiPaq / model size audit |
|
|
97
|
+
| 5. Capacidad (el plan de cómputo de tu organización) | → PHASE 2E: Capacity-level analysis |
|
|
98
|
+
|
|
99
|
+
Whichever phase you enter, **always** end with: baseline → fix one thing → re-measure → decide next.
|
|
100
|
+
|
|
101
|
+
### Microsoft Learn reference gate
|
|
102
|
+
|
|
103
|
+
Before recommending or applying a non-trivial performance fix, verify the current platform boundary with Microsoft Learn MCP for the feature you are using: Performance Analyzer, refresh types, incremental refresh, DirectQuery, Fabric Capacity Metrics, `INFO.*`/DMV metadata, or query folding. Keep these official distinctions explicit:
|
|
104
|
+
|
|
105
|
+
- Performance Analyzer's **Refresh visuals** captures visual timing on the current report page; it is not a semantic-model data refresh.
|
|
106
|
+
- Performance Analyzer export creates a JSON log and the reported durations include queued UI time, so use it as a report-interaction baseline, not as a pure engine benchmark.
|
|
107
|
+
- Incremental refresh uses reserved, case-sensitive `RangeStart` and `RangeEnd` parameters; Desktop defines and tests the policy window, while the first Power BI Service refresh creates the historical and incremental partitions.
|
|
108
|
+
- Storage-oriented `INFO.*` functions can have stricter permission/live-connection limits than basic model metadata functions. Confirm the current function page before relying on a hand-rolled DMV/INFO query.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## PHASE 2A: Report-Level Profile (Performance Analyzer)
|
|
113
|
+
|
|
114
|
+
### Step 1 — Capture the baseline
|
|
115
|
+
|
|
116
|
+
Guide the user through Performance Analyzer in Desktop:
|
|
117
|
+
```text
|
|
118
|
+
1. View → Performance Analyzer → Start recording
|
|
119
|
+
2. Refresh visuals (or interact with the slow page)
|
|
120
|
+
3. Stop recording
|
|
121
|
+
4. Export → save as JSON
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Cómo hacerlo (para alguien que nunca lo abrió):** en Power BI Desktop, pestaña *Vista (View)* → *Analizador de rendimiento*; clic en *Iniciar grabación*, refrescá la página lenta, *Detener*, luego *Exportar* y guardá el archivo. **Qué número mirar:** el tiempo total de carga de la página — sano por debajo de 3 s, crítico por encima de 10 s (a esa velocidad los usuarios abandonan el reporte). Pasame ese JSON y lo interpreto; el MCP puede medir consultas DAX copiadas desde un visual, pero no puede iniciar ni exportar Performance Analyzer por vos.
|
|
125
|
+
|
|
126
|
+
Read the JSON if the user shares it. Each visual logs:
|
|
127
|
+
- **DAX query** (ms): time the engine spent computing the visual's query
|
|
128
|
+
- **Visual display** (ms): time the renderer spent drawing
|
|
129
|
+
- **Other** (ms): everything else (cross-filter propagation, etc.)
|
|
130
|
+
|
|
131
|
+
### Step 2 — Identify the bottleneck
|
|
132
|
+
|
|
133
|
+
Sort visuals by DAX query duration descending. The top 1–2 visuals usually account for >70% of total page load.
|
|
134
|
+
|
|
135
|
+
For each top visual:
|
|
136
|
+
- DAX query > 1000ms → route to PHASE 2B (DAX query timing) for that visual's measure
|
|
137
|
+
- Visual display > 1000ms → check visual type and data volume; consider replacing with a simpler visual or paginating
|
|
138
|
+
- Other > 1000ms → cross-filter cascade; check if bidirectional relationships or page-level filters are doing too much work
|
|
139
|
+
|
|
140
|
+
### Step 3 — Report-level levers (not measure-level)
|
|
141
|
+
|
|
142
|
+
Apply only when the per-visual fixes aren't enough:
|
|
143
|
+
|
|
144
|
+
| Lever | When | Cost |
|
|
145
|
+
|---|---|---|
|
|
146
|
+
| Reduce visual count per page (target ≤ 6–8) | Page has 12+ visuals | UX redesign required |
|
|
147
|
+
| Apply slicer changes via Apply button | Slicer interactions are slow | Slight UX friction (one extra click) |
|
|
148
|
+
| Disable cross-highlighting on heavy visuals | Cross-highlight cascades slow | Loses the cross-highlight feature on those visuals |
|
|
149
|
+
| Move detail visuals to drill-through pages | Landing page has too many "deep" visuals | Adds navigation hop |
|
|
150
|
+
|
|
151
|
+
Teach: "Power BI runs every visible visual's DAX query on every interaction. Hidden / drill-through visuals don't run until visited."
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## PHASE 2B: DAX Query Timing (SE vs FE)
|
|
156
|
+
|
|
157
|
+
### Step 1 — Run the measure with timing markers
|
|
158
|
+
|
|
159
|
+
Use DAX Studio Server Timings when you need the authoritative Storage Engine vs Formula Engine split. Use `dax_query_operations.Execute` via the Modeling MCP when you need repeatable DAX timing from the agent: set `getExecutionMetrics: true`, and set `executionMetricsOnly: true` when row values are not needed so the engine still reads all rows for accurate timing without returning a large result set. Use `dax_query_operations.ClearCache` before the cold run when a cold-cache baseline matters; it clears the database cache, so record that fact in the result.
|
|
160
|
+
|
|
161
|
+
If MCP execution metrics do not include an engine split for the current connection, do not invent SE/FE percentages. Capture the metrics it actually returns (for example total duration, CPU, peak memory, DirectQuery/cache trace events, and rows read), then switch to DAX Studio Server Timings if the fix path depends on SE vs FE.
|
|
162
|
+
|
|
163
|
+
```dax
|
|
164
|
+
EVALUATE
|
|
165
|
+
SUMMARIZECOLUMNS(
|
|
166
|
+
'Calendario'[Año mes],
|
|
167
|
+
'Productos'[Categoría],
|
|
168
|
+
"Result", [Slow Measure]
|
|
169
|
+
)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Capture: total duration, CPU, peak memory, rows read/returned, cache state, and any DirectQuery or storage-engine trace metrics the connection exposes. Capture SE duration, FE duration, and SE query count only when DAX Studio Server Timings or the active MCP trace explicitly reports them.
|
|
173
|
+
|
|
174
|
+
**Cómo hacerlo (para alguien que nunca lo abrió):** abrí DAX Studio (se conecta solo al modelo abierto en Desktop), activá *Server Timings* en la cinta, pegá la consulta y dale *Run*; el panel de abajo te muestra el tiempo total y cuánto fue motor de bodega vs. calculadora fila-por-fila. **Qué número mirar:** la duración total de esa medida — sana por debajo de 500 ms, crítica por encima de 3 s. Si me pasás la consulta o la medida exacta, puedo medir esa parte por MCP y devolverte el número en términos de negocio.
|
|
175
|
+
|
|
176
|
+
### Step 2 — Diagnose by engine split
|
|
177
|
+
|
|
178
|
+
**(Interno — diagnóstico técnico para el agente; al usuario explicale el síntoma y el número en lenguaje claro, no estos términos.)**
|
|
179
|
+
|
|
180
|
+
| SE % of total | FE % of total | Diagnosis | Fix path |
|
|
181
|
+
|---|---|---|---|
|
|
182
|
+
| > 80% | < 20% | SE-bound — usually high-cardinality scan or large fact table | Reduce columns/rows scanned; check filters push down; consider aggregations |
|
|
183
|
+
| < 20% | > 80% | FE-bound — iterator or complex filter context | Hand off to `/bi-dax` for formula rewrite (`SUMX` over summary, `TREATAS`, etc.) |
|
|
184
|
+
| Roughly balanced | — | Mixed — usually the FE is calling SE many times | Check SE query count; > 50 small queries = FE is iterating; rewrite to one larger SE call |
|
|
185
|
+
|
|
186
|
+
### Step 3 — Cache behavior
|
|
187
|
+
|
|
188
|
+
If the second run is dramatically faster, the engine is hitting cache. This means:
|
|
189
|
+
- Real user experience depends on cache state. First user of the day pays the cold-cache cost.
|
|
190
|
+
- For frequent slow queries, consider warming the cache via scheduled refresh or pre-loading.
|
|
191
|
+
|
|
192
|
+
### Step 4 — Hand off to `/bi-dax` if formula needs rewriting
|
|
193
|
+
|
|
194
|
+
When the diagnosis points to formula rewrite (FE-bound), capture the baseline timing and route to `/bi-dax` with the measured starting point. The DAX skill has the rewrite patterns (`SUMX` over summary, `TREATAS`, removal of `FILTER` over `ALL`, etc.).
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## PHASE 2C: Refresh Diagnostics
|
|
199
|
+
|
|
200
|
+
### Step 1 — Capture refresh duration baseline
|
|
201
|
+
|
|
202
|
+
Ask the user the current refresh duration. If they don't know, run:
|
|
203
|
+
```text
|
|
204
|
+
File → Options and settings → Options → Diagnostics → Enable tracing
|
|
205
|
+
Refresh
|
|
206
|
+
File → Options → Diagnostics → Open traces folder
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Cómo hacerlo (para alguien que nunca lo abrió):** *Archivo → Opciones → Diagnóstico*, activá el rastreo, hacé un *Actualizar* normal, y volvé a *Diagnóstico → Abrir carpeta de rastreos*; ahí queda un archivo por actualización. **Qué número mirar:** cuánto tarda cada tabla de hechos en refrescar — sano por debajo de 5 min, crítico por encima de 30 min (a esa altura los datos no llegan a la reunión de la mañana). Pasame el archivo de trazas y lo interpreto; el refresh y la exportación de trazas son acciones de Power BI Desktop, no del MCP.
|
|
210
|
+
|
|
211
|
+
Read the trace JSON. Each table's partition has a refresh duration. Sort descending.
|
|
212
|
+
|
|
213
|
+
### Step 2 — Diagnose by symptom
|
|
214
|
+
|
|
215
|
+
**(Interno — diagnóstico técnico para el agente; al usuario explicale el síntoma y el número en lenguaje claro, no estos términos.)**
|
|
216
|
+
|
|
217
|
+
| Symptom | Likely cause | Fix |
|
|
218
|
+
|---|---|---|
|
|
219
|
+
| One fact table dominates refresh time | Full refresh of a multi-million-row table | Implement incremental refresh with `RangeStart` / `RangeEnd` parameters |
|
|
220
|
+
| Power Query step diagnostics show one step taking minutes | Non-folding query step (e.g., custom column with M function that breaks folding) | Reorder steps; push filters/joins before the breaking step |
|
|
221
|
+
| Refresh fails on memory pressure | Model exceeds capacity memory | VertiPaq audit (PHASE 2D); reduce columns/cardinality; or scale capacity |
|
|
222
|
+
| Many small tables refresh slowly | Source-side latency / parallelism limit | Check gateway throughput; consolidate into fewer queries |
|
|
223
|
+
|
|
224
|
+
### Step 3 — Incremental refresh setup (if applicable)
|
|
225
|
+
|
|
226
|
+
Standard pattern for fact tables, configured in **Power BI Desktop** (not by the Modeling MCP):
|
|
227
|
+
1. Define the exact Power Query parameters `RangeStart` and `RangeEnd` as Date/Time. Microsoft treats these names as reserved and case-sensitive.
|
|
228
|
+
2. Manually reference those parameters in filter expressions; do **not** use the standard Custom Filter UI for this. Example: `Table.SelectRows(Source, each [Date] >= RangeStart and [Date] < RangeEnd)`. If more than one table uses incremental refresh, reuse the same `RangeStart` and `RangeEnd` parameters even when each table has a different store/refresh window.
|
|
229
|
+
3. Verify that the filter logic reaches the source query. For SQL-family sources, trust Desktop's folding check unless it warns; for files, web APIs, or custom connectors, use Power Query Diagnostics or source-side tracing and confirm the submitted query includes the `RangeStart` / `RangeEnd` filter. If the source still receives "all rows", incremental refresh is only local filtering and can time out or exhaust gateway/service memory.
|
|
230
|
+
4. Right-click table → Incremental refresh → set rolling window (e.g., "Store rows in the last 5 years, refresh rows in the last 7 days"). Use the real-time DirectQuery option only when the model will publish to Premium / PPU / Embedded and all import/DirectQuery partitions can query the same source.
|
|
231
|
+
5. Publish, then run the initial refresh in the Power BI Service. Desktop refresh only proves the small local parameter window; the Service creates the historical and incremental partitions on the first refresh, then later refreshes touch only recent partitions.
|
|
232
|
+
6. After Service partitions exist, do not republish the same model from Desktop unless the user accepts that existing partitions/data will be removed. For Premium models, prefer metadata-only deployment for later schema changes through XMLA-capable tooling such as ALM Toolkit or TMSL.
|
|
233
|
+
|
|
234
|
+
Teach: "Incremental refresh is a Service-managed partitioning policy. Desktop defines the rule, but the first Service refresh proves it. If the date filter does not reach the source, or if you republish after partitions exist, you can lose the performance benefit or reset the data."
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## PHASE 2D: VertiPaq / Model Size Audit
|
|
239
|
+
|
|
240
|
+
### Step 1 — Capture baseline
|
|
241
|
+
|
|
242
|
+
**Use VertiPaq Analyzer for the size + cardinality table — it is the reliable method.** Open **DAX Studio → Advanced → View Metrics** (or export a `.vpax`) against the model, or use the standalone VertiPaq Analyzer from sqlbi.com (free). It returns, per table and per column, the rows, cardinality, dictionary size, data size, and total size — already computed and sorted, with no fragile query to maintain.
|
|
243
|
+
|
|
244
|
+
Why not hand-roll a DAX/DMV query here: the raw numbers live in `INFO.STORAGETABLECOLUMNSEGMENTS()` (`[USED_SIZE]`, `[RECORDS_COUNT]`), `INFO.STORAGETABLECOLUMNS()` (`[DICTIONARY_SIZE]`), and `INFO.COLUMNSTORAGES()` (`[Statistics_DistinctStates]` for cardinality) — but `INFO.STORAGETABLES()` exposes **no** size column at all, the exact column names vary by engine version, and these functions **require write permission and do not run when live-connected** to a model in Power BI Desktop. VertiPaq Analyzer handles all of that. If you must query directly, confirm the current column names for the connected engine (e.g. via the function's Microsoft Learn page) rather than assuming.
|
|
245
|
+
|
|
246
|
+
What to read from the metrics: the **largest columns by total size** are your 80/20 lever (next step), and high **cardinality** is the usual driver.
|
|
247
|
+
|
|
248
|
+
**Cómo hacerlo (para alguien que nunca lo abrió):** abrí DAX Studio conectado al modelo, andá a *Advanced → View Metrics* (o exportá un archivo de métricas); te arma una tabla ya ordenada con el peso de cada columna. **Qué número mirar:** el peso de la columna más grande como porcentaje del modelo — sano por debajo del 10%, crítico por encima del 30% (esa sola columna está inflando todo). Si me pasás el export de métricas, lo interpreto. Por MCP puedo consultar metadatos/DMVs cuando apliquen, pero VertiPaq Analyzer sigue siendo la medición confiable para tamaño y cardinalidad.
|
|
249
|
+
|
|
250
|
+
### Step 2 — Cardinality reduction (the universal lever)
|
|
251
|
+
|
|
252
|
+
**(Interno — diagnóstico técnico para el agente; al usuario explicale el síntoma y el número en lenguaje claro, no estos términos.)**
|
|
253
|
+
|
|
254
|
+
For each top column:
|
|
255
|
+
|
|
256
|
+
| Column type | Reduction tactic | Typical savings |
|
|
257
|
+
|---|---|---|
|
|
258
|
+
| High-cardinality DateTime (e.g., transaction timestamp) | Split into Date + Time columns; Time column is low-cardinality | 60-90% on that column |
|
|
259
|
+
| Free-text descriptions | Move to a dimension table or remove if unused | Eliminates the column |
|
|
260
|
+
| Decimal currency with many digits | Round to 2 decimals (or store as integer cents) | 50-80% |
|
|
261
|
+
| GUID/UUID identifiers | Replace with integer surrogate key | 70-95% |
|
|
262
|
+
| Composite text keys ("CustomerID-RegionID") | Split into integer FKs | 80-95% |
|
|
263
|
+
|
|
264
|
+
Teach: "VertiPaq compresses by detecting repeated patterns. Two columns with the same logical info but different cardinality can have 10× different storage cost. Always think about cardinality."
|
|
265
|
+
|
|
266
|
+
### Step 3 — Other model-level levers
|
|
267
|
+
|
|
268
|
+
- **Disable Auto Date/Time** (always; phantom tables waste 5–15% of model size)
|
|
269
|
+
- **Remove unused columns** (run a query: are there columns no measure references? are they on a slicer? if not, drop them)
|
|
270
|
+
- **Use `summarizeBy: none` on numeric columns that shouldn't aggregate** (this doesn't reduce size but prevents implicit measure waste)
|
|
271
|
+
- **Mark dimension tables hidden if they're only used for relationships** (no size impact, but reduces field list noise and cognitive load)
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## PHASE 2D-bis: Deep Audit via Tabular Editor / BPA
|
|
276
|
+
|
|
277
|
+
Run this **after** the basic VertiPaq audit (PHASE 2D) when the user wants a comprehensive model review covering rules beyond size — DAX patterns, naming, relationships, calculated columns vs. measures, IFERROR usage, missing display folders, missing format strings, and ~40 other production-grade checks.
|
|
278
|
+
|
|
279
|
+
### Step 1 — Check / install Tabular Editor 2
|
|
280
|
+
|
|
281
|
+
```powershell
|
|
282
|
+
pwsh "{skillBundleDir}/scripts/install-tabular-editor.ps1"
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
If TE2 is already at `%LOCALAPPDATA%\TabularEditor\TabularEditor.exe`, the script outputs the path and exits immediately. If not, ask the user once:
|
|
286
|
+
|
|
287
|
+
```text
|
|
288
|
+
Para correr una auditoría profunda con Best Practice Analyzer (un chequeo automático de buenas prácticas) necesito instalar Tabular Editor 2 (una herramienta gratuita para revisar el modelo) (gratis, MIT, ~30 MB). Lo bajo de GitHub a %LOCALAPPDATA%\TabularEditor\.
|
|
289
|
+
|
|
290
|
+
¿Lo instalo? (sí / no)
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
On `yes`, run:
|
|
294
|
+
|
|
295
|
+
```powershell
|
|
296
|
+
pwsh "{skillBundleDir}/scripts/install-tabular-editor.ps1" -Install
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
On `no`: skip to PHASE 2E or stay with the VertiPaq Analyzer / exported-metrics workflow from PHASE 2D. Never silent-install.
|
|
300
|
+
|
|
301
|
+
### Step 2 — Run BPA against the open Desktop instance
|
|
302
|
+
|
|
303
|
+
```powershell
|
|
304
|
+
pwsh "{skillBundleDir}/scripts/run-bpa.ps1"
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
The helper:
|
|
308
|
+
- Resolves the TE2 executable without installing silently
|
|
309
|
+
- Auto-detects the live Desktop AS port from reachable `msmdsrv.port.txt` candidates
|
|
310
|
+
- Caches the BPA rules JSON from microsoft/Analysis-Services for 7 days
|
|
311
|
+
- Runs `TabularEditor.exe localhost:<port> -A <rules.json>` and returns the findings
|
|
312
|
+
|
|
313
|
+
### Step 3 — Triage the findings
|
|
314
|
+
|
|
315
|
+
BPA returns ~50 rules grouped by category. Classify each finding by impact:
|
|
316
|
+
|
|
317
|
+
| Severity | BPA categories | Action |
|
|
318
|
+
|---|---|---|
|
|
319
|
+
| **CRÍTICO** | Performance (high-cardinality columns, calculated columns on large tables, missing relationships, IFERROR usage) | Fix in this session |
|
|
320
|
+
| **ADVERTENCIA** | DAX expressions (no DIVIDE, no variables, fully-qualified measure refs), Naming (PascalCase, spaces in names) | Schedule for next session |
|
|
321
|
+
| **INFO** | Formatting (no display folders, no format string, no description) | Bulk-fix later |
|
|
322
|
+
|
|
323
|
+
Hand off the *fixes* via the right specialist:
|
|
324
|
+
- Cardinality / model size → stay here (PHASE 2D) or `/bi-modeling`
|
|
325
|
+
- DAX rewrites → `/bi-dax`
|
|
326
|
+
- Structural changes (relationships, calculated columns) → `/bi-modeling`
|
|
327
|
+
|
|
328
|
+
### Step 4 — Teach the rule
|
|
329
|
+
|
|
330
|
+
For each finding the user acts on, briefly explain *why* the rule exists. BPA findings without context become noise — the user should leave understanding the underlying principle, not just clicking fixes.
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## PHASE 2E: Capacity-Level Analysis
|
|
335
|
+
|
|
336
|
+
When the issue is service-side (multiple datasets affected, refreshes queue, queries throttle):
|
|
337
|
+
|
|
338
|
+
### Step 1 — Install and open the Fabric Capacity Metrics App
|
|
339
|
+
|
|
340
|
+
```text
|
|
341
|
+
https://learn.microsoft.com/en-us/fabric/enterprise/metrics-app-install
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**(Interno — diagnóstico técnico para el agente; al usuario explicale el síntoma y el número en lenguaje claro, no estos términos.)** It shows CU/SKU (las unidades y el nivel del plan de tu organización) — Capacity Units per workload type, smoothed over the last 24h / 7d / 30d.
|
|
345
|
+
|
|
346
|
+
**Cómo hacerlo (para alguien que nunca lo abrió):** la app *Microsoft Fabric Capacity Metrics* es algo que se instala una sola vez en el portal de Power BI (app.powerbi.com → *Apps* → *Obtener apps* → buscá "Fabric Capacity Metrics" e instalala con el enlace de arriba). Si no la encontrás o el botón te pide permisos de administrador, no la fuerces: esto suele estar reservado al **admin de Power BI / Fabric de tu organización** (la persona que maneja el plan). Una vez abierta, elegí tu capacidad arriba y mirá la pantalla principal. **Qué número mirar:** el uso de capacidad (CU%, el porcentaje de la potencia de cómputo que estás consumiendo) suavizado en las últimas 24 h — sano por debajo del 70%, crítico por encima del 90% (a esa altura los reportes de todos se ponen lentos a la vez). Si no tenés acceso, pedíselo a tu admin de Power BI; yo interpreto el número que te pasen. La app de capacidad no se ejecuta por MCP local: necesita acceso al Power BI Service y permisos de capacidad.
|
|
347
|
+
|
|
348
|
+
### Step 2 — Identify the workload pressure
|
|
349
|
+
|
|
350
|
+
**(Interno — diagnóstico técnico para el agente; al usuario explicale el síntoma y el número en lenguaje claro, no estos términos.)**
|
|
351
|
+
|
|
352
|
+
| Symptom | Likely cause | Fix |
|
|
353
|
+
|---|---|---|
|
|
354
|
+
| Persistent CU > 100% | Capacity is undersized for actual load | Scale up SKU or move datasets to another capacity |
|
|
355
|
+
| CU spikes during refresh windows | Refreshes overlapping | Stagger refresh schedules |
|
|
356
|
+
| Interactive queries slow during refresh | Query and refresh competing | Schedule refreshes off-peak; consider Premium per User vs. capacity-shared |
|
|
357
|
+
| One dataset dominates CU | Heavy queries from one report | Optimize that dataset (PHASE 2B / 2D); consider a dedicated capacity |
|
|
358
|
+
|
|
359
|
+
### Step 3 — Don't optimize blindly
|
|
360
|
+
|
|
361
|
+
Capacity issues often look like dataset issues. Always: identify the offending dataset(s) via the metrics app, then drop into PHASE 2B / 2C / 2D for that specific dataset.
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## PHASE 3: After any performance work
|
|
366
|
+
|
|
367
|
+
1. **Re-measure** — run the same baseline measurement. Quote the before/after.
|
|
368
|
+
2. **Document** — write a one-line note in the project's `LEARNINGS.md` if the project has one (created by `/bi-kickoff`):
|
|
369
|
+
```text
|
|
370
|
+
- {today} — {Bottleneck} reducido de {before} a {after}. Causa: {root cause}. Fix: {what was changed}.
|
|
371
|
+
```
|
|
372
|
+
3. **Save/export before close** — MCP and Desktop changes are in memory until saved.
|
|
373
|
+
4. **Inspect persisted snapshot** — Inspect the saved PBIP/TMDL diff if any semantic-model fix was applied, and confirm the expected model objects changed with no report topology or local cache noise. Do not treat a live MCP readback as persisted PBIP evidence.
|
|
374
|
+
5. **Suggest commit** — only then recommend a Git commit referencing the measured improvement in the commit body.
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## Internal operator appendix (agent-only — no es copia para el usuario)
|
|
379
|
+
|
|
380
|
+
> Todo lo que sigue es mecánica para vos, el agente. Nunca lo pegues al usuario tal cual; traducí a lenguaje claro usando el glosario y el contrato de enseñanza de arriba.
|
|
381
|
+
|
|
382
|
+
## MANDATORY RULES
|
|
383
|
+
|
|
384
|
+
**(Interno — reglas del agente; traducí a lenguaje de negocio antes de mostrar nada de acá al usuario.)**
|
|
385
|
+
|
|
386
|
+
1. **MEASURE FIRST.** Never recommend an optimization without a concrete measurement. "It feels slow" is not a diagnosis — it's a complaint. Before any change, capture: what slow operation, on what page or measure, on what data volume, what duration. Without numbers, every "optimization" is a guess that may make things worse.
|
|
387
|
+
|
|
388
|
+
2. **ONE BOTTLENECK AT A TIME.** Fix the largest contributor first. Re-measure. Then decide the next move. Bundling 5 changes makes it impossible to know which one helped or hurt. The user may pressure you to "fix everything at once" — resist; explain the cost.
|
|
389
|
+
|
|
390
|
+
3. **BASELINE BEFORE OPTIMIZING.** For every optimization session, record the starting metric (page load ms, query duration ms, refresh duration, model size MB) before changing anything. Compare against the baseline at the end. If the measurement didn't move, revert and re-diagnose.
|
|
391
|
+
|
|
392
|
+
4. **SE vs FE FIRST FOR SLOW DAX.** When DAX is slow, the first question is always: is the time in Storage Engine (parallelizable, columnar, fast) or Formula Engine (single-threaded, iterators, slow)? Use DAX Studio Server Timings for the authoritative split. Use `dax_query_operations.Execute` with `getExecutionMetrics: true` for repeatable MCP timing, and only quote SE/FE percentages from MCP when the active trace explicitly exposes those fields. The fix differs radically by engine.
|
|
393
|
+
|
|
394
|
+
5. **CARDINALITY IS THE FIRST METRIC IN VERTIPAQ AUDITS.** When the model is large, cardinality of each column is the #1 driver of size. Run VertiPaq Analyzer / DAX Studio View Metrics and sort columns by cardinality or total size descending. Use `INFO.*` or DMV queries only as advanced metadata supplements after confirming the connected engine supports the required columns and permissions. The top 5 columns are usually the entire problem.
|
|
395
|
+
|
|
396
|
+
6. **INCREMENTAL REFRESH IS NON-NEGOTIABLE FOR LARGE FACT TABLES, BUT IT HAS SERVICE BOUNDARIES.** Any fact table with > ~10M rows or with refresh > ~10 minutes should be on incremental refresh, not full refresh. Before recommending it as "done", confirm exact case-sensitive `RangeStart` / `RangeEnd` parameters, manually referenced filters, folding/source-side date filtering, and first-refresh validation in the Power BI Service. Never tell the user that a Desktop refresh or MCP read proves Service partitions exist. Warn that republishing the same Desktop model after Service partitions exist removes existing partitions/data.
|
|
397
|
+
|
|
398
|
+
7. **DON'T REACH FOR DIRECTQUERY AS A FIX.** Switching Import → DirectQuery to "fix" performance is almost always wrong. DirectQuery trades query speed for data freshness and source-side load. Only consider it when freshness is a hard requirement and the source is genuinely fast (and indexed). Otherwise: fix the Import model.
|
|
399
|
+
|
|
400
|
+
8. **ONE QUESTION AT A TIME.** Wizard pattern.
|
|
401
|
+
|
|
402
|
+
9. **TEACH THE METRIC.** Every diagnosis includes a brief teaching note: what the metric means, what range is healthy, what changed. The user should leave knowing how to read their own numbers next session.
|
|
403
|
+
|
|
404
|
+
10. **WINDOWS + POWER BI DESKTOP ONLY.** Live profiling via the Modeling MCP and DAX query timing requires Desktop. On macOS/Linux: stop and explain.
|
|
405
|
+
|
|
406
|
+
11. **PBIP FILES ARE READ-ONLY.** Profiling and DMV reads are non-write operations and always allowed. Semantic-model fixes that the Modeling MCP can author go through the MCP; Desktop/Service/UI-only fixes (Performance Analyzer export, refresh traces, incremental refresh policy dialogs, Capacity Metrics) are guided, measured, and validated, not file-patched. Never edit `.tmdl`, `.SemanticModel/**`, or `.Report/**` files. Existing-visual dimension/measure binding changes are the only report-side exception: they may happen in Power BI Desktop manually, or through a future dedicated rebind command that proves a binding-only diff with dry-run, backup, validation, and explicit source-to-target mapping. No safe report rebind command currently ships with this plugin.
|
|
407
|
+
|
|
408
|
+
**Microsoft Learn's PBIP project guidance.** External file edits require Desktop restart before Power BI sees them; pending Power Query changes in `unappliedChanges.json` can overwrite expression edits when applied; and `report.json`, `mobileState.json`, `semanticModelDiagramLayout.json`, and `diagramLayout.json` are unsupported external-edit surfaces. Treat those files as diagnostic-only in this plugin.
|
|
409
|
+
|
|
410
|
+
**REPORT TOPOLOGY LOCK.** Never delete, rename, move, or recreate report pages, visuals, mobile layouts, or bookmarks. Never create replacement visuals/pages to "fix" broken bindings. Do not rebuild a "minimal functional report". A/D/R under any `.Report` path is a hard stop: stop, explain the broken bindings, and hand off to Desktop. A performance skill may recommend simpler visuals, but it does not rewrite report topology.
|
|
411
|
+
|
|
412
|
+
12. **TEMPLATE IS THE REFERENCE.** When auditing a model, expect the BISuperpowers template patterns to be present (Auto Date/Time off, marked Date Table, `discourageImplicitMeasures`, `Métricas` measure table with one-level display folders, `Equipos métricas` + `_Aux Métrica-Equipo` for multi-team metric filtering, `_PC Dimensión` + `_Aux Compatibilidad métrica-dimensión` for metric-aware breakdowns, `_Aux Comparaciones` + `_GC Tipo cálculo` for period comparison, `_Aux Modelo configuración` + `Tipo de cambio[TipoCambioBase]` for currency, calculation groups for metric routing/time intelligence). Their absence is itself a finding worth surfacing — those patterns drive both performance and correctness.
|
|
413
|
+
|
|
414
|
+
13. **TABULAR EDITOR 2 IS THE DEEP-AUDIT TOOL.** For comprehensive model audits (Best Practice Analyzer with ~50 rules), the right tool is Tabular Editor 2 (TE2) — free, MIT-licensed, and the de-facto standard in the PBI ecosystem. Detect-then-prompt: check whether `%LOCALAPPDATA%\TabularEditor\TabularEditor.exe` exists; if not, ask the user once before installing. Never silent-install. Use the bundled helpers in `scripts/` (relative to `{skillBundleDir}`):
|
|
415
|
+
- `scripts/install-tabular-editor.ps1` — detects or installs TE2 (~30 MB, .NET Framework required, already present on any machine running PBI Desktop).
|
|
416
|
+
- `scripts/run-bpa.ps1` — runs Microsoft's BPA rules against the open Desktop instance and returns findings.
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## Performance Anti-patterns
|
|
421
|
+
|
|
422
|
+
| Don't | Do instead | Why |
|
|
423
|
+
|---|---|---|
|
|
424
|
+
| "Optimize" without measuring | Capture a baseline first | Without numbers, every change is a guess |
|
|
425
|
+
| Bundle 5 fixes into one commit | One change, re-measure, then next | Otherwise you can't tell what helped or hurt |
|
|
426
|
+
| Switch to DirectQuery to "fix" Import perf | Optimize the Import model | DQ trades query speed for freshness; rarely the right answer |
|
|
427
|
+
| Add `DISTINCTCOUNT` over a 100M-row text column | Use integer surrogate keys, then DISTINCTCOUNT on int | Cardinality determines compression and scan cost |
|
|
428
|
+
| Refresh full fact table nightly | Incremental refresh with RangeStart/RangeEnd | Wastes hours of compute and capacity |
|
|
429
|
+
| Treat Desktop refresh as proof of incremental partitions | Publish and monitor the first Service refresh | Partitions are created by the Service, not by Desktop/MCP |
|
|
430
|
+
| Republish an incrementally refreshed Desktop model over the Service model | Use metadata-only deployment for Premium schema changes, or explicitly accept a partition/data reset | Republishing removes existing Service partitions/data |
|
|
431
|
+
| Hide visuals as a "perf fix" | Move heavy detail to drill-through pages and re-measure with Performance Analyzer | Hiding is not a proven optimization; measure the page after moving work out of the render path |
|
|
432
|
+
| Resolve "feels slow" subjectively | Always quote ms or MB | Subjective perf is unactionable |
|
|
433
|
+
| Add aggregations before measuring | Confirm the bottleneck first | Aggregations add complexity; only worth it if measurement justifies |
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Healthy Performance Targets
|
|
438
|
+
|
|
439
|
+
Use these as defaults. Adjust to the user's context.
|
|
440
|
+
|
|
441
|
+
| Metric | Healthy | Warning | Critical |
|
|
442
|
+
|---|---|---|---|
|
|
443
|
+
| Page load (Performance Analyzer total) | < 3s | 3–10s | > 10s |
|
|
444
|
+
| Single visual DAX query | < 500ms | 500ms–3s | > 3s |
|
|
445
|
+
| Slicer interaction | < 1s | 1–3s | > 3s |
|
|
446
|
+
| Refresh duration (per fact table) | < 5min | 5–30min | > 30min |
|
|
447
|
+
| Model size (.pbix) | < 500MB | 500MB–2GB | > 2GB |
|
|
448
|
+
| Top column size (% of model) | < 10% | 10–30% | > 30% |
|
|
449
|
+
| Capacity CU (smoothed 24h) | < 70% | 70–90% | > 90% |
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## Complexity Adaptation
|
|
454
|
+
|
|
455
|
+
- **Guiado**: explain every metric and tool from scratch (what is Performance Analyzer, what is SE vs FE, what is cardinality)
|
|
456
|
+
- **Intermedio**: explain non-obvious diagnoses (why this engine, why this column dominates); skip definitions of basic tools
|
|
457
|
+
- **Directo**: lead with the bottleneck, the metric, and the fix; explain edge cases and capacity-level concerns
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
## What this skill does NOT do
|
|
462
|
+
|
|
463
|
+
- **Formula-level rewrites of measures**: that's `/bi-dax`. This skill identifies *that* a measure is the bottleneck and quantifies the cost; the rewrite happens in `/bi-dax`.
|
|
464
|
+
- **Star schema redesign**: that's `/bi-modeling`. If the diagnosis points to a fundamentally wrong model shape (snowflake, missing Date table, many-to-many spaghetti), hand off.
|
|
465
|
+
- **Direct PBIP edits**: never. Profiling and DMV reads are non-write operations; semantic-model writes supported by the Modeling MCP go through MCP, while Desktop/Service/UI-only fixes are guided and validated without patching PBIP files.
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## Related Skills
|
|
470
|
+
|
|
471
|
+
- `/bi-modeling` — when the bottleneck is structural (relationships, snowflake, missing Date table)
|
|
472
|
+
- `/bi-dax` — when the bottleneck is a specific measure that needs a formula rewrite
|
|
473
|
+
- `/bi-connect` — when the MCP connection isn't established and you can't run DAX timing queries
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## Bundle contents
|
|
478
|
+
|
|
479
|
+
- `scripts/install-tabular-editor.ps1` — detects or installs TE2 to `%LOCALAPPDATA%\TabularEditor\`. Idempotent; outputs the resolved path. Use `-Force` to reinstall.
|
|
480
|
+
- `scripts/run-bpa.ps1` — runs Microsoft's Best Practice Analyzer rules against the open PBI Desktop instance via TE2 CLI. Auto-detects port; caches rules JSON for 7 days.
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## Related Resources
|
|
485
|
+
|
|
486
|
+
- [Performance Analyzer in Power BI Desktop](https://learn.microsoft.com/en-us/power-bi/create-reports/desktop-performance-analyzer)
|
|
487
|
+
- [DAX Studio](https://daxstudio.org/)
|
|
488
|
+
- [VertiPaq Analyzer](https://www.sqlbi.com/tools/vertipaq-analyzer/)
|
|
489
|
+
- [Tabular Editor 2 (free, MIT)](https://github.com/TabularEditor/TabularEditor)
|
|
490
|
+
- [Microsoft Best Practice Rules for Tabular Editor](https://github.com/microsoft/Analysis-Services/tree/master/BestPracticeRules)
|
|
491
|
+
- [Optimization guide for Power BI](https://learn.microsoft.com/en-us/power-bi/guidance/power-bi-optimization)
|
|
492
|
+
- [Incremental refresh for semantic models](https://learn.microsoft.com/en-us/power-bi/connect-data/incremental-refresh-overview)
|
|
493
|
+
- [Fabric Capacity Metrics app](https://learn.microsoft.com/en-us/fabric/enterprise/metrics-app)
|
|
494
|
+
- [DirectQuery model guidance](https://learn.microsoft.com/en-us/power-bi/guidance/directquery-model-guidance)
|