From 82dda0395da0a7a877fa5351709b85d75ff38264 Mon Sep 17 00:00:00 2001
From: Jose Henrique
Date: Thu, 11 Jun 2026 15:30:09 -0300
Subject: [PATCH] docs & fixes
---
AGENTS.md | 27 +-
.../src/components/SpacedReviewComponent.tsx | 14 +-
README.md | 4 +-
dev.ps1 | 11 -
dev.sh | 19 -
mindforge.cronjob/README.md | 11 +-
mindforge.cronjob/deploy/README.md | 8 +-
project-context.md | 375 ++++--------------
re-deploy.ps1 | 12 +
9 files changed, 133 insertions(+), 348 deletions(-)
delete mode 100644 dev.ps1
delete mode 100644 dev.sh
create mode 100644 re-deploy.ps1
diff --git a/AGENTS.md b/AGENTS.md
index 345f89f..f1a8e4d 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,15 +1,18 @@
-# Agents
+# Agentes
-Have a read in `project-context.md` file, it will be the main source of truth for the project. Always keep it up to date with the latest project specs and architecture decisions.
+Leia o arquivo `project-context.md`, pois ele é a principal fonte de verdade do projeto.
-## UI specs
-- All UI needs to be have a glassy-look, with a not-so-dark background
-- Buttons needs to appear iOS-like and modern
-- All text inputs, displays and content should appear with a modern typefont
-- All texts needs to be in Brazilian Portuguese
+## Manutenção do project-context
+- Mantenha o `project-context.md` sempre atualizado com o estado atual do projeto, sem transformá-lo em histórico de mudanças.
+- Sempre que houver alteração em arquitetura, endpoints, contratos de API, variáveis de ambiente, UI/UX, fluxos de produto ou decisões técnicas, atualize o `project-context.md` na mesma entrega.
-## Testing
-Follow strictly the testing requirements:
-- It should NOT have any form of integration testing, nor unit testing, or any kind of testing.
-- The only type of testing that should be done is building the project - make sure it compiles, and it's enough.
-- Don't create random tests or any kind of files that is related to testing. All testing will be done by a human later on.
\ No newline at end of file
+## Especificações de UI
+- Toda a interface precisa ter aparência de vidro, com um fundo não tão escuro.
+- Os botões precisam parecer modernos, no estilo iOS.
+- Todos os campos de texto, exibições e conteúdos devem ter uma tipografia moderna.
+- Todos os textos precisam estar em português brasileiro.
+
+## Testes
+- Não deve haver nenhuma forma de teste de integração, nem teste unitário, nem qualquer outro tipo de teste.
+- O único tipo de validação que deve ser feito é compilar o projeto - basta verificar se ele compila.
+- Toda a validação será feita por um humano depois.
diff --git a/Mindforge.Web/src/components/SpacedReviewComponent.tsx b/Mindforge.Web/src/components/SpacedReviewComponent.tsx
index e8e81b1..227c90e 100644
--- a/Mindforge.Web/src/components/SpacedReviewComponent.tsx
+++ b/Mindforge.Web/src/components/SpacedReviewComponent.tsx
@@ -98,7 +98,7 @@ export function SpacedReviewComponent() {
const [dashboard, setDashboard] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
- const [selectedStatuses, setSelectedStatuses] = useState(['Red', 'Amber']);
+ const [selectedStatuses, setSelectedStatuses] = useState(['Red', 'Amber', 'Green', 'Grey']);
const [selectedLibraryIds, setSelectedLibraryIds] = useState([]);
const [startingSession, setStartingSession] = useState(false);
const [sessionCards, setSessionCards] = useState([]);
@@ -129,6 +129,14 @@ export function SpacedReviewComponent() {
const kept = current.filter((libraryId) => available.has(libraryId));
return kept.length > 0 ? kept : allLibraryIds;
});
+
+ setSelectedStatuses((current) => {
+ if (current.length > 0) {
+ return current;
+ }
+
+ return ['Red', 'Amber', 'Green', 'Grey'];
+ });
} catch (err: any) {
setError(err?.message || 'Falha ao carregar status de revisao espacada.');
} finally {
@@ -214,7 +222,7 @@ export function SpacedReviewComponent() {
}
if (selectedRagLibraries.length === 0) {
- setError('Nenhum arquivo encontrado com os filtros selecionados.');
+ setError('Nenhum arquivo encontrado com os filtros atuais. Ajuste os status ou os arquivos selecionados.');
return;
}
@@ -400,7 +408,7 @@ export function SpacedReviewComponent() {
{startingSession ? 'Iniciando...' : 'Iniciar Revisao Espacada'}
diff --git a/README.md b/README.md
index 08f56ce..0718fc0 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@
-## Mindforge Architecture
+# Arquitetura do Mindforge
-This is a project that will be used to aid the user in making notes and studying for hard exams and tests.
\ No newline at end of file
+Este é um projeto que será usado para ajudar o usuário a fazer anotações e estudar para provas e testes difíceis.
diff --git a/dev.ps1 b/dev.ps1
deleted file mode 100644
index 50fb991..0000000
--- a/dev.ps1
+++ /dev/null
@@ -1,11 +0,0 @@
-# Starting Mindforge Development Environment
-
-# Start API
-Write-Host "Starting Mindforge.API..." -ForegroundColor Cyan
-Start-Process powershell -ArgumentList "-NoExit", "-Command", "dotnet run --project Mindforge.API"
-
-# Start Web
-Write-Host "Starting Mindforge.Web..." -ForegroundColor Cyan
-Start-Process powershell -ArgumentList "-NoExit", "-Command", "cd Mindforge.Web; npm run dev"
-
-Write-Host "Both projects are starting in separate windows." -ForegroundColor Green
diff --git a/dev.sh b/dev.sh
deleted file mode 100644
index 4f2322a..0000000
--- a/dev.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-# Function to handle script termination
-cleanup() {
- echo "Shutting down..."
- kill $(jobs -p)
- exit
-}
-
-trap cleanup SIGINT SIGTERM
-
-echo "Starting Mindforge.API..."
-(cd Mindforge.API && dotnet run) &
-
-echo "Starting Mindforge.Web..."
-(cd Mindforge.Web && npm run dev) &
-
-echo "Both projects are running. Press Ctrl+C to stop both."
-wait
diff --git a/mindforge.cronjob/README.md b/mindforge.cronjob/README.md
index c645a0d..684b233 100644
--- a/mindforge.cronjob/README.md
+++ b/mindforge.cronjob/README.md
@@ -1,10 +1,11 @@
# Mindforge.Cronjob
-The project is called Mindforge.Cronjob, it's a small part of a bigger project called **Mindforge**.
-The main purpose of it is to create small summaries on `.md` documents in Brazilian Portuguese language using AI API calls.
+O projeto se chama Mindforge.Cronjob e faz parte de um projeto maior chamado **Mindforge**.
-## How it works
+O objetivo principal dele é criar pequenos resumos de documentos `.md` em português brasileiro usando chamadas de API de IA.
-This project will fetch all the changes in a Git repository from the last 7 days, and will create a summary of all the changes in a single `.md` file.
+## Como funciona
-It will use either Gemini or ChatGPT API to create the summary.
\ No newline at end of file
+Este projeto busca todas as alterações em um repositório Git dos últimos 7 dias e cria um resumo de todas as mudanças em um único arquivo `.md`.
+
+Ele usa a API do Gemini ou do ChatGPT para gerar o resumo.
diff --git a/mindforge.cronjob/deploy/README.md b/mindforge.cronjob/deploy/README.md
index 0e20850..4fd5593 100644
--- a/mindforge.cronjob/deploy/README.md
+++ b/mindforge.cronjob/deploy/README.md
@@ -1,6 +1,6 @@
-# Deploy
+# Implantação
-## Setup environment
+## Configuração do ambiente
```bash
kubectl create ns mindforge
@@ -13,8 +13,8 @@ kubectl create secret generic mindforge-secrets -n mindforge \
--from-literal=SSH_PRIVATE_KEY="your_ssh_private_key"
```
-## Deployment itself
+## Implantação
```bash
kubectl apply -f mindforge-cronjob.yaml
-```
\ No newline at end of file
+```
diff --git a/project-context.md b/project-context.md
index 9e59383..cc0ce4b 100644
--- a/project-context.md
+++ b/project-context.md
@@ -1,34 +1,36 @@
# Mindforge
-## Visao Geral (Overview)
+## Visão Geral
-Mindforge e uma ferramenta de estudo para auxiliar na preparacao para concursos publicos brasileiros. O sistema permite validar e gerar materiais de estudo a partir de arquivos Markdown hospedados em repositorios Git, utilizando IA (OpenRouter/OpenAI-compatible API) para processamento.
+Mindforge é uma ferramenta de estudo para auxiliar na preparação para concursos públicos brasileiros. O sistema permite validar e gerar materiais de estudo a partir de arquivos Markdown hospedados em repositórios Git, utilizando IA (API compatível com OpenRouter/OpenAI) para processamento.
-A interface e em **portugues brasileiro** e possui um tema escuro com efeito vidro ("glassy-look").
+A interface é em **português brasileiro** e possui um tema escuro com efeito vidro ("glassy-look").
---
-## Tech Stack
+## Stack Tecnológica
### Frontend (Mindforge.Web)
-| Tecnologia | Versao | Finalidade |
+| Tecnologia | Versão | Finalidade |
|---|---|---|
-| **Preact** | ^10.29.0 | UI library (lightweight React alternative) |
-| **Vite** | ^8.0.1 | Build tool e dev server |
-| **TypeScript** | ~5.9.3 | Tipagem estatica |
-| **marked** | ^17.0.4 | Renderizacao Markdown -> HTML |
+| **Preact** | ^10.29.0 | Biblioteca de interface (alternativa leve ao React) |
+| **Vite** | ^8.0.1 | Ferramenta de build e servidor de desenvolvimento |
+| **TypeScript** | ~5.9.3 | Tipagem estática |
+| **marked** | ^17.0.4 | Renderização Markdown -> HTML |
| **diff** | ^8.0.3 | Diff de texto (word-level) |
| **Google Fonts (Lato)** | 300/400/700 | Tipografia da interface |
### Backend API (Mindforge.API)
-| Tecnologia | Versao | Finalidade |
+| Tecnologia | Versão | Finalidade |
|---|---|---|
| **.NET 9** | net9.0 | ASP.NET Core Web API |
| **C#** | - | Linguagem |
| **Microsoft.AspNetCore.OpenApi** | 9.0.12 | Suporte OpenAPI/Swagger |
+| **Dapper** | 2.1.66 | Acesso a dados do domínio de flashcards |
+| **Npgsql** | 9.0.4 | Driver PostgreSQL para persistência de flashcards |
### Cronjob (mindforge.cronjob)
-| Tecnologia | Versao | Finalidade |
+| Tecnologia | Versão | Finalidade |
|---|---|---|
| **Go** | 1.22 | Linguagem |
| **godotenv** | v1.5.1 | Carregamento de arquivos .env |
@@ -41,163 +43,37 @@ A interface e em **portugues brasileiro** e possui um tema escuro com efeito vid
| **Gitea** | Git hosting + Container registry (`git.ivanch.me`) |
| **Gitea Actions** | CI/CD (build & deploy no push para main) |
| **Nginx Ingress** | K8s ingress controller |
-| **OpenRouter API** | Provedor LLM (endpoint OpenAI-compatible) |
+| **OpenRouter API** | Provedor LLM (endpoint compatível com OpenAI) |
---
-## Arquitetura (Architecture)
+## Arquitetura
-O projeto e um **monorepo** com tres servicos independentes e deployaveis separadamente.
-
-```
-┌─────────────────────────────────────────────────────┐
-│ Kubernetes Cluster │
-│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
-│ │ mindforge-web │ │ mindforge-api│ │ cronjob │ │
-│ │ (Preact SPA) │──│ (.NET 9 API) │ │ (Go app) │ │
-│ │ port 80 │ │ port 8080 │ │ (weekly) │ │
-│ └──────────────┘ └──────┬───────┘ └─────┬─────┘ │
-│ │ │ │ │
-│ mindforge.haven api.mindforge.haven │ │
-└──────────────────────────┼─────────────────┼───────┘
- │ │
- ┌──────┴───────┐ ┌──────┴───────┐
- │ OpenRouter │ │ Gitea │
- │ (OpenAI API)│ │ (Git repos) │
- └──────────────┘ └──────┬───────┘
- │
- ┌────────┴────────┐
- │ Discord │
- │ Webhooks │
- └─────────────────┘
-```
-
-### Servicos
-
-#### 1. Mindforge.Web (Frontend)
-- **Tipo**: Single Page Application (SPA)
-- **Funcao**: Interface do usuario para validacao de arquivos e geracao de flashcards
-- **Modulos**: Home, Verificador, Flashcards
-- **Roteamento**: State-based manual via `useState` (nao usa react-router). Componentes sao alternados com `display: block/none`.
-- **Estado**: Apenas `useState`/`useEffect` locais. Sem store global, sem Context API.
-
-#### 2. Mindforge.API (Backend)
-- **Tipo**: REST API
-- **Padrao arquitetural**: Clean layered architecture
- - **Controllers** -> validacao e roteamento HTTP
- - **Services** -> logica de negocio (FileService, FlashcardService, AgentService, GiteaService)
- - **Providers** -> abstracao de APIs externas (OpenAIApiProvider implementa ILlmApiProvider)
- - **Middlewares** -> cross-cutting concerns (ExceptionHandlingMiddleware)
- - **Models** -> DTOs e tipos de request/response
-- **DI**: Todos servicos e providers registrados como Scoped
-- **CORS**: Allow all origins
-- **Auth**: Nenhuma no momento
-
-#### 3. Mindforge.Cronjob (Background Worker)
-- **Tipo**: Kubernetes CronJob
-- **Schedule**: Sabados as 9:00 AM
-- **Pipeline**:
- 1. Clona repositorio Git via SSH
- 2. Encontra arquivos modificados nos ultimos 7 dias (`.md`, exceto `Conteudos.md`)
- 3. Filtra commits de "refactor" via `git log`
- 4. Ranqueia por linhas alteradas, seleciona top N (default 10)
- 5. Gera resumo em texto com IA para cada arquivo
- 6. Formata resumo em Markdown
- 7. Envia para Discord via webhook (chunked em 1800 chars)
-- **Error handling**: Reporta ao Haven Notify
-
-### Decisoes de Arquitetura (Architecture Decisions)
-
-1. **Sem banco de dados**: Totalmente stateless. Conteudo de estudo vive em repositorios Git, acessados via Gitea API em tempo de request.
-2. **Git como content store**: Nao ha upload de arquivos - o conteudo e lido diretamente do repositorio Git.
-3. **IA como engine de processamento**: Toda validacao e geracao e delegada ao LLM via OpenRouter.
-4. **Provider abstraction**: `ILlmApiProvider` permite trocar o backend de IA sem alterar a logica de negocio.
-5. **Monorepo com deploys independentes**: Cada servico tem seu proprio Dockerfile, manifesto K8s e pipeline CI.
-6. **Roteamento manual no frontend**: Sem lib de router, toggle de visibilidade via estado.
-7. **Preact em vez de React**: Bundle size menor.
+O projeto é um monorepo com três serviços independentes.
+- `Mindforge.Web`: SPA em Preact/Vite com navegação manual por estado e sem `react-router`.
+- `Mindforge.API`: REST API em camadas com Controllers, Services, Repositories, Providers, Middlewares e Models; o domínio de flashcards é persistido em PostgreSQL (`mindforge`) via `Dapper` + `Npgsql`, com schema criado no startup.
+- `mindforge.cronjob`: worker em Go executado semanalmente para resumir alterações recentes em arquivos `.md`.
+- Integrações principais: OpenRouter para IA, Gitea como repositório de conteúdo e Discord via webhook para notificações.
+- Deploy: cada serviço possui Dockerfile, manifesto Kubernetes e pipeline independente no Gitea Actions.
+- Decisões-chave: Git como content store, revisão espaçada calculada em leitura e Preact em vez de React.
---
-## Estrutura do Projeto (Project Structure)
+## Estrutura do Projeto
-```
-mindforge/
-├── AGENTS.md # Instrucoes para agentes AI
-├── project-context.md # Este arquivo - fonte da verdade do projeto
-├── README.md
-├── mindforge.png # Logo do projeto
-├── dev.ps1 / dev.sh # Scripts de inicializacao dev
-├── .gitea/workflows/ # CI/CD pipelines
-│ ├── mindforge-api.yaml
-│ ├── mindforge-web.yaml
-│ └── mindforge-cronjob.yaml
-│
-├── Mindforge.API/ # Backend .NET 9
-│ ├── Program.cs # Entry point: DI, CORS, middleware
-│ ├── Controllers/
-│ │ ├── FileController.cs # POST /api/v1/file/check
-│ │ ├── FlashcardController.cs # POST /api/v1/flashcard/generate
-│ │ └── RepositoryController.cs # GET /api/v1/repository/*
-│ ├── Services/ # Logica de negocio
-│ │ ├── AgentService.cs
-│ │ ├── FileService.cs
-│ │ ├── FlashcardService.cs
-│ │ ├── GiteaService.cs
-│ │ └── Interfaces/
-│ ├── Providers/
-│ │ ├── ILlmApiProvider.cs # Interface do provedor LLM
-│ │ └── OpenAIApiProvider.cs # Implementacao OpenAI/OpenRouter com retry
-│ ├── Middlewares/
-│ │ └── ExceptionHandlingMiddleware.cs
-│ ├── Models/
-│ │ ├── FileTreeNode.cs
-│ │ └── Requests/ # DTOs de request
-│ ├── Exceptions/
-│ │ └── UserException.cs # 400 Bad Request customizado
-│ └── deploy/
-│ └── mindforge-api.yaml # Manifest K8s (Deployment + Service + Ingress)
-│
-├── Mindforge.Web/ # Frontend Preact + Vite
-│ ├── vite.config.ts
-│ ├── tsconfig.app.json # Target ES2023, JSX preact, strict mode
-│ ├── .env # VITE_API_BASE_URL=http://localhost:5123
-│ ├── src/
-│ │ ├── main.tsx # Entry point
-│ │ ├── app.tsx # Componente raiz: header, sidebar, modulos
-│ │ ├── app.css # Estilos hero, animacoes
-│ │ ├── index.css # CSS variables, reset, layout base
-│ │ ├── services/
-│ │ │ └── MindforgeApiService.ts # Cliente API (fetch, interfaces tipadas)
-│ │ └── components/
-│ │ ├── Button.tsx / .css # Botao reutilizavel (primary/secondary)
-│ │ ├── Header.tsx / .css # Header fixo com logo + nome do repo
-│ │ ├── Sidebar.tsx / .css # Navegacao lateral
-│ │ ├── VerificadorComponent.tsx / .css # Validador de arquivos
-│ │ ├── FlashcardComponent.tsx / .css # Gerador de flashcards
-│ │ └── FileTreeComponent.tsx / .css # Arvore de arquivos do repo
-│ └── deploy/
-│ └── mindforge-web.yaml # Manifest K8s
-│
-└── mindforge.cronjob/ # CronJob em Go
- ├── cmd/mindforge.cronjob/main.go # Entry point
- ├── internal/
- │ ├── agent/agent.go # Cria e formata resumos
- │ ├── llm/ # Servico LLM
- │ ├── git/git.go # Clone, diff, SSH
- │ ├── errors/errors.go # Reporte de erros
- │ └── message/messages.go # Notificacoes Discord
- └── deploy/
- └── mindforge-cronjob.yaml # Manifest K8s CronJob
-```
+- `mindforge/`: raiz do projeto com documentação, scripts, logo e workflows do Gitea.
+- `Mindforge.API/`: backend .NET 9 com controllers, services, repositories, providers, models e deploy Kubernetes.
+- `Mindforge.Web/`: frontend Preact + Vite com componentes de interface, cliente de API e deploy Kubernetes.
+- `mindforge.cronjob/`: worker em Go com lógica de IA, Git, erros e mensagens do Discord, além do deploy Kubernetes.
---
-## API Endpoints
+## Endpoints da API
-### File Controller (`/api/v1/file`)
-| Metodo | Rota | Descricao |
+### Controller de Arquivos (`/api/v1/file`)
+| Método | Rota | Descrição |
|---|---|---|
-| POST | `/api/v1/file/check` | Valida linguagem ou conteudo de um arquivo |
+| POST | `/api/v1/file/check` | Valida a linguagem ou o conteúdo de um arquivo |
```json
// Request
@@ -213,64 +89,59 @@ mindforge/
}
```
-### Flashcard Controller (`/api/v1/flashcard`)
-| Metodo | Rota | Descricao |
+### Controller de Flashcards (`/api/v1/flashcard`)
+| Método | Rota | Descrição |
|---|---|---|
-| POST | `/api/v1/flashcard/generate` | Gera flashcards em CSV |
+| POST | `/api/v1/flashcard/generate` | Gera ou substitui bibliotecas de flashcards a partir dos arquivos selecionados |
+| GET | `/api/v1/flashcard/libraries` | Lista todas as bibliotecas persistidas |
+| GET | `/api/v1/flashcard/libraries/{id}` | Retorna uma biblioteca específica com seus cards |
+| POST | `/api/v1/flashcard/review-session` | Inicia uma sessão de revisão com bibliotecas selecionadas |
+| POST | `/api/v1/flashcard/review-answer` | Registra se a resposta do card estava correta |
+| GET | `/api/v1/flashcard/rag-status` | Retorna o dashboard de revisão espaçada por matéria/submatéria |
-```json
-// Request
-{
- "fileContent": "string",
- "fileName": "string",
- "amount": 10,
- "mode": "Basic" | "Simple" | "Detailed" | "Hyper"
-}
+Formas de requisição principais:
+- `POST /api/v1/flashcard/generate`: `{ filePaths: string[], amount: 10-30, difficulty: "Easy" | "Hard" }`
+- `POST /api/v1/flashcard/review-session`: `{ libraryIds: number[] }`
+- `POST /api/v1/flashcard/review-answer`: `{ cardId: number, correct: boolean }`
-// Response
-{
- "result": "string (CSV: Frente;Verso\nFrente;Verso\n...)"
-}
-```
-
-### Repository Controller (`/api/v1/repository`)
-| Metodo | Rota | Descricao |
+### Controller de Repositório (`/api/v1/repository`)
+| Método | Rota | Descrição |
|---|---|---|
-| GET | `/api/v1/repository/info` | Nome do repositorio |
-| GET | `/api/v1/repository/tree` | Arvore de arquivos do repositorio |
-| GET | `/api/v1/repository/file?path=...` | Conteudo de um arquivo especifico |
+| GET | `/api/v1/repository/info` | Nome do repositório |
+| GET | `/api/v1/repository/tree` | Árvore de arquivos do repositório |
+| GET | `/api/v1/repository/file?path=...` | Conteúdo de um arquivo específico |
---
-## Convencoes de Desenvolvimento (Development Conventions)
+## Convenções de Desenvolvimento
### Frontend (Preact/TypeScript)
-- **Componentes**: Funcoes nomeadas exportadas com `export function Nome()`. Sem `export default`.
+- **Componentes**: Funções nomeadas exportadas com `export function Nome()`. Sem `export default`.
- **Props**: Interfaces TypeScript definidas no mesmo arquivo do componente.
-- **Hooks**: `useState`, `useEffect` importados de `preact/hooks`.
+- **Hooks**: `useState` e `useEffect` importados de `preact/hooks`.
- **Children**: Tipados como `ComponentChildren` de `preact`.
- **CSS**: Um arquivo `.css` por componente, importado diretamente. **Sem CSS Modules.**
- **Estado**: Apenas estado local (`useState`). Sem store global, sem Context API.
-- **Roteamento**: Alternancia de componentes via `display: block/none` com estado `activeModule`. Nao usa react-router.
-- **API**: Chamadas via `MindforgeApiService` (objeto singleton com metodos estaticos usando `fetch`).
-- **TypeScript**: Strict mode, `erasableSyntaxOnly`, `verbatimModuleSyntax`, `noUnusedLocals`, `noUnusedParameters`.
+- **Roteamento**: Alternância de componentes via `display: block/none` com o estado `activeModule`. Não usa `react-router`.
+- **API**: Chamadas via `MindforgeApiService` (objeto singleton com métodos estáticos usando `fetch`).
+- **TypeScript**: Modo estrito, `erasableSyntaxOnly`, `verbatimModuleSyntax`, `noUnusedLocals`, `noUnusedParameters`.
- **Alias**: `react` e `react-dom` mapeados para `preact/compat/` no tsconfig.
### Backend (C#/.NET 9)
- **Namespaces**: `Mindforge.API.Controllers`, `Mindforge.API.Services`, etc.
-- **Interfaces**: Prefixo `I` (ex: `IFileService`, `ILlmApiProvider`).
-- **DI**: Todos servicos registrados como `Scoped` em `Program.cs`.
-- **Controllers**: Atributo `[Route("api/v1/...")]`. Metodos retornam `IActionResult`.
-- **Tratamento de erros**: `ExceptionHandlingMiddleware` captura `UserException` (400) e excecoes genericas (500).
+- **Interfaces**: Prefixo `I` (ex.: `IFileService`, `ILlmApiProvider`).
+- **DI**: Todos os serviços registrados como `Scoped` em `Program.cs`.
+- **Controllers**: Atributo `[Route("api/v1/...")]`. Métodos retornam `IActionResult`.
+- **Tratamento de erros**: `ExceptionHandlingMiddleware` captura `UserException` (400) e exceções genéricas (500).
### UI/UX
-- **Idioma**: Todo texto em **portugues brasileiro**.
+- **Idioma**: Todo texto em **português brasileiro**.
- **Tema**: Escuro com efeito vidro (glassy). `backdrop-filter: blur()`, fundos `rgba` semitransparentes.
-- **Botoes**: Estilo iOS-like, modernos. Variantes `primary` (com blur) e `secondary` (transparente).
+- **Botões**: Estilo iOS-like, modernos. Variantes `primary` (com blur) e `secondary` (transparente).
- **Tipografia**: Lato (Google Fonts), pesos 300/400/700.
-- **Background**: `#005873` (azul petroleo escuro). Nao muito escuro.
+- **Background**: `#005873` (azul petróleo escuro). Não muito escuro.
-### CSS Variables (definidas em `index.css`)
+### Variáveis CSS (definidas em `index.css`)
```css
--color-bg: #005873;
--color-header: #0f0f0f;
@@ -283,129 +154,49 @@ mindforge/
```
### Git
-- Branches: `main` (producao)
-- CI/CD: Gitea Actions dispara no push para main, build com Docker Buildx multi-arch, push para Gitea Container Registry, deploy no K8s.
+- Branches: `main` (produção)
+- CI/CD: Gitea Actions dispara no push para `main`, faz build com Docker Buildx multi-arch, envia para o Gitea Container Registry e faz o deploy no K8s.
---
-## Configuracao & Environment Variables
+## Configuração e Variáveis de Ambiente
### API (Mindforge.API)
-| Variavel | Descricao |
+| Variável | Descrição |
|---|---|
-| `OPENAI_API_URL` | URL do endpoint OpenAI-compatible (OpenRouter) |
-| `OPENAI_TOKEN` | Token de autenticacao da API |
+| `OPENAI_API_URL` | URL do endpoint compatível com OpenAI (OpenRouter) |
+| `OPENAI_TOKEN` | Token de autenticação da API |
| `OPENAI_MODEL` | Modelo LLM a ser usado |
-| `GITEA_REPO_URL` | URL do repositorio Gitea |
+| `GITEA_REPO_URL` | URL do repositório Gitea |
| `GITEA_ACCESS_TOKEN` | Token de acesso ao Gitea |
+| `ConnectionStrings:MindforgeDb` | Conexão PostgreSQL usada pelo domínio de flashcards |
+
+Fallback local/padrão para o banco de flashcards:
+`Host=localhost;Port=3307;Database=mindforge;Username=root;Password=root`.
### Web (Mindforge.Web)
-| Variavel | Descricao |
+| Variável | Descrição |
|---|---|
-| `VITE_API_BASE_URL` | URL base da API (default: `http://localhost:5123`) |
+| `VITE_API_BASE_URL` | URL base da API (padrão: `http://localhost:5123`) |
### Cronjob
-| Variavel | Descricao |
+| Variável | Descrição |
|---|---|
-| `GIT_REPOSITORY` | URL do repo Git a clonar |
-| `DISCORD_WEBHOOK_URL` | Webhook do Discord para notificacoes |
+| `GIT_REPOSITORY` | URL do repositório Git a clonar |
+| `DISCORD_WEBHOOK_URL` | Webhook do Discord para notificações |
| `OPENAI_API_URL` | URL do endpoint OpenAI |
-| `OPENAI_TOKEN` | Token de autenticacao |
-| `HAVEN_NOTIFY_URL` | URL do servico de reporte de erros |
+| `OPENAI_TOKEN` | Token de autenticação |
+| `HAVEN_NOTIFY_URL` | URL do serviço de reporte de erros |
## Repositório base para os arquivos
A base do repositório para os arquivos de estudo (compartilhado pelo Obsidian) é https://git.ivanch.me/ivanch/concurso.
-Ele segue o padrão `[base]/concurso/[Matéria]/[SubMatéria*]/[Arquivo]`, onde [base] é a URL do git, concurso é o nome da pasta dentro do git base, Matéria é o nome da matéria (ex: `Direito Constitucional`), SubMatéria é o nome da submatéria (ex. `Poder Legislativo`) - podendo ser opcional e com múltiplas submatérias -, e Arquivo é o nome do arquivo (ex: `Câmara dos Deputados.md`).
+Ele segue o padrão `[base]/concurso/[Matéria]/[SubMatéria*]/[Arquivo]`, onde [base] é a URL do Git, `concurso` é o nome da pasta dentro do Git base, `Matéria` é o nome da matéria (ex.: `Direito Constitucional`), `SubMatéria` é o nome da submatéria (ex.: `Poder Legislativo`) - podendo ser opcional e com múltiplas submatérias - e `Arquivo` é o nome do arquivo (ex.: `Câmara dos Deputados.md`).
Exemplos:
- [base]/Concursos/Direito Constitucional/Poder Legislativo/Câmara dos Deputados.md
- [base]/Concursos/Direito Constitucional/Poder Legislativo/CPIs.md
- [base]/Concursos/Direito Constitucional/Ciência, Meio Ambiente e Índios.md
- [base]/Concursos/Direito Constitucional/Ciência, Meio Ambiente e Índios.md
-- [base]/Concursos/TI/Analise e Engenharia de Dados/Data Lake e Data Warehouse.md
+- [base]/Concursos/TI/Análise e Engenharia de Dados/Data Lake e Data Warehouse.md
- [base]/Concursos/TI/Rede/VLAN.md
-- [base]/Concursos/TI/Rede/Email/IMAP e POP3.md
-
----
-
-## Atualizacao - Flashcards Persistidos (2026-05-30)
-
-### Mudancas de Arquitetura
-- A API deixa de ser totalmente stateless para o dominio de flashcards.
-- Flashcards agora sao persistidos em PostgreSQL (`mindforge`) via `Dapper` + `Npgsql`.
-- O schema e criado de forma idempotente no startup da API.
-
-### Tabelas de Flashcard
-- `flashcard_libraries`: `id`, `file_path` (unico), `file_name`, `subject`, `difficulty`, `card_count`, `created_at`, `updated_at`.
-- `flashcards`: `id`, `library_id`, `front`, `back`, `position`, `correct_count`, `incorrect_count`, `last_reviewed_at`, `created_at`.
-
-### API de Flashcards (v1)
-- `POST /api/v1/flashcard/generate`
- Request: `{ filePaths: string[], amount: 10-30, difficulty: "Easy" | "Hard" }`
- Comportamento: gera por arquivo selecionado, substitui biblioteca anterior do mesmo `file_path` e retorna bibliotecas com cards.
-- `GET /api/v1/flashcard/libraries`
- Lista todas as bibliotecas persistidas, com `subject` para agrupamento na UI.
-- `GET /api/v1/flashcard/libraries/{id}`
- Retorna detalhes de uma biblioteca com seus cards.
-- `POST /api/v1/flashcard/review-session`
- Request: `{ libraryIds: number[] }`
- Retorna os cards combinados para sessao de revisao (sem repeticao espaciada nesta fase).
-- `POST /api/v1/flashcard/review-answer`
- Request: `{ cardId: number, correct: boolean }`
- Registra no banco o resultado da revisao (`Acertei`/`Errei`) por card.
-
-### Frontend
-- Modulo `Flashcards` atualizado para:
- - selecionar multiplos arquivos;
- - definir quantidade fixa por arquivo (10-30);
- - definir dificuldade (`Facil`/`Dificil`);
- - gerar e exibir resumo das bibliotecas salvas (sem download CSV).
-- Novo modulo `Revisao Flashcards`:
- - lista bibliotecas agrupadas por materia (`subject`);
- - permite selecionar multiplas bibliotecas;
- - embaralha aleatoriamente os cards ao iniciar a sessao de revisao;
- - inicia sessao estilo Anki simplificada (frente, revelar verso, acertei/errei, anterior, progresso visual).
- - ao gerar novamente uma biblioteca, os contadores `correct_count` e `incorrect_count` dos cards sao resetados para zero.
-
-### Novas Configuracoes
-- `ConnectionStrings:MindforgeDb` para conexao PostgreSQL.
-- Fallback local/default:
- `Host=localhost;Port=3307;Database=mindforge;Username=root;Password=root`.
-
----
-
-## Atualizacao - Revisao Espacada RAG (2026-06-01)
-
-### Mudancas de Arquitetura
-- O dominio de flashcards guarda `last_reviewed_at` por card.
-- O status RAG da revisao espacada e calculado em tempo de leitura **por biblioteca/arquivo** (grupo de cards), nao por card.
-- O agrupamento de dashboard usa `subject` + `subSubject`, onde `subSubject` vem dos segmentos do caminho apos a materia e antes do arquivo.
-
-### Regras RAG por Arquivo (biblioteca)
-- `Grey`: nenhum card da biblioteca possui `last_reviewed_at`.
-- `Red`: ultima revisao da biblioteca ha 40 dias ou mais **ou** desempenho agregado `< 40%`.
-- `Amber`: ultima revisao da biblioteca ha 30 dias ou mais **ou** desempenho agregado `<= 60%`.
-- `Green`: ultima revisao da biblioteca abaixo de 30 dias **e** desempenho agregado `> 60%`.
-- Desempenho agregado: `sum(correct_count) / (sum(correct_count) + sum(incorrect_count))`.
-
-### Banco e Repositorio
-- Tabela `flashcards` recebeu coluna `last_reviewed_at TIMESTAMPTZ NULL` (migracao idempotente no startup).
-- `POST /api/v1/flashcard/review-answer` agora atualiza `correct_count`/`incorrect_count` e define `last_reviewed_at = NOW()`.
-
-### API de Flashcards (v1)
-- Novo endpoint `GET /api/v1/flashcard/rag-status`:
- - Retorna dashboard de revisao espacada com grupos por materia/submateria.
- - Inclui bibliotecas/arquivos com `ragStatus`, `performanceRate`, `totalAnswers` e `lastReviewedAt`.
- - Inclui sumarios por materia/submateria com percentuais:
- - Verde = `green / (green + amber + red)`
- - Atencao = `(amber + red) / (green + amber + red)`
- - Arquivos cinza ficam fora do denominador.
-
-### Frontend
-- Novo modulo `Revisao Espacada` abaixo de `Revisao Flashcards` na sidebar.
-- O painel mostra:
- - status agregados por materia e submateria;
- - status por arquivo com destaque visual (cores e icones);
- - filtros por status RAG (Vermelho, Amarelo, Verde, Cinza);
- - total de arquivos selecionados para revisao.
-- A sessao de revisao espacada reutiliza o fluxo de resposta (`Acertei`/`Errei`) e prioriza cards de arquivos por status (Red, Amber, Green, Grey).
+- [base]/Concursos/TI/Rede/E-mail/IMAP e POP3.md
diff --git a/re-deploy.ps1 b/re-deploy.ps1
new file mode 100644
index 0000000..4646b8a
--- /dev/null
+++ b/re-deploy.ps1
@@ -0,0 +1,12 @@
+# Exit on any error
+$ErrorActionPreference = "Stop"
+
+docker login git.ivanch.me
+
+Write-Host "Building and pushing Docker images..."
+docker buildx bake --set '*.platform=linux/amd64,linux/arm64' --push
+
+Write-Host "Build and push completed successfully."
+
+kubectl delete -f ./deploy/deployment.yaml
+kubectl apply -f ./deploy/deployment.yaml
\ No newline at end of file