wizz-method 1.18.2 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +1 -1
- package/skills-registry.yaml +2 -11
- package/src/modules/lowticket/README.md +2 -2
- package/src/modules/lowticket/module.yaml +1 -1
- package/src/modules/lowticket/skills/lowticket-funil/SKILL.md +3 -3
- package/src/modules/lowticket/skills/lowticket-funil/references/copy-das-paginas.md +5 -3
- package/src/modules/lowticket/skills/lowticket-funil/references/mapa-do-funil.md +2 -0
- package/src/modules/lowticket/skills/lowticket-metodologia/SKILL.md +3 -3
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/03-campanha-bidcap.md +18 -0
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/04a-criativos-ia.md +47 -1
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/04b-criativos-formatos.md +33 -2
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/05-oferta.md +7 -4
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/06-pagina-vendas.md +10 -8
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/06a-instagram.md +9 -0
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/06b-player-vsl.md +79 -0
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/07-funil-upsell.md +61 -7
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/07a-copy-humanizacao.md +73 -0
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/09-especialista-coproducao.md +1 -1
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/11-checklist-roi.md +3 -3
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/12-mineracao-ofertas.md +64 -5
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/12a-mineracao-veredito.md +48 -2
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/12b-fabrica-de-ofertas.md +41 -94
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/12c-anatomia-low-ticket.md +111 -0
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/15-como-estender.md +5 -3
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/17-rastreamento.md +127 -0
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/18-copy-desejo-oferta.md +245 -0
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/INDEX.md +14 -7
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/guardrails.md +59 -5
- package/src/modules/lowticket/skills/lowticket-metodologia/knowledge/pontos-em-aberto.md +72 -11
- package/src/modules/lowticket/skills/lowticket-minerador/SKILL.md +6 -6
- package/src/modules/lowticket/skills/lowticket-minerador/references/rubrica.md +27 -2
- package/src/modules/lowticket/skills/lowticket-pagina/SKILL.md +5 -3
- package/src/modules/lowticket/skills/lowticket-pagina/references/metas-e-medicao.md +1 -0
- package/src/modules/lowticket/skills/lowticket-pagina/references/padroes-de-codigo.md +4 -0
- package/src/modules/lowticket/skills/lowticket-trafego/SKILL.md +2 -0
- package/src/modules/lowticket/skills/lowticket-trafego/references/reguas.md +4 -3
- package/src/modules/wizz/README.md +1 -1
- package/src/modules/wizz/_shared/model-ladder.md +2 -0
- package/src/modules/wizz/agents/wizz-ads/SKILL.md +3 -6
- package/src/modules/wizz/agents/wizz-ads/customize.toml +1 -8
- package/src/modules/wizz/agents/wizz-maestro/SKILL.md +1 -1
- package/src/modules/wizz/module.yaml +1 -1
- package/src/skills-lib/ad-creative/SKILL.md +1 -1
- package/src/skills-lib/paid-ads/SKILL.md +1 -1
- package/src/skills-lib/wizz-router/references/routing-table-flat.md +2 -5
- package/tools/installer/core/installer.js +20 -3
- package/tools/installer/modules/env-vars.js +41 -0
- package/tools/installer/modules/mcp-config.js +98 -14
- package/tools/installer/ui.js +6 -1
|
@@ -59,8 +59,7 @@ Use esta tabela pra mapear skills/CLIs/MCPs direto **fora de projeto Wizz** (sem
|
|
|
59
59
|
| Intenção / palavras-chave | Skills a oferecer | Prioridade |
|
|
60
60
|
|---|---|---|
|
|
61
61
|
| Ideias de marketing, estratégia de marketing, posicionamento | `marketing-ideas` + `marketing-psychology` + `product-marketing-context` | 1 |
|
|
62
|
-
| Paid ads, anúncios, Google Ads, Meta Ads, TikTok Ads, mídia paga | `paid-ads` + `ad-creative` + `analytics-tracking`
|
|
63
|
-
| Gestão de campanha Meta/Facebook/Instagram via API real | **MCP meta-ads** (`mcp-meta-ads`) direto | 1 |
|
|
62
|
+
| Paid ads, anúncios, Google Ads, Meta Ads, TikTok Ads, mídia paga | `paid-ads` + `ad-creative` + `analytics-tracking` | 1 |
|
|
64
63
|
| Pixel/UTM/atribuição erradas, "a venda não bate com o gerenciador", "onde está furando o funil", tráfego orgânico inflado, conferir tracking antes de subir campanha | `tracking-audit` (+ `analytics-tracking` se for SaaS/produto) | 1 |
|
|
65
64
|
| Lançamento de feature, lançamento de produto, go-to-market | `launch-strategy` + `social-content` + `email-sequence` | 1 |
|
|
66
65
|
| Site pronto pra subir, pré-lançamento de SITE, "revisa antes do deploy", checklist de go-live, ou item pontual pré-lançamento (og:image/prévia de link, FAQ com schema, robots.txt, LGPD, alt text) | `site-launch-kit` | 1 |
|
|
@@ -97,6 +96,4 @@ Quando nenhuma skill/MCP instalado cobrir o pedido, **classifique o que falta**
|
|
|
97
96
|
|
|
98
97
|
**Falta um MCP:** informe → `claude mcp list` → consulte `skills-registry.yaml` (`mcps:`/`mcp_utility:`, com `server` pronto) → proponha `claude mcp add <id> [-e VAR=$VAR] -- <command> [args]`. Secrets sempre via env/placeholder, nunca token real.
|
|
99
98
|
|
|
100
|
-
MCPs comuns: context7 (docs de libs), supabase (Postgres),
|
|
101
|
-
|
|
102
|
-
Para paid ads Meta, o MCP `mcp-meta-ads` dá acesso real à API Meta Marketing (campanhas, ad sets, ads, métricas, criativos). Combine com `paid-ads` + `ad-creative` + `analytics-tracking`. O `META_ACCESS_TOKEN` vem de env local: nunca exponha em logs ou código commitado.
|
|
99
|
+
MCPs comuns: context7 (docs de libs), supabase (Postgres), exa (pesquisa). Browser/E2E é sempre via CLI `agent-browser`, nunca via MCP Playwright.
|
|
@@ -4,7 +4,7 @@ const { Manifest } = require('./manifest');
|
|
|
4
4
|
const { OfficialModules } = require('../modules/official-modules');
|
|
5
5
|
const { installSkillsLib } = require('../modules/skills-lib');
|
|
6
6
|
const { writeMcpConfig, renderAddCommand, prepareMcps, partitionAlreadyConfigured } = require('../modules/mcp-config');
|
|
7
|
-
const { promptMissingEnvVars } = require('../modules/env-vars');
|
|
7
|
+
const { promptMissingEnvVars, mcpsWithMissingRequiredEnv } = require('../modules/env-vars');
|
|
8
8
|
const { installClis, renderInstallCommand } = require('../modules/cli-config');
|
|
9
9
|
const { writeDepsCache, readPreviousMcpPins } = require('../modules/deps-cache');
|
|
10
10
|
const { IdeManager } = require('../ide/manager');
|
|
@@ -423,7 +423,7 @@ class Installer {
|
|
|
423
423
|
// is still cheap for an already-installed binary: prepareMcp is
|
|
424
424
|
// detect-first, so only a genuinely missing binary pays for the
|
|
425
425
|
// network-heavy install/post_install steps.
|
|
426
|
-
|
|
426
|
+
let { ready: mcpsReady, failed: mcpsFailed } = await prepareMcps({ mcps: toWrite });
|
|
427
427
|
for (const f of mcpsFailed) {
|
|
428
428
|
await prompts.log.warn(
|
|
429
429
|
`MCP ${f.id} não pôde ser preparado (${f.error}). Config NÃO escrita para evitar ENOENT — instale manualmente e adicione depois com \`claude mcp add\`.`,
|
|
@@ -451,10 +451,27 @@ class Installer {
|
|
|
451
451
|
mcps: mcpsReady,
|
|
452
452
|
});
|
|
453
453
|
const envInteractive = !config.skipPrompts && !!process.stdin.isTTY;
|
|
454
|
-
await promptMissingEnvVars(mcpsForEnvVars, {
|
|
454
|
+
const envResult = await promptMissingEnvVars(mcpsForEnvVars, {
|
|
455
455
|
projectDir: paths.projectRoot,
|
|
456
456
|
interactive: envInteractive,
|
|
457
457
|
});
|
|
458
|
+
|
|
459
|
+
// A required (no-default) var that stayed unresolved means
|
|
460
|
+
// the server would be written with a permanently-broken
|
|
461
|
+
// literal `${VAR}` — never write it (E1: never fail the
|
|
462
|
+
// install, just drop that server and tell the user how to
|
|
463
|
+
// retry).
|
|
464
|
+
const missingEnv = mcpsWithMissingRequiredEnv(mcpsReady, envResult.skipped);
|
|
465
|
+
if (missingEnv.length > 0) {
|
|
466
|
+
const missingIds = new Set(missingEnv.map((m) => m.id));
|
|
467
|
+
mcpsReady = mcpsReady.filter((m) => !missingIds.has(m.id));
|
|
468
|
+
for (const m of missingEnv) {
|
|
469
|
+
await prompts.log.warn(
|
|
470
|
+
`MCP ${m.id} não gravado: faltou ${m.missing.join(', ')}. Rode o installer de novo quando tiver a chave, ou adicione com \`claude mcp add\`.`,
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
addResult('MCP servers', 'warn', `não gravados por falta de env var: ${missingEnv.map((m) => m.id).join(', ')}`);
|
|
474
|
+
}
|
|
458
475
|
} catch (error) {
|
|
459
476
|
await prompts.log.warn(`Falha ao configurar env vars dos MCPs: ${error.message}`);
|
|
460
477
|
addResult('MCP env vars', 'warn', error.message);
|
|
@@ -589,9 +589,50 @@ async function promptMissingEnvVars(mcps, opts = {}) {
|
|
|
589
589
|
};
|
|
590
590
|
}
|
|
591
591
|
|
|
592
|
+
/**
|
|
593
|
+
* Find which of `mcps` have at least one REQUIRED (`hasDefault: false`) env
|
|
594
|
+
* placeholder that stayed unresolved, per the `skipped` list returned by
|
|
595
|
+
* `promptMissingEnvVars`/`resolveEnvVars`. A var WITH a default
|
|
596
|
+
* (`hasDefault: true`) is fine even when skipped — the Claude Code runtime
|
|
597
|
+
* resolves `${VAR:-default}` itself — so only `hasDefault: false` entries
|
|
598
|
+
* count here.
|
|
599
|
+
*
|
|
600
|
+
* Writing a server whose required placeholder never resolved to anywhere
|
|
601
|
+
* (not `process.env`, not `.env`, not the global store, not typed
|
|
602
|
+
* interactively) would embed a literal, permanently-broken `${VAR}` into
|
|
603
|
+
* `.mcp.json`: the server sits in the config but can never actually start.
|
|
604
|
+
* Callers use this to drop such a server from the write instead. Pure: no
|
|
605
|
+
* I/O.
|
|
606
|
+
*
|
|
607
|
+
* @param {Array<{id: string}>} mcps - Resolved MCP entries to check
|
|
608
|
+
* @param {Array<{name: string, mcpIds: string[], hasDefault: boolean}>} [skipped]
|
|
609
|
+
* - The `skipped` array from `promptMissingEnvVars`/`resolveEnvVars`
|
|
610
|
+
* @returns {Array<{id: string, missing: string[]}>} One entry per affected
|
|
611
|
+
* MCP id, with the names of its unresolved required vars (in encounter order)
|
|
612
|
+
*/
|
|
613
|
+
function mcpsWithMissingRequiredEnv(mcps, skipped) {
|
|
614
|
+
const missingByMcpId = new Map();
|
|
615
|
+
for (const entry of skipped || []) {
|
|
616
|
+
if (!entry || entry.hasDefault) continue;
|
|
617
|
+
for (const id of entry.mcpIds || []) {
|
|
618
|
+
if (!missingByMcpId.has(id)) missingByMcpId.set(id, []);
|
|
619
|
+
missingByMcpId.get(id).push(entry.name);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
const result = [];
|
|
624
|
+
for (const mcp of mcps || []) {
|
|
625
|
+
if (mcp && mcp.id && missingByMcpId.has(mcp.id)) {
|
|
626
|
+
result.push({ id: mcp.id, missing: missingByMcpId.get(mcp.id) });
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return result;
|
|
630
|
+
}
|
|
631
|
+
|
|
592
632
|
module.exports = {
|
|
593
633
|
extractEnvPlaceholders,
|
|
594
634
|
resolveEnvVars,
|
|
635
|
+
mcpsWithMissingRequiredEnv,
|
|
595
636
|
persistEnvValues,
|
|
596
637
|
persistProjectEnv,
|
|
597
638
|
persistGlobalEnv,
|
|
@@ -326,25 +326,101 @@ async function partitionAlreadyConfigured({ projectDir, mcps }) {
|
|
|
326
326
|
return { toPrepare, alreadyConfigured };
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
+
/**
|
|
330
|
+
* Resolve the set of MCP ids covered by an installed Claude Code plugin
|
|
331
|
+
* (`~/.claude/plugins/installed_plugins.json`). A plugin key in that file's
|
|
332
|
+
* `plugins` map is `<name>@<marketplace>` (e.g.
|
|
333
|
+
* `supabase@claude-plugins-official`); the plugin covers catalog MCP id
|
|
334
|
+
* `<name>`. If the plugin ships its own `.mcp.json`
|
|
335
|
+
* (`<installPath>/.mcp.json`, `installPath` from the plugin's install
|
|
336
|
+
* record) with an `mcpServers` block, every key in that block is ALSO
|
|
337
|
+
* covered (e.g. the `vercel` plugin ships a server named `vercel`).
|
|
338
|
+
*
|
|
339
|
+
* Read failures at the top level (missing/malformed
|
|
340
|
+
* `installed_plugins.json`) fall back to "nothing covered", same spirit as
|
|
341
|
+
* the `~/.claude.json` handling in `partitionGloballyConfigured`. A failure
|
|
342
|
+
* reading ONE plugin's own `.mcp.json` (missing `installPath`, missing
|
|
343
|
+
* file, malformed JSON) only skips that plugin's extra ids — the plugin's
|
|
344
|
+
* own name stays covered, since that didn't require reading anything past
|
|
345
|
+
* the already-parsed top-level file.
|
|
346
|
+
*
|
|
347
|
+
* @param {string} [installedPluginsPath] - Override of
|
|
348
|
+
* `~/.claude/plugins/installed_plugins.json` (tests)
|
|
349
|
+
* @returns {Promise<Set<string>>}
|
|
350
|
+
*/
|
|
351
|
+
async function resolvePluginCoveredIds(installedPluginsPath) {
|
|
352
|
+
const file = installedPluginsPath || path.join(os.homedir(), '.claude', 'plugins', 'installed_plugins.json');
|
|
353
|
+
const ids = new Set();
|
|
354
|
+
|
|
355
|
+
if (!(await fs.pathExists(file))) return ids;
|
|
356
|
+
|
|
357
|
+
let data;
|
|
358
|
+
try {
|
|
359
|
+
data = JSON.parse(await fs.readFile(file, 'utf8'));
|
|
360
|
+
} catch {
|
|
361
|
+
return ids;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const plugins = data && typeof data === 'object' && data.plugins && typeof data.plugins === 'object' ? data.plugins : null;
|
|
365
|
+
if (!plugins) return ids;
|
|
366
|
+
|
|
367
|
+
for (const [key, entries] of Object.entries(plugins)) {
|
|
368
|
+
const name = String(key).split('@')[0];
|
|
369
|
+
if (name) ids.add(name);
|
|
370
|
+
|
|
371
|
+
if (!Array.isArray(entries)) continue;
|
|
372
|
+
for (const entry of entries) {
|
|
373
|
+
const installPath = entry && entry.installPath;
|
|
374
|
+
if (!installPath || typeof installPath !== 'string') continue;
|
|
375
|
+
|
|
376
|
+
const mcpJsonPath = path.join(installPath, '.mcp.json');
|
|
377
|
+
try {
|
|
378
|
+
if (!(await fs.pathExists(mcpJsonPath))) continue;
|
|
379
|
+
const mcpConfig = JSON.parse(await fs.readFile(mcpJsonPath, 'utf8'));
|
|
380
|
+
const servers =
|
|
381
|
+
mcpConfig && typeof mcpConfig === 'object' && mcpConfig.mcpServers && !Array.isArray(mcpConfig.mcpServers)
|
|
382
|
+
? mcpConfig.mcpServers
|
|
383
|
+
: null;
|
|
384
|
+
if (servers) {
|
|
385
|
+
for (const serverKey of Object.keys(servers)) ids.add(serverKey);
|
|
386
|
+
}
|
|
387
|
+
} catch {
|
|
388
|
+
// Malformed/unreadable plugin .mcp.json: skip its extra ids, the
|
|
389
|
+
// plugin's own name (added above) stays covered.
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return ids;
|
|
395
|
+
}
|
|
396
|
+
|
|
329
397
|
/**
|
|
330
398
|
* Split resolved MCP entries into those still worth offering/installing in
|
|
331
|
-
* the project and those the user already
|
|
332
|
-
* `mcpServers` key of `~/.claude.json`)
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
399
|
+
* the project and those the user already has covered elsewhere: configured
|
|
400
|
+
* GLOBALLY (user scope, the `mcpServers` key of `~/.claude.json`), or
|
|
401
|
+
* covered by an installed Claude Code PLUGIN
|
|
402
|
+
* (`~/.claude/plugins/installed_plugins.json`, see
|
|
403
|
+
* `resolvePluginCoveredIds`). Either way, the server is already live —
|
|
404
|
+
* usually with the real key embedded — so writing the registry's
|
|
405
|
+
* `${VAR}`-placeholder copy into the project `.mcp.json` would at best
|
|
406
|
+
* duplicate it and at worst shadow a working config with a broken
|
|
407
|
+
* placeholder one, then prompt the user for a key they already have.
|
|
337
408
|
*
|
|
338
|
-
* Read failures (missing/malformed `~/.claude.json`
|
|
339
|
-
*
|
|
409
|
+
* Read failures (missing/malformed `~/.claude.json` or
|
|
410
|
+
* `installed_plugins.json`) fall back to "nothing is global"/"nothing is
|
|
411
|
+
* plugin-covered", the safe default: worst case the user sees the old
|
|
412
|
+
* behavior. An id present in BOTH sources is reported once, in
|
|
413
|
+
* `globallyConfigured` only (never duplicated into `pluginCovered`).
|
|
340
414
|
*
|
|
341
415
|
* @param {Object} args
|
|
342
416
|
* @param {Array<{id: string}>} args.mcps - Resolved MCP entries to partition
|
|
343
417
|
* @param {string} [args.claudeJsonPath] - Override of `~/.claude.json` (tests)
|
|
344
|
-
* @
|
|
418
|
+
* @param {string} [args.installedPluginsPath] - Override of
|
|
419
|
+
* `~/.claude/plugins/installed_plugins.json` (tests)
|
|
420
|
+
* @returns {Promise<{toInstall: Array<Object>, globallyConfigured: string[], pluginCovered: string[]}>}
|
|
345
421
|
*/
|
|
346
|
-
async function partitionGloballyConfigured({ mcps, claudeJsonPath }) {
|
|
347
|
-
if (!mcps || mcps.length === 0) return { toInstall: [], globallyConfigured: [] };
|
|
422
|
+
async function partitionGloballyConfigured({ mcps, claudeJsonPath, installedPluginsPath }) {
|
|
423
|
+
if (!mcps || mcps.length === 0) return { toInstall: [], globallyConfigured: [], pluginCovered: [] };
|
|
348
424
|
|
|
349
425
|
const file = claudeJsonPath || path.join(os.homedir(), '.claude.json');
|
|
350
426
|
let globalIds = new Set();
|
|
@@ -359,13 +435,21 @@ async function partitionGloballyConfigured({ mcps, claudeJsonPath }) {
|
|
|
359
435
|
}
|
|
360
436
|
}
|
|
361
437
|
|
|
438
|
+
const pluginIds = await resolvePluginCoveredIds(installedPluginsPath);
|
|
439
|
+
|
|
362
440
|
const toInstall = [];
|
|
363
441
|
const globallyConfigured = [];
|
|
442
|
+
const pluginCovered = [];
|
|
364
443
|
for (const mcp of mcps) {
|
|
365
|
-
if (mcp && mcp.id && globalIds.has(mcp.id))
|
|
366
|
-
|
|
444
|
+
if (mcp && mcp.id && globalIds.has(mcp.id)) {
|
|
445
|
+
globallyConfigured.push(mcp.id);
|
|
446
|
+
} else if (mcp && mcp.id && pluginIds.has(mcp.id)) {
|
|
447
|
+
pluginCovered.push(mcp.id);
|
|
448
|
+
} else {
|
|
449
|
+
toInstall.push(mcp);
|
|
450
|
+
}
|
|
367
451
|
}
|
|
368
|
-
return { toInstall, globallyConfigured };
|
|
452
|
+
return { toInstall, globallyConfigured, pluginCovered };
|
|
369
453
|
}
|
|
370
454
|
|
|
371
455
|
/**
|
package/tools/installer/ui.js
CHANGED
|
@@ -629,9 +629,14 @@ class UI {
|
|
|
629
629
|
// duplicate config and re-prompt for a key that already works. Filter it
|
|
630
630
|
// out of every path below (multiselect, --mcps, --yes) with an info line
|
|
631
631
|
// so nothing disappears silently.
|
|
632
|
-
const { toInstall, globallyConfigured } = await partitionGloballyConfigured({ mcps: resolved });
|
|
632
|
+
const { toInstall, globallyConfigured, pluginCovered } = await partitionGloballyConfigured({ mcps: resolved });
|
|
633
633
|
if (globallyConfigured.length > 0) {
|
|
634
634
|
await prompts.log.info(`MCPs já configurados no seu Claude global (~/.claude.json), pulados: ${globallyConfigured.join(', ')}`);
|
|
635
|
+
}
|
|
636
|
+
if (pluginCovered.length > 0) {
|
|
637
|
+
await prompts.log.info(`MCPs já cobertos por plugin do Claude Code (user scope), pulados: ${pluginCovered.join(', ')}`);
|
|
638
|
+
}
|
|
639
|
+
if (globallyConfigured.length > 0 || pluginCovered.length > 0) {
|
|
635
640
|
resolved = toInstall;
|
|
636
641
|
if (resolved.length === 0) return { toWrite: [], toRecommend: [] };
|
|
637
642
|
}
|