Is Neither Discuss

Every now and then I see some more of the Muskrat Standom’s effluent ooze past my eyes and all I can think is, kid, that boot’s never gonna lick you back.

Timnit Gebru recently wrote about Effective Altruism for Wired, where she correctly notes that it’s all self-serving nonsense, “promising an “unimaginably great future” around the corner while proliferating products harming marginalized groups in the now.”

“Some of the billionaires who have committed significant funds to this goal include Elon Musk, Vitalik Buterin, Ben Delo, Jaan Tallinn, Peter Thiel, Dustin Muskovitz, and Sam Bankman-Fried, who was one of EA’s largest funders until the recent bankruptcy of his FTX cryptocurrency platform.

… and she’s right. But I also think that there’s a dynamic at play that she’s elided, an ideological metagame at play.

In his 1963 speech “Wealth And Poverty“, Galbraith observed that “the modern conservative is not even especially modern. He is engaged, on the contrary, in one of man’s oldest, best financed, most applauded, and, on the whole, least successful exercises in moral philosophy. That is the search for a superior moral justification for selfishness. It is an exercise which always involves a certain number of internal contradictions and even a few absurdities”.

This was penned before social media existed, obviously, and long before it was thoroughly weaponized, so it’s understandable how quaint it seems today. How could Galbraith have anticipated the rise of the postmodern conservative, for whom power is self-evidently its own justification, for whom the whole ideas of truth or moral justification are laughable as anything but a tool for retaining that power?

There’s a particular strain of technically-competent, ideologically-adrift pseudointellectual who somehow just stops asking questions the moment they’ve got a mental model that “makes sense” to them. You’ve met their flock on the hellbird and they’ve got a prominent hive over on the orange website, but you’ll find them in any techno-libertarian circle where a dash of cleverness mixed with the facile reasoning that comes with graphs in Econ 101 is praised until it becomes a self-reinforcing cycle, a nerd-posturing Coriolis force churning all these ideas together as they circle the bowl. “The market exists therefore systemic inequality obviously can’t” is the grade of reasoning I’m sure you’ve seen, championed by people happy to believe that the whole story is the just-so story they’ve just told themselves.

Setting aside inquiry and getting to work once you’ve got what you believe is a good mental model of a system is actually a pretty good approach to writing software, and if you’re both a competent engineer and a comfortably-incurious human being you can get a lot done that way. But politics and ideology aren’t software.

The code will never ask you, to whom is it useful that I believe this?

Are they really on my side?

Do I want to be on theirs?

I’ve said this before, that stories are weapons.

Software is quite literally an idea that you’ve taken out of your head and turned into a machine, a set of decisions and parameters that you, as a programmer, impose on people who will have little or no say in the matter. It is ideology and bias turned into power. If you’re happy to repeat things you’ve heard without caring about whether or not they’re true, what are you?

… and I will very happily bet you sixteen billion dollars – payable in six hundred years, assuming an average 4% interest rate – that exactly none of Musk, Buterin, Delo, Tallinn, Thiel, Muskovitz, or Bankman-Fried or anyone else whose net worth goes past the seven-digit mark gives a single fuck about “effective altruism”. Not one. They care about retaining wealth and power, full stop.

And that’s where Effective Altruism really shines. Not as a philosophy, but as a weapon.

Because Effective Altruism gives this entire class of technically competent people a mental model that “makes sense” and has a veneer of moral nobility to it while – conveniently – justifying not doing anything in the present that might inconvenience that wealth and power.

As an ideology, effective altruism is obviously a pile of nonsense. It’s what you’d end up with if you started with Scientology and replaced “thetans” with “dollars.” But as a tool, it’s fantastic: precision-designed to target people who are capable of understanding and changing complex systems and completely neuter them as a threat to that wealth and power.

Put differently: what effective altruism is most effective at is turning smart kids into political NPCs. It’s effective at making its adherents ideologically irrelevant, the world’s smartest, most useful idiots.

Technical Note: Bluetooth & Automatic Volume Adjustment

The symptoms for this are that:

  • You’re probably using MacOS,
  • and your bluetooth headset is automatically, seemingly randomly, muting and unmuting during calls,
  • but this muting is not reflected in the visible state of the call software,
  • leading you to believe that it’s a problem with the bluetooth headset itself.

The solution to this is to find and disable automatic microphone volume adjustment in the application.

I can reproduce the problem with the “Aftershockz” bone-conduction headset I’m quite fond of. While this problem was not easy to diagnose, the solution is one checkbox.

In more detail, many conference applications, Zoom and Teams in particular, have an “automatically adjust microphone volume” option somewhere under the hood. This will in some cases auto-adjust your microphone volume to zero, which in turn results in the operating system sending a signal to your headset telling it to mute the mic in the hardware. The hardware will do that, but this change of state will not be reflected in the zoom client.

And there’s just enough lag in this process, particularly if you’re trying to solve it by pushing the buttons on the headset that unmute you, that nothing quite happens with the immediacy that we normally expect from discernible causality. So you can end up with the software tricking you into the impression that your headset is in some bizarro state of hardware failure, which is not the case.

A quick google search suggests that this is an endemic problem at the intersection of “MacOS confcall apps (Zoom, Teams, bunch of others…) that try to be clever with volume management” and “Bluetooth devices that try to manage power aggressively”, and digging into the preferences to uncheck the “automatically adjust microphone volume” option solves the problem immediately.

Bluetooth has not worked right anywhere since Nokia died, I have no idea how any human who has not been heads down over this class of problems for decades would even start forming a mental model of what might be happening here much less how to fix it, and despite taking some pride in this there are times that I actively resent having to be really good at solving problems that shouldn’t exist in the first place.

Zero Again

Printing press bed sizes, circa the late 1800s.

Hillel Wayne has registered a strenuous disagreement with a bit I wrote in 2013 about zero-indexing and now I need have an internet argument because, I suppose, that is simply my nature. I’ve never met them, though I’ve enjoyed their writing whenever I’ve come across it, so if you’re invested in precision beef calibration that’s where I am. They seem like decent people, I feel like my case was misrepresented, strap in.

Wayne makes some solid points; I could stand to clean up and republish that article, something I was reluctant to do back when it took off and haven’t gotten back to. He definitely understates the case in saying “Most modern languages have at least some C influence in them”: in fact, approximately every programming language now needs to speak C, something I’m really only mentioning because it gives me an excuse to link up an amazing post that deserves a wider audience. But he falls into the same trap I railed against in my 2013 conclusion: retelling just so stories because it’s easy and fun.

I think his gist-of-it summary is not really a fair reading of the post, but the straw man I’m initially arguing against is that the claim that zero-indexing specifically-in-C “makes sense” because of an argument Dijkstra made is compelling and easy to retell, and obviously nonsense, even if Dijkstra’s argument was influential to later languages.

You can make that claim about Python, though, and you’d be right! Dijkstra’s interval-elegance argument did carry the day there. But I don’t know this because Python was born after 1982, or because elegant math, or because of some hand-waved set of conflated circumstances. I know this because I looked it up and found that Guido Van Rossum said so.

Literally everything having to do with computing was somebody’s decision, and we should not be confident we really understand the why if we can’t point at the person.

We really start wobbling on the rails further in, when… look: there’s no kind way to say this: that offhand sentence “wire formats like EBDIC and ASCII “started from 0″, since they considered the 0-byte a valid unit” is exactly what I mean, when I’m talking about things that are made up, that don’t even rise to the level of wrong. What is ‘valid’? Who’s they? How do we get from there to why?

I mention it because I know the real answer, and talking about the “wire format” of a character encoding when the first networked computers wouldn’t exist for another half decade is precisely what I’m getting wound up about here. The reason we have an all-zero-bits representation in those character sets is the same reason we use null as a string terminator, and that reason antedates mainframes, transistors and the Church-Turing Thesis. There are plenty of benefits to it that came about later! Definitely. But the reason we chose to have that in EDCBIC and ASCII (and Baudot, ITA2 and others of that era) is not “all the ways it turned out to be useful later”, and that reason was so that we could easily re-use punchcards.

Punching Down

(Fun fact, and this is a fact: around the time these standards were being hammered out, punch cards and related tooling made up 30% of all of IBM’s revenue. Consequently, one design constraint on EDCBIC that ASCII did not share was anchored in IBM’s business model: keeping too many holes in punch cards from being too close together, making the cards less likely to fail. Yes, I can find you a citation for everything in these parentheses.)

There are a few other arguments in there, rebutting claims I’ve made that I don’t really think I made, but I recognize enough contrarian in myself that I guess I’m obligated to be charitable with anyone pointing their contrarian at me. And charitable can be a job, for sure, but fair’s fair and a job’s a job. But there’s one larger point here, the real point that I wanted to make then and want to make now, that I’m not going to let go:

“Hoye’s core point is it doesn’t matter what the practical benefits are, the historical context is that barely anybody used 0-indexing before BCPL came along and ruined everything. […] I may think that counting 0 as a natural number makes a lot of math more elegant, but clearly I’m just too dumb to rise to the level of wrong.”

My point is not, my point has never been, that “zero indexing is bad”. My point is “believing and repeating uninterrogated stories because they sounded plausible to you” is bad, and I’m saying that because it’s really, really bad.

“We’re doing this like this because it just makes sense” is not just the general shape of made up stories I see programmers and engineers telling themselves all the goddamn time. It’s a habit that opens an attack surface on your soul. Smart people who’ve fallen in the habit of believing and retelling just-so stories about why things are the way they are, stories that are easy to digest and repeat, are incredibly easy to manipulate into building monstrosities, ignoring structural and systemic injustices, and acting in service of forces they don’t even realize exist because their little constructed reality seems to hold itself together.

Stories are weapons. I don’t know how to say this loud enough. Software is quite literally an idea that you’ve taken out of your head and turned into a machine, a set of decisions and parameters that you, as a programmer, impose on people who will have little or no say in the matter. It is ideology and bias turned into power. If you’re happy to repeat things you’ve heard without caring about whether or not they’re true, what are you?

Because this is where antivaxxers come from. This how the cryptocurrency cultists can bring themselves to believe their racist monkey cartoons are worth anything or ending fiat currency will stop war or any amount of all the other bullshit they believe while they’re destroy the planet and the lives of the people on it. This is why the world’s worst despots have buildings full of people spending all day on the far end of a VPN pretending to be Michigan soccer moms or Boston Antifa or Alberta Gun-Owners Rights advocates or any goddamn thing that helps them pour kerosene on anything that might set a democracy on fire. This is how smart, young developers can convince themselves that their work is morally and politically neutral while building the algorithms that, oops, hand a megaphone to fascists and turn explicit racism into implicit policy.

It’s this. And yeah, sure: it’s also other things. It’s complicated. I get it.

But it’s this.

  • Don’t be a dick.

Ok, sure. I could stand to work on that part. I concede the point.

Making Light

Hey quick question, is it a normal thing to be so used to struggling to make things work right that when you try something new and it works exactly right on the first try that you feel kind of strangely sad and empty? Or is that super weird and probably really unhealthy and hey mhoye are you OK maybe you should probably talk to someone? Asking for a me.

Anyway, today I took a desk lamp whose Halogen light had burned out, whose crappy transformer always made those bulbs sputter, and whose mildly art-deco appearance I’d always liked, and swapped it out to run an LED bulb off USB power. It took about an hour’s work to replace the light with an LED, the switch with a nice heavy clicky one and now the whole thing runs off USB-C instead of wall voltage. It emits no appreciable heat, and if these calculations are to be believed, will run for decades for a few cents per year, assuming I leave it on all the time.

I hadn’t really appreciated how big a deal USB-PD voltage negotiation was until I found out that the little chips that handle that negotiation are about the size of the end of a pencil, that if you include the USB-C port you can replace basically any low-voltage transformer with something smaller than a quarter.

The magic search string, if you want to try this yourself, is “usb-pd trigger module”, and if you have a soft spot for ideas like componentized repairability and separation of concerns you’re in for a treat. In a practical sense, this means that the negotiation about what power is delivered to a device can be tiny and inexpensive, and the decision about what’s delivering that power is a separate question entirely. So if you, like me, have seen good hardware killed by bad power, there’s a whole class of problems you can put behind you.

Another way to say that is, power bricks are obsolete now; in fact, anything that doesn’t run a motor or heat up a coil won’t need wall voltage at all. It also means refurbishing old electrical stuff just got a lot cheaper and easier. That old lamp that looked great at the thrift shop or your grandmother’s basement but hasn’t worked since the Cold War and will definitely burn your house down? For a few bucks it’s good as new, running cheap and cool.

And there it is: to my significant surprise, something was cheap, easy, and worked exactly as intended on the first try.

I don’t think I’ll be able to recognize myself, if this keeps happening.

Park’s Haunted


I would like to thank the City of Toronto for warning me away from this clearly haunted staircase that’s somewhere in the Don Valley.

Your Mulders, Coopers and Constantines get all the limelight, but as far as I’m concerned, in the fight against your garden variety supernatural malefactors, it’s the workaday maintenance and cleanup crews that are the real heroes.

Free() As In Going To The Mattresses

If you’ve updated a mainstream Linux recently and it feels like everything is inexplicably crashy and unreliable when you’re trying to get anything of substance done, particularly on smaller machines, it’s not just you.

Fedora and Ubuntu have both started shipping with systemd-oomd – an unproven SystemD OOM-killer – turned by default, on the desktop versions of their products.

To break that incantation down – “single-user desktop machines run the system daemon out of memory daemon by default” – into what it means and explain how we got here would be an exercise in ritual humiliation that I have no inclination to pursue. A 17th-century grammarian two centuries too early for the light bulb might glance at that phrase and ask how the infernal ‘machine’ in question had become so thoroughly curse-ed that the word “daemon” is in there twice, and that would be an excellent question. Here in the 21st century it’s still an excellent question.

But in short, an “oom killer” is a program whose only job is to shut down – “kill” in the parlance of Unix – processes that are hoarding enough memory that the stability of the system is at risk. That is, when the whole system is out of memory, and one process is threatening to starve all the other processes out. The idea was born at a time when computers were insanely expensive, and it makes sense as a tool in exactly one setting: as a last line of defence on multi-user systems being shared by people doing work the system operators don’t care about at all.

A consumer desktop machine’s operator is also their sole user, and who almost certainly cares about no part of this computer’s operation at all but the work they’re doing. It is makes precise opposite of sense, and shipping an oom-killer at all – much less an unproven, buggy oom-killer – in that context was incredibly irresponsible. Prioritizing “system responsiveness” over literally whatever the human at the keyboard of the computer they own was working on at the time is an insult. It guarantees that the user experience of Linux will always be “it crashes at the worst possible time, every time”.

You can turn off systemd-oomd – I say again, “the system daemon out of memory daemon”, because nonsense unix-terminology salad is apparently just how we roll now – with:

sudo systemctl disable --now systemd-oomd

(you get down) followed by

sudo systemctl mask systemd-oomd

(and you stay down.)

Max Planck said, once upon a time, that science advances one funeral at a time. Maybe the Year Of Linux On The Desktop isn’t coming until people who grew up with phones take the reins from the people who grew up on mainframes. Maybe that’s already happened, and the Unix on the Desktop we’re stuck with is MacOS.

Setting Back Up

Getting this thing spun back up was a bit of an adventure – as you are no doubt unfortunately aware: software – and I wanted a few things out of my new setup, among those being “self-hosted WordPress backed by SQLite”, “https”, “cleanly importing the old data” and a few other modest housekeeping improvements. I’m starting with a network-facing Linux instance here, and I’m going to gloss over a few pretty hairy steps like “set up Apache2”, for which I apologize. I’ve been doing this for a long time; if you’ve found your way here in the weeks or months after this has been published and need more detailed instructions, email me.

Once you’ve got your Linux instance and Apache stood up straight, the rest of the preparation steps are straightforward:

  • Get yourself WordPress, install it and drop the db.php file from WP-SQLite-DB.
  • Set up SQLite3, PHP 7.whatever’s-current and Certbot on your instance via your usual package manager, in my case Apt, and
  • Have Certbot do its thing.

“Have Certbot do its thing” was actually remarkable: I am just a simple unfrozen caveman and your “hosted services” confuse and frighten me, and it’s been probably a decade since I’ve looked into this space so being able to just… cause a cert to occur? Without needing to put a credit card into anything or fax things to companies whose software you wouldn’t run with a gun to your head? Amazing. The Certbot+LetsEncrypt process was so fast and painless that I was actually startled, and “pleasantly startled by software” is a rare feeling I deeply mistrust. But it worked right on the first try, pretty wild.

Getting WordPress working right with SQLite was largely the opposite of that. Who doesn’t love debugging other people’s PHP for db-constraint correctness problems, or hand-editing XML? Well, everyone. That’s who doesn’t love it. You, me, everyone.

Before turning on Apache you’re going to want to take WP-SQLite-DB up on their offer to put the DB somewhere sensibly non-default, you might need to toss it and start fresh later, but fortunately if your database is SQLite that’s “mv” and not “oh god now I need to re-learn how MySQL works again”, and that on its own will make the whole effort worthwhile.

Anyway, let’s get into the two bits of unpleasantness.

The first thing you’re going to need to do is manually clean up your old WordPress backup. I don’t know when this bug was introduced, but WordPress-current will not import its own backups correctly. Specifically, when there is a line break and tabs between <content:encoded> tags and the <![CDATA[[ tags that follow it, the importer will assume that tab-tab-tab-tab-<![CDATA[[ is the part of the content you’re importing rather than an indication that it’s encoded. This manifests itself in – if you’re lucky! – all your old blogposts losing most of their formatting on import. But that’s not the best part.

No, the best part is that once you import that backup, if you open thus-afflicted posts in the WYSIWYG editor they’re all blank. Fun race condition: if you touch the post with the classic text-editor option first, it assumes it’s all text, and escapes all those brackets for you when you switch to visual. But if you touch it with the visual editor first, it assumes everything in those CDATA brackets is invisible, and helpfully scrubs it clean for you. Super helpful either way, but opening the editor for a post you know exits, if imperfectly, on your sites and discovering that the editor believes that page to be blank? You need to have a certain mental model of this class of malfeasance to figure that out, I think, and I’m not sure if I should be proud I can connect those dots easily or annoyed that this is the person I’ve spent my life becoming.

Like I said, I’ve been doing this a long time. Get you a man who can do both.

Anyway: I’m sorry I don’t have a regression range for you, but if you’re importing old WordPress backups into WordPress 6 you will definitely need to inspect that backup XML file, get your regex on and strip all the whitespace between the <content-or-whatever:encoded> tags and the <![CDATA[[ bits or you’re gonna have a bad time dot gif.

At this point you’ve got a WordPress instance that you can stand up, data that you can import, and superficially this will appear to work. The problem you’re going to hit when you’re trying to configure WordPress through its usual menus – for example, disabling comments – is that saving those options gives you a dialog saying your changes have been saved, but they won’t have changed.

WordPress won’t show any errors in the UI, but will instead inform you of the problem by dumping a web page into your Apache logs. It looks something like this:

[Tue Jun 21 17:18:07.151358 2022] [php7:notice] [pid 12535] [client IPADDR:57288] WordPress database error <div style="clear:both">&nbsp;</div><div class="queries" style="clear:both; margin_bottom:2px; border: red dotted thin;">Queries made or created this session were<br/>\r\n\t<ol>\r\n\t\t<li>Raw query:\nUPDATE `wp_options` SET `option_value` = NULL WHERE `option_name` = 'default_ping_status'</li>\r\n\t\t<li>Rewritten:\nUPDATE wp_options SET option_value = NULL WHERE option_name = 'default_ping_status'</li>\r\n\t\t<li>With Placeholders:\nUPDATE wp_options SET option_value = NULL WHERE option_name = :param_0 </li>\r\n\t\t<li>Prepare:\nUPDATE wp_options SET option_value = NULL WHERE option_name = :param_0 </li>\r\n\t\t<li>Executing:\narray (\n 0 => 'default_ping_status',\n)</li>\r\n\t</ol>\r\n</div><div style="clear:both; margin_bottom:2px; border: red dotted thin;" class="error_message" style="border-bottom:dotted blue thin;">Error occurred at line 1713 in Function execute_query. <br/> Error message was: Error while executing query! Error message was: SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: wp_options.option_value </div><pre>#0 WP_SQLite_DB\\PDOEngine->get_error_message() called at [/opt/wordpress/wp-content/db.php:2736]\n#1 WP_SQLite_DB\\wpsqlitedb->query(UPDATE `wp_options` SET `option_value` = NULL WHERE `option_name` = 'default_ping_status') called at [/opt/wordpress/wp-includes/wp-db.php:2476]\n#2 wpdb->update(wp_options, Array ([option_value] => Array ([value] => ,[format] => %s,[charset] => ,[length] => )), Array ([option_name] => Array ([value] => default_ping_status,[format] => %s,[charset] => ,[length] => ))) called at [/opt/wordpress/wp-includes/option.php:496]\n#3 update_option(default_ping_status, ) called at [/opt/wordpress/wp-admin/options.php:322]\n</pre> for query UPDATE `wp_options` SET `option_value` = NULL WHERE `option_name` = 'default_ping_status' made by update_option, WP_SQLite_DB\\wpsqlitedb->query, WP_SQLite_DB\\wpsqlitedb->print_error, referer: SITE/wp-admin/options-discussion.php

… which I think we can agree is less than helpful, but with some distillation we discover:

Error message was: SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: wp_options.option_value

This is the second part of the unpleasantness, and this took quite a while to figure out; that SQLite has some database constraints that WordPress doesn’t meet and isn’t interested in meeting. I’m not an expert – I think the general thrust of the problem is that where SQLite defaults to strict, MySQL defaults to sticking a crayon in its nose – but some precision chicanery in options.php seems to sort us out. In wp-admin/options.php at around the 320th line or so:

if ( isset( $_POST[ $option ] ) ) {
$value = $_POST[ $option ];
if ( ! is_array( $value ) ) {
$value = trim( $value );
$value = wp_unslash( $value );
// You probably shouldn't do this, but it makes WordPress work on SQLite.
$value = $value ?? '' ;
// If this breaks anything I am very sorry. It works on my machine. -mhoye

update_option( $option, $value );

A single line of code. The precise, surgical elegance of a scalpel taped to a brick. But it works. For me, on my machine.

Shut down Apache, rename the DB file and restart it, and there you are. A clean install of WordPress running (far as I can tell…) correctly backed by SQLite3.

Nothing to it.

Addendum: “Nothing to it”, he said, full of hubris. Well, haha. If you upgrade your Linux box – Ubuntu, in my case, via do-release-upgrade – you’ll need to reinstall libapache2-mod-php8.0 and php8.0-sqlite3 afterwards, and afterwards maybe do some aggressive career counselling for whoever decided that dumping an entire web page into my logs was OK.

Service Resumption

Apologies for the interruption, and the ugly defaults. Content has returned and full service will resume shortly. Please enjoy our new LetsEncrypt cert, a tolerable theme will be along shortly.

I have some recovery-editing to do, because the the WordPress import/export process is remarkably bad at importing things that have been exported.



On his deathbed, in the final moments, an angel appears radiant and glorious by Machiavelli’s bedside. Niccolo, it says in a gentle, sonorous whisper, your time here comes to an end. Come, the hour has struck that you must move on; know in your rest that your works will endure.

Among kings, queens, he asks in relief? Princes and ministers, their consorts and counsels?

No, the angel smiled, leaning close. No, Niccolo, no. It’s mostly assholes in airports.


A lot of them are moving their lips while they read.

“what is… how many?”

About half. I’d say half.

Priorities, Redux

Hi, neighbor.

Me, unixy old person: “… and before end to end encryption was standardized, that meant that something called replay attacks were possible. To mitigate this, kerberos authentication was invented, which…”

A young unixy person: “Can I pet Kerberos?”

Me: “what”

“Kerberos was named for the three-headed dog that guards the gates of the underworld, right?”

“… yes?”

“Can I pet the dog, is my question.”



“Ok, no, but file that bug immediately.”