Il problema
Marco, sviluppatore backend in un team remoto di 5 persone, si convince nel tempo che le sue proposte tecniche vengano sistematicamente ignorate nelle discussioni sul canale di team.
La sensazione è precisa: quando propone qualcosa — una libreria, un approccio architetturale, una modifica al workflow — la conversazione continua come se non avesse scritto nulla. Quando lo fa Giulia (la tech lead) o Dario (il senior più prolisso del team), la risposta arriva in pochi minuti.
Marco ne parla con una collega di fiducia. La collega dice: "Sicuro che non sia una tua impressione?" Marco: "Sicurissimo. Ti mando i messaggi dove si vede."
Ma invece di raccogliere esempi selettivi, decidono di analizzare l'intera chat.
L'analisi
Il team usa WhatsApp per le comunicazioni rapide. Marco esporta la chat: 18 mesi di conversazioni, ~15.000 messaggi.
WhatsApp esporta in formato .txt con struttura GG/MM/AA, HH:MM - Mittente: Testo. Un parser regex standard estrae ogni messaggio con timestamp e autore.
import re
from datetime import datetime
pattern = re.compile(r'^(\d{2}/\d{2}/\d{2}, \d{2}:\d{2}) - ([^:]+): (.+)$')
messages = []
with open("chat.txt", "r", encoding="utf-8") as f:
for line in f:
m = pattern.match(line.strip())
if m:
ts_str, sender, text = m.groups()
ts = datetime.strptime(ts_str, "%d/%m/%y, %H:%M")
messages.append({"ts": ts, "sender": sender, "text": text})
Metrica 1 — Topic-starter rate: quando qualcuno rompe il silenzio (gap >30 min dal suo ultimo messaggio) e apre un nuovo filone, quanto spesso viene raccolto entro 60 minuti? Filtra i messaggi "di risposta" e isola le iniziative genuine.
Questo metodo ha però un limite fondamentale: conta come "risposta" qualsiasi messaggio successivo, anche se qualcun altro ha nel frattempo cambiato argomento. Se Marco scrive "guardate questo link" e poi Luca dice "raga, ho comprato una macchina nuova" e tutti rispondono a Luca — il sistema contava la risposta di Luca come risposta a Marco.
Metrica 2 — Word overlap (più accurata): per ogni messaggio di apertura topic, si analizza il primo messaggio di risposta e si verifica se condivide parole significative col messaggio originale. Se l'overlap è zero, il primo a rispondere ha cambiato argomento — bypass. Se c'è overlap, stava rispondendo al topic originale.
STOPWORDS = {'e', 'è', 'la', 'il', 'ok', 'dai', 'raga', 'ma', 'che', ...}
def get_keywords(text, min_len=3):
words = re.findall(r'[a-zA-ZàèéìíîòóùúÀÈ]+', text.lower())
return {w for w in words if len(w) >= min_len and w not in STOPWORDS}
def topic_overlap(text_a, text_b):
kw_a = get_keywords(text_a)
kw_b = get_keywords(text_b)
if not kw_a:
return 0
return len(kw_a & kw_b)
# Per ogni topic-starter di X:
# - trova il primo messaggio non-X entro 60 min
# - se overlap > 0 → risposta diretta
# - se overlap = 0 e X aveva keywords → bypass (cambio topic)
Risultati — Metrica 1 (topic-starter rate)
| Persona | Topic avviati | Risposta entro 60 min | % |
|---|---|---|---|
| Giulia (tech lead) | ~800 | ~704 | 88% |
| Sara (PM) | ~420 | ~357 | 85% |
| Dario (senior) | ~760 | ~631 | 83% |
| Luca (junior) | ~280 | ~227 | 81% |
| Marco | ~700 | ~574 | 82% |
Marco è sostanzialmente identico agli altri. Ma questo include il caso "Luca risponde di macchine mentre Marco parlava di link".
Risultati — Metrica 2 (word overlap)
| Persona | Risposta diretta | Bypass (cambio topic) | Ignorato |
|---|---|---|---|
| Giulia (tech lead) | 22% | 57% | 21% |
| Sara (PM) | 19% | 63% | 18% |
| Dario (senior) | 17% | 64% | 19% |
| Luca (junior) | 16% | 68% | 16% |
| Marco | 24% | 55% | 21% |
Il bypass rate alto per tutti (55–68%) riflette la natura delle chat di gruppo: le conversazioni si sovrappongono costantemente. La colonna rilevante è quella relativa tra i membri. Marco ha il miglior direct reply rate e il minor bypass rate del team.
Diagnosi
Il bias di conferma funziona così: si nota e si memorizza ogni caso in cui si viene ignorati o scavalcati. Non si nota quando si riceve risposta, perché è la norma — non fa notizia. Nel tempo, i casi salienti (bypass, silenzio) sovrastimano la frequenza reale.
Con entrambe le metodologie — la semplice e quella che tiene conto del cambio topic — Marco risulta trattato come tutti gli altri. Anzi leggermente meglio. Il problema percepito non è nella chat, è nel modo in cui il cervello seleziona i ricordi.
Applicazioni pratiche
- Verificare se un membro del team si sta disconnettendo (response rate in calo nel tempo)
- Identificare chi guida realmente le conversazioni (topic-starter rate alto) vs chi segue
- Misurare l'engagement in un gruppo cliente o community
- Analizzare la distribuzione del carico comunicativo in un team remoto
Dati necessari: solo l'export .txt di WhatsApp (o .json di Slack). Zero API, zero infrastruttura. Un file Python di ~100 righe.
Limitazioni
- Non cattura le reazioni emoji (proxy parziale di "ack")
- I messaggi vocali appaiono come
<Media omessi>— non analizzabili - Il response rate è approssimato (nessun thread vero in WhatsApp)
Dare un numero a una percezione la trasforma da conflitto interpersonale a dato analizzabile. In questo caso il dato ha rassicurato Marco e chiuso una ruminazione che stava diventando logorante. In altri scenari — dove il dato avesse confermato la percezione — avrebbe fornito evidenza concreta su cui agire.