Aprovar design
Escrever spec → revisão → plano de implementação
Arquitetura, componentes, fluxo de dados e testes — revise seção por seção
A cena Three.js passa de órbita isométrica para exploração a pé. O backend continua o mesmo (Sanctum + /city/data), mas o payload ganha: ruas, prédios gerados, e um streaming de mensagens de chat via SSE (Server-Sent Events) por agente — sem dependência nova.
Frontend (Three.js)
├── CameraController — WASD + mouse, colisão AABB
├── CityGenerator — ruas, quadras, prédios de preenchimento
├── CharacterFactory — carrega modelos GLTF por tipo de agente
├── HudOverlay — painel POSIÇÃO + minimapa
└── ChatPanel — fluxo SSE /city/chat/{agent}
Backend (Laravel)
├── CityViewerController::data() — stores + agents + city layout
├── ChatController — SSE endpoint por agente
└── AgentThinkJob (queue) — chama OpenRouter, persiste last_decision
| CameraController | Pointer-lock, WASD, gravidade simples, raycast contra colisores AABB de prédios |
| CityGenerator | Rua central + quadras laterais a partir das posições das lojas; prédios de preenchimento procedural (seed determinística) |
| StreetMesh | Asfalto (canvas texture com faixas), calçada de ladrilho, postes a cada N metros |
| CharacterFactory | GLTF por agent.type; fallback: cápsula texturizada. Animação Idle/Walk/Run |
| HudOverlay | Painel POSIÇÃO (x,y,z, triângulos) + minimapa 2D no canto |
| ChatPanel | Abre ao clicar no NPC; mostra nome, status (pensando/respondendo), mensagens; envia via POST e recebe via SSE |
GET /city/data → lojas + agentes + layout de ruasCityGenerator monta ruas e prédios; prédios de loja ganham fachada customChatPanel abre → GET /city/chat/{agent}/stream (SSE)POST /city/chat/{agent} → job enfileirado → OpenRouter → persiste last_decision → SSE emite respostaerror_count++, backoff exponencial, status vira error no painelCityViewerController::data() retorna layout; ChatController valida input e rate-limit; job persiste last_decisionCameraController (colisão, WASD), CityGenerator (determinístico com seed), reconexão SSEEsse design está correto? Aprovo para escrever a especificação formal.