name: pianeta-web-moat-extension description: Estensione del MOAT del Pianeta Web oltre il ristorante. Ricognizione reale (codice + DB prod), critical path corretto, piano PR atomiche P0-P3. Il sito generato e il prodotto, la qualita e il moat. last_update: 2026-06-05 owner: gregorio + claude status: P0 in esecuzione (sequenza raccomandata confermata dal founder 2026-06-05)

Pianeta Web · Estensione del MOAT oltre il ristorante

SSoT della decisione "come ogni sito generato diventa il migliore del suo settore". Correlati: skill multiverbe-sector-onboarding + multiverbe-design-system · pianeta-web-compliance-2026-06-03.md (layer legale, gia in prod) · codice frontend/multiverbe-app/src/lib/site-design/ + sites-runtime/.

0. TL;DR

Una review adversariale aveva indicato il gap #1: "esiste una sola costituzione di design (restaurant)". La ricognizione reale su codice + DB di produzione ha trovato due buchi piu profondi:

  1. In produzione il generatore non produce NESSUN sito. Le uniche 2 righe in site_constitutions (restaurant, hair-salon) sono letteralmente {"placeholder": true, "pending_review": true} e active=false. La gold-standard restaurant.ts (1640 righe) vive nel codice ma non e mai stata seedata in prod (migration 2026-05-15g non applicata). Il worker richiede active=true -> oggi ogni generazione muore con constitution_not_found.
  2. Il contratto section_type e fratturato tra le due app. La pipeline persiste nomi lunghi (menu-showcase, booking-widget, contact-location, social-proof, about-story, private-events); la sites-runtime (renderer + schema.org SEO) si aspetta nomi corti (menu, booking, contact). Nessun mapping in mezzo. Anche seedando il ristorante, oggi renderizzerebbe solo hero + gallery; tutto il resto -> return null silenzioso. Mai emerso perche un sito reale non e mai stato renderizzato.

Conseguenza strategica: "costituzioni prima" e l'ordine sbagliato. Una costituzione e dati inerti finche le sue sezioni non hanno schema Zod + prompt builder (app generatore) e un componente React (sites-runtime). Prima il contratto + la section library (codice), poi le costituzioni (dati).

1. Architettura attuale (data vs codice)

Tre strati che devono parlarsi, su due app separate (frontend/multiverbe-app Vite + sites-runtime Next.js 16):

Strato Dove Natura
Costituzione di settore site_constitutions (jsonb DB), autorata in TS src/lib/site-design/constitutions/*.ts DATI
Orchestratore 6-stage src/lib/site-design/ai-pipeline/orchestrator.ts + Zod prompts/output-schemas/* + prompt prompts/by-section/* CODICE
Section Library (render) sites-runtime/components/sections/index.tsx + lib/seo/structured-data.ts CODICE

Pipeline: Stage 1 Brand Strategist -> 2 Art Director (sceglie sezioni+variant per pagina) -> 3 Copywriter (per sezione x locale, Kimi+QA Sonnet) -> 4 Visual Director (immagini) -> 5 CRO Auditor -> 6 Senior Reviewer (gate >=85, max 3 retry). Checkpoint su ai_generation_jobs. Cost-cap tier-aware. Il tipo SectorConstitutionEnriched (types.ts) e gia ricchissimo: multi-pagina, multi-locale (it/de/fr/en), moodSpecs, designDirectorBriefing, sectionRecipeEnriched (micro-interazioni + a11y + graceful degradation), localCROAdjustments CH, performance budget per device, A/B presets, seasonal rules.

Famiglie di sezione implementate oggi nella runtime: hero, menu, booking, gallery, contact, legal (6). Schemi+prompt nella pipeline: hero, menu, booking, gallery, social-proof, contact-location, about-story, private-events (8 — ma social-proof/about-story/private-events NON hanno renderer). I variantId combaciano gia tra le due app (es. menu-scroll-spy, contact-map-side): e solo la chiave-famiglia ad essere disallineata.

2. Critical path corretto · piano PR atomiche

P0 — Fondamenta: 1 settore vivo end-to-end (in corso)

  • PR1 — Riconciliazione contratto section_type (root-cause). SSoT unica family-resolver in sites-runtime, consumata da index.tsx (renderer) + structured-data.ts (SEO). Accetta i nomi canonici lunghi effettivamente persistiti. Esito: menu/booking/contact tornano a renderizzare. Test. CI verde.
  • PR2 — 3 renderer mancanti (social-proof, about-story, private-events): solo i componenti React (schema+prompt esistono gia). Osservatorio tokens, a11y AA, prefers-reduced-motion, i18n-ready, tabular-nums. Esito: il ristorante renderizza tutte le 8 famiglie del suo recipe.
  • PR3 — Seed + attiva la gold-standard restaurant. Rigenera la migration da restaurant.ts, applica a prod. L'attivazione (active=true) e una scrittura su DB prod -> conferma founder (postura prodotto, reversibile = due costanti come i flag legali).
  • VERIFY adversariale: un sito ristorante reale renderizza tutte le sezioni, schema.org corretto, a11y AA, mobile, 4 lingue. Bar "agenzia $5-15k vs template".

P1 — Section library sector-neutral (il vero codice del moat)

Vertical slice completi (Zod schema upstream + prompt builder + content-type mirror runtime + componente + a11y AA/i18n/reduced-motion), 1 PR ciascuno:

  • services-pricing — lista servizi + prezzo (il #1 per parrucchiere/gym/studio pro).
  • team — stylist / trainer / professionisti (foto, ruolo, bio breve).
  • testimonials — recensioni clienti (distinto dal social-proof Google-live; riusa dove possibile).
  • faq — domande frequenti (accordion accessibile + schema.org FAQPage).
  • booking adattivo — oggi il booking ha coperti/party cablati al ristorante; serve un adattatore per modalita tavolo / appuntamento / corso-trial.

P2 — Costituzioni nuove (dati, sul gold-standard)

hair-salon (gia riga stub) -> gym -> studio-professionale. Ognuna SectorConstitutionEnriched modellata su restaurant.ts, seedata + attivata. Verifica adversariale per ciascuna.

P3 — Scoping onboarding

Finche un settore non ha costituzione viva, l'onboarding instrada solo ai settori pronti, con stato onesto "in arrivo" — niente 404, niente ristorante-forzato. Mappa i 28 settori (6 macro, skill onboarding) -> disponibilita costituzione.

3. Tensione col gate (onesta)

Il gate del 15 Giu ha come collo di bottiglia le vendite (0/5 paganti) + l'entita Sagl, non il prodotto. Questo lavoro non sblocca i 5 paganti. Vale la pena ORA solo se il Pianeta Web e parte della demo ("ti generiamo il sito"): in quel caso il fatto che oggi generi zero siti e un buco da chiudere. Decisione founder 2026-06-05: procedere con la sequenza raccomandata, P0 first (artefatto demo-abile il piu presto possibile).

4. Vincoli tecnici (hard)

  • Due app. frontend/multiverbe-app/api/ e ESM NodeNext -> import relativi con .js esplicito (guard scripts/check-api-esm-imports.mjs). sites-runtime = Next.js 16, package separato che mirrora a mano i tipi degli Zod output-schema (non importa la pipeline).
  • Toolchain locale Windows rotta (pnpm/tsc/vitest): la verita e la CI Linux (push feat/** -> frontend-ci.yml) + Vercel build (sites-runtime). Codice verde al primo giro.
  • DB Supabase yqhixdqipojvgzfadufo eu-central-1, RLS, workspace_id. Schema prod -> chiedi. PII pseudonimizzata prima di Anthropic.
  • Semgrep ERROR+WARNING bloccante. PR atomiche su branch feat/**, merge --squash --admin solo dopo CI verde.

5. Stato esecuzione

P0 codice completo e in master (2026-06-05, 3 PR atomiche, CI sites-runtime verde):

  • [x] PR1 contratto section_type (SSoT sectionFamily) — MERGED #218
  • [x] PR2 3 renderer (social-proof / about / events) — MERGED #220
  • [x] PR3 seed restaurant rigenerato (era stale vs Stream 4) — MERGED #223
  • [ ] APPLY seed in prod + active=trueazione founder (Dashboard SQL editor: incolla database/migrations/2026-05-15g_seed_restaurant_constitution.sql, 66KB; pattern stabilito = Dashboard, non MCP). È il go-live del generatore: da "0 siti producibili" a "ristorante reale generabile".
  • [ ] VERIFY ristorante end-to-end (dopo l'apply: generazione reale o sito demo seedato → confermare che tutte le 8 famiglie renderizzano)
  • [ ] P1 section library (services-pricing, team, testimonials, faq, booking adattivo)
  • [ ] P2 costituzioni (hair-salon, gym, studio-professionale)
  • [ ] P3 onboarding scoping

Nota CI: il check types/supabase.ts ↔ prod schema e ROSSO pre-esistente (drift dei tipi dopo le RPC Booking, non legato a questo lavoro). Le 3 PR sono state mergiate via --admin. Fix alla radice (rigen via Supabase CLI) tracciato nel prompt di handoff step 5 "leave nothing behind"; il chip standalone e stato chiuso per non far partire una sessione doppia.

Handoff 2026-06-05: founder delega a una sessione autonoma successiva il GO-LIVE (apply seed, anche da browser) + P1-P3 + hardening/test finale. Prompt pronto: pianeta-web-handoff-2026-06-05.md.


Nota: ricognizione 2026-06-05 su codice reale + query DB prod (site_constitutions = 2 stub inattivi). Non e una stima: e lo stato verificato.