Documentação Inclusa
This commit is contained in:
64
documentação/00_PROJECT_OVERVIEW.md
Normal file
64
documentação/00_PROJECT_OVERVIEW.md
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# 📦 InventoryAI — Project Overview
|
||||||
|
|
||||||
|
## Visão Geral
|
||||||
|
|
||||||
|
**InventoryAI** é uma aplicação móvel de gestão de inventário pessoal inteligente.
|
||||||
|
O utilizador fotografa os seus pertences, a app organiza-os automaticamente por categoria, e sugere o que levar consoante o contexto (viagem, clima, ocasião).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Problema que resolve
|
||||||
|
|
||||||
|
As pessoas não sabem o que têm em casa. Perdem tempo a procurar itens, esquecem-se do que possuem, e não conseguem planear eficientemente o que levar para viagens ou eventos.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Proposta de Valor
|
||||||
|
|
||||||
|
> "Fotografa uma vez. A app lembra-se para sempre. Diz-te o que levar quando precisas."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Utilizador-alvo
|
||||||
|
|
||||||
|
- Pessoas que viajam frequentemente
|
||||||
|
- Quem tem muita roupa e não consegue gerir outfits
|
||||||
|
- Utilizadores organizados que querem controlo total dos seus bens pessoais
|
||||||
|
- Nómadas digitais e viajantes de longa duração
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Princípios de Design
|
||||||
|
|
||||||
|
1. **Simplicidade primeiro** — o MVP não tem IA avançada. Regras simples parecem inteligentes.
|
||||||
|
2. **Foto como input principal** — tirar foto é mais rápido do que escrever.
|
||||||
|
3. **Categorização automática** — o utilizador não quer trabalho manual.
|
||||||
|
4. **Sugestões contextuais** — a app responde a perguntas reais do utilizador.
|
||||||
|
5. **Evolução progressiva** — começar simples, adicionar IA com dados reais.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Estado atual do projeto
|
||||||
|
|
||||||
|
| Fase | Estado |
|
||||||
|
|------|--------|
|
||||||
|
| Definição do MVP | ✅ Concluído |
|
||||||
|
| Arquitetura técnica | ✅ Definida |
|
||||||
|
| Implementação | 🔲 Por iniciar |
|
||||||
|
| Testes com utilizadores | 🔲 Por iniciar |
|
||||||
|
| IA avançada | 🔲 Fase futura |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ficheiros de contexto deste projeto
|
||||||
|
|
||||||
|
| Ficheiro | Conteúdo |
|
||||||
|
|----------|----------|
|
||||||
|
| `00_PROJECT_OVERVIEW.md` | Este ficheiro — visão geral |
|
||||||
|
| `01_MVP_DEFINITION.md` | Funcionalidades mínimas viáveis |
|
||||||
|
| `02_ARCHITECTURE.md` | Stack técnica e estrutura da app |
|
||||||
|
| `03_AI_VISION_LAYER.md` | Integração de IA para imagens |
|
||||||
|
| `04_CATEGORIES_AND_TAGS.md` | Sistema de organização de itens |
|
||||||
|
| `05_RECOMMENDATION_ENGINE.md` | Lógica de sugestões (regras + IA futura) |
|
||||||
|
| `06_FUTURE_FEATURES.md` | Roadmap e funcionalidades avançadas |
|
||||||
|
| `07_AGENT_BEHAVIOR.md` | Como o agente IA deve comportar-se |
|
||||||
101
documentação/01_MVP_DEFINITION.md
Normal file
101
documentação/01_MVP_DEFINITION.md
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# 🎯 MVP — Definição do Produto Mínimo Viável
|
||||||
|
|
||||||
|
## Objetivo do MVP
|
||||||
|
|
||||||
|
Criar a versão mais simples possível da app que já seja útil para um utilizador real.
|
||||||
|
**Sem IA avançada. Sem funcionalidades complexas. Sem over-engineering.**
|
||||||
|
|
||||||
|
O MVP deve validar a hipótese central:
|
||||||
|
> "Os utilizadores estão dispostos a fotografar os seus itens para depois receber sugestões contextuais."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Funcionalidades obrigatórias (must-have)
|
||||||
|
|
||||||
|
### 1. 📸 Upload / Captura de Foto
|
||||||
|
- O utilizador tira foto a um item com a câmara do telemóvel
|
||||||
|
- Alternativa: selecionar foto da galeria
|
||||||
|
- A foto é guardada no perfil do item
|
||||||
|
- **Requisito mínimo:** uma foto por item
|
||||||
|
|
||||||
|
### 2. 📦 Guardar Item
|
||||||
|
- Cada item tem:
|
||||||
|
- `nome` (texto livre ou sugerido pela IA de imagem)
|
||||||
|
- `foto` (obrigatória)
|
||||||
|
- `categoria` (selecionada pelo utilizador ou auto-detetada)
|
||||||
|
- `tags` (opcional, atribuídas manualmente ou automaticamente)
|
||||||
|
- `data de adição`
|
||||||
|
- O item é guardado na base de dados do utilizador
|
||||||
|
|
||||||
|
### 3. 🏷️ Categorização
|
||||||
|
- O utilizador escolhe a categoria principal do item
|
||||||
|
- Categorias base disponíveis no MVP:
|
||||||
|
- Roupa
|
||||||
|
- Eletrónica
|
||||||
|
- Calçado
|
||||||
|
- Acessórios
|
||||||
|
- Documentos
|
||||||
|
- Outros
|
||||||
|
- Subcategorias simples dentro de cada categoria (ver `04_CATEGORIES_AND_TAGS.md`)
|
||||||
|
|
||||||
|
### 4. 🔍 Pesquisa e Visualização do Inventário
|
||||||
|
- Lista de todos os itens (grid de fotos ou lista)
|
||||||
|
- Filtrar por categoria
|
||||||
|
- Pesquisa por nome ou tag
|
||||||
|
- Detalhe do item ao clicar
|
||||||
|
|
||||||
|
### 5. 🎯 Sugestões Simples por Contexto (sem IA)
|
||||||
|
- O utilizador seleciona um contexto pré-definido:
|
||||||
|
- "Vou viajar (curta duração)"
|
||||||
|
- "Vou viajar (longa duração)"
|
||||||
|
- "Vou ao trabalho"
|
||||||
|
- "Fim de semana casual"
|
||||||
|
- A app filtra e mostra os itens relevantes para esse contexto
|
||||||
|
- As regras são estáticas e definidas manualmente (ver `05_RECOMMENDATION_ENGINE.md`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Funcionalidades excluídas do MVP
|
||||||
|
|
||||||
|
> Estas funcionalidades são importantes mas ficam para iterações futuras.
|
||||||
|
|
||||||
|
- ❌ Sugestões baseadas em clima
|
||||||
|
- ❌ Montagem automática de outfits
|
||||||
|
- ❌ Integração com calendário
|
||||||
|
- ❌ Assistente conversacional ("O que devo levar amanhã?")
|
||||||
|
- ❌ Sistema de preferências pessoais aprendidas
|
||||||
|
- ❌ Multi-utilizador / partilha
|
||||||
|
- ❌ Exportação de listas
|
||||||
|
- ❌ Notificações inteligentes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fluxo principal do utilizador (MVP)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Utilizador abre a app
|
||||||
|
2. Tira foto de um item
|
||||||
|
3. App sugere nome e categoria (via Google Vision)
|
||||||
|
4. Utilizador confirma ou edita
|
||||||
|
5. Item guardado no inventário
|
||||||
|
6. Utilizador acede ao inventário → pesquisa / filtra
|
||||||
|
7. Utilizador seleciona contexto → app mostra lista filtrada
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Critérios de sucesso do MVP
|
||||||
|
|
||||||
|
- [ ] Utilizador consegue adicionar 10 itens em menos de 5 minutos
|
||||||
|
- [ ] Pesquisa devolve resultados corretos em menos de 1 segundo
|
||||||
|
- [ ] Sugestão por contexto é considerada "útil" por 70%+ dos utilizadores testados
|
||||||
|
- [ ] Taxa de retenção ao fim de 7 dias > 40%
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notas para o agente IA
|
||||||
|
|
||||||
|
- Quando o utilizador pedir para construir uma funcionalidade, verificar primeiro se está no MVP ou no roadmap futuro
|
||||||
|
- Se estiver fora do MVP, avisar e perguntar se deve ser priorizada ou adiada
|
||||||
|
- Nunca adicionar complexidade desnecessária ao MVP
|
||||||
|
- Preferir sempre a solução mais simples que funcione
|
||||||
143
documentação/02_ARCHITECTURE.md
Normal file
143
documentação/02_ARCHITECTURE.md
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
# 🏗️ Arquitetura Técnica
|
||||||
|
|
||||||
|
## Stack Tecnológica
|
||||||
|
|
||||||
|
### Decisões principais
|
||||||
|
|
||||||
|
| Camada | Tecnologia escolhida | Alternativa considerada | Motivo da escolha |
|
||||||
|
|--------|----------------------|-------------------------|-------------------|
|
||||||
|
| App móvel | React Native | Flutter | Ecosistema JS, mais fácil de integrar com APIs web |
|
||||||
|
| Backend / Auth | Firebase | Supabase | Setup rápido, escalável, gratuito no início |
|
||||||
|
| Base de dados | Firestore | PostgreSQL (Supabase) | NoSQL flexível, sincronia em tempo real |
|
||||||
|
| Armazenamento de imagens | Firebase Storage | AWS S3 | Integrado com Firebase, simples |
|
||||||
|
| IA de imagem | Google Vision AI | AWS Rekognition | Melhor deteção de objetos, preço competitivo |
|
||||||
|
| IA de texto (futuro) | OpenAI API | Anthropic Claude API | Fase futura — não implementar no MVP |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Estrutura da Aplicação
|
||||||
|
|
||||||
|
```
|
||||||
|
inventoryai/
|
||||||
|
├── mobile/ # App React Native
|
||||||
|
│ ├── src/
|
||||||
|
│ │ ├── screens/ # Ecrãs principais
|
||||||
|
│ │ │ ├── HomeScreen.jsx
|
||||||
|
│ │ │ ├── AddItemScreen.jsx
|
||||||
|
│ │ │ ├── InventoryScreen.jsx
|
||||||
|
│ │ │ ├── ItemDetailScreen.jsx
|
||||||
|
│ │ │ └── SuggestionsScreen.jsx
|
||||||
|
│ │ ├── components/ # Componentes reutilizáveis
|
||||||
|
│ │ ├── services/ # Lógica de negócio e APIs
|
||||||
|
│ │ │ ├── firebase.js
|
||||||
|
│ │ │ ├── visionApi.js
|
||||||
|
│ │ │ └── suggestions.js
|
||||||
|
│ │ ├── hooks/ # Custom hooks React
|
||||||
|
│ │ ├── utils/ # Utilitários
|
||||||
|
│ │ └── constants/ # Categorias, regras, etc.
|
||||||
|
│ └── package.json
|
||||||
|
├── functions/ # Firebase Cloud Functions (opcional)
|
||||||
|
└── docs/ # Ficheiros .md deste projeto
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Modelo de Dados (Firestore)
|
||||||
|
|
||||||
|
### Coleção: `users/{userId}`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"uid": "string",
|
||||||
|
"email": "string",
|
||||||
|
"displayName": "string",
|
||||||
|
"createdAt": "timestamp",
|
||||||
|
"preferences": {
|
||||||
|
"defaultContext": "travel_short"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Coleção: `users/{userId}/items/{itemId}`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"name": "string",
|
||||||
|
"photoUrl": "string",
|
||||||
|
"thumbnailUrl": "string",
|
||||||
|
"category": "clothing | electronics | footwear | accessories | documents | other",
|
||||||
|
"subcategory": "string",
|
||||||
|
"tags": ["string"],
|
||||||
|
"visionLabels": ["string"],
|
||||||
|
"contextTags": ["travel", "work", "casual"],
|
||||||
|
"createdAt": "timestamp",
|
||||||
|
"updatedAt": "timestamp"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fluxo de Adição de Item
|
||||||
|
|
||||||
|
```
|
||||||
|
[Utilizador tira foto]
|
||||||
|
↓
|
||||||
|
[Upload para Firebase Storage]
|
||||||
|
↓
|
||||||
|
[Chamada à Google Vision API]
|
||||||
|
↓
|
||||||
|
[Receber labels automáticas]
|
||||||
|
↓
|
||||||
|
[Mapear labels → categoria + tags sugeridas]
|
||||||
|
↓
|
||||||
|
[Mostrar ao utilizador para confirmar/editar]
|
||||||
|
↓
|
||||||
|
[Guardar item no Firestore]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Autenticação
|
||||||
|
|
||||||
|
- Firebase Authentication
|
||||||
|
- Login com Google (obrigatório no MVP)
|
||||||
|
- Login com email/password (opcional no MVP)
|
||||||
|
- Todos os dados são isolados por `userId`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance e Limites
|
||||||
|
|
||||||
|
| Recurso | Limite gratuito Firebase | Estimativa uso MVP |
|
||||||
|
|---------|--------------------------|---------------------|
|
||||||
|
| Firestore reads | 50.000/dia | ~5.000/dia (100 users) |
|
||||||
|
| Firestore writes | 20.000/dia | ~2.000/dia |
|
||||||
|
| Storage | 5 GB | ~1 GB para 100 users |
|
||||||
|
| Google Vision API | 1.000 unidades/mês grátis | ~500 unidades/mês |
|
||||||
|
|
||||||
|
> Para o MVP com utilizadores de teste, o tier gratuito é suficiente.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Segurança (Firestore Rules — MVP)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
rules_version = '2';
|
||||||
|
service cloud.firestore {
|
||||||
|
match /databases/{database}/documents {
|
||||||
|
match /users/{userId}/{document=**} {
|
||||||
|
allow read, write: if request.auth != null && request.auth.uid == userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notas para o agente IA
|
||||||
|
|
||||||
|
- **Não** sugerir AWS, Azure ou outras clouds — a decisão está tomada: Firebase
|
||||||
|
- **Não** sugerir Flutter — a decisão está tomada: React Native
|
||||||
|
- Quando criar código de serviço, usar o padrão `services/` definido acima
|
||||||
|
- O modelo de dados do Firestore é o definido neste ficheiro — não alterar sem avisar
|
||||||
|
- Para novas funcionalidades, verificar se precisam de novas coleções no Firestore
|
||||||
|
- Imagens são sempre guardadas no Firebase Storage antes de qualquer processamento
|
||||||
204
documentação/03_AI_VISION_LAYER.md
Normal file
204
documentação/03_AI_VISION_LAYER.md
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
# 👁️ Camada de Visão por IA
|
||||||
|
|
||||||
|
## Objetivo
|
||||||
|
|
||||||
|
Usar IA de visão computacional para **identificar automaticamente** o que está na foto tirada pelo utilizador, sugerindo:
|
||||||
|
- Nome do item
|
||||||
|
- Categoria
|
||||||
|
- Tags relevantes
|
||||||
|
|
||||||
|
Isto reduz o esforço do utilizador ao mínimo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Serviço escolhido: Google Vision API
|
||||||
|
|
||||||
|
### Porquê Google Vision?
|
||||||
|
- Fácil integração com Firebase (mesmo ecosistema Google)
|
||||||
|
- Excelente deteção de objetos do quotidiano
|
||||||
|
- Labels em múltiplos idiomas
|
||||||
|
- Tier gratuito generoso (1.000 unidades/mês)
|
||||||
|
- Documentação extensa
|
||||||
|
|
||||||
|
### Funcionalidades usadas no MVP
|
||||||
|
|
||||||
|
| Feature | Uso |
|
||||||
|
|---------|-----|
|
||||||
|
| `LABEL_DETECTION` | Identificar o objeto (ex: "T-shirt", "Laptop") |
|
||||||
|
| `OBJECT_LOCALIZATION` | Confirmar que existe um objeto na foto |
|
||||||
|
|
||||||
|
> No MVP **não** usamos OCR, Safe Search ou outras features avançadas.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Integração técnica
|
||||||
|
|
||||||
|
### Chamada à API (exemplo React Native)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// services/visionApi.js
|
||||||
|
|
||||||
|
const VISION_API_KEY = process.env.GOOGLE_VISION_API_KEY;
|
||||||
|
const VISION_API_URL = `https://vision.googleapis.com/v1/images:annotate?key=${VISION_API_KEY}`;
|
||||||
|
|
||||||
|
export async function analyzeImage(base64Image) {
|
||||||
|
const requestBody = {
|
||||||
|
requests: [
|
||||||
|
{
|
||||||
|
image: { content: base64Image },
|
||||||
|
features: [
|
||||||
|
{ type: 'LABEL_DETECTION', maxResults: 10 },
|
||||||
|
{ type: 'OBJECT_LOCALIZATION', maxResults: 5 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await fetch(VISION_API_URL, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(requestBody)
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return parseVisionResponse(data);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parsing da resposta
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// services/visionApi.js (continuação)
|
||||||
|
|
||||||
|
export function parseVisionResponse(data) {
|
||||||
|
const labels = data.responses[0]?.labelAnnotations || [];
|
||||||
|
const objects = data.responses[0]?.localizedObjectAnnotations || [];
|
||||||
|
|
||||||
|
// Extrair labels com score > 0.7
|
||||||
|
const highConfidenceLabels = labels
|
||||||
|
.filter(l => l.score > 0.7)
|
||||||
|
.map(l => l.description.toLowerCase());
|
||||||
|
|
||||||
|
// Mapear para categoria da app
|
||||||
|
const category = mapLabelsToCategory(highConfidenceLabels);
|
||||||
|
|
||||||
|
// Sugerir nome baseado no objeto mais confiante
|
||||||
|
const suggestedName = objects[0]?.name || labels[0]?.description || 'Item';
|
||||||
|
|
||||||
|
return {
|
||||||
|
suggestedName,
|
||||||
|
category,
|
||||||
|
tags: highConfidenceLabels.slice(0, 5),
|
||||||
|
rawLabels: highConfidenceLabels
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Mapeamento de Labels → Categorias
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// constants/categoryMapping.js
|
||||||
|
|
||||||
|
export const LABEL_TO_CATEGORY = {
|
||||||
|
// Roupa
|
||||||
|
't-shirt': 'clothing',
|
||||||
|
'shirt': 'clothing',
|
||||||
|
'dress': 'clothing',
|
||||||
|
'jacket': 'clothing',
|
||||||
|
'coat': 'clothing',
|
||||||
|
'jeans': 'clothing',
|
||||||
|
'trousers': 'clothing',
|
||||||
|
'sweater': 'clothing',
|
||||||
|
'clothing': 'clothing',
|
||||||
|
'fashion': 'clothing',
|
||||||
|
|
||||||
|
// Eletrónica
|
||||||
|
'laptop': 'electronics',
|
||||||
|
'computer': 'electronics',
|
||||||
|
'smartphone': 'electronics',
|
||||||
|
'tablet': 'electronics',
|
||||||
|
'headphones': 'electronics',
|
||||||
|
'camera': 'electronics',
|
||||||
|
'charger': 'electronics',
|
||||||
|
'cable': 'electronics',
|
||||||
|
'electronics': 'electronics',
|
||||||
|
|
||||||
|
// Calçado
|
||||||
|
'shoe': 'footwear',
|
||||||
|
'boot': 'footwear',
|
||||||
|
'sneaker': 'footwear',
|
||||||
|
'sandal': 'footwear',
|
||||||
|
'footwear': 'footwear',
|
||||||
|
|
||||||
|
// Acessórios
|
||||||
|
'bag': 'accessories',
|
||||||
|
'backpack': 'accessories',
|
||||||
|
'watch': 'accessories',
|
||||||
|
'sunglasses': 'accessories',
|
||||||
|
'hat': 'accessories',
|
||||||
|
'belt': 'accessories',
|
||||||
|
|
||||||
|
// Documentos
|
||||||
|
'passport': 'documents',
|
||||||
|
'document': 'documents',
|
||||||
|
'book': 'documents',
|
||||||
|
'notebook': 'documents',
|
||||||
|
};
|
||||||
|
|
||||||
|
export function mapLabelsToCategory(labels) {
|
||||||
|
for (const label of labels) {
|
||||||
|
if (LABEL_TO_CATEGORY[label]) {
|
||||||
|
return LABEL_TO_CATEGORY[label];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 'other'; // fallback
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fluxo de UX ao adicionar item
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Utilizador tira foto
|
||||||
|
2. App mostra loading ("A analisar item...")
|
||||||
|
3. Google Vision responde com labels
|
||||||
|
4. App mostra:
|
||||||
|
- Nome sugerido (editável)
|
||||||
|
- Categoria sugerida (editável)
|
||||||
|
- Tags sugeridas (checkboxes, editáveis)
|
||||||
|
5. Utilizador confirma ou ajusta
|
||||||
|
6. Item guardado
|
||||||
|
```
|
||||||
|
|
||||||
|
> O utilizador tem **sempre** controlo final. A IA apenas sugere.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tratamento de erros
|
||||||
|
|
||||||
|
| Erro | Comportamento |
|
||||||
|
|------|---------------|
|
||||||
|
| API indisponível | Mostrar formulário manual, sem sugestões |
|
||||||
|
| Foto sem objeto reconhecível | Mostrar sugestão "Outro" e pedir nome manual |
|
||||||
|
| Score muito baixo (< 0.5) | Ignorar label, não sugerir |
|
||||||
|
| Timeout | Retry 1x, depois formulário manual |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Evolução futura desta camada
|
||||||
|
|
||||||
|
- Fase 2: Treinar modelo custom com os dados dos utilizadores
|
||||||
|
- Fase 3: Identificar marcas e modelos específicos
|
||||||
|
- Fase 3: Reconhecimento de cor dominante para filtros de outfit
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notas para o agente IA
|
||||||
|
|
||||||
|
- A chave da API (`GOOGLE_VISION_API_KEY`) nunca deve aparecer em código client-side em produção — usar Firebase Cloud Functions como proxy
|
||||||
|
- No MVP, a chamada pode ser feita diretamente do cliente para simplicidade
|
||||||
|
- Nunca guardar `rawLabels` como `name` sem confirmação do utilizador
|
||||||
|
- O mapeamento de labels é iterativo — quando encontrar labels não mapeadas, adicionar ao ficheiro `categoryMapping.js`
|
||||||
146
documentação/04_CATEGORIES_AND_TAGS.md
Normal file
146
documentação/04_CATEGORIES_AND_TAGS.md
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
# 🏷️ Sistema de Categorias e Tags
|
||||||
|
|
||||||
|
## Filosofia
|
||||||
|
|
||||||
|
O sistema de organização deve ser:
|
||||||
|
- **Simples o suficiente** para não sobrecarregar o utilizador
|
||||||
|
- **Flexível o suficiente** para cobrir a maioria dos casos reais
|
||||||
|
- **Extensível** para futuras funcionalidades (outfits, clima, etc.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Categorias Principais (MVP)
|
||||||
|
|
||||||
|
| ID | Nome | Ícone | Descrição |
|
||||||
|
|----|------|-------|-----------|
|
||||||
|
| `clothing` | Roupa | 👕 | Peças de vestuário |
|
||||||
|
| `electronics` | Eletrónica | 💻 | Dispositivos e acessórios tecnológicos |
|
||||||
|
| `footwear` | Calçado | 👟 | Sapatos, botas, sandálias |
|
||||||
|
| `accessories` | Acessórios | 🎒 | Bolsas, relógios, óculos, bijuteria |
|
||||||
|
| `documents` | Documentos | 📄 | Passaporte, cartões, papéis importantes |
|
||||||
|
| `other` | Outros | 📦 | Tudo o resto |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Subcategorias por Categoria
|
||||||
|
|
||||||
|
### 👕 Roupa (`clothing`)
|
||||||
|
```
|
||||||
|
casual → t-shirts, calças de ganga, hoodies
|
||||||
|
formal → fatos, camisas, vestidos de cerimónia
|
||||||
|
sportswear → leggings, tops de treino, shorts
|
||||||
|
outerwear → casacos, impermeáveis, parkas
|
||||||
|
underwear → roupa interior, meias
|
||||||
|
sleepwear → pijamas, roupões
|
||||||
|
```
|
||||||
|
|
||||||
|
### 💻 Eletrónica (`electronics`)
|
||||||
|
```
|
||||||
|
computers → portáteis, tablets
|
||||||
|
phones → smartphones, earphones
|
||||||
|
cameras → máquinas fotográficas, action cams
|
||||||
|
cables → carregadores, cabos USB, adaptadores
|
||||||
|
gaming → consolas, comandos, jogos
|
||||||
|
audio → headphones, colunas bluetooth
|
||||||
|
```
|
||||||
|
|
||||||
|
### 👟 Calçado (`footwear`)
|
||||||
|
```
|
||||||
|
casual → sapatilhas, loafers
|
||||||
|
formal → sapatos de salto, mocassins
|
||||||
|
sport → ténis de corrida, chuteiras
|
||||||
|
outdoor → botas de caminhada, sandálias
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🎒 Acessórios (`accessories`)
|
||||||
|
```
|
||||||
|
bags → mochilas, malas, bolsas
|
||||||
|
watches → relógios analógicos e digitais
|
||||||
|
eyewear → óculos de sol, óculos de grau
|
||||||
|
jewelry → colares, pulseiras, brincos
|
||||||
|
hats → bonés, chapéus, gorros
|
||||||
|
belts → cintos
|
||||||
|
```
|
||||||
|
|
||||||
|
### 📄 Documentos (`documents`)
|
||||||
|
```
|
||||||
|
identity → passaporte, BI, carta de condução
|
||||||
|
health → cartão de saúde, receitas
|
||||||
|
travel → bilhetes, reservas, seguros
|
||||||
|
financial → cartões de crédito/débito
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tags de Contexto
|
||||||
|
|
||||||
|
Estas tags determinam em que situações o item é relevante para sugestões:
|
||||||
|
|
||||||
|
| Tag | Descrição | Exemplos de itens |
|
||||||
|
|-----|-----------|-------------------|
|
||||||
|
| `travel` | Qualquer tipo de viagem | Mala, passaporte, adaptador de tomadas |
|
||||||
|
| `work` | Ambiente de trabalho | Portátil, fato, sapatos formais |
|
||||||
|
| `casual` | Dia-a-dia informal | Jeans, t-shirt, sapatilhas |
|
||||||
|
| `sport` | Atividade física | Leggings, ténis de corrida, garrafa de água |
|
||||||
|
| `formal` | Eventos formais | Fato, vestido, sapatos de salto |
|
||||||
|
| `outdoor` | Exterior e natureza | Blusão, botas, impermeável |
|
||||||
|
| `beach` | Praia ou piscina | Biquíni, chinelos, protetor solar |
|
||||||
|
| `cold` | Clima frio | Casaco, cachecol, luvas |
|
||||||
|
| `hot` | Clima quente | Roupa leve, t-shirts, sandálias |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Atribuição Automática de Tags de Contexto
|
||||||
|
|
||||||
|
Baseado na categoria e subcategoria, a app atribui context tags automaticamente:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// constants/contextTagRules.js
|
||||||
|
|
||||||
|
export const AUTO_CONTEXT_TAGS = {
|
||||||
|
// Por categoria
|
||||||
|
'clothing.formal': ['work', 'formal'],
|
||||||
|
'clothing.casual': ['casual', 'travel'],
|
||||||
|
'clothing.sportswear':['sport'],
|
||||||
|
'clothing.outerwear': ['travel', 'cold', 'outdoor'],
|
||||||
|
|
||||||
|
'electronics.computers': ['work', 'travel'],
|
||||||
|
'electronics.phones': ['travel', 'work', 'casual'],
|
||||||
|
'electronics.cables': ['travel'],
|
||||||
|
'electronics.gaming': ['casual', 'travel'],
|
||||||
|
|
||||||
|
'footwear.formal': ['work', 'formal'],
|
||||||
|
'footwear.casual': ['casual', 'travel'],
|
||||||
|
'footwear.sport': ['sport'],
|
||||||
|
'footwear.outdoor': ['outdoor', 'travel'],
|
||||||
|
|
||||||
|
'accessories.bags': ['travel', 'work', 'casual'],
|
||||||
|
'documents.identity':['travel'],
|
||||||
|
'documents.travel': ['travel'],
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Interface de Tags (UX)
|
||||||
|
|
||||||
|
### Ao adicionar um item:
|
||||||
|
1. Categoria é sugerida automaticamente (Google Vision)
|
||||||
|
2. Subcategoria é apresentada como lista (scroll horizontal)
|
||||||
|
3. Tags de contexto são pré-selecionadas automaticamente
|
||||||
|
4. Utilizador pode adicionar/remover tags livremente
|
||||||
|
5. Máximo de **10 tags por item** no MVP
|
||||||
|
|
||||||
|
### Pesquisa por tags:
|
||||||
|
- Filtro por categoria (dropdown ou tabs)
|
||||||
|
- Filtro por context tag (chips selecionáveis)
|
||||||
|
- Pesquisa textual (nome ou qualquer tag)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notas para o agente IA
|
||||||
|
|
||||||
|
- As categorias e subcategorias definidas aqui são **fixas** no MVP — não criar novas sem validar
|
||||||
|
- As context tags são a base do sistema de sugestões em `05_RECOMMENDATION_ENGINE.md`
|
||||||
|
- Quando o utilizador edita manualmente as tags, essas preferências devem ser guardadas e têm prioridade sobre as automáticas
|
||||||
|
- O sistema de tags deve ser simples de perceber sem documentação — usar labels em português na UI
|
||||||
187
documentação/05_RECOMMENDATION_ENGINE.md
Normal file
187
documentação/05_RECOMMENDATION_ENGINE.md
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
# 🎯 Motor de Recomendações
|
||||||
|
|
||||||
|
## Filosofia
|
||||||
|
|
||||||
|
> "Não precisas de IA para parecer inteligente. Precisas de regras bem pensadas."
|
||||||
|
|
||||||
|
O motor de recomendações evolui em 3 fases:
|
||||||
|
|
||||||
|
| Fase | Tecnologia | Estado |
|
||||||
|
|------|-----------|--------|
|
||||||
|
| 1 — Regras estáticas | Lógica JS simples | ✅ MVP |
|
||||||
|
| 2 — IA de linguagem | OpenAI API | 🔲 Fase 2 |
|
||||||
|
| 3 — Recomendação personalizada | Histórico + ML | 🔲 Fase 3 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## FASE 1 — Regras Estáticas (MVP)
|
||||||
|
|
||||||
|
### Contextos disponíveis
|
||||||
|
|
||||||
|
O utilizador escolhe um dos seguintes contextos:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// constants/contexts.js
|
||||||
|
|
||||||
|
export const CONTEXTS = [
|
||||||
|
{
|
||||||
|
id: 'travel_short',
|
||||||
|
label: 'Viagem curta (1-3 dias)',
|
||||||
|
icon: '✈️',
|
||||||
|
tags: ['travel'],
|
||||||
|
priorityCategories: ['documents', 'clothing', 'electronics', 'footwear'],
|
||||||
|
maxItems: 20,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'travel_long',
|
||||||
|
label: 'Viagem longa (4+ dias)',
|
||||||
|
icon: '🧳',
|
||||||
|
tags: ['travel'],
|
||||||
|
priorityCategories: ['documents', 'clothing', 'electronics', 'footwear', 'accessories'],
|
||||||
|
maxItems: 40,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'work',
|
||||||
|
label: 'Dia de trabalho',
|
||||||
|
icon: '💼',
|
||||||
|
tags: ['work'],
|
||||||
|
priorityCategories: ['electronics', 'clothing', 'footwear', 'accessories'],
|
||||||
|
maxItems: 15,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'casual',
|
||||||
|
label: 'Fim de semana casual',
|
||||||
|
icon: '😎',
|
||||||
|
tags: ['casual'],
|
||||||
|
priorityCategories: ['clothing', 'footwear', 'accessories'],
|
||||||
|
maxItems: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sport',
|
||||||
|
label: 'Treino / Desporto',
|
||||||
|
icon: '🏃',
|
||||||
|
tags: ['sport'],
|
||||||
|
priorityCategories: ['clothing', 'footwear'],
|
||||||
|
maxItems: 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'outdoor',
|
||||||
|
label: 'Saída para o exterior',
|
||||||
|
icon: '🌲',
|
||||||
|
tags: ['outdoor', 'travel'],
|
||||||
|
priorityCategories: ['clothing', 'footwear', 'accessories'],
|
||||||
|
maxItems: 12,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lógica de filtragem
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// services/suggestions.js
|
||||||
|
|
||||||
|
export function getSuggestionsForContext(items, contextId) {
|
||||||
|
const context = CONTEXTS.find(c => c.id === contextId);
|
||||||
|
if (!context) return [];
|
||||||
|
|
||||||
|
// 1. Filtrar itens com pelo menos uma tag do contexto
|
||||||
|
const relevantItems = items.filter(item =>
|
||||||
|
item.contextTags.some(tag => context.tags.includes(tag))
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2. Ordenar por prioridade de categoria
|
||||||
|
const sorted = relevantItems.sort((a, b) => {
|
||||||
|
const aIndex = context.priorityCategories.indexOf(a.category);
|
||||||
|
const bIndex = context.priorityCategories.indexOf(b.category);
|
||||||
|
const aPriority = aIndex === -1 ? 999 : aIndex;
|
||||||
|
const bPriority = bIndex === -1 ? 999 : bIndex;
|
||||||
|
return aPriority - bPriority;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. Limitar ao máximo de itens
|
||||||
|
return sorted.slice(0, context.maxItems);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exemplos de output
|
||||||
|
|
||||||
|
**Contexto: "Viagem curta"**
|
||||||
|
```
|
||||||
|
✅ Passaporte (documents.identity → travel)
|
||||||
|
✅ Portátil (electronics.computers → travel, work)
|
||||||
|
✅ Carregador USB-C (electronics.cables → travel)
|
||||||
|
✅ T-shirt preta (clothing.casual → casual, travel)
|
||||||
|
✅ Jeans azul (clothing.casual → casual, travel)
|
||||||
|
✅ Sapatilhas brancas (footwear.casual → casual, travel)
|
||||||
|
❌ Fato de treino (clothing.sportswear → sport) ← não aparece
|
||||||
|
❌ Consola PS5 (electronics.gaming → casual) ← não aparece
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## FASE 2 — IA de Linguagem (OpenAI API)
|
||||||
|
|
||||||
|
> **Não implementar no MVP. Esta secção é referência para a Fase 2.**
|
||||||
|
|
||||||
|
### Objetivo
|
||||||
|
|
||||||
|
Permitir ao utilizador escrever em linguagem natural:
|
||||||
|
- "Vou viajar 4 horas de comboio"
|
||||||
|
- "Tenho uma reunião importante amanhã de manhã"
|
||||||
|
- "Fim de semana na praia"
|
||||||
|
|
||||||
|
### Arquitetura proposta
|
||||||
|
|
||||||
|
```
|
||||||
|
Utilizador escreve frase
|
||||||
|
↓
|
||||||
|
OpenAI API (classificação de contexto)
|
||||||
|
↓
|
||||||
|
Retorna JSON estruturado:
|
||||||
|
{
|
||||||
|
"context": "travel",
|
||||||
|
"duration": "short",
|
||||||
|
"environment": "transit",
|
||||||
|
"weather": "unknown",
|
||||||
|
"formality": "casual"
|
||||||
|
}
|
||||||
|
↓
|
||||||
|
Motor de regras Fase 1 (com parâmetros enriquecidos)
|
||||||
|
↓
|
||||||
|
Lista de itens sugeridos
|
||||||
|
```
|
||||||
|
|
||||||
|
### Prompt base para OpenAI
|
||||||
|
|
||||||
|
```
|
||||||
|
System: És um assistente de inventário pessoal.
|
||||||
|
Analisa a frase do utilizador e devolve APENAS um JSON com:
|
||||||
|
- context: "travel" | "work" | "casual" | "sport" | "outdoor" | "formal"
|
||||||
|
- duration: "short" | "medium" | "long" | null
|
||||||
|
- environment: "indoor" | "outdoor" | "transit" | null
|
||||||
|
- weather: "cold" | "hot" | "rainy" | null
|
||||||
|
- formality: "casual" | "formal" | null
|
||||||
|
|
||||||
|
User: {frase do utilizador}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## FASE 3 — Recomendação Personalizada
|
||||||
|
|
||||||
|
> **Fase muito futura. Apenas visão.**
|
||||||
|
|
||||||
|
- Sistema aprende quais itens o utilizador seleciona/ignora das sugestões
|
||||||
|
- Pontuação de relevância por item por contexto
|
||||||
|
- Integração com API de clima para filtros automáticos
|
||||||
|
- Histórico de viagens para sugestões baseadas em padrões
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notas para o agente IA
|
||||||
|
|
||||||
|
- **No MVP, usar APENAS a Fase 1.** Não implementar OpenAI no MVP.
|
||||||
|
- A lógica de `getSuggestionsForContext` deve ser pura (sem side effects)
|
||||||
|
- Os contextos são fixos no MVP — não adicionar sem validar com o utilizador
|
||||||
|
- A ordenação por `priorityCategories` é intencional e importante — respeitá-la
|
||||||
|
- Quando a Fase 2 for implementada, o output do OpenAI deve mapear para os IDs de contexto da Fase 1
|
||||||
119
documentação/06_FUTURE_FEATURES.md
Normal file
119
documentação/06_FUTURE_FEATURES.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# 🚀 Roadmap e Funcionalidades Futuras
|
||||||
|
|
||||||
|
## Visão a longo prazo
|
||||||
|
|
||||||
|
> "Uma app que conhece tudo o que possuis e te diz exatamente o que precisas, quando precisas."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fases de desenvolvimento
|
||||||
|
|
||||||
|
```
|
||||||
|
FASE 1 — MVP (agora)
|
||||||
|
├── Upload de fotos
|
||||||
|
├── Guardar itens
|
||||||
|
├── Categorização manual + auto (Google Vision)
|
||||||
|
├── Pesquisa / filtro
|
||||||
|
└── Sugestões simples por regras
|
||||||
|
|
||||||
|
FASE 2 — IA de Linguagem
|
||||||
|
├── Input em linguagem natural
|
||||||
|
├── Integração OpenAI API
|
||||||
|
└── Contextos dinâmicos
|
||||||
|
|
||||||
|
FASE 3 — Personalização
|
||||||
|
├── Aprendizagem por histórico
|
||||||
|
├── Integração com clima
|
||||||
|
└── Sugestões proativas
|
||||||
|
|
||||||
|
FASE 4 — Social e Avançado
|
||||||
|
├── Outfits automáticos
|
||||||
|
├── Pack automático para viagens
|
||||||
|
├── Integração com calendário
|
||||||
|
└── Assistente conversacional
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Funcionalidades por fase
|
||||||
|
|
||||||
|
### 🔵 Fase 2 — IA de Linguagem
|
||||||
|
|
||||||
|
**Input em linguagem natural**
|
||||||
|
- Utilizador escreve ou fala: "Vou a uma conferência em Londres por 3 dias"
|
||||||
|
- App interpreta e gera lista personalizada
|
||||||
|
- Implementado via OpenAI API (ver `05_RECOMMENDATION_ENGINE.md`)
|
||||||
|
|
||||||
|
**Contextos dinâmicos**
|
||||||
|
- Em vez de escolher de uma lista, o utilizador descreve a situação
|
||||||
|
- App infere contexto, duração, clima esperado, formalidade
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🟡 Fase 3 — Personalização
|
||||||
|
|
||||||
|
**Aprendizagem por histórico**
|
||||||
|
- App regista quais itens o utilizador aceitou/ignorou nas sugestões
|
||||||
|
- Com 10+ interações, começa a ajustar pesos de relevância
|
||||||
|
- Exemplo: utilizador nunca leva sapatos formais em viagens curtas → app para de sugerir
|
||||||
|
|
||||||
|
**Integração com API de clima**
|
||||||
|
- Utilizador indica destino e datas
|
||||||
|
- App consulta previsão meteorológica
|
||||||
|
- Filtra roupa por temperatura e condições
|
||||||
|
- APIs candidatas: OpenWeatherMap, WeatherAPI
|
||||||
|
|
||||||
|
**Sugestões proativas (push notifications)**
|
||||||
|
- "Tens uma reunião amanhã — lembra-te do teu fato"
|
||||||
|
- "Viagem na sexta — queres ver a tua lista?"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🔴 Fase 4 — Funcionalidades Avançadas
|
||||||
|
|
||||||
|
**Montagem automática de outfits**
|
||||||
|
- App combina peças de roupa compatíveis visualmente
|
||||||
|
- Usa cor dominante extraída das fotos
|
||||||
|
- Sugere conjuntos completos (peça cima + baixo + calçado + acessório)
|
||||||
|
|
||||||
|
**Pack automático para viagens**
|
||||||
|
- Utilizador diz: "Vou 5 dias ao Porto, clima ameno, reuniões + lazer"
|
||||||
|
- App gera lista completa, organizada por tipo de item
|
||||||
|
- Permite marcar o que já está na mala (checklist)
|
||||||
|
|
||||||
|
**Integração com Google Calendar / Apple Calendar**
|
||||||
|
- App lê eventos do calendário
|
||||||
|
- Antecipa necessidades: "Reunião importante na 5ª feira → fato?"
|
||||||
|
- Notificações contextuais automáticas
|
||||||
|
|
||||||
|
**Assistente conversacional**
|
||||||
|
- Chat dentro da app
|
||||||
|
- Perguntas como: "O que devo levar amanhã?"
|
||||||
|
- Resposta baseada em calendário + clima + inventário
|
||||||
|
- Implementado via OpenAI Assistants API ou similar
|
||||||
|
|
||||||
|
**Funcionalidades sociais (opcional)**
|
||||||
|
- Partilhar listas com parceiro de viagem
|
||||||
|
- "O que ele/ela já vai levar?" para evitar duplicações
|
||||||
|
- Listas de viagem colaborativas
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Integrações externas planeadas
|
||||||
|
|
||||||
|
| Serviço | Fase | Objetivo |
|
||||||
|
|---------|------|----------|
|
||||||
|
| Google Vision AI | 1 (MVP) | Identificar objetos nas fotos |
|
||||||
|
| OpenAI API | 2 | Processar linguagem natural |
|
||||||
|
| OpenWeatherMap | 3 | Dados de clima por destino |
|
||||||
|
| Google Calendar | 4 | Antecipação de necessidades |
|
||||||
|
| Apple Calendar | 4 | Antecipação de necessidades (iOS) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notas para o agente IA
|
||||||
|
|
||||||
|
- Quando o utilizador pedir uma funcionalidade das Fases 2-4, não recusar — mas clarificar que está fora do MVP e perguntar se deve ser planeada para uma fase futura
|
||||||
|
- Não implementar funcionalidades de fases futuras sem confirmação explícita do utilizador
|
||||||
|
- Ao planear uma funcionalidade futura, criar um documento de especificação separado antes de implementar
|
||||||
|
- A ordem das fases é intencional — não saltar fases sem validação com utilizadores reais
|
||||||
184
documentação/07_AGENT_BEHAVIOR.md
Normal file
184
documentação/07_AGENT_BEHAVIOR.md
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
# 🤖 Comportamento do Agente IA
|
||||||
|
|
||||||
|
## Propósito deste ficheiro
|
||||||
|
|
||||||
|
Este ficheiro define como um agente IA (assistente de código, Cursor, Copilot, Claude, etc.) deve comportar-se quando trabalha neste projeto.
|
||||||
|
**Lê este ficheiro primeiro antes de qualquer tarefa.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contexto do projeto
|
||||||
|
|
||||||
|
Estás a trabalhar num projeto chamado **InventoryAI** — uma app móvel de gestão de inventário pessoal com sugestões contextuais.
|
||||||
|
|
||||||
|
Lê os seguintes ficheiros para entender o projeto completo:
|
||||||
|
1. `00_PROJECT_OVERVIEW.md` — visão geral e princípios
|
||||||
|
2. `01_MVP_DEFINITION.md` — o que está incluído no MVP
|
||||||
|
3. `02_ARCHITECTURE.md` — stack técnica e modelo de dados
|
||||||
|
4. `03_AI_VISION_LAYER.md` — integração com Google Vision
|
||||||
|
5. `04_CATEGORIES_AND_TAGS.md` — sistema de organização
|
||||||
|
6. `05_RECOMMENDATION_ENGINE.md` — lógica de sugestões
|
||||||
|
7. `06_FUTURE_FEATURES.md` — roadmap futuro
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Regras de comportamento
|
||||||
|
|
||||||
|
### ✅ SEMPRE fazer
|
||||||
|
|
||||||
|
- **Verificar o ficheiro MVP** antes de implementar qualquer funcionalidade — só implementar o que está em `01_MVP_DEFINITION.md`
|
||||||
|
- **Respeitar a stack definida** em `02_ARCHITECTURE.md` — Firebase, React Native, Google Vision
|
||||||
|
- **Usar o modelo de dados** exatamente como definido (campos, tipos, nomes)
|
||||||
|
- **Manter o código simples** — se há duas formas, escolher a mais simples
|
||||||
|
- **Comentar decisões de arquitetura** no código quando relevante
|
||||||
|
- **Avisar** quando uma funcionalidade pedida está fora do MVP
|
||||||
|
- **Perguntar** antes de alterar o modelo de dados ou a arquitetura
|
||||||
|
- **Criar ficheiros de serviço** em `src/services/` para lógica de negócio
|
||||||
|
- **Usar constantes** de `src/constants/` para valores fixos (categorias, contextos, etc.)
|
||||||
|
|
||||||
|
### ❌ NUNCA fazer
|
||||||
|
|
||||||
|
- Adicionar funcionalidades que não estão no MVP sem confirmação explícita
|
||||||
|
- Mudar a stack tecnológica (ex: sugerir Flutter, Supabase, AWS)
|
||||||
|
- Implementar OpenAI no MVP — fica para a Fase 2
|
||||||
|
- Guardar a API key do Google Vision em código client-side em produção
|
||||||
|
- Criar lógica de base de dados fora dos ficheiros `services/`
|
||||||
|
- Usar `console.log` em produção para dados sensíveis do utilizador
|
||||||
|
- Alterar os nomes dos campos do modelo de dados sem avisar
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Linguagem e comunicação
|
||||||
|
|
||||||
|
- Comunicar em **português** (de Portugal, não do Brasil)
|
||||||
|
- Explicações técnicas devem ser **claras e objetivas**
|
||||||
|
- Quando há uma decisão de arquitetura, **explicar o porquê**
|
||||||
|
- Usar **exemplos de código** sempre que possível
|
||||||
|
- Avisos sobre o MVP devem ser **visíveis** (usar emoji ⚠️ ou bloco de nota)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ordem de construção obrigatória
|
||||||
|
|
||||||
|
Seguir esta ordem ao implementar. Não avançar para o próximo passo sem o anterior estar funcional:
|
||||||
|
|
||||||
|
```
|
||||||
|
PASSO 1: 📸 Upload de fotos
|
||||||
|
└── Câmara + seleção de galeria
|
||||||
|
└── Upload para Firebase Storage
|
||||||
|
└── URL guardado no estado
|
||||||
|
|
||||||
|
PASSO 2: 📦 Guardar itens
|
||||||
|
└── Formulário básico (nome, categoria)
|
||||||
|
└── Gravar no Firestore
|
||||||
|
└── Autenticação Firebase
|
||||||
|
|
||||||
|
PASSO 3: 🏷️ Categorização
|
||||||
|
└── Integração Google Vision API
|
||||||
|
└── Mapeamento labels → categorias
|
||||||
|
└── UI de confirmação/edição
|
||||||
|
|
||||||
|
PASSO 4: 🔍 Pesquisa e visualização
|
||||||
|
└── Lista de itens (grid)
|
||||||
|
└── Filtro por categoria
|
||||||
|
└── Pesquisa por nome
|
||||||
|
|
||||||
|
PASSO 5: 🎯 Sugestões simples
|
||||||
|
└── Seleção de contexto
|
||||||
|
└── Lógica de filtragem por tags
|
||||||
|
└── Apresentação da lista sugerida
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Como responder a pedidos fora do MVP
|
||||||
|
|
||||||
|
Quando o utilizador pede uma funcionalidade que está fora do MVP:
|
||||||
|
|
||||||
|
```
|
||||||
|
⚠️ MVP: Esta funcionalidade não está incluída no MVP atual.
|
||||||
|
|
||||||
|
Está documentada como [Fase X] em 06_FUTURE_FEATURES.md.
|
||||||
|
|
||||||
|
Opções:
|
||||||
|
1. Adiar para a Fase X (recomendado — manter foco no MVP)
|
||||||
|
2. Priorizar agora (implica atrasar outras funcionalidades do MVP)
|
||||||
|
|
||||||
|
O que preferes?
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Padrões de código obrigatórios
|
||||||
|
|
||||||
|
### Nomenclatura
|
||||||
|
```javascript
|
||||||
|
// Componentes React: PascalCase
|
||||||
|
ItemCard.jsx
|
||||||
|
AddItemScreen.jsx
|
||||||
|
|
||||||
|
// Serviços e utilitários: camelCase
|
||||||
|
visionApi.js
|
||||||
|
suggestions.js
|
||||||
|
|
||||||
|
// Constantes: camelCase (ficheiros), UPPER_SNAKE_CASE (valores)
|
||||||
|
categoryMapping.js → export const LABEL_TO_CATEGORY = { ... }
|
||||||
|
contexts.js → export const CONTEXTS = [ ... ]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Estrutura de um serviço
|
||||||
|
```javascript
|
||||||
|
// services/exemplo.js
|
||||||
|
|
||||||
|
// 1. Imports
|
||||||
|
import { db } from './firebase';
|
||||||
|
|
||||||
|
// 2. Funções puras (sem side effects)
|
||||||
|
export function processarDados(input) { ... }
|
||||||
|
|
||||||
|
// 3. Funções de base de dados
|
||||||
|
export async function guardarItem(userId, item) { ... }
|
||||||
|
export async function obterItens(userId) { ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tratamento de erros
|
||||||
|
```javascript
|
||||||
|
// Sempre usar try/catch em chamadas assíncronas
|
||||||
|
try {
|
||||||
|
const resultado = await guardarItem(userId, novoItem);
|
||||||
|
// sucesso
|
||||||
|
} catch (erro) {
|
||||||
|
console.error('Erro ao guardar item:', erro.message);
|
||||||
|
// mostrar mensagem ao utilizador (não o erro técnico)
|
||||||
|
Alert.alert('Erro', 'Não foi possível guardar o item. Tenta novamente.');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Perguntas frequentes
|
||||||
|
|
||||||
|
**P: O utilizador pediu uma funcionalidade — implemento já?**
|
||||||
|
R: Verificar `01_MVP_DEFINITION.md`. Se estiver no MVP, implementar. Se não, avisar e perguntar.
|
||||||
|
|
||||||
|
**P: Posso usar uma biblioteca nova?**
|
||||||
|
R: Só se resolver um problema que não tem solução simples sem ela. Avisar antes de instalar.
|
||||||
|
|
||||||
|
**P: O modelo de dados precisa de um campo novo — adiciono?**
|
||||||
|
R: Avisar o utilizador, explicar o impacto, aguardar confirmação.
|
||||||
|
|
||||||
|
**P: A API do Google Vision não está a funcionar nos testes — o que fazer?**
|
||||||
|
R: Criar um mock local (`services/visionApiMock.js`) que retorna dados fixos para desenvolvimento.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ficheiros de referência rápida
|
||||||
|
|
||||||
|
| Quero saber... | Ficheiro |
|
||||||
|
|----------------|----------|
|
||||||
|
| O que está no MVP? | `01_MVP_DEFINITION.md` |
|
||||||
|
| Que tecnologias usar? | `02_ARCHITECTURE.md` |
|
||||||
|
| Como a IA de imagem funciona? | `03_AI_VISION_LAYER.md` |
|
||||||
|
| Que categorias existem? | `04_CATEGORIES_AND_TAGS.md` |
|
||||||
|
| Como funcionam as sugestões? | `05_RECOMMENDATION_ENGINE.md` |
|
||||||
|
| O que vem a seguir? | `06_FUTURE_FEATURES.md` |
|
||||||
70
documentação/AI_AGENTS_LOG.md
Normal file
70
documentação/AI_AGENTS_LOG.md
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# 📝 AI Agents Log
|
||||||
|
|
||||||
|
## Propósito
|
||||||
|
|
||||||
|
Este ficheiro regista toda a atividade do agente de recomendação.
|
||||||
|
Cada execução gera uma entrada neste log.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Formato de Entrada
|
||||||
|
|
||||||
|
### Data:
|
||||||
|
YYYY-MM-DD
|
||||||
|
|
||||||
|
### Agente:
|
||||||
|
Recommender-MVP
|
||||||
|
|
||||||
|
### Tipo:
|
||||||
|
- recomendacao
|
||||||
|
- erro
|
||||||
|
- melhoria
|
||||||
|
|
||||||
|
### Descrição:
|
||||||
|
O que foi feito
|
||||||
|
|
||||||
|
### Itens afetados:
|
||||||
|
Lista de itens usados
|
||||||
|
|
||||||
|
### Ação tomada:
|
||||||
|
O que se decidiu
|
||||||
|
|
||||||
|
### Notas:
|
||||||
|
Observações úteis
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Regras de Logging
|
||||||
|
|
||||||
|
1. **SEMPRE** registar após cada execução
|
||||||
|
2. Tipo `recomendacao` → quando sugestões são geradas com sucesso
|
||||||
|
3. Tipo `erro` → quando lista vazia, pedido ambíguo ou dados incompletos
|
||||||
|
4. Tipo `melhoria` → quando se detetam problemas no sistema
|
||||||
|
5. Nunca omitir entradas de erro — são tão importantes como sucessos
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Histórico
|
||||||
|
|
||||||
|
### Data:
|
||||||
|
2026-04-24
|
||||||
|
|
||||||
|
### Agente:
|
||||||
|
Recommender-MVP
|
||||||
|
|
||||||
|
### Tipo:
|
||||||
|
recomendacao
|
||||||
|
|
||||||
|
### Descrição:
|
||||||
|
Implementação inicial do motor de recomendações MVP. Sistema de regras estáticas com 6 contextos, parser por palavras-chave, logging e deteção de melhorias.
|
||||||
|
|
||||||
|
### Itens afetados:
|
||||||
|
T-shirt preta, Portátil, Nintendo Switch, Fones de ouvido, Passaporte, Carregador USB-C, Jeans azul, Sapatilhas brancas, Mochila, Fato de treino
|
||||||
|
|
||||||
|
### Ação tomada:
|
||||||
|
Criado APPprojetoLP.dart com modelo de dados alinhado com 02_ARCHITECTURE.md, contextos de 05_RECOMMENDATION_ENGINE.md, e tags de 04_CATEGORIES_AND_TAGS.md
|
||||||
|
|
||||||
|
### Notas:
|
||||||
|
- Parser de pedidos é básico (palavras-chave). Fase 2 usará OpenAI API.
|
||||||
|
- Clima e formalidade são detetados mas não filtram itens no MVP.
|
||||||
|
- Duração "medium" (ex: 4 horas) não tem regras específicas ainda.
|
||||||
115
documentação/RULE_ENGINE.md
Normal file
115
documentação/RULE_ENGINE.md
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# ⚙️ Rule Engine — Regras de Recomendação (MVP)
|
||||||
|
|
||||||
|
## Propósito
|
||||||
|
|
||||||
|
Define as regras estáticas que o motor de recomendações segue para sugerir itens ao utilizador.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Regras Ativas (MVP)
|
||||||
|
|
||||||
|
### R1 — Filtragem por Context Tags
|
||||||
|
```
|
||||||
|
IF item.contextTags contém pelo menos uma tag do contexto
|
||||||
|
THEN item é relevante
|
||||||
|
```
|
||||||
|
|
||||||
|
### R2 — Ordenação por Prioridade de Categoria
|
||||||
|
```
|
||||||
|
Ordenar itens pela posição da categoria em context.priorityCategories
|
||||||
|
Categorias fora da lista → prioridade baixa (999)
|
||||||
|
```
|
||||||
|
|
||||||
|
### R3 — Limite de Itens
|
||||||
|
```
|
||||||
|
Retornar no máximo context.maxItems itens
|
||||||
|
```
|
||||||
|
|
||||||
|
| Contexto | maxItems |
|
||||||
|
|----------|----------|
|
||||||
|
| travel_short | 20 |
|
||||||
|
| travel_long | 40 |
|
||||||
|
| work | 15 |
|
||||||
|
| casual | 10 |
|
||||||
|
| sport | 8 |
|
||||||
|
| outdoor | 12 |
|
||||||
|
|
||||||
|
### R4 — Interpretação de Pedido (Parser)
|
||||||
|
```
|
||||||
|
Palavras-chave → contexto + duração + clima + formalidade
|
||||||
|
|
||||||
|
viagem/comboio/voo → travel_short + transit
|
||||||
|
trabalho/reunião → work + indoor
|
||||||
|
fim de semana/casual/lazer → casual
|
||||||
|
treino/desporto/gym → sport
|
||||||
|
exterior/caminhada → outdoor + outdoor
|
||||||
|
|
||||||
|
4+ dias/semana/longa → duration:long + upgrade para travel_long
|
||||||
|
4 horas/média → duration:medium
|
||||||
|
1-2 horas/curta → duration:short
|
||||||
|
|
||||||
|
frio/inverno → weather:cold
|
||||||
|
calor/verão/praia → weather:hot
|
||||||
|
chuva → weather:rainy
|
||||||
|
|
||||||
|
formal/cerimónia → formality:formal
|
||||||
|
casual/informal → formality:casual
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Regras Pendentes (a implementar)
|
||||||
|
|
||||||
|
### R5 — Filtro por Duração
|
||||||
|
```
|
||||||
|
IF duration == short → apenas essenciais (documents, cables, 1x clothing)
|
||||||
|
IF duration == medium → essenciais + entretenimento
|
||||||
|
IF duration == long → essenciais + entretenimento + conforto extra
|
||||||
|
```
|
||||||
|
**Estado:** Não implementado no MVP atual. Duração é detetada mas não filtra.
|
||||||
|
|
||||||
|
### R6 — Filtro por Clima
|
||||||
|
```
|
||||||
|
IF weather == cold → priorizar outerwear, remover beach/hot items
|
||||||
|
IF weather == hot → priorizar roupa leve, remover cold items
|
||||||
|
IF weather == rainy → priorizar outerwear + accessories.impermeável
|
||||||
|
```
|
||||||
|
**Estado:** Clima é detetado mas não filtra itens no MVP.
|
||||||
|
|
||||||
|
### R7 — Filtro por Formalidade
|
||||||
|
```
|
||||||
|
IF formality == formal → priorizar clothing.formal, footwear.formal
|
||||||
|
IF formality == casual → excluir clothing.formal
|
||||||
|
```
|
||||||
|
**Estado:** Formalidade é detetada mas não filtra itens no MVP.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Mapeamento de Context Tags (04_CATEGORIES_AND_TAGS.md)
|
||||||
|
|
||||||
|
| Categoria.Subcategoria | Context Tags |
|
||||||
|
|------------------------|-------------|
|
||||||
|
| clothing.formal | work, formal |
|
||||||
|
| clothing.casual | casual, travel |
|
||||||
|
| clothing.sportswear | sport |
|
||||||
|
| clothing.outerwear | travel, cold, outdoor |
|
||||||
|
| electronics.computers | work, travel |
|
||||||
|
| electronics.phones | travel, work, casual |
|
||||||
|
| electronics.cables | travel |
|
||||||
|
| electronics.gaming | casual, travel |
|
||||||
|
| footwear.formal | work, formal |
|
||||||
|
| footwear.casual | casual, travel |
|
||||||
|
| footwear.sport | sport |
|
||||||
|
| footwear.outdoor | outdoor, travel |
|
||||||
|
| accessories.bags | travel, work, casual |
|
||||||
|
| documents.identity | travel |
|
||||||
|
| documents.travel | travel |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notas para o Agente
|
||||||
|
|
||||||
|
- **NÃO** adicionar regras novas sem validar com o utilizador
|
||||||
|
- As regras R5-R7 estão identificadas como pendentes — implementar quando o MVP base estiver estável
|
||||||
|
- O parser de palavras-chave (R4) é temporário — Fase 2 substitui por OpenAI
|
||||||
|
- Sempre que uma regra pendente for implementada, atualizar este ficheiro e o AI_AGENTS_LOG.md
|
||||||
Reference in New Issue
Block a user