# Task 1 — Il guscio: layout e foglio di stile — report **Stato:** completato. 5/5 test nuovi verdi, suite completa allo stato atteso (1 fallito pre-esistente e fuori perimetro), `npx tsc --noEmit` pulito. Commit fatto. **Commit:** `34c66ca` — "longevity: il guscio della piattaforma, senza semaforo sui punteggi" File aggiunti (solo questi, `git add` esplicito, nessun `-A`): - `src/layouts/Longevity.astro` - `src/styles/longevity.css` - `src/pages/longevity/index.astro` - `tests/longevity/pagine.test.ts` ## Procedura seguita (TDD) ### Step 1-2: test scritto, verificato rosso Comando: ``` npm test -- tests/longevity/pagine.test.ts ``` Esito (prima dell'implementazione): **5 falliti** — `ENOENT` su `src/layouts/Longevity.astro` e `src/styles/longevity.css` (file non esistenti), e `existsSync(.../index.astro)` a `false`. ### Step 3: implementazione - `src/layouts/Longevity.astro` — niente `import Header`/`Footer` pubblico, ``, props `title`, `crumbs`, `variante` (`'referto' | 'gestionale'`, default `'referto'`). Solo la forma `referto` è realizzata in questo task: una colonna (`.lg-shell`, `max-width: 760px`) senza navigazione, come richiesto dal brief — la barra laterale gestionale arriva col piano successivo. - `src/styles/longevity.css` — globale, prefissato `.lg`, con le variabili locali richieste: ```css --lg-tratteggio: #d8d2c8; /* il perimetro di ciò che non sappiamo */ --lg-fuori-range: #b05a4e; /* SOLO per una misura sospetta, mai per un punteggio */ ``` Nessuna variabile `--lg-ok` / `--lg-buono` / `--lg-verde`: l'intensità di un punteggio è affidata a `--lg-intensita` (0..1), consumata come `opacity` su `.lg-score__bar-fill` sopra un unico colore d'accento (`var(--c-accent)`), non a un colore diverso per fascia. - `src/pages/longevity/index.astro` — nessun indice, solo `Astro.redirect('/longevity/io')` (la rotta `/longevity/io` arriva col Task 3; per ora la protezione è già del middleware esistente su `isProtectedPath`/`canAccessAdminPath`, nessuna modifica ad `auth.ts` necessaria: le regole per `/longevity` ci sono già). ### Step 4: test target verde Comando: ``` npm test -- tests/longevity/pagine.test.ts ``` Output: ``` Test Files 1 passed (1) Tests 5 passed (5) ``` ### Step 5: suite completa + typecheck Comando: ``` npm test ``` Output (coda): ``` ❯ tests/modifiche-agosto.test.ts (25 tests | 1 failed) 72ms × l'inaugurazione dice la data e che il programma manca ancora 8ms FAIL tests/modifiche-agosto.test.ts > promo ed eventi > l'inaugurazione dice la data e che il programma manca ancora AssertionError: expected 'Inaugurazione' to contain '19 settembre 2026' Test Files 1 failed | 37 passed (38) Tests 1 failed | 313 passed (314) ``` Esattamente il rosso pre-esistente dichiarato nel brief (fuori perimetro, non toccato) — nessun altro test rotto, i 5 nuovi inclusi nel verde. Comando: ``` npx tsc --noEmit ``` Output: nessuno (exit pulito). ### Step 6: commit ``` git status --porcelain # solo i 4 file nuovi, nessun altro modificato git add src/layouts/Longevity.astro src/styles/longevity.css src/pages/longevity/index.astro tests/longevity/pagine.test.ts git commit -m "longevity: il guscio della piattaforma, senza semaforo sui punteggi" ``` ``` [feat/longevity 34c66ca] longevity: il guscio della piattaforma, senza semaforo sui punteggi 4 files changed, 176 insertions(+) ``` `git status` dopo il commit: albero pulito. ## Dubbi / note per chi esegue il Task 2/3 - `src/pages/longevity/index.astro` reindirizza a `/longevity/io`, che non esiste ancora (arriva col Task 3): finché il Task 3 non è fatto, visitare `/longevity/` produce un redirect verso una rotta 404. È il comportamento descritto dal brief, non un difetto di questo task. - La variante `gestionale` è dichiarata nel tipo `Props` di `Longevity.astro` (con `data-variante` sul `` per un eventuale hook CSS futuro) ma il corpo del layout renderizza solo la forma a colonna: nessuna barra laterale è stata costruita, come da perimetro del task ("questo task realizza la prima; la seconda arriva col piano del gestionale"). - Non ho toccato `src/lib/auth.ts`: le regole per `/longevity` (incluso il ramo `/longevity/gestionale` per il ruolo `trainer`) risultavano già presenti in `RULES` e `isProtectedPath`, presumibilmente da un piano precedente (strato dati). Segnalo per conferma, nel caso non fosse atteso. --- ## Rinforzo dopo revisione (2026-08-22) **Stato:** completato. Commit `2ea822a` sopra a `34c66ca`. Tre correzioni chieste dal coordinatore, tutte in `tests/longevity/pagine.test.ts` (unico file toccato, nessuna modifica a layout/CSS/pagina): 1. **Test anti-semaforo reso strutturale.** Il vecchio test cercava tre nomi vietati nel CSS — un colore scritto direttamente (esadecimale) o una variabile con un altro nome lo aggiravano. Il nuovo test (`nelle regole di un punteggio compaiono solo i colori ammessi...`) fa il contrario: prende ogni regola CSS il cui selettore contiene `lg-score`, estrae ogni dichiarazione su una proprietà-colore (`color`, `background`, `border-*-color`, `outline-color`, `fill`, `stroke`), e verifica che il valore sia `var(--nome)` con `--nome` in un allowlist esplicito (l'accento del sito, il tratteggio, il fuori range, più i token neutri di testo/sfondo già in uso). Qualunque letterale (hex, `rgb()`, nome CSS) o `var()` fuori allowlist è una violazione raccolta in un array che il test pretende vuoto. Il vecchio test sui nomi vietati è rimasto come controllo separato (cattura anche un token dichiarato ma mai usato, es. `--lg-verde-scuro: ...;` non referenziato in nessuna regola). 2. **Test sulla rotta rinforzato.** Prima verificava solo `existsSync`. Ora legge il file e controlla che contenga `Astro.redirect('/longevity/io')` con una regex sul contenuto, non solo sull'esistenza. 3. **Prefisso classi, un carattere.** `c.startsWith('lg')` accettava anche `lgfoo` (senza trattino). Cambiato in `c === 'lg' || c.startsWith('lg-')`. ### Prova richiesta: il test nuovo diventa rosso davvero Backup del CSS reale, poi due regressioni iniettate una alla volta (gli esempi dati dal coordinatore), test rilanciato, poi ripristino e riverifica verde. **Regressione 1 — verde esadecimale su una classe di punteggio**, aggiunta in coda al foglio: `.lg-score--alto { color: #6f8f6a; }`. Comando: `npm test -- tests/longevity/pagine.test.ts`. Output (estratto): tests/longevity/pagine.test.ts (6 tests | 1 failed) x nelle regole di un punteggio compaiono solo i colori ammessi: l'accento, il tratteggio, il fuori range AssertionError: expected [ Array(1) ] to deeply equal [] + ".lg-score--alto { color: #6f8f6a }" Test Files 1 failed (1) Tests 1 failed | 5 passed (6) **Rosso, come atteso.** (La stringa riportata include anche il commento sulla riga precedente perché il parser del test cattura tutto ciò che precede la graffa aperta — cosmetico, non inficia la rilevazione.) **Regressione 2 — variabile con nome innocuo**: `.lg-score--alto { color: var(--lg-buona-salute); }`. Stesso comando. Output: `Tests 1 failed | 5 passed (6)` — **rosso**, stesso test. **Ripristino** dal backup fatto prima delle due prove, poi verifica che il file torni identico all'HEAD già committato (`git diff --stat` senza output) e che il test torni verde: Test Files 1 passed (1) Tests 6 passed (6) ### Verifiche finali `npm test -- tests/longevity/pagine.test.ts` → 6/6 verdi. `npm test` → `Test Files 1 failed | 37 passed (38)`, `Tests 1 failed | 314 passed (315)`; il fallito è sempre e solo `tests/modifiche-agosto.test.ts > ... inaugurazione ...` (pre-esistente, fuori perimetro, non toccato). `npx tsc --noEmit` → nessun output, pulito. ### Commit `git status --porcelain` prima di committare mostrava solo `tests/longevity/pagine.test.ts` modificato. git add tests/longevity/pagine.test.ts git commit -m "longevity: test anti-semaforo strutturale (colori ammessi, non nomi vietati) e rotta verificata sul contenuto" Risultato: [feat/longevity 2ea822a] longevity: test anti-semaforo strutturale (colori ammessi, non nomi vietati) e rotta verificata sul contenuto 1 file changed, 44 insertions(+), 4 deletions(-)