# ☕ Morning, 2026-07-29 — OPAL Day-6

**Everything is running. Nothing needs starting. Go play.**

The night's work is on branch `claude/preload-eager-banks`, 5 commits, **435 tests green**.

---

## Just play — the three things to know

**1. Your run-through is being recorded (numerically) already.**
`gig-log` has been sampling at exactly 1.000 Hz since 00:57 — temps, CPU freq, throttle
counts, xruns, per-gear %CPU + RSS, and every LCXL control move. It's a systemd unit, it
starts with your session, and it costs **0.4% of one core**. Wall-clock stamped, so it
lines up with your Ardour take.

```bash
tools/gig-log.py mark "gimme acid drop"   # annotate mid-set, any time
tools/gig-log.py report                   # read it back afterwards
```

When you finish, run `report` and we'll review the run together.

**2. The LCXL looks different — on purpose.** Both things you spotted are fixed:

| | before | now |
|---|---|---|
| DJ filters (row C) | wash of oranges, 7 steps | **red** = cutting highs · **bright yellow** = bypass (centre) · **green** = cutting lows |
| knobs (rows A/B) | dim / not-dim only | your six-step ramp, wired in at last: dim red → red → dim amber → amber → dim green → green |
| mutes 73/74/75 | `R R G` 🤨 | all three identical |
| panic armed (`^93`) | invisible | **all four chord buttons flash red** |

Rows A/B will be uniform dim red at rest — that's "nothing brought in yet", and things
climb toward green as you bring them up.

**3. Right-click the tray → `Gear ▸ 3/6 up`.** It now says what's *already running*
(● running / ○ stopped / ✗ missing) instead of only offering to launch.

---

## One thing worth 5 minutes before you play

**Your set leaves ghosts at 8 of 12 transitions.** That's the crimewave synth you heard
under bombe_dj — `dN` replaces orbit N and says nothing about the others, so any orbit the
outgoing track declares and the incoming one doesn't just keeps playing.

```bash
tools/orphan-orbits.py            # the whole set, transition by transition
tools/orphan-orbits.py --matrix   # which orderings are cheap
```

- Under pressure: **`hush` between tracks.** Safe, costs the tail.
- **Perfect <3 declares all 12 orbits** → it's a free *reset point*. Anything can follow
  anything into it. Useful ordering lever for #12.
- Worst offenders: after REVOLUTION (4 orphans), after Gimme Acid (3).

Set list is now data: `armada/setlist_opal2026.txt`. Reorder it and re-run to re-answer.

---

## Also: the pre-gig gate can actually run now

`tools/check-tracks.sh` boots every track in the set and proves each declared orbit makes
sound — which is also the only compile check a `.tidal` file can have. It read a setlist
from the repo root that **never existed**, so it has been unrunnable since it was written.
Now it reads the same `armada/setlist_opal2026.txt` as the ghost report.

```bash
tools/check-tracks.sh          # ~45s per track by design; needs audio
tools/check-tracks.sh --help
```

Worth running once with sound up before OPAL — three times this week "the rig is silent"
turned out to be "the code did not compile".

---

## Waiting on your ears / hands (not on work)

1. **`pv-at --track` — run it with sound up.** It probes every control on a track and says
   MOVED / NO_IMPACT / INCONCLUSIVE. Built and unit-tested; the audio half has never run
   because the house was quiet. Start with `python3 tools/at --track live/midi/nova/acid/gimme_acid.tidal --seconds 4` (~8 min, 22 controls).
   Any **NO_IMPACT is a real find** — a mapped control that does nothing.
2. **#46 the surface remap** — needs you to re-learn Ardour's 12 gains by hand, and to move
   `piment_bresilien.tidal:77`'s crush off `^14`. Verify fader→orbit *by behaviour*; the
   saved session disagrees with the live mixer (#62).
3. **#8 thermals under load** — needs monitors + a heavy track for 10 min. gig-log now
   captures exactly what's needed. (Baseline so far tonight: **0 xruns, 0 throttle events.**)
4. **#70** you_my_sunshine d5/d11 cut-group clash, **#12** set order, **#13** transitions.

---

## Found while working, worth knowing

- The tray was wired to open **"Tidal Multi"** — the *archive* session — not "Tidal Live".
  Fixed. It also could never have launched Ardour at all (looked for `ardour8`, you have
  `ardour9`), and its running-check matched any shell that merely mentioned the word
  "ardour", so it could report Ardour up while it was down.
- `lens.py` couldn't see `gF1/gF2/gF3` **at all** — they live in `BootTidal.hs`, not in the
  tracks — so the acceptance test was blind to the three DJ filters and every mute. It now
  parses BootTidal. gimme_acid went 18 → 22 controls.
- Two of your three mutes were being measured with the wrong lens (`mask "f*16"` read as a
  density gate rather than a mute), so two working mutes would have reported as dead.
- `perf._read(None)` crashed instead of returning a default — the Bridge shares that path.

Full narrative is in the commit messages (they're written to be mined for the blog).

**Nothing I touched needs a reload or a restart. `check-boot.sh` passes. Have fun. 🤘**

---

## ⚠️ Added after your first playthrough — read this one

**The "drifts to silence over 4 bars" thing is not a drift.** `BootTidal.hs:100,126`:

```haskell
xfade i = transition tidal True (Sound.Tidal.Transition.xfadeIn 4) i
d1 = xfade 1 . (|< orbit 0)
```

Every `dN` is a **4-cycle crossfade** — your "over 4 bars" is that exact number. So the
sound you hear after ctrl+enter is the **previous** pattern fading out; the **new** one is
already silent. The crossfade is working fine and has been *masking* a silent-eval bug by
giving it a graceful exit.

**The sound right after ctrl+enter is not evidence the eval worked** — it's evidence the
last one did.

Discriminator, 10 seconds: **eval the same track twice.** Silent from bar 1 the second
time = confirmed. Then it's the usual silent-eval suspects — an unset `^NN` (which yields
*no events*, not 0), or a block that didn't compile. `tools/check-tracks.sh` answers that
for all 13 tracks at once and is runnable again.

Tracked as **#79**, and it blocks #77 (silence-guard), #74 (the control AT — its 8s settle
lands inside your fade) and #13 (transitions). Everything else can wait; this one can't.
