From e11d14ab578462822e55f5e763e4b5d10ed456f3 Mon Sep 17 00:00:00 2001 From: Roni Fabio Banaszewski Date: Thu, 10 Sep 2026 19:22:11 -0300 Subject: [PATCH 1/3] chore: adota npm workspaces na raiz do monorepo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O `architecture.md` mandava o `/utf-setup` copiar "os scripts de orquestração descritos no documento", mas não havia seção nenhuma onde descrevê-los — e a raiz sequer aparecia na árvore do §3. Sem isso, cada repositório inventava a sua raiz, e quem clonava instalava dependência duas vezes: uma na raiz (pelo json-server) e outra em `apps/web`. - `docs/architecture.md`: nova §3.1 com o `package.json` da raiz — `"private": true`, `"workspaces": ["apps/*"]` e os scripts `start`, `build`, `test`, `lint` e `api`. A raiz também passa a aparecer na árvore do §3. - `.agents/workflows/utf-setup.md`: gerar o app com `--skip-install` e instalar uma vez só, na raiz, depois que o `package.json` dela existir. Fora dessa ordem o npm cria um `node_modules` dentro de `apps/web` e o hoisting não acontece — sem erro nenhum, só desperdício invisível. Nx e Turborepo continuam fora: resolvem cache de build e grafo de dependências entre muitos subprojetos, que não é o problema desta disciplina. Co-Authored-By: Claude Opus 5 (1M context) --- .agents/workflows/utf-setup.md | 22 ++++++++++++++++++---- docs/architecture.md | 28 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/.agents/workflows/utf-setup.md b/.agents/workflows/utf-setup.md index ad07e79..84824b5 100644 --- a/.agents/workflows/utf-setup.md +++ b/.agents/workflows/utf-setup.md @@ -62,6 +62,12 @@ dentro da estrutura de pastas que o documento descreve. instalado — gerador desatualizado ou incompatível descoberto no meio do passo é retrabalho. - Desative o `git init` interno do gerador — o repositório é um só, na raiz. +- **Gere com a instalação de dependências desligada** (`--skip-install` no + `ng new`). O `package.json` da raiz, que declara os workspaces, só nasce no + Passo 3 — e um `npm install` disparado antes dele cria um `node_modules` + próprio dentro de `apps/web`, sem hoisting. A instalação acontece uma vez só, + na raiz, no fim do Passo 3. Se algum `ng add` precisar rodar antes disso, + faça a instalação da raiz primeiro. - Aceite os padrões do gerador. Não adicione biblioteca que o `architecture.md` não menciona. - Se o `architecture.md` declara ferramenta de teste diferente do padrão do gerador, @@ -86,10 +92,18 @@ dentro da estrutura de pastas que o documento descreve. Sem isso, um repositório tocado em Windows e Linux reescreve todos os arquivos a cada troca de máquina, e o diff de qualquer PR vira ruído. -3. `package.json` da raiz com os scripts de orquestração descritos no - `architecture.md` (ex.: `start`, `api`, `test`) — é ele que poupa o aluno de - entrar em `apps/web` a cada comando. Se o documento traz os scripts prontos, - copie-os literalmente. Dois casos desta disciplina: +3. `package.json` da raiz — **a raiz do npm workspace**, no formato do §3.1 do + `architecture.md`: `"private": true`, `"workspaces": ["apps/*"]` e os scripts de + orquestração (`start`, `build`, `test`, `lint`, `api`). É ele que dá um + `npm install` único para o repositório inteiro e poupa o aluno de entrar em + `apps/web` a cada comando — a flag `-w apps/web` faz isso por ele. Se o documento + traz os scripts prontos, copie-os literalmente. + + **Depois de criá-lo, rode `npm install` na raiz** — é esta instalação que junta as + dependências num `node_modules` só. Se `apps/web/node_modules` existir (geração + feita sem `--skip-install`), remova antes de instalar. + + Dois casos desta disciplina: - **json-server declarado para o MVP:** adicione a dependência, o script (`"api": "json-server db.json"` ou equivalente) e um `db.json` **vazio de negócio** (`{}`) — as entidades chegam pelas histórias, nunca pelo setup. diff --git a/docs/architecture.md b/docs/architecture.md index c9339e4..9058900 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -76,6 +76,7 @@ ├── README.md # a vitrine, na estrutura exigida pela ficha ├── docs/ # prd.md, este arquivo, design-tokens.md, checklist.md e guias ├── specs/ # uma pasta por história implementada +├── package.json # a raiz do workspace: scripts de orquestração (§3.1) └── apps/ ├── web/ # o app Angular — package.json próprio └── api/ # reservada para uma API real, se um dia existir @@ -88,6 +89,33 @@ > setup não gera backend nenhum; ela só guarda o lugar (e o `db.json` do > json-server, se o documento assim declarar). +### 📦 3.1. A raiz do monorepo (npm workspaces) + +O `package.json` da raiz declara os subprojetos e concentra os comandos: + +```json +{ + "name": "[nome-do-projeto]", + "private": true, + "workspaces": ["apps/*"], + "scripts": { + "start": "npm run start -w apps/web", + "build": "npm run build -w apps/web", + "test": "npm run test -w apps/web", + "lint": "npm run lint -w apps/web", + "api": "json-server db.json" + } +} +``` + +> 📌 **O que os workspaces resolvem aqui.** Um `npm install` na raiz instala as +> dependências de todos os `apps/*` de uma vez, num `node_modules` só: quem clona o +> repositório roda **um** comando, não um por pasta. A flag `-w` executa um script +> dentro de um subprojeto sem `cd`. O curinga `apps/*` faz qualquer pasta nova ali +> dentro ser reconhecida sem editar este arquivo, e `"private": true` impede a +> publicação acidental no npm. **`apps/api/` não tem `package.json` e é ignorada pelo +> npm** — nada a fazer nela. + ### Organização interna do app (`apps/web/src/app/` — feature-driven) [decidido na entrevista: `core/` (singletons: guards, interceptors, services de From 45379ab9a8d7fd998f1c1589a6f3ee14e5968840 Mon Sep 17 00:00:00 2001 From: Roni Fabio Banaszewski Date: Thu, 10 Sep 2026 19:32:01 -0300 Subject: [PATCH 2/3] =?UTF-8?q?chore:=20o=20setup=20instala=20o=20linter?= =?UTF-8?q?=20e=20a=20formata=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O Passo 5 mandava rodar o lint como prova de vida, e o `architecture.md` §2 exige declarar "os comandos exatos de suíte e lint" — mas nada instalava linter nenhum. O `ng new` não traz ESLint. Na prática o setup declarava um comando, exigia que ele passasse, e deixava o aluno com `npm run lint` inexistente. - Passo 2: `ng add angular-eslint` quando o documento declara comando de lint — gera o `eslint.config.js` e o alvo `lint` no `angular.json`. (O pacote é `angular-eslint`; `@angular-eslint/schematics` é o nome antigo.) - Passo 3, item 4: Prettier e `eslint-config-prettier` na raiz, mais `.prettierrc` e `.editorconfig`, e o script `format`. O `eslint-config-prettier` não é precaução teórica: a config recomendada do angular-eslint inclui `tseslint.configs.stylistic`, que conflita com o Prettier de verdade. - `architecture.md`: a linha de testes passa a dizer que o linter não vem no gerador, e o §3.1 ganha o script `format`. Extensão de IDE fica de fora de propósito — o que se versiona aqui é a regra que o agente lê; obedecer a ela é configuração da máquina de cada um. Co-Authored-By: Claude Opus 5 (1M context) --- .agents/workflows/utf-setup.md | 29 +++++++++++++++++++++++++++++ docs/architecture.md | 3 ++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/.agents/workflows/utf-setup.md b/.agents/workflows/utf-setup.md index 84824b5..3382dbd 100644 --- a/.agents/workflows/utf-setup.md +++ b/.agents/workflows/utf-setup.md @@ -70,6 +70,11 @@ dentro da estrutura de pastas que o documento descreve. faça a instalação da raiz primeiro. - Aceite os padrões do gerador. Não adicione biblioteca que o `architecture.md` não menciona. +- **O linter não vem no `ng new`.** Se o `architecture.md` declara um comando de + lint (e ele declara — §2 exige os comandos exatos de suíte e lint), instale o + oficial: `ng add angular-eslint`. Ele gera o `eslint.config.js` e cria o alvo + `lint` no `angular.json`. Sem isso, a prova de vida do Passo 5 roda um comando + que não existe. - Se o `architecture.md` declara ferramenta de teste diferente do padrão do gerador, siga o documento; se não declara, fique com o padrão do gerador e **relate isso no fim** como decisão que o usuário precisa ratificar no `architecture.md`. @@ -111,6 +116,30 @@ dentro da estrutura de pastas que o documento descreve. `manifest.webmanifest` com a identidade decidida no `/utf-design` (nome curto, cores, ícones) — sem inventar valores. +4. **Formatação, na raiz — regra do projeto, não preferência de quem digita.** + + Na raiz (sem `-w`, para ficarem como dependência da raiz e hoisted para todos + os apps): + + ``` + npm install -D prettier eslint-config-prettier + ``` + + Mais um `.prettierrc` (pode nascer `{}` — o padrão do Prettier serve) e um + `.editorconfig` com `indent_style`, `indent_size`, `end_of_line = lf` e + `insert_final_newline`. Acrescente ao `package.json` da raiz: + `"format": "prettier --write ."`. + + O `eslint-config-prettier` desliga as regras de estilo do ESLint que brigariam + com o Prettier — a config recomendada do angular-eslint inclui + `tseslint.configs.stylistic`, então o conflito é real, não teórico. Aplique-o + **por último** no `eslint.config.js`. + + Estes arquivos são o que o agente lê para saber como escrever: sem eles, cada + integrante formata de um jeito e todo Pull Request vira ruído de espaço em + branco. **Não instale extensão de IDE por eles** — extensão é da máquina de + cada um; aqui o que se versiona é a regra. + ## Passo 4 — As ferramentas do método O `.github/` **já vem no template**: `pull_request_template.md` e diff --git a/docs/architecture.md b/docs/architecture.md index 9058900..29473f7 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -47,7 +47,7 @@ - **Framework CSS:** [Tailwind, PrimeNG, …] (ID5) - **Dados (em duas fases):** **json-server** no MVP (E2) → **[Supabase, PocketBase, …]** na E3, com autenticação (JWT) e CRUD reais (IDs 21–22). A troca atinge só os Services (§2.1). - **PWA:** `manifest.webmanifest` — ícones, cores de tema, splash, standalone, offline (ID3) -- **Testes:** [ferramenta do gerador] + comandos exatos de suíte e lint (ID33) +- **Testes e lint:** [ferramenta do gerador] + comandos exatos de suíte e lint (ID33). O linter não vem no `ng new`: o setup instala o oficial (`ng add angular-eslint`), mais Prettier e `eslint-config-prettier` na raiz. ### 🌐 2.1. Camada de dados — regras estruturais @@ -103,6 +103,7 @@ O `package.json` da raiz declara os subprojetos e concentra os comandos: "build": "npm run build -w apps/web", "test": "npm run test -w apps/web", "lint": "npm run lint -w apps/web", + "format": "prettier --write .", "api": "json-server db.json" } } From 83ffc5d68532ab02679ea78b8c2d88b5d78c1099 Mon Sep 17 00:00:00 2001 From: Roni Fabio Banaszewski Date: Thu, 10 Sep 2026 19:35:22 -0300 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20o=20setup=20leva=20os=20design=20to?= =?UTF-8?q?kens=20at=C3=A9=20o=20CSS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O /utf-design conduzia uma entrevista inteira para decidir paleta com papel semântico, tipografia, espaçamento e breakpoints — e nada nunca escrevia isso no arquivo de estilo do app. O `design-tokens.md` prometia ser "de onde a IA vai ler quando começar a gerar tela", mas o Tailwind lê o bloco `@theme`, não o Markdown. Na prática o aluno decidia a paleta e o app seguia com as cores de fábrica. - Passo 2: depois de instalar o framework CSS, o setup **pergunta** se escreve o bloco de tema a partir do `design-tokens.md` ou se o aluno prefere escrever. Escrevendo, transcreve só o que está no documento para os namespaces do Tailwind, mantendo os nomes semânticos da equipe; valor ausente é pergunta, nunca invenção. Biblioteca com mecanismo próprio de tema (daisyUI) usa o dela, para não declarar cor em dois lugares. - Passo 0: `docs/design-tokens.md` entra nas pré-condições, já que agora é lido. - Passo 6: o despacho do tutor leva o `design-tokens.md` e o arquivo de estilo. - Tutor, modo `setup`: nova seção "O tema, do documento ao CSS" — token por token, por que o nome é o do papel e não o da cor, e o que muda no app inteiro quando um valor é trocado. Co-Authored-By: Claude Opus 5 (1M context) --- .agents/agents/tutor.md | 6 ++++++ .agents/workflows/utf-setup.md | 33 ++++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/.agents/agents/tutor.md b/.agents/agents/tutor.md index 032e8aa..351b2d1 100644 --- a/.agents/agents/tutor.md +++ b/.agents/agents/tutor.md @@ -226,6 +226,12 @@ o que a pasta `apps/api`, reservada e vazia, está guardando lugar para> (só os que importam: o `package.json`, `angular.json`, `tsconfig.json`, a configuração do runner de teste, `.gitignore`, `.gitattributes`, `.github/`) +## O tema, do documento ao CSS + + ## Por que a suíte nasce verde e vazia