About Steve

Steve is way into…

  • His wife, and his dog Rufus
  • Shallow, rocky creeks of the Appalachians; hollows; towns built on the side of mountains; abandoned roads, bridges, railways, and stairways.
  • Building web sites, apps, and frameworks with TypeScript, Node, React, GraphQL, and some PHP
  • Indiepop, dreampop, yacht rock, disco beats, 60’s pop, classic hip hop, Stereolab, Broadcast, ABBA, Deerhoof, Zombies, Innocence Mission…
  • Playing piano, guitar, bass, and drums if anyone will let him
  • Transcribing song chords
  • Nudging songwriters to embrace a wider view of harmony
  • Building little apps to share chords and keyboard snippets
  • Moose’s album Live a Little Love a Lot (all time)
  • Jorge Elbrecht’s album Here Lies (last decade)

github | threads | instagram

Shutdowns

For a moment, set aside any partisan views you have on this and past government shutdowns. We’re increasingly often finding us in these stalemates and I think it’s due to–what a surprise–the problems I regularly gripe about on here.

Primary is the mistaken belief that the Senate’s filibuster rule is worth maintaining. You know, because “it keeps healthy, productive debate alive in the Senate”. This notion has been laughable since at least the Obama administration. In practice the filibuster means the majority in the Senate can’t pass legislation; that’s it. That means the majority must resort to gigantic Frankenstein bills engineered to bypass the rule, and we get these regular stalemates over budget bills.

But it’s just a relatively new norm. The Constitution designed the Senate with a simple majority vote to change rules and pass bills. The majority could, at any time, change the rule and pass their desired budget, starting the end of any shutdown. Democrats could’ve done this in 2013 and Republicans could do it tomorrow.

But there’s fear that the press will treat this as a radical upending of norms (it isn’t). Fear that the public will realize they could’ve done this weeks ago (true). Fear that the minority party will in the future have one less constraint when they regain the majority (true). Some Senators seem genuinely concerned that without this non-Constitutional 60-vote hurdle, the Senate will break, but we can all see Congress is broken today. Ditch the filibuster and at least the Senate will always be able to pass budgets, and, because obstruction is impossible, there will be more incentive to have a seat at the table making those decisions. The filibuster hasn’t fostered debate; it’s busted it. Several Senators that have prominently defended the filibuster publicly in recent history have left the Senate, so, fingers crossed.

The second factor is just partisan acrimony arising from our dumb first-past-the-post election systems. I make this case more broadly here, but basically Congress is dominated by increasingly partisan actors that are more inclined to play hardball and refuse to compromise. To force stand-offs when this helps no one. In this moment both parties at least quietly acknowledge the need to extend ACA subsidies to avoid millions of people being priced out of health insurance, but each party must not “lose”. Republicans could put an ACA extension in their bill or end the filibuster, but that would be losing. Democrats, who lost the last election, could just approve the the last budget they approved last time, but that would be losing.

There’s definitely bad behavior going on here, but simply arriving at these shutdowns is a sign we need changes.

It’s time to boycott OpenAI

If you use AI, I think it’s time to boycott OpenAI and its products like Ch**GPT and S*ra in favor of its many competitors.

The economic case: Several large firms are placing very large bets on OpenAI ending up with a de facto monopoly, and when this doesn’t happen, the bubble’s pop will hurt the broader economy. It’s better for the public early on to loudly tell investors, “no, we’re going to use whatever’s cheapest, and you won’t recoup giant investments.” LLMs are math and I think will end up commodity goods whose cost will trend towards the cost of hardware + CPU time, which are both themselves commodities. I’ve not yet seen a case why OpenAI will be able to sustain a monopoly by sprinkling “special sauce” on top of models whose capabilities are in the ballpark of its competitors.

The WWW case: Atlas, the “browser” described here is a direct shot across the bow at the web. Even more than Google’s AI search results, it says to site authors, “the future is us drinking your content and users never knowing your site even exists.” I won’t pretend Atlas’ failure would stop anything. We’re well on the path to the collapse of the ad-supported web, and people who create sites for free won’t bother as few are reading and web hosting costs rise back up. Do you want to share your thoughts or promote your service or product? Here are the 5 companies you can pay and their terms of service will be outrageous.

The privacy case: Holy hell one feature of Atlas invites next level surveillance of the public. Your TV already catalogues the content you watch (yes, even attached HDMI devices) and is selling that data. Atlas invites you to share your whole browsing experience with OpenAI (and if not now, eventually its friendly 3rd-party partners). OpenAI’s service S*ra demands that copyright holders opt out. Good luck with that argument in court.

DOGE

“Good morning. On top of your current duties, your team is taking over providing a vital service to hundreds of millions of people.”

“How will we do that on top of the existing work?”

“Efficiency.”

“OK. Completely different domain; the people who know all the ins and outs of this service, and software and stuff, when do they train us?”

“Oh, we fired them. You’re going to be very efficient.”

“Well, why didn’t you just not fire the people already knowledgeable and doing this work?”

“We put daily numbers on a website. Firing people makes big numbers today.”

“Won’t we end up just expanding this office with a similar number of people except who won’t know what they’re doing? Is this going to work?”

“Look, I’m 23 making six figures. Elon and I will be back at SpaceX soon enough and if shit breaks Trump is going to blame you and Democrats and make some splashy deportations and it’s going to be fine.”

[Nervous laughter] “Oh good!”

“Oh, not for you. We’re going to slander you while you collapse under an impossible workload, but fine for me. SpaceX is getting some big contracts soon.”

”But we’ll save some money, right?”

”Possibly [deep drag on a cigarette] but most of that is going to the 1% in a big tax cut.”

“Cool I guess. This seems kinda cynical and cruel to the thousands who got fired and millions depending on these services.”

“If it makes you feel better, these particular victims are imaginary because this is a writing exercise. We don’t exist either.”

“Oh, huh…” [puts on basketball shorts, catches ball thrown from out of frame, shoots, crowd cheers]

Installing a Second HTTPS Service in DDev

Let’s say you have a DDev setup with https://example.ddev.site, but you need a second secure URL for a separate service. Normally you’d do this with additional_hostnames, but you still would need to use a nonstandard port like 8443 because port 443 across all the hostnames goes to the web container. But there is a way to get https://host2.ddev.site (on port 443) to be served by another DDev service:

First, in your new service, manually set up it up to serve port 443 on the new hostname:

    environment:
# This configures traefik to map host2.ddev.site:443 specifically
# to this container port 8080. Because we don't want the web container
# handling this hostname, we do NOT include it in additional_hostnames.
VIRTUAL_HOST: host2.ddev.site
HTTP_EXPOSE: 80:8080
HTTPS_EXPOSE: 443:8080

In DDev’s config.yaml, do not place host2 in additional_hostnames. The reason is this would place “host2.ddev.site” in the web container’s VIRTUAL_HOST. I recommend a comment to point this out:

# We _are_ using the hostname host2.ddev.site in the project, BUT we cannot
# list it here because then the web container would handle it.
additional_hostnames: []

✅ Now you have two HTTPS services:

  • example.ddev.site:443 -> web container port 80
  • host2.ddev.site:443 -> host2 container port 8080

Allowing https://host2.ddev.site to work inside another container

This isn’t essential, but in my case I needed to use the same URL in the browser and within a third container site3 running Alpine linux.

In the site3 Dockerfile, install ca-certificates, so we can later install the self-signed DDev cert:

RUN apk add ca-certificates

In docker-compose.site3.yaml, map the DNS and add a volume mount with the cert:

    external_links:
# Set up host2.ddev.site to reach the main traefik router
- ddev-router:host2.ddev.site
volumes:
- ".:/mnt/ddev_config"
# Allow copying mkcert/rootCA.pem into container
- ddev-global-cache:/mnt/ddev-global-cache

In config.yaml, add post-start hooks to install the cert:

hooks:
post-start:
- exec: cp /mnt/ddev-global-cache/mkcert/rootCA.pem /usr/local/share/ca-certificates/my-cert.crt
service: site3
- exec: update-ca-certificates
service: site3

Using the DDev cert with node

If site3 uses Node, you’ll need to select the OpenSSL cert store instead of the built-in one.

node --use-openssl-ca script.js

If using pm2:

NODE_OPTIONS="--use-openssl-ca" pm2 start ...

Quick Thoughts on “AI Music”

The tech is fascinating but the trajectory of it being used to screw artists is already clear. Hopefully artists will lawyer up and get their works out of training data.

Large artist unions should be mandated access to freely and deeply test public models for the purposes of detecting IP in the training data. If you’re making money providing a model, be prepared to show your papers on its training; trust needs to be earned.

Commercial models should be taxed, with revenue supporting ongoing development of tools for smaller artists to protect themselves from being ripped off.

If this effort goes well for artists, I generally expect sound quality of music generation to improve but “humanness” of the public models to sink. Bad news for companies wanting nearly free anodyne music for commercial use, but arguably better for art.

Where do the real prices of services like Udio land after investors stop footing the bills? Do these VC subsidized toys ignite the creative spirit of everyday non-artists to get into the game of actual music creation? What are we missing out on by having a world where very few people make music?

Restarting a node service on macOS boot

This was a pain to get right, so here’s what I landed on:

  1. Open System Settings > Energy Saver
  2. Turn on Start up automatically after a power failure
  3. Under Privacy & Security > Full Disk Access, add the executable /usr/sbin/cron
  4. Log in as root: sudo su
  5. Install pm2 globally: npm i -g pm2
  6. Don’t get trapped in vim: export EDITOR=nano
  7. Copy the PATH to clipboard: eval 'echo PATH="$PATH"' | pbcopy
  8. Edit crontab: crontab -e
  9. Paste in the PATH
  10. Create cron entries using the full path for file/directory references (you don’t need it for executables)

Example root cron:

PATH=/Users/steve/.bun/bin:/usr/local/bin:...

@reboot pm2 start /full/path/to/script.js

This creates a PM2 service for the root user. You can only see/remove its entries when logged in as root:

sudo su

# list services
pm2 list

# remove 1st entry
pm2 del 0

Keys and Scales

The early stages of learning music tends to leave musicians with the impression that being “in a key” means using notes in the key’s signature scale; the “diatonic” notes and chords built from them. Nope! Lots of chords using chromatic notes sound totally natural when in a key because…

A key is not its scale.

A key is more like a mental state set up by a particular chord being perceived as “home”. This provides a context where some melodies and harmonies sound more natural than others.

How do we get into this state? We think it’s from having the chord first in a piece or a loop, or by giving its chord tones emphasis by some melody. For example, here are the critical notes (root and 3rd) of a G major chord with the G note doubled on top, and we give G a little jump from D to help it be heard as the tonal center:

Once established in our head, there becomes a variety of familiar harmonies we’re use to hearing, but it isn’t really about the G major scale.

An example 4 bar loop in G major

We have: G – C/E | Eb – C | Bø7/FE | Am – Cm D7

The Eb chord in bar 2 (with Eb and Bb instead of E and B) sounds a bit intriguing, but not at all wrong:

And if you stop the song and play a scale over this chord, you’ll find it’s not the G major scale that sounds best!

It turns out the current chord has a ton of influence over which scale(s) sound best at the moment. Or as I like to think about it, some chords bend the scale to support the chord.

And this little part below from bar 3 doesn’t even sound like G major when you take it out of context:

This is plain old key of A minor material, even using the A harmonic minor scale with F instead of F#, and G# instead of G! In the context of our G major song, this is what’s called “tonicizing the two” because we’re momentarily using the dominant chord of ii (E), treating Am like a temporary tonic. But we’re still in G major.

So what can we play? And with what scales?

I put together a broad overview of chords commonly used in G major (and all the other keys). Any resource like this should be treated as a starting point, and I’m definitely not implying that music using more or rarer chords will be better in some way.

Regarding scales, to avoid perpetuating another misconception, we shouldn’t think of there being one “right” scale to pair with any chord. Context, genre, taste all come into play, and as with harmony, trust your ears. Usually the scale will have several notes in common with the key signature.

Of course there are some ways to predict scales that are commonly used… in another post.

Writing melodies over modal interchange

If you look at the common chords of A major you’ll find six maj7 chords fit the modes commonly used:

Amaj7, Dmaj7 from A Ionian (the diatonic ones); Gmaj7 borrowed from A Mixolydian; Cmaj7, Fmaj7 borrowed from A Aeolian; and Bbmaj7 borrowed from A Phrygian. Here’s a loop of them with an A pedal tone on top:

As you might expect, you can’t just play any A major melody over any scale. Here are a couple strategies:

Avoid the Changes

Here you keep the melody diatonic (here using only A Ionian), but craft the melody (and/or the chords) so the melody is always in the current mode.

Here’s an example that uses all seven notes of A major:

Play to the changes

Here you intentionally target notes that are newly brought to the scale by a mode change. E.g. switching from A Mixolydian to A Aeolian, you’d want to land on C or F.

Here’s an example over the same chords, but playing to the changes to squeeze in more chromatic notes:

And an example from pop music, in the chorus of “Something About You” (E major) the melody moves from the 3 scale degree to the b3 over the borrowed bVI chord:

Why I’ll vote for Kamala Harris

Harris seems to me a focused and competent adult with integrity, who can work with people to get things done while taking the awesome responsibility of the Presidency seriously. I expect she, like me, recognizes that a leader’s public behavior, character, and decency to other humans matter. There are plenty of public figures setting a bad example of how to live without the leader of the free world doing it, too. I expect she knows it’s morally wrong and particularly repugnant for a political leader in this era to bully and slander because it puts people in real danger. I expect she will never say things that lead to people and organizations getting death threats.

I expect she knows it’s also just not smart strategically to have a long enemies list if you want to have a positive effect on the world. I expect she will not inflame tensions or bring out the worst in crowds by suggesting that if not re-elected, certain doom will befall the country. I expect she feels some shame when lying. She has certainly lied, but I would gladly invite a comparison with her opponent.

I expect she won’t waste hours a day on social media or cable television getting a distorted and false view of the world. I expect she’ll recognize what she doesn’t know, and will learn from expert advisors rather than just people who praise her. Any decent economic advisor would warn her that blanket tariffs would be massively inflationary and risk starting a trade war that would endanger our own exports. (We should ask why the executive branch’s control of tariffs are so powerful.)

I expect she’ll recognize that the rule of law–state laws, attorneys general, and courts–decide how elections and recounts are run and adjudicated. I expect she won’t pretend as if recounts, investigations, or court cases didn’t happen or bring up lies already debunked by law enforcement.

This is not a particularly high bar. Arguably every major party candidate in recent history–save one–easily cleared it. I suppose if a candidate were exceptionally capable you could argue letting a few of these things slide, but in my opinion…

Donald Trump does not seem exceptionally capable.

His tax cuts raised the debt by trillions while achieving none of the promised outcomes. The economy he is credited for was a steady continuation of the 2012-2017 post-recession period as you can see on any graph of the major economic indicators like GDP and unemployment; there was no Trump bump. To be generous I could say he didn’t break anything (but the debt). Analyses of his tariff proposals look disastrous for the economy. There’s no credible theory of how he would reverse the worldwide phenomenon of inflation without a time machine, and to “bring back his economy” you’d need to fire lots of people because unemployment is lower now.

Subjectively, during his presidency he seemed driven by daily distractions and grievances he came across on social media and cable news, and he lacked the focus to ignore what didn’t matter and ignore the haters–he created more every day. His obsession with being perceived as having the greatest everything of all time led to national embarrassments like Sharpiegate and “alternative facts“. Although his team’s efforts to fast track COVID vaccine development and rollout should be applauded, he routinely undermined his own government’s efforts by downplaying his own family’s vaccinations and giving spotlight to fringe figures and unproven therapies [1]. There were weeks when one could argue his public behavior was a greater help to the outbreak.

I’m further convinced by the large pool of former Trump administration folks not endorsing him up to and including his former VP. All these people cannot just be chalked up to Trump Derangement Syndrome; they worked directly in his orbit.

He would be the oldest President in history, we know nothing official about his health, and if he passes in office it will lead to a man taking office who is at least on board with Trump’s demonization of immigrants and past behavior, and has promised to follow Trump into the darkness of testing the limits of post-election lies and the rule of law.

No thanks.

[1] For their part, scientists and politicians surely damaged their own reputations by various means in the COVID era, but I believe there were at the very least many thousands of deaths that could be attributed to the politicization of vaccines, and that will sadly continue.

Hungary and the Republican party

A PSA if you’ve watched leaders of the new Republican party hold up Hungary as a great country. Last I checked Hungary has…

  • National health insurance
  • 20 days paid vacation
  • 15 days paid sick leave
  • 24 weeks paid maternity leave
  • Tons of extra benefits for parents
  • Yearly minimum wage increases
  • Very few gun deaths due to strict gun control

Sounds nice, but the Republican party prevents us from enjoying those, so why might they promote Hungary as a model? Ah I see… The oppression of same-sex couples, limitations on the freedom of speech, a loud and corrupt leader who says nice things about Donald Trump…

If you want the good policies of Hungary that improve quality of life, elect people to Congress who will actually vote for those policies.