[
 {
  "chave": "CS-165",
  "territorio": "backend",
  "titulo": "A SECRETARIA GANHA LEITURA PROPRIA — `GET /aulas/secretaria` traz AO VIVO **E** PERMANENTES, e o `GET /aulas` DE HOJE ⛔ NAO SE TOCA. 🩸 A MEDICAO QUE OBRIGA A ESTE CARD, feita no codigo e ⛔ nao adivinhada: a lista da secretaria pede `GET /aulas` (`frontend/src/app/secretaria/aulas/dados.ts:137,195`), que e' servido por `calendario()` (`backend/src/modules/aula/aula.servico.ts:269`) com `where: { permanente: false }` SEMPRE (`:283`) e ainda a OMITIR as linhas de `inicio` nulo (`:306`); e o contrato `AulaNoCalendario` (`backend/src/modules/aula/aula.tipos.ts:64`) ⛔ nao tem campo `permanente` e tem `inicio: Date` ⛔ NAO anulavel. ⟹ HOJE A PERMANENTE ⛔ NAO APARECE NA SECRETARIA — ⛔ NEM EM «TODAS» — e o §3 da regra 292 ⛔ ja' nao e' verdade. ⟹ ROTA NOVA, ⛔ nao parametro na velha: `aquele `permanente: false` e' DELIBERADO e de ambito — o comentario ao lado diz que e' «uma lista de HORARIOS» e que a permanente «⛔ nao teria onde se encaixar». `GET /aulas` e' O CALENDARIO DO MEDICO (CS-17, CS-89) e mexer la' mudava o ecra dele, que ⛔ ninguem pediu; rota separada faz do «⛔ nao se toca» uma coisa PROVAVEL POR DIFF, e e' ADITIVA logo REVERSIVEL. O QUE A ROTA DEVOLVE, por linha: `{id, titulo, especialidade, nucleo, permanente, inicio, duracaoMin, blocos, responsavel}` — exactamente a forma que o frontend JA' DECLARA em `AulaNaLista` (`dados.ts:93-95`: `permanente: boolean` e `inicio: string | null`), logo `inicio` E' ANULAVEL e a permanente sai com `null`, ⛔ nunca com uma data fingida. 🩸 E ⛔ NENHUMA LINHA E' OMITIDA: o filtro de `inicio` nulo de `:306` ⛔ NAO se copia para ca' — era ele, com o `permanente: false`, que fazia a permanente desaparecer. A ORDEM, e e' a que o produto JA' TEM: primeiro as de instante por `inicio` ASCENDENTE (como `calendario()`), DEPOIS as permanentes por `criadoEm` DESCENDENTE com desempate por `id` ASCENDENTE (`aula.servico.ts:339`, e o desempate ⛔ nao e' zelo: duas aulas semeadas no mesmo milissegundo). ⛔ NAO SE INTERCALA e ⛔ nao se ordena por `inicio` nulo — ⛔ nao ha' instante por onde o fazer, e dar-lhe lugar na linha do tempo e' o que o §4 da regra 292 proibe. ⚠️ FAZ-SE COM DUAS LEITURAS CONCATENADAS, ⛔ nao com um `orderBy` sobre coluna anulavel: a posicao dos NULOS e' do motor do banco e ⛔ nao do nosso contrato. A FECHADURA: `@Papeis(Papel.SECRETARIA)` e ⛔ SEM `@PermitePendente()` ⟹ sem sessao 401, PENDENTE e REMOVIDO 403, coordenador/medico/especialista 403 — e e' EXACTAMENTE o que o ecra ja' declara («Só a secretaria…», `dados.ts:755-758`), ⛔ nao uma regra nova. 🩸 E A ROTA DECLARA-SE **ANTES** do `@Get(':id')`, pela cicatriz que o proprio ficheiro ja' escreve ao lado de `permanentes` (`aula.controlador.ts`): o Nest casa pela ORDEM, e declarada depois `:id = 'secretaria'` ganhava e a resposta era 404. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao toca `calendario()`, ⛔ nao toca `AulaNoCalendario`, ⛔ nao toca `GET /aulas/permanentes` (a biblioteca fica como esta' — e' leitura de outro papel), ⛔ nao mexe no `schema.prisma`, ⛔ nao escreve uma linha na base e ⛔ ⛔ NAO NASCE ECRA NENHUM AQUI",
  "escopo_paths": [
   "backend/src/modules/aula/",
   "backend/test/aula-secretaria.e2e-spec.ts"
  ],
  "aceites": [
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci",
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci -t 'com 1 permanente e 2 ao vivo na base a rota da secretaria devolve 3 linhas, e nao 2'",
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci -t 'as de instante saem primeiro por inicio crescente e a permanente sai NO FIM, nunca intercalada'",
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci -t 'duas permanentes saem por criadoEm descendente com desempate por id ascendente, e duas leituras dao a mesma ordem'",
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci -t 'cada linha traz permanente e inicio, e o inicio da permanente e nulo e nao uma data'",
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci -t 'nenhuma linha e omitida: a conta da rota bate com a conta das aulas na base'",
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci -t 'so a secretaria le: coordenador, medico e especialista levam 403'",
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci -t 'sem sessao da 401 e nao 403, porque o guarda de sessao corre antes'",
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci -t 'o medico PENDENTE leva 403 nesta rota, e continua a levar 200 com lista vazia em GET /aulas'",
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci -t 'O CALENDARIO DO MEDICO FICA IGUAL: com a mesma base que da 3 na rota da secretaria, GET /aulas devolve 2 e zero permanentes'",
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci -t 'o corpo de GET /aulas continua sem o campo permanente e com inicio sempre preenchido'",
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci -t 'GET /aulas/permanentes continua a devolver so as permanentes e com a forma de hoje'",
   "cd backend && npx jest test/aula-secretaria.e2e-spec.ts --runInBand --ci -t 'ler a rota nao escreve uma linha na base, e ler duas vezes da o mesmo corpo'",
   "cd backend && awk '/Get\\(.secretaria.\\)/{a=NR} /Get\\(.:id.\\)/{if(!b)b=NR} END{exit !(a&&b&&a<b)}' src/modules/aula/aula.controlador.ts",
   "cd backend && grep -q '@Papeis(Papel.SECRETARIA)' src/modules/aula/aula.controlador.ts && test $(grep -cE '^ *@PermitePendente\\(\\)' src/modules/aula/aula.controlador.ts) -eq 1",
   "cd backend && grep -q 'permanente: false' src/modules/aula/aula.servico.ts && test $(grep -c 'async calendario(' src/modules/aula/aula.servico.ts) -eq 1 && test $(grep -c 'async permanentes(' src/modules/aula/aula.servico.ts) -eq 1",
   "cd backend && awk '/interface AulaNoCalendario/,/^}/' src/modules/aula/aula.tipos.ts | grep -q 'inicio: Date;' && ! awk '/interface AulaNoCalendario/,/^}/' src/modules/aula/aula.tipos.ts | grep -q permanente",
   "cd backend && test $(ls prisma/migrations | wc -l) -eq 18",
   "cd backend && npm run build",
   "cd backend && npx jest test/aula.e2e-spec.ts test/permanente.e2e-spec.ts test/permanente-minutos.e2e-spec.ts test/gravacao.e2e-spec.ts --runInBand --ci"
  ],
  "depende_de": []
 },
 {
  "chave": "CS-166",
  "territorio": "frontend",
  "titulo": "A LISTA DA SECRETARIA PASSA A VER AS PERMANENTES, E GANHA A 5.ª ABA «PERMANENTES» — EM ULTIMO, DEPOIS DE «ENCERRADAS». 🩸 O QUE JA' ESTA' FEITO E ⛔ NAO SE REFAZ, medido: `AulaNaLista` ja' tem `permanente: boolean` e `inicio: string | null` (`dados.ts:93-95`); o classificador canonico do CS-91 ja' devolve `ETIQUETA_PERMANENTE` (`rotulo: 'PERMANENTE'`, `dados.ts:548-552`) quando ⛔ nao ha' instante (`etiquetaDeAula`, `:603-612`); `aulasDaAba` ja' filtra PELO ROTULO que esse classificador devolve (`:1040-1056`); e a linha ja' diz «Nao expira» no lugar do dia e hora (`pecas.tsx:288-325`). ⟹ FALTA O DADO CHEGAR E FALTA A ABA. (1) O ECRA PASSA A PEDIR A LEITURA DELA: nasce `lerAulasDaSecretaria()` sobre `GET /aulas/secretaria` (CS-165) e e' ESSA que `page.tsx:81` chama — `lerAulas()`/`ROTA_AULAS` FICAM, porque `[id]/page.tsx:246` ainda as usa e esse ecra ⛔ NAO ESTA' NESTA CERCA. (2) A ABA ENTRA EM QUINTO em `ABAS_DE_ESTADO` (`dados.ts:968-1001`) com `chave: 'permanentes'` e `rotuloDaEtiqueta: 'PERMANENTE'` ⟹ ⛔ NENHUM SEGUNDO CLASSIFICADOR NASCE (o comentario de `AbaDeEstado` ja' o proibia: «⛔ nao ha' um segundo classificador de estado neste produto, e ⛔ nao nasce aqui») e ⛔ nenhuma condicao de `permanente === true` entra em `page.tsx`. A ORDEM DA FILA E' «Todas · Agendadas · Ao vivo · Encerradas · Permanentes»: «Todas» a' cabeca pela convencao escrita do produto (`componentes/base/Chip.tsx:11`), e a nova EM ULTIMO porque as tres do meio sao uma LINHA DO TEMPO (futuro → agora → passado) e a permanente ⛔ nao esta' nela. (3) FRASE DE VAZIO PROPRIA, como as outras tres: ⛔ NAO se reaproveita `FRASE_VAZIO` (`dados.ts:760`) — essa fala da LISTA INTEIRA vazia, que e' outra coisa. (4) EM «TODAS» AS PERMANENTES SAEM NO FIM, e isso ⛔ NAO se faz aqui: vem JA' ORDENADO do servidor (CS-165) e 🩸 FILTRAR ⛔ NAO E' REORDENAR (R1.3 do CS-160) — ⛔ nenhum `sort` nasce neste ecra. (5) `?estado=permanentes` tem endereco proprio e recarregavel, e valor desconhecido continua a cair em «Todas» (`abaEscolhidaDe`, `:1013-1020`). 🩸 E AS QUATRO SPECS QUE ISTO OBRIGA A EMENDAR, MEDIDO E ⛔ NAO SUPOSTO — as e2e sao HERMETICAS e servem `**/api/v1/**` por `page.route`, logo trocar a rota do ecra PARTE-AS: `aulas.spec.ts:476` e `permanente-secretaria.spec.ts:301` casam a lista por `caminho.endsWith('/aulas')` e `/\\/aulas\\/[^/]+$/` (`:304`) apanharia `/aulas/secretaria` como DETALHE; e `alcance.spec.ts:1312` so' conhece `caminho === '/aulas'`, e esse ficheiro exige que `porSimular` acabe VAZIO. ⛔ O QUE ESTE CARD ⛔ NAO FAZ: ⛔ nao toca no classificador do CS-91, ⛔ nao toca em `componentes/base/`, ⛔ nao toca no calendario do medico nem na biblioteca `/aulas`, ⛔ ⛔ NAO RETIRA A PERMANENTE DE «TODAS» e ⛔ nao a mete em «Agendadas», «Ao vivo» ou «Encerradas»",
  "escopo_paths": [
   "frontend/src/app/secretaria/aulas/dados.ts",
   "frontend/src/app/secretaria/aulas/page.tsx",
   "frontend/src/app/secretaria/aulas/pecas.tsx",
   "frontend/e2e/aulas-permanentes.spec.ts",
   "frontend/e2e/aulas.spec.ts",
   "frontend/e2e/permanente-secretaria.spec.ts",
   "frontend/e2e/alcance.spec.ts"
  ],
  "aceites": [
   "cd frontend && npx playwright test e2e/aulas-permanentes.spec.ts --reporter=line",
   "cd frontend && npx playwright test e2e/aulas-permanentes.spec.ts -g 'a lista da secretaria pede a leitura dela e a permanente entra em Todas NO FIM a dizer Nao expira' --reporter=line",
   "cd frontend && npx playwright test e2e/aulas-permanentes.spec.ts -g 'sao cinco abas na ordem Todas Agendadas Ao vivo Encerradas Permanentes e a contagem de cada rotulo bate com as linhas que ela mostra' --reporter=line",
   "cd frontend && npx playwright test e2e/aulas-permanentes.spec.ts -g 'Permanentes mostra 1 linha e e a permanente, e Agendadas Ao vivo e Encerradas nao a mostram' --reporter=line",
   "cd frontend && npx playwright test e2e/aulas-permanentes.spec.ts -g 'a aba Permanentes sem permanentes mostra a frase dela e nao a da lista inteira vazia' --reporter=line",
   "cd frontend && npx playwright test e2e/aulas-permanentes.spec.ts -g 'recarregar estado=permanentes cai na mesma aba, e um valor desconhecido cai em Todas' --reporter=line",
   "cd frontend && npx playwright test e2e/aulas-permanentes.spec.ts -g 'O CALENDARIO DO MEDICO FICA IGUAL: pede /aulas, nunca a leitura da secretaria, e mostra as mesmas aulas' --reporter=line",
   "cd frontend && awk '/ABAS_DE_ESTADO: readonly/,/^\\];$/' src/app/secretaria/aulas/dados.ts | grep -o \"chave: '[a-z-]*'\" | tr '\\n' ' ' | grep -q \"chave: 'todas' chave: 'agendadas' chave: 'ao-vivo' chave: 'encerradas' chave: 'permanentes'\"",
   "cd frontend && grep -q \"rotuloDaEtiqueta: 'PERMANENTE'\" src/app/secretaria/aulas/dados.ts && test $(grep -c 'export function etiquetaDeAula' src/app/secretaria/aulas/dados.ts) -eq 1 && test $(grep -c 'fraseDoVazio: FRASE_VAZIO' src/app/secretaria/aulas/dados.ts) -eq 1",
   "cd frontend && grep -q 'aulas/secretaria' src/app/secretaria/aulas/dados.ts && grep -q 'lerAulasDaSecretaria' src/app/secretaria/aulas/page.tsx && grep -q 'lerAulas' src/app/secretaria/aulas/dados.ts",
   "cd frontend && ! grep -rqE 'permanente === true|\\.permanente \\?|sort\\(|reverse\\(' src/app/secretaria/aulas/page.tsx",
   "cd frontend && ! grep -rq 'aulas/secretaria' src/app/calendario/ src/app/aulas/ src/app/especialista/ src/lib/",
   "cd frontend && npx next build",
   "cd frontend && npx playwright test e2e/aulas.spec.ts e2e/permanente-secretaria.spec.ts e2e/calendario.spec.ts --reporter=line",
   "cd frontend && npx playwright test e2e/alcance.spec.ts --reporter=line",
   "cd frontend && test $(grep -cE \"'aba5-\" e2e/aulas-permanentes.spec.ts) -ge 7",
   "cd frontend && rm -f e2e/capturas/aba5-*.png && CAPTURAS=1 npx playwright test e2e/aulas-permanentes.spec.ts --reporter=line && test $(ls e2e/capturas/aba5-*.png | wc -l) -eq 7 && test $(md5sum e2e/capturas/aba5-*.png | cut -c1-32 | sort -u | wc -l) -eq 7"
  ],
  "depende_de": [
   "CS-165"
  ]
 }
]