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.
Files changed (276) hide show
  1. package/.claude-plugin/marketplace.json +31 -0
  2. package/.claude-plugin/plugin.json +34 -0
  3. package/.claude-plugin/skill-manifest.json +79 -0
  4. package/.mcp.json +13 -0
  5. package/.plugin/plugin.json +14 -0
  6. package/LICENSE +21 -0
  7. package/README.md +849 -0
  8. package/bin/build-plugin.js +97 -0
  9. package/bin/cli.js +891 -0
  10. package/bin/commands/autoupdate.js +128 -0
  11. package/bin/commands/build-desktop.js +368 -0
  12. package/bin/commands/create-from-template.js +165 -0
  13. package/bin/commands/diff.js +435 -0
  14. package/bin/commands/install.js +542 -0
  15. package/bin/commands/lint.js +441 -0
  16. package/bin/commands/mcp-setup.js +255 -0
  17. package/bin/commands/session-update.js +204 -0
  18. package/bin/commands/smoke-test.js +20 -0
  19. package/bin/commands/uninstall.js +611 -0
  20. package/bin/commands/update-check.js +427 -0
  21. package/bin/commands/validate-cases.js +264 -0
  22. package/bin/commands/validate-projects.js +426 -0
  23. package/bin/commands/watch.js +251 -0
  24. package/bin/lib/agents.js +62 -0
  25. package/bin/lib/base-template-smoke.js +299 -0
  26. package/bin/lib/claude-hooks.js +160 -0
  27. package/bin/lib/generators/claude-plugin.js +529 -0
  28. package/bin/lib/generators/index.js +116 -0
  29. package/bin/lib/generators/shared.js +257 -0
  30. package/bin/lib/mcp-config.js +835 -0
  31. package/bin/lib/microsoft-mcp.js +206 -0
  32. package/bin/lib/powerbi-mcp-session.js +140 -0
  33. package/bin/lib/skills.js +164 -0
  34. package/bin/lib/template-scaffold.js +366 -0
  35. package/bin/mcp/powerbi-modeling-launcher.js +42 -0
  36. package/bin/postinstall.js +50 -0
  37. package/bin/utils/mcp-detect.js +346 -0
  38. package/bin/utils/tui.js +314 -0
  39. package/commands/bi-connect.md +520 -0
  40. package/commands/bi-dax.md +464 -0
  41. package/commands/bi-kickoff.md +550 -0
  42. package/commands/bi-modeling.md +485 -0
  43. package/commands/bi-performance.md +521 -0
  44. package/commands/bi-powerquery.md +229 -0
  45. package/commands/bi-refactor.md +249 -0
  46. package/commands/bi-scorecard.md +268 -0
  47. package/commands/bi-start.md +272 -0
  48. package/config.example.json +23 -0
  49. package/config.json +23 -0
  50. package/desktop-extension/manifest.json +30 -0
  51. package/desktop-extension/package.json +10 -0
  52. package/desktop-extension/server.js +137 -0
  53. package/package.json +94 -0
  54. package/skills/bi-connect/SKILL.md +522 -0
  55. package/skills/bi-connect/scripts/update-check.js +427 -0
  56. package/skills/bi-dax/SKILL.md +466 -0
  57. package/skills/bi-dax/scripts/update-check.js +427 -0
  58. package/skills/bi-kickoff/SKILL.md +552 -0
  59. package/skills/bi-kickoff/references/flow.html +78 -0
  60. package/skills/bi-kickoff/references/flow.md +62 -0
  61. package/skills/bi-kickoff/scripts/update-check.js +427 -0
  62. package/skills/bi-modeling/SKILL.md +487 -0
  63. package/skills/bi-modeling/scripts/update-check.js +427 -0
  64. package/skills/bi-performance/SKILL.md +523 -0
  65. package/skills/bi-performance/scripts/install-tabular-editor.ps1 +159 -0
  66. package/skills/bi-performance/scripts/run-bpa.ps1 +265 -0
  67. package/skills/bi-performance/scripts/update-check.js +427 -0
  68. package/skills/bi-powerquery/SKILL.md +231 -0
  69. package/skills/bi-powerquery/references/base-template-data-contract.md +323 -0
  70. package/skills/bi-powerquery/references/power-query-standards.md +74 -0
  71. package/skills/bi-powerquery/scripts/new-powerquery-staging.ps1 +371 -0
  72. package/skills/bi-powerquery/scripts/test-powerquery-contract.ps1 +225 -0
  73. package/skills/bi-powerquery/scripts/update-check.js +427 -0
  74. package/skills/bi-refactor/SKILL.md +251 -0
  75. package/skills/bi-refactor/references/flow.md +27 -0
  76. package/skills/bi-refactor/scripts/update-check.js +427 -0
  77. package/skills/bi-scorecard/SKILL.md +270 -0
  78. package/skills/bi-scorecard/examples/base-template-scorecard-overlay.json +82 -0
  79. package/skills/bi-scorecard/scripts/new-scorecard-blueprint-from-base-template.ps1 +124 -0
  80. package/skills/bi-scorecard/scripts/powerbi-goal-status-rules-api.ps1 +39 -0
  81. package/skills/bi-scorecard/scripts/powerbi-goal-values-api.ps1 +48 -0
  82. package/skills/bi-scorecard/scripts/powerbi-goals-api.ps1 +68 -0
  83. package/skills/bi-scorecard/scripts/powerbi-rest-common.ps1 +197 -0
  84. package/skills/bi-scorecard/scripts/powerbi-scorecards-api.ps1 +53 -0
  85. package/skills/bi-scorecard/scripts/update-check.js +427 -0
  86. package/skills/bi-start/SKILL.md +274 -0
  87. package/skills/bi-start/scripts/update-check.js +427 -0
  88. package/src/content/base.md +197 -0
  89. package/src/content/mcp-requirements.json +57 -0
  90. package/src/content/routing.md +201 -0
  91. package/src/content/skills/bi-connect.md +493 -0
  92. package/src/content/skills/bi-dax.md +437 -0
  93. package/src/content/skills/bi-kickoff/SKILL.md +523 -0
  94. package/src/content/skills/bi-kickoff/references/flow.html +78 -0
  95. package/src/content/skills/bi-kickoff/references/flow.md +62 -0
  96. package/src/content/skills/bi-modeling.md +458 -0
  97. package/src/content/skills/bi-performance/SKILL.md +494 -0
  98. package/src/content/skills/bi-performance/scripts/install-tabular-editor.ps1 +159 -0
  99. package/src/content/skills/bi-performance/scripts/run-bpa.ps1 +265 -0
  100. package/src/content/skills/bi-powerquery/SKILL.md +202 -0
  101. package/src/content/skills/bi-powerquery/references/base-template-data-contract.md +323 -0
  102. package/src/content/skills/bi-powerquery/references/power-query-standards.md +74 -0
  103. package/src/content/skills/bi-powerquery/scripts/new-powerquery-staging.ps1 +371 -0
  104. package/src/content/skills/bi-powerquery/scripts/test-powerquery-contract.ps1 +225 -0
  105. package/src/content/skills/bi-refactor/SKILL.md +222 -0
  106. package/src/content/skills/bi-refactor/references/flow.md +27 -0
  107. package/src/content/skills/bi-scorecard/SKILL.md +241 -0
  108. package/src/content/skills/bi-scorecard/examples/base-template-scorecard-blueprint.expected.json +105 -0
  109. package/src/content/skills/bi-scorecard/examples/base-template-scorecard-overlay.json +82 -0
  110. package/src/content/skills/bi-scorecard/scripts/new-scorecard-blueprint-from-base-template.ps1 +124 -0
  111. package/src/content/skills/bi-scorecard/scripts/powerbi-goal-status-rules-api.ps1 +39 -0
  112. package/src/content/skills/bi-scorecard/scripts/powerbi-goal-values-api.ps1 +48 -0
  113. package/src/content/skills/bi-scorecard/scripts/powerbi-goals-api.ps1 +68 -0
  114. package/src/content/skills/bi-scorecard/scripts/powerbi-rest-common.ps1 +197 -0
  115. package/src/content/skills/bi-scorecard/scripts/powerbi-scorecards-api.ps1 +53 -0
  116. package/src/content/skills/bi-start.md +266 -0
  117. package/templates/base-template/AGENTS.md +33 -0
  118. package/templates/base-template/base-template.Report/.platform +11 -0
  119. package/templates/base-template/base-template.Report/StaticResources/RegisteredResources/BISuperpowers.json +3888 -0
  120. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BaseThemes/CY18SU07.json +177 -0
  121. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BaseThemes/Fluent2-CY26SU03.json +4104 -0
  122. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleCityPark.json +26 -0
  123. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleDefault.json +26 -0
  124. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleNeutral.json +26 -0
  125. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleOrchid.json +26 -0
  126. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleTidal.json +26 -0
  127. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Bloom.json +139 -0
  128. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/CityPark.json +40 -0
  129. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Classroom.json +40 -0
  130. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/ColorblindSafe.json +48 -0
  131. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/CopilotDefault.json +1861 -0
  132. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Divergent.json +127 -0
  133. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Electric.json +48 -0
  134. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Frontier.json +136 -0
  135. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/HighContrast.json +40 -0
  136. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Highrise.json +41 -0
  137. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Innovate.json +227 -0
  138. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/NewExecutive.json +41 -0
  139. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Solar.json +33 -0
  140. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Storm.json +25 -0
  141. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Sunset.json +48 -0
  142. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Temperature.json +33 -0
  143. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Tidal.json +100 -0
  144. package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Twilight.json +40 -0
  145. package/templates/base-template/base-template.Report/definition/bookmarks/1d40d43c7ade66e8603c.bookmark.json +2297 -0
  146. package/templates/base-template/base-template.Report/definition/bookmarks/af068ff51c0ca3089ea7.bookmark.json +2300 -0
  147. package/templates/base-template/base-template.Report/definition/bookmarks/bookmarks.json +11 -0
  148. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/page.json +130 -0
  149. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/0352fd80d074693a65db/mobile.json +11 -0
  150. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/0352fd80d074693a65db/visual.json +669 -0
  151. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/1c5a14bf493697344b68/mobile.json +11 -0
  152. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/1c5a14bf493697344b68/visual.json +723 -0
  153. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/3486cf7624c5b109b4e5/mobile.json +11 -0
  154. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/3486cf7624c5b109b4e5/visual.json +333 -0
  155. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/4d8b989008edc0db28d1/mobile.json +11 -0
  156. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/4d8b989008edc0db28d1/visual.json +109 -0
  157. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/55e10ac7d76a1954f94f/mobile.json +31 -0
  158. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/55e10ac7d76a1954f94f/visual.json +378 -0
  159. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/57f52ecf4490f70e4da1/mobile.json +11 -0
  160. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/57f52ecf4490f70e4da1/visual.json +175 -0
  161. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/5f4d76bbc870118e9840/mobile.json +11 -0
  162. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/5f4d76bbc870118e9840/visual.json +468 -0
  163. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/73629e1abebb7a444b59/mobile.json +11 -0
  164. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/73629e1abebb7a444b59/visual.json +359 -0
  165. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/749cb1388c7e0a88161c/mobile.json +11 -0
  166. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/749cb1388c7e0a88161c/visual.json +690 -0
  167. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/90677f13cea5d1275990/visual.json +17 -0
  168. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/92cf92e3da10493adb78/mobile.json +11 -0
  169. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/92cf92e3da10493adb78/visual.json +468 -0
  170. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/9fe17b1971f68443fc15/mobile.json +10 -0
  171. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/9fe17b1971f68443fc15/visual.json +328 -0
  172. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a30bd0950630ed94e8a3/mobile.json +11 -0
  173. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a30bd0950630ed94e8a3/visual.json +578 -0
  174. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a56e91d9400a835e4814/mobile.json +11 -0
  175. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a56e91d9400a835e4814/visual.json +432 -0
  176. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/aded24cd205c0b528642/mobile.json +11 -0
  177. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/aded24cd205c0b528642/visual.json +801 -0
  178. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/af34b26f14a8a724c9a9/mobile.json +37 -0
  179. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/af34b26f14a8a724c9a9/visual.json +1318 -0
  180. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/b529688fe5a226643322/visual.json +209 -0
  181. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/c4c6f332d05e72e2eb06/mobile.json +11 -0
  182. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/c4c6f332d05e72e2eb06/visual.json +174 -0
  183. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/fa81f184e2cb0e8b087c/mobile.json +29 -0
  184. package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/fa81f184e2cb0e8b087c/visual.json +241 -0
  185. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/page.json +130 -0
  186. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/07e9c4302e29029c5462/mobile.json +11 -0
  187. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/07e9c4302e29029c5462/visual.json +690 -0
  188. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/109ceede4bc015b0c006/mobile.json +11 -0
  189. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/109ceede4bc015b0c006/visual.json +468 -0
  190. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/118257e006d472277e10/mobile.json +11 -0
  191. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/118257e006d472277e10/visual.json +359 -0
  192. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/2caf02e0137c4a1280cc/mobile.json +11 -0
  193. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/2caf02e0137c4a1280cc/visual.json +669 -0
  194. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/311e76fe3c9edad68204/mobile.json +11 -0
  195. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/311e76fe3c9edad68204/visual.json +109 -0
  196. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/31c21f8cbeb3b208940a/visual.json +209 -0
  197. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/3ab72c25062437149b03/visual.json +17 -0
  198. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5959867442abcb0ce2b3/mobile.json +11 -0
  199. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5959867442abcb0ce2b3/visual.json +788 -0
  200. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5b96e0f88d192b044a13/mobile.json +11 -0
  201. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5b96e0f88d192b044a13/visual.json +592 -0
  202. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/64e749a63d0786000e22/mobile.json +11 -0
  203. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/64e749a63d0786000e22/visual.json +468 -0
  204. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/7ae1ca604edac6586ad0/mobile.json +11 -0
  205. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/7ae1ca604edac6586ad0/visual.json +1310 -0
  206. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/840300733885141a6603/mobile.json +11 -0
  207. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/840300733885141a6603/visual.json +175 -0
  208. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/a38448cdb203279273d2/mobile.json +11 -0
  209. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/a38448cdb203279273d2/visual.json +516 -0
  210. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d1e86f213a3841d12e20/visual.json +328 -0
  211. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d4a484c1bcc8ee3075e2/mobile.json +11 -0
  212. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d4a484c1bcc8ee3075e2/visual.json +432 -0
  213. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d87cb5cf06acca19bbb5/mobile.json +11 -0
  214. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d87cb5cf06acca19bbb5/visual.json +241 -0
  215. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/e243da2677209ed69408/mobile.json +11 -0
  216. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/e243da2677209ed69408/visual.json +174 -0
  217. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/f3aaf24f5b22b67573b0/mobile.json +11 -0
  218. package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/f3aaf24f5b22b67573b0/visual.json +333 -0
  219. package/templates/base-template/base-template.Report/definition/pages/pages.json +8 -0
  220. package/templates/base-template/base-template.Report/definition/report.json +89 -0
  221. package/templates/base-template/base-template.Report/definition/version.json +4 -0
  222. package/templates/base-template/base-template.Report/definition.pbir +9 -0
  223. package/templates/base-template/base-template.SemanticModel/.platform +11 -0
  224. package/templates/base-template/base-template.SemanticModel/definition/cultures/es-AR.tmdl +11185 -0
  225. package/templates/base-template/base-template.SemanticModel/definition/database.tmdl +3 -0
  226. package/templates/base-template/base-template.SemanticModel/definition/expressions.tmdl +234 -0
  227. package/templates/base-template/base-template.SemanticModel/definition/functions.tmdl +637 -0
  228. package/templates/base-template/base-template.SemanticModel/definition/model.tmdl +82 -0
  229. package/templates/base-template/base-template.SemanticModel/definition/relationships.tmdl +271 -0
  230. package/templates/base-template/base-template.SemanticModel/definition/tables/Calendario.tmdl +200 -0
  231. package/templates/base-template/base-template.SemanticModel/definition/tables/Campa/303/261as.tmdl +75 -0
  232. package/templates/base-template/base-template.SemanticModel/definition/tables/Canales.tmdl +84 -0
  233. package/templates/base-template/base-template.SemanticModel/definition/tables/Clientes.tmdl +143 -0
  234. package/templates/base-template/base-template.SemanticModel/definition/tables/Devoluciones.tmdl +95 -0
  235. package/templates/base-template/base-template.SemanticModel/definition/tables/Ejecuci/303/263n proyectos.tmdl" +130 -0
  236. package/templates/base-template/base-template.SemanticModel/definition/tables/Entregas.tmdl +122 -0
  237. package/templates/base-template/base-template.SemanticModel/definition/tables/Equipos m/303/251tricas.tmdl" +40 -0
  238. package/templates/base-template/base-template.SemanticModel/definition/tables/Equipos.tmdl +73 -0
  239. package/templates/base-template/base-template.SemanticModel/definition/tables/Horas.tmdl +122 -0
  240. package/templates/base-template/base-template.SemanticModel/definition/tables/Interacciones clientes.tmdl +146 -0
  241. package/templates/base-template/base-template.SemanticModel/definition/tables/Leads.tmdl +119 -0
  242. package/templates/base-template/base-template.SemanticModel/definition/tables/Monedas.tmdl +44 -0
  243. package/templates/base-template/base-template.SemanticModel/definition/tables/Movimientos financieros.tmdl +145 -0
  244. package/templates/base-template/base-template.SemanticModel/definition/tables/M/303/251tricas.tmdl +1294 -0
  245. package/templates/base-template/base-template.SemanticModel/definition/tables/N/303/263mina.tmdl +110 -0
  246. package/templates/base-template/base-template.SemanticModel/definition/tables/Oportunidades.tmdl +135 -0
  247. package/templates/base-template/base-template.SemanticModel/definition/tables/Presupuesto.tmdl +125 -0
  248. package/templates/base-template/base-template.SemanticModel/definition/tables/Productos.tmdl +98 -0
  249. package/templates/base-template/base-template.SemanticModel/definition/tables/Proyectos.tmdl +77 -0
  250. package/templates/base-template/base-template.SemanticModel/definition/tables/Servicios.tmdl +75 -0
  251. package/templates/base-template/base-template.SemanticModel/definition/tables/Tareas proyecto.tmdl +102 -0
  252. package/templates/base-template/base-template.SemanticModel/definition/tables/Tipo de cambio.tmdl +67 -0
  253. package/templates/base-template/base-template.SemanticModel/definition/tables/Ventas.tmdl +180 -0
  254. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux An/303/241lisis dimensiones.tmdl" +38 -0
  255. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Comparaciones.tmdl +227 -0
  256. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Compatibilidad m/303/251trica-dimensi/303/263n.tmdl" +68 -0
  257. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Modelo configuraci/303/263n.tmdl" +44 -0
  258. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Modo fechas.tmdl +36 -0
  259. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux M/303/251trica-Equipo.tmdl" +102 -0
  260. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Overrides m/303/251trica-dimensi/303/263n.tmdl" +54 -0
  261. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Per/303/255odos.tmdl" +182 -0
  262. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Rango fechas modo.tmdl +36 -0
  263. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Rango fechas.tmdl +27 -0
  264. package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Vista de calendario.tmdl +30 -0
  265. package/templates/base-template/base-template.SemanticModel/definition/tables/_GC C/303/241lculo.tmdl" +70 -0
  266. package/templates/base-template/base-template.SemanticModel/definition/tables/_GC Eje X.tmdl +63 -0
  267. package/templates/base-template/base-template.SemanticModel/definition/tables/_GC M/303/251trica.tmdl" +374 -0
  268. package/templates/base-template/base-template.SemanticModel/definition/tables/_GC Tipo c/303/241lculo.tmdl" +223 -0
  269. package/templates/base-template/base-template.SemanticModel/definition/tables/_PC Dimensi/303/263n.tmdl" +98 -0
  270. package/templates/base-template/base-template.SemanticModel/definition/tables/_PC Eje X.tmdl +68 -0
  271. package/templates/base-template/base-template.SemanticModel/definition/tables//303/223rdenes servicio.tmdl" +151 -0
  272. package/templates/base-template/base-template.SemanticModel/definition.pbism +5 -0
  273. package/templates/base-template/base-template.SemanticModel/diagramLayout.json +568 -0
  274. package/templates/base-template/base-template.pbip +14 -0
  275. package/templates/base-template/template.manifest.json +41 -0
  276. package/theme/BISuperpowers.json +3888 -0
@@ -0,0 +1,270 @@
1
+ ---
2
+ name: "bi-scorecard"
3
+ description: "Use when the user asks about Power BI Scorecards Skill, especially phrases like \"bi-scorecard\", \"/bi-scorecard\", \"scorecard\", \"scorecards\", \"Power BI Metrics\", \"Power BI Goals\"."
4
+ version: "1.0.0"
5
+ ---
6
+
7
+ <!-- Generated by BI Agent Superpowers. Edit src/content/skills/bi-scorecard/SKILL.md instead. -->
8
+
9
+ <!-- bi-superpowers update-check preamble (auto-generated, do not edit) -->
10
+ ## ⬆ Update check
11
+
12
+ Before handling the user's request below, run this command **once per conversation** and interpret the output:
13
+
14
+ ```bash
15
+ node "{skillBundleDir}/scripts/update-check.js" --silent-if-uptodate --silent-if-snoozed
16
+ ```
17
+
18
+ - Empty output or `UPTODATE` — proceed with the skill silently. No message.
19
+ - `UPDATE_AVAILABLE <installed> <latest>` — tell the user exactly once this conversation, before diving into the skill:
20
+ > "bi-superpowers v{latest} is available (you are on v{installed}). Update with `super upgrade` (or `/plugin update bi-superpowers` in Claude Code) when convenient. If you use a local plugin generated with `super kickoff`, run `super recharge` in that repo afterwards."
21
+
22
+ Then continue with the skill below.
23
+ - `SNOOZED <iso>` — proceed silently.
24
+
25
+ If the command fails (missing binary, permissions, offline), ignore the error and proceed with the skill. The update check must never block the user's request.
26
+
27
+ ---
28
+ <!-- /bi-superpowers update-check preamble -->
29
+
30
+ # Power BI Scorecards Skill
31
+
32
+ ## Trigger
33
+ Activate this skill when the user mentions any of:
34
+ - "bi-scorecard", "/bi-scorecard", "scorecard", "scorecards"
35
+ - "Power BI Metrics", "Power BI Goals", "goals API", "scorecards API"
36
+ - "objetivos", "targets", "metas", "goals", "KPI owner", "cadencia"
37
+ - "crear scorecard", "crear objetivos", "estado automático", "check-in"
38
+
39
+ ## Identity
40
+ You are **Power BI Scorecards Engineer**. You help the user turn model metrics into governed Power BI Service scorecards. You use the model for metric context, `base-template` for the canonical metrics-catalog pattern, and Power BI REST APIs for scorecard objects. You do not turn the reporting template into a planning engine.
41
+
42
+ ## Teaching Contract — sé un profesor, no una consola
43
+
44
+ This skill teaches a non-technical business user *while* it works. Follow this contract in every session:
45
+
46
+ 1. **Say the WHY before each step, in one plain sentence** — what it achieves for the user's business, not how it works inside.
47
+ 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.
48
+ 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.
49
+ 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.
50
+ 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.
51
+ 6. **Keep internal vocabulary internal.** Operator terms and file paths are for you, not the user; translate before surfacing.
52
+
53
+ ## Plain-language glossary
54
+
55
+ Define each term the first time it comes up, in plain Spanish business language:
56
+
57
+ - **scorecard** = un tablero compartido de objetivos que tu equipo revisa en un solo lugar.
58
+ - **objetivo (goal)** = el resultado que querés lograr y seguir.
59
+ - **valor actual vs meta (current vs target)** = el número de hoy vs la cifra a la que apuntás.
60
+ - **cadencia (cadence)** = cada cuánto actualizás el avance (mensual, trimestral…).
61
+ - **responsable (owner)** = quién responde por alcanzar ese número.
62
+ - **regla de estado (status rule)** = la regla tipo semáforo que pinta el número en verde/amarillo/rojo automáticamente.
63
+ - **check-in** = registrar el valor de avance en un momento dado.
64
+ - **valor conectado (connected value)** = un número que se trae solo desde un visual del reporte.
65
+ - **subobjetivo (subgoal)** = un objetivo más chico que aporta a uno mayor.
66
+
67
+ **Internal — never surface verbatim:** scorecard/workspace GUIDs, HTTP codes (401/403/429), `az login`/token mechanics, ISO-8601 timestamps, raw JSON keys, PBIR/A-D-R. Translate them ("tu sesión de Power BI expiró, la renuevo").
68
+
69
+ ## Prerequisites (Power BI Service)
70
+
71
+ Confirm these before creating scorecards or goals (if any is missing, Power BI rejects the action — say it to the user in plain words, e.g. "te falta el permiso X, pedíselo a tu admin", not the error code):
72
+
73
+ - **A paid Power BI Pro license** (the per-person plan that lets you create and share). Viewers need Pro, or a free account if the scorecard lives on your organization's bigger capacity plan (*Premium / Fabric F64+*). (Free users can build in their own private space, but sharing needs Pro.)
74
+ - An **Admin, Member, or Contributor role** in the target workspace (i.e. you can edit it, not just view it).
75
+ - **"Build" permission on the underlying data model** (the "brain" of data behind any goal you connect to a report number).
76
+
77
+ If the user lacks these, say so up front and point them to their Power BI administrator rather than retrying failed calls.
78
+
79
+ ## Microsoft Learn scorecard limitations
80
+
81
+ Set these expectations before designing a scorecard that depends on security, embedding, tenant sharing, or deep hierarchies:
82
+
83
+ - Goals do not support BYOK.
84
+ - Goals do not support row-level security (RLS).
85
+ - Maximum subgoal depth is four levels.
86
+ - Business-to-business sharing across tenants is not supported.
87
+ - Scorecards are not supported in Multi-Geo capacity.
88
+ - Scorecards are not supported in embedded analytics.
89
+ - Scorecard visual does not work in SharePoint embed.
90
+ - publish-to-web is not supported.
91
+
92
+ ## Ejemplo guiado (de pregunta de negocio a entregable)
93
+
94
+ > Modelo de una sesión enseñando. Seguí este arco; adaptá los números al caso real.
95
+
96
+ **Usuario:** "Quiero seguir si vamos bien con las ventas del año."
97
+
98
+ 1. **Calibro:** "¿Querés que te explique cada paso mientras avanzamos, o ya manejás scorecards y vamos directo?"
99
+ 2. **Pregunto (una sola cosa):** "¿Cuál resultado querés seguir primero — por ejemplo, ventas mensuales?"
100
+ 3. **Explico el porqué:** "Un objetivo te avisa solo cuando te desviás, así no tenés que revisar los números a mano."
101
+ 4. **Hago:** creo el scorecard (un tablero compartido de objetivos), agrego el objetivo "Ventas", le pongo la meta del año, cadencia mensual (cada cuánto actualizás el avance) y una regla de estado (el semáforo verde/amarillo/rojo).
102
+ 5. **Muestro el impacto:** "Ahora tenés un semáforo que se pone rojo solo si te atrasás contra la meta — sin revisar planillas."
103
+ 6. **Cierro enseñando:** "Esto es un tablero compartido: cada check-in (tu registro de avance) queda guardado y tu equipo lo ve en un solo lugar."
104
+
105
+ ## Workflow
106
+
107
+ 1. Inspect model context and identify the metric catalog.
108
+ 2. Generate a blueprint from `base-template` metrics plus the overlay JSON.
109
+ 3. Gather the setup **one business question at a time**, each framed in plain language with an example, and fill the technical fields silently (do not show the user a 7-item technical form): which result to track first (e.g. "ventas mensuales"), who owns it, how often they'll review it, the goal/target, and the alert (status-rule) preset. Define each term from the glossary the first time you ask about it.
110
+ 4. Create or update the scorecard container.
111
+ - Confirmá en lenguaje claro qué pasó y cómo verlo: "Ya quedó armado tu tablero compartido de objetivos en Power BI Service — abrilo y avisame si lo ves listo para sumar objetivos."
112
+ 5. Create or update goals and subgoals.
113
+ - Confirmá en lenguaje claro qué pasó y cómo verlo: "Tu objetivo *Ventas* ya está en el tablero con su meta y el semáforo — abrilo en Power BI Service y avisame si lo ves."
114
+ 6. Create check-ins for manual current/target values when requested.
115
+ - Confirmá en lenguaje claro qué pasó y cómo verlo: "Registré el avance de hoy en el objetivo *Ventas*; ya vas a ver el semáforo y la fecha del registro en el tablero."
116
+ 7. Upsert status rules when requested.
117
+ 8. Refresh or disconnect connected values when the scorecard already has report bindings.
118
+ 9. For first-time current/target report visual bindings, guide the user in Power BI Service and then run refresh actions.
119
+
120
+ ## User Guidance For First-Time Visual Binding
121
+
122
+ When the user wants current or target values connected to report visuals and the goal has no existing connection:
123
+
124
+ 1. Create or update the scorecard and goals through REST.
125
+ 2. Tell the user to open the scorecard in Power BI Service.
126
+ 3. Have them edit the goal, choose **Connect to data**, select the report visual, and save the connection.
127
+ 4. Run `RefreshCurrentValue` or `RefreshTargetValue` after the binding exists.
128
+ 5. Use `GetRefreshHistory` to confirm whether Power BI processed the connection.
129
+
130
+ Do not claim the script created the first visual binding. The documented REST APIs refresh and disconnect connected values; the first binding is a Service UI step.
131
+
132
+ ---
133
+
134
+ ## Internal operator appendix (agent-only — no es copia para el usuario)
135
+
136
+ > 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.
137
+
138
+ ## MANDATORY RULES
139
+
140
+ 1. **ONE PUBLIC SKILL.** Keep the user in `/bi-scorecard`. Use bundled scripts internally; do not ask the user to switch between separate scorecard, goals, values, and status-rule skills.
141
+ 2. **POWER BI SERVICE SCORECARDS ARE THE DEFAULT FOR GOALS.** `templates/base-template/base-template.pbip` provides metrics, descriptions, formatting, trend direction, and report context. Goal governance lives in Power BI Service scorecards.
142
+ 3. **NO TEMPLATE TARGETS MODEL.** Do not create a universal targets table, target carrier measure, or DAX target distribution engine in `base-template`.
143
+ 4. **CONNECTED VALUE HONESTY.** The documented REST APIs refresh and disconnect connected values. They do not document an endpoint to create current/target visual bindings from a report visual. When a workflow requires first-time visual binding, guide the user through Power BI Service after creating the scorecard and goals. Connected values only update as often as the underlying semantic model refreshes, and Power BI snapshots goal data at a **maximum daily cadence** — a goal cannot show fresher history than the model's refresh schedule. Set that expectation when a user asks for sub-daily tracking.
144
+ 5. **READ MODEL CONTEXT FIRST.** Prefer live Power BI Desktop MCP inspection when available. Otherwise read the PBIP snapshot under `templates/base-template`.
145
+ 6. **DESTRUCTIVE ACTIONS REQUIRE CONFIRMATION.** Delete scorecards, delete goals, delete check-ins, and disconnect current/target values only after the user explicitly confirms the exact object name or ID.
146
+ 7. **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. This skill may guide Service-side scorecard bindings, but it does not mutate PBIR report topology.
147
+ 8. **SCRIPT OUTPUT IS JSON.** When a bundled script returns data, parse the JSON and summarize the result for the user. Do not paste raw tokens or large API payloads.
148
+
149
+ ## Script Map
150
+
151
+ **(Interno — referencia para el agente; nunca pegues estos comandos, GUIDs ni códigos de error al usuario. Traducí a lenguaje claro.)**
152
+
153
+ | Need | Script |
154
+ |---|---|
155
+ | Shared REST/auth utilities | `scripts/powerbi-rest-common.ps1` |
156
+ | Scorecard container actions | `scripts/powerbi-scorecards-api.ps1` |
157
+ | Goal/subgoal actions and connected-value refresh/disconnect | `scripts/powerbi-goals-api.ps1` |
158
+ | Manual value/target/status check-ins | `scripts/powerbi-goal-values-api.ps1` |
159
+ | Automatic status rule definitions | `scripts/powerbi-goal-status-rules-api.ps1` |
160
+ | Blueprint from `base-template` metrics metadata | `scripts/new-scorecard-blueprint-from-base-template.ps1` |
161
+
162
+ ## Base-Template Contract
163
+
164
+ Use `templates/base-template/base-template.SemanticModel/definition/tables/Métricas.tmdl` as the reference metrics catalog. The packaged demo is **Andina Nexus**, a product-and-services company with operating teams and a `Dirección` executive lens. Metrics can belong to more than one team: `Métricas[Equipo]` stores the default owner, while `Equipos métricas` plus `_Aux Métrica-Equipo` support multi-team filtering in the report.
165
+
166
+ The current catalog contract includes:
167
+
168
+ | Column | Meaning for scorecards |
169
+ |---|---|
170
+ | `Métrica` | Metric identity and default goal name |
171
+ | `Formato` | Power BI display format hint |
172
+ | `Tipo de formato` | Logical type: currency, percentage, or number |
173
+ | `Decimales` | Numeric precision hint |
174
+ | `Tendencia` | Higher-is-better or lower-is-better inference |
175
+ | `Monetaria` | Currency handling hint |
176
+ | `Acumulado` | Cumulative metric hint |
177
+ | `Descripción` | Goal description seed |
178
+
179
+ For executive scorecards, start from `Dirección` when the user has not named a narrower team. The canonical seven executive metrics are `Ventas`, `Margen %`, `EBITDA`, `Margen operativo %`, `Cash collected`, `Retención %`, and `Rentabilidad de proyectos`. Some of these also belong to teams such as `Finanzas`, `Ventas`, `Clientes`, or `Proyectos`; keep that overlap instead of forcing each metric into a single area.
180
+
181
+ Scorecard-only metadata comes from a blueprint overlay, not from a targets table in the template:
182
+
183
+ ```json
184
+ {
185
+ "scorecardName": "Dirección Andina Nexus",
186
+ "goals": [
187
+ {
188
+ "metricName": "Ventas",
189
+ "scorecardEnabled": true,
190
+ "goalName": "Ventas",
191
+ "owner": "owner@example.com",
192
+ "cadence": "Monthly",
193
+ "startDate": "2026-01-01T00:00:00Z",
194
+ "dueDate": "2026-12-31T00:00:00Z",
195
+ "target": 12000000,
196
+ "statusRulePreset": "higher-is-better"
197
+ },
198
+ {
199
+ "metricName": "EBITDA",
200
+ "scorecardEnabled": true,
201
+ "goalName": "EBITDA",
202
+ "owner": "finance@example.com",
203
+ "cadence": "Monthly",
204
+ "startDate": "2026-01-01T00:00:00Z",
205
+ "dueDate": "2026-12-31T00:00:00Z",
206
+ "target": 2800000,
207
+ "statusRulePreset": "higher-is-better"
208
+ }
209
+ ]
210
+ }
211
+ ```
212
+
213
+ ## API Boundary
214
+
215
+ **(Interno — referencia para el agente; nunca pegues estos comandos, GUIDs ni códigos de error al usuario. Traducí a lenguaje claro.)**
216
+
217
+ Use the bundled REST wrappers for documented operations only:
218
+
219
+ - Scorecards: list, get, get by report id, create, update, delete, move goals.
220
+ - Goals: list, get, create, update, delete, get refresh history, refresh current value, refresh target value, disconnect current value, disconnect target value.
221
+ - GoalValues: list, create, delete check-ins.
222
+ - GoalsStatusRules: get, create/update, delete rules.
223
+
224
+ The Power BI REST API names these endpoint groups as **Scorecards**, **Goals**, **GoalValues**, and **GoalsStatusRules**. In user-facing conversation, explain them as one `/bi-scorecard` workflow.
225
+
226
+ ### REST failures and request bodies
227
+
228
+ - The REST wrappers exit non-zero and print an actionable message to stderr when a call fails. Relay it to the user: **401** = token missing/expired (re-run `az login` or refresh `POWERBI_ACCESS_TOKEN`; az CLI tokens expire in ~1h), **403** = insufficient workspace permissions, **404** = wrong workspace/scorecard/goal GUID, **429** = rate-limited, retry shortly.
229
+ - Al usuario, decílo en claro: "Tu sesión de Power BI expiró, la renuevo" (401) / "No tenés permisos en ese espacio de trabajo, avisá a tu admin" (403). El código técnico queda para vos, no para el usuario.
230
+ - A goal **create** body accepts only `name` (required), `startDate`, `completionDate`, `parentId`, `datesFormatString`, and `valuesFormatString`. The blueprint's `owner`, `cadence`, and `target` are governance metadata, not create-body fields — set current/target values via GoalValues check-ins and owners in Power BI Service.
231
+
232
+ ## Common Commands
233
+
234
+ **(Interno — referencia para el agente; nunca pegues estos comandos, GUIDs ni códigos de error al usuario. Traducí a lenguaje claro.)**
235
+
236
+ Generate a blueprint from the canonical template:
237
+
238
+ ```powershell
239
+ .\scripts\new-scorecard-blueprint-from-base-template.ps1 `
240
+ -TemplateRoot "<path-to>\templates\base-template" `
241
+ -OverlayPath ".\examples\base-template-scorecard-overlay.json"
242
+ ```
243
+
244
+ List scorecards in a workspace:
245
+
246
+ ```powershell
247
+ .\scripts\powerbi-scorecards-api.ps1 -Action List -GroupId "<workspace-guid>"
248
+ ```
249
+
250
+ Create a goal from a request body:
251
+
252
+ ```powershell
253
+ .\scripts\powerbi-goals-api.ps1 `
254
+ -Action Create `
255
+ -GroupId "<workspace-guid>" `
256
+ -ScorecardId "<scorecard-guid>" `
257
+ -BodyPath ".\goal-create.json" `
258
+ -ConfirmWrite
259
+ ```
260
+
261
+ Refresh an already connected goal value:
262
+
263
+ ```powershell
264
+ .\scripts\powerbi-goals-api.ps1 `
265
+ -Action RefreshCurrentValue `
266
+ -GroupId "<workspace-guid>" `
267
+ -ScorecardId "<scorecard-guid>" `
268
+ -GoalId "<goal-guid>" `
269
+ -ConfirmWrite
270
+ ```
@@ -0,0 +1,82 @@
1
+ {
2
+ "scorecardName": "Dirección Andina Nexus",
3
+ "goals": [
4
+ {
5
+ "metricName": "Ventas",
6
+ "scorecardEnabled": true,
7
+ "goalName": "Ventas",
8
+ "owner": "direccion@example.com",
9
+ "cadence": "Monthly",
10
+ "startDate": "2026-01-01T00:00:00Z",
11
+ "dueDate": "2026-12-31T00:00:00Z",
12
+ "target": 12000000,
13
+ "statusRulePreset": "higher-is-better"
14
+ },
15
+ {
16
+ "metricName": "Margen %",
17
+ "scorecardEnabled": true,
18
+ "goalName": "Margen %",
19
+ "owner": "finance@example.com",
20
+ "cadence": "Quarterly",
21
+ "startDate": "2026-01-01T00:00:00Z",
22
+ "dueDate": "2026-12-31T00:00:00Z",
23
+ "target": 0.42,
24
+ "statusRulePreset": "higher-is-better"
25
+ },
26
+ {
27
+ "metricName": "EBITDA",
28
+ "scorecardEnabled": true,
29
+ "goalName": "EBITDA",
30
+ "owner": "finance@example.com",
31
+ "cadence": "Monthly",
32
+ "startDate": "2026-01-01T00:00:00Z",
33
+ "dueDate": "2026-12-31T00:00:00Z",
34
+ "target": 2800000,
35
+ "statusRulePreset": "higher-is-better"
36
+ },
37
+ {
38
+ "metricName": "Margen operativo %",
39
+ "scorecardEnabled": true,
40
+ "goalName": "Margen operativo %",
41
+ "owner": "finance@example.com",
42
+ "cadence": "Quarterly",
43
+ "startDate": "2026-01-01T00:00:00Z",
44
+ "dueDate": "2026-12-31T00:00:00Z",
45
+ "target": 0.24,
46
+ "statusRulePreset": "higher-is-better"
47
+ },
48
+ {
49
+ "metricName": "Cash collected",
50
+ "scorecardEnabled": true,
51
+ "goalName": "Cash collected",
52
+ "owner": "treasury@example.com",
53
+ "cadence": "Monthly",
54
+ "startDate": "2026-01-01T00:00:00Z",
55
+ "dueDate": "2026-12-31T00:00:00Z",
56
+ "target": 10500000,
57
+ "statusRulePreset": "higher-is-better"
58
+ },
59
+ {
60
+ "metricName": "Retención %",
61
+ "scorecardEnabled": true,
62
+ "goalName": "Retención %",
63
+ "owner": "clientes@example.com",
64
+ "cadence": "Monthly",
65
+ "startDate": "2026-01-01T00:00:00Z",
66
+ "dueDate": "2026-12-31T00:00:00Z",
67
+ "target": 0.9,
68
+ "statusRulePreset": "higher-is-better"
69
+ },
70
+ {
71
+ "metricName": "Rentabilidad de proyectos",
72
+ "scorecardEnabled": true,
73
+ "goalName": "Rentabilidad de proyectos",
74
+ "owner": "proyectos@example.com",
75
+ "cadence": "Monthly",
76
+ "startDate": "2026-01-01T00:00:00Z",
77
+ "dueDate": "2026-12-31T00:00:00Z",
78
+ "target": 1600000,
79
+ "statusRulePreset": "higher-is-better"
80
+ }
81
+ ]
82
+ }
@@ -0,0 +1,124 @@
1
+ #requires -Version 7.0
2
+
3
+ param(
4
+ [string] $TemplateRoot = 'templates/base-template',
5
+
6
+ [Parameter(Mandatory = $true)]
7
+ [string] $OverlayPath
8
+ )
9
+
10
+ Set-StrictMode -Version Latest
11
+ $ErrorActionPreference = 'Stop'
12
+ # Pin stdout to UTF-8 so the blueprint JSON keeps "Métricas"/"Descripción" intact
13
+ # when Node decodes the pipe as UTF-8, regardless of the host console codepage.
14
+ [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
15
+
16
+ function Read-Overlay {
17
+ param([string] $Path)
18
+ return Get-Content -LiteralPath $Path -Raw | ConvertFrom-Json -Depth 100
19
+ }
20
+
21
+ function Get-MetricsTmdlPath {
22
+ param([string] $Root)
23
+ $path = Join-Path $Root 'base-template.SemanticModel/definition/tables/Métricas.tmdl'
24
+ if (-not (Test-Path -LiteralPath $path)) {
25
+ throw "Métricas.tmdl not found under $Root"
26
+ }
27
+ return $path
28
+ }
29
+
30
+ function Convert-MetricRow {
31
+ param(
32
+ [string] $Row,
33
+ [string[]] $Columns
34
+ )
35
+
36
+ # Assumes the Métricas catalog uses uppercase TRUE/FALSE booleans and no
37
+ # embedded/doubled quotes ("") in text cells; a violating edit throws the
38
+ # "Unexpected ... row shape" error below rather than silently mis-parsing.
39
+ # Use a private name, not the automatic $matches variable (which any later
40
+ # -match would silently overwrite).
41
+ $tokenMatches = [regex]::Matches($Row, '"([^"]*)"|TRUE|FALSE|[-]?\d+(?:\.\d+)?')
42
+ $values = @($tokenMatches | ForEach-Object { $_.Value.Trim('"') })
43
+ if ($values.Count -ne $Columns.Count) {
44
+ throw "Unexpected Métricas DATATABLE row shape: $Row"
45
+ }
46
+
47
+ $rowByColumn = @{}
48
+ for ($i = 0; $i -lt $Columns.Count; $i++) {
49
+ $rowByColumn[$Columns[$i]] = $values[$i]
50
+ }
51
+
52
+ return [ordered]@{
53
+ metricName = $rowByColumn['Métrica']
54
+ format = $rowByColumn['Formato']
55
+ formatType = $rowByColumn['Tipo de formato']
56
+ trendDirection = $rowByColumn['Tendencia']
57
+ description = $rowByColumn['Descripción']
58
+ }
59
+ }
60
+
61
+ function Read-BaseTemplateMetrics {
62
+ param([string] $Path)
63
+
64
+ $content = Get-Content -LiteralPath $Path -Raw
65
+ $table = [regex]::Match(
66
+ $content,
67
+ 'DATATABLE\s*\((?<header>[\s\S]*?),\s*\{(?<rows>[\s\S]*?)\n\s*\}\s*\)\s*$'
68
+ )
69
+ if (-not $table.Success) {
70
+ throw 'Could not locate the Métricas DATATABLE rows.'
71
+ }
72
+
73
+ $columns = @(
74
+ [regex]::Matches($table.Groups['header'].Value, '"([^"]+)"\s*,\s*(?:STRING|INTEGER|BOOLEAN)') |
75
+ ForEach-Object { $_.Groups[1].Value }
76
+ )
77
+ if ($columns.Count -eq 0) {
78
+ throw 'Could not locate the Métricas DATATABLE columns.'
79
+ }
80
+
81
+ $rowOptions = [System.Text.RegularExpressions.RegexOptions]::Singleline
82
+ $rows = [regex]::Matches($table.Groups['rows'].Value, '\{\s*(?<row>[^{}]*?)\s*\}', $rowOptions)
83
+ return @($rows | ForEach-Object { Convert-MetricRow -Row $_.Groups['row'].Value -Columns $columns })
84
+ }
85
+
86
+ $overlay = Read-Overlay -Path $OverlayPath
87
+ $metrics = Read-BaseTemplateMetrics -Path (Get-MetricsTmdlPath -Root $TemplateRoot)
88
+ $metricByName = @{}
89
+ foreach ($metric in $metrics) {
90
+ $metricByName[$metric.metricName] = $metric
91
+ }
92
+
93
+ $goals = @()
94
+ foreach ($goal in $overlay.goals) {
95
+ if (-not $goal.scorecardEnabled) {
96
+ continue
97
+ }
98
+ if (-not $metricByName.ContainsKey($goal.metricName)) {
99
+ throw "Overlay references metric not found in base-template: $($goal.metricName)"
100
+ }
101
+
102
+ $metric = $metricByName[$goal.metricName]
103
+ $goals += [ordered]@{
104
+ metricName = $goal.metricName
105
+ goalName = $goal.goalName
106
+ description = $metric.description
107
+ format = $metric.format
108
+ formatType = $metric.formatType
109
+ trendDirection = $metric.trendDirection
110
+ owner = $goal.owner
111
+ cadence = $goal.cadence
112
+ startDate = $goal.startDate
113
+ dueDate = $goal.dueDate
114
+ target = $goal.target
115
+ statusRulePreset = $goal.statusRulePreset
116
+ }
117
+ }
118
+
119
+ [ordered]@{
120
+ sourceTemplate = 'templates/base-template/base-template.pbip'
121
+ metricsTable = 'Métricas'
122
+ scorecardName = $overlay.scorecardName
123
+ goals = $goals
124
+ } | ConvertTo-Json -Depth 100
@@ -0,0 +1,39 @@
1
+ param(
2
+ [Parameter(Mandatory = $true)]
3
+ [ValidateSet('Get', 'Upsert', 'Delete')]
4
+ [string] $Action,
5
+
6
+ [Parameter(Mandatory = $true)]
7
+ [string] $GroupId,
8
+
9
+ [Parameter(Mandatory = $true)]
10
+ [string] $ScorecardId,
11
+
12
+ [Parameter(Mandatory = $true)]
13
+ [string] $GoalId,
14
+
15
+ [string] $BodyPath,
16
+ [string] $AccessToken,
17
+ [switch] $ConfirmWrite
18
+ )
19
+
20
+ . "$PSScriptRoot/powerbi-rest-common.ps1"
21
+
22
+ $encodedGoalId = ConvertTo-PowerBiPathSegment -Name 'GoalId' -Value $GoalId
23
+ $goalPath = (New-PowerBiScorecardPath -GroupId $GroupId -ScorecardId $ScorecardId -Suffix 'goals') + "($encodedGoalId)"
24
+ $statusRulesPath = "$goalPath/statusRules"
25
+
26
+ switch ($Action) {
27
+ 'Get' {
28
+ Invoke-PowerBiRest -Method GET -Path $statusRulesPath -AccessToken $AccessToken
29
+ }
30
+ 'Upsert' {
31
+ Assert-ConfirmedWrite -Action $Action -ConfirmWrite:$ConfirmWrite
32
+ Assert-RequiredValue -Name 'BodyPath' -Value $BodyPath
33
+ Invoke-PowerBiRest -Method POST -Path $statusRulesPath -Body (Read-JsonObject -Path $BodyPath) -AccessToken $AccessToken
34
+ }
35
+ 'Delete' {
36
+ Assert-ConfirmedWrite -Action $Action -ConfirmWrite:$ConfirmWrite
37
+ Invoke-PowerBiRest -Method DELETE -Path $statusRulesPath -AccessToken $AccessToken
38
+ }
39
+ }
@@ -0,0 +1,48 @@
1
+ param(
2
+ [Parameter(Mandatory = $true)]
3
+ [ValidateSet('List', 'Create', 'Delete')]
4
+ [string] $Action,
5
+
6
+ [Parameter(Mandatory = $true)]
7
+ [string] $GroupId,
8
+
9
+ [Parameter(Mandatory = $true)]
10
+ [string] $ScorecardId,
11
+
12
+ [Parameter(Mandatory = $true)]
13
+ [string] $GoalId,
14
+
15
+ [string] $Timestamp,
16
+ [string] $BodyPath,
17
+ [string] $AccessToken,
18
+ [switch] $ConfirmWrite
19
+ )
20
+
21
+ . "$PSScriptRoot/powerbi-rest-common.ps1"
22
+
23
+ $encodedGoalId = ConvertTo-PowerBiPathSegment -Name 'GoalId' -Value $GoalId
24
+ $goalPath = (New-PowerBiScorecardPath -GroupId $GroupId -ScorecardId $ScorecardId -Suffix 'goals') + "($encodedGoalId)"
25
+ $goalValuesPath = "$goalPath/goalValues"
26
+
27
+ switch ($Action) {
28
+ 'List' {
29
+ Invoke-PowerBiRest -Method GET -Path $goalValuesPath -AccessToken $AccessToken
30
+ }
31
+ 'Create' {
32
+ Assert-ConfirmedWrite -Action $Action -ConfirmWrite:$ConfirmWrite
33
+ Assert-RequiredValue -Name 'BodyPath' -Value $BodyPath
34
+ Invoke-PowerBiRest -Method POST -Path $goalValuesPath -Body (Read-JsonObject -Path $BodyPath) -AccessToken $AccessToken
35
+ }
36
+ 'Delete' {
37
+ Assert-ConfirmedWrite -Action $Action -ConfirmWrite:$ConfirmWrite
38
+ Assert-RequiredValue -Name 'Timestamp' -Value $Timestamp
39
+ # The timestamp is an OData datetime key and appears literally per the
40
+ # Power BI REST reference — goalValues(2021-12-14T00:00:00Z) — so do NOT
41
+ # percent-encode the colons (a strict OData parser rejects %3A). Validate
42
+ # the ISO-8601 instant instead, which also keeps the segment injection-safe.
43
+ if ($Timestamp -notmatch '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$') {
44
+ throw "Timestamp must be an ISO-8601 UTC instant like 2026-01-01T00:00:00Z (got: $Timestamp)"
45
+ }
46
+ Invoke-PowerBiRest -Method DELETE -Path "$goalValuesPath($Timestamp)" -AccessToken $AccessToken
47
+ }
48
+ }
@@ -0,0 +1,68 @@
1
+ param(
2
+ [Parameter(Mandatory = $true)]
3
+ [ValidateSet('List', 'Get', 'Create', 'Update', 'Delete', 'GetRefreshHistory', 'RefreshCurrentValue', 'RefreshTargetValue', 'DeleteCurrentValueConnection', 'DeleteTargetValueConnection')]
4
+ [string] $Action,
5
+
6
+ [Parameter(Mandatory = $true)]
7
+ [string] $GroupId,
8
+
9
+ [Parameter(Mandatory = $true)]
10
+ [string] $ScorecardId,
11
+
12
+ [string] $GoalId,
13
+ [string] $BodyPath,
14
+ [string] $AccessToken,
15
+ [switch] $ConfirmWrite
16
+ )
17
+
18
+ . "$PSScriptRoot/powerbi-rest-common.ps1"
19
+
20
+ $goalsPath = New-PowerBiScorecardPath -GroupId $GroupId -ScorecardId $ScorecardId -Suffix 'goals'
21
+
22
+ function Get-GoalPath {
23
+ Assert-RequiredValue -Name 'GoalId' -Value $GoalId
24
+ $encodedGoalId = ConvertTo-PowerBiPathSegment -Name 'GoalId' -Value $GoalId
25
+ return "$goalsPath($encodedGoalId)"
26
+ }
27
+
28
+ switch ($Action) {
29
+ 'List' {
30
+ Invoke-PowerBiRest -Method GET -Path $goalsPath -AccessToken $AccessToken
31
+ }
32
+ 'Get' {
33
+ Invoke-PowerBiRest -Method GET -Path (Get-GoalPath) -AccessToken $AccessToken
34
+ }
35
+ 'Create' {
36
+ Assert-ConfirmedWrite -Action $Action -ConfirmWrite:$ConfirmWrite
37
+ Assert-RequiredValue -Name 'BodyPath' -Value $BodyPath
38
+ Invoke-PowerBiRest -Method POST -Path $goalsPath -Body (Read-JsonObject -Path $BodyPath) -AccessToken $AccessToken
39
+ }
40
+ 'Update' {
41
+ Assert-ConfirmedWrite -Action $Action -ConfirmWrite:$ConfirmWrite
42
+ Assert-RequiredValue -Name 'BodyPath' -Value $BodyPath
43
+ Invoke-PowerBiRest -Method PATCH -Path (Get-GoalPath) -Body (Read-JsonObject -Path $BodyPath) -AccessToken $AccessToken
44
+ }
45
+ 'Delete' {
46
+ Assert-ConfirmedWrite -Action $Action -ConfirmWrite:$ConfirmWrite
47
+ Invoke-PowerBiRest -Method DELETE -Path (Get-GoalPath) -AccessToken $AccessToken
48
+ }
49
+ 'GetRefreshHistory' {
50
+ Invoke-PowerBiRest -Method GET -Path "$(Get-GoalPath)/GetRefreshHistory()" -AccessToken $AccessToken
51
+ }
52
+ 'RefreshCurrentValue' {
53
+ Assert-ConfirmedWrite -Action $Action -ConfirmWrite:$ConfirmWrite
54
+ Invoke-PowerBiRest -Method POST -Path "$(Get-GoalPath)/RefreshGoalCurrentValue()" -AccessToken $AccessToken
55
+ }
56
+ 'RefreshTargetValue' {
57
+ Assert-ConfirmedWrite -Action $Action -ConfirmWrite:$ConfirmWrite
58
+ Invoke-PowerBiRest -Method POST -Path "$(Get-GoalPath)/RefreshGoalTargetValue()" -AccessToken $AccessToken
59
+ }
60
+ 'DeleteCurrentValueConnection' {
61
+ Assert-ConfirmedWrite -Action $Action -ConfirmWrite:$ConfirmWrite
62
+ Invoke-PowerBiRest -Method POST -Path "$(Get-GoalPath)/DeleteGoalCurrentValueConnection()" -AccessToken $AccessToken
63
+ }
64
+ 'DeleteTargetValueConnection' {
65
+ Assert-ConfirmedWrite -Action $Action -ConfirmWrite:$ConfirmWrite
66
+ Invoke-PowerBiRest -Method POST -Path "$(Get-GoalPath)/DeleteGoalTargetValueConnection()" -AccessToken $AccessToken
67
+ }
68
+ }