ganbatte-os 0.2.20 → 0.2.21

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.
@@ -0,0 +1,218 @@
1
+ # T-104 — Hook de contexto para branch Storybook
2
+
3
+ **Sprint:** S07 · **Due:** 2026-04-19 · **Prioridade:** normal · **Pts:** 2
4
+ **ClickUp:** https://app.clickup.com/t/86agxge41
5
+ **Assignee:** Douglas Oliveira · **Status:** ✅ concluída (2026-04-17)
6
+
7
+ ---
8
+
9
+ ## Notas de execução (2026-04-17)
10
+
11
+ - Hook (`.claude/hooks/storybook-branch-check.sh`) e matchers em `.claude/settings.json` já estavam implementados e válidos (AC1–AC5 ✓).
12
+ - Criado smoke test em `.gos/tests/hooks/storybook-branch-check.test.sh` — **4/4 PASS** (branch atual `dev`).
13
+ - **Bug no fixture do plano corrigido na execução:** o exemplo original `"edite a story do Button"` não casava o regex `storybook|\.stories\.|\.storybook` (palavra "story" isolada não é match). Ajustado para `"edite a story do Button no storybook"`.
14
+ - Adicionada seção `## Context hook (T-104)` ao final de `docs/fractus/deploy-storybook.md`.
15
+ - Não foi feito commit/push — conforme convenção (Douglas commita).
16
+
17
+ ---
18
+
19
+ ## Contexto
20
+
21
+ Trabalho de Storybook no Fractus deve acontecer exclusivamente na branch `feat/storybook` (ver memória `reference_vercel_storybook.md` e `feedback_storybook_deploy_douglas.md`). Devs/agentes esquecem e editam `*.stories.tsx` em `master`/`dev`, gerando PRs que o workflow `auto-merge-feat-storybook.yml` rejeita.
22
+
23
+ Solução: hook Claude Code que injeta lembrete contextual em dois momentos:
24
+ 1. **UserPromptSubmit** — prompt menciona "storybook" ou `.stories.`
25
+ 2. **PreToolUse(Write|Edit)** — tool_input.file_path contém `.stories.` ou `.storybook`
26
+
27
+ O hook **já está implementado** em `.claude/hooks/storybook-branch-check.sh` (48 linhas) e registrado em `.claude/settings.json:6-30`. Esta task portanto é **validação + documentação + fechamento**.
28
+
29
+ ## Arquivos afetados
30
+
31
+ | Arquivo | Ação |
32
+ |---|---|
33
+ | `.claude/hooks/storybook-branch-check.sh` | [REVISAR] já existe, confirmar lógica |
34
+ | `.claude/settings.json` | [REVISAR] matchers UserPromptSubmit + PreToolUse |
35
+ | `.gos/tests/hooks/storybook-branch-check.test.sh` | [NOVO] script de smoke test com fixtures |
36
+ | `docs/fractus/deploy-storybook.md` | [EDITAR] adicionar seção "Context hook" |
37
+
38
+ ## Passo a passo
39
+
40
+ ### 1. Auditar hook atual
41
+
42
+ ```bash
43
+ cat .claude/hooks/storybook-branch-check.sh
44
+ cat .claude/settings.json
45
+ ```
46
+
47
+ Checklist do AC (revisar no script):
48
+ - Linha 30: `grep -iqE 'storybook|\.stories\.|\.storybook'` → cobre AC1+AC2 ✓
49
+ - Linha 38: `git -C "$fractus_dir" branch --show-current` → lê branch do fractus ✓
50
+ - Linha 43-45: warning só se branch != `feat/storybook` → cobre AC3+AC4 ✓
51
+ - Linha 48: `exit 0` → cobre AC5 ✓
52
+
53
+ ### 2. Confirmar branch existe no remoto
54
+
55
+ ```bash
56
+ cd packages/fractus
57
+ git ls-remote origin feat/storybook
58
+ # Deve retornar um hash. Se vazio, criar:
59
+ # git fetch && git checkout -b feat/storybook origin/master && git push -u origin feat/storybook
60
+ ```
61
+
62
+ ### 3. Criar script de smoke test
63
+
64
+ Novo `.gos/tests/hooks/storybook-branch-check.test.sh`:
65
+
66
+ ```bash
67
+ #!/usr/bin/env bash
68
+ # Smoke test do hook storybook-branch-check.sh
69
+ set -e
70
+
71
+ HOOK=".claude/hooks/storybook-branch-check.sh"
72
+ export CLAUDE_PROJECT_DIR="$(pwd)"
73
+
74
+ echo "=== Test 1: UserPromptSubmit com 'storybook' em branch errada ==="
75
+ # Mock: fractus em branch master (presumido)
76
+ OUT=$(echo '{"user_prompt":"edite a story do Button"}' | bash "$HOOK")
77
+ if [[ "$OUT" == *"STORYBOOK BRANCH CONTEXT"* ]]; then
78
+ echo "PASS: warning injetado"
79
+ else
80
+ echo "FAIL: warning não apareceu. Output: $OUT"
81
+ exit 1
82
+ fi
83
+
84
+ echo "=== Test 2: prompt sem storybook (silencioso) ==="
85
+ OUT=$(echo '{"user_prompt":"liste as tasks abertas"}' | bash "$HOOK")
86
+ if [[ -z "$OUT" ]]; then
87
+ echo "PASS: silencioso"
88
+ else
89
+ echo "FAIL: deveria ser silencioso. Output: $OUT"
90
+ exit 1
91
+ fi
92
+
93
+ echo "=== Test 3: PreToolUse em .stories.tsx em branch errada ==="
94
+ OUT=$(echo '{"tool_input":{"file_path":"/e/Github/Ganbatte/packages/fractus/src/components/Button.stories.tsx"}}' | bash "$HOOK")
95
+ if [[ "$OUT" == *"STORYBOOK BRANCH CONTEXT"* ]]; then
96
+ echo "PASS: warning injetado por file_path"
97
+ else
98
+ echo "FAIL. Output: $OUT"
99
+ exit 1
100
+ fi
101
+
102
+ echo "=== Test 4: exit code sempre 0 ==="
103
+ echo '{}' | bash "$HOOK" ; echo "exit=$?" # esperado: 0
104
+
105
+ echo ""
106
+ echo "✅ Todos os testes passaram"
107
+ ```
108
+
109
+ ```bash
110
+ chmod +x .gos/tests/hooks/storybook-branch-check.test.sh
111
+ bash .gos/tests/hooks/storybook-branch-check.test.sh
112
+ ```
113
+
114
+ ### 4. Smoke test manual ponta a ponta
115
+
116
+ No Claude Code:
117
+ - Sessão em `master` do fractus: digitar "editar a story do Button" → aguardar warning na resposta do assistente.
118
+ - `cd packages/fractus && git checkout feat/storybook` → mesmo prompt → sem warning.
119
+ - Voltar pra master: `Edit` em arquivo `.stories.tsx` → warning aparece no contexto injetado.
120
+
121
+ ### 5. Documentar
122
+
123
+ Adicionar em `docs/fractus/deploy-storybook.md`, seção nova ao final:
124
+
125
+ ```markdown
126
+ ## Context hook (T-104)
127
+
128
+ Claude Code tem um hook local (`.claude/hooks/storybook-branch-check.sh`) que
129
+ injeta um lembrete quando prompts ou edições tocam em Storybook e a branch
130
+ atual não é `feat/storybook`. Sempre `exit 0` — nunca bloqueia.
131
+
132
+ Matchers em `.claude/settings.json`:
133
+ - `UserPromptSubmit` (qualquer prompt)
134
+ - `PreToolUse` com matcher `Write|Edit`
135
+
136
+ O hook detecta Storybook via regex `storybook|\.stories\.|\.storybook` no
137
+ texto do prompt ou no `tool_input.file_path`/`command`.
138
+
139
+ Para validar: `bash .gos/tests/hooks/storybook-branch-check.test.sh`.
140
+ ```
141
+
142
+ ## Critérios de aceite (literais)
143
+
144
+ - **AC1:** Hook dispara em `UserPromptSubmit` quando prompt menciona storybook.
145
+ - **AC2:** Hook dispara em `PreToolUse (Write/Edit)` para arquivos `.stories.*`.
146
+ - **AC3:** Injeta lembrete se branch não for `feat/storybook`.
147
+ - **AC4:** Silencioso na branch correta.
148
+ - **AC5:** Nunca bloqueia (exit 0).
149
+
150
+ ## Verificação end-to-end
151
+
152
+ - [ ] `bash .gos/tests/hooks/storybook-branch-check.test.sh` — todos os 4 testes PASS
153
+ - [ ] Smoke manual (passo 4) — warning aparece em branch errada, silencioso em `feat/storybook`
154
+ - [ ] `echo '{}' | bash .claude/hooks/storybook-branch-check.sh; echo $?` → `0`
155
+ - [ ] docs/fractus/deploy-storybook.md tem seção "Context hook"
156
+
157
+ ## Entrega ao Douglas (**NÃO commitar, NÃO dar push**)
158
+
159
+ > ⚠️ Dev **NÃO commita**. Douglas valida e commita.
160
+
161
+ Fluxo do dev:
162
+ 1. Rodar script de teste — colar output.
163
+ 2. Smoke manual — screenshot/texto do warning aparecendo.
164
+ 3. `git status && git diff --stat` — colar em evidência.
165
+ 4. Avisar Douglas.
166
+
167
+ ### Mensagem de commit sugerida (Douglas usa)
168
+
169
+ ```
170
+ feat(claude-hooks): validar hook storybook-branch-check + doc + smoke test
171
+
172
+ Refs T-104
173
+
174
+ - Script de smoke test em .gos/tests/hooks/
175
+ - Seção "Context hook" em docs/fractus/deploy-storybook.md
176
+ - 4/4 smoke tests PASS
177
+ ```
178
+
179
+ ## Rollback
180
+
181
+ ```bash
182
+ rm -f .gos/tests/hooks/storybook-branch-check.test.sh
183
+ git restore docs/fractus/deploy-storybook.md
184
+ ```
185
+
186
+ O hook em si já estava comitado antes — não mexer.
187
+
188
+ ## Dependências e bloqueios
189
+
190
+ - **Independente.** Pode rodar em paralelo com T-110.
191
+ - **Risco:** se `feat/storybook` não existir no remoto, AC4 não pode ser validado. Criar antes.
192
+
193
+ ## Checklist de entrega
194
+
195
+ - [ ] AC1-AC5 verificados com smoke tests
196
+ - [ ] `bash .gos/tests/hooks/storybook-branch-check.test.sh` PASS
197
+ - [ ] Smoke manual em branch errada + correta
198
+ - [ ] `docs/fractus/deploy-storybook.md` atualizado
199
+ - [ ] `git status` e `git diff --stat` colados
200
+ - [ ] **NÃO fiz commit nem push**
201
+ - [ ] Douglas notificado
202
+
203
+ ## Checklist do Douglas
204
+
205
+ - [ ] Revisar diff
206
+ - [ ] Rodar script de teste localmente
207
+ - [ ] Commit+push com mensagem sugerida
208
+ - [ ] ClickUp T-104 → `complete`
209
+
210
+ ## Evidência de entrega
211
+
212
+ ```
213
+ # smoke test output
214
+ (output)
215
+
216
+ # git diff --stat
217
+ (output)
218
+ ```
@@ -0,0 +1,355 @@
1
+ # T-110 — Resolver drift TypeScript + instalar pre-commit hook (fractus)
2
+
3
+ **Sprint:** S07 · **Due:** 2026-04-17 · **Prioridade:** high · **Pts:** ~5-8
4
+ **ClickUp:** https://app.clickup.com/t/86agy94tb
5
+ **Assignee:** Douglas Oliveira
6
+ **Status:** ✅ **CONCLUÍDA** (validada empiricamente em 2026-04-17)
7
+
8
+ ---
9
+
10
+ ## ✅ Conclusão validada — 2026-04-17
11
+
12
+ Todos os 7 ACs do plano original verificados empiricamente. Evidências abaixo.
13
+
14
+ | AC | Resultado | Evidência |
15
+ |-----|-----------|-----------|
16
+ | AC1 | ✅ | `src/types/supabase.ts` regenerado (26.697 bytes, 17/04 11:00). `programas`/`patrocinadores`: **0 ocorrências**. `investidores`/`projeto_investidores`: **5 ocorrências** (schema atual do banco). |
17
+ | AC2 | ✅ | `src/lib/validations/projeto.ts` existe com `projetoSchema` + `ProjetoInput`. |
18
+ | AC3 | ✅ | `grep -r "programSchema\|ProgramInput"` em `src/` → **0 arquivos**. Imports renomeados. |
19
+ | AC4 | ✅ | `PageHeader` tipando `breadcrumbs` corretamente — confirmado via `tsc --noEmit` exit 0. |
20
+ | AC5 | ✅ | `tsc --noEmit 2>&1 \| grep -c TS7006` → **0**. |
21
+ | AC6 | ✅ | `npx tsc --noEmit; echo $?` → **exit 0** (zero erros, de 82 originais). |
22
+ | AC7 | ✅ | `.git/hooks/pre-commit` instalado (175 bytes, executável `-rwxr-xr-x`), delega para `.gos/scripts/hooks/pre-commit-validate.js` via `GANBATTE_ROOT`. |
23
+
24
+ ### Comandos de validação (reproduzíveis)
25
+
26
+ ```bash
27
+ cd packages/fractus
28
+ npx tsc --noEmit; echo "exit=$?" # → exit=0
29
+ ls -la .git/hooks/pre-commit # → -rwxr-xr-x, 175 bytes
30
+ grep -r "programSchema\|ProgramInput" src | wc -l # → 0
31
+ grep -c "programas\|patrocinadores" src/types/supabase.ts # → 0
32
+ ```
33
+
34
+ ---
35
+
36
+ ## ⚠️ Escopo residual (fora desta task) — [PRD 2026-04-17]
37
+
38
+ O PRD novo exige rename adicional `Investidor → Financiador` (M4 em [impacto-tasks-clickup.md](../../../packages/fractus/docs/regras-de-negocio/impacto-tasks-clickup.md)). **Isto não estava no plano original da T-110 e não bloqueia o fechamento dela.**
39
+
40
+ Ação: **abrir task nova** (ex.: T-111) cobrindo:
41
+ 1. Migration `financiadores` + `projeto_financiadores` (renomear tabelas).
42
+ 2. Regerar `supabase.ts`.
43
+ 3. Renomear `src/lib/validations/investidor*` → `financiador*`, paths `/dashboard/investidores/` → `/dashboard/financiadores/`, tabelas em server actions.
44
+ 4. 10 arquivos ainda referenciando `investidor*` (ver grep): `src/app/dashboard/investidores/`, `src/components/domain/sponsors/`, `src/components/domain/investors/`, `src/app/actions/investors/actions.ts`, `src/app/actions/projects/actions.ts`, `src/app/dashboard/projetos/[id]/page.tsx`, `src/lib/validations/projeto.ts`, `src/components/ui/delete-dialog.stories.tsx`.
45
+
46
+ Referências:
47
+ - [packages/fractus/docs/prd.md](../../../packages/fractus/docs/prd.md) §Glossário
48
+ - [packages/fractus/docs/regras-de-negocio/impacto-tasks-clickup.md](../../../packages/fractus/docs/regras-de-negocio/impacto-tasks-clickup.md) M4
49
+
50
+ ---
51
+
52
+ ## Contexto
53
+
54
+ Após a T-095 (validação tipada de env vars com Zod + server-only), `npx tsc --noEmit` em `packages/fractus` retornou **82 erros em ~20 arquivos**. A causa-raiz é drift acumulado após a T-092 (renomeação de domínio: `programas → projetos`, `patrocinadores → investidores`, `formularios → pesquisas`):
55
+
56
+ 1. `src/types/supabase.ts` (26.7 KB, gerado 16/abr 22:04) ainda reflete o schema antigo — migration `supabase/migrations/20260412000000_prd_alignment.sql` renomeou no banco mas os tipos **não foram regenerados**.
57
+ 2. `src/lib/validations/program.ts` só exporta `programSchema`/`ProgramInput`; server actions e componentes que foram renomeados (`projects/`, `investors/`) importam `projetoSchema`/`ProjetoInput` que ainda não existem.
58
+ 3. `PageHeader` espera `breadcrumbs?: React.ReactNode` mas 5 pages passam array `[{label, href}]`.
59
+ 4. Callbacks `.map/.filter` em 10+ lugares sem anotação de tipo → `implicit any`.
60
+ 5. Pages legadas `/dashboard/patrocinadores/` e `/dashboard/programas/` continuam no repositório mesmo com as rotas novas ativas.
61
+ 6. `.git/hooks/pre-commit` **não existe**; `pre-commit-validate.js` (em `.gos/scripts/hooks/`) já está pronto, só falta instalar.
62
+
63
+ Sem isso, qualquer CI/CD com tsc gate e o `gos:doctor` falham. Esta task desbloqueia todas as outras da sprint.
64
+
65
+ ## Arquivos afetados
66
+
67
+ | Arquivo | Ação |
68
+ |---|---|
69
+ | `packages/fractus/src/types/supabase.ts` | [REGENERAR] via supabase CLI |
70
+ | `packages/fractus/src/lib/validations/projeto.ts` | [NOVO] com `projetoSchema` + `ProjetoInput` |
71
+ | `packages/fractus/src/lib/validations/program.ts` | [DELETAR] após confirmar zero imports |
72
+ | `packages/fractus/src/lib/validations/investidor.ts` | [NOVO] (se `patrocinador.ts` existia, substituir) |
73
+ | `packages/fractus/src/app/actions/projects/actions.ts:5` | [EDITAR] import |
74
+ | `packages/fractus/src/app/actions/investors/actions.ts` | [EDITAR] refs à tabela `investidores` |
75
+ | `packages/fractus/src/components/domain/projects/create-project-dialog.tsx:29` | [EDITAR] import |
76
+ | `packages/fractus/src/components/layout/page-header.tsx:16` | [EDITAR] ampliar tipo de `breadcrumbs` |
77
+ | `packages/fractus/src/app/dashboard/instancias/[id]/page.tsx:51` | [EDITAR] breadcrumbs consumer |
78
+ | `packages/fractus/src/app/dashboard/participantes/*/page.tsx` | [EDITAR] breadcrumbs consumer |
79
+ | `packages/fractus/src/app/dashboard/patrocinadores/` | [REMOVER] rota legada |
80
+ | `packages/fractus/src/app/dashboard/programas/` | [REMOVER] rota legada |
81
+ | `packages/fractus/.git/hooks/pre-commit` | [NOVO] shell que delega para `pre-commit-validate.js` |
82
+
83
+ ## Passo a passo
84
+
85
+ ### 1. Regenerar tipos Supabase (AC1)
86
+
87
+ ```bash
88
+ cd packages/fractus
89
+
90
+ # Opção A — supabase local rodando
91
+ npx supabase status # confirmar que está up
92
+ npx supabase gen types typescript --local > src/types/supabase.ts
93
+
94
+ # Opção B — projeto remoto
95
+ npx supabase login # se ainda não logado
96
+ npx supabase gen types typescript --project-id <PROJECT_ID> > src/types/supabase.ts
97
+ ```
98
+
99
+ > **Troubleshooting:** se `supabase` CLI não instalada, `pnpm add -D supabase`. PROJECT_ID está em `supabase/config.toml` (`project_id = "fractus"`).
100
+
101
+ Validação:
102
+ ```bash
103
+ grep -E "investidores|projetos|projeto_investidores" src/types/supabase.ts | head
104
+ # Deve retornar ≥3 ocorrências
105
+ grep -E "programas|patrocinadores" src/types/supabase.ts
106
+ # Deve retornar 0 ocorrências
107
+ ```
108
+
109
+ ### 2. Criar `projetoSchema` e `ProjetoInput` (AC2)
110
+
111
+ Novo arquivo `packages/fractus/src/lib/validations/projeto.ts`:
112
+
113
+ ```ts
114
+ import { z } from 'zod'
115
+
116
+ export const projetoSchema = z.object({
117
+ nome: z.string().min(3, "Nome deve ter pelo menos 3 caracteres"),
118
+ descricao: z.string().optional(),
119
+ dataInicio: z.date(),
120
+ dataFim: z.date(),
121
+ totalInscritos: z.number().int().min(0, "Total de inscritos não pode ser negativo"),
122
+ quantidadeVagas: z.number().int().min(1).optional(),
123
+ investidorIds: z.array(z.string().uuid()).optional(),
124
+ }).refine((d) => d.dataFim > d.dataInicio, {
125
+ message: "A data de término deve ser após a data de início",
126
+ path: ["dataFim"],
127
+ })
128
+
129
+ export type ProjetoInput = z.infer<typeof projetoSchema>
130
+ ```
131
+
132
+ Remover `src/lib/validations/program.ts` **após confirmar que não há mais imports dele**:
133
+ ```bash
134
+ grep -r "programSchema\|ProgramInput\|from.*validations/program" packages/fractus/src
135
+ # Deve retornar 0 resultados antes de deletar
136
+ ```
137
+
138
+ ### 3. Fix imports renomeados (AC3)
139
+
140
+ ```bash
141
+ cd packages/fractus
142
+
143
+ # Ver todos os imports antigos
144
+ grep -rn "programSchema\|ProgramInput" src
145
+ grep -rn "patrocinador\|Patrocinador" src
146
+ grep -rn "from.*'programas'\|'patrocinadores'" src
147
+ ```
148
+
149
+ Trocar em cada arquivo:
150
+ - `programSchema` → `projetoSchema`
151
+ - `ProgramInput` → `ProjetoInput`
152
+ - `patrocinadorIds` → `investidorIds`
153
+ - Table refs em Supabase queries: `'programas'` → `'projetos'`, `'patrocinadores'` → `'investidores'`, `'programa_patrocinadores'` → `'projeto_investidores'`
154
+
155
+ Pontos críticos:
156
+ - `src/app/actions/projects/actions.ts:5` — import do schema
157
+ - `src/app/actions/investors/actions.ts` — 10 erros TS2339/TS2769 no select
158
+ - `src/components/domain/projects/create-project-dialog.tsx:29` — import
159
+
160
+ ### 4. Tipar breadcrumbs (AC4)
161
+
162
+ Editar `src/components/layout/page-header.tsx`:
163
+
164
+ ```ts
165
+ export type BreadcrumbItem = { label: string; href?: string }
166
+
167
+ interface PageHeaderProps {
168
+ title: string
169
+ // antes: breadcrumbs?: React.ReactNode
170
+ breadcrumbs?: BreadcrumbItem[] | React.ReactNode
171
+ // ...resto
172
+ }
173
+
174
+ // No render:
175
+ function renderBreadcrumbs(b: PageHeaderProps['breadcrumbs']) {
176
+ if (!b) return null
177
+ if (Array.isArray(b)) {
178
+ return (
179
+ <nav className="...">
180
+ {b.map((item, i) => (
181
+ <span key={i}>
182
+ {item.href ? <Link href={item.href}>{item.label}</Link> : item.label}
183
+ {i < b.length - 1 && <span className="mx-2">/</span>}
184
+ </span>
185
+ ))}
186
+ </nav>
187
+ )
188
+ }
189
+ return b
190
+ }
191
+ ```
192
+
193
+ Pages consumers permanecem passando arrays — zero churn nos 5 arquivos.
194
+
195
+ ### 5. Resolver implicit `any` (AC5)
196
+
197
+ Rodar `npx tsc --noEmit 2>&1 | grep "TS7006"` para ver todos. Para cada:
198
+
199
+ ```ts
200
+ // antes
201
+ items.map((i) => i.nome)
202
+ // depois
203
+ items.map((i: Participante) => i.nome) // importa Participante de @/types/supabase
204
+ ```
205
+
206
+ Prefira inferência completa: se `items` vem de um `supabase.from('participantes').select()`, anote a variável superior, não o callback.
207
+
208
+ ### 6. Remover rotas legadas
209
+
210
+ ```bash
211
+ cd packages/fractus
212
+ rm -rf src/app/dashboard/patrocinadores src/app/dashboard/programas
213
+ ```
214
+
215
+ Confirmar que links na sidebar/menus apontam para `/dashboard/projetos` e `/dashboard/investidores`:
216
+ ```bash
217
+ grep -rn "dashboard/patrocinadores\|dashboard/programas" src
218
+ # Deve retornar 0
219
+ ```
220
+
221
+ ### 7. `tsc --noEmit` exit 0 (AC6)
222
+
223
+ ```bash
224
+ cd packages/fractus
225
+ npx tsc --noEmit
226
+ echo "exit=$?" # precisa imprimir "exit=0"
227
+ ```
228
+
229
+ ### 8. Instalar pre-commit hook (AC7)
230
+
231
+ Criar `packages/fractus/.git/hooks/pre-commit`:
232
+
233
+ ```bash
234
+ #!/usr/bin/env bash
235
+ # Delegate to ganbatte-os pre-commit-validate.js
236
+ set -e
237
+
238
+ # GANBATTE_ROOT = dois níveis acima de .git (packages/fractus -> Ganbatte)
239
+ GANBATTE_ROOT="$(cd "$(dirname "$0")/../../../../" && pwd)"
240
+ export GANBATTE_ROOT
241
+
242
+ node "$GANBATTE_ROOT/.gos/scripts/hooks/pre-commit-validate.js"
243
+ ```
244
+
245
+ Dar permissão executável:
246
+ ```bash
247
+ chmod +x packages/fractus/.git/hooks/pre-commit
248
+ ```
249
+
250
+ **Teste dummy** (não commitar):
251
+ ```bash
252
+ cd packages/fractus
253
+ echo "const broken: string = 123" >> src/app/page.tsx # força erro TS
254
+ git add src/app/page.tsx
255
+ git commit -m "test: should fail" # deve abortar
256
+ git restore --staged src/app/page.tsx && git checkout -- src/app/page.tsx
257
+ ```
258
+
259
+ ## Critérios de aceite (literais)
260
+
261
+ - **AC1:** Regenerar `src/types/supabase.ts` via supabase CLI — tabelas `investidores`, `projetos`, `projeto_investidores` presentes; `programas`/`patrocinadores` ausentes.
262
+ - **AC2:** Criar `projetoSchema` + `ProjetoInput` em `src/lib/validations/projeto.ts`.
263
+ - **AC3:** Fix imports renomeados nas pages — grep por `programSchema|ProgramInput|patrocinador` em `src/` retorna 0.
264
+ - **AC4:** Tipar `breadcrumbs` (ReactNode vs array) — 5 pages compilam sem TS2322.
265
+ - **AC5:** Tipar callbacks `.map/.filter` — zero TS7006.
266
+ - **AC6:** `npx tsc --noEmit` retorna exit 0.
267
+ - **AC7:** Pre-commit hook instalado em `packages/fractus/.git/hooks/pre-commit`, executável, delegando para `pre-commit-validate.js`.
268
+
269
+ ## Verificação end-to-end
270
+
271
+ - [ ] `cd packages/fractus && npx tsc --noEmit; echo $?` → `0`
272
+ - [ ] `pnpm lint` OK
273
+ - [ ] `pnpm build` OK
274
+ - [ ] `pnpm dev` e navegar `/dashboard/projetos` e `/dashboard/investidores` — página carrega sem erro 500
275
+ - [ ] Pre-commit hook testado com commit que deve falhar (arquivo com erro TS) e commit que deve passar
276
+ - [ ] `npm run gos:doctor` (root) — exit 0
277
+ - [ ] Todos os ACs (AC1 … AC7) checados
278
+
279
+ ## Entrega ao Douglas (**NÃO commitar, NÃO dar push**)
280
+
281
+ > ⚠️ **IMPORTANTE — dev NÃO executa commit nem push.** Douglas valida e commita.
282
+
283
+ Fluxo do dev:
284
+ 1. Deixar working tree sujo com todas as mudanças.
285
+ 2. `cd packages/fractus && git status > /tmp/t110-status.txt && git diff --stat > /tmp/t110-diff.txt`
286
+ 3. `pnpm lint && pnpm typecheck && pnpm build 2>&1 | tail -20` — colar última linha.
287
+ 4. Preencher Checklist de entrega e avisar Douglas em `#cspo-tech` + comment na task ClickUp.
288
+
289
+ ### Mensagem de commit sugerida (Douglas usa)
290
+
291
+ ```
292
+ fix(fractus): resolver drift TypeScript + instalar pre-commit hook
293
+
294
+ Refs T-110
295
+
296
+ - AC1: supabase.ts regenerado (investidores, projetos, projeto_investidores)
297
+ - AC2: projetoSchema + ProjetoInput em src/lib/validations/projeto.ts
298
+ - AC3: imports renomeados (programSchema→projetoSchema, patrocinador→investidor)
299
+ - AC4: PageHeader breadcrumbs aceita BreadcrumbItem[] | ReactNode
300
+ - AC5: callbacks .map/.filter tipados (zero TS7006)
301
+ - AC6: npx tsc --noEmit exit 0 (82 → 0 erros)
302
+ - AC7: .git/hooks/pre-commit instalado (delega para pre-commit-validate.js)
303
+ ```
304
+
305
+ ## Rollback
306
+
307
+ ```bash
308
+ cd packages/fractus
309
+ git checkout -- src/types/supabase.ts
310
+ git restore src/
311
+ rm -f .git/hooks/pre-commit
312
+ ```
313
+
314
+ ## Dependências e bloqueios
315
+
316
+ - **Upstream:** T-095 (env vars Zod) — fechada 16/04.
317
+ - **Downstream (bloqueia):** T-084, T-085, T-086 — CI/CD com tsc gate só roda após esta.
318
+ - **Risco:** se supabase CLI não autenticada, passo 1 trava. Mitigação: usar `supabase start` local ou solicitar credenciais ao Douglas.
319
+
320
+ ## Checklist de entrega (dev preenche antes de avisar Douglas)
321
+
322
+ - [ ] AC1 … AC7 verificados manualmente
323
+ - [ ] `pnpm lint` OK
324
+ - [ ] `pnpm typecheck` exit 0
325
+ - [ ] `pnpm build` OK
326
+ - [ ] Smoke test `/dashboard/projetos` e `/dashboard/investidores`
327
+ - [ ] Pre-commit hook testado (falha em erro TS, passa em código limpo)
328
+ - [ ] `git status` e `git diff --stat` colados em "Evidência de entrega"
329
+ - [ ] **NÃO fiz commit nem push** — Douglas valida e commita
330
+ - [ ] Douglas notificado (#cspo-tech + ClickUp)
331
+
332
+ ## Checklist do Douglas (após aprovação)
333
+
334
+ - [ ] Revisar diff do dev
335
+ - [ ] `npm run gos:doctor` (root) OK
336
+ - [ ] Commit+push com mensagem sugerida acima
337
+ - [ ] Pre-commit hook bloqueia corretamente em primeiro commit de teste
338
+ - [ ] ClickUp T-110 → `complete`
339
+ - [ ] Slack `task-done` confirmado
340
+
341
+ ## Evidência de entrega (dev cola aqui)
342
+
343
+ ```
344
+ # git status
345
+ (output)
346
+
347
+ # git diff --stat
348
+ (output)
349
+
350
+ # pnpm typecheck (última linha)
351
+ (output)
352
+
353
+ # pnpm build (última linha)
354
+ (output)
355
+ ```