wizz-method 1.16.0 → 1.17.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.
Files changed (67) hide show
  1. package/package.json +4 -2
  2. package/removals.txt +6 -0
  3. package/skills-registry.yaml +81 -123
  4. package/src/bmm-skills/3-solutioning/wizz-generate-project-context/project-context-template.md +5 -0
  5. package/src/bmm-skills/3-solutioning/wizz-generate-project-context/steps/step-01-discover.md +16 -5
  6. package/src/bmm-skills/3-solutioning/wizz-generate-project-context/steps/step-03-complete.md +5 -0
  7. package/src/bmm-skills/4-implementation/wizz-retrospective/customize.toml +3 -1
  8. package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/__pycache__/sprint_status.cpython-313.pyc +0 -0
  9. package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/tests/__pycache__/test_git_evidence.cpython-313-pytest-9.1.1.pyc +0 -0
  10. package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/tests/__pycache__/test_sprint_status.cpython-313-pytest-9.1.1.pyc +0 -0
  11. package/src/bmm-skills/4-implementation/wizz-sprint-planning/customize.toml +3 -1
  12. package/src/bmm-skills/4-implementation/wizz-sprint-planning/scripts/__pycache__/sprint_plan.cpython-313.pyc +0 -0
  13. package/src/bmm-skills/4-implementation/wizz-sprint-planning/scripts/tests/__pycache__/test_sprint_plan.cpython-313-pytest-9.1.1.pyc +0 -0
  14. package/src/core-skills/wizz-advanced-elicitation/scripts/__pycache__/pick_methods.cpython-313.pyc +0 -0
  15. package/src/core-skills/wizz-advanced-elicitation/scripts/tests/__pycache__/test_pick_methods.cpython-313-pytest-9.1.1.pyc +0 -0
  16. package/src/core-skills/wizz-brainstorming/scripts/__pycache__/brain.cpython-313.pyc +0 -0
  17. package/src/core-skills/wizz-brainstorming/scripts/tests/__pycache__/test_brain.cpython-313-pytest-9.1.1.pyc +0 -0
  18. package/src/core-skills/wizz-brainstorming/scripts/tests/__pycache__/test_brain.cpython-314.pyc +0 -0
  19. package/src/core-skills/wizz-forge-idea/scripts/__pycache__/resolve_personas.cpython-314.pyc +0 -0
  20. package/src/core-skills/wizz-forge-idea/scripts/tests/__pycache__/test_resolve_personas.cpython-314.pyc +0 -0
  21. package/src/core-skills/wizz-party-mode/scripts/__pycache__/resolve_party.cpython-314.pyc +0 -0
  22. package/src/core-skills/wizz-party-mode/scripts/tests/__pycache__/test_resolve_party.cpython-314.pyc +0 -0
  23. package/src/modules/wizz/_shared/encerramento.md +22 -0
  24. package/src/modules/wizz/agents/wizz-designer/SKILL.md +1 -1
  25. package/src/modules/wizz/agents/wizz-maestro/SKILL.md +4 -0
  26. package/src/modules/wizz/agents/wizz-qa/SKILL.md +6 -0
  27. package/src/modules/wizz/agents/wizz-social/SKILL.md +1 -0
  28. package/src/modules/wizz/subagents/codex/wizz-exec-haiku.toml +12 -0
  29. package/src/modules/wizz/subagents/codex/wizz-exec-opus.toml +12 -0
  30. package/src/modules/wizz/subagents/codex/wizz-exec-review.toml +11 -0
  31. package/src/modules/wizz/subagents/codex/wizz-exec-sonnet.toml +12 -0
  32. package/src/modules/wizz/subagents/gemini/wizz-exec-haiku.md +12 -0
  33. package/src/modules/wizz/subagents/gemini/wizz-exec-opus.md +12 -0
  34. package/src/modules/wizz/subagents/gemini/wizz-exec-review.md +11 -0
  35. package/src/modules/wizz/subagents/gemini/wizz-exec-sonnet.md +12 -0
  36. package/src/modules/wizz/subagents/opencode/wizz-exec-haiku.md +12 -0
  37. package/src/modules/wizz/subagents/opencode/wizz-exec-opus.md +12 -0
  38. package/src/modules/wizz/subagents/opencode/wizz-exec-review.md +11 -0
  39. package/src/modules/wizz/subagents/opencode/wizz-exec-sonnet.md +12 -0
  40. package/src/modules/wizz/subagents/wizz-exec-haiku.md +12 -0
  41. package/src/modules/wizz/subagents/wizz-exec-opus.md +12 -0
  42. package/src/modules/wizz/subagents/wizz-exec-review.md +11 -0
  43. package/src/modules/wizz/subagents/wizz-exec-sonnet.md +12 -0
  44. package/src/skills-lib/launch-readiness/SKILL.md +94 -0
  45. package/src/skills-lib/launch-readiness/references/01-tecnico-build.md +26 -0
  46. package/src/skills-lib/launch-readiness/references/02-seguranca.md +26 -0
  47. package/src/skills-lib/launch-readiness/references/03-seo-descoberta.md +27 -0
  48. package/src/skills-lib/launch-readiness/references/04-analytics-medicao.md +25 -0
  49. package/src/skills-lib/launch-readiness/references/05-conteudo-prova-social.md +25 -0
  50. package/src/skills-lib/launch-readiness/references/06-legal-lgpd.md +25 -0
  51. package/src/skills-lib/launch-readiness/references/07-infra-deploy-rollback.md +26 -0
  52. package/src/skills-lib/launch-readiness/references/08-fusao-priorizacao.md +33 -0
  53. package/src/skills-lib/launch-readiness/references/09-persistencia-project-context.md +48 -0
  54. package/src/skills-lib/site-launch-kit/SKILL.md +1 -1
  55. package/src/skills-lib/taste-skill/SKILL.md +4 -2
  56. package/src/skills-lib/{taste-redesign → taste-skill}/references/design-audit.md +30 -41
  57. package/src/skills-lib/taste-skill/references/redesign-protocol.md +2 -2
  58. package/src/skills-lib/taste-skill/references/upgrade-techniques.md +33 -0
  59. package/src/skills-lib/wizz-offer-forge/SKILL.md +3 -2
  60. package/src/skills-lib/wizz-router/SKILL.md +7 -1
  61. package/src/skills-lib/wizz-router/references/routing-table-flat.md +3 -2
  62. package/tools/fetch-assets.mjs +3 -2
  63. package/tools/installer/commands/trace-report.js +248 -4
  64. package/tools/installer/modules/official-modules.js +5 -0
  65. package/wizz-modules.yaml +3 -3
  66. package/src/skills-lib/taste-redesign/SKILL.md +0 -42
  67. package/src/skills-lib/taste-redesign/references/upgrade-techniques.md +0 -31
@@ -11,13 +11,137 @@
11
11
 
12
12
  const os = require('node:os');
13
13
  const path = require('node:path');
14
+ const yaml = require('yaml');
14
15
  const fs = require('../fs-native');
15
16
  const prompts = require('../prompts');
17
+ const { getProjectRoot } = require('../project-root');
16
18
 
17
19
  function getTraceFile() {
18
20
  return process.env.WIZZ_TRACE_FILE || path.join(os.homedir(), '.claude', 'wizz-trace.jsonl');
19
21
  }
20
22
 
23
+ // `--coverage` (P2 da auditoria 360°, "evals de descoberta"): cruza o
24
+ // catálogo de skills do skills-registry.yaml (fonte única, lido em runtime
25
+ // e nunca hardcoded aqui) contra os marcadores de decisão (`type:
26
+ // "decision"`, escritos por tools/hooks/wizz-decision-trace.js) já
27
+ // agregados no mesmo JSONL. Mede subutilização de roteamento: uma skill
28
+ // pode estar SELECIONADA (`sel`), DESCARTADA COM MOTIVO (`desc`, correto:
29
+ // foi considerada e explicitamente preterida) ou NUNCA CONSIDERADA (não
30
+ // aparece em nenhum dos dois arrays de nenhum trace): esta última é a
31
+ // falha de roteamento silenciosa que o item da auditoria pede pra medir.
32
+ function getRegistryFile() {
33
+ return path.join(getProjectRoot(), 'skills-registry.yaml');
34
+ }
35
+
36
+ // Lê e parseia skills-registry.yaml, devolvendo o catálogo de ids de
37
+ // skills em ordem alfabética estável (mesma lista independente da ordem em
38
+ // que as áreas/skills aparecem no YAML). Escopo deliberado: só as skills
39
+ // `areas.*.skills[]` e as cross-cutting `utility[]` (graphify, find-skills,
40
+ // enhance-prompt, wizz-router; também são skills de verdade em
41
+ // src/skills-lib/). CLIs/MCPs/squads ficam de fora: `sel`/`desc` no
42
+ // marcador de decisão podem citar agentes ou skills (ver encerramento.md),
43
+ // mas este comando mede especificamente subutilização de SKILL, não de
44
+ // ferramenta/squad. Lança em vez de devolver `null` em erro: quem chama
45
+ // decide como reportar (fail-clear, não fail-silent: ao contrário do
46
+ // trace, o catálogo é a fonte de verdade e um erro aqui é um bug real).
47
+ function collectSkillCatalog(registryFile) {
48
+ const raw = fs.readFileSync(registryFile, 'utf8');
49
+ const registry = yaml.parse(raw);
50
+ const ids = new Set();
51
+ for (const area of Object.values(registry.areas || {})) {
52
+ for (const skill of area.skills || []) {
53
+ if (skill && typeof skill.id === 'string') ids.add(skill.id);
54
+ }
55
+ }
56
+ for (const item of registry.utility || []) {
57
+ if (item && typeof item.id === 'string') ids.add(item.id);
58
+ }
59
+ return [...ids].sort();
60
+ }
61
+
62
+ // Agrega os traces `type: "decision"` já parseados contra o catálogo.
63
+ // Função pura (mesmo espírito de `aggregate`/`aggregateLadder`), testável
64
+ // sem tocar em disco. `catalogIds` já deve vir ordenado (saída de
65
+ // `collectSkillCatalog`): a ordem de `neverConsidered` deriva dela, então
66
+ // a saída é estável entre execuções.
67
+ //
68
+ // Ids de `sel`/`desc` que não pertencem ao catálogo (ex.: agente
69
+ // "wizz-designer" em vez de skill) são ignorados aqui, não contados como
70
+ // erro: o marcador aceita os dois tipos (encerramento.md), este comando só
71
+ // mede a fatia de skills.
72
+ //
73
+ // Categorização mutuamente exclusiva por skill (soma sempre = catalogTotal):
74
+ // selecionada (apareceu em algum `sel`) > descartada-só (apareceu só em
75
+ // `desc`, nunca em `sel`) > nunca considerada (nenhum dos dois). Se uma
76
+ // skill foi selecionada numa decisão e descartada noutra, conta como
77
+ // selecionada: "foi de fato usada ao menos uma vez" pesa mais que "também
78
+ // foi preterida uma vez" para o proposito de subutilização.
79
+ function aggregateCoverage(entries, catalogIds) {
80
+ const catalogSet = new Set(catalogIds);
81
+ const selected = new Set();
82
+ const discarded = new Set();
83
+ let decisionCount = 0;
84
+
85
+ for (const entry of entries) {
86
+ if (!entry || entry.type !== 'decision') continue;
87
+ const decision = entry.decision;
88
+ if (!decision || typeof decision !== 'object') continue;
89
+ decisionCount++;
90
+
91
+ if (Array.isArray(decision.sel)) {
92
+ for (const id of decision.sel) {
93
+ if (typeof id === 'string' && catalogSet.has(id)) selected.add(id);
94
+ }
95
+ }
96
+ if (Array.isArray(decision.desc)) {
97
+ for (const pair of decision.desc) {
98
+ if (Array.isArray(pair) && typeof pair[0] === 'string' && catalogSet.has(pair[0])) {
99
+ discarded.add(pair[0]);
100
+ }
101
+ }
102
+ }
103
+ }
104
+
105
+ const discardedOnly = [];
106
+ const neverConsidered = [];
107
+ for (const id of catalogIds) {
108
+ if (selected.has(id)) continue;
109
+ if (discarded.has(id)) discardedOnly.push(id);
110
+ else neverConsidered.push(id);
111
+ }
112
+
113
+ return {
114
+ catalogTotal: catalogIds.length,
115
+ decisionCount,
116
+ selectedCount: selected.size,
117
+ discardedOnlyCount: discardedOnly.length,
118
+ neverConsidered,
119
+ };
120
+ }
121
+
122
+ function formatCoverageSummary(stats, registryFile) {
123
+ const consideredCount = stats.catalogTotal - stats.neverConsidered.length;
124
+ const lines = [
125
+ `Catálogo: ${stats.catalogTotal} skills (${registryFile})`,
126
+ `Traces de decisão: ${stats.decisionCount}`,
127
+ `Selecionadas (sel): ${stats.selectedCount} (${pct(stats.selectedCount, stats.catalogTotal)})`,
128
+ `Descartadas c/ motivo: ${stats.discardedOnlyCount} (${pct(stats.discardedOnlyCount, stats.catalogTotal)})`,
129
+ `Nunca consideradas: ${stats.neverConsidered.length} (${pct(stats.neverConsidered.length, stats.catalogTotal)})`,
130
+ `Cobertura do catálogo: ${pct(consideredCount, stats.catalogTotal)}`,
131
+ ];
132
+
133
+ if (stats.decisionCount === 0) {
134
+ lines.push('', '(nenhum trace de decisão encontrado; rode com WIZZ_TRACE=1 e feche pedidos roteados pra gerar dados)');
135
+ } else if (stats.neverConsidered.length === 0) {
136
+ lines.push('', 'Nunca consideradas: nenhuma, catálogo 100% coberto.');
137
+ } else {
138
+ lines.push('', 'Nunca consideradas:');
139
+ for (const id of stats.neverConsidered) lines.push(` ${id}`);
140
+ }
141
+
142
+ return lines.join('\n');
143
+ }
144
+
21
145
  // Faz o parse de 1 linha JSONL. Retorna `null` (em vez de lançar) para
22
146
  // linhas corrompidas — fail-open, mesmo espírito do resto do framework: o
23
147
  // trace nunca pode quebrar quem o lê.
@@ -31,14 +155,24 @@ function parseLine(line) {
31
155
 
32
156
  // Agrega as entradas já parseadas em contadores/período. Função pura, sem
33
157
  // I/O, para ser testável isoladamente do disco.
158
+ //
159
+ // Linhas tipadas (`type: "decision"` do marcador 🧭 e `type: "ladder"` da
160
+ // escada de modelos, ambas escritas por tools/hooks/wizz-decision-trace.js)
161
+ // são IGNORADAS aqui: são outra granularidade de evento (o fecho de um
162
+ // pedido, não o roteamento em si) e contá-las junto de trivial/mode poluiria
163
+ // as contagens. `type: "ladder"` alimenta só `aggregateLadder`, abaixo.
34
164
  function aggregate(entries) {
35
165
  const byMode = { wizz: 0, flat: 0, null: 0 };
166
+ let total = 0;
36
167
  let trivialCount = 0;
37
168
  let warningsCount = 0;
38
169
  let firstTs = null;
39
170
  let lastTs = null;
40
171
 
41
172
  for (const entry of entries) {
173
+ if (entry.type === 'decision' || entry.type === 'ladder') continue;
174
+ total++;
175
+
42
176
  if (entry.isTrivial) {
43
177
  trivialCount++;
44
178
  } else {
@@ -54,9 +188,9 @@ function aggregate(entries) {
54
188
  }
55
189
 
56
190
  return {
57
- total: entries.length,
191
+ total,
58
192
  trivialCount,
59
- routedCount: entries.length - trivialCount,
193
+ routedCount: total - trivialCount,
60
194
  byMode,
61
195
  warningsCount,
62
196
  firstTs,
@@ -64,6 +198,53 @@ function aggregate(entries) {
64
198
  };
65
199
  }
66
200
 
201
+ // Bucket de rota pra agregação da escada de modelos: agrupa qualquer
202
+ // "agent:*" (designer, copy, seo, etc.) numa única chave — o que importa
203
+ // pra aderência é "foi delegado a um agente de área", não qual área
204
+ // especificamente. `maestro` e `flat` ficam como buckets próprios; qualquer
205
+ // outro valor (ou ausência) cai em `outro`.
206
+ function ladderBucket(rota) {
207
+ if (typeof rota !== 'string' || rota.length === 0) return 'outro';
208
+ if (rota.startsWith('agent:')) return 'agent:*';
209
+ if (rota === 'maestro') return 'maestro';
210
+ if (rota === 'flat') return 'flat';
211
+ return 'outro';
212
+ }
213
+
214
+ // Agrega as linhas `type: "ladder"` (uma por pedido roteado que fechou com
215
+ // marcador de decisão — ver wizz-decision-trace.js) em aderência à escada
216
+ // de modelos: quantos pedidos invocaram algum subagente wizz-exec-*,
217
+ // quebrado por rota. Função pura, mesmo espírito de `aggregate`.
218
+ function aggregateLadder(entries) {
219
+ const byRoute = {};
220
+
221
+ const bump = (bucket, invoked) => {
222
+ if (!byRoute[bucket]) byRoute[bucket] = { total: 0, withExec: 0 };
223
+ byRoute[bucket].total++;
224
+ if (invoked) byRoute[bucket].withExec++;
225
+ };
226
+
227
+ let total = 0;
228
+ let withExec = 0;
229
+
230
+ for (const entry of entries) {
231
+ if (!entry || entry.type !== 'ladder') continue;
232
+ total++;
233
+ const invoked = Array.isArray(entry.execs) && entry.execs.length > 0;
234
+ if (invoked) withExec++;
235
+ bump(ladderBucket(entry.rota), invoked);
236
+ }
237
+
238
+ return { total, withExec, byRoute };
239
+ }
240
+
241
+ // Percentual formatado, protegido contra divisão por zero (mostra "—" em
242
+ // vez de NaN%/Infinity% quando o denominador é 0).
243
+ function pct(part, total) {
244
+ if (!total) return '—';
245
+ return `${Math.round((part / total) * 100)}%`;
246
+ }
247
+
67
248
  function formatSummary(stats, traceFile) {
68
249
  const lines = [
69
250
  `Arquivo: ${traceFile}`,
@@ -82,10 +263,34 @@ function formatSummary(stats, traceFile) {
82
263
  return lines.join('\n');
83
264
  }
84
265
 
266
+ // Ordem de exibição fixa das rotas na segunda caixa — independente da ordem
267
+ // em que apareceram no arquivo, pra saída estável entre execuções.
268
+ const ROUTE_DISPLAY_ORDER = ['agent:*', 'maestro', 'flat', 'outro'];
269
+
270
+ function formatLadderSummary(ladderStats) {
271
+ const lines = [
272
+ `Pedidos roteados com dado de escada: ${ladderStats.total}`,
273
+ `Invocaram algum wizz-exec-*: ${ladderStats.withExec} (${pct(ladderStats.withExec, ladderStats.total)})`,
274
+ 'Por rota:',
275
+ ];
276
+
277
+ const routes = ROUTE_DISPLAY_ORDER.filter((route) => ladderStats.byRoute[route]);
278
+ if (routes.length === 0) {
279
+ lines.push(' (sem dados)');
280
+ } else {
281
+ for (const route of routes) {
282
+ const bucket = ladderStats.byRoute[route];
283
+ lines.push(` ${route.padEnd(8)} ${bucket.withExec}/${bucket.total} (${pct(bucket.withExec, bucket.total)})`);
284
+ }
285
+ }
286
+
287
+ return lines.join('\n');
288
+ }
289
+
85
290
  module.exports = {
86
291
  command: 'trace-report',
87
292
  description: 'Resume o arquivo local de trace do roteamento (WIZZ_TRACE)',
88
- options: [],
293
+ options: [['--coverage', 'Cruza o catálogo de skills do registry contra os traces: mede skills nunca consideradas no roteamento']],
89
294
  action: async (options) => {
90
295
  try {
91
296
  const traceFile = getTraceFile();
@@ -112,10 +317,37 @@ module.exports = {
112
317
  }
113
318
  }
114
319
 
320
+ // `--coverage` é um modo alternativo, não aditivo: troca as 2 caixas
321
+ // base (contagem trivial/mode e escada de modelos) por 1 caixa focada
322
+ // em subutilização de skills. Motivo: são leituras diferentes do mesmo
323
+ // JSONL (roteamento agregado vs catálogo x descoberta): misturar as
324
+ // 3 caixas por padrão poluiria a saída sem ganho pro caso de uso de
325
+ // cada flag.
326
+ if (options.coverage) {
327
+ const registryFile = getRegistryFile();
328
+ let catalogIds;
329
+ try {
330
+ catalogIds = collectSkillCatalog(registryFile);
331
+ } catch (error) {
332
+ await prompts.log.error(`Não foi possível ler o catálogo de skills: ${error.message}`);
333
+ await prompts.log.message(`Esperado em: ${registryFile}`);
334
+ process.exit(1);
335
+ return;
336
+ }
337
+
338
+ const coverageStats = aggregateCoverage(entries, catalogIds);
339
+ await prompts.box(formatCoverageSummary(coverageStats, registryFile), 'Cobertura do Catálogo de Skills');
340
+ process.exit(0);
341
+ return;
342
+ }
343
+
115
344
  const stats = { ...aggregate(entries), corruptedCount };
116
345
 
117
346
  await prompts.box(formatSummary(stats, traceFile), 'Wizz Trace Report');
118
347
 
348
+ const ladderStats = aggregateLadder(entries);
349
+ await prompts.box(formatLadderSummary(ladderStats), 'Aderência à Escada de Modelos');
350
+
119
351
  process.exit(0);
120
352
  } catch (error) {
121
353
  await prompts.log.error(`Trace report failed: ${error.message}`);
@@ -127,5 +359,17 @@ module.exports = {
127
359
  },
128
360
  // Exportado só para teste unitário direto da agregação, sem precisar
129
361
  // spawnar o processo pra cada caso de borda.
130
- _internal: { aggregate, parseLine, formatSummary },
362
+ _internal: {
363
+ aggregate,
364
+ parseLine,
365
+ formatSummary,
366
+ aggregateLadder,
367
+ ladderBucket,
368
+ formatLadderSummary,
369
+ pct,
370
+ collectSkillCatalog,
371
+ aggregateCoverage,
372
+ formatCoverageSummary,
373
+ getRegistryFile,
374
+ },
131
375
  };
@@ -292,6 +292,11 @@ class OfficialModules {
292
292
  * @param {Object} options.logger - Logger instance for output
293
293
  */
294
294
  async install(moduleName, wizzDir, fileTrackingCallback = null, options = {}) {
295
+ // Aliases (ex.: bauto → bmad-loop) chegam crus via --modules e via
296
+ // moduleIds de instalações antigas; sem normalizar aqui, o cache de
297
+ // getPluginResolution, o targetPath e o manifest usariam o código legado.
298
+ moduleName = await this.externalModuleManager.resolveCanonicalCode(moduleName);
299
+
295
300
  // Check if this module has a plugin resolution (custom marketplace install)
296
301
  const { CustomModuleManager } = require('./custom-module-manager');
297
302
  const customMgr = new CustomModuleManager();
package/wizz-modules.yaml CHANGED
@@ -81,12 +81,12 @@ modules:
81
81
  # .claude-plugin/marketplace.json via plugin resolver (ver external-manager).
82
82
  marketplace-plugin: true
83
83
  post-install-message: |
84
- Wizz Loop installed. To finish setup, run the bmad-loop-setup skill
85
- from your agent:
84
+ Wizz Loop installed. To finish setup, ask your agent to run the setup
85
+ skill (the command keeps the upstream name):
86
86
 
87
87
  > use the bmad-loop-setup skill
88
88
 
89
- It installs the bmad-loop orchestrator tool and wires up the per-project
89
+ It installs the Wizz Loop orchestrator tool and wires up the per-project
90
90
  hooks and policy. The automation skills don't run until setup completes.
91
91
 
92
92
  bmad-creative-intelligence-suite:
@@ -1,42 +0,0 @@
1
- ---
2
- name: taste-redesign
3
- description: Upgrades existing websites and apps to premium quality. Audits current design, identifies generic AI patterns, and applies high-end design standards without breaking functionality. Works with any CSS framework or vanilla CSS. Use when the user asks to redesign, upgrade, or audit an existing site or app that looks generic or AI-generated, without rewriting it from scratch.
4
- ---
5
-
6
- # Redesign Skill
7
-
8
- ## How This Works (first step)
9
-
10
- When applied to an existing project, follow this sequence:
11
-
12
- 1. **Scan** — Read the codebase. Identify the framework, styling method (Tailwind, vanilla CSS, styled-components, etc.), and current design patterns.
13
- 2. **Diagnose** — Load `references/design-audit.md` and run through the full checklist. List every generic pattern, weak point, and missing state you find.
14
- 3. **Fix** — Load `references/upgrade-techniques.md` for high-impact replacements, then apply targeted upgrades working with the existing stack. Do not rewrite from scratch. Improve what's there. Follow the Fix Priority order below.
15
-
16
- ## Fix Priority
17
-
18
- Apply changes in this order for maximum visual impact with minimum risk:
19
-
20
- 1. **Font swap** — biggest instant improvement, lowest risk
21
- 2. **Color palette cleanup** — remove clashing or oversaturated colors
22
- 3. **Hover and active states** — makes the interface feel alive
23
- 4. **Layout and spacing** — proper grid, max-width, consistent padding
24
- 5. **Replace generic components** — swap cliche patterns for modern alternatives
25
- 6. **Add loading, empty, and error states** — makes it feel finished
26
- 7. **Polish typography scale and spacing** — the premium final touch
27
-
28
- ## Rules
29
-
30
- - Work with the existing tech stack. Do not migrate frameworks or styling libraries.
31
- - Do not break existing functionality. Test after every change.
32
- - Before importing any new library, check the project's dependency file first.
33
- - If the project uses Tailwind, check the version (v3 vs v4) before modifying config.
34
- - If the project has no framework, use vanilla CSS.
35
- - Keep changes reviewable and focused. Small, targeted improvements over big rewrites.
36
-
37
- ## Reference map — load each file when you reach that step
38
-
39
- - `references/design-audit.md` — the full audit checklist across 9 categories (Typography, Color and Surfaces, Layout, Interactivity and States, Content, Component Patterns, Iconography, Code Quality, Strategic Omissions). **Load during the Diagnose step.**
40
- - `references/upgrade-techniques.md` — high-impact techniques (Typography, Layout, Motion, Surface upgrades) to replace generic patterns found in the audit. **Load during the Fix step.**
41
-
42
- Zero content was cut when this skill was split — every audit item and technique above lives verbatim in its `references/` file.
@@ -1,31 +0,0 @@
1
- # Upgrade techniques
2
-
3
- Load this file during the Fix step, once the audit has identified which categories need work. High-impact techniques to replace generic patterns, grouped by Typography, Layout, Motion, and Surface upgrades.
4
-
5
- ## Upgrade Techniques
6
-
7
- When upgrading a project, pull from these high-impact techniques to replace generic patterns:
8
-
9
- ### Typography Upgrades
10
- - **Variable font animation.** Interpolate weight or width on scroll or hover for text that feels alive.
11
- - **Outlined-to-fill transitions.** Text starts as a stroke outline and fills with color on scroll entry or interaction.
12
- - **Text mask reveals.** Large typography acting as a window to video or animated imagery behind it.
13
-
14
- ### Layout Upgrades
15
- - **Broken grid / asymmetry.** Elements that deliberately ignore column structure — overlapping, bleeding off-screen, or offset with calculated randomness.
16
- - **Whitespace maximization.** Aggressive use of negative space to force focus on a single element.
17
- - **Parallax card stacks.** Sections that stick and physically stack over each other during scroll.
18
- - **Split-screen scroll.** Two halves of the screen sliding in opposite directions.
19
-
20
- ### Motion Upgrades
21
- - **Smooth scroll with inertia.** Decouple scrolling from browser defaults for a heavier, cinematic feel.
22
- - **Staggered entry.** Elements cascade in with slight delays, combining Y-axis translation with opacity fade. Never mount everything at once.
23
- - **Spring physics.** Replace linear easing with spring-based motion for a natural, weighty feel on all interactive elements.
24
- - **Scroll-driven reveals.** Content entering through expanding masks, wipes, or draw-on SVG paths tied to scroll progress.
25
-
26
- ### Surface Upgrades
27
- - **True glassmorphism.** Go beyond `backdrop-filter: blur`. Add a 1px inner border and a subtle inner shadow to simulate edge refraction.
28
- - **Spotlight borders.** Card borders that illuminate dynamically under the cursor.
29
- - **Grain and noise overlays.** A fixed, pointer-events-none overlay with subtle noise to break digital flatness.
30
- - **Colored, tinted shadows.** Shadows that carry the hue of the background rather than using generic black.
31
-