Commit 57cf60a3 by PLN (Algolia)

docs: 027 — the instruments were the broken part, plus the pre-gig close-out

Achievement log for the night before CosmicFest, and the board amendment that
carries the resume points a cold session will need.

The log's through-line is not the LED daemon; it is that FOUR separate
instruments returned confident wrong numbers in one evening — `ps -o %cpu`
summed as if it were instantaneous (it is a lifetime average; the main pulsar
process read 2.1% while one child renderer burned 112%), `pw-top`'s ERR column
read as current when it is cumulative (delta over 25 s: zero on every node), a
shell path built as `live/$f` when `$f` already began `live/`, and a
`grep -cE '[1-9] move'` that silently skips `10 move`. Three of the four
returned a plausible number rather than an error, which is the whole problem: a
wrong tool is rarely silent-and-empty, it is confident-and-slightly-off.

Board amendment records what the next session must not redo:
* The highlighter is EXONERATED by its own instrument — 5 RAF/s x 1.671 ms =
  0.8% of a core, `markers 293 live, creates/destroys 0/s` over 4h42m. The
  marker leak is dead in the field. Do NOT re-open that hunt.
* Five hypotheses for the ~112% renderer are already dead, each with its
  evidence, so they are not re-tried: editor-background (disabled),
  sound-browser rAF loops (all terminate), fork-per-LED (2.8 ms p50, bench p99
  18 ms zero overrun), aseqdump pipe buffering (disproved on an isolated client).
* gig-up is 5 blockers -> 1, and the survivor is PLN's decision to defer 20
  column moves rather than renumber knobs hours before playing.
* CosmicFest EXISTS (PLN's own words) but has no canonical www page. The date
  and venue must come from him, never backfilled from eb9221de.
* Parked and flagged: 3205e7f unpushed in the pulsar-tidalcycles fork,
  sound-browser.js's 144 unvalidated insertions, backlog.md's +60 lines, and a
  one-line hello_fred.tidal stub.
parent 0f271843
...@@ -506,3 +506,82 @@ edition. Per `feedback_metadata_vs_mastering` I will not invent the date or the ...@@ -506,3 +506,82 @@ edition. Per `feedback_metadata_vs_mastering` I will not invent the date or the
A3-old's *"Build it"* is done; its still-live residue is only the two safety rules A3-old's *"Build it"* is done; its still-live residue is only the two safety rules
(test-namespace allowlist, Content-ID-arrives-by-email) and the sanctioned deletion of (test-namespace allowlist, Content-ID-arrives-by-email) and the sanctioned deletion of
playlist `2282681433` once v4 is up. Suggest folding both into A3/A4 and deleting. playlist `2282681433` once v4 is up. Suggest folding both into A3/A4 and deleting.
---
## AMENDMENT — 2026-08-22, pre-gig close-out *(appended; EPIC I above is the commit list)*
### ✅ CosmicFest is REAL and PLN plays it next — the open question above is half-answered
PLN, in his own words this session: *"do please do a commit `feat: cosmicfest prep`"* and
*"tomo ill setp and play"*. So the gig EXISTS and is imminent; that part needs no further
asking. What is still missing is only the **canonical metadata**`content/lives/2026/`
has no cosmicfest page (2025's is a different edition). Per `feedback_metadata_vs_mastering`
the venue/date/lineup must come from PLN or the www content, never from a commit message.
- [ ] **A6-adjacent:** create `content/lives/2026/cosmicfest.md` + `tracks.json` from PLN's
details AFTER the gig. Do not backfill it from `eb9221d`.
### gig-up: 4 of 5 blockers cleared, and the 5th is a DECISION not a defect
| gate | before | after |
|---|---|---|
| tools executable | FAIL | ✅ `4e0d63a` — two scripts +x on disk, 644 in the index |
| audio graph | FAIL | ✅ `b503502` — absent-UMC is now `warn`, not NO-GO |
| mute map | FAIL | ✅ `fix-mute-roles --apply`, converged to 0 |
| pvlint (setlist) | FAIL (4 err) | ✅ 0 errors — two crushbus slot collisions split |
| **surface grid intact** | FAIL | 🔴 **still red, on purpose** |
**Why the last one stays red.** 9 knobs off-column, **20 moves pending** — ghosts 10,
something_about_drums 7, perfect 2, the_revolution 1. PLN: *"migration i unfinishe dgrrr
lets not finish it before set for now."* Renumbering which physical knob does what, in four
tracks he plays imminently, is a muscle-memory change and not a safety fix; two of the moves
cannot resolve mechanically anyway (one `overflow -> gSel`, one `FIXME (no slot)`).
- [ ] **AFTER the gig:** `python3 tools/migrate-columns.py --plan` then apply, then
`tools/check-drift.sh` must go green and `--plan` must report 0 moves.
### 🔎 RESUME: a renderer burns ~112% and it is NOT the highlighter
The open perf thread, with the guesswork already eliminated so nobody repeats it:
* **The highlighter is EXONERATED by its own instrument.** `tidalcycles:highlight-stats`
over a 16919 s window: `RAF 5/s, work 5/s, frame avg 1.671 ms` = **0.8% of one core**.
Not the burner, not close.
* **The marker leak is genuinely DEAD in the field:** `markers 293 live,
creates/destroys 0/s`, `toggles 105/s` (the cheap reuse path doing its job), `errors 0`.
Confirms `6e9f374` (2026-07-18) + `ba77c4f` (2026-08-03) over a 4.7-hour window. **Do not
re-open the leak hunt.**
* **Already ruled out:** `editor-background` is in `disabledPackages`; sound-browser's three
`rAF(processChunk)` loops all terminate on `currentIndex < total`; `aseqdump` flushes per
event (proved on an isolated client — median 40 ms inter-arrival at a 25/s send rate);
fork+exec per LED write costs 2.8 ms p50 and `--bench` shows the coalescer at p99 18 ms
with zero overrun.
* **Caveat on the evidence:** the profile window was 4h42m while the hot renderer (pid
799788, `--type=renderer`, 3 `Media` threads) was 3 minutes old — so the stats likely came
from a DIFFERENT window than the burner. The 0.8% conclusion holds regardless.
* **Next step:** run `tidalcycles:highlight-stats` *in the hot window*, and get a per-thread
breakdown inside pid `--type=renderer` (the 3 `Media` threads are unexplained with
editor-background disabled).
- [ ] **NOT a gig blocker:** xrun delta over 25 s was **0 on every node** (ardour's 1200, SC's
38, the sink's 11 are all historical). High CPU has not cost audio. Fix it for editor
responsiveness, not for sound.
### Remaining known jank (editor only)
`jank: 245 frames >16ms, 91 >50ms | worst 179.82ms did 22 adds / 5 removes` — one visible
stall roughly every 3.1 minutes, ~6.5 ms per add, so stalls scale with burst size. The
highlight stylesheet is already proven to set no layout-affecting property
(`spec/highlight-class-contract-spec.cjs`), so the cost is elsewhere in the add path.
- [ ] Attribute the per-add cost in `#createPositionMarkers` / the add path (post-gig).
### ⚠️ PARKED — not mine to commit
* `~/Work/Tools/pulsar-tidalcycles`**`3205e7f` is committed but UNPUSHED** (no SSH access
to `github.com/PLNech/pulsar-tidalcycles` from that session). Branch
`perf/event-highlighter`. PLN pushes it.
* Same repo: `lib/sound-browser.js` has **144 uncommitted insertions** (waveformCache, lazy
AudioContext, currentAudio tracking) written by an earlier session. Loaded by the running
Pulsar. Unvalidated — left alone deliberately.
* `Tidal`: `backlog.md` (+60 lines) and `armada/setlist_opal2026.txt` are PLN's own
uncommitted edits, untouched all session (`feedback_...` — backlog is never mechanized).
* `Tidal`: `live/midi/nova/breaks/hello_fred.tidal` is a 1-line stub (`d1 $ `) — deliberately
not committed.
# 027 — 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.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment