Files
pulse-libs/.learnings/LEARNINGS.md
T

208 lines
6.4 KiB
Markdown

# Learnings — Padrões bem-sucedidos
_Registro de padrões que funcionam, para replicar._
---
## [LRN-20260519-001] category
**Logged**: 2026-05-19T20:39:00-03:00
**Priority**: high
**Status**: pending
**Area**: config
### Summary
Instalar skills do Clawhub com `/var/lib/openclaw/tools/node/npm/bin/clawhub`
### Details
O CLI `clawhub` não está no `$PATH` global, mas existe instalado em `/var/lib/openclaw/tools/node/npm/bin/clawhub`. Sempre usar o caminho completo.
### Suggested Action
Adicionar symlink ou alias para `clawhub` no PATH do agente, ou sempre usar o caminho completo.
### Metadata
- Source: error
- Tags: clawhub, cli, path, install
- Pattern-Key: clawhub.cli_path
---
## [LRN-20260519-002] clawhub-search-qc
**Logged**: 2026-05-19T20:42:00-03:00
**Priority**: medium
**Status**: pending
**Area**: config
### Summary
`clawhub search` com termos muito específicos retorna vazio; usar termos genéricos primeiro
### Details
Pesquisas com termos combinados como "programming developer full-stack" retornaram vazio. Termos simples como "autonomous agent" retornaram resultados. Melhor abordar a pesquisa em múltiplas queries curtas.
### Suggested Action
Fazer múltiplas searches com termos curtos e depois filtrar manualmente.
### Metadata
- Source: error
- Tags: clawhub, search, query
- Pattern-Key: clawhub.search_strategy
---
<!-- Novas entradas acima desta linha -->
## [LRN-20260519-003] biblioteca-compartilhada-libs
**Logged**: 2026-05-19T21:30:00-03:00
**Priority**: medium
**Status**: pending
**Area**: config
### Summary
Criar biblioteca inteligente compartilhada em `libs/` para reuso entre projetos, com conhecimento extraído de todas as skills instaladas.
### Details
Toda skill que instalamos tem conhecimento valioso (padrões, gotchas, templates).
Ao invés de cada agente lembrar de cor, centralize em `libs/<dominio>/`:
- skills são extraídas e promovidas para arquivos .md limpos na biblioteca
- novos projetos copiam `libs/` como template de padrões
- o próprio agente consulte `libs/` antes de implementar qualquer coisa
### Suggested Action
Quando instalar nova skill:
1. Ler o SKILL.md
2. Extrair o conhecimento útil
3. Promover para `libs/<dominio>/` apropriado
4. Atualizar `libs/INDEX.md`
### Metadata
- Source: best_practice
- Tags: biblioteca, reuso, padroes, compartilhamento
- Pattern-Key: libs.shared_knowledge_base
- Recurrence-Count: 1
---
---
## [LRN-20260519-004] category
**Logged**: 2026-05-19T23:10:00-03:00
**Priority**: high
**Status**: pending
**Area**: testing
### Summary
Vitest jsdom — mocks obrigatórios antes de renderizar hooks que usam APIs do navegador
### Details
No ambiente jsdom:
- `localStorage` não existe → mock com `Object.defineProperty(global, 'localStorage', ...)` antes de qualquer hook useLocalStorage
- `navigator.clipboard` não existe → mock antes de useClipboard
- `window.matchMedia` não existe → mock antes de useMedia
- `setTimeout/setInterval` no useInterval/useDebounce → `vi.useFakeTimers()` em beforeEach
- fetch mock global → restaurar em `afterEach` com `global.fetch = originalFetch`
### Suggested Action
Criar um arquivo `tests/setup.ts` com todos os mocks globais e importar em `vitest.config.ts`.
### Metadata
- Source: best_practice
- Tags: vitest, jsdom, mocks, testing
- Pattern-Key: vitest.jsdom.mocks
- Recurrence-Count: 3
---
## [LRN-20260519-005] category
**Logged**: 2026-05-19T23:10:00-03:00
**Priority**: medium
**Status**: pending
**Area**: testing
### Summary
React Testing Library — renderHook + act() para testar hooks assíncronos
### Details
Hooks que fazem async operations (useAsync, useFetch, useClipboard):
1. `renderHook` retorna `{ result }`
2. Para atualizações async, sempre envolva em `act(async () => { await ... })`
3. Para等待 promises: `await act(async () => { await new Promise(r => setTimeout(r, ms)); })`
4. Com fakeTimers: `act(() => { vi.advanceTimersByTime(ms); })`
5. Nunca acesse `result.current` diretamente após um await async — sempre dentro de act()
### Suggested Action
Template de teste async:
```ts
it('descrição', async () => {
global.fetch = vi.fn(() => Promise.resolve(makeRes(200, body))) as any;
const { result } = renderHook(() => useFetch<T>('/url', {}));
await act(async () => { await new Promise(r => setTimeout(r, 50)); });
expect(result.current.status).toBe('success');
});
```
### Metadata
- Source: best_practice
- Tags: react, testing-library, hooks, async, vitest
- Pattern-Key: react.testing-library
- Recurrence-Count: 3
---
## [LRN-20260520-001] vitest-pure-dom-matchers
**Logged**: 2026-05-20T00:52:00-03:00
**Priority**: high
**Status**: applied
**Area**: testing
### Summary
Vitest jsdom puro — matchers nativos DOM valem mais que `@testing-library/jest-dom` para projetos pequenos
### Details
Problema: `@testing-library/jest-dom` não estava instalado. Erros \"Invalid Chai property: toHaveClass\" apareceram em 44 testes.
Solução aplicada: trocar todos os 56 testes de componentes para usar:
- `.classList.contains('bg-indigo-600')` ao invés de `.toHaveClass('bg-indigo-600')`
- `.getAttribute('id')` ao invés de `.toHaveAttribute('id', 'x')`
- `.textContent` / `container.querySelector()` ao invés de `screen.getByText()
- `tagName` ao invés de `getByRole('heading')`
Resultado: 56/56 testes verdes, 0 dependências extras.
### Suggested Action
Padronizar esta abordagem em todos os arquivos de teste. Só instalar `@testing-library/jest-dom` se surgir matcher que não dá para escrever com `.classList.contains()` nativo.
### Metadata
- Source: best_practice
- Tags: vitest, jsdom, testing, dom, pure-matchers
- Pattern-Key: vitest.pure-dom-matchers
- Recurrence-Count: 1
---
## [LRN-20260520-002] jsdom-fireEvent-writable-value
**Logged**: 2026-05-20T00:52:00-03:00
**Priority**: low
**Status**: workaround
**Area**: testing
### Summary
No jsdom, `value` de `<input>` não é writable — `fireEvent.change` não atualiza `input.value` diretamente
### Details
Worksaround: `Object.defineProperty(inp, 'value', { writable: true, value: 'abc' })` antes de `fireEvent.change(inp)`. Confirmado como solução mínima para testes de `onChange` em estruturas Tree AST plantes como jsdom.
### Suggested Action
Criar helper `test-utils.ts` com `setInputValue(el, val)` para encapsular o workaround.
### Metadata
- Source: error
- Tags: jsdom, fireEvent, input, value, onChange
- Pattern-Key: jsdom.fireEvent-change-writable
- Recurrence-Count: 1