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,441 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lint Command (checkup)
|
|
3
|
+
* ======================
|
|
4
|
+
* Validates skill files for proper structure and format.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* super checkup Lint all skills
|
|
8
|
+
* super checkup dax.md Lint specific skill
|
|
9
|
+
* super checkup --fix Auto-fix issues (where possible)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const tui = require('../utils/tui');
|
|
15
|
+
const { readSkillDirectory, normalizeSkillName } = require('../lib/skills');
|
|
16
|
+
|
|
17
|
+
// Lint rules configuration
|
|
18
|
+
const RULES = {
|
|
19
|
+
// Required sections
|
|
20
|
+
requiredSections: {
|
|
21
|
+
enabled: true,
|
|
22
|
+
severity: 'error',
|
|
23
|
+
sections: ['Trigger', 'Identity', 'MANDATORY RULES'],
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
// Trigger section validation
|
|
27
|
+
triggerFormat: {
|
|
28
|
+
enabled: true,
|
|
29
|
+
severity: 'warning',
|
|
30
|
+
description: 'Trigger section should have bullet points with quoted phrases',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
// Title validation
|
|
34
|
+
hasTitle: {
|
|
35
|
+
enabled: true,
|
|
36
|
+
severity: 'error',
|
|
37
|
+
description: 'Skill must have an H1 title',
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
// Code block validation
|
|
41
|
+
codeBlocks: {
|
|
42
|
+
enabled: true,
|
|
43
|
+
severity: 'warning',
|
|
44
|
+
description: 'Code blocks should have language specified',
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
// Link validation
|
|
48
|
+
brokenLinks: {
|
|
49
|
+
enabled: true,
|
|
50
|
+
severity: 'warning',
|
|
51
|
+
description: 'Internal links should point to existing files',
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// Maximum file size
|
|
55
|
+
maxSize: {
|
|
56
|
+
enabled: true,
|
|
57
|
+
severity: 'warning',
|
|
58
|
+
maxBytes: 50000, // 50KB
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
// Naming convention. Folder-based skills follow Anthropic's convention
|
|
62
|
+
// of `<folder>/SKILL.md` (uppercase), so allow that literal too.
|
|
63
|
+
naming: {
|
|
64
|
+
enabled: true,
|
|
65
|
+
severity: 'error',
|
|
66
|
+
pattern: /^([a-z0-9-]+\.md|SKILL\.md)$/,
|
|
67
|
+
description: 'Skill files should be lowercase-kebab-case.md, or SKILL.md inside a skill folder',
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Lint a single skill file
|
|
73
|
+
* @param {string} filePath - Path to skill file
|
|
74
|
+
* @returns {Object} Lint result with errors and warnings
|
|
75
|
+
*/
|
|
76
|
+
function lintFile(filePath) {
|
|
77
|
+
const result = {
|
|
78
|
+
file: path.basename(filePath),
|
|
79
|
+
path: filePath,
|
|
80
|
+
errors: [],
|
|
81
|
+
warnings: [],
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
let content;
|
|
85
|
+
try {
|
|
86
|
+
content = fs.readFileSync(filePath, 'utf8');
|
|
87
|
+
} catch (e) {
|
|
88
|
+
result.errors.push({ rule: 'file-read', message: `Cannot read file: ${e.message}` });
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const lines = content.split('\n');
|
|
93
|
+
const filename = path.basename(filePath);
|
|
94
|
+
|
|
95
|
+
// Rule: File naming convention
|
|
96
|
+
if (RULES.naming.enabled && !RULES.naming.pattern.test(filename)) {
|
|
97
|
+
addIssue(
|
|
98
|
+
result,
|
|
99
|
+
'naming',
|
|
100
|
+
RULES.naming.severity,
|
|
101
|
+
`File name "${filename}" should be lowercase-kebab-case.md`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Rule: Max file size
|
|
106
|
+
if (RULES.maxSize.enabled) {
|
|
107
|
+
const stats = fs.statSync(filePath);
|
|
108
|
+
if (stats.size > RULES.maxSize.maxBytes) {
|
|
109
|
+
addIssue(
|
|
110
|
+
result,
|
|
111
|
+
'maxSize',
|
|
112
|
+
RULES.maxSize.severity,
|
|
113
|
+
`File size (${(stats.size / 1024).toFixed(1)}KB) exceeds ${RULES.maxSize.maxBytes / 1024}KB limit`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Rule: Has H1 title
|
|
119
|
+
if (RULES.hasTitle.enabled) {
|
|
120
|
+
const hasH1 = lines.some((line) => /^#\s+.+/.test(line));
|
|
121
|
+
if (!hasH1) {
|
|
122
|
+
addIssue(
|
|
123
|
+
result,
|
|
124
|
+
'hasTitle',
|
|
125
|
+
RULES.hasTitle.severity,
|
|
126
|
+
'Missing H1 title (should start with "# Title")'
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Rule: Required sections
|
|
132
|
+
if (RULES.requiredSections.enabled) {
|
|
133
|
+
RULES.requiredSections.sections.forEach((section) => {
|
|
134
|
+
const sectionPattern = new RegExp(`^##\\s+${section}`, 'mi');
|
|
135
|
+
if (!sectionPattern.test(content)) {
|
|
136
|
+
addIssue(
|
|
137
|
+
result,
|
|
138
|
+
'requiredSections',
|
|
139
|
+
RULES.requiredSections.severity,
|
|
140
|
+
`Missing required section: "## ${section}"`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Rule: Trigger format validation
|
|
147
|
+
if (RULES.triggerFormat.enabled) {
|
|
148
|
+
const triggerSection = extractSection(content, 'Trigger');
|
|
149
|
+
if (triggerSection) {
|
|
150
|
+
const hasBullets = /[-*]\s+["'].+["']/.test(triggerSection);
|
|
151
|
+
if (!hasBullets) {
|
|
152
|
+
const lineNum = findSectionLine(lines, 'Trigger');
|
|
153
|
+
addIssue(
|
|
154
|
+
result,
|
|
155
|
+
'triggerFormat',
|
|
156
|
+
RULES.triggerFormat.severity,
|
|
157
|
+
'Trigger section should have bullet points with quoted phrases (e.g., - "keyword")',
|
|
158
|
+
lineNum
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Rule: Code blocks should have language
|
|
165
|
+
if (RULES.codeBlocks.enabled) {
|
|
166
|
+
// Track fence open/close state so we only flag OPENING fences that lack a
|
|
167
|
+
// language specifier. Closing fences are always bare ``` and must never be
|
|
168
|
+
// flagged (the previous next-line heuristic mis-flagged every closing fence).
|
|
169
|
+
let inFence = false;
|
|
170
|
+
lines.forEach((line, index) => {
|
|
171
|
+
const trimmed = line.trim();
|
|
172
|
+
if (!trimmed.startsWith('```')) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (inFence) {
|
|
176
|
+
inFence = false; // closing fence — carries no language by definition
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
inFence = true; // opening fence
|
|
180
|
+
if (trimmed === '```') {
|
|
181
|
+
addIssue(
|
|
182
|
+
result,
|
|
183
|
+
'codeBlocks',
|
|
184
|
+
RULES.codeBlocks.severity,
|
|
185
|
+
'Code block missing language specifier (e.g., ```dax)',
|
|
186
|
+
index + 1
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Rule: Check internal links
|
|
193
|
+
if (RULES.brokenLinks.enabled) {
|
|
194
|
+
const linkPattern = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
195
|
+
let match;
|
|
196
|
+
while ((match = linkPattern.exec(content)) !== null) {
|
|
197
|
+
const linkPath = match[2];
|
|
198
|
+
// Only check relative markdown links
|
|
199
|
+
if (linkPath.endsWith('.md') && !linkPath.startsWith('http')) {
|
|
200
|
+
const resolvedPath = path.resolve(path.dirname(filePath), linkPath);
|
|
201
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
202
|
+
const lineNum = findLineWithText(lines, match[0]);
|
|
203
|
+
addIssue(
|
|
204
|
+
result,
|
|
205
|
+
'brokenLinks',
|
|
206
|
+
RULES.brokenLinks.severity,
|
|
207
|
+
`Broken internal link: ${linkPath}`,
|
|
208
|
+
lineNum
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return result;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Add an issue to the result
|
|
220
|
+
* @param {Object} result - Result object
|
|
221
|
+
* @param {string} rule - Rule name
|
|
222
|
+
* @param {string} severity - 'error' or 'warning'
|
|
223
|
+
* @param {string} message - Issue message
|
|
224
|
+
* @param {number} [line] - Line number
|
|
225
|
+
*/
|
|
226
|
+
function addIssue(result, rule, severity, message, line) {
|
|
227
|
+
const issue = { rule, message };
|
|
228
|
+
if (line) issue.line = line;
|
|
229
|
+
|
|
230
|
+
if (severity === 'error') {
|
|
231
|
+
result.errors.push(issue);
|
|
232
|
+
} else {
|
|
233
|
+
result.warnings.push(issue);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Extract a section from markdown content
|
|
239
|
+
* @param {string} content - Markdown content
|
|
240
|
+
* @param {string} sectionName - Section name (without ##)
|
|
241
|
+
* @returns {string|null} Section content or null
|
|
242
|
+
*/
|
|
243
|
+
function extractSection(content, sectionName) {
|
|
244
|
+
// Locate the section heading first, then slice from there to the next
|
|
245
|
+
// H2 heading or horizontal rule. The earlier regex used a multiline
|
|
246
|
+
// `$` as a stop anchor, which matches end of LINE — so it returned
|
|
247
|
+
// only the heading line and dropped the body, breaking downstream
|
|
248
|
+
// rules like triggerFormat that inspect the body.
|
|
249
|
+
const headingMatch = new RegExp(`^##\\s+${sectionName}\\b`, 'mi').exec(content);
|
|
250
|
+
if (!headingMatch) return null;
|
|
251
|
+
const tail = content.slice(headingMatch.index);
|
|
252
|
+
const next = tail.search(/\n##\s+|\n---+\s*\n/);
|
|
253
|
+
return next === -1 ? tail : tail.slice(0, next);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Find line number of a section
|
|
258
|
+
* @param {string[]} lines - Array of lines
|
|
259
|
+
* @param {string} sectionName - Section name
|
|
260
|
+
* @returns {number|null} Line number or null
|
|
261
|
+
*/
|
|
262
|
+
function findSectionLine(lines, sectionName) {
|
|
263
|
+
for (let i = 0; i < lines.length; i++) {
|
|
264
|
+
if (new RegExp(`^##\\s+${sectionName}`, 'i').test(lines[i])) {
|
|
265
|
+
return i + 1;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Find line number containing text
|
|
273
|
+
* @param {string[]} lines - Array of lines
|
|
274
|
+
* @param {string} text - Text to find
|
|
275
|
+
* @returns {number|null} Line number or null
|
|
276
|
+
*/
|
|
277
|
+
function findLineWithText(lines, text) {
|
|
278
|
+
for (let i = 0; i < lines.length; i++) {
|
|
279
|
+
if (lines[i].includes(text)) {
|
|
280
|
+
return i + 1;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Parse command line arguments
|
|
288
|
+
* @param {string[]} args - CLI arguments
|
|
289
|
+
* @returns {Object} Parsed options
|
|
290
|
+
*/
|
|
291
|
+
function parseArgs(args) {
|
|
292
|
+
const options = {
|
|
293
|
+
files: [],
|
|
294
|
+
fix: false,
|
|
295
|
+
json: false,
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
for (let i = 0; i < args.length; i++) {
|
|
299
|
+
const arg = args[i];
|
|
300
|
+
|
|
301
|
+
if (arg === '--fix') {
|
|
302
|
+
options.fix = true;
|
|
303
|
+
} else if (arg === '--json') {
|
|
304
|
+
options.json = true;
|
|
305
|
+
} else if (!arg.startsWith('-')) {
|
|
306
|
+
options.files.push(arg);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return options;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Display lint summary
|
|
315
|
+
* @param {Object[]} results - Array of lint results
|
|
316
|
+
*/
|
|
317
|
+
function displaySummary(results) {
|
|
318
|
+
const totalErrors = results.reduce((sum, r) => sum + r.errors.length, 0);
|
|
319
|
+
const totalWarnings = results.reduce((sum, r) => sum + r.warnings.length, 0);
|
|
320
|
+
const filesWithIssues = results.filter(
|
|
321
|
+
(r) => r.errors.length > 0 || r.warnings.length > 0
|
|
322
|
+
).length;
|
|
323
|
+
|
|
324
|
+
console.log('');
|
|
325
|
+
tui.section('Summary');
|
|
326
|
+
|
|
327
|
+
const table = tui.createTable(
|
|
328
|
+
['Metric', 'Count'],
|
|
329
|
+
[
|
|
330
|
+
['Files checked', results.length.toString()],
|
|
331
|
+
['Files with issues', filesWithIssues.toString()],
|
|
332
|
+
['Errors', tui.colors.error(totalErrors.toString())],
|
|
333
|
+
['Warnings', tui.colors.warning(totalWarnings.toString())],
|
|
334
|
+
]
|
|
335
|
+
);
|
|
336
|
+
console.log(table);
|
|
337
|
+
|
|
338
|
+
if (totalErrors > 0) {
|
|
339
|
+
console.log(`\n${tui.icons.error} ${tui.colors.error(`${totalErrors} error(s) found`)}`);
|
|
340
|
+
} else if (totalWarnings > 0) {
|
|
341
|
+
console.log(
|
|
342
|
+
`\n${tui.icons.warning} ${tui.colors.warning(`${totalWarnings} warning(s) found`)}`
|
|
343
|
+
);
|
|
344
|
+
} else {
|
|
345
|
+
console.log(`\n${tui.icons.success} ${tui.colors.success('All skills passed validation!')}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Main lint command handler
|
|
351
|
+
* @param {string[]} args - Command arguments
|
|
352
|
+
* @param {Object} config - CLI configuration with paths
|
|
353
|
+
*/
|
|
354
|
+
function lintCommand(args, config) {
|
|
355
|
+
const options = parseArgs(args);
|
|
356
|
+
|
|
357
|
+
// Try cache directory first, fall back to local skills
|
|
358
|
+
let skillsDir = config.skillsDir;
|
|
359
|
+
const localSkills = path.join(config.packageDir, '.agents', 'prompts', 'skills');
|
|
360
|
+
|
|
361
|
+
if (!fs.existsSync(skillsDir)) {
|
|
362
|
+
if (fs.existsSync(localSkills)) {
|
|
363
|
+
skillsDir = localSkills;
|
|
364
|
+
} else {
|
|
365
|
+
tui.error('Skills directory not found. Try reinstalling: npm install -g bi-superpowers');
|
|
366
|
+
process.exit(1);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
tui.header('BI Agent Superpowers', 'Skill Linter');
|
|
371
|
+
|
|
372
|
+
// Determine which files to lint. Use the shared skill loader so we
|
|
373
|
+
// catch both flat (`<name>.md`) and folder-based (`<name>/SKILL.md`)
|
|
374
|
+
// skills — a previous version filtered with `f.endsWith('.md')` and
|
|
375
|
+
// silently skipped every folder-based skill.
|
|
376
|
+
const allSkills = readSkillDirectory(skillsDir);
|
|
377
|
+
const skillsByName = new Map(allSkills.map((s) => [s.name, s]));
|
|
378
|
+
let filesToLint = [];
|
|
379
|
+
|
|
380
|
+
if (options.files.length > 0) {
|
|
381
|
+
filesToLint = options.files
|
|
382
|
+
.map((f) => {
|
|
383
|
+
// Existing absolute / relative file path the user passed verbatim.
|
|
384
|
+
if (fs.existsSync(f) && fs.statSync(f).isFile()) {
|
|
385
|
+
return f;
|
|
386
|
+
}
|
|
387
|
+
// Look up by skill name. normalizeSkillName accepts `dax`,
|
|
388
|
+
// `dax.md`, `folder-skill`, or `folder-skill/SKILL.md`.
|
|
389
|
+
const skill = skillsByName.get(normalizeSkillName(f));
|
|
390
|
+
if (skill) return skill.path;
|
|
391
|
+
|
|
392
|
+
tui.warning(`Skill not found: ${f}`);
|
|
393
|
+
return null;
|
|
394
|
+
})
|
|
395
|
+
.filter(Boolean);
|
|
396
|
+
} else {
|
|
397
|
+
filesToLint = allSkills.map((s) => s.path);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (filesToLint.length === 0) {
|
|
401
|
+
tui.warning('No skill files found to lint');
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
tui.info(`Linting ${filesToLint.length} skill file(s)...`);
|
|
406
|
+
console.log('');
|
|
407
|
+
|
|
408
|
+
// Run linting
|
|
409
|
+
const results = filesToLint.map((file) => lintFile(file));
|
|
410
|
+
|
|
411
|
+
// Output results
|
|
412
|
+
if (options.json) {
|
|
413
|
+
console.log(JSON.stringify(results, null, 2));
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Display individual results
|
|
418
|
+
results.forEach((result) => {
|
|
419
|
+
tui.lintResult(result);
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
// Display summary
|
|
423
|
+
displaySummary(results);
|
|
424
|
+
|
|
425
|
+
// Exit with error code if there are errors
|
|
426
|
+
const hasErrors = results.some((r) => r.errors.length > 0);
|
|
427
|
+
if (hasErrors) {
|
|
428
|
+
process.exit(1);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Expose primitives for tests (B3 — replace fake tests with real ones).
|
|
433
|
+
module.exports = Object.assign(lintCommand, {
|
|
434
|
+
lintFile,
|
|
435
|
+
parseArgs,
|
|
436
|
+
extractSection,
|
|
437
|
+
findSectionLine,
|
|
438
|
+
findLineWithText,
|
|
439
|
+
addIssue,
|
|
440
|
+
RULES,
|
|
441
|
+
});
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Setup Command
|
|
3
|
+
* =================
|
|
4
|
+
* Configures the official Microsoft MCP servers for an existing project-local
|
|
5
|
+
* BI Superpowers plugin. Normal multi-agent setup is user-level via
|
|
6
|
+
* `super install --all --yes`; this command refuses arbitrary repo-local writes.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* super mcp-setup
|
|
10
|
+
* super mcp-setup --tool claude-plugin
|
|
11
|
+
* super mcp-setup --dry-run
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const tui = require('../utils/tui');
|
|
17
|
+
const mcpDetect = require('../utils/mcp-detect');
|
|
18
|
+
const {
|
|
19
|
+
ABSOLUTE_LAUNCHER_MODE,
|
|
20
|
+
PLUGIN_ROOT_LAUNCHER_MODE,
|
|
21
|
+
createMcpConfigForFormat,
|
|
22
|
+
mergeMcpConfig,
|
|
23
|
+
} = require('../lib/microsoft-mcp');
|
|
24
|
+
const { readJsonStrict, readJsoncStrict, writeJson } = require('../lib/mcp-config');
|
|
25
|
+
|
|
26
|
+
const MCP_CONFIGS = {
|
|
27
|
+
'claude-plugin': {
|
|
28
|
+
name: 'Claude Code Plugin',
|
|
29
|
+
configPath: '.mcp.json',
|
|
30
|
+
format: 'plugin',
|
|
31
|
+
},
|
|
32
|
+
'claude-code': {
|
|
33
|
+
name: 'Claude Code (legacy standalone)',
|
|
34
|
+
configPath: '.claude/settings.json',
|
|
35
|
+
format: 'claude',
|
|
36
|
+
},
|
|
37
|
+
cursor: {
|
|
38
|
+
name: 'Cursor (legacy)',
|
|
39
|
+
configPath: '.cursor/mcp.json',
|
|
40
|
+
format: 'cursor',
|
|
41
|
+
},
|
|
42
|
+
kilocode: {
|
|
43
|
+
name: 'Kilo Code (legacy)',
|
|
44
|
+
configPath: '.kilo/kilo.jsonc',
|
|
45
|
+
format: 'kilo',
|
|
46
|
+
},
|
|
47
|
+
'open-code': {
|
|
48
|
+
name: 'OpenCode (legacy)',
|
|
49
|
+
configPath: 'opencode.config.json',
|
|
50
|
+
format: 'opencode',
|
|
51
|
+
},
|
|
52
|
+
vscode: {
|
|
53
|
+
name: 'VS Code (legacy)',
|
|
54
|
+
configPath: '.vscode/settings.json',
|
|
55
|
+
format: 'vscode',
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
function parseArgs(args) {
|
|
60
|
+
const options = {
|
|
61
|
+
tool: null,
|
|
62
|
+
dryRun: false,
|
|
63
|
+
targetDir: process.cwd(),
|
|
64
|
+
deprecatedFlags: [],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
for (let index = 0; index < args.length; index++) {
|
|
68
|
+
const arg = args[index];
|
|
69
|
+
|
|
70
|
+
if (arg === '--tool' || arg === '-t') {
|
|
71
|
+
options.tool = args[++index];
|
|
72
|
+
} else if (arg === '--dry-run') {
|
|
73
|
+
options.dryRun = true;
|
|
74
|
+
} else if (arg === '--port' || arg === '-p' || arg === '--github' || arg === '-g') {
|
|
75
|
+
options.deprecatedFlags.push(arg);
|
|
76
|
+
if (args[index + 1] && !args[index + 1].startsWith('-')) {
|
|
77
|
+
index++;
|
|
78
|
+
}
|
|
79
|
+
} else if (!arg.startsWith('-')) {
|
|
80
|
+
options.targetDir = arg;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return options;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function loadConfiguredTools(targetDir) {
|
|
88
|
+
const configPath = path.join(targetDir, '.bi-superpowers.json');
|
|
89
|
+
if (fs.existsSync(configPath)) {
|
|
90
|
+
try {
|
|
91
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
92
|
+
if (Array.isArray(config.tools) && config.tools.length > 0) {
|
|
93
|
+
return Array.from(new Set(config.tools));
|
|
94
|
+
}
|
|
95
|
+
} catch (error) {
|
|
96
|
+
// Ignore invalid config and fall back below.
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const pluginManifest = path.join(targetDir, '.claude-plugin', 'plugin.json');
|
|
101
|
+
if (fs.existsSync(pluginManifest)) {
|
|
102
|
+
return ['claude-plugin'];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return ['claude-plugin'];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function hasLocalPluginMarker(targetDir) {
|
|
109
|
+
return (
|
|
110
|
+
fs.existsSync(path.join(targetDir, '.bi-superpowers.json')) ||
|
|
111
|
+
fs.existsSync(path.join(targetDir, '.claude-plugin', 'plugin.json'))
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function writeConfig(filePath, config, dryRun) {
|
|
116
|
+
if (dryRun) {
|
|
117
|
+
tui.info(`Would write: ${tui.formatPath(filePath)}`);
|
|
118
|
+
tui.muted(JSON.stringify(config, null, 2).slice(0, 220) + '...');
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
writeJson(filePath, config);
|
|
124
|
+
return true;
|
|
125
|
+
} catch (error) {
|
|
126
|
+
tui.error(`Failed to write ${filePath}: ${error.message}`);
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function getLauncherMode(targetDir, packageDir, tool) {
|
|
132
|
+
if (tool === 'claude-plugin' && path.resolve(targetDir) === path.resolve(packageDir)) {
|
|
133
|
+
return PLUGIN_ROOT_LAUNCHER_MODE;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return ABSOLUTE_LAUNCHER_MODE;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function mcpSetupCommand(args, config) {
|
|
140
|
+
const options = parseArgs(args);
|
|
141
|
+
const targetDir = path.resolve(options.targetDir);
|
|
142
|
+
|
|
143
|
+
tui.header('BI Agent Superpowers', 'Microsoft MCP Setup');
|
|
144
|
+
|
|
145
|
+
if (options.dryRun) {
|
|
146
|
+
tui.dryRunNotice();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (options.deprecatedFlags.length > 0) {
|
|
150
|
+
tui.warning(
|
|
151
|
+
`Deprecated flags ignored: ${options.deprecatedFlags.join(', ')}. MCP setup now targets local Claude Code plugin configs and uses the official Microsoft servers.`
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (options.tool && !MCP_CONFIGS[options.tool]) {
|
|
156
|
+
tui.error(`Unknown tool: ${options.tool}`);
|
|
157
|
+
tui.info(`Available tools: ${Object.keys(MCP_CONFIGS).join(', ')}`);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!hasLocalPluginMarker(targetDir)) {
|
|
162
|
+
tui.warning('mcp-setup is only for existing project-local BI Superpowers plugin configs.');
|
|
163
|
+
tui.info(
|
|
164
|
+
'For Codex, GitHub Copilot, Gemini CLI, Kilo Code, and Claude Code user-level installs, run:'
|
|
165
|
+
);
|
|
166
|
+
tui.listItem('super install --all --yes');
|
|
167
|
+
tui.info(
|
|
168
|
+
'That writes user-level skills and MCP config under your home directory without creating files in this repo.'
|
|
169
|
+
);
|
|
170
|
+
tui.info(
|
|
171
|
+
'If you intentionally need local Claude Code plugin files, run `super kickoff` first, then rerun `super mcp-setup` inside that initialized repo.'
|
|
172
|
+
);
|
|
173
|
+
process.exitCode = 2;
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
let configuredTools = loadConfiguredTools(targetDir);
|
|
178
|
+
|
|
179
|
+
if (options.tool) {
|
|
180
|
+
configuredTools = [options.tool];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
tui.section('Configured Outputs');
|
|
184
|
+
configuredTools.forEach((tool) => {
|
|
185
|
+
tui.success(MCP_CONFIGS[tool].name);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const status = mcpDetect.getMcpStatus();
|
|
189
|
+
|
|
190
|
+
tui.section('Official Microsoft MCP Status');
|
|
191
|
+
if (status.local.installed) {
|
|
192
|
+
tui.success(`Power BI Modeling MCP detected: ${status.local.path}`);
|
|
193
|
+
if (status.local.version) {
|
|
194
|
+
tui.info(`Version: ${status.local.version}`);
|
|
195
|
+
}
|
|
196
|
+
} else {
|
|
197
|
+
tui.warning('Power BI Modeling MCP not detected locally.');
|
|
198
|
+
tui.info(mcpDetect.getModelingMcpError());
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
tui.success('Microsoft Learn MCP: https://learn.microsoft.com/api/mcp');
|
|
202
|
+
|
|
203
|
+
const results = {
|
|
204
|
+
success: [],
|
|
205
|
+
failed: [],
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
tui.section('Writing Configurations');
|
|
209
|
+
configuredTools.forEach((tool) => {
|
|
210
|
+
const toolConfig = MCP_CONFIGS[tool];
|
|
211
|
+
const filePath = path.join(targetDir, toolConfig.configPath);
|
|
212
|
+
let ok = false;
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
const existingConfig =
|
|
216
|
+
toolConfig.format === 'kilo'
|
|
217
|
+
? readJsoncStrict(filePath) || {}
|
|
218
|
+
: readJsonStrict(filePath) || {};
|
|
219
|
+
const generatedConfig = createMcpConfigForFormat(toolConfig.format, {
|
|
220
|
+
packageDir: config.packageDir,
|
|
221
|
+
launcherMode: getLauncherMode(targetDir, config.packageDir, tool),
|
|
222
|
+
});
|
|
223
|
+
const mergedConfig = mergeMcpConfig(existingConfig, generatedConfig, toolConfig.format);
|
|
224
|
+
ok = writeConfig(filePath, mergedConfig, options.dryRun);
|
|
225
|
+
} catch (error) {
|
|
226
|
+
tui.error(`Failed to prepare ${filePath}: ${error.message}`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (ok) {
|
|
230
|
+
results.success.push(toolConfig.name);
|
|
231
|
+
tui.success(`${toolConfig.name}: ${tui.formatPath(toolConfig.configPath)}`);
|
|
232
|
+
} else {
|
|
233
|
+
results.failed.push(toolConfig.name);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
console.log('');
|
|
238
|
+
tui.section('Next Steps');
|
|
239
|
+
tui.listItem(
|
|
240
|
+
'Install the official Microsoft Power BI Modeling MCP extension in VS Code/Cursor on Windows if you need write access to Desktop/PBIP semantic models.'
|
|
241
|
+
);
|
|
242
|
+
tui.listItem('Refresh or restart your MCP client after config changes.');
|
|
243
|
+
|
|
244
|
+
if (configuredTools.includes('claude-plugin')) {
|
|
245
|
+
tui.listItem(`Run Claude Code with the plugin: claude --plugin-dir ${targetDir}`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (results.failed.length > 0) {
|
|
249
|
+
console.log('');
|
|
250
|
+
tui.warning(`Completed with failures: ${results.failed.join(', ')}`);
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
module.exports = mcpSetupCommand;
|