sync: workspace completo — sistema de memória Gitea + pulse-memory/pulse-skills/pulse-docs/pulse-projects + memória 2026-05-20
This commit is contained in:
+96
-73
@@ -4,7 +4,81 @@ _Registro de padrões que funcionam, para replicar._
|
||||
|
||||
---
|
||||
|
||||
## [LRN-20260519-001] category
|
||||
## [LRN-20260520-003] gitea-api-autenticacao-completa
|
||||
|
||||
**Logged**: 2026-05-20T12:31:00-03:00
|
||||
**Priority**: high
|
||||
**Status**: reference
|
||||
**Area**: devops | api
|
||||
|
||||
### Summary
|
||||
Gitea API suporta 5 métodos de autenticação — todos usam o mesmo API token
|
||||
|
||||
### Details
|
||||
Fontes estudadas: https://docs.gitea.com/development/api-usage
|
||||
|
||||
**Métodos de autenticação (ordem de preferência):**
|
||||
1. `Authorization: token <hash>` — mais comum, não usa username na URL
|
||||
2. `token=<hash>` query string — simples para curl/GETs
|
||||
3. `access_token=<hash>` query string — compat OAuth2 consumers
|
||||
4. HTTP Basic (`username:password`) — cria token, admin
|
||||
5. HTTP Basic + OTP — quando 2FA habilitado (`X-Gitea-OTP: 123456`)
|
||||
6. SSH HTTP Signature — chaves SSH registradas, draft-cavage-http-signatures
|
||||
|
||||
**Token nunca é reexibido** — apare | |:"`name":"meu-token","sha1":"9fcb11..."` — só sha1 na listagem /**/
|
||||
**Scopes**: formato `<read|write>:<permission>`, ou `all` para tudo.
|
||||
Permissions: activitypub, admin, issue, misc, notification, organization, package, repository, user
|
||||
|
||||
**Pagination**: `?page=N&limit=N`, header `Link` (`rel=next/last`), `x-total-count`
|
||||
|
||||
**Sudo (admin)**: adicionar `Sudo: username` header ou param `sudo=username`
|
||||
|
||||
### Suggested Action
|
||||
Usar sempre `scopes:["all"]` para automação, guardar token em segredo,
|
||||
preferir header `Authorization: token` sobre query string.
|
||||
|
||||
### Metadata
|
||||
- Source: documentation
|
||||
- Tags: gitea, api, auth, token, swagger, devops
|
||||
- Pattern-Key: gitea-api.authentication
|
||||
- Recurrence-Count: 1
|
||||
|
||||
---
|
||||
|
||||
## [LRN-20260520-004] gitea-api-endpoints-reference
|
||||
|
||||
**Logged**: 2026-05-20T12:31:00-03:00
|
||||
**Priority**: medium
|
||||
**Status**: reference
|
||||
**Area**: devops | api
|
||||
|
||||
### Summary
|
||||
Mapa dos endpoints Gitea API v1 por domínio
|
||||
|
||||
### Details
|
||||
- **Usuário**: `GET /api/v1/user`, `GET /api/v1/users/:username`
|
||||
- **Repos**: `GET/POST /api/v1/user/repos`, `GET /api/v1/repos/:owner/:repo`
|
||||
- **Issues**: `GET/POST /api/v1/repos/:owner/:repo/issues`
|
||||
- **Pulls**: `GET/POST /api/v1/repos/:owner/:repo/pulls`
|
||||
- **Webhooks**: `GET/POST /api/v1/repos/:owner/:repo/hooks`
|
||||
- **Admin users**: `GET/POST/PUT/DELETE /api/v1/admin/users`
|
||||
- **Swagger**: `https://host/api/swagger`
|
||||
- **OpenAPI JSON**: `https://host/swagger.v1.json`
|
||||
|
||||
### Suggested Action
|
||||
Consultar SKILL.md `skills/gitea-api/SKILL.md` antes de usar a API.
|
||||
|
||||
### Metadata
|
||||
- Source: documentation
|
||||
- Tags: gitea, api, endpoints, rest
|
||||
- Pattern-Key: gitea-api.endpoints
|
||||
- Recurrence-Count: 1
|
||||
|
||||
---
|
||||
|
||||
<!-- entradas anteriores acima -->
|
||||
|
||||
## [LRN-20260519-001] clawhub.cli_path
|
||||
|
||||
**Logged**: 2026-05-19T20:39:00-03:00
|
||||
**Priority**: high
|
||||
@@ -50,8 +124,6 @@ Fazer múltiplas searches com termos curtos e depois filtrar manualmente.
|
||||
|
||||
---
|
||||
|
||||
<!-- Novas entradas acima desta linha -->
|
||||
|
||||
## [LRN-20260519-003] biblioteca-compartilhada-libs
|
||||
|
||||
**Logged**: 2026-05-19T21:30:00-03:00
|
||||
@@ -60,61 +132,44 @@ Fazer múltiplas searches com termos curtos e depois filtrar manualmente.
|
||||
**Area**: config
|
||||
|
||||
### Summary
|
||||
Criar biblioteca inteligente compartilhada em `libs/` para reuso entre projetos, com conhecimento extraído de todas as skills instaladas.
|
||||
Criar biblioteca inteligente compartilhada em `libs/` para reuso entre projetos
|
||||
|
||||
### 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`
|
||||
Toda skill instalada tem conhecimento valioso. Centralizar em `libs/<dominio>/`:
|
||||
- skills são extraídas e promovidas para arquivos .md limpos
|
||||
- novos projetos copiam `libs/` como template
|
||||
- o agente consulta `libs/` antes de implementar
|
||||
|
||||
### Metadata
|
||||
- Source: best_practice
|
||||
- Tags: biblioteca, reuso, padroes, compartilhamento
|
||||
- Tags: biblioteca, reuso, padroes
|
||||
- Pattern-Key: libs.shared_knowledge_base
|
||||
- Recurrence-Count: 1
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
## [LRN-20260519-004] vitest-jsdom-global-mocks
|
||||
|
||||
## [LRN-20260519-004] category
|
||||
**Logged**: 2026-05-19T23:10:00-03:00
|
||||
**Priority**: high
|
||||
**Status**: pending
|
||||
**Status**: applied
|
||||
**Area**: testing
|
||||
|
||||
### Summary
|
||||
Vitest jsdom — mocks obrigatórios antes de renderizar hooks que usam APIs do navegador
|
||||
Vitest jsdom — mocks globais 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`.
|
||||
`localStorage`, `navigator.clipboard`, `window.matchMedia` não existem no jsdom puro — mockar em `beforeAll/beforeEach` global.
|
||||
|
||||
### Metadata
|
||||
- Source: best_practice
|
||||
- Tags: vitest, jsdom, mocks, testing
|
||||
- Pattern-Key: vitest.jsdom.mocks
|
||||
- Recurrence-Count: 3
|
||||
- Recurrence-Count: 3 → promoted
|
||||
|
||||
---
|
||||
|
||||
## [LRN-20260519-005] category
|
||||
## [LRN-20260519-005] react-testing-library-hooks-async
|
||||
|
||||
**Logged**: 2026-05-19T23:10:00-03:00
|
||||
**Priority**: medium
|
||||
**Status**: pending
|
||||
@@ -124,31 +179,13 @@ Criar um arquivo `tests/setup.ts` com todos os mocks globais e importar em `vite
|
||||
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');
|
||||
});
|
||||
```
|
||||
Sempre envolver awaits em `act(async () => { ... })`, nunca acessar `result.current` após await diretamente fora de `act()`.
|
||||
|
||||
### Metadata
|
||||
- Source: best_practice
|
||||
- Tags: react, testing-library, hooks, async, vitest
|
||||
- Pattern-Key: react.testing-library
|
||||
- Recurrence-Count: 3
|
||||
- Recurrence-Count: 3 → promoted
|
||||
|
||||
---
|
||||
|
||||
@@ -160,25 +197,14 @@ it('descrição', async () => {
|
||||
**Area**: testing
|
||||
|
||||
### Summary
|
||||
Vitest jsdom puro — matchers nativos DOM valem mais que `@testing-library/jest-dom` para projetos pequenos
|
||||
Vitest jsdom puro — matchers nativos DOM funcionam sem `@testing-library/jest-dom`
|
||||
|
||||
### 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.
|
||||
Usar `.classList.contains()`, `.getAttribute()`, `.textContent`, `container.querySelector()` ao invés de matchers RTL. 56/56 testes verdes, 0 dependências extras.
|
||||
|
||||
### Metadata
|
||||
- Source: best_practice
|
||||
- Tags: vitest, jsdom, testing, dom, pure-matchers
|
||||
- Tags: vitest, jsdom, testing, matchers
|
||||
- Pattern-Key: vitest.pure-dom-matchers
|
||||
- Recurrence-Count: 1
|
||||
|
||||
@@ -192,16 +218,13 @@ Padronizar esta abordagem em todos os arquivos de teste. Só instalar `@testing-
|
||||
**Area**: testing
|
||||
|
||||
### Summary
|
||||
No jsdom, `value` de `<input>` não é writable — `fireEvent.change` não atualiza `input.value` diretamente
|
||||
No jsdom, `Object.defineProperty(input, 'value', { writable: true })` permite `fireEvent.change`
|
||||
|
||||
### 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.
|
||||
Workaround mínimo para testar onChange em inputs no jsdom puro, onde `.value` é readonly.
|
||||
|
||||
### Metadata
|
||||
- Source: error
|
||||
- Tags: jsdom, fireEvent, input, value, onChange
|
||||
- Tags: jsdom, fireEvent, input, value
|
||||
- Pattern-Key: jsdom.fireEvent-change-writable
|
||||
- Recurrence-Count: 1
|
||||
|
||||
Reference in New Issue
Block a user