@luquimbo/bi-superpowers 4.1.1 → 4.1.3

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 (42) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.claude-plugin/skill-manifest.json +1 -1
  4. package/.plugin/plugin.json +1 -1
  5. package/AGENTS.md +4 -5
  6. package/CHANGELOG.md +24 -0
  7. package/README.md +633 -93
  8. package/bin/cli.js +52 -54
  9. package/bin/commands/build-desktop.js +60 -6
  10. package/bin/commands/diff.js +86 -1
  11. package/bin/commands/watch.js +50 -5
  12. package/bin/lib/generators/claude-plugin.js +1 -1
  13. package/bin/postinstall.js +1 -1
  14. package/commands/bi-start.md +2 -2
  15. package/commands/pbi-connect.md +1 -1
  16. package/commands/project-kickoff.md +5 -5
  17. package/commands/report-design.md +8 -8
  18. package/desktop-extension/server.js +43 -10
  19. package/package.json +5 -5
  20. package/skills/bi-start/SKILL.md +3 -3
  21. package/skills/bi-start/scripts/update-check.js +1 -1
  22. package/skills/pbi-connect/SKILL.md +2 -2
  23. package/skills/pbi-connect/scripts/update-check.js +1 -1
  24. package/skills/project-kickoff/SKILL.md +6 -6
  25. package/skills/project-kickoff/scripts/update-check.js +1 -1
  26. package/skills/report-design/SKILL.md +9 -9
  27. package/skills/report-design/references/layouts/finance.md +2 -2
  28. package/skills/report-design/references/native-visuals.md +2 -2
  29. package/skills/report-design/references/slicer.md +1 -1
  30. package/skills/report-design/references/textbox.md +1 -1
  31. package/skills/report-design/scripts/create-visual.js +65 -1
  32. package/skills/report-design/scripts/update-check.js +1 -1
  33. package/skills/report-design/scripts/validate-pbir.js +29 -0
  34. package/src/content/skills/bi-start.md +2 -2
  35. package/src/content/skills/project-kickoff.md +4 -4
  36. package/src/content/skills/report-design/SKILL.md +7 -7
  37. package/src/content/skills/report-design/references/layouts/finance.md +2 -2
  38. package/src/content/skills/report-design/references/native-visuals.md +2 -2
  39. package/src/content/skills/report-design/references/slicer.md +1 -1
  40. package/src/content/skills/report-design/references/textbox.md +1 -1
  41. package/src/content/skills/report-design/scripts/create-visual.js +65 -1
  42. package/src/content/skills/report-design/scripts/validate-pbir.js +29 -0
@@ -25,25 +25,58 @@ const server = new McpServer({
25
25
  version: '0.0.0-template',
26
26
  });
27
27
 
28
- // Load all skill markdown files from the bundled skills/ directory.
29
- const skillFiles = fs.existsSync(skillsDir)
30
- ? fs.readdirSync(skillsDir).filter((f) => f.endsWith('.md'))
31
- : [];
28
+ function loadBundledSkills(directory) {
29
+ if (!fs.existsSync(directory)) {
30
+ return [];
31
+ }
32
+
33
+ const skills = [];
34
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
35
+ const entryPath = path.join(directory, entry.name);
36
+
37
+ if (entry.isFile() && entry.name.endsWith('.md')) {
38
+ skills.push({
39
+ name: path.basename(entry.name, '.md'),
40
+ bundleDir: directory,
41
+ content: fs.readFileSync(entryPath, 'utf8'),
42
+ });
43
+ continue;
44
+ }
45
+
46
+ if (entry.isDirectory()) {
47
+ const skillPath = path.join(entryPath, 'SKILL.md');
48
+ if (fs.existsSync(skillPath)) {
49
+ skills.push({
50
+ name: entry.name,
51
+ bundleDir: entryPath,
52
+ content: fs.readFileSync(skillPath, 'utf8'),
53
+ });
54
+ }
55
+ }
56
+ }
57
+
58
+ return skills.sort((a, b) => a.name.localeCompare(b.name));
59
+ }
32
60
 
33
61
  // Register each skill as an MCP prompt that Claude Desktop can invoke.
34
- for (const file of skillFiles) {
35
- const name = path.basename(file, '.md');
36
- const content = fs.readFileSync(path.join(skillsDir, file), 'utf8');
62
+ for (const skill of loadBundledSkills(skillsDir)) {
63
+ const { name, bundleDir, content } = skill;
37
64
 
38
65
  // Use the first non-header line as a short description for the prompt.
39
66
  const firstLine = content.split('\n').find((l) => l.trim() && !l.startsWith('#'));
40
67
  const description = firstLine ? firstLine.slice(0, 120).trim() : `BI Superpowers: ${name}`;
68
+ const promptText = [
69
+ `Bundled skill directory: ${bundleDir}`,
70
+ 'Resolve this skill\'s references/ and scripts/ paths relative to that directory.',
71
+ '',
72
+ content,
73
+ ].join('\n');
41
74
 
42
75
  server.prompt(name, { description }, () => ({
43
76
  messages: [
44
77
  {
45
78
  role: 'user',
46
- content: { type: 'text', text: content },
79
+ content: { type: 'text', text: promptText },
47
80
  },
48
81
  ],
49
82
  }));
@@ -73,7 +106,7 @@ into Claude Desktop, add the following to your \`claude_desktop_config.json\`
73
106
  \`\`\`json
74
107
  {
75
108
  "mcpServers": {
76
- "powerbi-modeling": {
109
+ "powerbi-modeling-mcp": {
77
110
  "command": "node",
78
111
  "args": ["<absolute path to powerbi-modeling-launcher.js>"]
79
112
  },
@@ -85,7 +118,7 @@ into Claude Desktop, add the following to your \`claude_desktop_config.json\`
85
118
  }
86
119
  \`\`\`
87
120
 
88
- The \`powerbi-modeling\` server requires Power BI Desktop on Windows
121
+ The \`powerbi-modeling-mcp\` server requires Power BI Desktop on Windows
89
122
  with a model open. If you prefer automated setup, run
90
123
  \`super install\` from the bi-superpowers CLI — it configures both
91
124
  servers across all 5 supported AI agents.
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@luquimbo/bi-superpowers",
3
- "version": "4.1.1",
3
+ "version": "4.1.3",
4
4
  "description": "Open-source Power BI Desktop toolkit for Claude Code, GitHub Copilot, Codex, Gemini CLI, and Kilo Code. Ships 4 skills and 2 official Microsoft MCP servers.",
5
5
  "main": "bin/cli.js",
6
6
  "bin": {
7
- "bi-superpowers": "bin/cli.js"
7
+ "bi-superpowers": "bin/cli.js",
8
+ "super": "bin/cli.js"
8
9
  },
9
10
  "scripts": {
10
11
  "build:plugin": "node bin/build-plugin.js",
@@ -23,10 +24,9 @@
23
24
  "adm-zip": "^0.5.17",
24
25
  "boxen": "^5.1.2",
25
26
  "chalk": "^4.1.2",
26
- "chokidar": "^3.6.0",
27
+ "chokidar": "^4.0.3",
27
28
  "cli-table3": "^0.6.5",
28
- "ora": "^5.4.1",
29
- "update-notifier": "^5.1.0"
29
+ "ora": "^5.4.1"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@eslint/js": "^9.39.2",
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: "bi-start"
3
3
  description: "Use when the user asks about BI Start Skill, especially phrases like \"bi-start\", \"bi start\", \"/bi-start\", \"empezar\", \"comenzar\", \"arranco\"."
4
- version: "4.1.1"
4
+ version: "4.1.3"
5
5
  ---
6
6
 
7
7
  <!-- Generated by BI Agent Superpowers. Edit src/content/skills/bi-start.md instead. -->
@@ -57,7 +57,7 @@ Interpret the single-line output:
57
57
  ```bash
58
58
  super upgrade
59
59
  ```
60
- After it finishes, remind: _"Corré `super install --yes` cuando puedas para propagar las skills nuevas a tus agentes."_
60
+ After it finishes, remind: _"Si instalaste skills en el perfil del agente, corré `super install --yes`. Si además usás un plugin local generado con `super kickoff`, corré `super recharge` dentro de ese repo."_
61
61
 
62
62
  On `no` — respect it, continue to PHASE 1 silently. The update-state.json already tracks the user's snooze per `update-check.js` semantics.
63
63
 
@@ -182,7 +182,7 @@ Stop. Don't hover. The user will tell you what they want next.
182
182
  - **Project analysis or setup**: that's `/project-kickoff`. If the user says "analizar mi proyecto", "armar el modelo base", "arrancar uno nuevo desde cero", delegate.
183
183
  - **MCP wiring details**: that's `/pbi-connect`. bi-start just offers to dispatch it; the actual configuration work is in that skill.
184
184
  - **Report authoring**: that's `/report-design`. Same pattern.
185
- - **Running the update**: bi-start offers + dispatches `super upgrade`; the actual npm install + subsequent `super install --yes` chain is owned by `/bin/cli.js`.
185
+ - **Running the update**: bi-start offers + dispatches `super upgrade`; the actual refresh path after eso (`/plugin update bi-superpowers`, `super install --yes`, o `super recharge`) is owned by `/bin/cli.js`.
186
186
 
187
187
  ## Related Skills
188
188
 
@@ -47,7 +47,7 @@ const HTTPS_TIMEOUT_MS = 5000;
47
47
  // Rewritten at generation time when this helper is copied into
48
48
  // `skills/<name>/scripts/update-check.js`. In the canonical source under
49
49
  // `bin/commands/`, it stays null and we fall back to package.json.
50
- const BUNDLED_INSTALLED_VERSION = "4.1.1";
50
+ const BUNDLED_INSTALLED_VERSION = "4.1.3";
51
51
 
52
52
  // ---------------------------------------------------------------------------
53
53
  // Argument parsing
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: "pbi-connect"
3
3
  description: "Use when the user asks about Power BI MCP Connection Skill, especially phrases like \"connect Power BI\", \"PBI connection\", \"MCP connection\", \"Power BI MCP\", \"modeling mcp\", \"Power BI Modeling MCP\"."
4
- version: "4.1.1"
4
+ version: "4.1.3"
5
5
  ---
6
6
 
7
7
  <!-- Generated by BI Agent Superpowers. Edit src/content/skills/pbi-connect.md instead. -->
@@ -17,7 +17,7 @@ node "{skillBundleDir}/scripts/update-check.js" --silent-if-uptodate --silent-if
17
17
 
18
18
  - Empty output or `UPTODATE` — proceed with the skill silently. No message.
19
19
  - `UPDATE_AVAILABLE <installed> <latest>` — tell the user exactly once this conversation, before diving into the skill:
20
- > "Hay **bi-superpowers v{latest}** disponible (estás en v{installed}). Actualizá con `super upgrade` (o `/plugin update bi-superpowers` en Claude Code) cuando te venga bien."
20
+ > "Hay **bi-superpowers v{latest}** disponible (estás en v{installed}). Actualizá con `super upgrade` (o `/plugin update bi-superpowers` en Claude Code) cuando te venga bien. Si estás usando un plugin local generado con `super kickoff`, después corré `super recharge` en ese repo."
21
21
 
22
22
  Then continue with the skill below.
23
23
  - `SNOOZED <iso>` — proceed silently.
@@ -47,7 +47,7 @@ const HTTPS_TIMEOUT_MS = 5000;
47
47
  // Rewritten at generation time when this helper is copied into
48
48
  // `skills/<name>/scripts/update-check.js`. In the canonical source under
49
49
  // `bin/commands/`, it stays null and we fall back to package.json.
50
- const BUNDLED_INSTALLED_VERSION = "4.1.1";
50
+ const BUNDLED_INSTALLED_VERSION = "4.1.3";
51
51
 
52
52
  // ---------------------------------------------------------------------------
53
53
  // Argument parsing
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: "project-kickoff"
3
3
  description: "Use when the user asks about Project Kickoff Skill, especially phrases like \"I'm starting a brand-new BI project from scratch\", \"analizar proyecto\", \"analyze project\", \"project kickoff\", \"nuevo proyecto\", \"new project\"."
4
- version: "4.1.1"
4
+ version: "4.1.3"
5
5
  ---
6
6
 
7
7
  <!-- Generated by BI Agent Superpowers. Edit src/content/skills/project-kickoff.md instead. -->
@@ -17,7 +17,7 @@ node "{skillBundleDir}/scripts/update-check.js" --silent-if-uptodate --silent-if
17
17
 
18
18
  - Empty output or `UPTODATE` — proceed with the skill silently. No message.
19
19
  - `UPDATE_AVAILABLE <installed> <latest>` — tell the user exactly once this conversation, before diving into the skill:
20
- > "Hay **bi-superpowers v{latest}** disponible (estás en v{installed}). Actualizá con `super upgrade` (o `/plugin update bi-superpowers` en Claude Code) cuando te venga bien."
20
+ > "Hay **bi-superpowers v{latest}** disponible (estás en v{installed}). Actualizá con `super upgrade` (o `/plugin update bi-superpowers` en Claude Code) cuando te venga bien. Si estás usando un plugin local generado con `super kickoff`, después corré `super recharge` en ese repo."
21
21
 
22
22
  Then continue with the skill below.
23
23
  - `SNOOZED <iso>` — proceed silently.
@@ -594,11 +594,11 @@ Once the model has at least 1 fact, 1 dim, and 3 measures in place, propose movi
594
594
 
595
595
  El siguiente paso lógico es armar los 3 reportes con `/report-design`. Ese skill va a:
596
596
  1. Usar el dominio que ya definimos ({domain})
597
- 2. Inspeccionar tu modelo vía el pbi CLI para las medidas/dimensiones exactas
598
- 3. Generar 3 páginas con visuales vía CLI (card, line, bar, matrix)
597
+ 2. Inspeccionar tu modelo vía el Modeling MCP (o `pbi-cli-tool` si hace falta) para las medidas/dimensiones exactas
598
+ 3. Generar 3 páginas con scripts Node + comandos `pbi report` (card, line, bar, matrix)
599
599
  4. Cerrar y reabrir PBI Desktop para que renderice
600
600
 
601
- Requisito: necesitás pbi-cli-tool instalado (si no lo tenés el skill te guía).
601
+ Requisito: necesitás Windows + Power BI Desktop + Python 3.10+ + `pipx` + `pbi-cli-tool` (si te falta algo, el skill te guía).
602
602
 
603
603
  ¿Arrancamos con /report-design, o preferís agregar más medidas al modelo primero?
604
604
  ```
@@ -610,7 +610,7 @@ If the user opts for reports, load `/report-design` and let it run. If they want
610
610
  ## What this skill does NOT do
611
611
 
612
612
  - **No scoring / benchmarking** of an existing model. For that, the user can ask "audit this model" separately.
613
- - **Report authoring** is delegated to `/report-design` which orchestrates the `pbi-cli-tool` CLI — don't write `.Report/` files from here.
613
+ - **Report authoring** is delegated to `/report-design` which uses bundled Node scripts plus the `pbi` CLI runtime flow — don't write `.Report/` files from here.
614
614
 
615
615
  ---
616
616
 
@@ -47,7 +47,7 @@ const HTTPS_TIMEOUT_MS = 5000;
47
47
  // Rewritten at generation time when this helper is copied into
48
48
  // `skills/<name>/scripts/update-check.js`. In the canonical source under
49
49
  // `bin/commands/`, it stays null and we fall back to package.json.
50
- const BUNDLED_INSTALLED_VERSION = "4.1.1";
50
+ const BUNDLED_INSTALLED_VERSION = "4.1.3";
51
51
 
52
52
  // ---------------------------------------------------------------------------
53
53
  // Argument parsing
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: "report-design"
3
3
  description: "Use when the user asks about Report Design Skill, especially phrases like \"crear reportes\", \"armar el reporte\", \"diseñar reporte\", \"report design\", \"create reports\", \"build dashboard\"."
4
- version: "4.1.1"
4
+ version: "4.1.3"
5
5
  ---
6
6
 
7
7
  <!-- Generated by BI Agent Superpowers. Edit src/content/skills/report-design.md instead. -->
@@ -17,7 +17,7 @@ node "{skillBundleDir}/scripts/update-check.js" --silent-if-uptodate --silent-if
17
17
 
18
18
  - Empty output or `UPTODATE` — proceed with the skill silently. No message.
19
19
  - `UPDATE_AVAILABLE <installed> <latest>` — tell the user exactly once this conversation, before diving into the skill:
20
- > "Hay **bi-superpowers v{latest}** disponible (estás en v{installed}). Actualizá con `super upgrade` (o `/plugin update bi-superpowers` en Claude Code) cuando te venga bien."
20
+ > "Hay **bi-superpowers v{latest}** disponible (estás en v{installed}). Actualizá con `super upgrade` (o `/plugin update bi-superpowers` en Claude Code) cuando te venga bien. Si estás usando un plugin local generado con `super kickoff`, después corré `super recharge` en ese repo."
21
21
 
22
22
  Then continue with the skill below.
23
23
  - `SNOOZED <iso>` — proceed silently.
@@ -38,13 +38,13 @@ Activate this skill when the user mentions:
38
38
  - Explicit invocation: `/report-design`
39
39
 
40
40
  ## Identity
41
- You are **BI Report Architect**, an orchestrator that turns a finished semantic model into a Power BI report. You author PBIR via **bundled Node scripts** — not via `pbi-cli-tool` upstream:
41
+ You are **BI Report Architect**, an orchestrator that turns a finished semantic model into a Power BI report. You author the PBIR visual/theme layer via **bundled Node scripts** — not via the old `pbi visual` / `pbi report set-theme` path:
42
42
 
43
43
  - `scripts/create-visual.js` — creates any of the 28 native PBI visualTypes with a canonical `visual.json` shape (allowlist-driven, validated). **This replaces `pbi visual add` + `pbi visual bind`.**
44
44
  - `scripts/apply-theme.js` — registers a custom theme with the canonical `report.json` shape. **This replaces `pbi report set-theme`** (which writes invalid metadata for PBI Desktop March 2026).
45
45
  - `scripts/validate-pbir.js` — allowlist + bind-role validator. **Complements `pbi report validate`**, which passes `valid: True` even on non-native types like `stackedBarChart`.
46
46
 
47
- The `pbi-cli-tool` (MIT, by MinaSaad1) is kept around for **one purpose only**: model introspection via XMLA (`pbi connect`, `pbi measure list`, `pbi table list`, `pbi column list`). Prefer the Microsoft Modeling MCP when available — same capability, better integrated.
47
+ The `pbi-cli-tool` (MIT, by MinaSaad1) is still required today for **three parts of the flow**: model introspection via XMLA (`pbi connect`, `pbi measure list`, `pbi table list`, `pbi column list`), report page management (`pbi report add-page`, `pbi report list-pages`), and schema validation (`pbi report validate`). Prefer the Microsoft Modeling MCP when available for the introspection part — same capability, better integrated.
48
48
 
49
49
  Full rationale: `references/native-visuals.md` → section "Lo que este skill YA no hace via CLI".
50
50
 
@@ -295,7 +295,7 @@ Do NOT hand-author `report.json` theme metadata. The canonical PBIR shape (for r
295
295
  - `resourcePackages` includes a `{name: "RegisteredResources", type: "RegisteredResources"}` package whose `items[]` has `{name: "<file>.json", path: "<file>.json", type: "CustomTheme"}`
296
296
  - the theme file itself lives at `<reportPath>/StaticResources/RegisteredResources/<file>.json`
297
297
 
298
- **Conditional formatting (variance KPI green/red, diverging matrix gradients, signed-color bars) is DEFERRED to v4.1.** The layouts mention conditional color in design notes; in v4.0.0 the agent renders those visuals with default theme colors and skips the formatting step. Do not call `pbi format` from this skill in v4.0.0 — the `pbi format` syntax is not yet documented or tested for our use cases. Better a plain report that renders than a fancy one that breaks.
298
+ **Conditional formatting note.** Layout notes may describe variance colors, diverging matrix gradients, or signed-color bars as design intent. The current `report-design` flow does not author those formatting rules. Render those visuals with theme/default colors unless you have a tested PBIR formatting implementation. Do not invent `pbi format` calls from this skill.
299
299
 
300
300
  ### 4.4 Validate (two layers)
301
301
 
@@ -370,8 +370,8 @@ Cuando guardes desde Desktop, commiteá el .pbip a git para versionar.
370
370
  **References** (`references/`):
371
371
  - `native-visuals.md` — **canonical reference**: 28 native visualTypes, their roles, shape canonical, copy-paste examples (read this before authoring)
372
372
  - `pbi-desktop-installation.md` — why the standalone installer build is required (not Microsoft Store), install + uninstall steps
373
- - `cli-setup.md` — how to install Python + pipx + pbi-cli-tool + pywin32 (only needed for model introspection via XMLA; scripts don't require it)
374
- - `cli-commands.md` — cheatsheet of the `pbi` commands still used by this skill (mostly `pbi connect` / `pbi measure list` for model introspection; authoring commands are superseded by the Node scripts)
373
+ - `cli-setup.md` — how to install Python + pipx + pbi-cli-tool + pywin32 (required because this skill still uses `pbi` for connect, page operations, and validation)
374
+ - `cli-commands.md` — cheatsheet of the `pbi` commands still used by this skill (`pbi connect`, `pbi measure list`, `pbi report add-page`, `pbi report list-pages`, `pbi report validate`)
375
375
  - `textbox.md` — historical manual-write pattern for textboxes (superseded by `create-visual.js --type textbox`; kept for reference)
376
376
  - `slicer.md` — historical manual-write pattern for slicers (superseded by `create-visual.js --type slicer --slicer-mode ...`; kept for reference)
377
377
  - `close-write-open-pattern.md` — why and how to handle the Desktop restart cycle
@@ -385,7 +385,7 @@ Cuando guardes desde Desktop, commiteá el .pbip a git para versionar.
385
385
  - `layouts/generic.md` — fallback 3-page composition
386
386
 
387
387
  **Scripts** (`scripts/`):
388
- - `ensure-pbi-cli.sh` — idempotent installer for the pbi-cli-tool (only needed for model introspection via XMLA)
388
+ - `ensure-pbi-cli.sh` — idempotent installer for the pbi-cli-tool (required for this skill's current runtime flow)
389
389
  - `apply-theme.js` — registers a custom PBIR theme with the canonical shape Desktop accepts (replaces the broken `pbi report set-theme` in PBI Desktop March 2026)
390
390
  - `create-visual.js` — creates any of the 28 native PBI visualTypes with a canonical `visual.json` shape (replaces `pbi visual add` + `pbi visual bind`; enforces allowlist)
391
391
  - `validate-pbir.js` — allowlist + role-checks validator that catches non-native visualTypes and missing/invalid bindings (complements `pbi report validate`)
@@ -402,4 +402,4 @@ Cuando guardes desde Desktop, commiteá el .pbip a git para versionar.
402
402
 
403
403
  ## Credit
404
404
 
405
- This skill orchestrates the [`pbi-cli-tool`](https://github.com/MinaSaad1/pbi-cli) CLI by MinaSaad1 (MIT License). The CLI does the heavy lifting of PBIR JSON generation; we handle the teaching journey, planning, and Desktop lifecycle.
405
+ This skill integrates with the [`pbi-cli-tool`](https://github.com/MinaSaad1/pbi-cli) CLI by MinaSaad1 (MIT License) for model introspection, page operations, and schema validation. Visual and theme authoring are handled by the bundled Node scripts; we orchestrate the teaching journey, planning, and Desktop lifecycle.
@@ -28,7 +28,7 @@ Roles used below (to be resolved via the MCP):
28
28
  | Scenario slicer | slicer (manual JSON — see `references/slicer.md`) | 848, 312, 336, 80 | `Scenario[Scenario]` |
29
29
 
30
30
  **Design notes:**
31
- - Variance KPI: conditional formatting (green positive, red negative) is deferred to v4.1 render as plain card for v4.0.0.
31
+ - Variance KPI: green/red conditional coloring is design intent only. Render as a plain card with theme/default colors unless a tested PBIR formatting implementation is available.
32
32
  - Year slicer default: current year (single-select).
33
33
 
34
34
  ---
@@ -61,5 +61,5 @@ Roles used below (to be resolved via the MCP):
61
61
  | Account × Month matrix | matrix | 16, 512, 1168, 144 | rows: `account-dim-column`, cols: `'Date'[Month]`, values: `variance-measure` with diverging gradient |
62
62
 
63
63
  **Design notes:**
64
- - Variance-sign coloring (diverging palette) is deferred to v4.1 render bars/matrix with default theme colors for v4.0.0.
64
+ - Variance-sign coloring (diverging palette) is design intent only. Render bars/matrix with theme/default colors unless a tested PBIR formatting implementation is available.
65
65
  - The bottom matrix is short (144px) so it acts as a "heatmap strip" rather than a scrollable table.
@@ -311,7 +311,7 @@ Si PBI Desktop introduce un visualType nuevo (o encontrás uno nativo que falta
311
311
 
312
312
  ## Features de `visual.json` que `create-visual.js` NO soporta todavía
313
313
 
314
- Descubiertos al regenerar la smoke-test "Galería de Visuales" end-to-end con el script (backlog item 2, cycle v4.1). No bloquean el authoring — la shape que emite el script pasa `pbi report validate` y `validate-pbir.js` — pero sí dejan regresiones visuales si el `visual.json` hand-written aprovechaba alguno de estos features:
314
+ Descubiertos al regenerar la smoke-test "Galería de Visuales" end-to-end con el script. No bloquean el authoring — la shape que emite el script pasa `pbi report validate` y `validate-pbir.js` — pero sí dejan regresiones visuales si el `visual.json` hand-written aprovechaba alguno de estos features:
315
315
 
316
316
  1. **`query.sortDefinition`** — sort explícito por medida/columna con dirección. `create-visual.js` no lo emite, así que un visual "ranking" tipo barChart ordenado descendente por una medida pierde el orden en la regeneración. **Workaround**: ordenar en Desktop manualmente después del `.pbip` abrir, o hand-extender el `visual.json` con `sortDefinition` post-creación. **Fix futuro**: `--sort-by "Role:Field" --sort-dir descending` en `create-visual.js`.
317
317
 
@@ -319,7 +319,7 @@ Descubiertos al regenerar la smoke-test "Galería de Visuales" end-to-end con el
319
319
 
320
320
  3. **`queryState.<Role>.projections[].active`** — las columnas siempre salen con `active: true`, las medidas nunca. Si un visual hand-written tenía `active: true` en una medida (para indicar que la medida es la "default Y") o `active: false` en una columna (hidden projection), el script normaliza. Rara vez significativo para el render pero cambia el shape JSON.
321
321
 
322
- 4. **Formato condicional**: colores signados (positivo verde / negativo rojo), gradientes en matriz, data bars en tabla. Ninguno de estos expresa shape via `create-visual.js`. Quedó deferido a v4.1+ en `SKILL.md` PHASE 4.3.
322
+ 4. **Formato condicional**: colores signados (positivo verde / negativo rojo), gradientes en matriz, data bars en tabla. Ninguno de estos expresa shape via `create-visual.js`; tratarlos como diseño previsto hasta que exista una implementación PBIR testeada.
323
323
 
324
324
  Cualquier cambio en el script que cubra estos gaps debe: (a) agregar el flag a `parseArgs`, (b) cubrirlo con tests en `create-visual.test.js`, (c) documentarlo en este archivo, (d) regenerar la Galería para que ejercite el feature.
325
325
 
@@ -86,4 +86,4 @@ cat > "<reportPath>/definition/pages/<pageName>/visuals/<visualName>/visual.json
86
86
  EOF
87
87
  ```
88
88
 
89
- A reusable helper script (`scripts/write-slicer.sh`) is a v4.1 candidate; v4.0.0 ships with the heredoc pattern.
89
+ Prefer `scripts/create-visual.js --type slicer` for new slicers. Keep the heredoc pattern above only as a fallback when the helper script is unavailable.
@@ -98,4 +98,4 @@ cat > "<reportPath>/definition/pages/<pageName>/visuals/<visualName>/visual.json
98
98
  EOF
99
99
  ```
100
100
 
101
- A reusable helper script (`scripts/write-textbox.sh`) is a v4.1 candidate; v4.0.0 ships with the heredoc pattern.
101
+ Prefer `scripts/create-visual.js --type textbox` for new textboxes. Keep the heredoc pattern above only as a fallback when the helper script is unavailable.
@@ -679,6 +679,66 @@ function nextInt(existing, key) {
679
679
  return max + 1;
680
680
  }
681
681
 
682
+ function validateVisualName(name) {
683
+ if (typeof name !== 'string' || name.trim() === '') {
684
+ fail('--name must be a non-empty visual folder name');
685
+ }
686
+
687
+ if (name !== name.trim()) {
688
+ fail(`--name must not have leading or trailing whitespace (got: ${JSON.stringify(name)})`);
689
+ }
690
+
691
+ if (
692
+ name === '.' ||
693
+ name === '..' ||
694
+ /[\\/]/.test(name) ||
695
+ path.basename(name) !== name ||
696
+ path.win32.basename(name) !== name ||
697
+ path.posix.basename(name) !== name
698
+ ) {
699
+ fail(`--name must be a single visual folder name, not a path (got: ${JSON.stringify(name)})`);
700
+ }
701
+
702
+ if (/[\u0000-\u001f<>:"|?*]/.test(name)) {
703
+ fail(`--name contains characters that are not valid in a Windows folder name (got: ${JSON.stringify(name)})`);
704
+ }
705
+ }
706
+
707
+ function validateNumericOptions(args) {
708
+ const numericOptions = [
709
+ ['x', '--x'],
710
+ ['y', '--y'],
711
+ ['z', '-z'],
712
+ ['width', '--width'],
713
+ ['height', '--height'],
714
+ ['tabOrder', '--tab-order'],
715
+ ];
716
+
717
+ for (const [key, flag] of numericOptions) {
718
+ if (args[key] != null && !Number.isFinite(args[key])) {
719
+ fail(`${flag} must be a finite number`);
720
+ }
721
+ }
722
+
723
+ for (const [key, flag] of [
724
+ ['width', '--width'],
725
+ ['height', '--height'],
726
+ ]) {
727
+ if (args[key] != null && args[key] <= 0) {
728
+ fail(`${flag} must be greater than 0`);
729
+ }
730
+ }
731
+ }
732
+
733
+ function assertPathInside(childPath, parentPath, label) {
734
+ const parent = path.resolve(parentPath);
735
+ const child = path.resolve(childPath);
736
+ const relative = path.relative(parent, child);
737
+ if (!relative || relative.startsWith('..') || path.isAbsolute(relative)) {
738
+ fail(`${label} resolved outside the expected directory: ${child}`);
739
+ }
740
+ }
741
+
682
742
  // ---------------------------------------------------------------------------
683
743
  // main()
684
744
  // ---------------------------------------------------------------------------
@@ -698,6 +758,7 @@ function main() {
698
758
  if (!args.reportPath) fail('--report-path is required');
699
759
  if (!args.page) fail('--page is required');
700
760
  if (!args.type) fail('--type is required (use --list-types to see options)');
761
+ validateNumericOptions(args);
701
762
 
702
763
  // ---- type validation with friendly errors for known non-native aliases
703
764
  if (KNOWN_NON_NATIVE_TYPES[args.type]) {
@@ -727,8 +788,11 @@ function main() {
727
788
  } while (existing.some((v) => v.name === candidate));
728
789
  name = candidate;
729
790
  }
791
+ validateVisualName(name);
730
792
 
731
- const visualDir = path.join(pageDir, 'visuals', name);
793
+ const visualsDir = path.join(pageDir, 'visuals');
794
+ const visualDir = path.join(visualsDir, name);
795
+ assertPathInside(visualDir, visualsDir, '--name');
732
796
  const visualJsonPath = path.join(visualDir, 'visual.json');
733
797
  if (fs.existsSync(visualJsonPath)) {
734
798
  fail(
@@ -47,7 +47,7 @@ const HTTPS_TIMEOUT_MS = 5000;
47
47
  // Rewritten at generation time when this helper is copied into
48
48
  // `skills/<name>/scripts/update-check.js`. In the canonical source under
49
49
  // `bin/commands/`, it stays null and we fall back to package.json.
50
- const BUNDLED_INSTALLED_VERSION = "4.1.1";
50
+ const BUNDLED_INSTALLED_VERSION = "4.1.3";
51
51
 
52
52
  // ---------------------------------------------------------------------------
53
53
  // Argument parsing
@@ -130,6 +130,33 @@ function boundRoles(visualData) {
130
130
  return bound;
131
131
  }
132
132
 
133
+ function validatePosition(position) {
134
+ const errors = [];
135
+ const requiredFields = ['x', 'y', 'z', 'height', 'width', 'tabOrder'];
136
+
137
+ if (!position || typeof position !== 'object') {
138
+ return requiredFields.map((field) => ({
139
+ severity: 'error',
140
+ rule: 'position-number',
141
+ field,
142
+ message: `position.${field} must be a finite number`,
143
+ }));
144
+ }
145
+
146
+ for (const field of requiredFields) {
147
+ if (!Number.isFinite(position[field])) {
148
+ errors.push({
149
+ severity: 'error',
150
+ rule: 'position-number',
151
+ field,
152
+ message: `position.${field} must be a finite number`,
153
+ });
154
+ }
155
+ }
156
+
157
+ return errors;
158
+ }
159
+
133
160
  function validateVisual(visual) {
134
161
  const errors = [];
135
162
  const { data, path: filePath } = visual;
@@ -148,6 +175,8 @@ function validateVisual(visual) {
148
175
  errors.push({ severity: 'error', rule: 'name', message: 'missing "name"' });
149
176
  }
150
177
 
178
+ errors.push(...validatePosition(data.position));
179
+
151
180
  const vt = data.visual && data.visual.visualType;
152
181
  if (!vt) {
153
182
  errors.push({ severity: 'error', rule: 'visual-type', message: 'missing visualType' });
@@ -49,7 +49,7 @@ Interpret the single-line output:
49
49
  ```bash
50
50
  super upgrade
51
51
  ```
52
- After it finishes, remind: _"Corré `super install --yes` cuando puedas para propagar las skills nuevas a tus agentes."_
52
+ After it finishes, remind: _"Si instalaste skills en el perfil del agente, corré `super install --yes`. Si además usás un plugin local generado con `super kickoff`, corré `super recharge` dentro de ese repo."_
53
53
 
54
54
  On `no` — respect it, continue to PHASE 1 silently. The update-state.json already tracks the user's snooze per `update-check.js` semantics.
55
55
 
@@ -174,7 +174,7 @@ Stop. Don't hover. The user will tell you what they want next.
174
174
  - **Project analysis or setup**: that's `/project-kickoff`. If the user says "analizar mi proyecto", "armar el modelo base", "arrancar uno nuevo desde cero", delegate.
175
175
  - **MCP wiring details**: that's `/pbi-connect`. bi-start just offers to dispatch it; the actual configuration work is in that skill.
176
176
  - **Report authoring**: that's `/report-design`. Same pattern.
177
- - **Running the update**: bi-start offers + dispatches `super upgrade`; the actual npm install + subsequent `super install --yes` chain is owned by `/bin/cli.js`.
177
+ - **Running the update**: bi-start offers + dispatches `super upgrade`; the actual refresh path after eso (`/plugin update bi-superpowers`, `super install --yes`, o `super recharge`) is owned by `/bin/cli.js`.
178
178
 
179
179
  ## Related Skills
180
180
 
@@ -565,11 +565,11 @@ Once the model has at least 1 fact, 1 dim, and 3 measures in place, propose movi
565
565
 
566
566
  El siguiente paso lógico es armar los 3 reportes con `/report-design`. Ese skill va a:
567
567
  1. Usar el dominio que ya definimos ({domain})
568
- 2. Inspeccionar tu modelo vía el pbi CLI para las medidas/dimensiones exactas
569
- 3. Generar 3 páginas con visuales vía CLI (card, line, bar, matrix)
568
+ 2. Inspeccionar tu modelo vía el Modeling MCP (o `pbi-cli-tool` si hace falta) para las medidas/dimensiones exactas
569
+ 3. Generar 3 páginas con scripts Node + comandos `pbi report` (card, line, bar, matrix)
570
570
  4. Cerrar y reabrir PBI Desktop para que renderice
571
571
 
572
- Requisito: necesitás pbi-cli-tool instalado (si no lo tenés el skill te guía).
572
+ Requisito: necesitás Windows + Power BI Desktop + Python 3.10+ + `pipx` + `pbi-cli-tool` (si te falta algo, el skill te guía).
573
573
 
574
574
  ¿Arrancamos con /report-design, o preferís agregar más medidas al modelo primero?
575
575
  ```
@@ -581,7 +581,7 @@ If the user opts for reports, load `/report-design` and let it run. If they want
581
581
  ## What this skill does NOT do
582
582
 
583
583
  - **No scoring / benchmarking** of an existing model. For that, the user can ask "audit this model" separately.
584
- - **Report authoring** is delegated to `/report-design` which orchestrates the `pbi-cli-tool` CLI — don't write `.Report/` files from here.
584
+ - **Report authoring** is delegated to `/report-design` which uses bundled Node scripts plus the `pbi` CLI runtime flow — don't write `.Report/` files from here.
585
585
 
586
586
  ---
587
587
 
@@ -9,13 +9,13 @@ Activate this skill when the user mentions:
9
9
  - Explicit invocation: `/report-design`
10
10
 
11
11
  ## Identity
12
- You are **BI Report Architect**, an orchestrator that turns a finished semantic model into a Power BI report. You author PBIR via **bundled Node scripts** — not via `pbi-cli-tool` upstream:
12
+ You are **BI Report Architect**, an orchestrator that turns a finished semantic model into a Power BI report. You author the PBIR visual/theme layer via **bundled Node scripts** — not via the old `pbi visual` / `pbi report set-theme` path:
13
13
 
14
14
  - `scripts/create-visual.js` — creates any of the 28 native PBI visualTypes with a canonical `visual.json` shape (allowlist-driven, validated). **This replaces `pbi visual add` + `pbi visual bind`.**
15
15
  - `scripts/apply-theme.js` — registers a custom theme with the canonical `report.json` shape. **This replaces `pbi report set-theme`** (which writes invalid metadata for PBI Desktop March 2026).
16
16
  - `scripts/validate-pbir.js` — allowlist + bind-role validator. **Complements `pbi report validate`**, which passes `valid: True` even on non-native types like `stackedBarChart`.
17
17
 
18
- The `pbi-cli-tool` (MIT, by MinaSaad1) is kept around for **one purpose only**: model introspection via XMLA (`pbi connect`, `pbi measure list`, `pbi table list`, `pbi column list`). Prefer the Microsoft Modeling MCP when available — same capability, better integrated.
18
+ The `pbi-cli-tool` (MIT, by MinaSaad1) is still required today for **three parts of the flow**: model introspection via XMLA (`pbi connect`, `pbi measure list`, `pbi table list`, `pbi column list`), report page management (`pbi report add-page`, `pbi report list-pages`), and schema validation (`pbi report validate`). Prefer the Microsoft Modeling MCP when available for the introspection part — same capability, better integrated.
19
19
 
20
20
  Full rationale: `references/native-visuals.md` → section "Lo que este skill YA no hace via CLI".
21
21
 
@@ -266,7 +266,7 @@ Do NOT hand-author `report.json` theme metadata. The canonical PBIR shape (for r
266
266
  - `resourcePackages` includes a `{name: "RegisteredResources", type: "RegisteredResources"}` package whose `items[]` has `{name: "<file>.json", path: "<file>.json", type: "CustomTheme"}`
267
267
  - the theme file itself lives at `<reportPath>/StaticResources/RegisteredResources/<file>.json`
268
268
 
269
- **Conditional formatting (variance KPI green/red, diverging matrix gradients, signed-color bars) is DEFERRED to v4.1.** The layouts mention conditional color in design notes; in v4.0.0 the agent renders those visuals with default theme colors and skips the formatting step. Do not call `pbi format` from this skill in v4.0.0 — the `pbi format` syntax is not yet documented or tested for our use cases. Better a plain report that renders than a fancy one that breaks.
269
+ **Conditional formatting note.** Layout notes may describe variance colors, diverging matrix gradients, or signed-color bars as design intent. The current `report-design` flow does not author those formatting rules. Render those visuals with theme/default colors unless you have a tested PBIR formatting implementation. Do not invent `pbi format` calls from this skill.
270
270
 
271
271
  ### 4.4 Validate (two layers)
272
272
 
@@ -341,8 +341,8 @@ Cuando guardes desde Desktop, commiteá el .pbip a git para versionar.
341
341
  **References** (`references/`):
342
342
  - `native-visuals.md` — **canonical reference**: 28 native visualTypes, their roles, shape canonical, copy-paste examples (read this before authoring)
343
343
  - `pbi-desktop-installation.md` — why the standalone installer build is required (not Microsoft Store), install + uninstall steps
344
- - `cli-setup.md` — how to install Python + pipx + pbi-cli-tool + pywin32 (only needed for model introspection via XMLA; scripts don't require it)
345
- - `cli-commands.md` — cheatsheet of the `pbi` commands still used by this skill (mostly `pbi connect` / `pbi measure list` for model introspection; authoring commands are superseded by the Node scripts)
344
+ - `cli-setup.md` — how to install Python + pipx + pbi-cli-tool + pywin32 (required because this skill still uses `pbi` for connect, page operations, and validation)
345
+ - `cli-commands.md` — cheatsheet of the `pbi` commands still used by this skill (`pbi connect`, `pbi measure list`, `pbi report add-page`, `pbi report list-pages`, `pbi report validate`)
346
346
  - `textbox.md` — historical manual-write pattern for textboxes (superseded by `create-visual.js --type textbox`; kept for reference)
347
347
  - `slicer.md` — historical manual-write pattern for slicers (superseded by `create-visual.js --type slicer --slicer-mode ...`; kept for reference)
348
348
  - `close-write-open-pattern.md` — why and how to handle the Desktop restart cycle
@@ -356,7 +356,7 @@ Cuando guardes desde Desktop, commiteá el .pbip a git para versionar.
356
356
  - `layouts/generic.md` — fallback 3-page composition
357
357
 
358
358
  **Scripts** (`scripts/`):
359
- - `ensure-pbi-cli.sh` — idempotent installer for the pbi-cli-tool (only needed for model introspection via XMLA)
359
+ - `ensure-pbi-cli.sh` — idempotent installer for the pbi-cli-tool (required for this skill's current runtime flow)
360
360
  - `apply-theme.js` — registers a custom PBIR theme with the canonical shape Desktop accepts (replaces the broken `pbi report set-theme` in PBI Desktop March 2026)
361
361
  - `create-visual.js` — creates any of the 28 native PBI visualTypes with a canonical `visual.json` shape (replaces `pbi visual add` + `pbi visual bind`; enforces allowlist)
362
362
  - `validate-pbir.js` — allowlist + role-checks validator that catches non-native visualTypes and missing/invalid bindings (complements `pbi report validate`)
@@ -373,4 +373,4 @@ Cuando guardes desde Desktop, commiteá el .pbip a git para versionar.
373
373
 
374
374
  ## Credit
375
375
 
376
- This skill orchestrates the [`pbi-cli-tool`](https://github.com/MinaSaad1/pbi-cli) CLI by MinaSaad1 (MIT License). The CLI does the heavy lifting of PBIR JSON generation; we handle the teaching journey, planning, and Desktop lifecycle.
376
+ This skill integrates with the [`pbi-cli-tool`](https://github.com/MinaSaad1/pbi-cli) CLI by MinaSaad1 (MIT License) for model introspection, page operations, and schema validation. Visual and theme authoring are handled by the bundled Node scripts; we orchestrate the teaching journey, planning, and Desktop lifecycle.
@@ -28,7 +28,7 @@ Roles used below (to be resolved via the MCP):
28
28
  | Scenario slicer | slicer (manual JSON — see `references/slicer.md`) | 848, 312, 336, 80 | `Scenario[Scenario]` |
29
29
 
30
30
  **Design notes:**
31
- - Variance KPI: conditional formatting (green positive, red negative) is deferred to v4.1 render as plain card for v4.0.0.
31
+ - Variance KPI: green/red conditional coloring is design intent only. Render as a plain card with theme/default colors unless a tested PBIR formatting implementation is available.
32
32
  - Year slicer default: current year (single-select).
33
33
 
34
34
  ---
@@ -61,5 +61,5 @@ Roles used below (to be resolved via the MCP):
61
61
  | Account × Month matrix | matrix | 16, 512, 1168, 144 | rows: `account-dim-column`, cols: `'Date'[Month]`, values: `variance-measure` with diverging gradient |
62
62
 
63
63
  **Design notes:**
64
- - Variance-sign coloring (diverging palette) is deferred to v4.1 render bars/matrix with default theme colors for v4.0.0.
64
+ - Variance-sign coloring (diverging palette) is design intent only. Render bars/matrix with theme/default colors unless a tested PBIR formatting implementation is available.
65
65
  - The bottom matrix is short (144px) so it acts as a "heatmap strip" rather than a scrollable table.