Sole identity — backlog di follow-up (post PR #144)
Stato: 2026-06-02. Origine: sessione "Qualità di TUTTI i system prompt". Identità del Sole validata (
ops/sole-identity-2026-06-02.md) e implementata (buildSoleIdentity). Questo doc è il brief autorevole per la sessione fresca: tutto ciò che NON è entrato in PR #144, rankizzato, con scope + file + acceptance criteria. Decisione founder: i 4 workstream sotto sono tutti in scope; questa sessione ha chiuso il P0; il resto si esegue da qui.
Già fatto (PR #144 · NON ri-fare)
- SSoT
frontend/multiverbe-app/api/_lib/sole-identity.ts(buildSoleIdentity· voce "noi" · language-aware it/de/fr/en + fallback mondo · role-aware · per-settore viaai_brain_seed· 3 surface cockpit/outbound/content). Port edge Denosupabase/functions/_shared/sole-identity.ts. - Tutti i system prompt sopra l'identità:
analyze-planet-data,sole-crm-suggestions(fallback localizzati it/de/fr/en),sector-deduction(22 settori, language-aware),generate-outreach(Mistral),generate-text(Gemini), site-buildersystem-prompt, edgecontext-builder(routing Gemini/Groq invariato). - Onboarding popola
entity_profile+ settaworkspaces.primary_languagedalla lingua UI. - Overlay reso reale: il cockpit ora rende
goals→ priorità localizzate +personality→ tono (prima erano caricati ma inutilizzati). Guardrail test surface×locale. - Loop personalità chiuso (commit
db901e9): l'onboarding (Step3) cattura il tono →personality.tone_key;buildSoleIdentitylo rende localizzato (it/de/fr/en) su tutte le surface. → item 1.1 + 1.2 sotto sono FATTI. - Contract-test matrix (commit
34b1ed9): guard 5 lingue × 3 surface + ruoli + overlay + litmus "freelance in Svezia" (zero residui IT/CH/PMI), eseguita localmente verde → parte statica del workstream 2.1 FATTA (resta solo l'LLM-judge, gated API key).
📌 Stato repo 2026-06-03 (per la sessione fresca)
- #142 (memoria +
sole-ask) È MERGIATA in master (80b76ef), insieme a #140 Content, #141 Sales Boss-View, #143. Quindiapi/_lib/memory.ts·pii.ts·memory-embed.ts·api/ai/sole-ask.ts·_inngest/functions/memory-sync.tssono su master → cablaresole-askabuildSoleIdentitynon è più bloccato. - PR #144 (questa: SSoT identità) ora CONFLITTA con master su 2 soli file:
api/content/generate-text.ts(toccato anche da #140 Content) evitest.config.ts(io e #142 abbiamo aggiunto lo stesso includeapi/**→ merge banale). → rebase piccolo prima del merge. - Nuove direttive founder 2026-06-03 (vedi prompt sessione fresca): pianeti dinamici per tier+settore (no "hai 4 pianeti" hardcoded), revisione tassonomia settori/artisti freelance, chat proattiva a card (2 opzioni o 1 risposta), proattività bounded/token-efficient.
🆕 Direttive founder 2026-06-03 → sessione fresca (T1-T4)
✅ T1-T4 ESEGUITI 2026-06-04 — PR #174 (3 commit atomici + fix CI lint/test). Modello pianeti a due assi (accesso=tier, salienza=settore · resolver
api/_lib/workspace-planets.ts), tassonomia "Creativi & Artisti" (6 macro / 28 settori · migration2026-06-04a),sole-asksubuildSoleIdentity+ card proattive (componenteSoleChatin HomePage), proattività bounded. Record completo:sole-v2-pianeti-tassonomia-2026-06-04.md. Residui non bloccanti: foregrounding salient/dormant nella Home, QA madrelingua de/fr sulle nuove label, eval LLM-judge sulle card.
Dettaglio operativo nel prompt di kickoff (chat 2026-06-03). Sintesi durevole:
- T1 · Pianeti DINAMICI per tier+settore (IMPORTANTISSIMO): no "hai 4 pianeti" hardcoded (
analyze-planet-data.tsPLANET_KEYS+ procedura). Creare SSoTresolveWorkspacePlanets({tier, sectorId, activeModules})(canon 02/03/11 · fonti:subscriptions.plan_tierviatier-caps.ts,workspaces.active_modules,sectors) → usarlo inbuildSoleIdentity+analyze-planet-data+ ogni "hai X pianeti". - T2 · Tassonomia settori/artisti freelance + ruoli: macro creativa rivista (designer, produttore musicale, cantante, studio di registrazione…), togliere il taglio "solo fotografo/eventi", ampliare per il mondo business. Tocca
sectors(DB additivo · CHIEDI se destructive),sectors-fallback.ts,sector-deduction.ts, canon 11. Proporre la tassonomia al founder PRIMA. - T3 · Chat proattiva a CARD (FONDAMENTALE):
sole-ask(prima portarlo subuildSoleIdentity· è ancora hardcoded "PMI svizzere/titolare/amica esperta") ritornasuggestionsstrutturati: 2 opzioni o 1 risposta personalizzata, rese come card al posto della tastiera. Frontend chat semplice. - T4 · Proattività bounded + token-efficient: ≤2-3 suggerimenti, concisi,
maxTokensstretti, niente over-suggesting.
✅ RISOLTO — la CI ora gira su #144 (era un conflitto, non un setting)
- Causa reale: PR #144 era in CONFLITTO → GitHub non poteva creare il merge-commit di test → i workflow
pull_requestnon partivano (le Actions sono attive:enabled: all, girano sulle altre PR). - Fix applicato (sessione 2026-06-03): mergiato master nel branch + risolti 2 conflitti (
generate-textauth #140 + identità ·vitest.config) + chiuso il gate lint (helperpick()sui lookup i18n, senza alzare il cap) + import test senza.ts. → Frontend gate PASS (lint+vitest+build),mergeStateStatusCLEAN, MERGEABLE. - Lezione: PR con solo check Vercel e nessun Actions = quasi sempre un conflitto. Risolvi il conflitto, non le impostazioni.
🔴 Workstream 1 — Overlay + onboarding (residuo dopo il fix)
1.1 ✅ FATTO (commit db901e9) — Onboarding cattura il tono
- Perché: oggi l'overlay rende il tono solo se
entity_profile.personalityè popolato, ma l'onboarding non lo chiede → resta vuoto. Il render è forward-compatible: appena l'onboarding scrive il tono, il Sole lo usa. - Scope: micro-step (o campo nello Step3) con 3-4 opzioni di registro (es. diretto / caloroso / professionale / informale) oppure una frase libera breve. Salvare in
entity_profile.personality = { tone: <valore> }. - File:
src/components/onboarding/Step3Workspace.tsx(+types.ts),SetupWizardV2.tsx(handleStep3Complete+handleFinalComplete),src/lib/entity-profile.ts(aggiungere parampersonality). - Acceptance: nuovo onboarding scrive
personality.tone; il cockpit mostra "Il nostro tono: …" nella lingua impostata. Test onboarding aggiornato. - Effort: ~0.5g. Nota UX: decidere opzioni + copy (design, non bolt-on).
1.2 ✅ FATTO (commit db901e9) — Tono su content + outbound
- Perché: la voce dell'azienda (tono) conta anche quando il Sole scrive contenuti/outreach, non solo nel cockpit.
- File:
api/_lib/sole-identity.ts(renderepersonality/tono anche per surface content+outbound). - Acceptance: content/outbound includono il tono quando presente; test esteso. Effort: ~1h.
1.3 Scala di maturità (bloccata su decisione founder) · P2/P3
- Stato: il founder sta passando da
nucleare/solare/galattico/cosmicoa un modello stellaredwarf/subgiant/giant/supergiant/hypergiant. IlCHECKdel DB è ancora sui valori vecchi;entity-profile.tsper ora NON scrivematurity_level(NULL). - Scope (dopo lock founder): migration additiva del
CHECKsuentity_profile.maturity_level(ALTER → CHIEDERE al founder); default a onboarding = livello più basso; render della maturità nell'overlay cockpit. - Acceptance: onboarding scrive il livello iniziale; il Sole può citare la fase dell'azienda. Dep: scala fissata dal founder.
🟠 Workstream 2 — Eval + localizzazione pro
2.1 Eval harness sull'output REALE del modello · P2 (il vero "big-tech")
- ✅ Parte statica FATTA (commit
34b1ed9): contract-test matrix sul prompt assemblato (settore×lingua×surface×ruolo×overlay + litmus Svezia). Resta sotto solo l'eval sull'output del modello (LLM-judge), che costa API. - Perché: il contract-test verifica il prompt; l'LLM-judge verifica cosa il Sole produce. "Qualità assoluta" va misurata su entrambi.
- Scope: fixtures (settore × locale × surface) → chiamata modello → giudice-LLM su: lingua corretta, zero slop/em-dash, voce "noi", nessun numero inventato, registro di settore. Scorecard + soglia.
- File: nuovo
scripts/eval-sole-prompts.tsoapi/_lib/__eval/(gated, NON in CI di default: costa API). - Dep:
ANTHROPIC_API_KEY. Acceptance: eval runnabile che produce una scorecard per settore×locale con pass/fail. Effort: 1-2g. Nota: decidere cadenza (manuale pre-release vs nightly).
2.2 Catalogo i18n UNICO Node + edge · P2
- Perché: la prosa localizzata è scritta a mano nel modulo Node e RI-scritta nel port Deno (doppia manutenzione). Aggiungere una lingua = editare 2 posti.
- Scope: estrarre tutta la prosa localizzata (pack identità, template fallback CRM, pain-labels, role-labels) in un JSON condiviso (es.
api/_lib/sole-i18n.json) importato sia da Node sia da Deno (entrambi possono importare JSON). - File:
api/_lib/sole-identity.ts,supabase/functions/_shared/sole-identity.ts, nuovo JSON,sole-crm-suggestions.ts(catalogo CRM),analyze-planet-data.ts(catalogo rule-based). - Acceptance: una sola fonte; aggiungere una lingua = editare il JSON; Node ed edge leggono gli stessi dati; test verdi. Effort: ~1g. Rischio: regressione → farlo DOPO 2.1 (l'eval cattura il drift).
2.3 QA madrelingua de/fr · P2 (pre-clienti non-IT)
- Scope: revisione madrelingua di tutta la prosa de/fr (identità, template, label). Dep: persona madrelingua. Acceptance: sign-off. Nota: bloccante prima di esporre il prodotto a clienti DE/FR.
2.4 Humanizer su tutta la copy utente · P1 (rapido)
- Scope: passare
anthropic-skills:humanizersu tutta la copy che l'utente legge (template fallbacksole-crm-suggestions+analyze-planet-datait/de/fr/en + titoli suggerimenti). Regola progettofeedback_humanizer_always_on_text. - Acceptance: copy humanizer-clean. Effort: ~2h.
🟡 Workstream 3 — Igiene dati + compliance + perf
3.1 Un solo locale canonico · P2
- Problema: 3 colonne locale (
workspaces.primary_language,workspaces.language,entity_profile.language).buildSoleIdentityfa coalesce, ma è drift-prone. - Scope: canonico =
workspaces.primary_language; deprecare le altre (derivate o droppate). Migration (ALTER → CHIEDERE). Acceptance: una sola fonte di verità per la lingua. Effort: 0.5g + migration.
3.2 Dedup campi identità · P2
- Problema: nome/settore/paese duplicati in
workspacesEentity_profile. - Scope:
entity_profiletiene SOLO l'overlay (goals/personality/maturity); nome/settore/paese si leggono daworkspaces. Aggiornareentity-profile.ts(non scrivere i duplicati) +loadSoleIdentity(già workspace-first). Acceptance: nessuna duplicazione scritta; identità invariata. Effort: 0.5g.
3.3 Compliance · nome operatore → Anthropic (US) · P1 (responsabilità penale CHF 250k)
- Problema: il nome di battesimo dell'operatore viene inviato ad Anthropic (US, fuori EU Data Boundary) e NON è documentato in privacy/DPA/sub-processor.
- Scope: aggiungere in
docs/legal/privacy-policy.md,docs/legal/dpa-template.md,docs/legal/sub-processors-list.mdla menzione esplicita: "il nome di battesimo dell'utente operatore è trattato da Anthropic (sub-processor, US) per personalizzare le risposte del Sole; i dati dei clienti/contatti restano pseudonimizzati". Dep: review fiduciario (PTEK). Acceptance: i 3 doc lo riportano. Effort: ~2h + review. - Testo pronto (IT): «Per rivolgersi all'utente per nome, Multiverbe trasmette ad Anthropic (sub-processor con sede negli Stati Uniti) il solo nome di battesimo dell'utente che opera il prodotto. Nessun cognome, e-mail o dato di clienti/contatti terzi viene trasmesso in chiaro: questi ultimi sono sempre pseudonimizzati prima dell'invio a qualunque modello.»
3.4 Perf · cache degli identity load · P2
- Problema: ogni chiamata agente fa +query (
entity_profile+sectors+team_members+ admin-lookup nome); nel cron fan-out è per-workspace. - Scope: memoizzare
loadSoleIdentityper(workspaceId,userId)nell'arco di una richiesta/processo. Acceptance: nessun doppio load nella stessa richiesta. Effort: ~2h.
🔵 Workstream 4 — sole-ask + consolidamento cervelli
4.1 sole-ask sull'identità (dopo merge PR #142) · P1, dep esterna
- Scope: in
api/ai/sole-ask.tssostituireSYSTEM_PROMPT_BASEconbuildSoleIdentity({ workspaceId, userId, operatorFirstName })(il first name si estrae dagetUser→user_metadata), mantenendo le sezioni dati (memoria/pianeti/oggi).recallMemoriesè già presente. - Dep: PR #142 merged. Acceptance:
sole-askparla con l'identità, nella lingua del workspace, si rivolge all'operatore per nome. Effort: ~1h. Swap di ~2 righe.
4.2 Consolidamento cervelli edge → Anthropic + memoria · P3 (post-gate)
- Problema: l'edge ai-copilot ha ora la VOCE giusta ma gira su Gemini/Groq + tabelle legacy (
brand_intelligence/dashboard_config/ai_goals), mentre l'api Sole gira su Anthropic +entity_memory. Due cervelli con conoscenza diversa sotto lo stesso volto. - Scope: migrare le edge function
ai-copilot-*sul routing canonico (llm-client/agent-core) +entity_memory, validando la parità (piano inops/proposta-consolidamento-cervelli-2026-05-30.md). Effort: multi-giorno. Esplicitamente post-gate.
Note operative
- CI:
frontend-ci(vitest + lint) NON è partita sulla PR #144 (anomalia GitHub Actions · zero run sul branch, mentre PR sorelle l'hanno avuta). Il gate equivalentetsc && vite buildè verde via Vercel. Verificare/ri-innescare prima del merge. - Voce "noi" + "tu Marco": il Sole parla come l'azienda ("abbiamo") e si rivolge a Marco che fa parte dell'azienda. Validare con un test UX reale; rifinire se suona straniante.
- 5 workspace reali: non hanno
entity_profilee restanoprimary_language='it'→ beneficiano solo ri-onboardando. Backfill a basso valore (account di test founder).
Sequenza consigliata verso il gate 22 Giu
- P1 rapidi: 2.4 humanizer · 3.3 compliance (carta) · 1.1 onboarding tono · 4.1 sole-ask (appena #142 è merged).
- P2 qualità: 2.1 eval harness → 2.2 catalogo i18n → 1.2 tono content/outbound → 3.4 perf.
- P2 dati: 3.1 locale canonico · 3.2 dedup (insieme, una migration).
- Post-gate: 2.3 QA madrelingua de/fr (pre-clienti non-IT) · 1.3 maturità (dopo lock scala) · 4.2 consolidamento cervelli.