# 029 — The instruments were the broken part

**Landed 2026-08-21/22, the night before CosmicFest.** PLN opened with *"i dont see midi
feedback visuel anymore on the LCXL fix this first plz"* and closed with *"are we ready to
play? :P"*. Answer: yes — zero xruns. But almost nothing that went wrong was where the
tools said it was.

## The LED feedback: hardware fine, daemon gone

The journal had the entire story and nobody was reading it:

```
lcxl-leds --watch: no LCXL sequencer port; retrying in 30s   (x8)
Stopping LCXL LED watcher...  ->  Stopped.
```

Board unplugged, watcher retried, watcher **stopped** — and `Restart=always` does not
resurrect a unit somebody stopped. He replugged; the board came back and the daemon did
not. Three holes let that be invisible for a whole session:

1. `lcxl-leds-watch` was **missing from the Bridge's SERVICES table**, so the panel showed
   a fully green rig over a dark board — one table row from the failure `rig.py`'s own
   docstring opens with ("A GREEN UNIT IS NOT SOUND").
2. The unit was `linked`, not `enabled`. It never started at login.
3. `midi-autoconnect` was `disabled` too — and this is the nasty one. The prescribed fix
   for the LED USB-OUT stall **is a replug**, and a replug drops the ALSA-seq wiring that
   nothing was re-applying. **The remedy for one failure silently triggers another,
   mid-set.**

## The gate that could not fail

Looking for what else watched the surface, the pre-gig "LCXL -> SC" check was:

```
aconnect -l | grep -A3 "Launch Control XL" | grep -q "128:"
```

`grep -A3` matches each of the *three* lines containing "Launch Control XL" and trails three
lines after each; the last window runs off the end of the LCXL block into the next client
header — which is literally `client 128: 'SuperCollider'`. **The needle was always in the
haystack. It would have passed with the desk wired to nothing**, and it had been passing
since it was written.

Proved rather than argued: recorded the live graph, stripped only the Midi-Through -> SC
edge, ran both gates against the doctored file. Old gate green. New gate red.
`tools/lcxl-path.py` walks the graph instead (it has to — the real path is two hops) and
takes a recorded-graph argument **so the gate can be tested for FAILURE without unplugging
hardware at a venue.** The reason the old one survived is that nobody could cheaply watch it
fail.

## The check that told me to delete his set

`check-drift` flagged 13 uncommitted `.tidal` files as *"the stale-buffer signature"* and its
remedy section led with `git checkout -- <file>`. I nearly relayed it.

All 13 were PLN's own work — the `^43/^44 -> ^41` gMask-retirement migration continued by
hand, plus real musical edits: `resetCycles`, new `octersubbus`/`squizbus` sends, a
`slow 2 $ ply 2` rework, `gain 1.4->1.6`, `n "74" -> n "25"`. That command would have wiped
the set the night before the show.

The script's own header had the right principle — *"drift is not control numbers changed, it
is control numbers moved AWAY FROM THE GRID"* — but its per-file test could only count
**how many** `^NN` lines changed, not **which direction** they moved. Both its conditions
were true for innocent reasons: the grid was unaligned because the migration was
**half-applied**, and the flagged files were the half that was done.

**Volume of change cannot separate a repair from a regression. Only direction can** — and
`migrate-columns --plan` already knew.

## Four instruments, four wrong numbers

The through-line of the night, and the reason this log exists:

| instrument | what it said | what was true |
|---|---|---|
| `ps -o %cpu` summed over the tree | pulsar at 122%, then 130% | lifetime AVERAGE; main proc 2.1%, one child renderer 112% |
| `pw-top` ERR column | ardour 1200 xruns | cumulative; **delta over 25 s = 0 on every node** |
| a shell path `live/$f` | 13 files, all zeros | `$f` already began `live/` — measuring nothing, tidily |
| `grep -cE '[1-9] move'` | 10 pending moves | skips `10 move`; the real figure was 20 |

Three of the four returned a **plausible number rather than an error**. A wrong tool is
rarely silent-and-empty; it is confident-and-slightly-off.

And the warning that started the whole perf hunt — *"#7 (highlighter marker pool). This is
the JITTER SOURCE"* — named a cause it could not see. Both marker leaks were fixed weeks
earlier (`6e9f374`, `ba77c4f`), and PLN's own profile settled it: **5 RAF/s x 1.671 ms =
0.8% of one core**, `markers 293 live, creates/destroys 0/s` over 4.7 hours. A warning that
names the wrong cause is worse than one that names none — it spends the reader's time
defending its guess.

## What shipped

`72937cc` LED watcher on the panel + the all-full-brightness daylight ramp ·
`7bda1cc` the false-green gate + two units nobody started · `4e0d63a` +x on disk, 644 in
the index · `b503502` absent-is-not-broken + the 512-deep queue that WAS the 1 s HUD lag ·
`cb5a625` check-drift stops recommending data loss · `c821bdf` stop naming an unseeable
cause · `eb9221d` **CosmicFest prep**, 24 track files · `3205e7f` (other repo, unpushed)
`evicted NaN`.

gig-up went **5 blockers -> 1**, and the survivor is a decision, not a defect: 20 column
moves deferred by PLN — *"lets not finish it before set for now"* — because renumbering
which knob does what, hours before playing, is a muscle-memory change and not a safety fix.

**Deps:** unblocks nothing; hardens everything H1 (PRE-GIG) named. The post-gig queue is the
20 column moves, the unattributed ~112% renderer, and CosmicFest's canonical www metadata —
which must come from PLN, never from a commit message.
