{
  "version": "relationship-texting-benchmarks-v2",
  "codeVersion": "0bc2ae04",
  "generatedAt": "2026-08-22T05:45:22.228Z",
  "publishable": true,
  "sample": {
    "accounts": 20,
    "threads": 29,
    "totalMessages": 4600611,
    "unitOfAnalysis": "account",
    "spanDaysMedian": 264,
    "minCohortToPublish": 15,
    "minCohortForBreakdown": 10
  },
  "definitions": {
    "account": "One person who uploaded at least one history. All rates are computed per account before being combined, so a heavy uploader cannot dominate a figure.",
    "thread": "One uploaded two-party message history, deduplicated so a re-upload of the same relationship counts once.",
    "message": "One sent item carrying a timestamp and a direction. Attachments without text still count as messages.",
    "direction": "Outbound is the account that requested the analysis; inbound is the other party.",
    "replyGap": "Seconds between a message and the next message from the other side, only where the direction changes, capped at seven days.",
    "per1000": "Class counts normalised by messages sent in that direction, so the larger sender does not dominate.",
    "repair": "A message the classifier scores as an explicit attempt to de-escalate or reconnect after friction."
  },
  "exclusions": [
    {
      "reason": "below_message_floor",
      "threads": 119
    },
    {
      "reason": "eligible",
      "threads": 89
    },
    {
      "reason": "implausible_timestamps",
      "threads": 46
    },
    {
      "reason": "span_too_short",
      "threads": 37
    },
    {
      "reason": "one_sided",
      "threads": 19
    },
    {
      "reason": "account_cap",
      "threads": 8
    }
  ],
  "stateMix": [
    {
      "state": "Affection",
      "outgoingPer1k": 22.463,
      "incomingPer1k": 20.819,
      "accounts": 20,
      "absent": false,
      "suppressed": false
    },
    {
      "state": "Repair",
      "outgoingPer1k": 2.108,
      "incomingPer1k": 2.481,
      "accounts": 20,
      "absent": false,
      "suppressed": false
    },
    {
      "state": "Blame",
      "outgoingPer1k": 0,
      "incomingPer1k": 0,
      "accounts": 20,
      "absent": true,
      "suppressed": false
    },
    {
      "state": "Distress",
      "outgoingPer1k": 0,
      "incomingPer1k": 0,
      "accounts": 20,
      "absent": true,
      "suppressed": false
    },
    {
      "state": "Harassment",
      "outgoingPer1k": 0.032,
      "incomingPer1k": 0,
      "accounts": 20,
      "absent": false,
      "suppressed": false
    },
    {
      "state": "Threat",
      "outgoingPer1k": 0,
      "incomingPer1k": 0,
      "accounts": 20,
      "absent": true,
      "suppressed": false
    },
    {
      "state": "Neutral/Uncertain",
      "outgoingPer1k": 973.105,
      "incomingPer1k": 973.999,
      "accounts": 20,
      "absent": false,
      "suppressed": false
    }
  ],
  "replyLatency": {
    "userSlowerThreads": 9,
    "partnerSlowerThreads": 13,
    "decidedThreads": 22
  },
  "findings": [
    {
      "id": "volume-asymmetry",
      "anchor": "volume-asymmetry",
      "headline": "The person who asked for the analysis sent 53% of the messages",
      "detail": "Computed per account, then taken across accounts. This describes who chooses to have a thread analysed, not relationships in general.",
      "value": 53,
      "unit": "percent",
      "range": [
        46.5,
        59.3
      ],
      "basis": "20 accounts, 4,600,611 messages"
    },
    {
      "id": "affection-direction",
      "anchor": "affection-direction",
      "headline": "Affection ran higher outbound in 14 of 20 accounts",
      "detail": "Per 1,000 messages: 22.463 outbound against 20.819 inbound.",
      "value": 1.08,
      "unit": "ratio",
      "basis": "20 accounts with a measurable split"
    },
    {
      "id": "neutral-share",
      "anchor": "neutral-share",
      "headline": "97.4% of messages carried no detectable emotional signal",
      "detail": "Long histories are mostly logistics, timing and small talk. The affective classes are the exception, which is why single screenshots mislead.",
      "value": 97.4,
      "unit": "percent",
      "basis": "20 accounts, 4,600,611 messages"
    },
    {
      "id": "affection-vs-repair",
      "anchor": "affection-vs-repair",
      "headline": "Expressions of affection outnumbered repair attempts by about 10.7 to 1",
      "detail": "Warmth is common; explicitly trying to fix a rupture is rare. The gap between them is the most stable ratio in the cohort.",
      "value": 10.7,
      "unit": "ratio",
      "basis": "20 accounts"
    },
    {
      "id": "hostile-classes-rare",
      "anchor": "hostile-classes",
      "headline": "Hostile language was near-absent: the most common such class ran 0.032 per 1,000 messages",
      "detail": "Distress, Threat did not reach a measurable rate. This is a property of who uploads, not evidence that hostility is rare in relationships.",
      "value": 0.032,
      "unit": "per_1000_messages",
      "basis": "20 accounts"
    }
  ],
  "withheld": [
    {
      "state": "Criticism",
      "reason": "Direction split is a measurement artifact, not a behavioural finding. Withheld pending a direction-blind re-scoring."
    },
    {
      "state": "Manipulation",
      "reason": "Direction split is a measurement artifact, not a behavioural finding. Withheld pending a direction-blind re-scoring."
    },
    {
      "state": "Repair",
      "reason": "The account majority (12 outbound vs 6 inbound) points the opposite way to the combined rate (2.108 vs 2.481). No direction claim is made."
    },
    {
      "state": "Blame",
      "reason": "Rate rounds to zero across the cohort; the class is too rare here to report."
    },
    {
      "state": "Reply latency",
      "reason": "Threads split 9 to 13 on which side replies more slowly -- no consistent direction, so no reply-speed claim is made."
    },
    {
      "state": "Thread duration",
      "reason": "Span is clustered on a few exact values from repeat uploads of the same relationship, so a median span would describe the upload pattern rather than the relationships."
    }
  ],
  "limitations": [
    "The cohort is people who chose to have a relationship analysed. It is not a random or representative sample of relationships.",
    "Direction is defined by who uploaded. Any statistic split by direction inherits that selection.",
    "Classifier labels are model output, not clinical judgements, and carry the error rate of the model that produced them.",
    "The cohort is small. Figures show shape and order of magnitude, not precision, and no significance test is claimed.",
    "Grey Mirror measures patterns in text. It does not diagnose abuse, deception, illness or predict outcomes."
  ]
}
