@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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.claude-plugin/skill-manifest.json +1 -1
- package/.plugin/plugin.json +1 -1
- package/AGENTS.md +4 -5
- package/CHANGELOG.md +24 -0
- package/README.md +633 -93
- package/bin/cli.js +52 -54
- package/bin/commands/build-desktop.js +60 -6
- package/bin/commands/diff.js +86 -1
- package/bin/commands/watch.js +50 -5
- package/bin/lib/generators/claude-plugin.js +1 -1
- package/bin/postinstall.js +1 -1
- package/commands/bi-start.md +2 -2
- package/commands/pbi-connect.md +1 -1
- package/commands/project-kickoff.md +5 -5
- package/commands/report-design.md +8 -8
- package/desktop-extension/server.js +43 -10
- package/package.json +5 -5
- package/skills/bi-start/SKILL.md +3 -3
- package/skills/bi-start/scripts/update-check.js +1 -1
- package/skills/pbi-connect/SKILL.md +2 -2
- package/skills/pbi-connect/scripts/update-check.js +1 -1
- package/skills/project-kickoff/SKILL.md +6 -6
- package/skills/project-kickoff/scripts/update-check.js +1 -1
- package/skills/report-design/SKILL.md +9 -9
- package/skills/report-design/references/layouts/finance.md +2 -2
- package/skills/report-design/references/native-visuals.md +2 -2
- package/skills/report-design/references/slicer.md +1 -1
- package/skills/report-design/references/textbox.md +1 -1
- package/skills/report-design/scripts/create-visual.js +65 -1
- package/skills/report-design/scripts/update-check.js +1 -1
- package/skills/report-design/scripts/validate-pbir.js +29 -0
- package/src/content/skills/bi-start.md +2 -2
- package/src/content/skills/project-kickoff.md +4 -4
- package/src/content/skills/report-design/SKILL.md +7 -7
- package/src/content/skills/report-design/references/layouts/finance.md +2 -2
- package/src/content/skills/report-design/references/native-visuals.md +2 -2
- package/src/content/skills/report-design/references/slicer.md +1 -1
- package/src/content/skills/report-design/references/textbox.md +1 -1
- package/src/content/skills/report-design/scripts/create-visual.js +65 -1
- 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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
|
35
|
-
const name =
|
|
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:
|
|
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.
|
|
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": "^
|
|
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",
|
package/skills/bi-start/SKILL.md
CHANGED
|
@@ -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.
|
|
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: _"
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
598
|
-
3. Generar 3 páginas con
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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-
|
|
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
|
|
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
|
|
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 (
|
|
374
|
-
- `cli-commands.md` — cheatsheet of the `pbi` commands still used by this skill (
|
|
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 (
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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: _"
|
|
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
|
|
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
|
|
569
|
-
3. Generar 3 páginas con
|
|
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
|
|
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
|
|
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-
|
|
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
|
|
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
|
|
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 (
|
|
345
|
-
- `cli-commands.md` — cheatsheet of the `pbi` commands still used by this skill (
|
|
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 (
|
|
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
|
|
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:
|
|
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
|
|
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.
|