1. 22 Sep, 2026 21 commits
    • chore(live): sunny_side_up — acid bass up two octaves, the ^59 mask gate off · 26f20c02
      Desk edit from tonight's rehearsal. `|- note 36` -> `|- note 12` on acidOto3092,
      and the mask(16,32)+ply gate commented out so d7 runs the arp clean.
      PLN (Algolia) authored
    • docs(backlog): clear the tail, keep what was in it · c2fd9716
      PLN: "deliberate killed tail was just a agent log or srth, capture that removed
      as learning, nut then let me clean that backlog indeed was gboing tedious."
      
      The tail is cleared and the new AI ENGINEER candidate section stands. But the
      543 lines were not a log: they were two sessions of rig notes from 6-7
      September, and six items in them were still open. Losing them to a backlog
      cleanup is the quiet kind of loss — nobody misses a note they have forgotten
      writing.
      
      So the whole block is archived verbatim in docs/, with the open items hoisted
      to the top of it where they can be read without scrolling. The one that
      matters: `sudo tools/install-protect.sh` was never run, so the OOM-protection
      daemon has never actually protected anything — it reported ok only because
      scsynth and sclang already sat at the target value, and no write was attempted.
      PLN (Algolia) authored
    • docs(gig): where the hands have to go after the remap, and two stale claims fixed · 092e1a17
      The remap commit carried counts. Counts do not help at the desk: a knob that
      moved from C5 to B4 is a knob that does nothing when you reach for it. The
      tracker now holds the was/now table for every one of the 24 moves, because
      PLN is rehearsing jeudrill and rose_rouge tonight and both of them moved.
      
      Also recorded: techno_orage's ^58 firing across d5 and d6, the corpus-wide
      154-file job that is explicitly NOT for tonight, the 114 duplicate FIXME lines
      left behind by the old non-idempotent tool, and the fact that "the set" still
      resolves to the Opal list through backlog.md while Thursday's arc lives only
      in armada/setlist_thu24.txt — a default nobody should trust this week.
      
      Two fixes in the tool itself:
      
        * the FIXME dedupe was a snapshot taken before the insert loop, so one run
          could still stack two identical notes when an orbit is split across two
          blocks. It now learns as it writes.
        * the docstring still promised that buttons were "Phase 2, after the gig".
          They were folded in when #94 shipped, and the tool has been moving BT/BL
          cells ever since. A docstring that defers work the code already does is
          the one place a reader can learn the wrong scope.
      PLN (Algolia) authored
    • fix(surface): finish the column remap on the tracks actually in play · d8effb67
      The #94 remap was run against a setlist, not the catalog, so conformance was
      never a property of a track — it was a property of having been on that list.
      Two days of desk edits then pushed listed tracks back out: swapping jeudrill's
      d9 and d10 bodies moved the orbits but not their knobs, so d4's effect was
      sitting in d5's column again.
      
      Migrated, one simultaneous permutation per file, 24 moves across six tracks:
      
        jeudrill        6   the d9/d10 swap's knobs follow their orbits
        liquid_nite     4   the four PLN had not reached by hand
        rose_rouge      3
        techno_orage    9
        cyber_hump      1
        siberie_samuel  1
      
      liquid_nite is the one that prompted this — PLN saw it in the catalog, wanted
      it in the set, and found it half-migrated: he had walked the buttons down a
      column by hand (^42 -> ^41, ^43 -> ^42) and stopped. The knobs are now on
      their own columns too, and it evaluates clean.
      
      VERIFIED, not assumed: re-plan reports 0 moves on all six; silent-eval
      --seeded is OK on five. techno_orage still FAILS, on the same d2 that was
      already silent before this commit — unchanged, and still PLN's call to fix or
      cut. pvlint: 0 errors, 21 warnings, all pre-existing shapes (PV013 missing
      family mutes, PV005 double declarations). One is worth reading: PV008 says
      techno_orage's ^58 drives d5 AND d6, which is the overflow the tool annotated
      rather than commented — a $-step cannot be commented out without breaking the
      block's arity, so that button really does fire across two columns until gSel
      folds it.
      
      AND THE TOOL NO LONGER TALKS TO ITSELF. Every run stacked another
      byte-identical FIXME paragraph above the same line: cafe_glace carried the
      same note three times, and 90 files in the corpus carry 114 duplicate lines
      between them. An overflow is a standing condition, not an event, so it earns
      one note. The comment-out still runs on a repeat pass — if a line came back to
      life it is firing across columns again whatever the note says — only the note
      is deduplicated. Proven by applying twice and diffing: 15/13 both times.
      
      Corpus-wide, 154 files still want 709 moves with zero clashes. Not tonight.
      PLN (Algolia) authored
    • chore(live): commit the desk edits that were sitting uncommitted · 0399c2d3
      Everything here was already in the working tree — played, kept, never
      committed. Written down now so the gig runs off the repo and not off one
      laptop's dirty tree.
      
        siberie_samuel  NEW FILE, and it is in the Thursday candidate arc. It
                        existed only as an untracked file: nothing outside this
                        filesystem knew the track was real.
        liquid_nite     the buttons walked down a column by hand (^42 -> ^41,
                        ^43 -> ^42) and a long tail of commented-out orbits was
                        cut. The button axis is Phase 2 of the #94 remap, so this
                        is hand work ahead of the tool, not a conflict with it.
        jeudrill        d9 and d10 swapped bodies; the d9 crushbus commented out.
        you_my_sunshine cut 3 and the legato sweep off; room 0.14 -> 0.8, sz 0.9.
        techno_orage    back to the Children Holiday line, slow 4 on the notes,
                        cut 3 dropped.
        esperluette     the bassWarsaw d5 removed.
        sept1           resetCycles dropped from the top.
        piment_bresilien whitespace.
      
      setlist_opal2026.txt loses its SOUNDCHECK section, so the pairwise walk in
      orphan-orbits.py starts on the real opener. That file is a record of a past
      gig, so the removal is visible here on purpose rather than folded into a
      larger commit.
      PLN (Algolia) authored
    • feat(setbuilder): the picker now holds the catalog it already measured · cdbc28ff
      The sweep evaluated all 703 tracks on Sunday night and found 597 that compile
      and emit. The picker still carried fourteen hand-written entries, so the page
      said the library was fourteen deep — the measurement existed and the surface
      that needed it did not have it.
      
      gen_setbuilder_catalog.py turns the sweep into the page's data, joined against
      two things the verdict alone does not tell you: how often the driver journal
      saw the track loaded (what the hands know), and how many of its sample banks
      the preload plan already warms (a cold bank is not a fault, it just hiccups on
      the first bar). Sample names come from setlist_samples.py, never a fresh regex.
      
      The sweep results now live in docs/ instead of a scratchpad that dies with the
      session — an artifact nobody can compare against is the preload.scd story.
      
      Ids are repo-relative paths, not stems. Sixteen stems collide across folders
      (major_nostalgia in chill and techno, all four FFF tracks in two trees) and a
      stem key merged each pair into one card, silently. Picks stored under the old
      stem keys are migrated on load where the stem is unambiguous.
      
      And the Thu-24 list is a candidate arc, not a locked set. It was exported from
      the builder, not decided at the desk; rehearsal decides.
      PLN (Algolia) authored
    • docs(tasks): the set is locked, the preload covers it, and the gate that would… · 806c1e5d
      docs(tasks): the set is locked, the preload covers it, and the gate that would have undone both is fixed
      PLN (Algolia) authored
    • fix(preload): the gate asked the wrong question, and asked it in the wrong locale · c52de40d
      gig-up runs check-preload --fix whenever the check fails, so a plan that was a
      deliberate superset scored STALE and got silently narrowed — bass2 would have
      been dropped on gig night and ete_a_mauerpark would have lazy-loaded mid-set.
      Membership now uses comm -13/-23 (missing is a fault, extra is information),
      counts join on shared banks, and --fix emits the union so it can never shrink.
      
      Second hole, latent: under en_US.UTF-8 a whole-line sort orders 'bass2 5' before
      'bass 4' while join compares field 1, so join dropped a pair (123 of 124 shared
      banks) and 2>/dev/null ate its warning — a count check with a hole reports ok.
      LC_ALL=C and sort -k1,1 on every set operation; join now equals comm -12.
      Extras are also count-checked against disk: SuperDirt asserts the recorded count
      at boot whether or not the bank is in the set.
      PLN (Algolia) authored
    • docs: the whole catalog measured — 84.9% of 703 tracks compile and emit · 080b7f7b
      Not sampled: every .tidal under live/ evaluated with silent-eval --seeded.
      85 do not compile and 21 have a genuinely silent orbit; the failures are
      diffuse helper/API drift (scope errors on g, jchord; Pattern String type
      mismatches), not one rotten folder. Playable is still not gig-ready — the
      play log remains the better signal for a set.
      PLN (Algolia) authored
    • feat(set): the Thu-24 setlist, ten tracks in play order · 2fbb7d37
      From PLN's Set Builder export, 120/120 min. All ten pass silent-eval seeded;
      the set needs 46 banks, all present on disk. preload.scd (gitignored, generated)
      regenerated as a superset — 125 banks, adding bass2 for ete_a_mauerpark.
      PLN (Algolia) authored
    • fix(tray): wrap QjackCtl in pw-jack so it opens the graph the rig lives in · fa0ec298
      The row existed but bare, and libjack.so.0 resolves to jackd2's — an unwrapped
      qjackctl shows an empty jackd2 graph instead of PipeWire's. Same wrap as Ardour.
      PLN (Algolia) authored
    • docs(armada): status page caught up — the cap is lifted, the faders are fine, the run is the gate · 92c2e340
      Three rig items and two of the three next moves closed while the page was being built;
      SOUND now carries the measured Master reading instead of the wrong -inf claim.
      PLN (Algolia) authored
    • feat(armada): gig status page — five buckets, one gate, glance and close · 89bef9dd
      Where Thursday stands on paper: rig, set, sound, stage, rehearsal, each with an honest
      figure and the items only PLN can do, over a live countdown to doors.
      PLN (Algolia) authored
    • docs(tasks): the orbit faders are fine — it is the Master that sits 30 dB down · 859c9cbd
      check-mix against the running session: twelve orbit faders between +0.0 and +6.0 dB,
      none muted, all routed to master. The overnight -inf reading does not hold. Master
      -30.2 dB is the real finding, and with OSC off only PLN's eyes can confirm the live value.
      PLN (Algolia) authored
    • fix(rig): the OLED re-arm reprinted its own stale cache forever · bbda3e94
      A hard DJF swing froze the readout: the 20 Hz door dropped events without
      parking one, and the 0.9 s re-arm then replayed the cached strings, so a
      value the glass never caught was reprinted indefinitely — pinned at 127 the
      'end stop' continue skipped the display entirely and 5.6kHz (value ~108)
      stayed on screen for good. The re-arm now recomputes from self.values, so any
      dropped event heals within 0.9 s whatever ate it; the door parks instead of
      dropping; the flush takes the freshest value. Momentary family_mute lines
      still replay — mutes_held() is transient state, not durable.
      PLN (Algolia) authored
    • style(armada): set builder on paper — light theme, one family with the status page · b513d793
      Cream ground, warm brown ink, sage for OK, amber for WARN, terracotta for the
      played-recently badge. Screenshot-verified over HTTP at 1400px.
      PLN (Algolia) authored
    • feat(armada): set builder — pick and order the Thu-24 arc against validated state · 4f83790a
      Fourteen candidates: the nine from the overnight sweep plus the five the driver journal
      shows PLN actually played this week, each with its silent-eval verdict. Per-track minutes
      against the 120-minute target, reorder, copy the paths out. One static file, no build,
      renders offline, LAN-reachable for phone picking.
      PLN (Algolia) authored
    • docs(tasks): Tue-22 gig state — the latency cut is not live, the CPU is capped,… · 0cd6300a
      docs(tasks): Tue-22 gig state — the latency cut is not live, the CPU is capped, and the play log names the set
      
      Three corrections from measurement: sclang predates the s.latency edit (still 0.2 in the
      process), max_perf_pct is 55 so every audio number is suspect, and the driver journal shows
      12 tracks actually played in 5 days — five of them outside the overnight sweep.
      PLN (Algolia) authored
    • fix(rig): saturated encoder flicks slam to the end stop · 8e7b7134
      rel_delta caps one message at +-63 (7-bit offset-64); firmware acceleration
      compresses a fast flick to 1-2 messages, so flick-to-max landed at ~125.
      A saturated delta in the end-stop band (>=115 up / <=12 down) now snaps to
      127/0 — slow turns never saturate, precise control untouched. Feel bands,
      PLN vetoes at rehearsal.
      PLN (Algolia) authored
    • perf(rig): all analogue controls onto our OLED overlay by default · 9a4918a4
      The firmware's per-control value row never shows driver-integrated values
      for relative encoders (stuck at 0 — probe H5 unresolved); PLN chose one
      coherent fast overlay over 29 firmware-drawn fictions. Overlay-only mode
      (promoted from --oled-overlay fallback to default) draws every knob on the
      global 0x36 target with bring-up-after-write; --oled-native restores the
      old firmware-drawn mode.
      PLN (Algolia) authored
  2. 21 Sep, 2026 4 commits
  3. 20 Sep, 2026 5 commits
  4. 18 Sep, 2026 1 commit
    • fix(gig-up): speak the dialect the tray speaks — accept --converge and --quiet · fa548f0f
      Every tray GIG UP click POSTed to the Bridge, which ran
      'gig-up.sh --converge --quiet' — flags this script never parsed, so the
      arg guard rejected it with 'unknown option' and exit 2, output swallowed
      by the Bridge's capture. Net effect: Pulsar opened (PRE_APPS, before the
      POST) and nothing else ever booted. The script and its caller had
      drifted apart on paper only — this is the contract, written down.
      PLN (Algolia) authored
  5. 17 Sep, 2026 2 commits
    • feat(tray): Bridge-styled menu, de-dashed copy, keyboard mnemonics · 6fb0f98d
      The double click was the appindicator extension's, not ours: it reserves
      double-click for SNI Activate (instant menu) and delays single-click by
      400 ms, so a single click feels dead. Nothing to fix tray-side; documented
      in the changelog.
      
      - BRIDGE_QSS restyles the Qt-drawn popup on dark desktops: tonal surfaces,
        hairline borders, hover pill, magenta on the engaged radio; circles for
        radio groups, squares for boolean toggles. Contrast measured: body 14.7:1,
        disabled 6.4:1, radio ring 3.3:1 (bumped from 2.3:1 in review).
      - stat rows and the thermal tooltip read in tabular digits.
      - every user-visible string loses its em dash (colons, parens, middots);
        same pass on gearbox.py labels (shared with the web Bridge) and the
        launcher blurbs; unknown gearbox placeholder is now n/a, not a bare dash.
      - mnemonics on the action rows (&Open Bridge, &GIG UP, &Restart SuperDirt,
        R&ig, &Start at login, Cut G&PU, &Quit); verified over DBusMenu that Qt
        exports them as underscores, so the shell-drawn twin gets them too.
        Literal ampersand does not survive the export, so the copy avoids it.
      PLN (Algolia) authored
    • fix(launcher): converge the rig units — the tray and lens died and nothing brought them back · 4ea24cb0
      The GUI launcher started SuperDirt, Ardour and Pulsar as raw processes and
      never touched the systemd --user layer, so a tray that exits 0 when the shell
      takes its host away (perf-tray, Sep 14) or a user-closed MIDI lens (exit 78)
      stayed dead: the only convergers were tools/gig-up.sh --converge, rig-doctor
      and the Bridge watcher, and the Bridge was dead too. Three days of launches
      "worked" with no tray and no lens.
      
      ensure() now refuses to start a unit whose proof process already runs outside
      it — which is what makes it safe for the launcher to call --ensure --apply
      after scsynth is up instead of spawning a second SuperDirt through
      parvagues-sc.service. --status agrees, so a launcher-started SuperDirt is no
      longer a false problem row. gig-up.sh converges right after the ready-wait,
      and honours the midiviz close-latch (the tray's MIDI Monitor button is the
      way back within a session).
      PLN (Algolia) authored
  6. 11 Sep, 2026 1 commit
    • fix(gig-up): SuperDirt starts under pw-jack, or it steals the card · 6e49f925
      open_term() launched sclang directly, bypassing parvagues-sc.service and its
      10-pipewire-jack.conf drop-in. With jack2 installed, ldconfig hands scsynth the
      real libjack, it finds no server and starts jackd on hw:sofsoundwire, which
      takes the card from PipeWire by D-Bus reservation. Meters move, nothing is
      audible (raw jackd -dalsa bypasses ALSA UCM, so the SOF speaker route is never
      enabled), and Bluetooth cannot work at all since jackd has no BT backend.
      
      Also adds tools/parvagues.desktop so the ordered launcher is one Super-key away;
      nothing had ever been installed in ~/.local/share/applications.
      PLN (Algolia) authored
  7. 07 Sep, 2026 6 commits
    • fix(tray): the menu the shell will not draw, and the checks that missed it · 440d086c
      "i see the parvagues tray icon, but doesnt react when i click" — twice, with
      the unit green both times. Three findings, in the order they mattered:
      
      - The menu WAS exported and populated all along (19 rows over
        com.canonical.dbusmenu). What made it useless is the style: with
        QT_QPA_PLATFORMTHEME=qt5ct and no qt5ct config under the unit, Qt picks
        `qt5ct-style` with a bare #efefef palette — a 2009 grey box on a Yaru
        desktop. Now: Fusion, plus an explicit dark palette when the desktop asks
        for dark (GNOME's color-scheme is the one setting that knows).
      - The tray host on GNOME is an EXTENSION, and it registers its
        StatusNotifierWatcher seconds after login. perf-tray printed "No system
        tray available", exited 1, and only Restart= saved it 3 s later. A slower
        login loses that race. Now it waits up to 120 s, polling on a QTimer
        (availability arrives over D-Bus, so the event loop has to be spinning).
      - New check `perf-tray reachable`: unit active, item REGISTERED with the live
        pid (a stale item from an old pid looks identical on screen), and the menu
        populated over dbusmenu — the only one of the three that a click needs.
        Negative-tested against a stopped tray.
      
      Also:
      - `wireplumber churn` check: starts per hour, and who asked for them. The
        existing checks could only see the wreckage (a failed unit, a dummy sink);
        this sees the cause while audio still works. It FAILs on tonight's 48.
      - The kwin midiviz-pin check asked KDE questions on a GNOME session, so it
        warned forever about a file that will never exist. Desktop-aware now: a
        check that cries wolf is one nobody reads on the day it is right.
      PLN (Algolia) authored
    • feat(monitor): headphones mode — every orbit in your ears, no Ardour · 5818b2b0
      The rig is multichannel by design: orbit k is the pair (out_{2k-1}, out_{2k}),
      wired to its own Ardour track at a gig. Away from the stage that design means
      d1 is the only orbit that can reach a sink — and on a freshly booted laptop
      (2026-09-07) not even that: scsynth had NO links to any sink, so the whole box
      was silent with every check green.
      
      - tools/fold-orbits.py: fold all orbit pairs onto one stereo sink, summed at
        unity. Idempotent, and it VERIFIES — pw-link exits 0 for "File exists" and
        for a port that vanished mid-call, so its exit status proves nothing. The
        channel count is discovered from the graph (28 today, 12 in an older
        comment, 2 on stock SuperDirt), never assumed. Refuses while Ardour runs,
        which owns the mix and prunes SC->hardware links every 2 s.
      - gig-up.sh --headphones: SuperDirt -> fold -> Pulsar. No Ardour, no fader
        restore; the fold becomes the readiness gate, because it IS the whole
        monitoring path.
      - gig-preflight: `monitor path` check — stage (Ardour receiving on N tracks)
        or headphones (fold present), and it asks fold-orbits rather than
        re-deriving the port math.
      - 18 tests, fixtures captured from the real graph: `pw-link -lo` marks links
        by INDENTATION only, so a grep of it fabricates relationships, and a source
        port printed with no indented child is the exact state this tool fixes.
      
      Measured, not assumed: 14/14 orbits arrive at the sink (bd swept d1-d14, peak
      per orbit), and the links survive 32 s of autoroute reconciling.
      PLN (Algolia) authored
    • fix(doctor): failed system units warn, failed user units fail · 0af672a5
      First production run of the failed-units check flipped the whole set-
      readiness verdict on apport-autoreport.service — honest but wrong: the
      rig runs entirely in user scope, and system-scope corpses (apport, snapd
      chores) rarely gate a set. User scope stays a FAIL.
      PLN (Algolia) authored