wizz-method 2.18.0 → 2.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/package.json +5 -3
- package/removals.txt +10 -0
- package/skills-registry.yaml +50 -38
- package/src/bmm-skills/1-analysis/wizz-set-feature/SKILL.md +9 -9
- package/src/bmm-skills/4-implementation/wizz-create-story/SKILL.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-dev-story/SKILL.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-qa-generate-e2e-tests/SKILL.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-qa-generate-e2e-tests/checklist.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-quick-dev/SKILL.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-sprint-status/SKILL.md +5 -5
- package/src/bmm-skills/module-help.csv +1 -1
- package/src/bmm-skills/module.yaml +1 -1
- package/src/core-skills/_shared/handoff-protocol.md +2 -2
- package/src/modules/lowticket/skills/wizz-lowticket-funil/SKILL.md +1 -1
- package/src/modules/lowticket/skills/wizz-lowticket-guia/SKILL.md +1 -1
- package/src/modules/lowticket/skills/wizz-lowticket-metodologia/SKILL.md +1 -1
- package/src/modules/lowticket/skills/wizz-lowticket-minerador/SKILL.md +1 -1
- package/src/modules/lowticket/skills/wizz-lowticket-pagina/SKILL.md +1 -1
- package/src/modules/lowticket/skills/wizz-lowticket-trafego/SKILL.md +1 -1
- package/src/modules/wizz/_shared/cerebro.md +7 -7
- package/src/modules/wizz/_shared/communication-rules.md +1 -1
- package/src/modules/wizz/_shared/encerramento.md +4 -3
- package/src/modules/wizz/_shared/organizacao.md +8 -4
- package/src/modules/wizz/_shared/token-economy.md +1 -1
- package/src/modules/wizz/_shared/video-pipeline.md +4 -4
- package/src/modules/wizz/agents/wizz-ads/SKILL.md +4 -1
- package/src/modules/wizz/agents/wizz-ads/customize.toml +12 -3
- package/src/modules/wizz/agents/wizz-ads/knowledge/playbook.md +36 -0
- package/src/modules/wizz/agents/wizz-copy/SKILL.md +4 -1
- package/src/modules/wizz/agents/wizz-copy/customize.toml +2 -3
- package/src/modules/wizz/agents/wizz-copy/knowledge/playbook.md +34 -0
- package/src/modules/wizz/agents/wizz-designer/SKILL.md +2 -2
- package/src/modules/wizz/agents/wizz-designer/customize.toml +2 -3
- package/src/modules/wizz/agents/wizz-growth/SKILL.md +4 -1
- package/src/modules/wizz/agents/wizz-growth/customize.toml +33 -4
- package/src/modules/wizz/agents/wizz-growth/knowledge/playbook.md +39 -0
- package/src/modules/wizz/agents/wizz-maestro/SKILL.md +6 -8
- package/src/modules/wizz/agents/wizz-maestro/customize.toml +2 -3
- package/src/modules/wizz/agents/wizz-memoria/SKILL.md +7 -7
- package/src/modules/wizz/agents/wizz-memoria/customize.toml +5 -6
- package/src/modules/wizz/agents/wizz-qa/SKILL.md +5 -6
- package/src/modules/wizz/agents/wizz-qa/customize.toml +3 -4
- package/src/modules/wizz/agents/wizz-seo/SKILL.md +4 -1
- package/src/modules/wizz/agents/wizz-seo/customize.toml +2 -3
- package/src/modules/wizz/agents/wizz-seo/knowledge/playbook.md +31 -0
- package/src/modules/wizz/agents/wizz-social/SKILL.md +3 -3
- package/src/modules/wizz/agents/wizz-social/customize.toml +2 -3
- package/src/modules/wizz/overrides/wizz-agent-analyst.toml +2 -2
- package/src/modules/wizz/overrides/wizz-agent-architect.toml +3 -3
- package/src/modules/wizz/overrides/wizz-agent-dev.toml +3 -3
- package/src/modules/wizz/overrides/wizz-agent-pm.toml +2 -2
- package/src/modules/wizz/overrides/wizz-agent-tech-writer.toml +2 -2
- package/src/modules/wizz/overrides/wizz-agent-ux-designer.toml +2 -2
- package/src/skills-lib/_shared/complexity-signal.md +8 -9
- package/src/skills-lib/_shared/dispatch-rule.yaml +21 -0
- package/src/skills-lib/{cerebro → wizz-cerebro}/SKILL.md +1 -1
- package/src/skills-lib/{ctc-align → wizz-ctc-align}/SKILL.md +1 -1
- package/src/skills-lib/{enhance-prompt → wizz-enhance-prompt}/SKILL.md +1 -1
- package/src/skills-lib/{find-skills → wizz-find-skills}/SKILL.md +1 -1
- package/src/skills-lib/wizz-huashu-design/references/sfx-library.md +1 -1
- package/src/skills-lib/wizz-huashu-design/scripts/add-music.sh +1 -1
- package/src/skills-lib/wizz-huashu-design/scripts/html2pptx.js +45 -37
- package/src/skills-lib/wizz-huashu-design/scripts/mix-voiceover.sh +1 -1
- package/src/skills-lib/wizz-huashu-design/scripts/narrate-pipeline.mjs +11 -5
- package/src/skills-lib/wizz-huashu-design/scripts/test_scripts.py +209 -0
- package/src/skills-lib/wizz-huashu-design/scripts/tts-doubao.mjs +42 -28
- package/src/skills-lib/wizz-ig-profile-optimizer/SKILL.md +1 -1
- package/src/skills-lib/wizz-inicio-de-projeto/SKILL.md +1 -1
- package/src/skills-lib/wizz-launch-readiness/SKILL.md +7 -7
- package/src/skills-lib/wizz-launch-readiness/references/02-seguranca.md +3 -3
- package/src/skills-lib/wizz-launch-readiness/references/03-seo-descoberta.md +5 -5
- package/src/skills-lib/wizz-launch-readiness/references/04-analytics-medicao.md +1 -1
- package/src/skills-lib/wizz-launch-readiness/references/05-conteudo-prova-social.md +6 -6
- package/src/skills-lib/wizz-launch-readiness/references/06-legal-lgpd.md +1 -1
- package/src/skills-lib/wizz-launch-readiness/references/08-fusao-priorizacao.md +1 -1
- package/src/skills-lib/wizz-offer-forge/SKILL.md +3 -3
- package/src/skills-lib/{pesquisa-de-publico-do-piva → wizz-pesquisa-de-publico-do-piva}/README.md +1 -1
- package/src/skills-lib/{pesquisa-de-publico-do-piva → wizz-pesquisa-de-publico-do-piva}/SKILL.md +1 -1
- package/src/skills-lib/wizz-router/SKILL.md +3 -3
- package/src/skills-lib/wizz-router/references/routing-table-flat.md +9 -9
- package/src/skills-lib/{security-audit-pentest → wizz-security-audit-pentest}/SKILL.md +1 -1
- package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/SKILL.md +1 -1
- package/src/skills-lib/wizz-video-effects/SKILL.md +3 -3
- package/src/skills-lib/wizz-video-effects/references/data-contract.md +3 -3
- package/src/skills-lib/wizz-video-effects/scripts/fill_breaths.py +15 -1
- package/src/skills-lib/wizz-video-effects/scripts/test_fill_breaths.py +20 -0
- package/src/skills-lib/wizz-video-styles/SKILL.md +2 -2
- package/src/skills-lib/wizz-video-styles/data/recipes.json +32 -1
- package/src/skills-lib/wizz-video-styles/data/references.json +211 -1
- package/src/skills-lib/wizz-video-styles/data/styles.json +54 -0
- package/src/skills-lib/wizz-video-styles/references/generated-prompts.md +13 -3
- package/src/skills-lib/wizz-video-styles/references/style-picker.md +4 -2
- package/src/skills-lib/wizz-video-styles/references/styles/ui-morph.md +68 -0
- package/src/skills-lib/wizz-video-styles/scripts/analyze.sh +21 -9
- package/src/skills-lib/wizz-video-styles/scripts/references.mjs +1 -0
- package/src/skills-lib/wizz-web-security/SKILL.md +1 -1
- package/tools/fetch-assets.mjs +1 -1
- package/tools/hooks/README.md +18 -14
- package/tools/hooks/rtk-rewrite.js +95 -0
- package/tools/hooks/security-defensive-context.js +17 -1
- package/tools/hooks/session-rules.js +25 -5
- package/tools/hooks/wizz-arrumar.js +126 -12
- package/tools/hooks/wizz-artifact-guard.js +41 -7
- package/tools/hooks/wizz-cerebro-lib.js +239 -0
- package/tools/hooks/wizz-close-reminder.js +124 -0
- package/tools/hooks/wizz-debug-lib.js +55 -0
- package/tools/hooks/wizz-decision-trace.js +19 -2
- package/tools/hooks/wizz-feature.js +20 -4
- package/tools/hooks/wizz-router-enforce.js +30 -13
- package/tools/installer/command-text.js +243 -0
- package/tools/installer/commands/catalog.js +2 -0
- package/tools/installer/commands/doctor.js +10 -12
- package/tools/installer/commands/fetch-assets.js +5 -5
- package/tools/installer/commands/install.js +6 -7
- package/tools/installer/commands/resolve.js +17 -17
- package/tools/installer/commands/trace-report.js +40 -37
- package/tools/installer/core/doctor.js +60 -55
- package/tools/installer/core/hooks-settings.js +88 -14
- package/tools/installer/core/hooks-smoke.js +134 -0
- package/tools/installer/core/installer.js +61 -52
- package/tools/installer/core/quick-update.js +2 -3
- package/tools/installer/install-text.js +201 -0
- package/tools/installer/modules/channel-plan.js +2 -2
- package/tools/installer/modules/env-vars.js +5 -6
- package/tools/installer/modules/skills-lib.js +1 -1
- package/tools/installer/ui.js +17 -9
- /package/src/skills-lib/{cerebro → wizz-cerebro}/references/comandos-pesquisa-e-memoria.md +0 -0
- /package/src/skills-lib/{cerebro → wizz-cerebro}/references/comandos-rotina-e-captura.md +0 -0
- /package/src/skills-lib/{cerebro → wizz-cerebro}/references/comandos-sessao.md +0 -0
- /package/src/skills-lib/{ctc-align → wizz-ctc-align}/scripts/align.py +0 -0
- /package/src/skills-lib/{enhance-prompt → wizz-enhance-prompt}/README.md +0 -0
- /package/src/skills-lib/{enhance-prompt → wizz-enhance-prompt}/references/KEYWORDS.md +0 -0
- /package/src/skills-lib/{pesquisa-de-publico-do-piva → wizz-pesquisa-de-publico-do-piva}/assets/template.html +0 -0
- /package/src/skills-lib/{pesquisa-de-publico-do-piva → wizz-pesquisa-de-publico-do-piva}/prompts.md +0 -0
- /package/src/skills-lib/{security-audit-pentest → wizz-security-audit-pentest}/references/stage-1-validacao-entrada.md +0 -0
- /package/src/skills-lib/{security-audit-pentest → wizz-security-audit-pentest}/references/stage-2-autorizacao.md +0 -0
- /package/src/skills-lib/{security-audit-pentest → wizz-security-audit-pentest}/references/stage-3-abuso-volume.md +0 -0
- /package/src/skills-lib/{security-audit-pentest → wizz-security-audit-pentest}/references/stage-4-vazamento-resposta.md +0 -0
- /package/src/skills-lib/{security-audit-pentest → wizz-security-audit-pentest}/references/stage-5-fusao-plano.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/01-cta-principal.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/02-barra-fixa-mobile.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/03-tempo-de-resposta.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/04-prova-social.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/05-faq-decisao.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/06-imagens-reais.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/07-endereco-como-chegar.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/08-titles.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/09-open-graph.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/10-breadcrumbs.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/11-alt-text.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/12-schema-local.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/13-robots-sitemap.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/14-privacidade-termos.md +0 -0
- /package/src/skills-lib/{site-launch-kit → wizz-site-launch-kit}/references/15-medicao.md +0 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// hooks-smoke.js — o `wizz doctor` EXECUTA cada hook instalado em
|
|
2
|
+
// `_wizz/hooks/` com um payload mínimo válido (por evento) e reporta o que
|
|
3
|
+
// quebrou. Existe porque os hooks são fail-open: uma cópia parcial (lib
|
|
4
|
+
// faltando, arquivo corrompido) faz a feature sumir em silêncio, e checar só
|
|
5
|
+
// "o arquivo existe" não pega isso.
|
|
6
|
+
//
|
|
7
|
+
// Roda com WIZZ_DEBUG=1, então os erros que o hook engole (ver
|
|
8
|
+
// tools/hooks/wizz-debug-lib.js) chegam em stderr e entram no relatório.
|
|
9
|
+
// Nada é gravado: WIZZ_DEBUG_FILE aponta para o null device, WIZZ_TRACE fica
|
|
10
|
+
// vazio e o payload do artifact-guard usa um arquivo que não existe.
|
|
11
|
+
//
|
|
12
|
+
// Rápido de propósito: ~40 ms por hook, timeout curto, sem rede.
|
|
13
|
+
|
|
14
|
+
const os = require('node:os');
|
|
15
|
+
const path = require('node:path');
|
|
16
|
+
const { it } = require('../install-text');
|
|
17
|
+
const { HOOK_DEFS } = require('./hooks-settings');
|
|
18
|
+
|
|
19
|
+
const HOOK_TIMEOUT_MS = 4000;
|
|
20
|
+
|
|
21
|
+
// Falha ao carregar o código do próprio hook = feature morta. É o caso que o
|
|
22
|
+
// smoke existe para pegar, então vira error (o resto é warn).
|
|
23
|
+
const LOAD_FAILURE_RE = /require |Cannot find module|MODULE_NOT_FOUND|SyntaxError/;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Payload mínimo válido por hook (formato real que o Claude Code envia).
|
|
27
|
+
* @param {string} id - basename do hook
|
|
28
|
+
* @param {string} projectDir
|
|
29
|
+
* @returns {object}
|
|
30
|
+
*/
|
|
31
|
+
function probePayload(id, projectDir) {
|
|
32
|
+
const base = { cwd: projectDir };
|
|
33
|
+
switch (id) {
|
|
34
|
+
case 'session-rules.js': {
|
|
35
|
+
return { ...base, hook_event_name: 'SessionStart', source: 'startup' };
|
|
36
|
+
}
|
|
37
|
+
case 'wizz-router-enforce.js': {
|
|
38
|
+
return { ...base, hook_event_name: 'UserPromptSubmit', prompt: 'implementa a feature de login com testes e validação' };
|
|
39
|
+
}
|
|
40
|
+
case 'security-defensive-context.js': {
|
|
41
|
+
return { ...base, hook_event_name: 'PreToolUse', tool_name: 'Skill', tool_input: { skill: 'security-review' } };
|
|
42
|
+
}
|
|
43
|
+
case 'rtk-rewrite.sh':
|
|
44
|
+
case 'rtk-rewrite.js': {
|
|
45
|
+
return { ...base, hook_event_name: 'PreToolUse', tool_name: 'Bash', tool_input: { command: 'echo wizz-doctor' } };
|
|
46
|
+
}
|
|
47
|
+
case 'wizz-artifact-guard.js': {
|
|
48
|
+
return {
|
|
49
|
+
...base,
|
|
50
|
+
hook_event_name: 'PostToolUse',
|
|
51
|
+
tool_name: 'Write',
|
|
52
|
+
tool_input: { file_path: path.join(projectDir, '__wizz-doctor-probe__.txt'), content: '' },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
case 'wizz-decision-trace.js':
|
|
56
|
+
case 'wizz-close-reminder.js': {
|
|
57
|
+
return { ...base, hook_event_name: 'Stop', stop_hook_active: false };
|
|
58
|
+
}
|
|
59
|
+
default: {
|
|
60
|
+
return base;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Execução real de um hook. Injetável em `deps.runHookProcess` nos testes.
|
|
67
|
+
* @param {{file: string, kind: 'node'|'shell', payload: object, cwd: string}} args
|
|
68
|
+
* @returns {{status: number|null, stderr: string, error: string|null}}
|
|
69
|
+
*/
|
|
70
|
+
function defaultRunHookProcess({ file, kind, payload, cwd }) {
|
|
71
|
+
const { spawnSync } = require('node:child_process');
|
|
72
|
+
const [cmd, args] = kind === 'shell' ? ['bash', [file]] : [process.execPath, [file]];
|
|
73
|
+
const res = spawnSync(cmd, args, {
|
|
74
|
+
cwd,
|
|
75
|
+
input: JSON.stringify(payload),
|
|
76
|
+
encoding: 'utf8',
|
|
77
|
+
timeout: HOOK_TIMEOUT_MS,
|
|
78
|
+
env: { ...process.env, WIZZ_DEBUG: '1', WIZZ_DEBUG_FILE: os.devNull, WIZZ_TRACE: '', CLAUDE_PROJECT_DIR: cwd },
|
|
79
|
+
});
|
|
80
|
+
return { status: res.status, stderr: res.stderr || '', error: res.error ? res.error.message : null };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function debugLines(stderr) {
|
|
84
|
+
return String(stderr)
|
|
85
|
+
.split('\n')
|
|
86
|
+
.filter((line) => line.startsWith('[wizz-debug]'));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Executa cada hook instalado e classifica o resultado.
|
|
91
|
+
* @param {object} deps
|
|
92
|
+
* @param {string} deps.wizzDir
|
|
93
|
+
* @param {string} deps.projectDir
|
|
94
|
+
* @param {(p: string) => boolean} deps.fileExists
|
|
95
|
+
* @param {boolean} deps.rtkOnPath - sem rtk no PATH o rtk-rewrite.sh é pulado
|
|
96
|
+
* @param {Function} [deps.runHookProcess]
|
|
97
|
+
* @returns {{check: 'hooks-run', status: 'ok'|'warn'|'error', detail: string}}
|
|
98
|
+
*/
|
|
99
|
+
function checkHooksRun({ wizzDir, projectDir, fileExists, rtkOnPath, runHookProcess = defaultRunHookProcess }) {
|
|
100
|
+
const hooksDir = path.join(wizzDir, 'hooks');
|
|
101
|
+
const errors = [];
|
|
102
|
+
const warnings = [];
|
|
103
|
+
let ran = 0;
|
|
104
|
+
|
|
105
|
+
for (const def of HOOK_DEFS) {
|
|
106
|
+
if (def.requires === 'rtk' && !rtkOnPath) continue;
|
|
107
|
+
const file = path.join(hooksDir, def.id);
|
|
108
|
+
if (!fileExists(file)) continue; // ausência é do check `hooks`
|
|
109
|
+
ran++;
|
|
110
|
+
const res = runHookProcess({ file, kind: def.kind, payload: probePayload(def.id, projectDir), cwd: projectDir });
|
|
111
|
+
const lines = debugLines(res.stderr);
|
|
112
|
+
if (res.error || res.status !== 0) {
|
|
113
|
+
const why = res.error || `exit ${res.status}`;
|
|
114
|
+
const tail = String(res.stderr).trim().split('\n').slice(-2).join(' | ');
|
|
115
|
+
errors.push(it('hrBroke', { id: def.id, why, tail: tail ? `: ${tail}` : '' }));
|
|
116
|
+
} else if (lines.some((l) => LOAD_FAILURE_RE.test(l))) {
|
|
117
|
+
errors.push(it('hrNoLibs', { id: def.id, line: lines.find((l) => LOAD_FAILURE_RE.test(l)) }));
|
|
118
|
+
} else if (lines.length > 0) {
|
|
119
|
+
warnings.push(it('hrSwallowed', { id: def.id, line: lines[0].replace('[wizz-debug] ', '') }));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (errors.length > 0) {
|
|
124
|
+
return {
|
|
125
|
+
check: 'hooks-run',
|
|
126
|
+
status: 'error',
|
|
127
|
+
detail: `${errors.join('\n')}${warnings.length > 0 ? `\n${warnings.join('\n')}` : ''}\n${it('hrPartialCopy')}`,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if (warnings.length > 0) return { check: 'hooks-run', status: 'warn', detail: warnings.join('\n') };
|
|
131
|
+
return { check: 'hooks-run', status: 'ok', detail: it('hrOk', { n: ran }) };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
module.exports = { checkHooksRun, probePayload, defaultRunHookProcess, HOOK_TIMEOUT_MS };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { it } = require('../install-text');
|
|
1
2
|
const os = require('node:os');
|
|
2
3
|
const path = require('node:path');
|
|
3
4
|
const fs = require('../fs-native');
|
|
@@ -16,7 +17,7 @@ const { WIZZ_FOLDER_NAME } = require('../ide/shared/path-utils');
|
|
|
16
17
|
const { InstallPaths } = require('./install-paths');
|
|
17
18
|
const { ExternalModuleManager } = require('../modules/external-manager');
|
|
18
19
|
const { resolveModuleVersion } = require('../modules/version-resolver');
|
|
19
|
-
const { buildHookEntries, filterHooksRegisteredGlobally, mergeHooksIntoSettings } = require('./hooks-settings');
|
|
20
|
+
const { buildHookEntries, filterHooksRegisteredGlobally, mergeHooksIntoSettings, removeHooksFromSettings } = require('./hooks-settings');
|
|
20
21
|
|
|
21
22
|
const { ExistingInstall } = require('./existing-install');
|
|
22
23
|
const { warnPreNativeSkillsLegacy } = require('./legacy-warnings');
|
|
@@ -426,7 +427,7 @@ class Installer {
|
|
|
426
427
|
addResult('Resolved customizations', 'ok', `${resolvedCount} snapshot(s) → _wizz/_resolved/`);
|
|
427
428
|
}
|
|
428
429
|
} catch (error) {
|
|
429
|
-
await prompts.log.warn(
|
|
430
|
+
await prompts.log.warn(it('resolvedFail', { error: error.message }));
|
|
430
431
|
addResult('Resolved customizations', 'warn', error.message);
|
|
431
432
|
}
|
|
432
433
|
|
|
@@ -454,7 +455,7 @@ class Installer {
|
|
|
454
455
|
await prompts.log.warn(`Skills no registry sem pasta em skills-lib (ignoradas): ${result.skipped.join(', ')}`);
|
|
455
456
|
}
|
|
456
457
|
} catch (error) {
|
|
457
|
-
await prompts.log.warn(
|
|
458
|
+
await prompts.log.warn(it('globalSkillsFail', { error: error.message }));
|
|
458
459
|
addResult('Global skills', 'warn', error.message);
|
|
459
460
|
}
|
|
460
461
|
|
|
@@ -480,12 +481,10 @@ class Installer {
|
|
|
480
481
|
// network-heavy install/post_install steps.
|
|
481
482
|
let { ready: mcpsReady, failed: mcpsFailed } = await prepareMcps({ mcps: toWrite });
|
|
482
483
|
for (const f of mcpsFailed) {
|
|
483
|
-
await prompts.log.warn(
|
|
484
|
-
`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\`.`,
|
|
485
|
-
);
|
|
484
|
+
await prompts.log.warn(it('mcpPrepareFail', { id: f.id, error: f.error }));
|
|
486
485
|
}
|
|
487
486
|
if (mcpsFailed.length > 0) {
|
|
488
|
-
addResult('MCP servers', 'warn',
|
|
487
|
+
addResult('MCP servers', 'warn', it('failedList', { list: mcpsFailed.map((f) => f.id).join(', ') }));
|
|
489
488
|
}
|
|
490
489
|
|
|
491
490
|
// Env var assistance (3.3, design em _audit parte 3 seção E):
|
|
@@ -521,14 +520,12 @@ class Installer {
|
|
|
521
520
|
const missingIds = new Set(missingEnv.map((m) => m.id));
|
|
522
521
|
mcpsReady = mcpsReady.filter((m) => !missingIds.has(m.id));
|
|
523
522
|
for (const m of missingEnv) {
|
|
524
|
-
await prompts.log.warn(
|
|
525
|
-
`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\`.`,
|
|
526
|
-
);
|
|
523
|
+
await prompts.log.warn(it('mcpNotWritten', { id: m.id, missing: m.missing.join(', ') }));
|
|
527
524
|
}
|
|
528
|
-
addResult('MCP servers', 'warn',
|
|
525
|
+
addResult('MCP servers', 'warn', it('mcpMissingEnv', { list: missingEnv.map((m) => m.id).join(', ') }));
|
|
529
526
|
}
|
|
530
527
|
} catch (error) {
|
|
531
|
-
await prompts.log.warn(
|
|
528
|
+
await prompts.log.warn(it('mcpEnvFail', { error: error.message }));
|
|
532
529
|
addResult('MCP env vars', 'warn', error.message);
|
|
533
530
|
}
|
|
534
531
|
|
|
@@ -558,34 +555,30 @@ class Installer {
|
|
|
558
555
|
}
|
|
559
556
|
const pinUpdated = mcpResult.pinUpdated || [];
|
|
560
557
|
if (pinUpdated.length > 0) {
|
|
561
|
-
await prompts.log.info(
|
|
562
|
-
|
|
563
|
-
);
|
|
564
|
-
addResult('MCP servers', 'ok', `pin atualizado: ${pinUpdated.map((u) => u.id).join(', ')}`);
|
|
558
|
+
await prompts.log.info(it('mcpPinUpdated', { list: pinUpdated.map((u) => u.id).join(', ') }));
|
|
559
|
+
addResult('MCP servers', 'ok', it('mcpPinUpdatedShort', { list: pinUpdated.map((u) => u.id).join(', ') }));
|
|
565
560
|
}
|
|
566
561
|
const pinCustomized = mcpResult.pinCustomized || [];
|
|
567
562
|
if (pinCustomized.length > 0) {
|
|
568
|
-
await prompts.log.warn(
|
|
569
|
-
`Há atualização de pin disponível para ${pinCustomized.map((c) => c.id).join(', ')}, mas o bloco no .mcp.json foi customizado (diferente do que o installer escreveu) — mantido intacto. Atualize manualmente se quiser o pin novo.`,
|
|
570
|
-
);
|
|
563
|
+
await prompts.log.warn(it('mcpPinCustomized', { list: pinCustomized.map((c) => c.id).join(', ') }));
|
|
571
564
|
}
|
|
572
565
|
if (mcpResult.skipped.length > 0) {
|
|
573
|
-
await prompts.log.info(
|
|
566
|
+
await prompts.log.info(it('mcpKept', { list: mcpResult.skipped.join(', ') }));
|
|
574
567
|
}
|
|
575
568
|
}
|
|
576
569
|
const toRecommend = mcpPlan.toRecommend || [];
|
|
577
570
|
if (toRecommend.length > 0) {
|
|
578
571
|
const lines = toRecommend.map((m) => ` ${renderAddCommand(m)}`).join('\n');
|
|
579
|
-
await prompts.log.info(
|
|
572
|
+
await prompts.log.info(it('mcpRecommend', { lines }));
|
|
580
573
|
}
|
|
581
574
|
// Remind only when a written server expects secrets the user must fill.
|
|
582
575
|
const needsSecrets = toWrite.filter((m) => m.server && m.server.env && Object.keys(m.server.env).length > 0);
|
|
583
576
|
if (needsSecrets.length > 0) {
|
|
584
577
|
const vars = [...new Set(needsSecrets.flatMap((m) => Object.values(m.server.env)))];
|
|
585
|
-
await prompts.log.warn(
|
|
578
|
+
await prompts.log.warn(it('mcpDefineEnv', { list: vars.join(', ') }));
|
|
586
579
|
}
|
|
587
580
|
} catch (error) {
|
|
588
|
-
await prompts.log.warn(
|
|
581
|
+
await prompts.log.warn(it('mcpFail', { error: error.message }));
|
|
589
582
|
addResult('MCP servers', 'warn', error.message);
|
|
590
583
|
}
|
|
591
584
|
|
|
@@ -599,37 +592,41 @@ class Installer {
|
|
|
599
592
|
try {
|
|
600
593
|
const alreadyInstalled = cliPlan.alreadyInstalled || [];
|
|
601
594
|
if (alreadyInstalled.length > 0) {
|
|
602
|
-
await prompts.log.info(
|
|
595
|
+
await prompts.log.info(it('cliKept', { list: alreadyInstalled.map((c) => c.id).join(', ') }));
|
|
603
596
|
}
|
|
604
597
|
const toInstall = cliPlan.toInstall || [];
|
|
605
598
|
if (toInstall.length > 0) {
|
|
606
599
|
message('Installing CLIs...');
|
|
607
600
|
const cliResult = await installClis({ clis: toInstall });
|
|
608
601
|
if (cliResult.installed.length > 0) {
|
|
609
|
-
addResult('CLIs', 'ok',
|
|
602
|
+
addResult('CLIs', 'ok', it('installedList', { list: cliResult.installed.join(', ') }));
|
|
610
603
|
}
|
|
611
604
|
for (const f of cliResult.failed) {
|
|
612
605
|
await prompts.log.warn(
|
|
613
|
-
|
|
606
|
+
it('cliInstallFail', {
|
|
607
|
+
id: f.id,
|
|
608
|
+
error: f.error,
|
|
609
|
+
command: renderInstallCommand(toInstall.find((c) => c.id === f.id) || {}),
|
|
610
|
+
}),
|
|
614
611
|
);
|
|
615
612
|
}
|
|
616
613
|
if (cliResult.failed.length > 0) {
|
|
617
|
-
addResult('CLIs', 'warn',
|
|
614
|
+
addResult('CLIs', 'warn', it('failedList', { list: cliResult.failed.map((f) => f.id).join(', ') }));
|
|
618
615
|
}
|
|
619
616
|
// M14: verify failure never aborts (CLIs are opt-in) — just a
|
|
620
617
|
// clear warning that the tool cloned/installed but a runtime
|
|
621
618
|
// dependency might still be missing.
|
|
622
619
|
for (const w of cliResult.warnings || []) {
|
|
623
|
-
await prompts.log.warn(
|
|
620
|
+
await prompts.log.warn(it('cliInstalledBut', { id: w.id, warning: w.warning }));
|
|
624
621
|
}
|
|
625
622
|
}
|
|
626
623
|
const toRecommend = cliPlan.toRecommend || [];
|
|
627
624
|
if (toRecommend.length > 0) {
|
|
628
625
|
const lines = toRecommend.map((c) => ` ${renderInstallCommand(c)}`).join('\n');
|
|
629
|
-
await prompts.log.info(
|
|
626
|
+
await prompts.log.info(it('cliRecommend', { lines }));
|
|
630
627
|
}
|
|
631
628
|
} catch (error) {
|
|
632
|
-
await prompts.log.warn(
|
|
629
|
+
await prompts.log.warn(it('cliFail', { error: error.message }));
|
|
633
630
|
addResult('CLIs', 'warn', error.message);
|
|
634
631
|
}
|
|
635
632
|
|
|
@@ -654,7 +651,7 @@ class Installer {
|
|
|
654
651
|
addResult('Skill deps cache', 'ok', 'skill-deps-cache.json');
|
|
655
652
|
}
|
|
656
653
|
} catch (error) {
|
|
657
|
-
await prompts.log.warn(
|
|
654
|
+
await prompts.log.warn(it('depsCacheFail', { error: error.message }));
|
|
658
655
|
addResult('Skill deps cache', 'warn', error.message);
|
|
659
656
|
}
|
|
660
657
|
} else if (config.isQuickUpdate() && (config.modules || []).includes('bmm')) {
|
|
@@ -662,9 +659,7 @@ class Installer {
|
|
|
662
659
|
// preserves settings and skips provisioning entirely, so say it
|
|
663
660
|
// explicitly instead of leaving the user to notice by absence
|
|
664
661
|
// (see project memory: "atualizei e não veio skill").
|
|
665
|
-
await prompts.log.info(
|
|
666
|
-
'Quick Update: skills globais, MCPs e CLIs não foram alterados. Rode install e escolha "Modify Wizz Installation" para instalar itens novos.',
|
|
667
|
-
);
|
|
662
|
+
await prompts.log.info(it('quickUpdateSkipped'));
|
|
668
663
|
}
|
|
669
664
|
|
|
670
665
|
// RT-C1 (item 3): registra os hooks copiados acima em
|
|
@@ -688,19 +683,15 @@ class Installer {
|
|
|
688
683
|
const { settings: globalSettings } = await this._readSettingsJson(this._globalSettingsFile());
|
|
689
684
|
const { entries: hookEntries, skipped: skippedGlobalHooks } = filterHooksRegisteredGlobally(allHookEntries, globalSettings);
|
|
690
685
|
if (skippedGlobalHooks.length > 0) {
|
|
691
|
-
await prompts.log.info(
|
|
692
|
-
`Hook(s) já registrados no settings.json global (~/.claude/settings.json), pulando no projeto para não rodar 2x: ${skippedGlobalHooks.join(', ')}.`,
|
|
693
|
-
);
|
|
686
|
+
await prompts.log.info(it('hooksGlobalSkipped', { list: skippedGlobalHooks.join(', ') }));
|
|
694
687
|
}
|
|
695
688
|
|
|
696
689
|
if (hookEntries.length > 0) {
|
|
697
690
|
const settingsFile = path.join(paths.projectRoot, '.claude', 'settings.json');
|
|
698
691
|
const { settings: existingSettings, invalidJson } = await this._readSettingsJson(settingsFile);
|
|
699
692
|
if (invalidJson) {
|
|
700
|
-
await prompts.log.warn(
|
|
701
|
-
|
|
702
|
-
);
|
|
703
|
-
addResult('Hooks settings', 'warn', 'settings.json inválido, hooks não registrados');
|
|
693
|
+
await prompts.log.warn(it('hooksSettingsInvalid', { file: settingsFile }));
|
|
694
|
+
addResult('Hooks settings', 'warn', it('hooksInvalidSettings'));
|
|
704
695
|
} else {
|
|
705
696
|
const newSettings = mergeHooksIntoSettings(existingSettings, hookEntries);
|
|
706
697
|
pendingHooksSettingsWrite = {
|
|
@@ -726,14 +717,12 @@ class Installer {
|
|
|
726
717
|
`0 hook(s) → .claude/settings.json (${skippedGlobalHooks.length} pulado(s) por já estar no global)`,
|
|
727
718
|
);
|
|
728
719
|
}
|
|
729
|
-
if (!rtkOnPath && installedHookFiles.includes('
|
|
730
|
-
addResult('Hooks settings', 'warn',
|
|
731
|
-
await prompts.log.info(
|
|
732
|
-
'rtk não encontrado no PATH: rtk-rewrite.sh foi copiado para _wizz/hooks/ mas NÃO registrado em settings.json (rtk é opcional). Instale rtk e rode o install de novo para ativá-lo.',
|
|
733
|
-
);
|
|
720
|
+
if (!rtkOnPath && installedHookFiles.includes(require('./hooks-settings').RTK_HOOK_ID)) {
|
|
721
|
+
addResult('Hooks settings', 'warn', it('hooksRtkMissing'));
|
|
722
|
+
await prompts.log.info(it('hooksRtkMissingLong'));
|
|
734
723
|
}
|
|
735
724
|
} catch (error) {
|
|
736
|
-
await prompts.log.warn(
|
|
725
|
+
await prompts.log.warn(it('hooksFail', { error: error.message }));
|
|
737
726
|
addResult('Hooks settings', 'warn', error.message);
|
|
738
727
|
}
|
|
739
728
|
|
|
@@ -845,7 +834,7 @@ class Installer {
|
|
|
845
834
|
await prompts.log.warn(`_resolved/_config.json: ${warning}`);
|
|
846
835
|
}
|
|
847
836
|
} catch (error) {
|
|
848
|
-
await prompts.log.warn(
|
|
837
|
+
await prompts.log.warn(it('resolvedConfigFail', { error: error.message }));
|
|
849
838
|
}
|
|
850
839
|
|
|
851
840
|
message('Generating help catalog...');
|
|
@@ -1244,12 +1233,10 @@ class Installer {
|
|
|
1244
1233
|
}
|
|
1245
1234
|
const totalLegacy = results.reduce((n, r) => n + r.findings.length, 0);
|
|
1246
1235
|
if (totalLegacy > 0) {
|
|
1247
|
-
await prompts.log.warn(
|
|
1248
|
-
`${totalLegacy} regra(s) antiga(s) no CLAUDE.md/AGENTS.md (GSD, superpowers, BMAD puro ou modelo aposentado). O bloco Wizz no topo tem prioridade, mas vale limpar: rode wizz doctor para ver as linhas.`,
|
|
1249
|
-
);
|
|
1236
|
+
await prompts.log.warn(it('legacyRules', { n: totalLegacy }));
|
|
1250
1237
|
}
|
|
1251
1238
|
} catch (error) {
|
|
1252
|
-
await prompts.log.warn(
|
|
1239
|
+
await prompts.log.warn(it('instructionsFail', { error: error.message }));
|
|
1253
1240
|
addResult('Project instructions', 'warn', error.message);
|
|
1254
1241
|
}
|
|
1255
1242
|
}
|
|
@@ -1693,12 +1680,34 @@ class Installer {
|
|
|
1693
1680
|
async uninstallModules(projectDir) {
|
|
1694
1681
|
const { wizzDir } = await this.findWizzDir(projectDir);
|
|
1695
1682
|
if (await fs.pathExists(wizzDir)) {
|
|
1683
|
+
await this._unregisterHooks(projectDir);
|
|
1696
1684
|
await fs.remove(wizzDir);
|
|
1697
1685
|
return true;
|
|
1698
1686
|
}
|
|
1699
1687
|
return false;
|
|
1700
1688
|
}
|
|
1701
1689
|
|
|
1690
|
+
/**
|
|
1691
|
+
* Tira de .claude/settings.json os hooks que o install registrou (apontam para
|
|
1692
|
+
* _wizz/hooks/, que o uninstall apaga). Hook de terceiro e demais chaves ficam;
|
|
1693
|
+
* settings.json inválido não é tocado; arquivo que sobraria vazio é removido.
|
|
1694
|
+
* @param {string} projectDir - Project directory
|
|
1695
|
+
* @returns {Promise<number>} Quantos hooks foram desregistrados
|
|
1696
|
+
*/
|
|
1697
|
+
async _unregisterHooks(projectDir) {
|
|
1698
|
+
const file = path.join(projectDir, '.claude', 'settings.json');
|
|
1699
|
+
const { settings, invalidJson } = await this._readSettingsJson(file);
|
|
1700
|
+
if (invalidJson) return 0;
|
|
1701
|
+
const { settings: cleaned, removed } = removeHooksFromSettings(settings);
|
|
1702
|
+
if (removed === 0) return 0;
|
|
1703
|
+
if (Object.keys(cleaned).length === 0) {
|
|
1704
|
+
await fs.remove(file);
|
|
1705
|
+
} else {
|
|
1706
|
+
await this._writeSettingsJson(file, cleaned);
|
|
1707
|
+
}
|
|
1708
|
+
return removed;
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1702
1711
|
/**
|
|
1703
1712
|
* Get installation status
|
|
1704
1713
|
*/
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* `externalModuleManager`, `manifest`, `install`) instead of inheriting from
|
|
9
9
|
* it, so it can be tested/reasoned about independently.
|
|
10
10
|
*/
|
|
11
|
+
const { it } = require('../install-text');
|
|
11
12
|
const path = require('node:path');
|
|
12
13
|
const fs = require('../fs-native');
|
|
13
14
|
const { OfficialModules } = require('../modules/official-modules');
|
|
@@ -110,9 +111,7 @@ async function quickUpdate(installer, config) {
|
|
|
110
111
|
// _installAndConfigure); that only happens on a fresh install or
|
|
111
112
|
// Modify. Surfacing this before any work starts avoids the confusion of
|
|
112
113
|
// "I updated and skills didn't come" (see project memory).
|
|
113
|
-
await prompts.log.info(
|
|
114
|
-
'Quick Update: atualiza os módulos já instalados com as configurações preservadas. Skills globais, MCPs e CLIs novos não são provisionados neste modo; rode install e escolha "Modify Wizz Installation" para isso.',
|
|
115
|
-
);
|
|
114
|
+
await prompts.log.info(it('quickUpdateScope'));
|
|
116
115
|
|
|
117
116
|
// Detect existing installation
|
|
118
117
|
const existingInstall = await ExistingInstall.detect(wizzDir);
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text the install/update flow prints OUTSIDE the guided screens: the copy
|
|
3
|
+
* phase, the `--advanced` prompts and the final summary. The guided screens
|
|
4
|
+
* use guided/messages.js; both follow the language picked at the start
|
|
5
|
+
* (`--lang` or the guided question), so English mode never mixes in
|
|
6
|
+
* Portuguese (pendência de 2026-09-25).
|
|
7
|
+
*
|
|
8
|
+
* The language lives here as module state because these strings are printed
|
|
9
|
+
* deep inside core/installer.js and modules/*, far from where it is chosen.
|
|
10
|
+
* ui.promptInstall calls setInstallLang once; the default is English.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const fs = require('node:fs');
|
|
14
|
+
const path = require('node:path');
|
|
15
|
+
const { normalizeLang } = require('./guided/messages');
|
|
16
|
+
const COMMAND_TEXT = require('./command-text');
|
|
17
|
+
|
|
18
|
+
const MESSAGES = {
|
|
19
|
+
en: {
|
|
20
|
+
resolvedFail: 'Could not generate _wizz/_resolved/ (fail-open): {error}',
|
|
21
|
+
resolvedConfigFail: 'Could not generate _wizz/_resolved/_config.json (fail-open): {error}',
|
|
22
|
+
globalSkillsFail: 'Could not install global skills: {error}',
|
|
23
|
+
failedList: 'failed: {list}',
|
|
24
|
+
installedList: 'installed: {list}',
|
|
25
|
+
mcpMissingEnv: 'not written, missing env var: {list}',
|
|
26
|
+
mcpEnvFail: 'Could not configure the MCP env vars: {error}',
|
|
27
|
+
mcpPinUpdated: 'MCPs with updated pin (block had not been customized): {list}',
|
|
28
|
+
mcpPinUpdatedShort: 'pin updated: {list}',
|
|
29
|
+
mcpPinCustomized:
|
|
30
|
+
'A pin update is available for {list}, but the block in .mcp.json was customized (differs from what the installer wrote), so it was left as is. Update it by hand if you want the new pin.',
|
|
31
|
+
mcpKept: 'MCPs already present and up to date in .mcp.json (kept): {list}',
|
|
32
|
+
mcpRecommend: 'Recommended MCPs (run whenever you want):\n{lines}',
|
|
33
|
+
mcpDefineEnv: 'Set the MCP environment variables before using them: {list}',
|
|
34
|
+
mcpFail: 'Could not configure MCPs: {error}',
|
|
35
|
+
cliKept: 'CLIs already installed (kept): {list}',
|
|
36
|
+
cliInstallFail: 'Could not install CLI {id}: {error}. Run it by hand: {command}',
|
|
37
|
+
cliInstalledBut: 'CLI {id} installed, but {warning}',
|
|
38
|
+
cliRecommend: 'Recommended CLIs (run whenever you want):\n{lines}',
|
|
39
|
+
cliFail: 'Could not configure CLIs: {error}',
|
|
40
|
+
depsCacheFail: 'Could not write the dependency cache: {error}',
|
|
41
|
+
hooksInvalidSettings: 'invalid settings.json, hooks not registered',
|
|
42
|
+
hooksRtkMissing: 'rtk not found on PATH: rtk-rewrite.sh copied but not registered (optional)',
|
|
43
|
+
hooksFail: 'Could not register hooks in .claude/settings.json: {error}',
|
|
44
|
+
instructionsFail: 'Could not write the Wizz block to CLAUDE.md/AGENTS.md: {error}',
|
|
45
|
+
mcpPrepareFail:
|
|
46
|
+
'MCP {id} could not be prepared ({error}). Config NOT written to avoid ENOENT: install it by hand and add it later with `claude mcp add`.',
|
|
47
|
+
mcpNotWritten:
|
|
48
|
+
'MCP {id} not written: missing {missing}. Run the installer again once you have the key, or add it with `claude mcp add`.',
|
|
49
|
+
quickUpdateScope:
|
|
50
|
+
'Quick Update: refreshes the modules already installed, keeping their settings. New global skills, MCPs and CLIs are not provisioned in this mode; run install and choose "Modify Wizz Installation" for that.',
|
|
51
|
+
quickUpdateSkipped:
|
|
52
|
+
'Quick Update: global skills, MCPs and CLIs were not changed. Run install and choose "Modify Wizz Installation" to install new items.',
|
|
53
|
+
hooksGlobalSkipped:
|
|
54
|
+
'Hook(s) already registered in the global settings.json (~/.claude/settings.json), skipped in the project so they do not run twice: {list}.',
|
|
55
|
+
hooksSettingsInvalid:
|
|
56
|
+
'{file} exists but is not valid JSON: hooks were copied to _wizz/hooks/ but NOT registered in settings.json. Fix the file and run install again.',
|
|
57
|
+
hooksRtkMissingLong:
|
|
58
|
+
'rtk not found on PATH: rtk-rewrite.sh was copied to _wizz/hooks/ but NOT registered in settings.json (rtk is optional). Install rtk and run install again to turn it on.',
|
|
59
|
+
legacyRules:
|
|
60
|
+
'{n} old rule(s) in CLAUDE.md/AGENTS.md (GSD, superpowers, plain BMAD or a retired model). The Wizz block at the top wins, but it is worth cleaning up: run wizz doctor to see the lines.',
|
|
61
|
+
unknownAreas: 'Unknown areas ignored: {list}',
|
|
62
|
+
areasQuestion: 'Which global skill areas should be installed? (empty = all)',
|
|
63
|
+
mcpGlobalSkipped: 'MCPs already configured in your global Claude (~/.claude.json), skipped: {list}',
|
|
64
|
+
mcpPluginSkipped: 'MCPs already covered by a Claude Code plugin (user scope), skipped: {list}',
|
|
65
|
+
mcpQuestion: 'Which MCPs should go into .mcp.json? (unticked ones become a command to run later)',
|
|
66
|
+
unknownClis: 'Unknown or already installed CLIs ignored: {list}',
|
|
67
|
+
cliQuestion: 'Which CLIs should be installed now? (unticked ones become a command to run later)',
|
|
68
|
+
traceQuestion: 'Turn on the routing meter? (local, writes only to ~/.claude/wizz-trace.jsonl on your machine, never leaves it)',
|
|
69
|
+
quickUpdateNoSkills:
|
|
70
|
+
'Skills/MCPs/CLIs were not changed (Quick Update). To provision them, run install and choose "Modify Wizz Installation".',
|
|
71
|
+
doneWarnings: 'Finished with {n} warning(s). See the summary above for details.',
|
|
72
|
+
doneErrors: 'Finished with {n} real failure(s). See the summary above for details.',
|
|
73
|
+
envValue: 'Value for {name}{usedBy} (Enter to skip):',
|
|
74
|
+
envUsedBy: ' (used by: {list})',
|
|
75
|
+
gitignoreAdded: ".claude/settings.local.json was added to the project's .gitignore (it holds API keys and must not go to git).",
|
|
76
|
+
notGitRepo: 'This folder is not a git repository: make sure .claude/settings.local.json (API keys) is never committed.',
|
|
77
|
+
},
|
|
78
|
+
pt: {
|
|
79
|
+
resolvedFail: 'Falha ao gerar _wizz/_resolved/ (fail-open): {error}',
|
|
80
|
+
resolvedConfigFail: 'Falha ao gerar _wizz/_resolved/_config.json (fail-open): {error}',
|
|
81
|
+
globalSkillsFail: 'Falha ao instalar skills globais: {error}',
|
|
82
|
+
failedList: 'falharam: {list}',
|
|
83
|
+
installedList: 'instalados: {list}',
|
|
84
|
+
mcpMissingEnv: 'não gravados por falta de env var: {list}',
|
|
85
|
+
mcpEnvFail: 'Falha ao configurar env vars dos MCPs: {error}',
|
|
86
|
+
mcpPinUpdated: 'MCPs com pin atualizado (bloco não havia sido customizado): {list}',
|
|
87
|
+
mcpPinUpdatedShort: 'pin atualizado: {list}',
|
|
88
|
+
mcpPinCustomized:
|
|
89
|
+
'Há atualização de pin disponível para {list}, mas o bloco no .mcp.json foi customizado (diferente do que o installer escreveu), então ficou intacto. Atualize manualmente se quiser o pin novo.',
|
|
90
|
+
mcpKept: 'MCPs já presentes e atualizados no .mcp.json (mantidos): {list}',
|
|
91
|
+
mcpRecommend: 'MCPs recomendados (rode quando quiser):\n{lines}',
|
|
92
|
+
mcpDefineEnv: 'Defina as variáveis de ambiente dos MCPs antes de usar: {list}',
|
|
93
|
+
mcpFail: 'Falha ao configurar MCPs: {error}',
|
|
94
|
+
cliKept: 'CLIs já instalados (mantidos): {list}',
|
|
95
|
+
cliInstallFail: 'Falha ao instalar CLI {id}: {error}. Rode manualmente: {command}',
|
|
96
|
+
cliInstalledBut: 'CLI {id} instalado, mas {warning}',
|
|
97
|
+
cliRecommend: 'CLIs recomendados (rode quando quiser):\n{lines}',
|
|
98
|
+
cliFail: 'Falha ao configurar CLIs: {error}',
|
|
99
|
+
depsCacheFail: 'Falha ao gravar cache de dependências: {error}',
|
|
100
|
+
hooksInvalidSettings: 'settings.json inválido, hooks não registrados',
|
|
101
|
+
hooksRtkMissing: 'rtk não encontrado no PATH: rtk-rewrite.sh copiado mas não registrado (opcional)',
|
|
102
|
+
hooksFail: 'Falha ao registrar hooks em .claude/settings.json: {error}',
|
|
103
|
+
instructionsFail: 'Falha ao gravar o bloco Wizz no CLAUDE.md/AGENTS.md: {error}',
|
|
104
|
+
mcpPrepareFail:
|
|
105
|
+
'MCP {id} não pôde ser preparado ({error}). Config NÃO escrita para evitar ENOENT: instale manualmente e adicione depois com `claude mcp add`.',
|
|
106
|
+
mcpNotWritten:
|
|
107
|
+
'MCP {id} não gravado: faltou {missing}. Rode o installer de novo quando tiver a chave, ou adicione com `claude mcp add`.',
|
|
108
|
+
quickUpdateScope:
|
|
109
|
+
'Quick Update: atualiza os módulos já instalados com as configurações preservadas. Skills globais, MCPs e CLIs novos não são provisionados neste modo; rode install e escolha "Modify Wizz Installation" para isso.',
|
|
110
|
+
quickUpdateSkipped:
|
|
111
|
+
'Quick Update: skills globais, MCPs e CLIs não foram alterados. Rode install e escolha "Modify Wizz Installation" para instalar itens novos.',
|
|
112
|
+
hooksGlobalSkipped:
|
|
113
|
+
'Hook(s) já registrados no settings.json global (~/.claude/settings.json), pulando no projeto para não rodar 2x: {list}.',
|
|
114
|
+
hooksSettingsInvalid:
|
|
115
|
+
'{file} existe mas não é JSON válido: hooks copiados para _wizz/hooks/, mas NÃO registrados em settings.json. Corrija o arquivo e rode o install de novo.',
|
|
116
|
+
hooksRtkMissingLong:
|
|
117
|
+
'rtk não encontrado no PATH: rtk-rewrite.sh foi copiado para _wizz/hooks/ mas NÃO registrado em settings.json (rtk é opcional). Instale rtk e rode o install de novo para ativá-lo.',
|
|
118
|
+
legacyRules:
|
|
119
|
+
'{n} regra(s) antiga(s) no CLAUDE.md/AGENTS.md (GSD, superpowers, BMAD puro ou modelo aposentado). O bloco Wizz no topo tem prioridade, mas vale limpar: rode wizz doctor para ver as linhas.',
|
|
120
|
+
unknownAreas: 'Áreas desconhecidas ignoradas: {list}',
|
|
121
|
+
areasQuestion: 'Quais áreas de skills globais instalar? (vazio = todas)',
|
|
122
|
+
mcpGlobalSkipped: 'MCPs já configurados no seu Claude global (~/.claude.json), pulados: {list}',
|
|
123
|
+
mcpPluginSkipped: 'MCPs já cobertos por plugin do Claude Code (user scope), pulados: {list}',
|
|
124
|
+
mcpQuestion: 'Quais MCPs configurar no .mcp.json? (não marcados viram comando pra rodar depois)',
|
|
125
|
+
unknownClis: 'CLIs desconhecidos/já instalados ignorados: {list}',
|
|
126
|
+
cliQuestion: 'Quais CLIs instalar agora? (não marcados viram comando pra rodar depois)',
|
|
127
|
+
traceQuestion: 'Quer ligar o medidor de roteamento? (local, grava só em ~/.claude/wizz-trace.jsonl na sua máquina, nunca sai daqui)',
|
|
128
|
+
quickUpdateNoSkills:
|
|
129
|
+
'Skills/MCPs/CLIs não foram alterados (Quick Update). Para provisioná-los, rode install e escolha "Modify Wizz Installation".',
|
|
130
|
+
doneWarnings: 'Concluído com {n} aviso(s). Veja o resumo acima para detalhes.',
|
|
131
|
+
doneErrors: 'Concluído com {n} falha(s) real(is). Veja o resumo acima para detalhes.',
|
|
132
|
+
envValue: 'Valor para {name}{usedBy} (Enter para pular):',
|
|
133
|
+
envUsedBy: ' (usada por: {list})',
|
|
134
|
+
gitignoreAdded: '.claude/settings.local.json foi adicionado ao .gitignore do projeto (guarda API keys, não deve ir pro git).',
|
|
135
|
+
notGitRepo: 'Este diretório não é um repositório git: garanta que .claude/settings.local.json (API keys) nunca seja versionado.',
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// doctor, resolve e trace-report (command-text.js) entram na mesma tabela.
|
|
140
|
+
Object.assign(MESSAGES.en, COMMAND_TEXT.en);
|
|
141
|
+
Object.assign(MESSAGES.pt, COMMAND_TEXT.pt);
|
|
142
|
+
|
|
143
|
+
let current = 'en';
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Set the language for the rest of the run.
|
|
147
|
+
* @param {string|undefined} raw - "en", "pt", "pt-BR"…; unknown keeps English
|
|
148
|
+
*/
|
|
149
|
+
function setInstallLang(raw) {
|
|
150
|
+
current = normalizeLang(raw) || 'en';
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Language of an existing install, from `communication_language` in
|
|
155
|
+
* _wizz/core/config.yaml ("Portugues", "Português (Brasil)", "English"…), so
|
|
156
|
+
* `wizz update` without --lang keeps talking the language picked at install.
|
|
157
|
+
* @param {string} wizzDir
|
|
158
|
+
* @returns {'en'|'pt'|null} null when absent or unreadable
|
|
159
|
+
*/
|
|
160
|
+
function langOfInstall(wizzDir) {
|
|
161
|
+
try {
|
|
162
|
+
const text = fs.readFileSync(path.join(wizzDir, 'core', 'config.yaml'), 'utf8');
|
|
163
|
+
const match = text.match(/^communication_language:\s*["']?([^"'\n]+)/m);
|
|
164
|
+
if (!match) return null;
|
|
165
|
+
return /^portugu/i.test(match[1].trim()) ? 'pt' : 'en';
|
|
166
|
+
} catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Language for the commands that run on an existing install (doctor,
|
|
173
|
+
* resolve, trace-report): WIZZ_LANG wins, then `communication_language` of
|
|
174
|
+
* the install, then English. Sets it for the rest of the run.
|
|
175
|
+
* @param {string|null} wizzDir - _wizz/ of the project, or null
|
|
176
|
+
* @returns {'en'|'pt'}
|
|
177
|
+
*/
|
|
178
|
+
function useCommandLang(wizzDir) {
|
|
179
|
+
const fromEnv = normalizeLang(process.env.WIZZ_LANG);
|
|
180
|
+
setInstallLang(fromEnv || (wizzDir && langOfInstall(wizzDir)) || 'en');
|
|
181
|
+
return current;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function getInstallLang() {
|
|
185
|
+
return current;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Translate a key in the current language, filling {placeholders}.
|
|
190
|
+
* @param {string} key
|
|
191
|
+
* @param {Object} [vars]
|
|
192
|
+
* @returns {string}
|
|
193
|
+
*/
|
|
194
|
+
function it(key, vars = {}) {
|
|
195
|
+
const table = MESSAGES[current] || MESSAGES.en;
|
|
196
|
+
const value = key in table ? table[key] : MESSAGES.en[key];
|
|
197
|
+
if (typeof value !== 'string') throw new Error(`install-text: unknown key "${key}"`);
|
|
198
|
+
return value.replaceAll(/\{(\w+)\}/g, (match, name) => (name in vars ? String(vars[name]) : match));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
module.exports = { MESSAGES, setInstallLang, getInstallLang, langOfInstall, useCommandLang, it };
|
|
@@ -187,12 +187,12 @@ function orphanPinWarnings(channelOptions, selectedCodes) {
|
|
|
187
187
|
* Warn when --pin / --next targets a bundled module (core, bmm). Those are
|
|
188
188
|
* shipped inside the installer binary — there's no git clone to override, so
|
|
189
189
|
* the flag has no effect. Users who actually want a prerelease core/bmm
|
|
190
|
-
* should use `npx
|
|
190
|
+
* should use `npx wizz-method@next install`.
|
|
191
191
|
*/
|
|
192
192
|
function bundledTargetWarnings(channelOptions, bundledCodes) {
|
|
193
193
|
const warnings = [];
|
|
194
194
|
const bundled = new Set(bundledCodes || []);
|
|
195
|
-
const hint = '(bundled module; use `npx
|
|
195
|
+
const hint = '(bundled module; use `npx wizz-method@next install` for a prerelease)';
|
|
196
196
|
for (const code of channelOptions?.pins?.keys() || []) {
|
|
197
197
|
if (bundled.has(code)) {
|
|
198
198
|
warnings.push(`--pin for '${code}' has no effect ${hint}.`);
|