No telegraphs aboard (part 1)

Tap, tap, tap, tap, tap, tap. Octavia’s foot dully struck the cab floor unrelentingly. It would have been an attractive polyrhythm when juxtaposed against the deafening strokes of the locomotive pistons – if only it were audible at all. Kiril casually slid a piece of coal toward the tender pile, further clearing out the area around his modest perch.

The rest of the cab was filthy, coated with oil and soot. Kiril sat in the middle of a clean circle about two feet in diameter, having patiently slid away the coal balls and scraped off the worst of the grime from the floor. (He realized far too late that he was exchanging the cleanliness of his own soles to this end.)

Octavia sat on one of the window-side seats, eschewing the view and facing into the cab. She glowered at the engineer, clearly unsatisfied with the services rendered. “Driver, how long now?”

Gia, for the third time, Gia.” The engineer spared no glance for Octavia, tapping her finger on one of the dials instead. Her gaze flickered a moment to another dial; she seized her shovel and brushed past Kiril to scoop a generous helping of coal. “We passed Lower Derrynoose about thirty minutes back, so that puts us twenty out from Ballymore. You’ve got a map, you can work out the rest.”

Octavia kicked a stray piece of coal across the cab and off the train. Gia indignantly stabbed the floor with her shovel. “Them’s the rules. This is regular passenger service. This locomotive can’t go much faster than this, anyhow.” Gia walked back to the coal pile to grab another scoop.

“There’ll be a lot worse than a missed timetable if they send someone after us right now,” muttered Octavia, kicking another coal ball overboard.

The access door to the frontmost carriage opened without warning. All three cab occupants turned to look. A concerned, bespectacled face poked up over the top of the tender. “Hey, we’ve got – “

WHAM. A low clap of thunder rang in Kiril’s ears as the whole train leaped forward a bit.

” – trouble,” finished the passenger, reseating his spectacles, which had slipped badly from the collision.

Octavia leaped to her feet. “Driver – ” (“Gia!“) ” – you’d better be pretty damn sure that them’s the rules you want to die by.”

Octavia and Kiril clambered over the tender and alighted on the passenger gangway. Octavia jumped up the access ladder and poked her head over the lip of the carriage roof. Kiril stared up, watching her expression.

“Mmm, yeah, that’s bad.” Octavia looked down at Kiril. “They’ve sent a locomotive after us. Looks beefy.”

“They’re trying to catch us?” Kiril yelled up at her.

“No, it’s just the locomotive.” Octavia returned her gaze to the pursuing engine. “They’re trying to wreck us.” She raised a hand, pointing two fingers down the length of the train. She murmured something Kiril couldn’t hear, but his field of vision went white a moment later as a blinding beam of light jumped across the carriage roofs.

Far away, a dull thunk sounded. Octavia frowned and repeated the incantation. Kiril closed his eyes this time, and the dull thunk reprised itself.

Octavia shrugged and dropped to the gangway. “Did you get it?” asked Kiril. “Yeah, but it’s no good, not after I gave it two direct hits to the smokebox,” grumbled Octavia. “It flinched quite a lot, but it’s definitely been buffed to deal with this.”

Kiril glanced at Gia, who had taken a seat by the firebox, unflapped by the fact that her train was being pursued by a murderous locomotive. “What do we do?”

Octavia grabbed Kiril’s hand and began tracing symbols into his palm. Kiril’s hand began to glow like an ember, and Octavia traced faster. “Delayed fortification seal with a mass multiplier. Evacuate the last carriage and apply this to its floor – then decouple it. For pity’s sake, don’t touch anything else with that hand!”

Octavia finished off the seal. Kiril’s hand glowed brighter for a moment, then dimmed as the seal sank in. Kiril made a fist, nodded, and dashed into the frontmost carriage.

Octavia climbed up back into the tender and dropped into the cab. “Gia. You’re not going to like this.”

Gia looked up from tending the firebox and snapped its wing-doors shut. “What the hell do you want with my engine?”

“I want it to survive, much like I want me to survive,” growled Octavia. “And believe me, if I don’t do this, the train’s not going to survive.” Octavia squatted down and began tracing symbols on the firebox doors, keeping her hand about an inch off the searing-hot surface.

Now Gia was the one glaring at Octavia. “I’ll concede that driving her faster is better than being rammed by…whatever demon you’ve visited upon this train, but just remember that I’m the one with my hands on the throttle.”

Octavia grinned. “Well, Gia, by your leave, I think we’d best be passing Ballymore in under ten minutes, then.” She sat in the engineer’s window-side seat and leaned out of the cab, facing the rear of the train. Peering down the line, she took aim again with her right hand and fired off another two beams of light.

“‘Scuse me, sorry, sorry, coming through, ‘scuse me…” Kiril pushed through the throngs of panicky passengers, a lone salmon swimming upstream against a powerful current. Two flashes streaked past the windows on his left. “Ah, ladies and gentlemen, boys and girls, don’t panic, don’t panic, but also, please don’t open the windows for now, not if your heads are fond of your necks.”

The densely packed passengers thinned as Kiril approached the rearmost carriage. He tore open the door and stepped in. The few remaining passengers (curious gawkers, staring agape out the rear door, which had been smashed ajar by the first impact) looked up at his sudden arrival. Kiril rolled his eyes.

“What do you think you’re doing? Out! Out! Into this carriage, please!” Kiril stepped aside and gestured to the door, motioning the stragglers to vacate this rearmost car.

The last passenger to leave paused to take a passing glance at his hand, still glowing faintly. “What’s with your hand?”

Kiril groaned exasperatedly. “It still punches the same, want to see?” He seized this last passenger by the scruff of his neck and single-handedly threw him into the car ahead.

Kiril ran up and down the length of the carriage, making sure that nobody was left behind. He took note that the pursuing locomotive, despite being knocked back twice now by Octavia’s beams (two more flashes of light – thunk, thunk – three times now), was still closing the gap menacingly. Its smokebox bore an unnatural ruddy hue, and the smoke blowing out its stack was too thick to judge as unenchanted.

“Right, then.” Kiril squatted at the center of the car and touched his glowing hand to the floor. His hand glowed brighter, then dimmed to nothingness.

Three streaks of light went past his field of vision, impacting the pursuing locomotive loudly and pushing it back a bit further than before. Kiril sprang to his feet and dashed to the carriage gangway. The train was gaining speed, but so was the pursuing locomotive.

Kiril ignored the gawking passengers gathered at the door to the carriage ahead. He grabbed hold of the doorframe and squatted down on the gangway, reaching underneath with his casting hand. He closed his eyes and blindly traced two each of the seal of delayed action and the seal of undoing. He could, at the very least, draw these reliably without Octavia’s guidance. He topped it off with a seal of closure.

Kiril stood and entered the carriage ahead, not being shy about pushing passengers back. “You lot seem like you’d be gawking if your own parents were being guillotined,” he muttered. He braced both hands on the doorframe, waiting for his seals of delayed action to wear off.

Clank! The coupling holding the rearmost carriage to the second-from-the-rear came undone. The rearmost carriage began to separate idly from the rest of the train, no longer being pulled forward. Before it could separate so far as to pull the brake lines taut, snap! the second seal of undoing came due, and the brake piping was disconnected.

Kiril’s seal of closure activated in response to the second seal of undoing, ensuring that the air brakes remained pressurized in this car (and for the rest of the train). The rearmost carriage, though, was fully detached, and without a pressurized link, entered its failsafe mode in which the airbrakes were fully applied.

Finally, Octavia’s delayed seals now took effect. The car became instantaneously heavier and stronger; the latter change was not obvious, but the former was immediately apparent. Momentum-scaling seals are both finicky and time-consuming to draw; by happy coincidence, it was to their advantage that total momentum was preserved when mass was scaled up. Scaling up the mass of the rearmost carriage as Octavia had done would scale down its velocity. This manifests a natural and powerful braking action.

The rearmost carriage, with its mass greatly amplified and its brakes at maximum, shot violently away from the train. The pursuing locomotive, still doggedly gaining speed, jumped forward hungrily to meet it.

190: further adventures in PMX and my musical limits

Further adventures in PMX

Thus far, I have completed my arrangements of

  • Recover Decoration – for solo piano
  • Sophie’s Castle (TKCA-72775 track 24) – for soloist and piano
  • Underwater Town (TKCA-73340 track 29) – for vocalist and piano

I’m thinking about where to go next. The obvious choice is “The Boy Who Drank the Star” (TKCA-72775 track 25), but that piece daunts me. I absolutely want to do right by it, but without a trusted brass soloist (preferably a trumpet player) to bounce ideas off of, it’s easy to imagine this going poorly.

My musical limits

I listened to two different things this evening that prompted a thought about the limits of my musical ability.

Cabin Pressure – S3E4 – Ottery St Mary – Part 9

…in which Douglas and Arthur gain extraordinary expertise in pushing a piano up a hill to a pub in Ottery St Mary. The proprietor plays a few notes to spot-check the delivered piano. They are the three bare notes B3, F#4, F#5, and finally a major second comprising F#6 and G#6. I can tell this by inspection (and am confident of my guess), but anyone could reasonably derive this by standing next to a piano and trying a bunch of note sequences.

I can be confident about my guess because these are three single, unmistakable notes, followed by a tiny tonal cluster whose sound I find quite familiar.

But this note sequence is nothing – absolutely nothing – when pitted against

Marc-André Hamelin’s “Variations on a Theme by Paganini”

Hamelin’s sense of tonality positively blinds me. Here is a piece chock-full of adorable musical allusions (most of which flew over my head, like the Beethoven op. 109?) and carefully clustered writing. I find most of these inscrutable; I suspect that if you shut me in a room with a recording of this piece, I would be unable to rederive its score before I died. The density of its construction makes it nigh on impossible for me to deduce exactly what notes are being played at any given time.

Sensitivity to tonality is definitely worth something here: hearing the saccharine transition from A minor to A major to D flat major gives away the Rachmaninoff allusion before the melody line kicks in. But the dense harmonies of this composition otherwise obscure much about it that I consider essential.

It feels like we’ve arrived at a beautiful and intractable musical problem: the notes make a one-way trip to my brain, where I can appreciate them viscerally, but cannot deconstruct them whatsoever. It’s kind of like hearing a musical hashing function. I can make guesses – bad guesses – but bad guesses in such dense writing materially detract from the quality of the arrangement. This is often obvious even from a visceral and cursory perspective. You cannot substitute Mountain Dew for sugar and expect Mary Berry to give you passing marks on your cake. Hell, you might not even fool a child.

Compare, instead, to the situation in which you shut me in a room with a recording of a Vivaldi bassoon concerto. The antiquated, well-trodden tonality Vivaldi used is imprinted heavily in my head; I wager that I could create a serviceable arrangement of any such concerto with two or three days’ concentrated work. It would not be perfect, but in my unsubstantiated opinion, Vivaldi hailed from a time period where a C643 was…just a C643, and from an analytical standpoint, it doesn’t matter exactly where you place every single note that comprises that chord.


189: Some typesetting

Ever since I switched to my new laptop, I’ve found myself unable to use MuseScore. It seems like an issue with my graphics card that I can’t fix for myself. For some months now, I’ve been looking to take up a different musical typesetting system to fill this gap. This weekend, I took the first step in actually figuring it out.

I’m using this delightfully obscure three-lettered preprocessor. Its name really does it no favors with search engines, and the underlying typesetting system doesn’t seem to get much love at its corresponding StackExchange site. I’ve been using this cheat-sheet and this slightly longer reference to get by. I selected my arrangement of Recover Decoration to experiment with; I’m happy to report that in the space of about a weekend, I’m nearly done porting all the notes, having used the most recently revised PDF generated from MuseScore. Some unstructured thoughts follow.

The volta look nice

As far as I can recall, manipulating the volta to create first and second endings was a bit of a chore for me. I personally prefer to minimize clicking and dragging in my life, and volta extension / adjustment involved quite a bit of both.

That’s not to say it was easy in PMX – I kept getting the notation wrong and causing MusixTex to spit some error about volta collision at me. My solution was at odds with the available documentation, which suggests you ought to “Vx” / “Vb” (to close a volta) at the end of its last measure. I could only make the error disappear by placing it at the start of the first unenclosed measure.

But once it came out, it was perfectly aligned – no finagling needed.

After some crying, the stock volta as typeset by PMX / MusixTex come out quite nicely. Please ignore all the collisions with other elements!

I feel empowered to make some revisions

The triplet depicted below used to zip by much quicker. When I paused to think about it, it wasn’t a zoom so much as a thing that elapsed in a quarter-note in a relatively quick piece.

The triplet gets its full due – not as a cluster of 64th notes, not as a grace group; just a full-fledged triplet.

I fixed a counting error; in the following phrase, the final eighth (Eb7) in the measure wasn’t previously present. I had to think a bit to catch this one.

You need to swing those chords!

I typed out the full voicings for the high “Oooh ~ ooohhh” vocalizations near the end of the chorus (rather than messing with the counts to reflect what the performer will actually do). It feels good to see these on the page.

Bar 64 is impossible to faithfully execute – but it sure does look nice on the page.

But most things stayed the same

The vast majority of the score is unchanged. A small portion of the score is deliberately left in a possible suboptimal state, actually, like this phrase (and all its rhythmic siblings) in the latter part of the verse:

There should be a lot more tied eighths here.

I deliberately left these intact because I like the look of these pseudo-triplets.

Some things need tweaking

Once I finish typing out the notes, at the very least, I feel compelled to fix some typographical nits here and there. These can only fester for now until I muster up the motivation to fix them.

In blue: to avoid overlapping the C flat octave with the rising voice below, I manually overrode the alignment and shifted the octave one note to the right. I’m fairly sure I can make the slur follow, but I’m a little surprised this isn’t automatic.
In purple: this difficult chord is actually assembled together from two logical voices and involves quite a lot of manual alignment override. The result is still subpar in that the flat accidental overlaps the D flat unacceptably.

In the most recent MuseScore revision, I close the cadenza with a bar of 17/4. This actually brings the whole arrangement shockingly close to the timing of the original song, but was neither fun to execute nor fun to hear. I elected to preserve common time in this revision and express the figure as…a 24-tuplet instead.

The file comment here actually says “I need to rewrite this.”


188: Occam’s Razor

The worst thing to happen to me in New Zealand took place before I even cleared passport control at Auckland Airport: my phone and I disagreed on the exact representation of my unlock pattern, and I was eventually forced to factory reset it and burn a 2FA backup code to regain any access whatsoever to my account (but the real pain happened immediately after, during the vulnerable setup process of the phone. A post for another time).

Thing is, on my Moto Z2 Play, I draw my unlock pattern every 72 hours. So some of that is muscle memory, but certainly not all of it – the defining feature of my unlock pattern is that it travels roughly from the southeast to the northwest (opposite how I write from day to day – left to right, top to bottom) and doesn’t use all the notches.

So when I was suddenly unable to convince my phone to let me in, it was reasonable to chalk it up to

  1. sleep deprivation,
  2. negative stress-driven feedback loop, and
  3. overestimation of exactly how well I knew my pattern.

Occam’s Razor dictates the above must be truth (absent better evidence). To escape my misery, I switched over to a Pixel 2 and set only an unlock PIN – a dead easy one at that.

And that’s where I started blunting Occam’s Razor.

I installed an update for Google Play Services (via the settings menu) and restarted my phone. Once it came up, it rejected my PIN several times. I made at least two attempts in which I was 100% sure I didn’t fat-finger the PIN somehow; I would swear on a bible that I had it dead to rights.

Time passed, several attempts were made, and uncountable oaths escaped my lips.

I spent quite some time in happy hour trying to reproduce it – and I got it once towards the end. Over dinner, I did it twice more; on the second reproduction run, I had armed my unlock PIN to “2468” and handed my phone to my manager, asking him to unlock it. He saw with his own eyes that I spoke truly. “2468” failed once for me and once for him – and then it unlocked the phone on the third try.

Unfortunately, this is where I started hitting inexplicable lag and jank, so I was unable to take a proper bug report. This issue only surfaces once every few reboots, so it’s hard to get a reproduction rolling. But I am not totally crazy. This is an absolutely awful bug and I am currently not a happy bunny.


187: fanfiction in the extreme

I recently rewrote naklo to make some breaking changes. The rewrite is complete and I’m proud to release naklo v3 (yes, 3.0.0 in semantic versioning – this release is again incompatible with previous implementations of naklo). Naklo v3 offers two big things:

  1. A brand-new metadata format that does away with using magic naklo-span tags everywhere. Given that tagging operations can be fully specified by a range and the tag name in question, I can now offer primary grouping by either range or by tag name.
  2. naklo is now written in Cython.

The fanfiction

One of my unit tests dry-runs a detailed tagging operation – essentially simulating tag application on a whole album. Instead of using foo and bar placeholders (or prequel memes), I elected to come up with an entire fictional album featuring my favorite pianist.

Blechacz previously spoke highly of Michelangeli on the record; curious, I purchased the remastered version of Michelangeli performing concerti by Ravel, Rachmaninoff, and Haydn. I was immediately fully taken in by Michelangeli’s Rach 4 – despite already having recordings by Ashkenazy and indeed by Rachmaninoff himself, I was surprised to find Michelangeli’s account far easier to comprehend.

It has then always been my dream to hear Blechacz take on the Rach 4 himself – I am convinced he could produce an interpretation that moves me as much as Michelangeli’s does.

But, in my opinion, the logistics of releasing a Rach 4 recording are unnecessarily difficult. The Rach 4 is the least popular child among the 5 Rachmaninoff works for piano and orchestra (no citation – but the only possible competitor here is the first concerto, and I’m quite sure that one gets programmed more often than does the fourth). The brave artist attempting to conquer a Rachmaninoff cycle must contend with the placement of this concerto to ensure that he or she doesn’t tank sales badly.

That brings me to this unit test. Blechacz seems unafraid of presenting difficult or more niche repertoire, but I approach this from a business perspective. To greatly increase the album’s chance of survival, the best placement of the Rach 4 in a complete cycle is to pair it with the single most popular concerto – the second.

From there, if you plan to record the Paganini Rhapsody as well, you would be well-served by pairing it with the first concerto (bookends!). The third concerto, almost hysterically famed for its difficulty, will survive just fine on its own (perhaps with other miscellanea if the artist is so inclined). If you do not count the Paganini Rhapsody toward a complete cycle, then the third concerto and first will pair together quite nicely.

I threw in two random works by Maurice Ravel just for the sake of it. I cannot justify those from a business perspective – I just thought it would be cool to hear Blechacz on La Valse. The menuet is a bonus chosen at random to bring the encore count up to two.

The naklo takeaways

  1. Just by eyeballing the Cython profiling, there appears to be no discernible benefit from actually passing my code under Cython. The type annotations appear to provide negligible speedup, and certainly I use vanishingly few C primitives to justify writing any cdef functions at all.
  2. The tag block identifiers are unfortunately named: there’s no reason whatsoever to call them classic-tag-block and inverted-tag-block. In the first place, naklo v2 did not give particular precedence to spans or tag names; the two were of equal importance in any given tag block (except when naklo-span was elided – in which case the tag block applies to all songs). If anything, the semantics of the inverted-tag-block are closer to the v2 form, since out of habit I always specified the naklo-span first if it was necessary. Better names: span-first-block and tag-name-first-block, respectively; self-describing and less weird connotation of “this is more normal than the other.”
  3. Unit tests are an extraordinary boon to the developer in a hurry. Having a simple public API in my head, writing the unit tests to fit allowed me to zero in on quirks and bugs before proceeding with the rest of the implementation (which was admittedly trivial once the NakloController class was finalized). The unit tests provided great peace of mind in assuring me that my implementation was more or less sound.

naklo v3 is now live and in active dogfood for myself. I love it, if I do say so myself!



It’s 16 January 2020. I spilled a mug of (warm) water all over my new ThinkPad T495.

Oh shit

To its credit, this thing didn’t panic immediately. I did the panicking. I powered it off as quickly as possibly, turned my desk lamp to glare at the spill spreading across my IKEA desk, and ran to grab my bath towel.

I dabbed furiously at the keyboard a few seconds before upending my laptop completely to drain. I also started wiping to make sure the spill didn’t spread too badly off the desk.

I lay supine on the bedroom floor and held my T495 over my face, playing a perverse and sad game of “upsy-daisy.” I stayed there for at least fifteen minutes, alternately shaking and blowing to chase most of the water out.

The damage

Not much, amazingly. I (unwisely – you should probably never do this) powered the T495 on and took checksums on my home directory. They were all fine; evidently the water hadn’t seriously damaged the SSD, CPU, or RAM.

However, my discrete left mouse button was inoperable. About ten minutes of uptime later, my discrete right mouse button also ceased to work.

Note that the Lenovo platform specification for the T495 indicates a “spill-resistant” keyboard. I wasn’t aware of that and was enormously relieved to read it. Thank goodness for that.

The aftermath

I intend to send the laptop for repairs (if I succeed in navigating the Lenovo support labyrinth). In the meantime, I’m writing this post from my work Pixelbook, logged in via my personal Gmail account. What happens in the meantime?

I will have a hard time accessing my backups

The external drives floating around the apartment are all encrypted with LUKS. At time of writing, this makes them incompatible with Chrome OS. Practically speaking, this means I need to access them from a similarly equipped Linux installation. I can either

  1. go to work and cable them up to my work computer or
  2. drive to my parents’ house and cable them up to my old computer.

In either case, the workflow will involve hooking up my drive to a temporary pass-through computer and selectively exfiltrating data that I need into my Chromebook via rsync-over-ssh in Crostini.

Of course, the day after this initial snafu, I managed to upgrade myself to a dev version of Chrome OS in which Crostini is broken. Good job, me. Unless I trim the exfiltration step and elect only to write down the most important passwords (!!!), my backups are functionally dead in the water.

The following effects ripple out (at least in part) from this one.

I have no access to my music

I tend obsessively to my local music library. As such, I have no premium subscriptions to streaming services. I would most likely take up a subscription with Primephonic, but in a pinch, the selection on Spotify will do. But none of this is permanent – ideally, I’ll soon be reunited with my data.

While Spotify has access to a lot of stuff,

  1. it lacks gapless playback,
  2. it’s laden with ads (my fault for not having a premium subscription, I concede),
  3. it has a huge selection but still misses albums that I went out of my way to collect, and
  4. its searching / filtering are vastly inferior to the facilities provided by Quod Libet.

I have no primary source of truth for my locally-based work

Some local-only work (e.g. my photo backups, some hacking work, and my expenditures SQL table) live tethered pretty exclusively to local storage. I treat my external backups as a last resort whose integrity is not verified often enough to be 100% trusted to take over at any time as a source of truth.

In any case, I don’t like the prospect of making an edit to one particular backup and then having to flush the results back into my “source of truth” storage when my laptop comes back from repairs. The net result puts most of my local work into limbo.

I can only easily access accounts for which I happened to memorize the password

Thank goodness that my memory extends to the password for the present account from which I’m logged in.

Luckily, this generally includes most of my general-purpose financial accounts and even my Facebook account (extending me access to Messenger and Instagram). reddit and Github are included for free, though they shouldn’t be – I’ve meant to change their passwords for a while now. If anything, this is a security liability on my part.

There’s something a little sad about rebuffing the Chrome browser’s well-intentioned offer to memorize my passwords for me.


My backups are insufficient

A cursory backup on an undefined cadence with further undefined verification runs is not sufficient. For all the data I proudly shuffle around, the above section lays bare a glaring flaw: without a source-of-truth to lead the backups, the backups themselves are inert and useless.

This is one of the selling points of cloud work and cloud backup. Not only do you get transparent replication, but you (typically) also get on-the-fly reconciliation, ensuring that your source of truth is…well, in the cloud, and clear to you at all times. If I were to start editing random stuff on the several mirrors of my data I have lying around, the reconciliation and leader-subordinate relationship gets murky.

Furthermore, the lack of a clearly defined backup cycle (together with a verification scheme) makes it hard to tell when it’s safe to rely on a backup.

What will I miss (from the original source of truth) if I restore from backup X tonight?

Without verification and some kind of logging, the above question is impossible to answer with any confidence. I don’t even need that much confidence in answering it – it’s not a huge issue WRT me – but it’s still annoyingly undecidable.

I’ve marooned myself on a technological island of my own making

For all my high-minded pontificating, this experience has really damned my philosophy. It’s not sufficient to say that I can bootstrap myself back from a pinch; I need to be able to do so easily. I opine that open implementations without open standards go hand in hand: each is (mostly) useless without the other. It’s all very well and good that I use a standard-fare infrastructure like LUKS – but it’s worse than useless when I attempt to switch to Chrome OS, because Chrome OS doesn’t support it ATOW. I’m now nursemaiding a couple of hard disks functionally full of gibberish.

The relative abundance of my locally-grounded work is also damning. To continue updating my personal expenditures, I’ve commandeered my to-do list on Google Keep and started writing CSV in it. This will need to be flushed locally to my source-of-truth once my laptop gets back from repairs. More generally, my refusal to use a cloud-based password manager has caused undue hassle for me in the past few days. If an emergency came up right now, it’s not clear that I could handle it without driving into the office.

I’m a damn clumsy fool

In the first place, this should never have happened solely on the grounds that there’s no reason ever to upend a mug of warm water on my laptop. I’ve had similar problems at work in the past year (having spilled coffee all over my desk at least thrice now). I need to fix this urgently.

Lenovo makes wonderful stuff ❤️

I have no right to expect that my ThinkPad T495 could boot at all today – but it still does (and I just checked it), only a little worse for the wear. It’s clearly a trooper – one that I look forward to having repaired and back up running.

Bon voyage to the depot, flaglock6!


185: two-note wayfinding

I heard a delightful song on KCSM (the Bay Area’s local Jazz station) this afternoon driving home from San Bruno.

  1. It was arranged for more than one vocalist (at least one high-register and one low).
  2. Other performers included a backing rhythm section, bass player, and piano.
  3. It was heavily swung and interspersed with free, improvisatory singing.
  4. Its chorus was always delineated with the near-full-measure hold of the phrase “Soul food,” (for human readers, “Souuuuuuuul Food!”) sung D flat to F (7/8 + 1/8).
tl;dr - the winner was Horace Silver's Home Cookin', performed by Lambert, Hendricks, and Ross.

I fell in love with the arrangement and the peppy performance. I wanted to purchase this song, probably the whole album. The universe chose this past day (28 December 2019) to confound me.

The song was unknown

The DJ didn’t announce the song immediately after it aired, passing directly onto the next song without comment. I didn’t want to stick around in my parked car for a whole other song just to catch a title. No problem. I could check the past playlist on the KCSM website.

The song was omitted from the KCSM playlist

It wasn’t there. I knew I was looking in the right neighborhood from the appearance of “Is You Is Or Is You Ain’t My Baby” performed by Catherine Russell. None of the entries after that song (played before 17:15) fit the bill. (Prudence forced me to check almost every single one of them for vocal work.)

Still no problem, right? I could consult Google-dono about the lyrics.

The lyrics weren’t readily Google-able

Google is famously (and scarily) good at distilling meaning out of word salad. It’s even better at performing simple reverse searches on lyrics, provided you give it enough words to go on.

The phrase “soul food” turns out not to be enough to go on. Aside from being the title of a 1997 film of the same name, it’s also

  1. the title of a song by Goodie Mob,
  2. the title of an instrumental by Cyrus Chestnut, and
  3. the subject of many other songs, according to some lyric indexing websites.

Trying several variations on “soul food jazz song,” “soul food swing,” etc. didn’t help.

The final resort

KCSM retains a limited archive of past playlists. I sought out the show around the 5 PM timeframe and scraped the MP3s served out of AWS (thanks, Firefox Inspector and curl!). I sat down and scrubbed back and forth, looking for the right time. I anchored on Art Tatum and worked backward. I hit indescribable vocal bubbliness and knew that I struck gold.

I activated Google Assistant and held her up to my speakers. The result came back almost immediately. I got to know Lambert, Hendricks, and Ross a little better.

What could have gone better

It’s a happy ending overall, but…

  1. I should have picked up faster that the lyrics were obscure or possibly not formally existent. AFAIK I listened to a random vocal setting of a Horace Silver instrumental; this explains why nobody’s uploaded lyrics for this.
  2. I shouldn’t have sunk my entire evening into tracking this song down from just two notes (D flat and F) and distilled it into this write-up.



“Young man.”

Mark paid her no mind.

“Young man!”

Mark puffed out his chest and heaved the package a little bit, holding it securely against his person. He fractionally quickened his gait, homing in on the UPS store.

“I say, now! Young! Man!”

Mark was starting to have a hard time feigning ignorance. Her tiny tethered dog thoroughly assured that.

“Young man! That’s quite enough!” The meddlesome lady had caught up. Her fire-alarm dog was now nipping at Mark’s heels. She planted herself firmly between Mark and the UPS store. He couldn’t casually squeeze past her, not with the rather bulky package in his arms.

Mark flashed his best innocent, unforced smile. “What can I do for you, ma’am?”

“You can tell me what’s in that box!” The yipping was unceasing. The clerk behind the counter looked up, a frown growing on his face.

Mark inhaled gently. “With all due respect, ma’am, that’s really none of your business. It’s one thing to have a warrant, but otherwise, if you’ll excuse me – ” and Mark deftly sidestepped her, entering the store. The lady gasped. The yipping intensified.

The UPS clerk did his best impression of a glaze-eyed, indifferent man, and began processing Mark’s package.

“What seems to be the trouble, ma’am?” Mark saw blue in his peripheral vision. His eye twitched.

“Oh, officer, officer! That horrible youth” (both of Mark’s eyes twitched at this) “refuses to show me the contents of his suspicious box!”

“But ma’am, he’s not actually obliged…” the well-meaning police officer trailed off, doubtlessly tanning his face on the high-powered glare meeting his gaze.

The blue sighed. After a beat, it grew in Mark’s periphery. “Sorry, sir, but – ” and Mark turned around, locking eyes with a kindly-looking man of moderate stature. “Could you please open up the box? You’d be doing me a favor.”

The UPS clerk paused. Mark remained silent.

“Fine,” he said, retaking his box into his arms. “But only to you, in the back room. Do you mind?” The UPS clerk shook his head, gesturing at the rear door.

Mark and the kindly officer ducked into the back room. Mark stopped and pivoted to face the officer.

“All right. Big favor to ask. You absolutely can’t show this to the old lady.”

J39M: this was supposed to end with something about rubber ducks. The point is that Mark definitely had something to hide, but it would have been something utterly inane.

183: the towel riddle

I was showering one day when I was hit with a paranoid thought. Said thought put down roots and blossomed into a full-blown riddle. When I told it to my DnD circle, they viciously put it through the wringer and helped me refine it quite a bit.

The riddle

After your workout, you go to the locker room for a shower. Your gym is generous and provides free towel service, so nobody who comes to this gym brings their own towel. Instead, there’s a common pile of towels for anyone to grab in the locker room. Common courtesy dictates that

  1. Towels have no owner until touched by a user.
  2. Once touched and taken from the pile, a towel logically belongs to the touchee and should be considered theirs.
  3. Towel users relinquish ownership of their towels by depositing them in the return bin (to be cleaned etc. etc.).
  4. Ownership is not transferable – touching an owned towel makes you a thief.

You grab a towel from the pile. This towel is now yours since you have touched it and removed it from the communal pile. You enter the shower, hanging up your towel on the peg just outside your stall. You shower up and finish. You reach for the peg, ready to dry off, but the person in the neighboring stall interrupts you.

“I’m sorry,” he or she ventures, “that’s my towel.”

“There must be some mistake,” you reply. “I definitely left my towel on this peg.”

The important meta-facts

The riddle-teller digresses here to lay down some truths not directly presented by the story.

  1. Neither you nor your neighbor are lying. Both of you are telling the truth in good faith. Neither of you is actively attempting to deceive the other.
  2. Neither you nor your neighbor are thieves, nor do either of you intend to become such.

The less important meta-facts

Here are some silly facts that try to pre-empt the more outlandish answers. (Hopefully they don’t just distract the riddle-hearer.)

  1. The towel pile cannot be annexed all at once – i.e. you cannot move the whole pile a centimeter and claim them all. Assume that nobody takes more than one towel from the pile per try to the gym.
  2. Leaving the gym trivially releases your ownership over any towels you’ve taken. Removing them from the gym makes you a thief, but assume nobody does that. Also, nobody lives at the gym to slowly take all the towels.
  3. The exact dimensions and number of shower stalls is mostly irrelevant – however, it may help to imagine both you and your neighbor as not having wall-side stalls.
  4. There is no intentional wordplay above. Only the dialogue between your neighbor and you has significance embedded in the wording, but it can still be rephrased validly in many ways.

The answer

My answer was that as you stepped in the shower, you hung your towel on the peg between you and your neighbor. However, your honest neighbor wasn’t there just yet – some other person (let’s call him or her Taylor) was showering in the adjoining stall. Taylor hopped into the shower, hanging his or her towel in line with your convention (depending if Taylor is on your right or your left – anyhow, Taylor hung his or her towel a whole stall away from you). However, once Taylor finished showering, Taylor mistakenly took your towel by mistake and went away.

At this point, your honest neighbor hopped into Taylor’s old stall. Seeing a towel hung up on the far peg, he or she chooses to hang his or her towel on the peg where your towel formerly hung. Therefore the towel is in fact your neighbor’s, and you did indeed leave your towel on that same peg. Unfortunately, you were inadvertently about to make a thief of yourself (but the dialogue stops just short of that).

Someone ventured a better answer, actually, which requires far less explaining: your towel fell off the peg just before your honest neighbor stepped into the adjoining stall. The same result applies.


182 – approximating 9 as 10

A few nights ago, I asked myself

Is 10 a workable substitution for 9?

I don’t quite remember the context, but I think it stemmed for wondering how far I overshot products when multiplying several things rounded up from 9 to 10.

I thought about it and set an arbitrary bar for goodness: if we stay within one order of magnitude of the true answer, then I consider 10 a good approximation for 9. Fortunately, this equation is easily expressed and easily solved:

10^{x} = (9^{x})(10)

for which we obtain x = 21.854. I believe this means that in any given product, you can up-round 9 (to 10) for 21 terms and still stay within an order of magnitude of the correct answer. So by this arbitrarily loose metric, it’s perfectly acceptable to round 9 up to 10 to perform your calculations. I rarely do products of 21 terms anyway.

The situation sours quickly if we tighten the goal, though. What if we want to come within 10% of the true answer?

(9^{x})(1.10) = 10^{x}

Unfortunately, solving for this yields x = 0.905. That is, you can’t even perform a single 10-for-9 substitution in any product without inflating your result in excess of 10%. You will always overshoot unacceptably. This should have been trivially obvious to me, but ah well. What if we accept a 30% error?

(9^{x})(1.30) = 10^{x}

We find that x = 2.490. We can make 2 10-for-9 substitutions in any product and come within 30% of the true answer – that’s not bad.


181: Quick lessons with firejail

I’ve been meaning to install firejail for a while but never got around to it, making all the imaginable excuses around possible impact, utility, etc. etc. I finally bit the bullet and installed it last night. I read the manpages and the associated resources on the Arch and Gento wikis. I applied profiles to feh, zathura, and my local installation of Firefox Nightly. What did I learn?

Running things out of your home directory is a little exceptional

I don’t keep Nightly in any system-wide location – it lives in my home directory, and I invoke it with my usual slurry of shell functions (stick it in a particular memory cgroup hierarchy, ground its stdout and stderr into /dev/null, and background it).

Upfront: firejail’s firefox profile prohibits access to our home directory (save for Downloads, .cache, .mozilla, and possibly others). My Nightly installation lives in ~/Documents – unreachable WRT the jail.

My first experience with firejail, then, was a frustrating head-to-desk affair where it stubbornly refused to execute /home/kalvin/Documents/Nightly/firefox. The error message read “No suitable … executable found,” which didn’t help at all even with the debug messages switched on. I could see it reporting an attempted exec call on the file, so it wasn’t some silly path expansion problem, but it didn’t offer up any other helpful self-diagnostics.

Of course, the resounding silence from Google staring back at me told me that this was definitely me in the wrong somewhere, so I dove back into the configuration to understand the imposed access controls. The eureka moment happened when I wrote my own firefox.local profile allowing access to ${HOME}/Documents, which worked at last!

(Ultimately, I erased the local config and just moved Nightly into my downloads directory.)

There’s (usually) no reason for my graphical applications to access the controlling terminal

My favorite bash function is called “quiet.” Succinctly,

function quiet() {
# Background argv, grounding std{out,err} to /dev/null.
"$@" 1>/dev/null 2>/dev/null &
# This is even more succinct as
# "$@" &>/dev/null &
# but I understand that is a bash extension, not a POSIX shell
# specification.

Upfront: feh will call tcsetattr() (I didn’t research why) if it detects its stdin connected to a tty. I have no use for terminal interaction with feh, so I might as well cut loose its stdin.

My last firejail adventure of the night was attempting to apply the feh profile. I always use feh by calling it from my ever-present terminal on the directory or file I want to view. Unfortunately, when I tried to run it in firejail, it started almost immediately in a frozen state. The problem disappears if I don’t background the process.

After lots of hemming and hawing, I noticed it also complained (after getting unstuck) that a call to tcsetattr() failed. The feh manpage explains that feh accepts input from stdin to allow for some graphical control. I don’t need this, and all it manages to do is net itself SIGTTOU (because I’ve backgrounded it).

I have amended my favorite function to

function quiet() {
"$@" 1>/dev/null 2>/dev/null </dev/null

and we’ll see if that works all right for me.



I reproduce the notes I kept for my Chicago trip over the new year in the paragraphs below. Content is lightly edited for readability.

Saturday sketches

  • Chicago History Museum [inserted above below bullet]
  • The Field Museum
  • Hot dogs behind (Kim & Carlo’s)
  • Chinatown

Sunday sketches

  • MSI! [Museum of Science and Industry]
  • Magnificent Mile, Cloud Gate [this was bumped below the riverwalk]
  • McCormick Bridgehouse [skipped this]
  • Chicago Riverwalk [did the whole thing, walked all the way out to Lake Michigan]
  • Chinatown [dinner at Daguan Noodle]

Amtrak 31 Dec

We crossed the Mississippi in complete darkness and stopped in Burlington, Iowa. The platform is so short that the second stop (made for coach passengers) is made with the locomotive protruding into a nearby level crossing. I saw one car pull up and visibly nope out by quickly performing an illicit three-point turn.

I had dinner with J, J, and K. J is going to Denver to visit his girlfriend. J & K are going to Salt Lake to ski. Salt Lake is only the first stop; Idaho follows for more skiing. J is a nursing student studying in Michigan; J & K grew up in Chicago.

Sitting in a darkened train compartment by yourself allows for a lot of introspection. [Probably I shouldn’t do it too much.]

Amtrak 1 Jan

Waking up to us backing into Denver Union Station is weird. Not sure how we ended up as such. Had breakfast with 2 retirees going home to Glenwood Springs plus a solo traveler who can work on the go. The solo traveler works for Cappex (sp?) and moonlights as a photographer. We joked lively about how camping out in Aspen as a paparazzo is doubtlessly lucrative. The lovely couple mentioned that Glenwood Springs has some awesome hot springs downtown.

Winter Park at Fraser looks like a lovely place to go when not in the dead of winter.

I reckon we passed through the Rockies and wound between the green bounds of a few national parks (according to Google Maps ATOW). The gorge / canyon path was the best, but the hills aren’t so bad. The view from the observation car was spectacular. It’s a pity my phone camera [Moto Z2 Play stock camera app] doesn’t remember manual settings as configured.

Had dinner with a Chinese father-son duo and M. The duo flew straight from Beijing to Chicago and are bound for Salt Lake. M was going boating with a friend in the Bahamas but got screwed by American Airlines. M changed his plans accordingly and decides to go to SF. He works for Ocean Mist Inc. in packing / produce and lives in Castroville.

Passing through the narrow mountain carved for our tracks in the dark is exciting and intriguing. The landscape in Utah looks almost a little sinister at night. I’m afraid to turn on any of my lights for fear of exposing my compartment to the outside world.

We were some distance outside Helper, UT (20+m?) and deep in the unlit countryside. We passed under a shadowy road bridge and I saw the most stars I’ve ever seen in my memory. Orion’s belt presented itself squarely toward my compartment. All around were dozens of acolyte stars, brighter than I’d ever seen. We rounded a bend and my compartment faced a not-so-bright patch of sky, taking Orion and co. out of sight.

[Around this time, I realized I was coming down with a cold – my throat was armed and ready to give me a bad time.]

Amtrak 2 Jan

I slept fitfully. I woke around 2:30 Pacific and realized we had crossed into Nevada. I woke again after 4 AM at a station stop. My throat felt marginally better (but still bad).

I woke at last at 5:50 AM to use the lavatory. The train was zooming across the plains at the time. I could see a gorgeous crescent moon flanked by 2 stars at an angle. It was a beautifully symmetric formation, the brighter star at 2:30 and the dimmer at 7:30 (so not straight up / down or left / right). The entire formation was visible at 9:00 when Google Maps indicated we were headed due West. The sun peeked over the mountains around 7 AM somewhat south of this ensemble.

I had breakfast with a family of 3 – J, C, and A (3.5 yrs). They had spent 1.5 weeks in Denver and were headed home to Emeryville. They plied me with horse trivia (J had an amazing ability to retain reading) and astute observations on the industrial buildings we passed in Nevada.

179: CRA and cgroups

Crazy Rich Asians

Sis rented the film two nights ago and we watched as a family. It was better than I expected. I was mostly concerned that the milestone of Asian representation in a large-scale Hollywood production was overshadowing all the other good points in the film. Everyone I’ve spoken to mostly has technical nitpicks with the film (e.g. Ah-ma‘s distinctly mainland-esque accent – is this really a problem though?) and the strange anti-spread of “diversity” in the Singapore depicted onscreen.

I for one enjoyed the film enormously. I appreciate no-frills romances, even when no gimmicks are involved. Dress up a story appropriately and you’ll win me over just like that.

I do nag myself a little about on what terms did I appreciate CRA? I was raised on a modest amount of Mahjong, so I understood full well the significance of the Mahjong parlor sequence and felt all the more moved for it. Would a non-Asian audience, less exposed to Mahjong, take it the same way? I wager most would walk away (justifiably) confused, only inferring from context what transpired.

Actually, I confess here to being an inadequate Mahjong player – I didn’t read Rachel’s hand quickly enough to positively affirm what she had done. But from the context I thought her point was clear.

This is all a distraction – the film makes sense to and resonates emotionally with me. I walked away with satisfaction that I had fully grasped the story being told.

Firefox cgroups annoyance

On occasion, Firefox will eat all my memory. This does some awful things to the system at large and takes a while to recover. Eventually I relegated it to its own memory hierarchy out of annoyance; my launcher aliases have all been prefixed with cgexec. Now, Firefox is only allowed to chew through 8 GB of memory (ha!).

Firefox presently uses several different processes to perform different purposes (or so I deduce from their names):

[j39m@SERN ~/Downloads]
$ pstree -aTp 8346
firefox,8346 -P default-1473025815439
├─Web Content,8444 -contentproc -childID 1 -isForBrowser -prefsLen 1 -prefMapSize 203416 -schedulerPrefs 0001,2 -parentBuildID 20181121183716 -greomni/usr/lib64
├─Web Content,8529 -contentproc -childID 2 -isForBrowser -prefsLen 79 -prefMapSize 203416 -schedulerPrefs 0001,2 -parentBuildID 20181121183716 -greomni/usr/lib6
├─Web Content,8540 -contentproc -childID 3 -isForBrowser -prefsLen 79 -prefMapSize 203416 -schedulerPrefs 0001,2 -parentBuildID 20181121183716 -greomni/usr/lib6
├─Web Content,8863 -contentproc -childID 6 -isForBrowser -prefsLen 4920 -prefMapSize 203416 -schedulerPrefs 0001,2 -parentBuildID 20181121183716 -greomni/usr/li
├─WebExtensions,2894 -contentproc -childID 17 -isForBrowser -prefsLen 7076 -prefMapSize 203416 -schedulerPrefs 0001,2 -parentBuildID 20181121183716 -greomni/usr/l
└─plugin-containe,8928 /home/kalvin/.mozilla/firefox/pgxfzusi.default-1473025815439/gmp-widevinecdm/ -greomni /usr/lib64/firefox/omni.ja -appomni

This past week, something started leaking memory while I was browsing Google Maps. I noticed the system slowly dramatically before the OOM-killer kicked in and decided to kill the WebExtensions process.

The immediate aftermath is not visible: since none of your content rendering processes are killed, you might not even notice anything wrong. I have 3 addons of consequence: NoScript, HTTPS Everywhere, and Vimium. Vimium mostly ceased to work (visibly so) and would not work until I had opened and closed a few tabs here and there. (I don’t know the exact mapping from tab to content process to WebExtensions process – but things were messed up).

The more exciting fallout was when I opened a Bloomberg article and was suddenly treated to an irksome auto-playing ad. I smacked the Alt+M and opened the NoScript menu with annoyance. It drew a blank – that was when I noticed the toolbar icon was superimposed with a question mark, indicating a non-functional NoScript.

So far, no sequence of opening new / closing old tabs has recovered this. The next step is to restart Firefox to see if that fixes things. While I hesitate to prognosticate, it follows that any reliance on your addons for security must always be tempered with some understanding that the architecture is not perfect.

I hesitate to prognosticate – so I will refrain – but I believe this reproducible by

  1. Opening Firefox,
  2. Finding the content process with pstree (not sure why pgrep is showing a different cmdline),
  3. Killing it with your favorite signal (SIGKILL to simulate OOM-killer?), and
  4. Checking if NoScript dies.