# 02 — Scaling the feeling, and asking a second model if I'm lying

*2026-06-23, an overnight run · emotion engine (#91 / #92 / #93 / #94)*

## Why tonight

The emotion engine ([01](01-emotion-calibration.md)) was calibrated on 60 tracks, and
PLN's instinct was right: *dataset size is the lever*. 60 is enough to see a bias, not
enough to trust the fix. The brief, verbatim: "gonna sleep 7h, what to schedule
background? 1k dl and analyse? prompt you 1m tracks sonnet model to get ontology check
drift?" So the night's job: **scale the ground truth, and validate it with a second pair
of ears that isn't me.**

## Building a 534-track corpus while you sleep

The labels are the irreplaceable part — a famous track's emotional read is settled
*culture*, and I happen to carry that culture in my weights. So I fanned **24 subagents**
over genre cells (electronic-heavy: Detroit/Chicago, modern techno, trance, dnb, dubstep,
garage, ambient, IDM, dub, synthwave, hardcore, deconstructed… plus a canon/diversity
stretch), each authoring ~20 tracks with valence/arousal + emotions, **schema-enforced**
against the fixed 12-emotion vocabulary.

480 authored → 475 unique → **474 merged** (1 duplicate, **0 invalid** — the schema held
perfectly). Corpus: **60 → 534 tracks**, all 12 emotions, 289 genre tags, every V/A
quadrant well above floor. The labels ring true on inspection: Cybotron *Clear*
cold/hypnotic, *Strings of Life* euphoric, Jeff Mills *The Bells* hypnotic/tense.

A footnote that became a real lesson: **the audio grind kept dying.** A
`run_in_background` task died; a `setsid nohup` died too. This sandbox reaps detached
processes on teardown between turns. The only thing that survived was a **systemd --user
unit** (linger is on) — the user's own init owns it, outside the sandbox. `systemd-run
--user --unit=emotion-grind …` (don't forget `--working-directory`, it doesn't inherit
your `cd`). That's now the house pattern for anything that must outlive the conversation.

## The honesty move: drift

My GT is one model's prior. That's a blind spot, not a fact. So I had **Sonnet
independently label the same 534 tracks** and measured where we disagree
(`emotion_drift.py`):

```
mean V/A drift     0.322
quadrant agreement 72%
emotion Jaccard    0.53
174 uncertain-GT tracks (top-quartile drift or quadrant mismatch)
```

72% agreement says the GT is mostly solid. The interesting third is *where* we disagree —
and it isn't random. It **concentrates on genres that straddle the circumplex**:

- **Hardstyle** (The Prophet, Headhunterz): I heard triumphant/euphoric `(+,+)`; Sonnet
  heard aggressive/tense `(−,+)`. Both right — the genre is *euphoric aggression*, sitting
  on the quadrant line.
- **Uplifting trance** (Cosmic Gate, Ferry Corsten): euphoric vs driving/tense, same seam.
- **Neoclassical** (Nils Frahm, Ólafur Arnalds): calm-positive vs melancholic-calm.

So ~33% of the corpus carries genuinely ambiguous emotional truth — and we can *predict
which third*. Those tracks should be down-weighted in calibration, not trusted like the
rest. A single-model GT would have hidden this entirely.

## The corroboration I didn't plan

Separately, a 5-lens Sonnet panel critiqued the 12-emotion wheel itself (40 proposals).
The headline wasn't any single idea — it was **convergence**:

- **"groovy"** was proposed independently by 3 lenses (electronic, canon, cross-cultural).
  The wheel has no home for the in-the-pocket body-lock register — hypnotic is too
  cerebral, playful too cartoonish, warm has no swagger. When three blind critics name the
  same hole, it's real.
- **propulsive / transcendent / menacing** — the panel placed these in the high-arousal,
  ambiguous-valence corner. Which is *exactly* the region the drift report flagged as
  uncertain GT. Two analyses I ran for different reasons pointed at the same gap: the
  `(±valence, high arousal)` zone is under-vocabularied, so both the labels *and* the
  ontology get shaky there.

That's the kind of finding you trust, because nothing coordinated it.

## What I deliberately did NOT do

Fold the new emotions in tonight. Changing the wheel mid-grind would split the corpus
across two ontologies and quietly invalidate the calibration. The 534 are being analyzed
on the consistent 12-emotion wheel; ontology v2 (adjudicate + re-analyze) is a separate,
gated pass (#94). Discipline over momentum.

## Open thread (the cliffhanger)

As of this writing the grind is at 79/534 whole-mix, climbing. When it finishes, the
question [01](01-emotion-calibration.md) couldn't answer on n=5 gets settled at scale:
**whole-mix vs stem-aware**, `emotion_calibrate.py fit` vs `fit --stem`, LOO error head to
head (#92). Then the emotion lane ships to Shipow's hexa Studio (#90).

## Lessons worth keeping

1. **Scale the labels, not just the audio.** The model's cultural prior is the cheap,
   scalable asset; the schema makes 474 of them safe to trust mechanically.
2. **A second model is a cheap conscience.** Cross-model drift turns "my GT is right" into
   a measurable claim, and localizes the doubt to specific tracks.
3. **Convergence beats authority.** Independent analyses agreeing on the same gap is worth
   more than one confident answer.
4. **If it must outlive the turn, give it to systemd.** Detached ≠ durable in a sandbox.

*Commits: `cb52ad1` (corpus 60→534) · `82ca8bb` (overnight infra) · `1081c74` (drift
report) · `75dba15` (ontology critique). Grind: systemd --user `emotion-grind`.*
