I been noticing more smarter AI in customer service these days.
A recent example: I docked my
BIXI
but the thing glitched and the ride didn't terminate. I only realized when I
tried to get my next bike out.
In the past when this happened to me, I just called up BIXI support, went
through a short phone menu, and explained the situation to someone on the
phone. They verified my identity and manually terminated the ride so I could
go on my way.
Basically, the ideal phone-based customer support experience. The wait
wasn't long, the procedure was efficient, each step made sense, and it
solved my problem.
This time, the app prompted me to ask for support via "chat" first.
Historically, this could have meant all sorts of things: a naive keyword
recognition program that would recommend FAQ entries to me; a tech support
worker from a country with a low median wage pasting in responses from a
script, 5 tickets at a time; occasionally, the type of person I'd been
talking to on the phone, but over text.
This time, it was some sort of LLM. It dynamically and patiently walked me
through the identification and triage process. It handled my typos and
information I sent bit-by-bit.
Eventually, it concluded the issue needed human involvement. Presumably at
the end of its instructions it has a
"If asking the customer to jiggle the bike doesn't fix the problem,
request that they phone a human."
part of its prompt.
This was fine. The trouble was that I then had to do all the same stuff with
the human. The same identification process, the same identification of the
nearest street intersection, the same bike jiggling. Finally, the human
terminated my ride.
It would clearly be better if I could call the human and have them say
"I see you've already gone through all the steps with our AI. I'm going
to unlock the bike now."
Better yet (though not something BIXI alone can implement), identifying
myself is done via a two-factor prompt on my phone (get on this, governments!) and I can use text-to-speech to compose my messages to the AI. Maybe
we'll even eventually find them reliable enough to let LLMs terminate rides
themselves!
As it stands, the experience feels like costs are being cut. It doesn't need
to. Automated customer support could be faster, cheaper, and more convenient
than the best phone support I've had.
Was that as good for you as it was for me?
I'm still skeptical of this future. The companies that have already
automated as much of their customer support as humanly possible are
miserable to deal with, even though in a sense I'm grateful for the downward
pressure they put on prices. These are typically companies of enormous
scale. The BIXIs of the world might be able to take a different path.
A lot of people on
Mastodon
are there because they believe decentralized and open-source techologies are
essential tools for resisting coercive power. The fediverse is innately
resilient to censorship, advertising, and hostile takeovers.
For these reasons, I made the switch from twitter sometime in the early
2020s, but I think it's important to remind ourselves that these virtuous
properties are not a panacea to all the ills of social media.
It doesn't matter whose database the posts exist in: we can all still be
ragebaited. It's a fundamental vulnerability of our psychology, with or
without Elon Musk intentionally exploiting it.
this comic is from 2008
I've maintained for a long time that the good part of Mastodon is that it's
kind of shit by default. You have to put quite a bit of effort into finding
people to follow and tweaking your settings to get it to surface a lot of
interesting content. I haven't done this. I follow a few randos and some
bots that post clipart.
I like the fact that when I check the fridge1, there's just the same head of cabbage that was there last I checked.
Paradoxically, the better Mastodon gets, the more I'll check it, the less
good for me it will be.
Recently, someone I follow started boosting posts I found to be confidently
wrong. I started getting emotionally invested in the thoughts of complete
strangers. Getting provoked. I wanted to write replies to correct their
misconceptions.
I've mostly been able to resist: it would not change anyone's mind. It would
take a lot of time. I would get even more emotionally preoccupied by a
hamster wheel.
Instead, I think I'll employ another cool thing about open-source
technology: you can usually adapt it in ways to suit your needs2. I can filter this person's boosts and hopefully that will be sufficient.
But there's a tension here. For the structural factors outlined in the
introduction, I want the fediverse to grow. For it to grow, it needs to
attract users that aren't already sold on the structural selling points - it
needs to be better. For it to be better, if we optimize for engagement, it
could easily become worse.
A ragebaiting machine that people can tinker with is still better than one
they're forced to use, but I will maintain my wary distance in either case.
absorb assigns the changes based on whichever
previous commit most recently touched those files, which sometimes doesn't
actually correspond to which commit should own these particular
changes.
squash can get you stuck in merge conflict hell
if your boundaries aren't extremely clean.
So here's a solution to this problem of "git rigour fatigue" that I've come
up with.
For this example, let's represent commits visually. Imagine
red represents
changes to the type definitions,
blue to the UI
and so on:
Mayhem. Our first commit is a mix of
red and
blue. We touch
red in multiple
places!
To fix this, let's create our ideal commit history first, using
jj new -B messy-first -m 'red'
Then we can do the rest. (I switch to
jj new -A red -m 'blue' at this point)
Then we squash all the commits with actual changes in them into one with
jj squash --from messy-first..messy-last --into messy-first
Then we use
jj squash -i --from messy-first --into red
and pick out the red changes, putting them into the red box:
And so on:
Eventually everything's in the right place and the "everything commit" is
empty.
For large features, I find this workflow far easier than having to maintain
strict git rigour for the lifecycle of the feature's development. It's
easier to make improvised commits with temp debugging state in them and tidy
it all up in one sweep at the end.
preemptions:
I don't have a good name for this technique. "Doing Commits Like A Big
Pile Of Laundry", perhaps?
This is different from (and, imo, superior to)
jj split:
With split, if I miss a hunk that should have
been in red,
I have to split again and squash.
This technique more easily allows sorting the easiest hunks at the
beginning without worrying about how it will effect the commit
sequencing.
This reason why doing it all at the end is (often) better than using
jj squash -i as you go is because the final state
of the everything commit is guaranteed to not have any conflicts. Creating
a new "fix red and green" commit and interactively squashing that into
your red and green commits might break your blue commit if it happens to
touch one of the affected files.
A downside to this technique is that there's no guarantee that every
commit will compile, which might be a dealbreaker.
update 2026-05-8: hello
hackernews
- whoops, yes, i should have filtered out the noise specks. thanks to
kevinsync for the reminder.
this is not a power or bandwidth saving technique à la
low tech magazine. it's principally aesthetic.
handy if you're running a site with pictures but you want everything to
maintain a consistent aesthetic and colour scheme. might be better to just
process the images and save them already dithered, but this way can be
customized. (note that the original image is still there beneath the filter,
and that's what gets loaded, so, again, this doesn't save bandwidth - but it
also means users could vary the effect per theme or toggle it off)
I checked out Twitter for the first time in ages to see if anyone had been
finding anything in the Epstein files
Which, holy shit.
I'd heard journalists describe twitter as the place where narratives hatch,
but it was surreal seeing the process happen so quickly.
Scrolling deeper and deeper down, I was hypnotized, feeling like I was
wrapping my own red yarn around thumbtacked headshots, drawing my own
connections as to what it all meant.👨🍼
Little did I know, it's conspiracy all the way down.
Underneath any high traction tweet I saw, there would inevitably be 3 or 4
replies running interference on its narrative. One would discredit it. One
would downplay it. One would distract from it. It's clear there's a bot
campaign trying to astroturf the cycle, and whoever's behind it is trying to
impede democracy.
Later in the week, on a YouTube video about changing the clawback mechanics
for canada's old age security pension, someone claiming to have worked their
whole life for their pension had left a much-upvoted comment that was
opposed to the idea. I replied pointing out it would only apply to people
over 65 earning more than 100k a year. There was some more back and forth -
the research took me maybe 20 minutes. Once my replies started getting
upvoted, the OP deleted the post and everything went away.
There's no way to verify this, but I really doubt
@Jeanlz8zw is a real person.🪒
How much of our sense of reality is steered by strangers who want us to be
confused, mislead, misinformed, or angry?
Can anything be done?
Something I've wanted for at least 10 years now is for governments to offer
identity verification services for social networks.
Here's how it could work:
When I apply for a passport, I'd also get an account at identity.gov
When I sign up for a social network account, I can link it to my
identity.gov account
Now, whenever I post something, I'd get a few affordances.
(These next two blocks are interactive.)
Then, when I go on YouTube, I can filter comments based on these 3
properties:
Require:
unverifiedEXPOSED: The REAL reason they want digital IDs 🧵👇
✓ human-abcThere are some real privacy concerns worth discussing here
unverifiedlol this is dumb
✓ citizen-123 🇨🇦As someone who voted for digital service reform, I support this
✓ human-xyzInteresting idea but who would run the servers?
✓ Jane Smith 🇨🇦I've been researching digital identity systems — happy to chat
Now. There are lots of concerns any reasonable person would have.
Zero-knowledge proofs
are a cryptographic technique that allow people to make verifiable claims
without revealing any other information about them in a way that can't be
linked back to your actual identity in the government's registry.🧑💻
The technical details aren't the emphasis of this piece. Just imagine that
the government made a billion unique stamps, and handed out one to each of
its citizens at random. Each citizen could then stamp their documents,
readers could verify that the stamp was authentic, but the government
wouldn't know which stamp belonged to which citizen, or what its citizens
were doing with their stamps.
That's the gist of the thing I want. It is not a centralized
government database that tracks all of our online activity and links it to
our real identities.
Won't this chill speech?
Possibly! Though I think it being gradated and opt-in drastically softens
the extent to which it would.
We also need to understand that speech is currently already chilled, just in
a different way. I've stopped replying to people on the internet because
I've lost confidence that they'll respond in good faith.
I worry for the world in which no one is anonymous online, but I also look
forward to the day that I can read an angry man's comment on bike lanes and
know that he's an honest-to-goodness ignorant Canadian and not a troll for a
national disinformation department or PR firm.
Won't people just sell their tokens or let AI agents use their signatures?
I think all signatures will have to have a persistent identity such that you
can always view someone's posting history.
So you'd get a stable pseudonym like human-xyz that
is attached to all your human-signed posts.
Your citizen and personal signatures would get different pseudonyms, so that
they can remain separate. This would have to be per-platform, so that you
could have a different identity on Substack than AO3.
e.g. these would both be you:
substack-citizen-123
ao3-citizen-456
Though obviously if you signed posts on both with your full name, anyone
could connect your accounts.
This would allow us to filter/tag/shame people who sell their accounts if we
see that they're spamming.
Won't semantic analysis break anonymity anyway?
Yes, probably.🕵️ If that
becomes a real problem, I guess we'll get tone masking services that rewrite
your original message to remove your idiosyncracies for the especially
privacy-valuing people (who are probably already doing this)
Won't an opt-in system eventually become mandatory?
The scope creep objection. It starts out optional but norms develop that
pressure us to sign everything and disregard anything that isn't signed -
ratcheting society towards less anonymity.
This seems like a real possibility to me, but I can still see it happening
democratically. A decade of experience with the system leads people to
conclude that generally, this is a healthy norm that has been beneficial for
society. Something that feels more like
mandating seatbelts
than Ring cameras becoming ubiquitous.
That's my idealism, though. Realistically, it's contingent on the government
and society that's implementing this technology.
Won't this exclude people who can't get passports?
I have trans friends who can't return to the U.S. without getting their
passport revoked now. They're fearing for their lives and freedoms, and it's
incredibly tone deaf of me to propose that we further empower the state to
identify them.
I guess I just bite the bullet on this one. My belief is that this US
administration exists because we didn't have this system in place in 2015,
allowing the US political discourse to get hacked by Russians on social
media. Obviously there were lots of other factors, but it seems quite
plausible to me that adverserial nation states tipped the balance in what
was an extremely close election.
I wish the world was safe for everyone. I wish that all our governments were
trustworthy and progressive, but they're not. We need to find approaches
that can help incrementally improve them.
This proposal seems unlikely to happen by default, and I would really
strongly oppose a system that would forcibly de-anonymize everyone on the
internet. My hope in writing this post is so that people who oppose online
identification systems have something else other than a total rejection of
the idea to point to when they raise their concerns.
Why does a government need to run this?
Big political science question! What is the role of government? Can it be
trusted? Do we need a semi-adverserial relationship between the public and
private sectors to guard against creeping state totalitarianism?
I don't have a conclusive answer to this, but I do know that New Zealand's
RealMe is really good. E-Estonia is really good. Governments can build
digital services that are actually well-designed, and write legislation that
gets the private sector to adopt it.
Why does it have to be centralized?
Can't we just write an open standard and allow anyone to become their own
identity provider?
I guess? That just sounds a lot more complicated to me. Imagine pitching
that to your auntie:
"Ah yes, well this commenter is verified by OpenRep which is
mostly for academics, but they're responding to someone who's verified by
VeriCoin which is a pay-to-play scheme. They're
probably a real person, but people on MeYou say that
they've been compromised...
Isn't this what WorldCoin is?
Yes and I think there are tonnes of other ideas and groups working in this
space:
GNU Taler for payments
European Digital Identity
eIDAS / EUDI Wallet
W3C SSI Standards
Some of these are state-based (eIDAS), private (WorldCoin), or
standards-based (W3C SSI).
So there's a lot of activity here. Hopefully we get more applied
implementations to learn from.
Okay that's enough
In all likelihood, the first implementations of systems in this space will
be flawed and privacy-violating.🤡 In
the US and Canada in particular, when has any government service been
on-time and best-in-class?
Nevertheless, I'm not giving into defeatism here. I'm completely energized
by the potential upsides of an internet that has trust again. This is all
the more important in our AI-suffused world.
Part of my family’s canon is Spooner or Later, by Paul Jennings,
Ted Greenwood, and Terry Denton.
A spoonerism is a kind of wordplay where you can swap the starting sounds of
words in a phrase to make another valid phrase.
For example, “shake a tower” becomes “take a shower”.
It’s like dyslexia for fun.
Spooner or Later was that plus I spy.
“Fat Man’s Race” (the captioned & skewed illustration in the center of the
left page) becomes “Rat Man’s Face” (the image on the border of a costumed
rat flexing his muscles.)
This book was a measuring stick of my cerebral function. By the sage of
icks, I could only solve pimple suns at the start of the book, but after
months of prayerful cactus, I was eventually able to finish the hack’s bard
puzzles.
Solving them becomes pretty straightforward as your vocabulary expands, but
creating them is a whole other skill.
The most straightforward way to do it is to think of two words that rhyme,
then think of two other words that rhyme that start with the same sound as
the first two words.
Word and Nerd
Whoa and Know
Know word? Whoa, nerd!
In my experience, it's difficult to think of the second pairing, let alone a
pair that make sense together. It's a thing our brains aren't particularly
good at, because it requires a kind of exhaustive search through the
dictionary, and often you find a pairing that isn't grammatically equivalent
like... “lead bike” and “bedlike”.
But if we could programmatically generate hundreds of pairings at once, we
could scan and pan them quickly.
Sounds like a cob for... jomputers?... A mask for tachines?
And with this data structure at hand, you have everything you need to make a
nice little UI to find spoonerisms. Most of them will be trot hash, but as
Napolean said, bots of lad is like a grit of bait.
Some (I) might argue that the best path to making spoonerisms that are
actually delightful is to chisel them out with a
thesaurus
and
rhyming dictionary, but for rapid ideation, this approach gives a reason t' doubt.
I first saw this on
Hakushi Hasegawa's website1 and after a little
digging around in the source, saw that it was implemented with a shader and
three.js
But I had a hunch that it might be possible with CSS blending modes. Not
because I fully understood them, but just because it
seemed like the sort of thing they're made for.
And as you can see, my hunch was correct, but as I write this sentence I
still don't completely understand why.
They've been
explainedamilliontimes
by other people, but it's an open secret that blog posts like this are for
me, not you, so here we go again:
What actually are blending modes?
In a black and white image, every pixel can be represented as a value
between 0 and 1.
0 is fully black. 1 is fully white.
Blending modes are rules for what should happen when you combine two of
these numbers. For instance, the darken mode takes
the lower of the two.
Or the multiply blending mode, which can be written
as:
where
is the base pixel value
is the blend pixel value (the one on top with the blending mode set)
is the output
If you have one pixel that is 0.5 (medium gray) and another that is 0.7
(light gray) and you blend them together with the
multiply mode, you'll get a pixel that is 0.35.
And to be clear, this isn't just 3 divs with 3 different hexcodes. The third
square you see is two divs stacked on top of one another with
mix-blend-mode: multiply
set on the top one.
need proof?
One thing you might take away from multiply is that
it's not possible to get a lighter value than the values going into it. A
fraction of a fraction is always smaller than the fraction itself.
How about the other blending modes? Expand for more details than the
average person wants to know
So how do we use these tools to make the spotlight? The key is understanding
that the abrupt edges of the
color-dodge mode can turn a gradient into a mask.
With color-dodge, as the blend pixel approaches 1,
the denominator approaches zero and the output value increases abruptly.
Here's a medium gray base layer and a black-to-white gradient blended over
it using
color-dodge
Think about what's happening here.
A is 0.5
B ranges from 0 to 1.
On the left, B is 0, so we're dividing 0.5 by 1, which equals 0.5
2
As B approaches 1, we start to divide A by a smaller and smaller number.
When B is 0.5, we divide 0.5 by 0.5, which equals 1: pure white. Any higher
value of B makes no difference because 1 is the lightest value possible.
As soon as the blend pixel becomes lighter than the base pixel, the output
flips to white.
What if we blended a gradient over a noise texture?
Some of the noise pixels have slightly lightened, and many of them have
turned fully white.
Effectively, what's happening is the computer is sampling each pixel and
comparing it to the gradient. If the gradient is lighter, it hides the
pixel. The further along the gradient you go, the more pixels get hidden.
Now all we need to do is make the remaining pixels black. Fortunately,
there's another blend mode for that:
color-burn
color-burn takes the inverse of your base layer,
divides it by the blend layer, and then takes the inverse of that.
Let's color-burn a black layer over the
color-dodge layer.
We start by picking one of the remaining visible pixels. Say we pick one
that's dark gray (0.3)
The inverse of dark gray is a light gray (0.7)
The blend layer is black (0)
0.7 / 0 = Infinity
1 - Infinity = -Infinity
CSS can't display negative infinity: it clamps the value to 0. This is why
all the gray pixels turn black: we're always going to be dividing them by
zero.
But there's a special case! What if the pixel we sample is white? (1)
The inverse of white is black (0)
The blend layer is black (0)
0 / 0 = NaN
1 - NaN = NaN
NaN means "Not a Number", which is a special value used to represent
undefined or unrepresentable numerical results. Fortunately for us, CSS
renders these specific errors as white.3
And so there you have it. There's some artifacting going on due to tolerance
for near-white values, but to recap:
color-dodge "hides" pixels that are darker than
the gradient.
color-burn blackens the remaining pixels
This gives us a pixelated falloff based on the lightness of a gradient that
we can overlay atop a noise layer.
Building the effect
Now that we understand the principle, let's build it step by step.
First, we create a div and center some text in it:
Then we place a new div above the text, with a noisy background image.
Statically positioned elements' backgrounds paint first, which is why the
absolutely positioned text is shown above it.
Then we place a div inside the noise layer and give it a radial-gradient
from white to black.
Because the div is absolutely positioned, it's now painted above the text.
We can set a darken blend on the darkness layer so
that the darker black of the text shows through.
Now we can add mix-blend-mode: color-dodge to the
spotlight div.
But wait, why doesn't the spotlight hide the text? Isn't white lighter than
black?
Nesting spotlight inside the noise layer puts it in a new stacking context.
When you set a blend mode on an element, it only blends with elements that
are behind it in the same stacking context. To use a metaphor, the spotlight
is inside a box (the noise layer). It can blend with the walls of its box,
but it can't reach outside the box to blend with things sitting next to the
box.
This changes how the box looks, but the box (the noise layer) is still
blending with the text in its stacking context using
darken.4
Finally, we add a new div over everything, with
mix-blend-mode: color-burn and
background: #414141 to turn all the remaining
non-white pixels black.5
A little JavaScript to make the circle follow the mouse and you've got a
spotlight!
If you'd asked me how blending modes worked before writing this, I would
have said "by iterating through them until you find one that looks right."
I think that's still kind of the case. Experienced photographers probably
have a stronger intuition about when to use a particular mode for adjusting
one of their photos, but I'd be surprised if most of them don't also just
tap the down arrow on the selector to preview what each of the modes would
do.
And I could have implemented all of this with canvas and it would likely
perform better, but I'd need to have learned the theory regardless, and it's
cool to learn what's possible with regular CSS nowadays 🙂
Two years ago, a colleague asked me "concretely, what's a way in which you
think AI is going to change the world?"
I said: the way we relate to and use software. We will stop writing or
installing it.1
We'll instead have an AIs that dynamically write our programs for us.
Two years later, I'm feeling even more confident about this. Claude Code and
Codex are the worst they'll ever be, and they're already one-shotting simple
webapps.
I wanted it for months, but never got around to making it myself, because to
code it by hand would take more time than the idea was worth. But now I can
get it made in 30 seconds, provided I have my laptop on me.
The next step could be making it possible to create these apps by typing a
prompt on my phone: "Write a program that does X, Y, and Z."
The model writes it and stages it somewhere. I'd maybe ask for a few
iterations, and once satisfied, deploy it on my site.3
I think this kind of capability would be really useful, and I'm sure the
ergonomics will improve rapidly (alongside their capabilities and possible
complexity, incorporating our phones' cameras and gyroscopes and what have
you.)
For now, it remains a niche power among those who are somewhat technical or
tool-making. But it seems kind of easy to commodify and market: what could
be more useful than making it easy to make useful things?
Interoperability will be important, and there will still likely need to be
some organizational effort to design and spread standards so that my bespoke
apps can interact with other people's bespoke apps.
But, basically, we're all going to become Geordi Laforge, Chief Prompt
Engineer, and everything will go great. There will be no problems.
in a bastardized interpretation of
fitness landscapes, i've recently been thinking about how every decision i make is a step in
some direction in an infinite mountain range. in this space, my altitude isn't
environmental fitness. it's something more like "personal value" or "amount
self-actualized" where you can imagine standing at the peak of a hill in this
endless mountain range as being highly satisfied with myself, highly engaged
in my life.