@luquimbo/bi-superpowers 1.0.0 → 1.1.2

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 (38) hide show
  1. package/.claude-plugin/marketplace.json +46 -0
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.mcp.json +4 -0
  4. package/AGENTS.md +98 -7
  5. package/README.md +139 -118
  6. package/bin/cli.js +45 -31
  7. package/bin/commands/install.js +317 -0
  8. package/bin/lib/microsoft-mcp.js +8 -0
  9. package/bin/lib/microsoft-mcp.test.js +5 -0
  10. package/package.json +1 -1
  11. package/skills/contributions/SKILL.md +1 -1
  12. package/skills/data-model-design/SKILL.md +1 -1
  13. package/skills/data-modeling/SKILL.md +82 -56
  14. package/skills/data-quality/SKILL.md +1 -1
  15. package/skills/dax/SKILL.md +74 -36
  16. package/skills/dax-doctor/SKILL.md +1 -1
  17. package/skills/dax-udf/SKILL.md +1 -1
  18. package/skills/deployment/SKILL.md +1 -1
  19. package/skills/excel-formulas/SKILL.md +1 -1
  20. package/skills/fabric-scripts/SKILL.md +1 -1
  21. package/skills/fast-standard/SKILL.md +1 -1
  22. package/skills/governance/SKILL.md +103 -50
  23. package/skills/migration-assistant/SKILL.md +1 -1
  24. package/skills/model-documenter/SKILL.md +1 -1
  25. package/skills/pbi-connect/SKILL.md +1 -1
  26. package/skills/power-query/SKILL.md +1 -1
  27. package/skills/project-kickoff/SKILL.md +1 -1
  28. package/skills/query-performance/SKILL.md +1 -1
  29. package/skills/report-design/SKILL.md +1 -1
  30. package/skills/report-layout/SKILL.md +1 -1
  31. package/skills/rls-design/SKILL.md +1 -1
  32. package/skills/semantic-model/SKILL.md +1 -1
  33. package/skills/testing-validation/SKILL.md +1 -1
  34. package/skills/theme-tweaker/SKILL.md +1 -1
  35. package/src/content/mcp-requirements.json +13 -0
  36. package/src/content/skills/data-modeling.md +81 -55
  37. package/src/content/skills/dax.md +73 -35
  38. package/src/content/skills/governance.md +102 -49
package/bin/cli.js CHANGED
@@ -43,7 +43,7 @@ try {
43
43
  // Wrapped in try-catch because they may not be available during initial npm install
44
44
  let searchCommand, lintCommand, diffCommand, watchCommand, mcpSetupCommand, tui;
45
45
  let setupCommand, addCommand, pullCommand, pushCommand, syncProfileCommand, syncSourceCommand;
46
- let changelogCommand, buildDesktopCommand;
46
+ let changelogCommand, buildDesktopCommand, installCommand;
47
47
  try {
48
48
  searchCommand = require('./commands/search'); // Fuzzy search across library content
49
49
  lintCommand = require('./commands/lint'); // Skill file validation
@@ -61,6 +61,7 @@ try {
61
61
  syncSourceCommand = require('./commands/sync-source'); // Bidirectional sync
62
62
  changelogCommand = require('./commands/changelog'); // Generate changelog from Git
63
63
  buildDesktopCommand = require('./commands/build-desktop'); // Build MCPB for Claude Desktop
64
+ installCommand = require('./commands/install'); // Multi-agent skill installer
64
65
  } catch (e) {
65
66
  // Silent fail - commands may not be available during npm install phase
66
67
  // This is expected behavior, not an error condition
@@ -126,47 +127,29 @@ const AI_TOOLS = generators ? generators.AI_TOOLS : {};
126
127
  * - Developer: Advanced tools for content management (xray, checkup, scan, sentinel, powers)
127
128
  * - Legacy: Old command names maintained for backward compatibility
128
129
  */
130
+ // Commands are registered lazily to avoid TDZ issues with const wrappers.
131
+ // Core commands use hoisted function declarations; developer commands use
132
+ // createCommandWrapper which is defined later. We populate the map in
133
+ // registerCommands() which runs before main().
129
134
  const commands = {
130
- // Core commands - basic info and status
135
+ // Core commands - basic info and status (hoisted functions, safe here)
131
136
  help: showHelp,
132
137
  version: showVersion,
133
138
  about: showInfo,
134
139
  status: showLicenseStatus,
135
140
 
136
- // Setup & sync - project configuration
137
- kickoff: initProject, // Interactive project setup wizard
138
- recharge: syncProject, // Regenerate AI tool configs from skills
139
- unlock: activateLicense, // Activate license key
140
- upgrade: updatePackage, // Update to latest npm version
141
-
142
- // Developer tools - content management
143
- xray: runSearch, // Fuzzy search library content
144
- checkup: runLint, // Validate skill files
145
- scan: runDiff, // Compare source vs generated
146
- sentinel: runWatch, // Watch and auto-regenerate
147
- powers: listAgents, // List available skills
148
- 'mcp-setup': runMcpSetup, // Configure MCP servers for AI tools
149
- mcp: runMcpSetup, // Alias for mcp-setup
150
- 'build-desktop': runBuildDesktop, // Build MCPB extension for Claude Desktop
141
+ // Setup & sync - project configuration (hoisted functions, safe here)
142
+ kickoff: initProject,
143
+ recharge: syncProject,
144
+ unlock: activateLicense,
145
+ upgrade: updatePackage,
146
+ powers: listAgents,
151
147
 
152
- // Repo multi-project commands (v3)
153
- setup: runSetup, // Onboarding wizard - creates bi-repo
154
- add: runAdd, // Add project to bi-repo
155
- pull: runPull, // Pull changes from original file to repo
156
- push: runPush, // Push changes from repo to original file
157
- 'sync-source': runSyncSource, // Bidirectional sync with original file
158
- 'sync-profile': runSyncProfile, // Sync snippets to base profile
159
- changelog: runChangelog, // Generate changelog from Git history
160
-
161
- // Legacy aliases (backward compatibility with v2.0.x)
148
+ // Legacy aliases (hoisted functions, safe here)
162
149
  init: initProject,
163
150
  sync: syncProject,
164
151
  activate: activateLicense,
165
152
  update: updatePackage,
166
- search: runSearch,
167
- lint: runLint,
168
- diff: runDiff,
169
- watch: runWatch,
170
153
  list: listAgents,
171
154
  info: showInfo,
172
155
  };
@@ -199,6 +182,7 @@ Usage:
199
182
  super <command> [options]
200
183
 
201
184
  Commands:
185
+ install Install skills for your AI agents (Claude, Copilot, Codex...)
202
186
  unlock Activate your license key
203
187
  kickoff [path] Initialize the Claude Code plugin in your project
204
188
  recharge [path] Regenerate the plugin from source skills
@@ -225,7 +209,15 @@ Repo Multi-Proyecto (v3):
225
209
  Options:
226
210
  --dry-run Preview changes without creating files (kickoff, recharge)
227
211
 
212
+ Install options:
213
+ --agent, -a Specify agents (e.g. -a claude-code -a codex)
214
+ --all Install for all supported agents
215
+ --yes, -y Skip confirmation prompts
216
+
228
217
  Examples:
218
+ super install # Interactive multi-agent installer
219
+ super install -a claude-code # Install for Claude Code only
220
+ super install --all --yes # Install for all agents, no prompts
229
221
  super unlock # Activate your license
230
222
  super kickoff # Initialize plugin in current directory
231
223
  super kickoff ./my-project # Initialize in specific directory
@@ -1006,6 +998,28 @@ const runSyncSource = createCommandWrapper(syncSourceCommand, 'Sync-source');
1006
998
  const runSyncProfile = createCommandWrapper(syncProfileCommand, 'Sync-profile');
1007
999
  const runChangelog = createCommandWrapper(changelogCommand, 'Changelog');
1008
1000
  const runBuildDesktop = createCommandWrapper(buildDesktopCommand, 'Build Desktop');
1001
+ const runInstall = createCommandWrapper(installCommand, 'Install');
1002
+
1003
+ // Register commands that depend on createCommandWrapper (avoids TDZ in object literal)
1004
+ commands.install = runInstall;
1005
+ commands.xray = runSearch;
1006
+ commands.checkup = runLint;
1007
+ commands.scan = runDiff;
1008
+ commands.sentinel = runWatch;
1009
+ commands['mcp-setup'] = runMcpSetup;
1010
+ commands.mcp = runMcpSetup;
1011
+ commands['build-desktop'] = runBuildDesktop;
1012
+ commands.setup = runSetup;
1013
+ commands.add = runAdd;
1014
+ commands.pull = runPull;
1015
+ commands.push = runPush;
1016
+ commands['sync-source'] = runSyncSource;
1017
+ commands['sync-profile'] = runSyncProfile;
1018
+ commands.changelog = runChangelog;
1019
+ commands.search = runSearch;
1020
+ commands.lint = runLint;
1021
+ commands.diff = runDiff;
1022
+ commands.watch = runWatch;
1009
1023
 
1010
1024
  /**
1011
1025
  * Run watch command (special case - needs additional context)
@@ -0,0 +1,317 @@
1
+ /**
2
+ * Install Command - Multi-agent skill installer
3
+ * ===============================================
4
+ *
5
+ * Installs BI Agent Superpowers skills into the correct directories
6
+ * for each AI coding agent. Inspired by the `npx skills` CLI from Vercel Labs.
7
+ *
8
+ * Skills are always installed at the user level (~/) to protect licensed content.
9
+ *
10
+ * Usage:
11
+ * npx @luquimbo/bi-superpowers install
12
+ * super install
13
+ * super install --agent claude-code --agent codex
14
+ * super install --all --yes
15
+ *
16
+ * @module commands/install
17
+ */
18
+
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+ const os = require('os');
22
+ const readline = require('readline');
23
+
24
+ // Agent registry: each agent's skill directory path (relative to home directory)
25
+ // Order matches the interactive installer display order
26
+ const AGENTS = {
27
+ 'github-copilot': { name: 'GitHub Copilot', dir: '.github/skills' },
28
+ 'claude-code': { name: 'Claude Code', dir: '.claude/skills' },
29
+ codex: { name: 'Codex (OpenAI)', dir: '.agents/skills' },
30
+ 'gemini-cli': { name: 'Gemini CLI', dir: '.gemini/skills' },
31
+ kilo: { name: 'Kilo Code', dir: '.kilocode/skills' },
32
+ };
33
+
34
+ // Universal path — most agents read from .agents/skills/
35
+ const UNIVERSAL_DIR = '.agents/skills';
36
+
37
+ /**
38
+ * Detect which agents are available by checking for their config directories
39
+ * @param {string} baseDir - Directory to check (project root or home)
40
+ * @returns {string[]} Array of detected agent IDs
41
+ */
42
+ function detectAgents(baseDir) {
43
+ const detected = [];
44
+ for (const [id, agent] of Object.entries(AGENTS)) {
45
+ const agentRoot = path.dirname(agent.dir);
46
+ const checkPath = path.join(baseDir, agentRoot);
47
+ if (fs.existsSync(checkPath)) {
48
+ detected.push(id);
49
+ }
50
+ }
51
+ return detected;
52
+ }
53
+
54
+ /**
55
+ * Create readline interface for interactive prompts
56
+ */
57
+ function createReadline() {
58
+ return readline.createInterface({
59
+ input: process.stdin,
60
+ output: process.stdout,
61
+ });
62
+ }
63
+
64
+ /**
65
+ * Prompt user with a question
66
+ */
67
+ function prompt(rl, question) {
68
+ return new Promise((resolve) => {
69
+ rl.question(question, (answer) => resolve(answer.trim()));
70
+ });
71
+ }
72
+
73
+ /**
74
+ * Display a numbered list and let user pick multiple items
75
+ * @param {readline.Interface} rl
76
+ * @param {Array<{id: string, name: string}>} items
77
+ * @param {string[]} preselected - IDs to preselect
78
+ * @returns {Promise<string[]>} Selected IDs
79
+ */
80
+ async function selectMultiple(rl, items, preselected = []) {
81
+ items.forEach((item, i) => {
82
+ const marker = preselected.includes(item.id) ? '●' : '○';
83
+ console.log(` ${i + 1}) ${marker} ${item.name}`);
84
+ });
85
+ console.log();
86
+ console.log(' Enter numbers separated by commas (e.g. 1,2,3)');
87
+ console.log(' Press Enter for detected agents, or "a" for all');
88
+
89
+ const answer = await prompt(rl, '\n > ');
90
+
91
+ if (answer.toLowerCase() === 'a') {
92
+ return items.map((item) => item.id);
93
+ }
94
+
95
+ if (answer === '') {
96
+ return preselected.length > 0 ? preselected : items.map((item) => item.id);
97
+ }
98
+
99
+ const indices = answer
100
+ .split(',')
101
+ .map((s) => parseInt(s.trim(), 10) - 1)
102
+ .filter((i) => i >= 0 && i < items.length);
103
+
104
+ return indices.map((i) => items[i].id);
105
+ }
106
+
107
+ /**
108
+ * Copy a skill directory to a target location
109
+ * @param {string} srcDir - Source skill directory (containing SKILL.md)
110
+ * @param {string} destDir - Destination directory
111
+ */
112
+ function copySkillDir(srcDir, destDir) {
113
+ if (!fs.existsSync(destDir)) {
114
+ fs.mkdirSync(destDir, { recursive: true });
115
+ }
116
+
117
+ const entries = fs.readdirSync(srcDir, { withFileTypes: true });
118
+ for (const entry of entries) {
119
+ const srcPath = path.join(srcDir, entry.name);
120
+ const destPath = path.join(destDir, entry.name);
121
+
122
+ if (entry.isDirectory()) {
123
+ copySkillDir(srcPath, destPath);
124
+ } else {
125
+ fs.copyFileSync(srcPath, destPath);
126
+ }
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Main install command handler
132
+ * @param {string[]} args - CLI arguments
133
+ * @param {Object} config - Command config from CLI
134
+ */
135
+ async function installCommand(args, config) {
136
+ const chalk = require('chalk');
137
+ const boxen = require('boxen');
138
+
139
+ const isYes = args.includes('--yes') || args.includes('-y');
140
+ const isAll = args.includes('--all');
141
+ const agentFlags = [];
142
+
143
+ // Parse --agent flags
144
+ for (let i = 0; i < args.length; i++) {
145
+ if ((args[i] === '--agent' || args[i] === '-a') && args[i + 1]) {
146
+ agentFlags.push(args[i + 1]);
147
+ i++;
148
+ }
149
+ }
150
+
151
+ // Always install at user level (home directory) to protect licensed content
152
+ const baseDir = os.homedir();
153
+
154
+ // Find skills from the package
155
+ const packageDir = config.packageDir || path.dirname(__dirname);
156
+ const skillsSourceDir = path.join(packageDir, 'skills');
157
+
158
+ if (!fs.existsSync(skillsSourceDir)) {
159
+ console.error(chalk.red('Skills directory not found. Try reinstalling the package.'));
160
+ process.exit(1);
161
+ }
162
+
163
+ // Read available skills
164
+ const skillDirs = fs
165
+ .readdirSync(skillsSourceDir, { withFileTypes: true })
166
+ .filter((d) => d.isDirectory() && fs.existsSync(path.join(skillsSourceDir, d.name, 'SKILL.md')))
167
+ .map((d) => d.name);
168
+
169
+ // Header
170
+ console.log(
171
+ boxen(
172
+ chalk.bold.cyan('BI Agent Superpowers') +
173
+ chalk.gray(` v${config.version}`) +
174
+ '\n' +
175
+ chalk.gray('Multi-agent skill installer'),
176
+ {
177
+ padding: 1,
178
+ borderStyle: 'round',
179
+ borderColor: 'cyan',
180
+ }
181
+ )
182
+ );
183
+
184
+ console.log(chalk.gray(` Install path: ~/${UNIVERSAL_DIR}/`));
185
+ console.log(chalk.gray(` Skills: ${skillDirs.length} available\n`));
186
+
187
+ // Determine which agents to install for
188
+ let selectedAgents;
189
+
190
+ if (isAll) {
191
+ selectedAgents = Object.keys(AGENTS);
192
+ } else if (agentFlags.length > 0) {
193
+ selectedAgents = agentFlags.filter((a) => AGENTS[a]);
194
+ const unknown = agentFlags.filter((a) => !AGENTS[a]);
195
+ if (unknown.length > 0) {
196
+ console.log(chalk.yellow(` Unknown agents: ${unknown.join(', ')}`));
197
+ console.log(chalk.gray(` Available: ${Object.keys(AGENTS).join(', ')}\n`));
198
+ }
199
+ } else if (isYes) {
200
+ selectedAgents = Object.keys(AGENTS);
201
+ } else {
202
+ // Interactive mode: detect and ask
203
+ const detected = detectAgents(baseDir);
204
+
205
+ console.log(chalk.cyan(' Select agents to install for:\n'));
206
+
207
+ const items = Object.entries(AGENTS).map(([id, agent]) => ({
208
+ id,
209
+ name: detected.includes(id) ? `${agent.name} ${chalk.green('(detected)')}` : agent.name,
210
+ }));
211
+
212
+ const rl = createReadline();
213
+ try {
214
+ selectedAgents = await selectMultiple(rl, items, detected);
215
+ } finally {
216
+ rl.close();
217
+ }
218
+ }
219
+
220
+ if (selectedAgents.length === 0) {
221
+ console.log(chalk.yellow('\n No agents selected. Nothing to install.'));
222
+ return;
223
+ }
224
+
225
+ console.log(
226
+ chalk.cyan(`\n Installing ${skillDirs.length} skills for ${selectedAgents.length} agents...\n`)
227
+ );
228
+
229
+ // Always install to universal path first
230
+ const universalTarget = path.join(baseDir, UNIVERSAL_DIR);
231
+ let installedCount = 0;
232
+
233
+ for (const skill of skillDirs) {
234
+ const src = path.join(skillsSourceDir, skill);
235
+ const dest = path.join(universalTarget, skill);
236
+ copySkillDir(src, dest);
237
+ installedCount++;
238
+ }
239
+
240
+ // List agents whose default dir is the universal path (e.g. Codex)
241
+ const universalAgents = selectedAgents
242
+ .filter((id) => AGENTS[id] && AGENTS[id].dir === UNIVERSAL_DIR)
243
+ .map((id) => AGENTS[id].name);
244
+ const universalSuffix = universalAgents.length > 0 ? ` — ${universalAgents.join(', ')}` : '';
245
+ console.log(chalk.green(` ✓ ${UNIVERSAL_DIR}/ (${installedCount} skills)${universalSuffix}`));
246
+
247
+ // Symlink agent-specific directories to universal path
248
+ const agentResults = [];
249
+ for (const agentId of selectedAgents) {
250
+ const agent = AGENTS[agentId];
251
+ if (agent.dir === UNIVERSAL_DIR) continue; // Already handled
252
+
253
+ const agentTarget = path.join(baseDir, agent.dir);
254
+
255
+ // If the directory already exists and is not a symlink, copy instead
256
+ if (fs.existsSync(agentTarget) && !fs.lstatSync(agentTarget).isSymbolicLink()) {
257
+ // Copy skills into existing directory
258
+ for (const skill of skillDirs) {
259
+ copySkillDir(path.join(skillsSourceDir, skill), path.join(agentTarget, skill));
260
+ }
261
+ agentResults.push({ agent: agent.name, method: 'copied', dir: agent.dir });
262
+ } else {
263
+ // Create symlink to universal directory
264
+ const parentDir = path.dirname(agentTarget);
265
+ if (!fs.existsSync(parentDir)) {
266
+ fs.mkdirSync(parentDir, { recursive: true });
267
+ }
268
+
269
+ // Remove existing symlink if present
270
+ if (fs.existsSync(agentTarget)) {
271
+ fs.unlinkSync(agentTarget);
272
+ }
273
+
274
+ try {
275
+ // Relative symlink from agent dir to universal dir
276
+ const relPath = path.relative(parentDir, universalTarget);
277
+ fs.symlinkSync(relPath, agentTarget);
278
+ agentResults.push({ agent: agent.name, method: 'symlinked', dir: agent.dir });
279
+ } catch (_e) {
280
+ // Fallback to copy if symlink fails (e.g. Windows without admin)
281
+ if (!fs.existsSync(agentTarget)) {
282
+ fs.mkdirSync(agentTarget, { recursive: true });
283
+ }
284
+ for (const skill of skillDirs) {
285
+ copySkillDir(path.join(skillsSourceDir, skill), path.join(agentTarget, skill));
286
+ }
287
+ agentResults.push({ agent: agent.name, method: 'copied', dir: agent.dir });
288
+ }
289
+ }
290
+ }
291
+
292
+ // Print results
293
+ for (const result of agentResults) {
294
+ const icon = result.method === 'symlinked' ? '→' : '✓';
295
+ console.log(chalk.green(` ${icon} ${result.dir}/ (${result.method}) — ${result.agent}`));
296
+ }
297
+
298
+ // Summary
299
+ const totalAgents = agentResults.length + 1; // +1 for universal
300
+ console.log(
301
+ boxen(
302
+ chalk.green.bold(`Installed ${installedCount} skills for ${totalAgents} agents`) +
303
+ '\n\n' +
304
+ chalk.gray('Skills are ready to use. Open your AI agent and start prompting.') +
305
+ '\n' +
306
+ chalk.gray('Example: "Help me write a DAX measure for YTD sales"'),
307
+ {
308
+ padding: 1,
309
+ margin: { top: 1 },
310
+ borderStyle: 'round',
311
+ borderColor: 'green',
312
+ }
313
+ )
314
+ );
315
+ }
316
+
317
+ module.exports = installCommand;
@@ -13,9 +13,11 @@ const path = require('path');
13
13
 
14
14
  const REMOTE_POWERBI_URL = 'https://api.fabric.microsoft.com/v1/mcp/powerbi';
15
15
  const FABRIC_MCP_PACKAGE = '@microsoft/fabric-mcp@latest';
16
+ const MICROSOFT_LEARN_URL = 'https://learn.microsoft.com/api/mcp';
16
17
  const MODELING_SERVER_NAME = 'powerbi-modeling-mcp';
17
18
  const REMOTE_SERVER_NAME = 'powerbi-remote';
18
19
  const FABRIC_SERVER_NAME = 'fabric-mcp-server';
20
+ const LEARN_SERVER_NAME = 'microsoft-learn';
19
21
  const ABSOLUTE_LAUNCHER_MODE = 'absolute';
20
22
  const PLUGIN_ROOT_LAUNCHER_MODE = 'plugin-root';
21
23
 
@@ -63,6 +65,10 @@ function createPluginMcpConfig(options = {}) {
63
65
  command: 'node',
64
66
  args: [launcherPath],
65
67
  },
68
+ [LEARN_SERVER_NAME]: {
69
+ type: 'http',
70
+ url: MICROSOFT_LEARN_URL,
71
+ },
66
72
  };
67
73
  }
68
74
 
@@ -166,9 +172,11 @@ module.exports = {
166
172
  PLUGIN_ROOT_LAUNCHER_MODE,
167
173
  REMOTE_POWERBI_URL,
168
174
  FABRIC_MCP_PACKAGE,
175
+ MICROSOFT_LEARN_URL,
169
176
  MODELING_SERVER_NAME,
170
177
  REMOTE_SERVER_NAME,
171
178
  FABRIC_SERVER_NAME,
179
+ LEARN_SERVER_NAME,
172
180
  resolveModelingLauncherPath,
173
181
  createPluginMcpConfig,
174
182
  createMcpConfigForFormat,
@@ -11,6 +11,7 @@ const {
11
11
  PLUGIN_ROOT_LAUNCHER_MODE,
12
12
  REMOTE_POWERBI_URL,
13
13
  FABRIC_MCP_PACKAGE,
14
+ MICROSOFT_LEARN_URL,
14
15
  createPluginMcpConfig,
15
16
  createMcpConfigForFormat,
16
17
  mergeMcpConfig,
@@ -58,6 +59,10 @@ describe('createPluginMcpConfig', () => {
58
59
  assert.strictEqual(config['powerbi-modeling-mcp'].type, 'stdio');
59
60
  assert.strictEqual(config['powerbi-modeling-mcp'].command, 'node');
60
61
  assert.ok(config['powerbi-modeling-mcp'].args[0].endsWith('powerbi-modeling-launcher.js'));
62
+ assert.deepStrictEqual(config['microsoft-learn'], {
63
+ type: 'http',
64
+ url: MICROSOFT_LEARN_URL,
65
+ });
61
66
  });
62
67
  });
63
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luquimbo/bi-superpowers",
3
- "version": "1.0.0",
3
+ "version": "1.1.2",
4
4
  "description": "Plugin-first Claude Code toolkit for Power BI, Microsoft Fabric, and Excel workflows powered by official Microsoft MCP servers.",
5
5
  "main": "bin/cli.js",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: "contributions"
3
3
  description: "Contributions Validation Skill: Contribution validation."
4
- version: "1.0.0"
4
+ version: "1.1.2"
5
5
  ---
6
6
 
7
7
  <!-- Generated by BI Agent Superpowers. Edit src/content/skills/contributions.md instead. -->
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: "data-model-design"
3
3
  description: "Use when the user asks about Data Model Design Skill, especially phrases like \"diseñar modelo de datos\", \"crear modelo Power BI\", \"arquitectura de datos\", \"empezar proyecto BI\", \"nuevo modelo semántico\"."
4
- version: "1.0.0"
4
+ version: "1.1.2"
5
5
  ---
6
6
 
7
7
  <!-- Generated by BI Agent Superpowers. Edit src/content/skills/data-model-design.md instead. -->