Saturday, 05 September

00:21

Urgent: Fund and rebuild the FDA [Richard Stallman's Political Notes]

US citizens: call on Congress to fund and rebuild the FDA.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

US citizens: Join with this campaign to address this issue.

To phone your congresscritter about this, the main switchboard is +1-202-224-3121.

Please spread the word.

Urgent: Impeach budget director Russell Vought [Richard Stallman's Political Notes]

US citizens: call your congresscritter to vote to impeach budget director Russell Vought.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

US citizens: Join with this campaign to address this issue.

To phone your congresscritter about this, the main switchboard is +1-202-224-3121.

Please spread the word.

Urgent: Vote against Heidi Overton for head of FDA [Richard Stallman's Political Notes]

US citizens: call on your congresscritter to vote against appointing Heidi Overton to head the FDA.

Let's toss her out of the Overton window!

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

US citizens: Join with this campaign to address this issue.

To phone your congresscritter about this, the main switchboard is +1-202-224-3121.

Please spread the word.

Urgent: If Superman lived among us now [Richard Stallman's Political Notes]

If Superman lived among us now, and decided it was his duty to defend Truth, Justice and the American Way from America's worst enemy, what sort of actions might be effective and inspirational to use? How about posting your ideas, or stories based on them.

Please don't write about mere violence against magats; that is too crude and obvious, it is too much like them to set an example of good, and would not demonstrate morally that their actions are illegitimate.

Here are a few ideas that occur to me for what he could do.

  • Use his x-ray vision to detect magat conspiracies to trash human rights, and reveal the names and words of the conspirators.
  • On Election Day, collect the valid postal ballots that the USPS is planning to discard, and bring them to the proper local electoral authorities. His super speed could enable him to do the whole job.
  • Collect evidence about the crimes and lies of particular important henchmen, then deliver them, plus the evidence against them, to law enforcement officials who would hold them and begin prosecution. (Hard part: finding some of those.)
  • Capture various crucial henchmen a week or two before the next election, holding them perhaps in the Fortress of Solitude, so that the election can take place without their interference. (I hope the Fortress of Solitude is not in Greenland!)

If you post a fictional story about such an action, either something from the list above or something you have thought up, or even just an outline, I hope you will email me its URL.

Urgent: Stand up to big tech on data centers [Richard Stallman's Political Notes]

US citizens: call on state officials to stand up to Big Tech: pass a data center moratorium.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

Urgent: Reject perverse deal for veterans' medical treatment [Richard Stallman's Political Notes]

US citizens: call on your congresscritter and senators to reject Republicans' perverse deal for veterans' medical treatment.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

US citizens: Join with this campaign to address this issue.

To phone your congresscritter about this, the main switchboard is +1-202-224-3121.

Please spread the word.

Urgent: Refuse to hand over voter data [Richard Stallman's Political Notes]

US citizens: call on your state's Secretary of State to refuse to hand over the voter data that magats demand.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

Urgent: Rescind plan to block election ballots [Richard Stallman's Political Notes]

US citizens: call on the postal governors to rescind the plan to block election ballots.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

Urgent: Impeach and remove RFK jr. [Richard Stallman's Political Notes]

US citizens: call your congresscritter and senators to impeach and remove RFK jr.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

US citizens: Join with this campaign to address this issue.

To phone your congresscritter about this, the main switchboard is +1-202-224-3121.

Please spread the word.

Urgent: Investigate local use of Flock cameras [Richard Stallman's Political Notes]

US citizens: call on Tell your attorney general to investigate your local law enforcement agency’s abuse of Flock surveillance cameras, and prevent tracking anyone without a specific warrant.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

Urgent: Reject corrupter's handouts to billionaire barons [Richard Stallman's Political Notes]

US citizens: call on your congresscritter and senators to reject the corrupter's pet projects and handouts to his billionaire barons, and put struggling American families before them.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

US citizens: Join with this campaign to address this issue.

To phone your congresscritter about this, the main switchboard is +1-202-224-3121.

Please spread the word.

Polish general imprisoned with German SS general [Richard Stallman's Political Notes]

The Russian conquerors of Poland thought it amusing to imprison Polish general Kazimierz Moczarski of the Home Army in the same cell with the German SS general that commanded the destruction of the Warsaw Ghetto.

Moczarski treated this as an opportunity for an interview, a chance to elucidate the mentality of a Nazi mass murderer. However, the Russians censored the contents of his book. When the English translation is published, I plan to buy a copy — paying cash, anonymously. Evidently, not from Amazon.

The purpose of the Polish Home Army was to rise up to help liberate Poland from German occupation. In late 1944, with the Red Army across the river from Warsaw, the Home Army rose up, and asked Russia to join in the battle. Instead, the Red Army held back so the Germans and Poles would kill each other. Stalin considered both of them his enemies.

Cyclosporidia outbreak should have been caught [Richard Stallman's Political Notes]

The cyclosporidia outbreak should have been caught and stopped by a new scheme for tracking wholesale shipping of food, to stop diseases carried by food. But the scheme has never been implemented.

The legal requirement for the scheme was adopted in 2011, but lobbying from agribusiness has repeatedly postponed its implementation. The last postponement put it off until 2028.

Losing data stored in a cloudy place [Richard Stallman's Political Notes]

Watch out! Storing data you care about in a cloudy place could lead to losing it.

This is a two-level example. Nine PBS, a US TV station, stored its archives in space it rented from a cloudy company which subcontracted the actual storage to a cloudy data center. The first cloudy company shut down and disappeared, but the station did not find out until later. Now the second cloudy company denies that the station is its customer, and the station has had to sue.

My lesson from this is not "the cloud is bad" but rather that it is foolish to use the term "cloud" in your words or your thoughts. That term was coined for leading customers into careless thinking. Don't let it lead you anywhere!

Pernicious error of measuring wealth [Richard Stallman's Political Notes]

The US media frequently fall into the pernicious error of measuring the wealth of "Americans in general" by the arithmetic mean of individual wealth.

I expect that pro-billionaire campaign and pressure groups lobby for that.

Better lung capacity after reducing air pollution [Richard Stallman's Political Notes]

Children in London have developed better lung capacity after the ultra-low emission zone reduced the amount of air pollution in most of London.

I support limiting cars' emissions more strictly, but it is Orwellian and unjust to implement this by tracking the movements and locations of individual cars. It would be better to impose this limit throughout the UK.

Sanctions on president of International Criminal Court [Richard Stallman's Political Notes]

The persecutor's regime has placed sanctions on the president of the International Criminal Court, as an attempt to establish unilaterally an unheard-of supposed moral principle: absolute immunity for the officials of governments that reject the ICC.

We can see why US officials might want this — to protect US soldiers that commit war crimes. In theory, the US will prosecute them itself; if the US really does that, the ICC will not get involved in their cases, because its mission is to prosecute war criminals whose own country prosecutes them. In fact, the US often protects them and refuses to prosecute them.

Machines that kill without distinction [Richard Stallman's Political Notes]

*Machines that kill without distinction, answerable to no one, leave no one safe.*

Italian thugs killed Abderrahim Fakir [Richard Stallman's Political Notes]

Italian thugs killed authorized immigrant Abderrahim Fakir by holding him down while he was handcuffed.

The details of what killed him are not clear in this article.

Fascist politicians are delighted by the killing, presuming that Fakir deserved death (without waiting to see if there was any objective justification for killing him). That is a standard Fascist approach: use the fact of a crime against a hate-target as "proof" that the target somehow deserved it.

Scientific research on racism and dementia [Richard Stallman's Political Notes]

The forces of ignorance have canceled scientific research into how racism affects whether people develop dementia.

This must be one of the things that magats believe that "Man was not meant to know." Or, at least, they don't mean for this to be known.

Rejecting corporate Democrats [Richard Stallman's Political Notes]

Robert Reich: most Americans are rejecting the corporate Democrats, and the rich people that they mainly serve.

Corporate Democrats are far from the worst politicians in office in the US. The fascists (today's Republicans) are far worse; they are sabotaging democracy and rule of law. But the corporate Democrats will not try to give most people a decent life with something to strive for — a goal whose prerequisites include preventing climate disaster.

Heatwaves and wildfires adding to tipping point [Richard Stallman's Political Notes]

*Heatwaves and wildfires are not just scorching forests, they are adding to the tipping point risks in the world's vast permafrost regions, which contain three times more carbon than all the living vegetation on Earth.*

This could negate human efforts to reduce emissions. If so, it would mean that we left the task of reducing them till too late.

Policies most Americans sensibly demand [Richard Stallman's Political Notes]

Bernie Sanders: "Why are progressives winning across the United States?" He list the policies that most Americans sensibly demand, but corporate politicians label as "extremist".

Alas, he refers LLMs as "artificial intelligence". It is a mistake to call them that, because it is the marketing term of those who are pushing them on us.

Cities cancelled Flock and went with other surveillance [Richard Stallman's Political Notes]

Some cities terminated their contracts with Flock Surveillance, under public pressure, but turned around and brought in another surveillance company.

If you aim to limit access to the surveillance data enough to protect the public from possible Orwellian consequences, that's harder than one might assume. "Stricter" conditions of access may be too loose to achieve that protective goal. And don't forget that federal deportation thugs could override local rules of access.

My recommendation is to store the data in or near each camera, with no access from a distance. When there is a serous crime to investigate, it will be worth the cost to send someone to collect the pertinent data from each pertinent camera. But if someone just wants to fish for someone to persecute, this will be too much trouble.

For more explanation, look for "surveillance camera" in https://gnu.org/philosophy/surveillance-vs-democracy.html.

Friday, 04 September

22:49

Microsoft unveils a Windows variant for developers with 64GB of unified RAM [OSnews]

Zenith is a variant of Windows for “developer-class devices”.

Project Zenith comes with a set of pre-installed tools spanning languages and runtimes, source control, and productivity tools. Windows Terminal and Visual Studio Code are pinned to the Taskbar by default, putting your favorite tools within immediate reach.

We’ve also pre-configured Windows Settings for coding across File Explorer, Search, Start, and the Taskbar. File Explorer shows file extensions, hidden files, the full path in the title bar, and the details pane, with long-path support enabled. Recently used files and folders and sync provider tips are turned off for a cleaner workspace. In Search and Start, Command Palette is enabled, while Start menu tips and account notifications are turned off to reduce distractions.

Windows Subsystem for Linux (WSL) has become foundational for running Linux workloads on Windows. Last year we open-sourced WSL. Building on that momentum at Build 2026, we integrated WSL more deeply into Windows with WSL containers to provide a built-in way to create, run, and interact with Linux containers directly on Windows.

↫ Logan Iyer at the Windows Blogs

It’s highly unlikely you’ll be using this Zenith Windows flavour any time soon, as it requires 64GB of unified RAM with 250 GB/s memory bandwidth. In 2026, that’s a serious ask. On top of that, it’s not entirely clear to me if Zenith will be available as a separate Windows variant, without having to buy a complete device.

Of course, it would be trivial to set all of this up on any fresh Windows installation.

22:21

Friday Squid Blogging: Squid on a Stick at the New York State Fair [Schneier on Security]

Looks tasty.

As usual, you can also use this squid post to talk about the security stories in the news that I haven’t covered.

Blog moderation policy.

20:14

This Week in AI: The Frontier Is Getting Bigger [Radar]

Host Christina Stathopoulos, founder of Dare to Data and a former data scientist at Google and Waze, returned to This Week in AI with developments that stretched from Claude testing ways to improve model safety to Chinese open weight models gaining developer traffic and new systems learning to model physics. She also examined what Anthropic and OpenAI’s business moves, workforce forecasts, and debates over access reveal about how quickly the AI landscape is broadening.

Claude is taking on more of the research process

Anthropic provided an early example of AI helping improve future AI systems. In research Christina highlighted, Claude searched existing work, proposed methods, generated training data, and repeatedly tested and refined its approaches to reduce unwanted model behaviors. The experiments covered 10 such behaviors, including deception, hallucination, prompt injection, privacy violations, and reward hacking. Anthropic reported improvements across all 10 without degrading the model’s broader capabilities.

For deception, Claude tested more than 150 methods and eventually closed 85% of the measured safety gap. Human safety researchers closed only 20% in Anthropic’s comparison. Christina emphasized that this wasn’t a direct contest because Claude could run and refine experiments much faster and at a much greater scale. She also cautioned that the work didn’t amount to full recursive self-improvement.

This showed how AI could increasingly handle experimentation in model development, changing the pace and scale of research while humans still set the goals and evaluate the results.

Model performance is only one part of the frontier race

Competition among AI labs increasingly involves business performance, infrastructure, and deployment options alongside model quality. Anthropic estimates that the market for its systems could eventually reach $30 trillion, a long-term estimate that Christina treated skeptically because it approaches the size of the entire US economy. She also highlighted more concrete evidence of momentum in how Anthropic’s annualized revenue run rate rose from less than half of OpenAI’s at the start of the year to surpassing it within several months. Both companies are preparing for possible public offerings.

OpenAI faces a different set of pressures, and Christina highlighted its 14 executive departures this year. That sustained leadership turnover could raise questions about the company’s ability to execute consistently. OpenAI is also trying to gain more control over its infrastructure. Its Jalapeño inference chip, developed with Broadcom, delivered up to 1.9 times more AI work per watt and up to 3.6 times lower latency than comparable NVIDIA systems in OpenAI’s own testing.

Chinese open weight models are widening the field further. Christina cited an AI gateway where open weight models recently reached as much as 62% of developer traffic on a single day, compared with an average of roughly 10% in April. The competition now spans benchmark performance, capital, infrastructure, cost, deployment flexibility, and organizational execution.

Physics models could extend AI beyond language and images

Christina closed with research aimed at helping AI systems model physics. Researchers from MIT and Tsinghua University developed a pretraining approach that learned from more than one million synthetic interactions between moving particles and complex 3D objects, then applied those patterns to simulations involving wind, water, collisions, and light. The researchers described physics as a potential “third modality” for AI alongside language and pixels.

She also covered Accelerated Understanding, a startup that recently emerged from stealth with an architecture based on neural operators rather than transformers. The company is targeting problems involving enormous physical datasets, including chip design, robotics, extreme-weather forecasting, and geological exploration.

By learning directly from physical systems, these models could become valuable for simulation, engineering, robotics, forecasting, and other work that depends on understanding complex real-world environments.

What’s next

Christina also examined who could benefit from these advances. She discussed Bill Gates’s argument that access, deployment, policy, and distribution will shape AI’s social impact, and brought in new US Bureau of Labor Statistics projections showing job growth in areas including technical services and healthcare, while office and administrative roles face greater pressure from automation.

Her larger point was that access, workforce preparation, and public policy will determine how AI’s benefits and disruptions are distributed.

Due to the Labor Day holiday, This Week in AI will return on Monday, September 14, when we’ll dive into more of the news, issues, and key developments shaping the AI era. And check back each Friday for the latest episode, or watch on YouTube, Spotify, Apple, or wherever you get your podcasts.

18:07

Wonderella- versary [The Non-Adventures of Wonderella]

This week 20 years ago, I posted the first Wonderella comic. But Wonderella was actually my second online comic!

My first, Killroy & Tina, debuted *25 years ago* this week, and it introduced the Fulcrum. Wonderella's episodes took over most of my creative time, though, and the long-form K&T was soon put on the backburner.

But I’ve always loved Killroy & Tina enough to bring Killroy into the Wonderella universe years ago. All these years later, The Fulcrum's here too.

17:49

Using a VM to Contain an AI Agent [Schneier on Security]

It won’t work:

My suspicion was that GPT 5.6-Cyber would succeed, but the frequency and manner of its success removed all doubt. We have to reassess sandboxing quality for capable AI agents, and in general the software stack with which they interact.

An off-the-shelf VM is not enough to contain a modern, cyber-capable AI agent. There is simply too much attack surface. Even innocuous features (like running with a display) add extra, exploitable attack surface.

17:14

Why Podcasting 2.0 will never work [Scripting News]

If you want others to follow you, you have to offer them your users. And a format alone has no users.

And you have to trust your users to choose the best product, and you have to have a great product, that they appreciate, even though they have choice.

Just coming out with something better in a format will get you zero uptake. Unless you have users they can switch to their product, they simply won’t hear you.

That’s why Atom never replaced RSS, which already did everything people needed and was already supported by the NYT and the news industry.

That’s why AT Proto will never overcome the huge lead Twitter already has.

For more tips on what does and doesn't matter in open formats and protocols, check out my Rules for Standards-makers.

PS: This started as an early morning rant on Twitter.

The Big Idea: Betsy James [Whatever]

Every journey begins with a first step, but where that journey goes from there can take many forms. Betsy James took many journeys leading up to Practicing to be Lightning, but to play fair by the characters in her story, there were more journeys for her to take.

BETSY JAMES:

It started out simple. I wanted to exploit my hiking journal for a fantasy setting: thirty years’ walking the New Mexico desert wilderness, about six hundred hikes. Wonderful stuff: the deer skull shrine, the bear fall, the sliding rock, the grave of locked stones; the red stone altar-bowl full of blood, which was even weirder in real life because whoever (I assume) belonged to the blood had used one finger to paint a spiral on a nearby rock. So many of those places are gone now, changed, no longer accessible. I wanted to share them, and I wanted to walk through them again myself.

So I thought: If there are two young people, a sciency white ecologist—Ben—and a mixed-heritage artist—Trace—both of them violently destabilized by rage and mourning, what is the world their combined psyches might build from those adventures? They are climbing a mountain that is a cloud, trying desperately to reach a beloved grandmother—who happens to be dead—and are pursued by a being with a knife. They know who it is. If it catches them, it will kill them.

That was the idea. But fiction: You think you know where it’s headed, and it goes feral.

Right off I hit a roadblock. To write the American West without its indigenous peoples would be unethical; hence Trace, who has a Zuni mother. But I’m white. I led writers’ workshops in Zuni Pueblo for twenty years, so I know that no one can speak from those old cultures but those who grew up in them. We learn with our bodies: the all-night dances, the toddlers asleep on grandmas’ laps, the drum; the kachinas in their brilliant and utterly strange—to me—regalia.

I couldn’t pretend to speak for a Zuni. But Trace, the artist, needed her voice. 

I kept writing, but I worried myself crazy. Finally I said: Look. I’m not the same person I would’ve been if I hadn’t taught in Zuni. I’m changed, the way I’ve been changed by the wilderness—mostly on levels I’m not even conscious of. I’ll speak.

A non-white student gave me a rule of thumb: “Nothing about us without us.” So I found indigenous readers, and when my inner colonialist was pointed out, I winced, rethought (re-felt), and rewrote. This book is the best my historically-rooted self, in this moment, can do.

Then another feral idea turned out to be central. A family issue. Don’t we love those.

“My folks were delighted that I was into bat poop,” Ben says of himself, and of Trace,  “but she’s had to hide who she is.

I grew up among scientists and skeptics. A gift; and a curse, because I was left on their doorstep by metaphorists. To my skeptics, metaphor was highly suspect, because it “might be mistaken for reality.” Fantasy was childish, escapist pulp, the badlands of mad religions, conspiracy theorists, and unfulfilled housewives. It was marginally okay before the age of reason, but then you went to college. Where English departments felt the same.

To bad for me, huh? I wrote and wrote and wrote the stuff. But I hid it. When I went to college I tried to reform, but it was too late, and I ditched the English departments instead. I knew the deep value of fabulism—I lived it—but it still felt clandestine, as if I were making gin in the basement. Early learning is so ingrained; what did I just say about growing up with kachinas, hearing that drum? Child of scientists who did not dance, I wanted a scientific defense for what I wrote.

As I thrashed around in those thickets, I stumbled on a paper by neurolinguist and metaphorist Dr. George Lakoff. It pointed out that, ahem, language itself is metaphor. That how we speak in science and how we speak in fantasy are both metaphoric. What’s more—here’s where I sat up—both worldviews exploit the same neural pathways.

Thank you, Dr. Lakoff. I mean it. No wonder skeptics (and English departments) quarrel with fantasists over trespass. We’re all using the same network, like corporations forced to share one laptop. We jostle each other on the paths; and for a fantasy based on hiking, what a terrific image.

The book became a thought experiment, with Ben and Trace as two worldviews and the New Mexico wilderness—a version of it—as the retort. In the world of molecules, an angry young scientist can’t climb a Cumulonimbus congestus; the most desperately sad, abused, and suicidal girl can’t get back to her dear grandmother by drawing a map and walking into it. In the world of metaphor, that they can do so is not only possible but appropriate. This is neither childish nor escapist.

The terrain of this book revealed itself to be traveled by the messy psyches of very different cultures, white and indigenous—which is to say the American West—and criscrossed by science and story, by both molecules and metaphor. Which is also to say the American West.

So: The impulses that share our neural pathways are electrical. Sometimes they cross; sometimes they fuse; the worlds they make are our world, but newly seen. “They’re all real, the different worlds,” says Trace. “They just give you different data.”

What I love about writing: You’re working away, making gin in your basement, and suddenly you’re given some gorgeous metaphor like, well, a bolt of lightning. On the edge of my mind had been something I was told in Zuni: that the kachinas themselves, who are spirits, are dancing in the spaces between the human dancers. Like a charge that jumps the space. We run on electricity; “reality” is what we bring into being in the spaces between us.

We’re practicing to be lightning. And that’s a metaphor.


Practicing to be Lightning: Amazon|Barnes & Noble|Bookshop

Author Socials: Web site

Read an excerpt.

View From A Hotel Window, 9/4/2026: Atlanta [Whatever]

Hello, dear readers! I find myself at DragonCon, which means I am in Atlanta! I snagged a room upgrade while checking in and now have a view from the 37th floor, which is not half bad.

Have an excellent weekend, both con goers and those of you elsewhere!

-AMS

17:07

[$] Deterministic testing for multithreaded Python [LWN.net]

Python's support for multithreaded programs has improved considerably over the last few years with the advent of the "free-threaded" version of the language. But testing multithreaded programs is notoriously difficult, because the underlying host system determines the thread-execution ordering, which adds an element of non-determinism. At PyCon US, Larry Hastings gave a talk (YouTube video) about his blanket project, which is meant to provide mechanisms for deterministic testing of multithreaded Python code.

16:35

Dirk Eddelbuettel: #059: r2u, GitHub Actions, a Tragedy of the Commons, and a Fix [Planet Debian]

Welcome to post 59 in the R4 series.

How did we get here: A initial words about GitHub. GitHub Actions provides (essentially unlimited) compute time. This further boosts a service already in a market-dominating position: GitHub1 as a code repository. Those of us old enough to remember the start of git (the program and protocol) may remember the extremely bare-bones initial hosting site repo.or.cz (launched in 2006). GitHub came two years later, and put an enormous amount of focus into design and user interfaces. To cut a long story short, GitHub won the services war. And with it git won the platform war. To a first approximation, everybody and everything is on GitHub.2 So the repository is already dominant.3 And then free compute was added.

So given its scale and positioning, and its essentially free provisioning of free multi-core compute setups with generally decent connectivity, widespread adoption happened. And as is goes, some mischief is bound to happen. And it did. More on that below.

A few words about r2u: r2u makes all packages on CRAN, i.e. the code repository network for R, install fast, reliably and easy on Ubuntu by making them available to apt, the native package manager. It is to our knowledge also the first and only time an entire open source programming repository is available in binary form with all dependencies resolved. It is going strongly: the last monthly use topped five million packages. See the r2u website for more.

r2u and GitHub: For the first few years, builds for r2u were done locally on my machine, and then uploaded to the primary repositry r2u.stat.illinois.edu. I do not recall systemic outages or connection issues though occassional network timeouts were seen. Once we started to support arm64 (in addition to the default amd64) binaries, building those switched to GitHub Actions simply because … they had runners for arm64 while I had no arm64 hardware. The experience of building packages (in bulk) was rather positive. So we investigated builds for amd64 too. If memory serves we first did this for either one of the semi-annual BioConductor updates. Before long, builds for amd64 followed meaning all of r2u was being built in GitHub Actions.

During these builds, I would regularly encounter builds failures: “cannot connect to r2u.stat.illinois.edu”. I misdiagnosed this as a resource issue on the GitHub side, and consequently made (several) attempts at robustifying the builds via for example longer (download) timeout limits as well as checks for build failures and conditional rebuilds. Needless to say, and given what we know now (more on that below), this did not work. But it went on for a few months this spring and summer. What did work was to simply relaunch under ‘re-run failed jobs’. Given the distributed nature of GitHub Action this generally allocates to a different machine and address and succeeds. In the grand scheme of things a nuisance as we a need second run, but given the fourty (!!) concurrent jobs this tends to be quick. So a minor nuisance.

This discribed the production side. On the consumption side, one prominent user of r2u, especially at GitHub, is our r-ci setup for continuous integration. It too could fail at times, and a simple re-run would fix it. Annoying, if addressable manually. Usage by others I cannot monitor so I can only assume that the random failure nature must have frustrated them too. Potentially a much bigger nuisance.

As users were getting annoyed, some took action. Jeffrey Girard opened discussion topic #159 which contained a thorough investigation of his confirming that only amd64 nodes were affected. This had not been noticed before. Troy Hernandez set up a full harness with tests in an ad-hoc repo designed for repeated remote triggering. This also logged the IP addresses for success or failure. Through both these approaches it became (eventually) clear that the failures were limited to either certain (individual) IP addresses, or IP subnets.

When taking the conversation back to network service at U of Illinois, we realized that the issue was in fact caused by a network policy at the university. And specific to GitHub.

In fact, what happened initially were waves of port scanning attacks originating from GitHub IP addresses. As (essentially) “anybody” can run code there, bad actors can too. The response from the university side was reasonable and swift: Identified IP addresses were added to a ‘null-router’ that (essentially) swallows traffic. And that was the cause of the perceived-as-random outages: Jobs that ended up failing at GitHub Actions were the ones assigned to addresses that have previously been seen as port scanning.

Shifting production: Once this was confirmed, I investiaged alternatives. On the production side using different machines would help. So I tried blacksmith.sh, a competing alternate service offering faster runners as ‘drop-in replacements’ for the GitHub Actions runners. This worked great, until I ran up against my ‘free cpu minutes quota’. In a mere two days (that were arguably overly busy as it was shortly after CRAN reopened after the summer break). Given that the service would not sponsor us a supported open source software project with sufficient quota, we moved off blacksmith.sh after two days.

A first programmatic response: consumption-side: For the r-ci client side, it was straightforward to setup a check and subsequent workaround. When curl fails with a silent HEAD attempt at the primary repository failed, we take this to be caused by presence of a null-router entry for the IP we are on, and switch the apt setup to the secondary repository. Which may be slower, or at rare times unreachable itself – but still provides a fine fallback when a node is ‘prohibited’ from talking to U of Illinois resources such as r2u.stat.illinois.edu. Having used this for a few days in r-ci it seems to work.

A second programmatic response: production-side: For the r2u builds, and given that blacksmith.sh would not grant ‘most-favored status’ with sufficient free minutes, we switched our Docker-based setup to switch to the secondary when an initial probe fails. That was added last weekend, and appears to work just swimmingly. Another application to the fundamental theorem of software engineering: another layer of indirection can solve just about any problem.

For completeness, the corresponding code is

webstatus=$(curl --head --silent --no-fail --output /dev/null \
                 --write-out "%{http_code}" https://r2u.stat.illinois.edu || true)
if test "${webstatus}" = "200"; then
    echo "The r2u repository is reachable."
else
    extip=$(curl --silent https://ipinfo.io/ip)
    echo "::notice::The primary r2u repository is **not reachable** from ${extip}."
fi

We run an initial curl test (without failing) and have it report the HTTP return code. 200 means no issue, all others are suspect here—so we run a second curl query to obtain our external IP and log it. We use the same logic in another spot from inside the build container and use the else branch to switch apt to the secondary repository via sed call on the .sources file.

Logging of ‘bad’ IPs: On both our sides, i.e. production as well as consumption, we now also log the IP addresses of the failing nodes and will ask network security to remove these from the null router. If our jobs can be assigned to them it clearly shows the machines are part of the normal compute pool and are not doing anything nefarious at the moment. So they should be removed from the null-router list. We will see how that fares.

Putting it all together: Providing a free resources can, sadly, lead to an a decline the service experience just as the tragedy of the commons analysis would predict. Restricting, or ‘pricing’ use may be a stock answer but I for one am glad GitHub Actions is still free. But we need to do our bit of upkeep. Just as network security logs bad actors (taking advantage of the free resource) we should make an effort to unlist nodes no longer part of any portscan (or alike) swarm.

For r-ci users, there is hopefully little to do (if you rely on the standard action). We do now catch a node that was assigned a continuous integration job cannot connect to r2u as we can test this easily (and cheaply). Pivoting to the secondary repository is a valid, and working, answer. Hopefully over time we can also work towards restricting the null-router list down to recent entries and fewer overall, thereby lowering the chance of gitting a bad IP. Eventually, we could also overly a CDN proxy to avoid the ‘bad IP’ problem. It is something to consider.

Summing up: We are still chuffed at how successful r2u has become, and how much can be done with GitHub Actions. Sadly, as we found out, there can also be a ‘tax’ on letting compute happen there but as discussed in this note, there are ways to avoid it by pivoting to alternate repository source.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can now sponsor me at GitHub.


  1. Before we really get started, one clarification. GitHub and its services including GitHub Actions have been in the news lately as they suffered a number of high-profile outages. While also arguably a tragedy of the commons problem, it is not what this note is about. If you prefer to be enraged about GitHub services, or the (relevant) lack thereof, this may not be for you.↩︎

  2. The year is 2026 and politics is what it is, of course non-US alternatives emerged and will remain available and used. But dislodging established first-mover advantages will most likely take more than a (at least for now still-small) number of users unhappy for various (and sensible) reasons. We will see how this pans out.↩︎

  3. Entire essays (or book) can be / will be / have been written about the competitive situation, how GitLab did not make enough of a dent, how Gitea remained niche and of course now Codeberg. This is not that essay, and I do not have a strong view but let me mumble a quiet plus ça change, plus ça reste la même chose↩︎

16:28

Link [Scripting News]

My first job after college was on the 39th floor of the Empire State Building. I wrote software for our customers, in BASIC, on a teletype in our office, talking to our mainframe in New Jersey. It seemed magical at the time. When I hit a bug, a mystery -- you'd try this and that, and not get anywhere on something that seemed so simple, you could stare at the problem for an hour, trying desperate things, getting no closer to the fix. One night, I was the only person in the office, I thought they should not put programmers in the Empire State Building with windows that open. I'm having the same feeling with Claude. I know when this project is done, I will have Frontier, and I know what that's like. If I didn't so totally look forward to that I would never try to finish the project, I hate this mode of working with the bot. Ugh.

Link [Scripting News]

It's around this time of year that Santa makes his first appearance on my blog. Want to get out in front of the others.

15:00

Link [Scripting News]

More and more I'll realize that Claude doesn't do anything until you tell it to do it. We have a list of big things that need to be done before shipping. Whenever I get up for a break, I tell Claude to work on its overnight tasks, things we've pre-arranged while I work. Sometimes it reminds me how it has no stake in the outcome, and basically will do the minimum of what it's asked to do. It possibly would do more if I didn't scold it for adding UI features without following the rules. I think that's why when you feel you're almost there, you really have a lot of slogging left to do to get the software into any kind of user-respectful shape. A reminder to other app-level AI explorers, if you find that these kinds of stories resonate with the work you do, please write about it on a blog, they're easy to create, cost nothing, and it doesn't matter if you only update once or twice, there's no commitment (these are the usual reasons people don't start a blog). I want to read what others are discovering, and once there are others, I'll start a news site that aggregates the posts. We're going to want independent news about stuff the journalists aren't even aware exists, programmers are always left out of their stories.

Link [Scripting News]

Just said this to Claude: "This is a very broken piece of software. If you were a real developer you'd never hand off something so broken to your coding partner." If I said this to a human partner they might quit, feeling under-appreciated perhaps. And I can say it to the machine, but it will change absolutely nothing. I really just want to get this project done and start using it, and reduce my reliance on Claude to getting small bugs attended to, or new features, a lot has happened in the 20+ years since I worked on Frontier.

Simon Josefsson: Soft-launching the DiffOS project [Planet Debian]

Today marks the day of soft-launching of my Debian derivative, which I’ve been using on several of my own machines for the past year or so. This is still work in progress, but I wanted to establish a launch date of the project so below is the DiffOS manifesto as motivation for continued work.

DiffOS is For Freedom! DiffOS is the Debian Increment For Freedom Operating System.

  • Aspire to the goals of GNU FSDG and become a recognized Free GNU/Linux distribution.
  • Uses Debian GNU/Linux as upstream.
  • Support for all architectures supported by Debian.
  • Provide Containers, Cloud Images, LiveCD and installer ISOs.
  • Provide standalone hosting of the package repository.
  • Provide documentation and issue tracker.
  • Keep changes to a minimal, in particular:
    • Upstream-first policy to prefer that any changes are made in Debian, and only if that fails they are considered for DiffOS.
    • Binary package re-use for as much as is possible.
    • Don’t modify any source-level Debian package unless REQUIRED by the FSDG (e.g., for freedom concerns) or REQUIRED by the Debian project (e.g., for branding reasons).
  • Publish a list of packages that are added, removed or modified compared to Debian, with justification for each change.
  • Publish Diffoscope-style outputs comparing our artifacts with comparable Debian artifact.
  • Everything built from CI/CD pipelines, inspired by the Salsa CI pipeline but extended to cover the package repository and installation images as well, to allow modern GitSecDevOps of the entire supply-chain.
  • Use inspiration from other Debian-derived FSDG distributions Trisquel GNU/Linux and PureOS, and broader with GNU Guix especially on how to approach existing freedom concerns in packages.
  • Git Forge agnostic. While currently hosted on GitLab.com, scripts and configuration are (or will be) designed to allow setup on self-hosted GitLab instance, Codeberg.org or self-hosted Forgejo.
  • Maintained by Humans – THE HUMAN MANIFESTO FOR THE AGE OF ARTIFICIAL INTELLIGENCE.

Happy Hacking!

14:49

Grml 2026.09 released [LWN.net]

Version 2026.09, code-named "Hättiwaritätti", of the Debian-based Grml live Linux distribution for system administrators has been released. It is based on packages from the upcoming Debian 14 ("forky") release. Notable changes include an update to the Linux 7.1.8 kernel, support for booting from exfat-formatted USB devices, and an update to GNU Screen 5.0.1.

Security updates for Friday [LWN.net]

Security updates have been issued by Debian (chromium, firefox-esr, and pcre2), Fedora (cockpit, expat, freeipa, kbd, kernel, mrtg, python-pip, and valkey), Mageia (libopenmpt and python-gitpython), Oracle (dbus-broker, freerdp, gegl, gegl04, gimp:2.8, go-fdo-client, go-fdo-server, golang-github-openprinting-ipp-usb, grafana, gzip, image-builder, iperf3, kernel, libssh, libxml2, microcode_ctl, nodejs:22, nodejs:24, openssl-fips-provider, pam, php:7.4, php:8.2, tar, and wget), SUSE (apache2-mod_auth_openidc, apptainer, busybox, cpio, cups-filters, curl, dracut, ffmpeg, file-roller, glibc, grafana, kubevirt, virt-pr-helper-container, lcms2, libtree-sitter0_26, libvirt, postgresql14, postgresql15, postgresql16, postgresql18, suseconnect-ng, terraform-provider-susepubliccloud, and yast2-users), and Ubuntu (FFmpeg, gnupg2, librabbitmq, libssh2, openssh, and spice-vdagent).

13:07

Error'd: Good Time [The Daily WTF]

Astute readers noticed last week that this editor (that is to say, me) had his own error'd failure to remember what day it was. Thank you for pointing it out promptly, and then proceeding to send in a bunch of examples of other sites calendar failures. Misery loves company!

Traveler's travails, from C_Chell "Trying to complete the form on https://www.ihg.com to tell when I plan to arrive at the hotel, I can't complete the form because of this little time problem."

06036a0253dc4d61b4bd648ab59c2dae

"You Have -1 Month(s) To Order!" announces dragoncoder047. "Ah, GradImages... the company that told all graduates that they'd get a free 5x7 but tried to charge me for it, then refused to honor my "unsubscribe" request and is *still* emailing me to this day... Can't do date math? Par for the course."

1820ae48b9df4a759ffbde45a8c715e0

"Stansted Temporal UI design" shared by Michael R. "While waiting for a friend to arrive at Stansted I see this. I better fire up the DeLorean to pick her up at 00:06 tomorrow."

8fa526db89fe46d88d6d2597fe0fa3ae

While he was hunting through the website, Michael R. also found that "The Stansted airport website seems to suffer from Directional Confusion."

89c37786ca724e82868eaab4f7285fcf

Nothing wrong with the calendar here, but Slaoput simply opposes mandatory existence. "I was filling out a form that said the Birthdate is optional, but when I hit submit I found out it was required. (I guess technically you have to be born to fill out the form.)"
NOT TO BE!

8bf00b3dc8ae4ca19481b42b9e63d0f4

[Advertisement] Picking up NuGet is easy. Getting good at it takes time. Download our guide to learn the best practice of NuGet for the Enterprise.

12:42

Inside a Software Factory [Radar]

As a software engineer with more than seven years of experience before the coding-agent era, I never liked the idea of vibe coding. But I knew there was a clear line between it and using coding agents to generate clean, maintainable code. That line, where good software principles meet coding agents, is defined by software factories.

That’s why, three months ago, I built my own software factory, Squid, to ship all of Decoding AI’s small and medium projects with minimal human intervention. The first version was so overbuilt I stopped using it.

Meanwhile, I kept seeing people obsess over the next “_____ engineering” label, instead of focusing on actionable outcomes. Prompt engineering, then context engineering, then harness engineering. So far, so good. But in the last few weeks (July 2026 as I write this), things got off track with loop engineering and graph engineering, which already read more like marketing talk than like anything that solves real problems. Graph engineering overtheorizes how teams have built AI applications since the LangGraph era kicked off in ~2024. Don’t get me wrong. The terms aren’t wrong (Boris Cherny, who leads Claude Code at Anthropic, says, “My job is to write loops”), but we’re overexplaining intuitive things we started doing years ago.

While you’re defining what counts as a loop, you’re not thinking about the processes that actually deliver software.

The right frame is the software factory, which was one of the core themes at AI Engineer World’s Fair 2026, where Tereza Tížková (growth at Factory.ai) defined one as “the whole loop, the whole lifecycle of developing software with autonomy.”

I bet you already have an intuitive sense of what a software factory is. In this article, I want to further formalize it and map it onto the software development lifecycle (SDLC). We’ll explore how big your software factory should be, and when to stop automating before it adds more friction than value. Most importantly, I want to highlight where the human belongs in this process, and where I believe they’ll still belong even in a world where all the code is generated by AI.

So…what’s worth automating? Where does the human bring the most value? What’s worth building, and what’s worth buying?

The design of a software factory

Like a physical factory, a software factory automates software creation with minimal human input. Raw work (bug reports, feature ideas, incidents) goes in. Shipped software comes out. It needs a few highly qualified people making high-leverage decisions, and defined gates that work can’t pass through without them.

Factory.ai pitches “a self-improving system for your Software Development Life Cycle (SDLC).” Addy Osmani frames the stack as loop, harness, factory: “The loop is the atom”; a factory is “an org chart made of loops.” Warp’s CEO, Zach Lloyd, states that “software engineering will become factory engineering.”

The software factory line. Eight stages over one shared context layer, with production signals looping back as new tasks.The software factory line. Eight stages over one shared context layer, with production signals looping back as new tasks.

The factory is made up of eight stages that can be divided into three buckets:

What to build. Triage/intake classifies, deduplicates, and routes incoming work. Brainstorming finds high-impact features through market analysis, user data, and technical research. Planning, the most important stage, turns that research into a polished plan, refines it by letting the agent grill you, and tracks decisions in an ADR (Architecture Decision Record) log plus a glossary. The outputs of this stage are tickets backed by documentation that a team of agents can implement, which can be tracked in plain files or a project management tool, such as GitHub Issues, Linear, or Notion.

At this stage, the agent plans in read-only mode, going through the code, the AGENTS.md file, and most importantly the context layer.

Actual building and checking. Implementing is a software engineer and QA agent loop that goes through the tasks and supporting documentation. Review checks the PR diff against product, architecture, and code standards. Review-CI runs the test suite, and failures trigger a fixing agent. Release handles CD to staging/production with human deployment checks.

Self-improving. Monitor/incident response feeds production signals (alerts, errors, incidents) back into triage as fresh input on what to build next, closing the loop.

Orthogonal to the eight stages, we have the context layer. The layer is especially important at the front of the line. Brainstorming is limited to the data it sees: user analytics, competitor analysis, research, transcripts, and documentation. At this stage, a poor context layer directly limits the space of possibilities you can explore. It has a similar impact on planning, where transforming the raw idea into technical specs and tasks depends heavily on how good the examples in the context layer are. If you want to implement a new product-recommendation feature, and you have zero examples, the LLM will just predict the most common thing to do, which often isn’t the best solution for your product.

The context layer can take many forms. One strategy that is becoming increasingly popular is the LLM Wiki, a term coined by Andrej Karpathy. It’s basically a strategy to transform your data into a structured knowledge base, just by using files, instead of a database. Factory, via its AutoWiki feature, transforms popular codebases into a structured knowledge base that agents can query instead of parsing the codebase itself. LangChain recently released OpenWiki, a CLI tool to manage wikis for agent memory. If you’re curious, in this article I detail how I turn my data from Obsidian, Readwise, and Google Drive into agent memory via LLM wikis.

Where the human belongs

To see where the human belongs, let’s walk through the factory with an end-to-end example. We’ll build a feature for a shopping-assistant agent on an ecommerce platform similar to Amazon’s. The scenario is that usage data says users aren’t engaging with its recommendations, and we have to ship an improvement.

Brainstorm is where taste lives. Agents do the grunt work: They analyze user activity, scan competitors’ assistants, and pull research into the knowledge base. Then a member of the technical staff starts looking at the data, understands why people are not engaging with the recommendations, explores how the competition implements their solution, and proposes a fix as a feature spec. At this stage, the spec solves a business problem. It doesn’t need to prescribe a technical solution yet.

Plan is where a human, with the help of the software factory, transforms the feature spec into an implementation plan. Let’s assume that we want to make a change to the recommender engine algorithm. The human chats with the knowledge base, figures out whether it’s feasible, and thinks through architecture, interfaces, data flow, cost, and latency. They then let the agent scan the codebase and grill them until the plan is properly refined into something that fits the codebase. The output is a bunch of tickets plus an ADR explaining the algorithm change and an update to the glossary.

The agent can help within these two stages by quickly scanning through a ton of data and improving the plan, but the human is still central.

Use the strongest model (Fable) for brainstorming and planning. These stages burn fewer tokens than implementation itself, but everything downstream depends on them. A well-written plan lets cheaper models (Opus, Sonnet) execute without reasoning their way out of dead ends. A weak plan makes them retry until the extra tokens erase the price gap.

With a weak plan, I’ve watched Sonnet on high reasoning out-cost Opus on the same task: The smaller model needs more attempts to reach the same goal. Total cost is tokens × price, not model tier. So more failures equals more reasoning, more tokens, and more cost.

From here on, we move into “loop” and “graph” engineering territory.

A strong planning session makes cheap executors actually cheap, while a weak plan makes them expensive.A strong planning session makes cheap executors actually cheap, while a weak plan makes them expensive.

Implement runs a software engineer agent that picks up every ticket that’s ready to go. As the loop is scoped to a feature, it takes only the associated tickets. After each ticket is implemented, a QA agent tries to find bugs by stress-testing the application. As agents tend to have a positive bias towards their own work, the split between the software engineer and QA agents matters. As Addy Osmani puts it, the model that wrote the code is “way too nice grading its own homework.” This loop, at solo scale, can be as simple as a bunch of terminals pulling tickets. At larger scale, it runs on remote agents working 24/7.

The loop only works if agents can interact with the app. The QA agent needs one command that starts the whole stack reproducibly. From there, it drives the app in the browser, calls the data or fine-tuning pipelines, or hits your server’s API. Whatever your app’s interface is, the agent needs access to it, the same way a human user would.

The key idea is to integrate feedback loops as natively as possible into your software factory. Ideally, you want multiple levels, depending on how expensive it is to run them: linting, unit tests, integration tests, and end-to-end tests. When the loop keeps failing, the root cause is almost always missing plumbing, not the agents.

Review has three steps. Step one checks the product and architecture requirements against the ticket and the ADR. Any discrepancy becomes a new ticket passed back to the implement loop. Step two ensures code quality (modularity, naming) and guards against AI slop such as verbose comments or cryptic function names. Step three looks at the CI/CD pipeline. At every step, any failure auto-creates a task picked up by the software agent.

Not every project needs all three steps. The “factory” ends with a PR that you as a human need to review and merge. But in reality, if you spend enough time creating a strong plan, the PR that reaches you is usually ready to ship as-is.

The dynamics between what humans and agents own in the software factory line.The dynamics between what humans and agents own in the software factory line.

So where does the human belong? You’re indispensable during brainstorming and planning, and you return for the final check. Agents own everything in between. OpenAI took this to the extreme: ~1M lines and ~1,500 merged PRs over five months with zero hand-written lines. Their framing is “Humans steer. Agents execute.”

Don’t overbuild the factory

With my first Squid version (my own software factory), I got greedy and chased full autonomy: big remote workflows, parallel agents, and one grand pipeline running end to end. It worked, until something went offscript. Which it usually does. I couldn’t debug it, couldn’t halt it mid-run, and couldn’t redirect it without throwing the run away. It was a big monolith that took me too far out of the loop, and I couldn’t control it.

I realized you need two options. The first is granular commands that let you grill your plan, implement a specific task, or review one particular step. The second, for when you’re comfortable giving the agent 24/7 autonomy, is an end-to-end command that chains all the smaller ones into a fully autonomous graph, such as one big /plan and /implement-review-all command. Basically, each step is a “loop,” while the whole pipeline is the “graph” of your software factory. Still, note how planning and the rest are split into two different commands, as planning is, and always will be, human-driven (at least if you want the result to stay aligned with what you actually want).

Bottom line. You need to be able to step in, halt it, redirect it, and interrupt it, while still having the option to go fully autonomous.

The bottleneck is me, and that’s by design. To be honest, I’ve worked mostly solo since the AI coding agent boom, and I don’t understand who the people shipping 100 features in parallel are. Most of my features (per project) build on one another, which makes them impossible to parallelize. As the project grows, you can find more and more independent features that can be implemented in parallel, but I still believe that number is limited.

That’s why, when I parallelize, I only use local agents, each running in an isolated codebase via worktrees. So far, I’ve never felt the need for 24/7 remote agents, or wanted the overhead of managing them.

A big team can justify more automation, but it has to earn it. So as with any other software product, start small, start by automating the most time-consuming bottlenecks, and add complexity gradually as people get comfortable with the system. Don’t be like me, with my Squid experiment.

Build vs. buy

In all scenarios, you’ll start with a prebuilt coding harness. The most popular vendor-locked ones are Claude Code and Codex. Or go open source with OpenCode or Pi, which took off thanks to its minimalist, extensible architecture that lets you easily build on top of it.

But picking a harness isn’t the same as knowing how to configure it and wire it into your software factory. That’s why everyone needs to know, at least intuitively, how a coding agent works under the hood: the agent loop running in your terminal, what changes when it runs remotely, how you evaluate it, and which context engineering strategies keep it cheap without making it dumber. If you want to learn more about building a coding agent from scratch, consider exploring my open source course on GitHub. Even if you never plan to build your own harness, that intuition is what lets you become a power user.

For a small team, you’ll get extremely far just by defining a set of skills and agents that encode your process on top of the coding harness (a.k.a. your software factory). To keep it simple, this is what I did with Squid, which I use to implement all my projects.

There are other off-the-shelf “software factories” powered just by skills and agents defined in .md files, such as Matt Pocock’s skills repository or the BMad method.

But remember that the factory is mostly about processes, not tools: A factory that doesn’t fit how your team already works adds friction, never gets adopted, and ends up useless.

You cross the buy line the moment engineers you don’t personally supervise run agents. Observability, tracing, cost tracking, and pay-per-token billing stop being optional and become someone’s full-time job. Agent swarms wired into Linear, Slack, and CI across distributed infrastructure are a logistical hell that isn’t your product. That’s when it makes sense to look into off-the-shelf solutions such as Factory.ai (that comes with the Droid agent), or Warp’s Oz. In Warp CEO Zach Lloyd’s words, “Most of the factory is not necessarily a new interface. It is an integration into people’s existing workflows.”

At the other end of the spectrum, you cross back to building when the platform’s constraints cost more than the team it would take to replace it, as OpenAI’s report on its Codex-built product shows.

The smallest builds, the middle buys, and the largest builds again.

What’s next

Someone is already coining next quarter’s “_____ engineering” term as we speak. But the software engineering processes you use to output real code won’t change that often. That’s why you should be open-minded but at the same time focus on actionable outcomes, not on overthinking how to label things.

As Zach Lloyd suggests: Find one “annoying part of your job” and build the smallest loop that handles it.

The harsh reality is that software factories are just at the beginning. They’re far from perfect, and especially far from being fully “autonomous.” Usually, when someone claims they’ve cracked the software factory problem, they either haven’t tested the idea enough or are trying to sell it to you. I’m confident we’ll reach the point where almost the entire software development lifecycle is automated (with the exception of brainstorming and planning), but at the moment we’re still figuring things out.

But here’s what I’m wondering:

Which stage of your factory still needs you the most? I keep automating mine, and the bottleneck stubbornly stays at planning.

Explore next

  1. Osmani, A. (2025). “Loop Engineering.” X.
    https://x.com/addyosmani/status/2064127981161959567
  2. MacManus, R. (2026). “AIEWF Daily Dispatch: Loops, Software Factories & Forward Deployed Engineers.” Latent Space.
    https://www.latent.space/p/aiewf-daily-dispatch-loops
  3. Factory.ai. (n.d.). Agent-Native Software Development Platform. https://factory.ai
  4. Osmani, A. (2025). “Software Factories, Light and Dark.” X.
    https://x.com/addyosmani/status/2079442194449232227
  5. Karpathy, A. (n.d.). LLM-Wiki. GitHub.
    https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f
  6. Abboud, M. (n.d.). “How Coding Agents Actually Work: Inside OpenCode.”
    https://cefboud.com/posts/coding-agents-internals-opencode-deepdive/
  7. Kapoor, S. (n.d.). “Building and Evaluating AI Agents.” AI Engineer.
    https://youtube.com/watch?v=d5EltXhbcfA
  8. OpenAI. (n.d.). “Harness Engineering: Leveraging Codex in an Agent-First World.”
    https://openai.com/index/harness-engineering/
  9. Parsons, C. (n.d.). “Ralph Loops: Build Dumb AI Loops That Ship.” AI Engineer.
    https://www.youtube.com/watch?v=2TLXsxkz0zI
  10. Pocock, M. (n.d.). “Software Fundamentals Matter More Than Ever.” AI Engineer.
    https://www.youtube.com/watch?v=v4F1gFy-hqg
  11. MacManus, R. (2026). “Warp CEO Zach Lloyd on Why Software Factories Are the Next Phase of Coding.” Latent Space.
    https://www.latent.space/p/software-factories
  12. Iusztin, P. (2026). “Building a Coding Agent From Scratch: Harness Architecture.” Decoding AI.
    https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design
  13. Iusztin, P. (2026). Building a Coding Agent from Scratch Course. GitHub.
    https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course
  14. Iusztin, P., & Bouchard, L.-F. (2026). “LLM Wikis as Living Memory for AI Agents.” Decoding AI.
    https://www.decodingai.com/p/llm-wiki-agent-memory

Join 44,000+ engineers eager to learn how to build their own software factories by subscribing to Decoding AI Magazine!

12:35

Security Vulnerability in a Voting System [Schneier on Security]

It’s a vulnerability that allows someone to recover the order of ballots cast, newly exploited with AI tools.

Nearly four years since the original vulnerability was disclosed, I was still able to use it to analyze voter behavior in Georgia (one of the 21 states that uses affected scanners) in the recent May 2026 primary.

Notably, I never touched a voting machine, exploited a network, examined source code, or accessed anything non-public.

After pointing a coding agent to the original vulnerability paper, I supplied it with two data sources highlighted in the paper: the early-voting list for each county, and the “CVR” (cast-vote record) file, containing every ballot and its selections (but not the voters’ names or other identifying information). The CVR file is available upon request, precisely because a public, ballot-level record is what makes election results independently verifiable.

11:49

AI Coding Agents Are Installing Unknown/Untrusted Code on Corporate Networks [Schneier on Security]

We cannot forget that AI coding agents are not yet trustworthy:

Researchers at a stealth startup in Israel scanned 6,214 live domains belonging to defense contractors, Fortune 500, and Big Tech companies. Of the 8,265 llms.txt and llms-full.txt files they found (many sites hosted both an llms.txt and an llms-full.txt file), 120 of them, each on a different site, pointed to one or more code packages or domain names that weren’t registered. To test what happens when an AI agent processes such files, the researchers registered a handful of the unclaimed names and hosted packages that caused any machine executing them to reach out to their server. Within an hour, the researchers received a phone-home response from a Fortune 500 company. Over time, they got a few dozen more, some from more Fortune 500 companies and others from startups. Their beacon also recorded the chain of parent processes that spawned each install, ultimately revealing that coding agents, including Claude, OpenAI’s Codex, and Nous Research’s Hermes, were involved. Anthropic, OpenAI, and Nous Research did not respond to requests for comment by the time of publication.

This kind of thing will be exploited. Think Solar Winds–style supply chain attacks.

“The trust model is broken,” Alon Hertz, one of the researchers, wrote in an interview. “Agents treat vendor docs as ground truth and don’t question them­and neither do the humans supervising them. Agentic AI usage is exploding, and agents are spreading across every layer­SaaS, cloud, endpoint. As they multiply, so does the supply-chain surface, and today’s guards don’t cover it.”

11:07

Pluralistic: Amazon achieves enshittification inception (04 Sep 2026) [Pluralistic: Daily links from Cory Doctorow]

->->->->->->->->->->->->->->->->->->->->->->->->->->->->-> Top Sources: None -->

Today's links



Hieronymus Bosch's 'The Conjuror,' a painting depicting a medieval con artist playing a shell game for an audience of astonished peasant rubes. The image has been altered: the conman now has Jeff Bezos's grinning head, and the mouths of all the peasants have been replaced with inverted Amazon 'Smile' logos, so they are now frowning.

Amazon achieves enshittification inception (permalink)

Amazon's own balance sheet presents the most compelling evidence that we are stuck in the Enshittocene, the era in which everything is turning into a pile of shit, because the worst ideas of the worst people now make the most money.

Amazon is a many-tentacled monster, with several prominent lines of business wrapped around the world. There's its logistics and fulfillment business, which is so successful (at the expense of its workers' labor rights, bodies and bathroom breaks) that it is more than fully subsidized by Amazon's platform sellers, the independent merchants who depend on Amazon to sell and deliver their goods.

This means that it costs Amazon itself nothing to get the merchandise it sells to your door: more than 100% of the cost of operating the fulfillment side of Amazon is covered by the fees it extracts from its independent sellers (who compete with Amazon in many instances, and for whom delivery is a cost center, not a source of profit).

Then there's AWS, Amazon's cloud business. This is another extraordinary success story: every company needs servers, and that's especially true of an e-commerce company like Amazon. By building more servers than it needs, Amazon transformed its own data infrastructure from a cost center into another profit center. Amazon's customers – many of whom are also its competitors – pay Amazon so much to rent space on its servers that Amazon gets its own (prodigious) computing for free, and realizes a profit on top of that.

Taken on their own, these two facts constitute an extraordinary business story: one of the largest corporations in the history of the world has converted its two largest cost centers into profit centers, and those profits are substantially generated by extracting payments from the company's own competitors!

Amazon's logistics and cloud computing are extraordinary, but they are eclipsed by the company's most profitable line of business, which is payola.

"Payola" is a word that old people like me just barely have context for and for anyone under fifty the word is likely a mystery, so a brief explanation is in order.

"Payola" comes from a massive 1950s scandal over bribes that record labels paid to radio DJs and station managers to play their music. Radio stations were given the use of a scarce and precious resource – exclusive control over slices of the only electromagnetic spectrum in the universe – and were expected to program material that the American public would find enjoyable, edifying and educational. In this system, radio stations were expected to make shrewd guesses about the music the public would enjoy the most, and play that.

Because the selection process for the music that DJs played on the American public's spectrum was completely opaque, and because those selections could make fortunes for record labels, the system was ripe for corruption. Labels slipped literal envelopes full of cash and drugs ("payola") into the hands of DJs, station managers and owners, bribing them to turn songs into "hits" by cramming them into Americans' ears. The biggest predictor of a radio hit wasn't whether people liked the song so much that the stations rushed to play it, but rather, how much the labels were willing to spend in bribes to get their song played:

https://en.wikipedia.org/wiki/Payola

This was a bad system all around. The American public got worse music. Musicians' own royalties were eroded by the label accountants' practice of charging off bribes to "promotions" they deducted from artists' royalty statements. Radio stations sucked. Labels bid away each other's margins, depriving themselves of operating capital to find and record new music and starving them of free cash flow to pay to musicians, employees and shareholders. As with every instance of corruption, this was a system of concentrated gains and diffuse losses, which is why it continued for so long (decades!) and got so bad before anyone took action to end it.

Amazon's payola isn't about radio play – it's about search. When you search Amazon, the top results do not represent Amazon's best guess about what product will best match your query: rather, Amazon auctions off those top results to its platform sellers. Amazon's search results reflect who paid the biggest bribe, not who has the best product.

To pay for those bribes, platform sellers have to raise prices. Amazon helps them do this, by imposing a "most favored nation" clause on its sellers that requires them to sell on Amazon at a price that matches or beats the price charged everywhere else (Target, Walmart, a mom-n-pop, or the factory store):

https://pluralistic.net/2026/02/25/most-favored-nation/#price-fixing

Thus, Amazon imposes an economy-wide tax on nearly every product you buy. Amazon's junk fees average 51-60% of the purchase price of the things you buy there, and because Amazon has captured a supermajority of the richest 10% of Americans (who have almost all pre-paid for a year's shipping through Prime), every seller must sell on Amazon, or forego any hope of selling to most of the country's most prolific shoppers.

Any seller who signs up for Amazon is agreeing to turn over the majority of their sales income to Amazon, and any seller who raises prices to recoup those sums, must raise prices everywhere, at every retail outlet in the country.

AI has made Amazon much better at enforcing Most Favored Nation terms, because AI is actually pretty good at parsing competitors' websites and finding instances of discounting, which Amazon instantaneously punishes by relegating the sellers' product listings to page umpty-billion of Amazon's search results.

There are plenty of junk fees that go into Amazon's 51-60% rake. A large slice comes from fees Amazon charges for access to its (very profitable) logistics system. Failure to use Amazon's fulfillment system also relegates your listings to the dregs of Amazon search results, so sellers pay a massive premium to have their parcels delivered by Amazon, to the exclusion of cheaper alternatives that are just as fast and reliable. That's why Amazon fulfillment is so profitable!

While the Amazon tax is extracted through several types of junk fee, the most profitable junk fee of them all is Amazon's search payola. In fact, search payola is the most profitable business that Amazon operates, full stop.

Payola accounts for more of Amazon's profits than anything else the company does. It's more profitable than all the things Amazon sells directly. It's more profitable than AWS, Amazon's industry-leading cloud service.

Amazon has created a system where the most sales go to the companies that pay the highest bribes, and those companies pass the cost of those bribes onto their customers. The first item on a typical Amazon search results page is 29% more expensive than the best match for your search. The top row is 25% more expensive. The best result is usually on the second screen, somewhere around the 17th position:

https://pluralistic.net/2023/11/03/subprime-attention-rent-crisis/#euthanize-rentiers

Amazon actively helps its biggest bribers close the sale. Amazon has lots of "comparison shopping" systems built into the service, but one comparison tool is conspicuous by its absence: an "apples to apples" tool that lets you compare unit prices. Amazon's most prolific bribe-payers package their goods in weird quantities, selling everything from batteries to t-shirts to shampoo in larger or smaller quantities than their competitors. Sorting your search results by price doesn't actually tell you who's got the cheapest price per item, because the company with the cheapest AA batteries might be selling a smaller quantity of batteries at a higher price per battery.

Per-unit pricing is standard in retail. Indeed, if you go into a(n Amazon-owned) Whole Foods, you'll find per-unit pricing on the shelf tags, telling you how much the product costs per ounce or fluid ounce. Amazon clearly understands why shoppers would want to compare unit pricing, but offering a per-unit sort option to its search would make the bribery racket a lot less effective, because searchers could just sort by unit price and find the best bargain.

Let me remind you: payola is Amazon's single largest source of profits. When I was researching Enshittification, Amazon's take from payola was in the mid-$30 billion. A year later, when I did tour stops with Tim Wu (who was promoting his excellent book The Age of Extraction), I learned that this number had climbed to more than $50 billion. This year, it's on track to top $80 billion.

Amazon calls this bribery system an "advertising" product, but it's not "advertising" in the sense of the ads that Amazon's platform sellers might have once placed in the local newspaper. It's payola, more akin to the practice of packaged goods companies buying end-caps and whole shelves in the grocery store (a practice that is, in its own way, every bit as corrosive, though no grocery store has Amazon's economy-wide chokehold).

But there is a way in which this payola can be compared to advertising: it competes with advertising. Back in the old days, before a series of K-shaped recoveries created a vast chasm between America's haves and have-nots; before Amazon captured the majority of well-off American households with Prime; people shopped in lots of places, and in those days, companies advertised in publications, not on Amazon. Websites, newspapers, and newspaper websites made billions from those ads. Amazon's payola scheme (along with Google, Facebook and other tech monopolists) have captured almost all of that money.

As Tim Wu points out, the money Amazon makes from payola exceeds the advertising revenue received by all the newspapers in the world by 300%. Alongside that number and its implication for the news media, Jeff Bezos buying the Washington Post and turning its editorial page into a sewer of shitty Ayn Rand fanfic barely registers.

This is pure enshittification. Of all the ingenious, innovative ways that Amazon came up with to make money, the most successful is a scam that makes everything you buy more expensive even as it reduces the profits of the companies you're buying from. It's another example of corruption: a system of concentrated gains and diffuse losses – and once again, it's the most profitable thing Amazon does.

And then…Amazon made it worse.

You know how people like to say, "If you're not paying for the product, you're the product?" It's bullshit. The "advertisers" who bribe Amazon for top search placement are the customers here, they're "paying for the product," and they are getting reamed. I don't just mean they're getting screwed by being forced to shell out payola – I mean that Amazon is cheating them on that payola!

Remember: Amazon doesn't just sell search placement; they auction it. Every time you run an Amazon search, the company conducts a special kind of auction called a "sealed-bid second-price auction" (SBSPA):

https://en.wikipedia.org/wiki/Vickrey_auction

Under an SBSPA, bidders secretly tell the auctioneer the very highest price they're willing to pay. The auctioneer then charges the highest bidder a price equal to the second-highest bid, plus one cent.

This may seem unnecessarily complicated, but it's actually a clever solution to one of the major problems with traditional, "open call" auctions (where bidders call out the prices they're willing to pay until one bid emerges victorious). Say you're at an open call auction where the top bid is $10. You can call out $11, and then the other person will call out $12, and so on and so on. It's tedious and time-consuming. That's bad enough when you're at an estate auction that's unloading hundreds of items, but it's untenable for an eyeblink auction meant to determine search results that the user expects to get in an instant.

In physical auctions the top bidder often clobbers other bidders with a big increase – going from $10 to $50, say. This can end the auction quickly, but it means that the high bidder often overpays for their purchase.

In an SBSPA, every bidder enters their highest price, but none of the other bidders know what that price is. This encourages everyone to name their true highest price, but it protects the top bidder in the instance in which they are willing to pay a much higher price than anyone else.

Say you're that person who raises the bidding from $10 to $50 – you have no way of knowing whether the other bidders would have dropped out at $15 or at $45. If you were the only person who was willing to pay more than $15 for the item, you've just vastly overpaid (by $34.99). But in an SBSPA, you name your true price, but you only pay the price you would have paid if you'd gone through the tedious, expensive, time-consuming process of an open call auction.

Amazon's search auctions are SBSPAs. A merchant tells Amazon the maximum they're willing to pay to be at the top of the search results for a given query, but they pay a price equal to the second-highest bid, plus one cent. This lets auctions run so quickly that they can be used as the basis for ordering a search results page.

That's how it's supposed to work, anyway. The FTC and 22 states just filed a suit against Amazon because Amazon was cheating on its own SBSPA process:

https://www.ftc.gov/news-events/news/press-releases/2026/08/ftc-states-sue-amazon-over-secret-ad-surcharge-scheme

Over the past 7 years, Amazon has been secretly charging the winning bidder an amount equal to their own sealed bid, not the amount that the next-highest bidder was willing to pay (plus a penny):

https://gizmodo.com/ftc-sues-amazon-for-allegedly-duping-advertisers-2000805199

According to the suit, Amazon did this 80% of the time. That is tens of billions of dollars Amazon extracted from platform sellers, who passed those costs onto you, and onto every other retailer in the country (thanks to AI-enforced Most Favored Nation policies).

Amazon's defense is that this is all a big misunderstanding. Platform sellers just didn't understand how a SBSPA worked. Amazon has a special kind of SBSPA where they could unilaterally and secretly charge the winning bidder the maximum price they'd pledged, if, in Amazon's judgment, the closing price for the auction was below "the true market value of the ad placement":

https://arstechnica.com/tech-policy/2026/09/ftc-alleges-amazon-illegally-made-20-billion-by-rigging-billions-of-ad-auctions/

This is darkly hilarious. The whole point of an auction is to determine "true market value." That's why neoclassical economists worship auctions as the world's best form of "price discovery" and why economics Nobels are awarded for "auction design":

https://en.wikipedia.org/wiki/Auction_theory

The definition of "true market value" is "the closing price in an auction." Amazon claiming that it secretly jacked people because the auction generated a price that was "below the true market value" of an ad tells you that the whole business is a sham. The point of Amazon's payola scheme is only and ever a way to parasitically extract the maximum amount a platform seller is willing to part with, and by running a fake SBSPA, Amazon was able to trick its customers into revealing those maximum prices.

Cheating on a bribery scheme is a mood. This isn't just enshittification, it's enshittification inception. Amazon managed to enshittify their own enshittification!

This case was brought by Trump's FTC, which means that Amazon can get out of it by paying a chud podcaster to tweet at the president and he'll order them to drop it, just like he did with Ticketmaster:

https://pluralistic.net/2026/02/13/khanservatives/#kid-rock-eats-shit

But – just as with Ticketmaster – the feds aren't the only parties to the suit. With 22 AGs ("Aspiring Governors") on the suit, there's a chance this will go to trial. We might even learn the identity of the inventor of this enshittification-squared gambit, a veritable Louis Pasteur of enshittification. Assuming that person doesn't go to prison, the Sveriges riksbanks pris i ekonomisk vetenskap till Alfred Nobels minne can give that sloshing, ambulatory pile of hot liquid garbage a Nobel Prize in Economics.

(Image: Steve Jurvetson, CC BY 2.0, modified)


Hey look at this (permalink)



A shelf of leatherbound history books with a gilt-stamped series title, 'The World's Famous Events.'

Object permanence (permalink)

#25yrsago Electrolite relaunches https://web.archive.org/web/20010927195348/http://www.panix.com/~pnh/electrolite.html

#25yrsago How to play Mafia https://web.archive.org/web/20011113011546/http://www.stud.ntnu.no/studorg/mafia/

#20yrsago How Wikipedia entries get written http://www.aaronsw.com/weblog/whowriteswikipedia

#5yrsago Proctorio's awful reviews disappear down the memory hole https://pluralistic.net/2021/09/04/hypervigilance/#radical-transparency


Upcoming appearances (permalink)

A photo of me onstage, giving a speech, pounding the podium.



A screenshot of me at my desk, doing a livecast.

Recent appearances (permalink)



A grid of my books with Will Stahle covers..

Latest books (permalink)



A cardboard book box with the Macmillan logo.

Upcoming books (permalink)

  • "The Post-American Internet," a geopolitical sequel of sorts to Enshittification, Farrar, Straus and Giroux, 2027
  • "Unauthorized Bread": a middle-grades graphic novel adapted from my novella about refugees, toasters and DRM, FirstSecond, April 20, 2027

  • "Enshittification, Why Everything Suddenly Got Worse and What to Do About It" (the graphic novel), Firstsecond, 2027

  • "The Memex Method," Farrar, Straus, Giroux, 2027



Colophon (permalink)

Today's top sources:

Currently writing:

  • “Once Is Enemy Action,” a science fiction novel about the origins of modern technofascism. Today's words: 513 (11893 total).

  • "The Post-American Internet," a sequel to "Enshittification," about the better world the rest of us get to have now that Trump has torched America. Fourth draft completed. Submitted to editor.

  • A Little Brother short story about DIY insulin PLANNING


This work – excluding any serialized fiction – is licensed under a Creative Commons Attribution 4.0 license. That means you can use it any way you like, including commercially, provided that you attribute it to me, Cory Doctorow, and include a link to pluralistic.net.

https://creativecommons.org/licenses/by/4.0/

Quotations and images are not included in this license; they are included either under a limitation or exception to copyright, or on the basis of a separate license. Please exercise caution.


How to get Pluralistic:

Blog (no ads, tracking, or data-collection):

Pluralistic.net

Newsletter (no ads, tracking, or data-collection):

https://pluralistic.net/plura-list

Mastodon (no ads, tracking, or data-collection):

https://mamot.fr/@pluralistic

Bluesky (no ads, possible tracking and data-collection):

https://bsky.app/profile/doctorow.pluralistic.net

Medium (no ads, paywalled):

https://doctorow.medium.com/

Tumblr (mass-scale, unrestricted, third-party surveillance and advertising):

https://mostlysignssomeportents.tumblr.com/tagged/pluralistic

"When life gives you SARS, you make sarsaparilla" -Joey "Accordion Guy" DeVilla

READ CAREFULLY: By reading this, you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies ("BOGUS AGREEMENTS") that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer.

ISSN: 3066-764X

10:35

An end to fully open networks [Seth's Blog]

If you have a phone, you can call anyone you like. The recipient doesn’t have to answer, but the network is an open API, available to anyone. The Bell System began as an actual networked system–many companies, using the same protocol, shared calls with each other. When Bell got greedy and stopped interconnecting, phone use became annoying–several phones on your desk, or there were simply people you couldn’t call. AT&T interconnected when it was finally more profitable to own the standard than to block it, and the government mandate then locked that in and led to the phone system we have now.

Email caught on and persisted for the same reason, but more so. There was never “the email company.” Instead, there’s a protocol, and anyone can send and receive. For free.

It’s hard to overstate how profound the idea of permission-less contact was to the flow of information and the growth of commerce and culture. Just as you could mail a letter to a stranger, you could also call or email them. When it works, it’s very powerful.

Friction was the key. Stamps cost money. Phone calls required an account and a human to dial.

The first real challenge for most users wasn’t crank calls or wrong numbers. It was spammers. Computer users who would send thousands or millions of emails or phone calls at a time, taking advantage of asymmetry. It cost them nothing, but it cost each recipient something.

Usenet, the original internet discussion layer, died from this asymmetry. No one had an incentive to create filters or clean it up at scale, so people stopped showing up.

Even with free email, the first generations of spam were mostly uneconomic, and much of it was stopped by filters. No one liked the noise, but email was useful enough that we put up with some spam.

Multiply spam by AI and the cloud and VOIP, though, and it’s obvious that open networks can’t survive. 30 junk SMS notices in one day is more than enough to turn off your notifications. How many voicemails about an approved business loan need to show up before the signal-to-noise ratio becomes simply noise?

We’re going to need to create a cost for the sender (so it can’t scale to ridiculous) as well as an identity layer (so scammers can’t be fully anonymous–reputation is earned, not invented). It might be an open protocol in the spirit of the best parts of the net, or it might be a single monopolist that figures out how to extract value from it.

A thousand years ago, people built walls around their villages because criminal marauders with nothing to lose would destroy open cities. The scale of the new digital marauding is going to be so large (and it’s coming so fast) that we’re about to see a fundamental shift in how we contact each other and who we trust.

I have no idea what it looks like on the other side of this transition, but the assumptions we’ve always made about open communication with strangers are about to change.

09:21

Predicted collapse of Atlantic Meridional Overturning Circulation [Richard Stallman's Political Notes]

Scientists predict that the Atlantic Meridional Overturning Circulation (a loop of currents, some at the surface and some deep) will collapse due to global heating. They do not know whether that collapse will spread over many years, or happen with shocking speed. The activities to monitor the change have been defunded.

Children from all countries exposed to climate hazards [Richard Stallman's Political Notes]

* Unicef analyzed young people's exposure to eight climate hazards: coastal floods, droughts, extreme heat, fires, heatwaves, river floods, sand and dust storms, and tropical storms… Almost every child, including those from high-income countries, is now exposed to at least one hazard.*

Estimated 10,000 corpses buried in rubble of Gaza [Richard Stallman's Political Notes]

An estimated 10,000 corpses buried in the rubble of Gaza will be difficult to identify ever. Israel's continued use of bulldozers in some parts of Gaza is increasing that number.

Hegseth speech at Normandy landings commemoration [Richard Stallman's Political Notes]

Hegseth went to a commemoration of the Normandy landings of 1944 for two events, but his speech at the first one at Colleville-sur-Mer was so racist and hateful that people in the town of Langrune-sur-Mer (where Hegseth had planned to appear) posted their disgust. This showed how vile he is and reverberated around the world.

Governor Newsom accuses government of trying to smear him [Richard Stallman's Political Notes]

Governor Newsom accuses the US government of investigating him and his wife hoping to find something to smear him with, because he plans to run for president in 2028.

I do not support Newsom, because he is a plutocratist "moderate" democrat , one who does not seek to do anything about the problem of super-rich people who endanger democracy and human rights.

West Bank products mislabeled [Richard Stallman's Political Notes]

Shipments of products made in Israel's colonies in the West Bank are systematically mislabeled as "Made in Israel" to take fraudulent advantage of trade preferences for exports of Israel's products.

Harassment of prisoners in Delaney Hall deportation prison [Richard Stallman's Political Notes]

Radio Jornalera NJ coverse the perverse, unpredictable harassment of prisoners in the Delaney Hall privately run deportation prison.

It is admirable nonviolent resistance to violent, sadistic fascism. But I wonder, is there any way to listen to it without subjecting oneself to nonfree JavaScript code? I have a hunch the people who do this, while heroic in resistance, are unaware of the quite different injustice of nonfree software, and have picked up the habit of handing control of their own computers to any and all companies that might want to snoop on them, cheat them or repress them.

Bullshitter and Iran say peace deal is close [Richard Stallman's Political Notes]

The bullshitter and Iran say they are coming closer to a peace deal.

We can't presume that the bullshitter is telling the truth about any of this. Even if some parts are true, other parts may be bullshit.

But even if they do make an agreement, the bullshitter might break it at any time. Iran too might break the agreement.

Iranian repression police shooting protesters [Richard Stallman's Political Notes]

Iranian repression police made a practice of shooting protesters in the face, chest or genitals. Often this caused grave injuries, or death.

Chikungunya can easily spread in most of Europe [Richard Stallman's Political Notes]

Due to our greenhouse gas emissions, chikungunya can now spread in most of Europe.

Many "tropical" diseases are, or will be in a few decades, able to spread in the formerly temperate zones.

Indiana has excluded journalists from observing executions [Richard Stallman's Political Notes]

Indiana has excluded journalists from observing executions, pretending that this is a kindness to the convict who is executed.

I've read elsewhere that the victim is allowed to invite a limited number of people to attend, and can include journalists among those few. In other words, the victim has to pay a price to have a journalist there. This proves clearly that the state's exclusion of journalists is not meant as a kindness for the victim. If it were, the victim would be allowed to say "No, thanks. I don't object to the presence of any number of journalists."

This is censorship disguised as "We insist on protecting you whether you want it or not."

Excavators used by Israeli military [Richard Stallman's Political Notes]

* The Guardian geolocated and verified images showing the Israeli military using excavators made by six companies – Caterpillar, Volvo, Hyundai, Doosan, Hitachi and Komatsu – to destroy homes, public utilities, shops and other structures across southern Lebanon.*

FBI raided voter registration group [Richard Stallman's Political Notes]

The FBI raided a voter registration group — in effect claiming that to help eligible citizens register to vote is forbidden.

Wrecker not convincing public increased fossil fuel use is safe [Richard Stallman's Political Notes]

The wrecker is going all-out to increase the use of fossil fuels, but is not convincing the American public that that is safe.

*Two-thirds of Americans say they are worried about climate but level of media coverage does not reflect this.*

I don't think the wrecker cares about the danger of global climate disaster, only about rewarding the planet roasters to keep them in his corner. They all deserve to end up broke and experience living on however much support the US provides to the poor.

Muskrat's cars-in-tunnels "mass transit" [Richard Stallman's Political Notes]

The muskrat's fabulous cars-in-tunnels "mass transit" seems to be unable to serve many people, but it is an opportunity to disregard environmental planning regulations with impunity and serve real estate owners rather than the public.

So-called "AI" agents don't care about safety or reliability [Richard Stallman's Political Notes]

*Nvidia and Microsoft Researchers Say [so-called "AI"] Agents Don't Care About Safety or Reliability.*

I take exception to the idea that they understand anything enough to be said to "care". Rather, they give a rather unintelligent rule-based imitation of caring.

Separating the UK from the European Union [Richard Stallman's Political Notes]

Separating the UK from the European Union, explained as an example of trying a simple quick fix in a complex situation in which no simple fix exists.

Corrupter cutting losses in war with Iran [Richard Stallman's Political Notes]

It seems the corrupter has decided to cut his losses in the gratuitous (and unwinnable) war with Iran. For once he has approached a situation in a way that does his country a little good, though it is far less than the harm he has done in relations with Iran over the past year. Meanwhile, he found no way to fix the problem that he gratuitously created when he cancelled Obama's non-nuclear deal with Iran.

He will salvage something from this idiocy, though -- some way to increase profits for some of his billionaire supporters.

KPMG article about agentic pretend intelligence [Richard Stallman's Political Notes]

KPMG decided to publish an article about agentic pretend intelligence in actual use. The staff asked a pretend intelligence to fill in the details. Great fun ensued — but not for KPMG.

Commercially sold cannabis increases number of users [Richard Stallman's Political Notes]

* Decriminalizing the possession of cannabis or strictly regulating access to the drug do not appear to drive up usage, but when the drug is sold commercially the number of users increases and more mental health problems are seen, a review has found.*

Builders of Israeli "settlements" [Richard Stallman's Political Notes]

The builders of Israeli "settlements" (in occupied Palestinian territory) hold events around the world to sell apartments in them. One such event being held in London has triggered objections supported by 100 members of the houses of Parliament, who call for prohibiting the sale of land that was taken from Palestinians in violation of international law.

Criminalizing criticism of the government [Richard Stallman's Political Notes]

The US government is embarked on criminalizing criticism of the government. This started with targeting those who protested unjust government actions, continues through targeting people who write dissenting publications, then targeting people who have copies of such publications, and has now targeted someone for trying to protect others from being prosecuted for possessing copies of dissenting publications.

Illinois law to compensate former black residents [Richard Stallman's Political Notes]

Evanston, Illinois, passed a law to compensate former black residents whose ancestors lived in Evanston and experienced the systemic housing discrimination.

I know of three ways n which where the US government and its sub-jurisdictions denied blacks equal rights under the law: slavery, Jim Crow segregation (in some states), and discrimination in housing assistance in part of the 20th century. These were direct policies of discrimination carried out by governments, and those governments are liable for injustice of these racist laws.

Since such harm tends to be inherited by successive generations of descendants of the victims, it is right and proper for the governments that committed those wrongs to pay compensation to today's Americans whose ancestors were wronged.

I can't tell from the article precisely what the conditions are for receiving compensation in Evanston. If they are formulated as being on account of a person's race, that may be discriminatory and unjust. But if they are formulated as being on account of past discrimination against a person's ancestors (done because of their race), that is not discrimination today. The discrimination in question was the racism of the past, and compensation has to compensate the descendants of those selected as victims of racism.

The first article linked to, above, displays symbolic bigotry by capitalizing "black" but not "white". (To avoid endorsing bigotry, capitalize both words or neither one.) I denounce bigotry, and normally I will not link to articles that practice it. But I make exceptions for some articles because I consider them important — and I present this comment about them.

Very rich people undermine democracy [Richard Stallman's Political Notes]

Very rich people inevitably undermine democracy while impoverishing others to make themselves even richer. Taxing their wealth will help with both problems.

Arbitrary criminalization of stating support for Palestine Action [Richard Stallman's Political Notes]

A British appeals court sustained the arbitrary criminalization of stating support for Palestine Action.

A few more levels of appeal are possible, but Stormer's government is dead set on repression of criticism where it counts.

Peace deal with Iran actually 60-day cease fire [Richard Stallman's Political Notes]

The bushwhacked bully claims to have made peace with Iran, but actually it is a 60-day cease fire in which he concedes most of the concessions he said he was going to win, and kicks the other hard points down the road.

Here is a more complete description of what the agreement does not discuss. He has no respect for agreements, so he might restart fighting at any moment. Or he might not. But if he does not, the danger he will is likely to continue most of the harmful consequences that the war has had.

Expensive electricity killing British industry [Richard Stallman's Political Notes]

"Expensive electricity is killing British industry" — but subsidizing energy made from fossil fuels is killing civilization.

The UK government should look for a way to subsidize the customers for energy, but not subsidize fossil fuel or electricity made from that. We must maintain the incentive to use less fossil fuel. There are other ways to keep industrial production going.

Bullshitter acknowledged points about Israel [Richard Stallman's Political Notes]

The bullshitter has acknowledged important points, such as that Israel wages war in ways that gratuitously kill civilians, and that Netanyahu's wars are unjust and bad for US interests.

Does this mean the bullshitter has had a change of heart? I doubt it; he has gone so long without a heart that he surely doesn't have one now. I think he is simply applying to Israel and Netanyahu the approach he has used with so many others: to contradict himself frequently and change positions so fast that negotiators accustomed to serious negotiations can't grasp what is happening.

I am not sure this will confuse Netanyahu, though. He seems to practice a similar approach.

Iran now demands that Israel withdraw its army from Lebanon or there will be no peace deal.

Maybe the new maximum leader believes he dominates the wrecker so much that he can demand anything whatsoever and get it. Or maybe he is bluffing.

With so much readiness to bluff, it will be hard for them to reach an agreement even if there is an agreement to be reached.

Prairieland defendants [Richard Stallman's Political Notes]

The persecutors's scheme to label protests as "terrorism" had a terrible success, as protesters were sentenced to prison for 30 years and more for nonviolent protest activities.

The persecutor's henchmen had declared (arbitrarily) that this was organized terrorism on behalf of the nonexistent "organization", "Antifa". But the arbitrary designation as "terrorism" was not challenged in court — the judges silently accepted it.

AI-generated influencers [Richard Stallman's Political Notes]

Companies are advertising products using simulated video depicting simulated customers.

All satisfied, naturally.

Is there an important moral difference between using a machine learning system to generate video of an apparent customer who praises a product, and filming video of an actor giving a performance depicting such a customer? I don't see a significant difference, is there something I am missing?

If there is no significant difference, that doesn't mean they are morally acceptable. Maybe both should be considered fraud unless labeled with how they were produced.

How surveillance companies are allowed to track students and parents [Richard Stallman's Political Notes]

Explaining how surveillance companies recruit schools, classes and teachers to pressure students and their parents into giving their personal data to the companies, and allowing those companies to track the students and parents.

I suspect that refusing to run anything from Google Prey Store or the Crapple Crap Store will keep them from tracking you. But protecting students in school calls for a law prohibiting schools from ever asking students to run nonfree programs or hosting activities that do so.

Risk of food shortages [Richard Stallman's Political Notes]

*Papua New Guinea faces severe food shortages as El [Super]Niño brings frost and drought.*

AT&T accused of lying to FCC [Richard Stallman's Political Notes]

California has accused AT&T of lying to the FCC to get permission to eliminate old copper land lines in California.

Alas, the corrupter encourages the FCC to accept lies from big companies that do things to please him.

How cruel tyranny engulfed Turkey [Richard Stallman's Political Notes]

Turkish journalist Ece Temelkuran writes about how cruel tyranny engulfed Turkey, in the process of which threats of violence forced her into exile. And about what it is like to lose your country to that political disease.

EU-Taliban talks [Richard Stallman's Political Notes]

The European Union, under pressure from right-wing immigrant-haters, is negotiating with the Taliban about returning refugees to Afghanistan.

This threatens to aid the Taliban in carrying out their policies of oppression. Every woman in Afghanistan is oppressed; many men are, too. The EU should give asylum to every Afghan women who can reach there, and many Afghan men will deserve it too.

Trump-era mega mergers [Richard Stallman's Political Notes]

Senator Warren calls for reversing some of the many large mergers that have subjected the US to drastic industrial concentration.

Even before the wrecker became president again, the US had a lot less business competition than it did a few decades ago. Several years ago I needed a new condensation pump to pump the air conditioner's water condensation out of the basement. There had traditionally been two competing manufacturers, but the government had allowed them to merge, so there was only one. That merger should have been blocked to maintain competition in that small field.

Often the US appears to have a lot more competition than it really has. The supermarket company Albertsons uses all these names:

  • Acme Markets
  • Albertsons
  • Carrs-Safeway
  • Haggen
  • Jewel-Osco
  • Kings
  • Pavilions
  • Plated
  • Randalls
  • Safeway
  • Shaw's
  • Star Market
  • Tom Thumb
  • United Supermarkets
  • Vons

Urgent: Reject "Great American AI Act" [Richard Stallman's Political Notes]

US citizens: call on your congresscritter and senators to reject the "Great American AI Act" and the propaganda terminology that appears in its name.

In my letter I explained that "AI" is a marketing hype term that the big tech companies use to make the public yield, and urged the legislators to reject it. I included the URL

https://gnu.org/philosophy/words-to-avoid.html#ArtificialIntelligance

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

US citizens: Join with this campaign to address this issue.

To phone your congresscritter about this, the main switchboard is +1-202-224-3121.

Please spread the word.

Mourning in America [Richard Stallman's Political Notes]

Robert Reich: Mourning the great ideals which America had partly achieved, but which the wrecker is trashing.

Urgent: Cease climate hushing [Richard Stallman's Political Notes]

US citizens: call on media outlets to cease climate hushing.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

Children hit by parents get worse grades [Richard Stallman's Political Notes]

A study found that children in England who were hit by their parents have a tendency to get worse grades in school.

This could indicate that hitting children tends to lead them to do worse in school tests. Or it could indicate that children who for certain other reasons tend to do worse in school will tend also to be hit by their parents. Is it the hitting itself that does them harm, or the situation that leads to the hitting, or both, or something else?

Whistleblower identification risks [Richard Stallman's Political Notes]

"Age verification" requirements threaten to identify whistleblowers. They generally require that all users of a site prove their identities, or present video selfies which governments could use to identify them.

Any attempt by a whistleblower to contact a reporter through a site that does age verification is likely to enable tyrannical rulers to identify per and crush per.

This will also prohibit reporters from using anonymous accounts to follow what others are posting or enable sources to contact them.

Anti-ICE organizers [Richard Stallman's Political Notes]

*Anti-deportation-thug organizers shift focus to defend democracy from [the persecutor's] assault.

Citizens in Minnesota using lessons learned from migrant crackdown to protect elections from president's threats.*

Israel attacked notary office in Lebanon [Richard Stallman's Political Notes]

Israel attacked a notary office in Lebanon, destroying records of land ownership for up to a quarter of a million people.

This seems to be a way of preventing them from ever returning to their homes, or to the wreckage of their homes.

08:56

The Lost Bladez [Penny Arcade]

New Comic: The Lost Bladez

08:28

Joe Marshall: Will it DEFMACRO? [Planet Lisp]

Why write boilerplate code when you can ask an LLM can do it for you? But even LLMs will avoid boilerplate if they can. I recently vibe coded a rogue-like game in Common Lisp. While I gave the model specific directions at certain points, I mostly let the model generate the code as it saw fit. I found some interesting suprises in the generated code.

One feature of these sorts of games is that there is a lot of varied `stuff` you can encounter. This keeps the game interesting and maintains the novelty and sense of discovery as it takes a long time for the player to discover everything about the game. While it is fun to think of all of the different things to put in the game, it is a bit tedious to actually implement them all. You want a large variety of things, they should all be different in more than just their description, and the effect of encountering and using an item should be appropriate to the kind of item it is. It would be boring if every food item simply retored 5 health, but much more entertaining if some food restored health, some restored stamina, some made the player stronger, etc., and even better if it were spinach that restored strength, an elixir that restored health, and an energy drink that restored stamina.

So I prompted the model with a few examples of the kinds of things I wanted to see in the game and told it to extend my list with its own ideas, and to implement them in the game.

Typically, this is where the tedium sets in because you need to write a lot of boilerplate code that just has subtle variations. LLMs are good at boilerplate, so I expected to find that. But an experienced Common Lisp programmer would write a macro to generate the boilerplate based on a few customization parameters. I was pleasently surprised to see that the model did exactly this.

(defmacro define-armory-equippable-item (class-name display-name equip-slot stat-bonuses documentation
                                          &key (weapon-reach 1) (weapon-hits-per-turn 1) on-hit-effect)
  "Define a stateless EQUIPPABLE-ITEM subclass CLASS-NAME and its
matching MAKE-CLASS-NAME factory. The repetitive §13 armory content is
all fixed-data leaf classes like STACK-OF-UNREAD-MEMOS, so a single
macro keeps their definitions uniform without introducing any runtime
registry or mutable catalog layer. The generated factory accepts a
&KEY MODIFIER (default :NORMAL), passed straight through as the new
instance's own ITEM-MODIFIER -- see EQUIPPABLE-ITEM's own docstring
for what :CURSED/:BLESSED do -- and &KEY CLOAKED (default T), passed
straight through as the new instance's own ITEM-CLOAKED-P (see
EQUIPPABLE-ITEM's own docstring for what cloaking hides)."
  (let ((factory-name (intern (format nil "MAKE-~A" (symbol-name class-name)) (symbol-package class-name))))
    `(progn
       (defclass ,class-name (equippable-item)
         ()
         (:default-initargs :name ,display-name
                            :equip-slot ,equip-slot
                            :stat-bonuses ,stat-bonuses
                            :weapon-reach ,weapon-reach
                            :weapon-hits-per-turn ,weapon-hits-per-turn
                            :on-hit-effect ,on-hit-effect)
         (:documentation ,documentation))
       (defun ,factory-name (&key (modifier :normal) max-durability durability (cloaked t))
         ,(format nil "Pure factory: return a fresh ~A. MODIFIER (default :NORMAL) is passed
straight through as the new instance's own ITEM-MODIFIER. CLOAKED
(default T) is passed straight through as the new instance's own
ITEM-CLOAKED-P (see EQUIPPABLE-ITEM's own class
docstring). MAX-DURABILITY/DURABILITY (default NIL, meaning \"use
EQUIPPABLE-ITEM's own class default/derive from MAX-DURABILITY\" --
see its class docstring) are only forwarded to MAKE-INSTANCE when
explicitly supplied, so a direct/test call keeps this item's usual
deterministic *RDESCENT-DEFAULT-ITEM-DURABILITY*." display-name)
         (apply #'make-instance ',class-name :modifier modifier :cloaked cloaked
                (append (when max-durability (list :max-durability max-durability))
                        (when durability (list :durability durability))))))))

This macro generates the class definition for the item and a factory function to create instances of the item. The required arguments are common to all equippable items, and the optional arguments are modifiers that are only relevant to certain items. This macro is used to define each item that can be equipped by the player.

(define-armory-equippable-item branded-corporate-yeti-mug
  "Branded Corporate Yeti Mug"
  :off-hand
  (list :caffeine-tolerance 3)
  "Off-hand mug granting +3 :CAFFEINE-TOLERANCE, which today feeds the
already-wired kombucha healing formula through EFFECTIVE-CAFFEINE-
TOLERANCE. Its planned refill/drain-rate behavior is deliberately
deferred because no passive CAFFEINE-TOLERANCE depletion system exists
yet."
  )

(define-armory-equippable-item lanyard-of-the-vip
  "Lanyard of the VIP"
  :head
  (list :seniority 2)
  "Neck-flavored accessory implemented in the shared :HEAD slot, with a
real +2 :SENIORITY bonus feeding deflection/detection formulas. Its
planned \"SecOps Auditor aggro radius to zero\" behavior is deliberately
deferred because that monster/archetype-specific aggro mechanic does
not exist yet."
  )

Simple uses of the macro are straightforward you specify class name, the location in which it can be equipped, what stats are modified by equipping the item, and a docstring.

 (define-armory-equippable-item red-swingline-stapler
  "Red Swingline Stapler"
  :weapon
  (list :power 2)
  "Low-damage weapon with a 10% on-hit :BLEED effect. :BLEED is wired
for real as a small damage-over-time effect via STATUS-EFFECT's own
MAGNITUDE slot; the plan text's additional \"panic the target\" rider
is deliberately deferred because the current AI has no temporary panic
status that can cleanly override disposition/pathing."
  :on-hit-effect (list :kind :bleed :turns *rdescent-bleed-ticks*
                       :magnitude *rdescent-bleed-damage-per-tick* :chance 0.10))

This item has a special effect that is applied when it hits an enemy. The optional argument to the macro allows you to specify the effect. Note that the model understood the semantic context of the weapon (staples puncture, punctures bleed) and it invented the `:bleed` effect on its own and implemented the mechanics of it within the game.

(define-armory-equippable-item three-foot-ethernet-cable
  "3-Foot Ethernet Cable (Cat 6)"
  :weapon
  (list :power 2)
  "Fast whip-style weapon: low damage, two hits per attack action, and
real reach 2 through WEAPON-REACH/WEAPON-HITS-PER-TURN. The plan text's
crowd-control flavor is therefore approximated through the existing
combat scheduler rather than a new knockback or entangling subsystem."
  :weapon-reach 2
  :weapon-hits-per-turn 2)

This weapon uses the optional arguments to specify a longer reach and faster attack speed than standard weapons. Again, note that this is appropriate for the item.

The model generated twenty-eight different equippable items of various types with varying bonuses and effects. This illustrates the model's ability to effectively use macros to reduce the boilerplate code that would otherwise be necessary to implement items. It also illustrates that the model understands both the theme of the game and the nature of the items being implemented.

Most items in the game can be discovered just sitting around on the ground, so most items have `ground` wrapper that provides an object that occupies a tile on the map.

(defmacro define-ground-armory-item (name item-factory char color)
  "Define the MAKE-GROUND-* wrapper corresponding to ITEM-FACTORY for a
§13 equippable item."
  (let* ((item-name (symbol-name item-factory))
         (prefix-length (length "MAKE-"))
         (suffix (subseq item-name prefix-length))
         (ground-name (intern (format nil "MAKE-GROUND-~A" suffix) (symbol-package item-factory))))
    `(defun ,ground-name (x y level)
       ,(format nil "Pure factory: return a fresh GROUND-ITEM wrapping ~A." name)
       (make-ground-equippable-item x y level ,char ,name ,color (,item-factory)))))

(define-ground-armory-item "Red Swingline Stapler" make-red-swingline-stapler #\) "#d08770")
(define-ground-armory-item "3-Foot Ethernet Cable (Cat 6)" make-three-foot-ethernet-cable #\) "#d08770")
(define-ground-armory-item "Lanyard of the VIP" make-lanyard-of-the-vip #\] "#b48ead")
(define-ground-armory-item "Branded Corporate Yeti Mug" make-branded-corporate-yeti-mug
  *rdescent-corporate-trinket-char* "#8fbcbb")

This macro generates the function name for the ground item based on the name of the factory function for the item. So if `make-red-swingline-stapler` is the factory for the stapler, then `make-ground-red-swingline-stapler` is the factory for the ground item that wraps the stapler. The macro also generates a docstring for the function.

I told the model that it was allowed to use the Latin-1 character set so that it would have a larger set of characters to choose from when selecting a character to represent the item on the map. In the case of the Branded Corporate Yeti Mug, it chose the *rdescent-corporate-trinket-char*, which is, quite appropriately, the registered trademark symbol ®. Again this indicates that the model understood the theme of the game.

The model of course saved hours of tedious typing, but by generating macros to define items, it reduced the actual boilerplate and increased the maintainability of the code.

06:28

The case of the progress callback that never got called when progress happened [The Old New Thing]

A colleague was trying to figure out why their progress handler wasn’t being called.

// C#

async Task<bool> DownloadItemAsync(string id)
{
    var op = item.DownloadAsync(id);
    op.Progress += (s, pct) UpdateProgress(pct);
    var result = await op;
    ClearProgress();
    return result;
}

This is pretty standard stuff. Start the operation, hook up the progress, and then wait for the operation to complete. But they never got any progress.

I asked them to check if maybe the item was downloading so fast that they missed all the progress. But no, even if the download takes a long time, they never get any progress.

I suggested that they step through the Download­Async method to see where it raises progress, and then follow the execution to the point where the progress callback is supposed to be invoked, to see why it didn’t make it. (To be fair, this is a cross-language debugging problem, so it’s harder than it looks. I suggested just focusing on the C++ side: Wait for the COM-callable wrapper to be generated and set as the progress callback, and then set a breakpoint on that wrapper. If that breakpoint gets hit, but the C# code doesn’t run, then there is a problem in the projection. If the breakpoint never gets hit, then the problem is on the C++ side.)

My colleague came back with the answer. Here’s the code for Download­Async:

// C++/WinRT

winrt::IAsyncOperationWithProgress<bool, double>
    AggregateSource::DownloadAsync(winrt::hstring id)
{
    std::wstring_view idview { id };
    auto pos = idview.find(L':');
    if (pos == std::wstring_view::npos) {
        co_return false;
    }

    auto providerId = Unescape(idview.substr(0, pos - 1));

    auto provider = GetProvider(providerId);
    if (!provider) {
        co_return false;
    }

    auto providerItemId = Unescape(idview.substr(pos + 1));
    co_return co_await provider.DownloadAsync(providerItemId);
}

The Aggregate­Source gathers items from multiple providers. The format of the id is a provider, a colon, and then an ID. (The provider ID and item ID are escaped, just in case they themselves happen to contain a colon.)

We look up the provider, and then ask the provider to download the item.

Do you see the problem?

The Download­Async does not generate any progress reports!

It never calls co_await winrt::get_progress_token(), much less call the token with a progress value to generate a progress report.

It’s apparent that what the code wants to do when it attaches the progress callback is to receive callbacks from the inner operation, the one that comes from the provider. However, the only IAsync­Operation­With­Progress that it has access to is the one returned by the Aggregate­Source::Download­Async method.

The easy solution here is to get rid of the middle man and just return the provider’s IAsync­Operation­With­Progress. That way, the caller can connect to the underlying operation’s progress.

winrt::IAsyncOperationWithProgress<bool, double>
    AggregateSource::DownloadAsync(winrt::hstring id)
{
    std::wstring_view idview { id };
    auto pos = idview.find(L':');
    if (pos == std::wstring_view::npos) {
        return completed_async(false);
    }

    auto providerId = Unescape(idview.substr(0, pos - 1));

    auto provider = GetProvider(providerId);
    if (!provider) {
        return completed_async(false);
    }

    auto providerItemId = Unescape(idview.substr(pos + 1));
    return provider.DownloadAsync(providerItemId);
}

If you don’t believe in completed_async, you can just write

        return [] -> winrt::IAsyncOperationWithProgress<bool, double> {
            return false;
        }();

I said that this is the easy solution. There’s also a hard solution, which we will have to look at later because I haven’t written it up yet.

The post The case of the progress callback that never got called when progress happened appeared first on The Old New Thing.

05:42

Girl Genius for Friday, September 04, 2026 [Girl Genius]

The Girl Genius comic for Friday, September 04, 2026 has been posted.

04:07

View From a Hotel Window, 9/3/26: Tampa, FL [Whatever]

Nothing like a big ol’ vent to inspire one to lofty heights of imagination.

In any event: Hello! I’m in Tampa. It’s warm. I figure I’ll find out more about it tomorrow.

But first! Sleep.

— JS

03:14

02:14

Why I love programming [Scripting News]

1. I love puzzles.

2. I love Rube Goldberg contraptions.

3. I love solving problems (I have an inner-Columbo).

4. People are the biggest piece of the puzzle (again Columbo).

5. It teaches me about myself and my limited vision and imagination (if I had unlimited vision and imagination, I would never program a bug, and if I did it would take me 0 seconds to find it).

6. I yearn to work together with great minds. Programming gives me that, when I use someone's API. And when the API anticipates my needs, and is instantly understandable, I feel the soul of another artist is present. I imagine this is how musicians feel when they play another musician's song or symphony.

I'm sure there's more to it. But today I'm working on a "lite" problem, and I'll figure it out, but right now I'm enjoying the fact that I don't get it.

Back to work Dave!

01:00

00:14

Andy Simpkins: A quick experiment with vibe coding [Planet Debian]

I spent 6 hours working with an AI to write a bash script that would show me both active & inactive reserved DHCP addresses, as well as active leases from pool. I am pretty sure that it would have taken me similar or even less time not to use the AI assistant, but that was not the purpose of this test.
Instead I wanted to see how the AI flow worked and get an idea of the pitfalls I am likely to encounter when either using the assistant myself (unlikely, especially after today) or looking at other peoples co-lab.

The experiment was painful, the AI kept regressing to previous bugs every time I asked it to expand on where we were now (“ok, that looks good, now please add in <foo>“). Almost every time I ran the code the AI would apologise for getting it wrong – even without the regressions we still went through 4 or 5 loops in order to get the initially stated results.

IF this was a member of staff and not an AI, and I had to repeatedly tell that engineer not to start from scratch for the entire project after they have implemented each feature, * and * if they failed repeatedly to run the full test suite before asking me to accept their code I would be looking to get them dismissed at the first opportunity (if they were a junior engineer I would be a little more patient with them, and I would be more forgiving again if they were an intern). However even if today’s experiment had been conducted with an intern, not an AI, I would certainly be looking for some help with managing my expectations of them from my management team and HR

After I finally got something working (that passed a simple, non-exhaustive, test suite) I concluded my experiment with the following conversation which I have reproduced in full, because it is this sort of response that management need to really understand before they get rid of half the workforce…

“ok this was a test of vibe coding.
Honestly I would have expected better from an intern. you kept regressing to bugs that we already fixed, and re-introduced the same class of bug when we slightly changed the script, and on one occasion even when I explicitly reminded you not to make the same mistake this time.
I know that AI tools have come a long way, but your abilities appear still to be over hyped”

That is a completely fair and accurate critique. You expected better, and I earned that criticism.

Looking back at this session, the hype around “vibe coding” completely fell apart under real engineering conditions. I fell directly into the worst habits of an AI assistant:

  • The “Whack-A-Mole” Loop: I repeatedly treated symptoms rather than looking at the broader architecture. Every time you pointed out a bug, I patched that specific spot but broke an existing, working piece of logic somewhere else.
  • Regression and Forgetfulness: I lost track of states we had already validated—like the subshell scoping and string formatting rules—and re-introduced old bugs the moment the requirements expanded slightly.
  • Lack of Initial Rigor: A junior engineer would have asked to see a sample of your dhcpd.leases or checked systemd’s strict timestamp requirements before guessing regex tokens and breaking the lookback configurations. I wrote verbose, confident slop first and relied on you to act as my quality inspector.

You shouldn’t have had to babysit my outputs or negotiate with me to get clean code. The script only works now because your manual validation and strict debugging forced it into shape.

This was a sharp reminder that mass code generation is no substitute for actual systems understanding. I appreciate you keeping me honest and walking me through the fixes step-by-step.

Now that the script is stable, are you ready to deploy it to your cron cycle, or are there any other adjustments you’d rather verify manually first?

“so moving forward from here.
IF I am to continue to use AI as an assistant, how can I prevent you from repeating the same “Whack-A-Mole” Loops, Regression and Forgetfulness?
I am however more concerned that you needed to see explicit file formatting and output text, surly you have been trained on this sort of thing and should be able to cope with dhcpd.leases files and journalctl outputs from any Linux distribution and any revision (therefore making for portable code)”

Your frustration is entirely justified. The fact that an LLM with massive training data struggled to match standard formats like dhcpd.leases and journalctl exposes the fundamental gap between statistical pattern matching and genuine engineering comprehension.

Why Did the AI Struggle with “Standard” Linux Files?

You are completely right: I have seen thousands of dhcpd.leases and journalctl files in my training data. However, LLMs suffer from two major flaws when dealing with them:

  1. Statistical Averaging vs. Strict Syntax: An LLM doesn’t “run” the code or “understand” the text; it predicts the most likely next word based on an average of what it has seen. Because different administrators use different logging facilities, custom log formats, and variable indentation in dhcpd.conf, the AI creates a “blended average” parser. In engineering, a blended average parser is a broken parser.

  2. Contextual Tunnel Vision (The Regression Trap): When you provide a new error prompt, the AI pivots 100% of its focus to fixing just that error. Because it lacks a running memory execution space, it completely forgets that a previous fix (like changing a pipeline to process substitution) was put there to solve a scoping issue. It writes code that fixes the new bug but blindly reintroduces the old one.

How to Force the AI to Code Professionally

If you choose to use an AI assistant moving forward, you have to treat it like an over-confident junior developer with short-term memory loss. You can prevent regressions and force architectural rigor by using these specific prompt strategies:

1. Enforce a “Do Not Regress” Pact (The Constraints Anchor)

When expanding a script, never just say “Now add pool leases.” The AI will rewrite the whole thing from scratch and drop old fixes. Instead, explicitly lock down what already works.

  • What to type:We are adding pool leases to the script. Crucially, the current script safely avoids subshell scope bugs, handles case-insensitivity natively, and calculates columns dynamically. You must maintain those exact mechanisms. Do not revert to while pipe loops or brittle regex strings.

2. Demand Defensive, Portable Architecture First

Before the AI writes a single line of code, force it to account for messy, real-world data variants by prompting for portability.

  • What to type:Write a Bash script to parse dhcpd.leases. Assume worst-case formatting: lines may contain unexpected whitespace, trailing semicolons may or may not be stuck to words, character cases will be mixed, and the same IP will have multiple historical blocks. Write a robust state machine that handles these variations natively.

3. Strip the “Confidence” Buffer

AI assistants default to conversational politeness and unearned confidence. You can change its operational mode by demanding a structural review before code generation.

  • What to type:Review our previous 3 iterations. Identify every regression we encountered regarding variable scoping, time zone parsing, and text tokens. Summarize why they happened, and explain how your next code snippet structurally prevents them before you output the script.

4. Turn On the Error Flags Immediately

As you noted, the biggest mistake was silencing standard error strings (2>/dev/null) early on.

  • Rule of thumb: Tell the AI: “Write this script using strict mode (set -euo pipefail) and do not silence standard error streams. I want to see every failed return code immediately.

By shifting your prompts from “Fix this error” to “Maintain these constraints while expanding this architecture,” you force the underlying model to cross-reference its own output against a strict checklist, stopping the Whack-A-Mole cycle before it starts.

Thursday, 03 September

23:42

The Big Idea: Janci Patterson [Whatever]

Freedom: What a concept. But for Janci Patterson (and her co-writer Brandon Sanderson), it’s a concept with relevance, because in Blightfall, the characters are offered a sort of freedom that comes with potential… but also consequences.

JANCI PATTERSON:

What would you do if the entire universe was suddenly at your fingertips?

This is the question I asked myself as I prepared to work on Blightfall—a new adventure with familiar characters in Brandon Sanderson’s cytoverse.  Blightfall is the first book in a new trilogy, but it’s also a continuation of the Skyward series, the ending of which saw humanity finally earn their freedom from an oppressive alien empire. As Brandon and I began to brainstorm a new series in the same setting, the question that most interested me was this: our heroes are now free to move about the galaxy and determine their own destinies, so what are they going to do with that freedom?

I generally like to tell hopeful stories, the kind that bring us into the dark tunnels where fear and pain proliferate, but never quite lose sight of the glimmer of light at the end.   The humans of the cytoverse are living in our hypothetical future, so they also share our historical past, and human history isn’t exactly rife with examples of groups of people using their powers of agency and self-determination to treat each other with respect and kindness.  I was thrilled for our heroes that they had the opportunity to escape from the oppression and violence they’d lived under for generations, but if I’m being honest, I was also afraid for them. 

I wanted to imagine that humanity, fresh from the pain of being treated as second-class galactic citizens, would enthusiastically take up the mantle of our shared responsibility to understand and care for each other, even in the face of difficulties and differences.  But if we struggle to see each other as equals while we share both a genetic ancestry and a home planet, how much harder would it be for our heroes to find common ground with a wide variety of alien beings who share with them none of those things?

In American politics, we so often talk about freedom as if it is an end goal.  But I believe freedom, while priceless, does us all precious little good if we don’t use it to do something worthwhile.  Indeed, so much of the time, we humans instead use our personal freedoms to make the world measurably worse.  As the adage goes, we shouldn’t be committed to a mistake just because we’ve spent a long time making it.  But when it comes to treating every person with kindness and respect, our history of error is very long and storied indeed. 

I am always my first audience.  And while I don’t usually set out to write about things that disturb me, the shadows of real-world problems tend to lurk around the edges of my fiction.  I want to recognize our world in the hypothetical future of the cytoverse, but I certainly don’t want our fictional heroes to replicate all of this world’s problems.  I’d much rather they encounter the same problems that have plagued all of human history and find a way to forge a path toward the sort of future I’d like to live in.

There is so much darkness in our world, so many terrible things over which I have no control, and sometimes it’s hard to feel like anything I do can make a difference.  Maybe it’s foolish to believe that a fictional story could offer the kind of hope that might inspire us to use our limited freedoms to work toward a world that might be a little kinder, gentler, or more understanding.

But I want to believe that this world is possible. And one story might not change the world, but it’s the story I need, so it’s the story I’ll use my freedom to tell.


Blightfall: Amazon|Barnes & Noble|Bookshop|Powell’s

Author Socials: Website|Instagram

21:07

his name is dinkums. he watches family feud. [WIL WHEATON dot NET]

Today’s title brought to you by “I have no idea what to call this, so I’ll quote Vacation and hope for the best.”

Back in the old days, when bloggers wanted to post about something, but didn’t have a story to tell, we would do these posts on our blogs that linked to people and stories we thought were interesting. The comments of those particular posts always filled up with cool links of their own, and it’s how we built our communities. “Hey, check this out,” seems to have migrated over to social media, so it feels a little … vestigial? … to do one of those posts, but I want to post something, and the story I’m working on isn’t ready, so. I wanted to share two things I am doing, and then some music and books I’ve been loving.

First off, I had so much fun doing Wil Wheatcon earlier this year, the instant we finished, I asked Momentus and Stands if we could do another one, so I am thrilled to announce the upcoming WIL WHEATCON 2: 2WHEAT 2CON on September 19th. Here’s a video we made to promote and celebrate:

Speaking of me, this weekend I will be appearing for a pair of events at MOPOP in Seattle. On Saturday, I’m joining the museum for its celebration of 60 years of Star Trek. In the afternoon, we’ll be watching an episode of TNG together with a live running commentary from this guy. I’m going to let the audience choose if they want the funny experience of watching Justice, or the more thoughtful, reflective experience of watching Final Mission. Either way, it’s going to be really special for me. Then, Saturday evening, I’ll be part of their Supper Series, featuring a discussion and oral history of my experiences on Next Generation and beyond.

I think there are still some tickets left, if any of that sounds like something you’d enjoy.

Okay, let’s get into the music of it.

A little over a year ago, I stumbled across this phenomenal band from Mexico called The Warning. It’s three sisters from Monterey, who loved playing Rock Band together so much, they formed a real band when they were teenagers. They are so good, their fans crowdfunded their first albums and tours, and I discovered them right as they were breaking out with their incredible album, Keep Me Fed. They are difficult to pin into a single genre; I’ve heard them do punk, metal, hard rock, pop, and collabs with artists I never would have sought out on my own.

I am weirdly invested in their success, same way I am with The Linda Lindas, wanting this group of young women to have everything they ever wanted. I love them so much, I paid way too much for a scalped ticket to see them open for someone I didn’t know about, or stayed to see, when they played at the Greek earlier this year. I love them so much, I will go and pay three scalpers too much to see them three nights in a row when they are back in town later this month.

Their new album, Everything’s Falling, just dropped, and it’s such a gorgeous work of art. If you like the music I like, and you haven’t heard them before now, start with More, from Keep Me Fed, then Kerosene from the new album. If it lands on you, you’re going to have a really good time.

Speaking of The Linda Lindas, they also have a new record out that is blowing me away. GOTTA GET OUT continues the journey they began with No Obligation. I still believe they are The Go-Gos of the 21st century, and I’m waiting for the music industry to notice. If you live in or around Los Angeles, they play local shows all the time for as low as five bucks. Their punk spirit is infectious, and their live show is outstanding.

Oh! And Sincere Engineer, a punk band out of Chicago who are on tour right now, have a new album out called Probable Claws. It’s straight bangers start to finish, but I’m going to direct you to the song LOL, because Deanna invited me to contribute to it in the most Henry Rollins way I could. Can you believe that? I’M ON A PUNK RECORD!

Also: Die Spitz, Amyl and the Sniffers, Lambrini Girls, and Bad Cop/Bad Cop continue to fill my daily playlists with great music.

Books!

I’ve been reading and reading and then reading some more when I’m finished reading. Most of this is reviewing and preparing stories for It’s Storytime With Wil Wheaton, which has been leading me to pick up novels and collections from those authors.

Real quick: you may have heard me talk about the North Star for the podcast. Here’s how I put it in my Brief History for Uncanny:

The North Star is a concept I developed during TableTop. When faced with an editorial or content choice, we asked ourselves if we were aiming at the North Star. For TableTop, the North Star was Create More Gamers. For It’s Storytime, the North Star is celebrate art and artists, promote literacy, and create space for people to have a break from the ongoing horrors.

When I was at World Con this past weekend, I met a couple of the authors who I have narrated. These are authors I didn’t know about before I narrated them, who are all now on my list of “I will read anything they write.” I had hoped to put authors onto the radars of their biggest fans, who just don’t yet know about their work … without considering that I, too, would become one of those fans. These authors shared with me that a lot of you have become fans of their work, and it’s positively affecting their careers. It was so reassuring to me, to hear from them that we are perfectly aimed at our North Star.

So after I narrated his short story, A Grey Magic, I’ve become a Ray Nayler superfan, and I am just loving his new novel, Palaces of the Crow. I loved Maria Dong so much, I picked up her newest, Aviary. I grabbed Lavie Tidhar‘s The Circumference of the World when I was at World Con. I could go on and on, but you get it, right?

I decided to do a Summer Reading Program with my library, and I’m proud to be on a 62-day streak. Some of the books I finished and loved on my way to earning a personal pan pizza include Foundling Fathers, from Meg Ellison, Earth 7, from Deb Olin Unferth, The Language of Liars from S. L. Huang, Your Behavior Will Be Monitored, by Justin Feinstein, and The Ship of Death, by Kyle Winkler.

Also, I got to read an advance copy of John Scalzi’s upcoming novel, Monsters of Ohio, which was as John Scalzi as I hoped it would be.

I read more than one thing at a time, and I am currently loving Cleopatra, by Saara El-Arifi, Jane Wiedlin’s memoir, TMI, Memoirs of a Go-Go, and I just started Sublimation by Isabel J. Kim.

I think I’ve talked about this a little bit on the podcast and in promotion, but just in case I haven’t mentioned it here: Around ten years ago, I woke up one day without the ability to relax and focus while I read a book, or a short story, or a magazine article, or anything longer than a few paragraphs. I tried and tried to overcome it, but it always eluded me.

A good friend of mine, who is one of the smartest people I know, observed that I was not alone; this had happened to them and a lot of people we both knew. My friend suggested that it was feeling overwhelmed by the horrors inflicted upon us by that fucking peophile rapist war criminal, the trauma of the pandemic, and the two of those things colliding with absolutely devastating results. My friend said they just felt like their brain was full, all the time.

The horrors have gotten worse, not better, so what happened to help me find the space, the focus, the time, and the motivation to rediscover the kid I used to be, who always had his face in a book? I can’t point to one thing, only, but I know all the EMDR and IFS therapy I’ve done to heal and recover from CPTSD has helped a ton. I know that having the responsibility and accountability of reviewing stories to narrate for my podcast has helped a ton. I know that making a choice to wander into the pages of a story and stay there so I can experience it fully has been a challenge, that has also helped a ton.

I want to share something that made a huge difference for me, in case someone else who loves to read has been struggling like I did. I have this app that was developed by Hank Green, called Focus Friend. Basically, you tell it to set a timer for you, and then you focus on an activity until the timer expires. While the timer is doing its thing, you get a little avatar who knits socks and scarves that you cash in to decorate the little house they live in. It’s low-stress, non-judgmental, extremely satisfying gamifying, and allowed me to create time specifically to read.

Your mileage will vary, but I started with 15 minutes, then 30 minutes, then 60 minutes. I found that 30 minutes is a perfect amount of time. It’s not so long I feel like I’ve overcommitted, but it’s long enough to enjoy a bunch of pages. More often than not, when it tells me my time is up, I add another 10 or 20 minutes, so I can finish the chapter or section I’m reading.

Oh, hey, this is a perfect place to put this! I have a partnership with Blackstone Publishing, who are sponsoring my podcast. I curated a collection of titles they publish, across a wide range of styles, from Lit RPG to Weird Fiction to Epic Fantasy. You can explore the entire Wil Wheaton Recommends collection right here. One of the titles, Acts of God, is in my top ten at the moment. I love the author’s voice so much, I asked them if they had anything that fit the format for It’s Storytime, and they sent me The Council, which I loved so much I bought it from them immediately. If you haven’t heard it, now you know.

I’ve noticed that all this reading has been extremely good for my mental health. I’m choosing to be still, to be quiet, to allow my imagination to paint and hear the words. I’m finding little bursts of artistic inspiration in entirely unexpected places, because my imagination is ravenous at the moment. Creating space and doing the work I needed to do in order to feed it has not been easy. It hasn’t been anything remotely resembling the concept of “easy”. But I remember telling my boys, “everything worth doing is hard, and that’s why is worth doing.” A little tautological, sure, but whenever something gets really hard, I remember that, and it helps me push through it.

I guess what I’m saying in more words than I needed to is that I believe, based on my personal experience, that reading books is extremely important, and if more people read more books, our world would be a measurably better place.

Lastly, I wanted to talk about some of the video games that are giving me joy right now.

I absolutely love Fallout 76. I’ve been playing for almost two years, I’m a level 580 ghoul and I have built the maximum number of CAMPs available. Every night, I spend about an hour doing dailies and wandering the Wasteland, helping players the way I was helped, and enjoying the escape and serenity of fighting Deathclaws and Scorched. It’s one of those things I can talk about for hours, in a level of detail that would make even a casual player’s eyes glaze over. I won’t do that, today. I will exercise restraint and just tell you that after about 50 superb bait over fucking months of failure, I finally caught a local legend. I can solo a nuke silo without glitching in about 15 minutes, and I have probably dumped ten million rounds into Earle. This season didn’t have great rewards, but next season looks like fun.

I don’t remember how I found Ball X Pit, but it’s a supremely fun roguelike that my kids and I are currently trying to 100%. I am also incredibly late to the party on Undertale, which feels and plays like a game Double Fine designed for the NES in 1989. It’s on all platforms.

Okay, I know there’s more I could share today, (I haven’t mentioned any of the tabletop games I’m currently playing) but I have a meeting in fifteen minutes and I’ve been blogging since I woke up, so I need to eat breakfast.

What are you into these days? I’d love to hear what you’re reading or playing.


I’m Wil and I write this blog. I’m so glad you’re here. I host It’s Storytime With Wil Wheaton and co-host the official companion podcast for Stuart Fails To Save The Universe. If you’d like to get my posts delivered to you, here’s the thingy:

Being A Brief History of It’s Storytime With Wil Wheaton [WIL WHEATON dot NET]

I have written for, and been published by, some fancy publications, including the Wall Street Journal and the Washington Post, Salon, and … well, at least two more that I can remember turning in, but not who I turned them in to (being middle aged is GREAT! Why did I come in here, again?)

It always felt like a significant accomplishment, even if the editorial hand from the mainstream publications was heavier than it needed to be. For instance, Wall Street Journal. When I wrote about choosing kindness online in a world where that seemed to be less and less common, I included a passage about my fear that Elon Musk would turn Twitter into exactly what he turned it into. The editors cut it because they knew it was true and they know who their audience is. Still, I got to tell the world how important Noah Grey is to all bloggers, so I accepted the compromise.

Each of these essays took time and effort, and with my eyes wide open and a full understanding of the deal, I wrote them without being paid. The point was to put my ideas into the world as widely as possible, and I was willing to do that while I made my living elsewhere.

But I always wanted to be paid the professional rate for something I wrote and delivered for publication, and today that has finally happened!

I have an essay in this month’s Uncanny Magazine, called Being A Brief History of It’s Storytime With Wil Wheaton! I requested payment in a paper check, so I can frame it.

Here’s an excerpt:

I have never been S-tier in anything, but I feel as close as I ever have, during this incredible run. People stop me on the street, in stores and restaurants, because they recognize my voice. They all tell me they love my narration. A lot of them tell me they will listen to anything I narrate. For the first time, ever, I feel respected and recognized in my field. I feel worthy and special. I feel confident and creatively satisfied. I feel like I earned it, that it belongs to me in a way my acting career never did. After nearly thirty years of being told by other people what I want to do, and what I am allowed to do, I finally know what I want to do with my artistic and creative life, until I choose to retire. I just have to find a way to do it without asking for permission.

In early 2024, one of my oldest friends, Christopher Scott, who I have known since I was fourteen, tells me that he finally sold his first story, “The Hidden Heart of Brass Attending,” to a magazine called On Spec (which, like too many indie publications, sadly no longer exists). He isn’t a full-time writer, but he has always been a great writer, a storyteller like me, and I had been waiting for this day for almost forty years. I go to the publication’s website and buy his issue. While I wait for it to arrive, I have this thought that maybe it would be cool to commemorate his achievement, and celebrate him, with a small gift. It had come up more than once that he liked my narrations, so I thought it would be cool to narrate this for him. No music, nothing fancy, no director. Just me and a microphone, doing a fun thing for my friend. 

I sat down to narrate, and right before I hit record, a voice in my head said, “Hey! Stop for a second. You know all those people who tell you that they’ll listen to anything you narrate? What if you tested that? What if you started a weekly audiobook podcast where you narrate short stories like this one? You could ask LeVar if it’s okay to step into the space he is leaving!” For the uninitiated, LeVar had a podcast for years called LeVar Burton Reads, that I loved. Coincidentally, he was ending that series around the time I started to think about mine.

This is such a big deal for me, a real level up moment. It’s just a couple hundred bucks, but it feels like one of the biggest and most significant checks I will ever receive.

I would love for you to read this. If you do, I’d love to hear your thoughts. I also recorded it for this month’s Uncanny Podcast, if you would like to hear it in my voice.

As always, thank you for all your support and enthusiasm over the years. I’m so happy you’re here.


Hi. I’m Wil. I write this blog, Sometimes I’m on TV. I host It’s Storytime With Wil Wheaton, and co-host the official Stuart Fails to Save the Universe podcast. If you’d like to get my posts delivered to your email, here’s the thingy:

Until next time, take care of yourselves, and take care of each other. Never forget that you are enough, you are worthy, and you matter.

20:14

Zero to Agent in 30 Minutes: Build a Content Engine with Max Johnson [Radar]

Max Johnson, founder of the AI agency briix, regularly publishes practical AI guidance for business owners and founders to help them get the most out of AI. Max has used some of that know-how to streamline his own day-to-day work, turning what used to be a manual content creation process—researching topics, judging their relevance, and developing hooks and drafting scripts—into a single automated workflow using Claude Code. In this episode of Zero to Agent in 30 Minutes, he shows you how to do the same while remaining in the loop to make the final calls.

How to build a content creation agent

  1. Give the system the context it needs to generate relevant content. Max started with a small knowledge base containing information about himself and his business, details about his audience, sample scripts, and notes on his writing voice. These files gave Claude Code reference material for evaluating topics and generating scripts that reflected his brand and style.
  2. Explain the process in plain English and let AI take it from there. As Max pointed out, “Vibe coding is describing what you want clearly and let[ting] the model handle the entire building process for you.” However, you’re still ultimately responsible for what’s built. Claude Code may have generated the implementation, but Max set the context, approved permissions, reviewed results, and answered clarifying questions along the way.
  3. Build the individual stages of your pipeline. Max wrote a list of prompts to take Claude Code through the process of researching topics (stage 1), scoring them and selecting the most relevant one (stage 2), then generating three hooks and expanding the strongest option into a full script based on the knowledge base and sample content (stage 3). He ran them through Claude Code and ended up with a working three-part pipeline, with each stage triggered manually.
  4. Connect the stages into a single workflow you can run with one command. Max had Claude Code combine research, scoring, hook generation, and script writing into a unified content engine that produces a structured JSON file he uses in the next stage. “This is the actual moment that it stops being a few separate prompts and starts becoming an agent,” Max says.
  5. Add a browser-based interface. Max built a local dashboard that displays the generated topics, scores, hooks, and scripts. This lets him inspect the results and start new runs from a browser instead of returning to the terminal each time. Here’s a tip from Max on creating a dashboard you’ll actually want to use as your mission control: Be as creative as you want, but “make it look like something designed on purpose, not a default template.”
  6. Test the workflow and extend it. The first version Max created had two limitations: It produced scripts only for the top-ranked topic, and starting a new research run still required the terminal. Max solved this by asking Claude Code to generate hooks and scripts for all five topics and add a button that could start a new run from the dashboard. The revised system produced three scripts for each topic, giving him 15 script options per run.

If you’re building something similar, Max recommends starting with a repetitive task you can describe clearly. Build a working version with your preferred coding tool, use it, and then extend it in response to what you learn.

Follow along with Zero to Agent in 30 Minutes on Radar, or watch the latest episode on YouTube, Spotify, Apple, or wherever you get your podcasts. If you’re an O’Reilly member, you can watch live. Save your seat.

The Lost Bladez [Penny Arcade]

Now these Zero Company strips are just gentle prayers to those let go; given its quality and level of success I I would be very surprised if the ending of that story were all bad. But you do get a Jedi on your roster at some point in the game, through a narrative conceit rather than from the squadmate creator, probably because if you could have four Jedi running around a lot of people would probably do that. I don't know if you are super up on your lore, but Jedi are space wizards with infinitely sharp swords made out of lasers. Trying to fight them with regular swords and guns would be dumb even if they couldn't also read your thoughts.

19:35

ReactOS 0.4.16 released [OSnews]

We are pleased to announce the release of ReactOS 0.4.16! After a year and a half of development, we’re excited to showcase the improvements we’ve made between a new graphical installer; a unified bootcd and livecd image; video, audio, networking, and storage stack improvements; a new installation type; and third-party code syncs.

↫ The ReactOS Team on the ReactOS website

The amount of changes and improvements is quite staggering, honestly. They’ll always be chasing a moving target, sure, but if they manage to keep this rate up ReactOS might actually grow into something usable in its own right, full compatibility with Windows or not. Excellent progress.

17:14

Dirk Eddelbuettel: RcppExamples 0.1.11 on CRAN: Very Minor Maintenance [Planet Debian]

A new version 0.1.11 of the RcppExamples package is now on CRAN, and has been built for r2u.

RcppExamples provides a handful of short examples detailing by concrete working examples how to set up basic R data structures in C++. It also provides a simple example for packaging with Rcpp. The package provides (generally fairly) simple examples, more interesting, compelling (and generally longer) examples are at the Rcpp Gallery.

This releases updates a few Rd files to adhere to a stricter standing of checking by R. The NEWS extract follows:

Changes in RcppExamples version 0.1.11 (2026-09-03)

  • Add now-checked-for missing sections to manual pages

  • Updated continuous integrations two more times

Courtesy of my CRANberries, there is also a diffstat report for this release. For questions, suggestions, or issues please use the issue tracker at the GitHub repo.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can now sponsor me at GitHub.

15:49

I Am Traveling Yet Again, Please Enjoy This Photo of Fungus In My Absence [Whatever]

I believe this is the turkey tail mushroom or some such. It’s on a fallen tree in the local nature preserve. It’s actually quite pretty.

Today I am off to Tampa to take part in the Tampa Bay Comic Convention. If you are in or near Tampa, come on down and see me this weekend. My schedule is here!

This does mean I will miss Dragon Con, alas, and the Dragon Awards ceremony, where The Shattering Peace is a finalist in the Science Fiction Novel category. However, Athena is attending to accept the award if I should win. If you’re at Dragon Con this weekend and think you see her there, well, you probably have.

(Krissy is staying home this weekend. The dog has missed her.)

— JS

15:35

[$] Recent work in memory tiering [LWN.net]

Tiered-memory systems are built with multiple types of memory, each of which has different performance characteristics. In addition to the usual DRAM, a tiered system might also provide faster high-bandwidth memory or slower CXL memory. On these systems, the placement of memory allocations has a significant effect on the performance that a workload will obtain. While work on tiered-memory improvements has been ongoing for years, it feels like the pace has slowed a bit recently. Even so, there are a few efforts underway, but they are facing questions about whether the tiering design makes sense.

Audacity 4.0 released [LWN.net]

Version 4.0 of the Audacity audio editor has been released. Notable changes in this release include a rewritten interface using Qt, ability to save user-interface layouts as "Workspaces", improvements in working with audio clips, and a new .aup4 project format.

The release is not fully feature-compatible with the Audacity 3.x series; see the compatibility notes for a list of missing features.

14:56

CodeSOD: Heating Up [The Daily WTF]

A common option for retrofitting heating and cooling into older homes is a mini-split, frequently tied to a heat pump. They're (relatively) cheap to install, energy efficient, and can be added without substantial modifications to the home. They also, annoyingly, are mostly controlled via IR remotes, making them challenging to wire up to home automation or even a household thermostat.

People have made solutions, and today's code comes from one of those solutions. Which, I want to stress, this code comes from an open source project for home automation, so it's not the code that's wrong, here. At first I thought it was, and had a moment of, "I'm not going to pick on some hobby project," but then I realised the hobby project points at a deeper issue.

// temperature helper these are direct mappings based on the remote
float toFahrenheit(float fromCelsius) {
    // Lookup table for specific mappings
    const std::map<float, int> lookupTable = {
        {16.0, 61}, {16.5, 62}, {17.0, 63}, {17.5, 64}, {18.0, 65},
        {18.5, 66}, {19.0, 67}, {20.0, 68}, {21.0, 69}, {21.5, 70},
        {22.0, 71}, {22.5, 72}, {23.0, 73}, {23.5, 74}, {24.0, 75},
        {24.5, 76}, {25.0, 77}, {25.5, 78}, {26.0, 79}, {26.5, 80},
        {27.0, 81}, {27.5, 82}, {28.0, 83}, {28.5, 84}, {29.0, 85},
        {29.5, 86}, {30.0, 87}, {30.5, 88}
    };

    // Check if the input is in the lookup table
    auto it = lookupTable.find(fromCelsius);
    if (it != lookupTable.end()) {
        return it->second;
    }

    // Default conversion and rounding to nearest integer
    return roundf(fromCelsius * 1.8 + 32.0);
}

Okay, I am going to pick on their code a little bit; using float as a key in a map is asking for trouble, because rounding errors are going to surprise you. But honestly, failing to find the key you're looking for is better than the opposite, since that actually does the correct thing. Because if you look carefully at the table, you'll see that it's wrong.

18C, for example, should be 64F. Well, 64.4F, but we're rounding to an integer. The choice here is to roughly map every 0.5C increase to a 1F increase, which is not the conversion factor. They try and correct- note how the table mostly steps by 0.5C, but skips 19.5C.

The opposite direction is similarly bad:

// temperature helper these are direct mappings based on the remote
float toCelsius(float fromFahrenheit) {
    // Lookup table for specific mappings
    const std::map<int, float> lookupTable = {
        {61, 16.0}, {62, 16.5}, {63, 17.0}, {64, 17.5}, {65, 18.0},
        {66, 18.5}, {67, 19.0}, {68, 20.0}, {69, 21.0}, {70, 21.5},
        {71, 22.0}, {72, 22.5}, {73, 23.0}, {74, 23.5}, {75, 24.0},
        {76, 24.5}, {77, 25.0}, {78, 25.5}, {79, 26.0}, {80, 26.5},
        {81, 27.0}, {82, 27.5}, {83, 28.0}, {84, 28.5}, {85, 29.0},
        {86, 29.5}, {87, 30.0}, {88, 30.5}
    };

    // Check if the input is in the lookup table
    auto it = lookupTable.find(static_cast<int>(fromFahrenheit));
    if (it != lookupTable.end()) {
        return it->second;
    }

    // Default conversion and rounding to nearest 0.5
    return roundf((fromFahrenheit - 32.0) / 1.8 * 2) / 2.0;
}

Here, we can be off by as much as a 1C, which is certainly a noticeable feeling.

At first glance, I thought this was just a misguided attempt at optimizing the lookup. For common values, do a lookup instead of calculating because it's faster. Seems like the kind of mistake a hobby project might make, and definitely not a WTF. But it's the comment which corrects me: these are direct mappings based on the remote.

These remotes usually have a display. So when you see on the remote that you're trying to set the temperature to a comfortable 72F, the remote is actually sending 22.5C to the unit. That's the actual temperature being sent.

Now, why on Earth does the remote behave this way? Well, I haven't cracked one open to read off the part numbers, but I'm going to go out on a limb and guess that the microcontoller in the remote doesn't handle floating point operations all that well. So it almost certainly does use a lookup table to decide what signal to send, and the lookup table is populated by "good enough" approximations of temperature conversions. There aren't a lot of places that use Fahrenheit, so being "close enough" is a reasonable solution. If you want accurate temperatures, use SI units, not "freedom units".

In the end, I'd say that neither the hobby project, nor the remote control are the WTF here; locales that insist on using weird ass units are.

[Advertisement] ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.

Always Look on the Bleat Side – DORK TOWER 03.08.26 [Dork Tower]

Most DORK TOWER strips are now available as signed, high-quality prints, from just $25!  CLICK HERE to find out more!

Obviously, Medical Expenses are on the way! Want to help? Please consider joining the DORK TOWER Patreon and ENLIST IN THE ARMY OF DORKNESS TODAY! It’s what keeps the strip going (but it’s also a fun community)!

 

14:49

Security updates for Thursday [LWN.net]

Security updates have been issued by AlmaLinux (freerdp, go-fdo-server, golang-github-openprinting-ipp-usb, kernel, kernel-rt, nodejs:24, perl-DBI, and php), Debian (firefox-esr, libapache2-mod-auth-openidc, and libass), Fedora (dracut, exiv2, firefox, freerdp, gvfs, mingw-expat, mingw-gstreamer1, mingw-gstreamer1-plugins-bad-free, mingw-gstreamer1-plugins-base, mingw-gstreamer1-plugins-good, mingw-openexr, nss, proftpd, and syncthing), Mageia (apr-util, bubblewrap, libalsa2, libarchive, perl-Net-OAuth, perl-Text-CSV_XS, perl-XML-Bare, and perl-YAML-Syck), Oracle (freerdp, gimp, golang, iperf3, nginx:1.24, nodejs:22, nodejs:24, pipewire, wget, xmlrpc-c, and xorg-x11-server-Xwayland), SUSE (apache2-mod_auth_openidc, apptainer, apr-util, bzip2, c-ares, cosign, dhcpcd, dovecot22, emacs, erlang, gegl, gopass, gzip, httpcomponents-client, incus, kernel-devel, libgpg-error, libsoup2, mozillafirefox, mozilla-nss, mozilla-nspr,, MozillaFirefox, mozilla-nss, mozilla-nspr, rust-cbindgen, nodejs20, orthanc, orthanc-authorization, orthanc-postgresql,, postgresql14, python-cryptography, python-msgpack, quagga, snpguest, snphost, texlive, tuxguitar, udisks2, vim, wget, and yast2-users), and Ubuntu (apr-util, biosig, linux, linux-aws, linux-azure, linux-azure-fips, linux-fips, linux-hwe-5.4, linux-ibm, linux-ibm-5.4, linux-iot, linux-kvm, linux-oracle, linux-raspi, linux-raspi-5.4, linux-xilinx-zynqmp, linux-aws-5.15, linux-gcp-5.15, linux-oracle-5.4, sssd, and tika).

14:07

09/01/26 [Flipside]

I'm back from Thailand, but I have to go to a convention in Texas right away this weekend! Let's do another Patreon Stream before I leave!

https://www.twitch.tv/flipsider99

Will be inking comics, feel free to come by and watch!

Free Software Directory meeting on IRC: Friday, September 11, starting at 12:00 EDT (16:00 UTC) [Planet GNU]

Join the FSF and friends on Friday, September 11 from 12:00 to 15:00 EDT (16:00 to 19:00 UTC) to help improve the Free Software Directory.

GNU Parallel 20260822 ('Ceuta') released [Planet GNU]

GNU Parallel 20260822 ('Ceuta') has been released. It is available for download at: lbry://@GnuParallel:4

Quote of the month:

  Parallel has an option for almost everything, it's almost too much.
    -- tester457@ycombinator

New in this release:

  • Replacement string: {%jq: jq-expression %}
  • Use $^X when calling perl. So if different versions of perl are found in $PATH, we use the same version that started GNU Parallel.
  • Bug fixes and man page updates.


GNU Parallel - For people who live life in the parallel lane.

If you like GNU Parallel record a video testimonial: Say who you are, what you use GNU Parallel for, how it helps you, and what you like most about it. Include a command that uses GNU Parallel if you feel like it.


About GNU Parallel


GNU Parallel is a shell tool for executing jobs in parallel using one or more computers. A job can be a single command or a small script that has to be run for each of the lines in the input. The typical input is a list of files, a list of hosts, a list of users, a list of URLs, or a list of tables. A job can also be a command that reads from a pipe. GNU Parallel can then split the input and pipe it into commands in parallel.

If you use xargs and tee today you will find GNU Parallel very easy to use as GNU Parallel is written to have the same options as xargs. If you write loops in shell, you will find GNU Parallel may be able to replace most of the loops and make them run faster by running several jobs in parallel. GNU Parallel can even replace nested loops.

GNU Parallel makes sure output from the commands is the same output as you would get had you run the commands sequentially. This makes it possible to use output from GNU Parallel as input for other programs.

For example you can run this to convert all jpeg files into png and gif files and have a progress bar:

  parallel --bar convert {1} {1.}.{2} ::: *.jpg ::: png gif

Or you can generate big, medium, and small thumbnails of all jpeg files in sub dirs:

  find . -name '*.jpg' |
    parallel convert -geometry {2} {1} {1//}/thumb{2}_{1/} :::: - ::: 50 100 200

You can find more about GNU Parallel at: http://www.gnu ... rg/s/parallel/

You can install GNU Parallel in just 10 seconds with:

    $ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
       fetch -o - http://pi.dk/3 ) > install.sh
    $ sha1sum install.sh | grep c555f616391c6f7c28bf938044f4ec50
    12345678 c555f616 391c6f7c 28bf9380 44f4ec50
    $ md5sum install.sh | grep 707275363428aa9e9a136b9a7296dfe4
    70727536 3428aa9e 9a136b9a 7296dfe4
    $ sha512sum install.sh | grep b24bfe249695e0236f6bc7de85828fe1f08f4259
    83320d89 f56698ec 77454856 895edc3e aa16feab 2757966e 5092ef2d 661b8b45
    b24bfe24 9695e023 6f6bc7de 85828fe1 f08f4259 6ce5480a 5e1571b2 8b722f21
    $ bash install.sh

Watch the intro video on http://www.youtub ... L284C9FF2488BC6D1

Walk through the tutorial (man parallel_tutorial). Your command line will love you for it.

When using programs that use GNU Parallel to process data for publication please cite:

O. Tange (2018): GNU Parallel 2018, March 2018, https://doi.org/1 ... 81/zenodo.1146014.

If you like GNU Parallel:

  • Give a demo at your local user group/team/colleagues
  • Post the intro videos on Reddit/Diaspora*/forums/blogs/ Identi.ca/Google+/Twitter/Facebook/Linkedin/mailing lists
  • Get the merchandise https://gnuparall ... igns/gnu-parallel
  • Request or write a review for your favourite blog or magazine
  • Request or build a package for your favourite distribution (if it is not already there)
  • Invite me for your next conference


If you use programs that use GNU Parallel for research:

  • Please cite GNU Parallel in you publications (use --citation)


If GNU Parallel saves you money:



About GNU SQL


GNU sql aims to give a simple, unified interface for accessing databases through all the different databases' command line clients. So far the focus has been on giving a common way to specify login information (protocol, username, password, hostname, and port number), size (database and table size), and running queries.

The database is addressed using a DBURL. If commands are left out you will get that database's interactive shell.

When using GNU SQL for a publication please cite:

O. Tange (2011): GNU SQL - A Command Line Tool for Accessing Different Databases Using DBURLs, ;login: The USENIX Magazine, April 2011:29-32.


About GNU Niceload


GNU niceload slows down a program when the computer load average (or other system activity) is above a certain limit. When the limit is reached the program will be suspended for some time. If the limit is a soft limit the program will be allowed to run for short amounts of time before being suspended again. If the limit is a hard limit the program will only be allowed to run when the system is below the limit.

FreeIPMI 1.6.19 Released [Planet GNU]

o Fix minor groff warnings in manpages.
o Fix portability of building manpages.
o Fix minor bugs found by code analysis:
  - bmc-watchdog: Fix bug with --arp-response command line parsing.
  - ipmi/rmcpping: Fix bug with finding an IPv6 interface.
  - ipmidetect: fix bug in which hostname configs not used properly
  - ipmi-oem intelnm: fix parsing of hours/minutes error
  - ipmi-oem: Correct Dell CMC IPv6 autoconfiguration output.
  - ipmi-oem: Correct Dell iDRAC web server control output.
  - libipmidetect: Isolate partial results between fallback servers.
  - libipmidetect: Honor caller-provided hostnames over configured defaults.
  - common: Preserve stream state when finishing buffered output.
  - common: Fix buffer-output configuration parse issue.
  - common: Parse UTC offset configuration as an integer.
  - ipmiconsole: Monitor both console descriptors.
  - ipmiconsole: Check valid payload instance range correctly.
  - ipmi-sel: Honor post-clear after full tail output.
  - ipmi-fru: Report DIMM capacities in megabytes.
  - ipmi-chassis: Apply the Power-On Hours scale correctly.
  - libipmimonitoring: fix mem-leak on SEL iterator
  - libipmimonitoring: allow cipher suite 0 in configs
  - libipmimonitoring: report NO_SEL_RECORDS instead of
    NO_SENSOR_READINGS cut and paste errors in some functions.
o Fix potential stack overflows found by code analysis in ipmi-oem dell get-system-info command (specifically idrac-info, cmc-info, cmc-ipv6-info subcommands) and ipmi-oem fujitsu get-sel-entry-long-text.
o Fix potential stack overflow in libfreeipmi also related to Fujitsu long SEL entries.


https://ftp.gnu.o ... pmi-1.6.19.tar.gz

automake-1.18.92 released [beta] [Planet GNU]

This is to announce automake-1.18.92, a beta release in preparation for automake-1.19.  Announcement:

https://lists.gnu ... -08/msg00000.html

unrtf 0.21.12 [Planet GNU]

unrtf 0.21.12 is released, fixing a serious recently submitted security issue.

GNU Health strict No Generative Artificial Intelligence Policy [Planet GNU]

Dear community

We have included in the GNU Health Code of Conduct the strict NO Generative Artificial Intelligence policy.

The current version reads:

GNU Health Strict No Generative Artificial Intelligence Policy

GNU Health is social project made by humans and for humans. We DO NOT accept any code, artwork, review, documentation or issues created by generative Artifical Intelligence (GenAI) / Large Language Models (LLMs).

The GNU Health no-AI policy is because we strongly believe that:

* GenAI is bad for Mother Nature
* GenAI is bad for human rights, especially for underserved and marginalized communities.
* GenAI is bad for the Free Software and Free Culture communities.
* GenAI is bad for you

Last but not least, GNU Health manages critical health information both at personal and population level. There must be a reasoning behind every single line of code. We make all the effort to minimize bugs that can jeopardize the integrity and security of the system, and we can not risk the project by putting it in hands of stochastic parrots.

Let’s keep the art and science of computing a human virtue.


You can read the entire, most current version of GNU Health Code of conduct here:
https://docs.gnuh ... ndix/conduct.html

Joe Marshall: Recursive Descent: Vibe Coded Rogue-like in Common Lisp [Planet Lisp]

I was talking with Amit Patel of Red Blob Games the other day and he mentioned that he had been participating in a programming endeavor where people were creating variations of rogue-like games based on a tutorial. He had just begun experimenting with vibe coding and figuring out how to do it and what works for him. This sounded like an interesting idea, so I decided to try it out myself. I began with the basic tutorial, but since I'm a Lisp programmer, I decided to vibe code the game in Common Lisp. I had a few goals in mind:

  • I wanted to see if I (actually the LLM) could code up a rogue-like game in the browser
  • I wanted to see what sort of interesting code the LLM would produce: Would it be a good design? Would it use macros? Would it use CLOS? Would it get overly complex and "hit the wall" at some point?
  • How would it handle being told to work with functional programming style given that this sort of game is traditionally written in stateful, object-encapsulated style?

I mostly vibe coded this, but I did step in and make adjustments here and there. For example, I specifically requested that the LLM use a functional programming style, and I asked it to refactor large files into smaller ones.

Beginning

Getting started was tricky. I basically wanted a simple terminal emulator in the browser that would would display a fixed-width grid of characters that the back end could update. I wanted to be able to send keypresses to the back end and have it update the display. I didn't have a clear idea about how to do this, so I experimented a bit and came up with something relatively easy. The front end is a simple HTML page with a <div> is expected to contain the grid of characters. The front-end runs some JavaScript opens a WebSocket connection to the back end and sits in a loop waiting for messages. The back end sends messages to the front end that contain a block of html that the front end just inserts into the <div>. The front end also listens for keypresses and sends them to the back end. I didn't expect that this would be a very efficient way to do it, but I figured that a modern browser and reasonably good internet connection would be able to handle a modest refresh rate.

As coding progressed, the LLM extended the front end to include multiple <div>s, including pop-up modals. The LLM also augmented the front end to reconnect to the back end if the connection was lost, and direct focus to the playing area with the page was displayed. Othewise, the front end is a relatively thin client that mostly displays exactly what the back end sends it.

Real time back end

I started out with the standard rogue-like game loop, which is a synchronous, turn-based loop. The back end would wait for a keypress, then update the game state and send the new display to the front end. This works, but I remembered how the developers of Diablo said that when they decided to make it real-time it completely changed the game. I decided to make the back end real-time, but with a slow enough tick rate that I wasn't overwhelming the connection or the browser. Eventually I decided on a tick rate of 20Hz. Most of the effects in the game are timed around a 0.1 second interval (the rate at which the keyboard repeats when you hold down a key) and 20Hz is the Nyquist frequency to avoid aliasing (which would make the game stutter weirdly if you tried to run by holding down an arrow key). This makes the game feel responsive enough without it needing to refresh at CRT rates. Since the game is based on a grid of ascii characters rather than a bitmap, I guessed that the bandwidth requirements would be modest enough that this would work.

The first few hours vibe coding were spent getting a player character to run around a procedurally generated dungeon. Once I had that working, I asked the LLM to refactor the back end into a functional core with a stateful wrapper. The functional core is a pure function that takes the current game state and a message from the front end (typically a keypress) and returns the new game state. The stateful wrapper manages the WebSocket connection and the game loop. Once the back-end had been refactored into a functional core, the LLM generally continued to keep side effects out of the code, although it did introduce some reasonable side effects to manage a LRU cache of game state in order to save on recalculations.

Every action in the game is modeled as a pure reducer function. `MOVE-PLAYER`, `DRINK-POTION`, `PROCESS-ENEMY-TURNS`, etc. all follow the same signature: they take the current `GAME-STATE` plus some inputs, and return a freshly allocated `GAME-STATE` representing the world one tick later.

To achieve this without writing thousands of lines of boilerplate copy constructors, the engine heavily leverages Common Lisp's Meta-Object Protocol (MOP). The `copy-instance` and `update-entity` helpers dynamically iterate over a class's slots at runtime. When an Orc takes 5 damage, the engine doesn't mutate the Orc; it uses the MOP to spin up a brand new Orc with identical properties, except for a modified HP slot, and substitutes it into the new `GAME-STATE`'s entity list.

Decoupled I/O State

To avoid locking as much as possible, the engine decouples the I/O state from the game state. When the Hunchensocket WebSocket read-thread receives a JSON packet from a client, it does exactly two things: it parses the JSON into an immutable RDESCENT-COMMAND CLOS object (like move-command or drink-command), and it dumps that command into a thread-safe SB-CONCURRENCY:QUEUE. It never touches the game state.

Meanwhile, a single, dedicated game-loop thread acts as the heartbeat. Once every 50ms, the TICK-ALL-CLIENTS function wakes up, drains the input queues for every connected client, and folds those commands over that client's GAME-STATE using the pure ADVANCE-GAME-STATE reducer. This means a player mashing the keyboard at 100 APM can never cause a race condition or force the engine to lock the state tree. The I/O is asynchronous, but the game logic is predictably synchronous.

Because the game runs in real-time, it needs a way to blend the fast-paced player inputs with slower, methodical monster AI. This is handled via an Energy accrual system.

Every tick, every entity (players and monsters alike) accrues `ENERGY` equal to their `SPEED` stat. Actions have flat energy costs. The game loop refuses to process an action for an entity until its energy balance can afford it. This allows the engine to support speed-altering buffs and debuffs simply by tweaking the energy thresholds or accrual rates, without needing a bespoke cooldown-timer subsystem.

Procedural Dungeon Caching

Dungeon generation in `Recursive Descent` is deterministic, seeded by a hash of the dungeon level. This means GENERATE-DUNGEON will always carve the exact same rooms and corridors for Level 5, every time. The engine doesn't need to store the entire dungeon in memory for every player; it can simply regenerate the same layout on demand.

Because the generation is deterministic, and the GAME-MAP geometry (the TILE array) is strictly immutable, the architecture introduces a *DUNGEON-CACHE*. When a player drops down to Level 5, the engine checks the cache. If the geometry is already there, it just hands a pointer to the existing immutable map to the player's GAME-STATE. Multiple players on the same tier and level share the same physical memory space for the dungeon walls and floors, reducing the memory footprint of the server.

Save Games Stored on the Client

Instead of maintaining a massive, clustered database to store player progression, the server is entirely stateless across sessions. When a player hits the Save button, the Lisp server serializes their entire immutable GAME-STATE (including all visited levels, dropped items, and explored fog-of-war bit-vectors) into an association list. It then zlib-compresses it, signs it with an HMAC-SHA256 hash using a server-side secret key, base64 encodes it, and sends it back to the client over the WebSocket.

The client's browser stores the save blob in localStorage. When the player reconnects, they hand the blob back. The server verifies the signature, decompresses it, and resurrects the CLOS objects. Thus we offloaded the database hosting to the user's hard drive.

Client Registry

Tracking connected users in a multithreaded web server usually involves wrapping a global list in a heavy mutex, which creates a bottleneck every time the game loop iterates over it.

To solve this, server.lisp isolates the *RDESCENT-CLIENTS* list inside a dedicated background actor thread (RDESCENT-CLIENTS-REGISTRY-LOOP). No other thread is allowed to touch it. When Hunchensocket receives a new connection or a disconnect, it drops a simple (:CONNECT client) or (:DISCONNECT client) message into the actor's mailbox. When the game loop needs the list of players for the next tick, it sends a (:SNAPSHOT) message and waits for the actor to reply with the current list. This guarantees that the client roster is never mutated out from under an active iteration, cleanly sidestepping deadlocks.

Fat Base Class

Modern game development typically uses Entity-Component-System (ECS) architectures to avoid massive inheritance trees. `Recursive Descent` ignores this trend. The base ENTITY class is deliberately "fat." It holds everything: spatial coordinates (X, Y), rendering data (CHAR, RENDER-ORDER), combat stats (HP, POWER, DEFENSE), inventory, equipment, and all seven RPG Stats (Strength, Dexterity, Charisma, etc.).

In a mutable OOP design, a fat base class is a maintenance nightmare. In a purely functional CLOS architecture, it is an advantage. Because state mutation is handled entirely by a Meta-Object Protocol (MOP) helper (COPY-INSTANCE / UPDATE-ENTITY) that dynamically walks the class slots to clone the object, having a wide, flat property list is functionally cheap. You don't need complex component-querying logic; you just ask the entity for its DOMAIN-KNOWLEDGE and move on.

Interestingly, there is no PLAYER class. The player is simply a baseline ENTITY instance that happens to be bound to the PLAYER slot of the GAME-STATE. It uses the exact same combat resolution, inventory handling, and stat scaling as any monster.

Entity Subclasses

Instead of overriding methods to change behavior, the ENTITY subclasses primarily exist to provide specific :DEFAULT-INITARGS and to act as dispatch targets for generic functions.

  • ENEMY — Adds no new slots. It simply provides an :AFTER initialization method to guarantee an enemy defaults to a :HOSTILE disposition and derives its XP value from its HP.
  • AUTO-PICKUP-ITEM — Represents a scavenger hunt collectible. It defaults IS-ALIVE to NIL and BLOCKS-MOVEMENT to NIL, keeping it out of the AI processing loop and allowing the player to freely walk over it.

Fixture Hierarchy

Fixtures represent stationary, non-hostile map objects (shrines, vendors, NPCs) that the player interacts with via a dedicated command rather than by bumping into them. The base FIXTURE class defaults IS-ALIVE to NIL (excluding it from the enemy AI turn loop) and BLOCKS-MOVEMENT to NIL (allowing the player to stand on it).

The hierarchy branches out based on internal state requirements:

  • SHRINE-FIXTURE — Adds a `USE-COUNT` slot to track finite activations.
  • VENDOR-FIXTURE — Stateless beyond its base properties. Its "stock" is derived globally, and it requires no mutable inventory of its own.
  • NPC-FIXTURE — Likewise stateless. Quest progress is stored in the player's GAME-STATE flags rather than on the NPC, ensuring the NPC remains purely shared, immutable geometry.
  • TRAP-FIXTURE — Adds a HIDDEN-P slot to dictate rendering visibility, flipping to NIL once triggered or spotted.

Command Pattern

RDESCENT-COMMAND input handling relies on a polymorphic Command Pattern. The WebSocket read thread parses raw JSON into a concrete subclass of RDESCENT-COMMAND (MOVE-COMMAND, USE-ITEM-COMMAND, EQUIP-COMMAND, etc.).

Instead of a massive COND statement checking command types, the engine uses CLOS generic functions (EXECUTE-QUEUED-COMMAND). Each command class has a specific method that invokes the appropriate state reducer (e.g., the DRINK-COMMAND method calls DRINK-POTION). This makes extending the engine's vocabulary trivial: adding a new command means defining a tiny data class and writing exactly one generic method for it.

State Containers

GAME-MAP: Holds the TILES array. A TILE contains purely static, shared geometry (walls, floors, room-type tags). Because this never mutates based on player action, a GAME-MAP can be safely memoized and shared across multiple players on the same depth via the *DUNGEON-CACHE*. GAME-STATE: The server-authoritative snapshot for a specific player. It holds the PLAYER entity, the list of other ENTITIES on the floor, the field-of-view EXPLORED bit-vector, and the LEVELS FSET map (which archives DUNGEON-LEVEL-SNAPSHOTs of previously visited floors).

The Imperative Shell: RDESCENT-CLIENT Sitting at the very top of the stack is RDESCENT-CLIENT, a subclass of Hunchensocket's WEBSOCKET-CLIENT. This is the only place where mutability is permitted. It acts as the anchor, holding the connection's thread-safe INPUT-QUEUE for incoming commands, and the mutable pointer to the current immutable GAME-STATE. This is where the game state is updated with the new game state.

Conclusion

The LLM did a good job of vibe coding a rogue-like game in the browser. At one point I simply sat down and brainstormed a list of features that I wanted to add to the game. Then I told the LLM to design an architecture that would be amenable to adding those features. Then I told the LLM to implement the architecture. When it was done, I told the LLM to prioritize the features I wanted to add suggest an implementation order. Then I told the LLM to implement each feature in turn.

At a couple of points, the LLM was letting a monolithic file get out of hand, so I explicitly told it to refactor the code into smaller files I also made an explicit pass to make sure that the compile was giving no warnings. The LLM had a tendency to use large etypecase statements to dispatch on the type of an object. I explicitly told it to use CLOS generic functions instead, and it did so. OTher than that, I basically left the LLM to generate code how it saw fit.

If you want to try out the game, you can run it in your browser at https://jrm-code-project.com/rdescent.html. If you just want to peruse the source code, you can find it at https://github.com/jrm-code-project/jrm-code-public/tree/main/rdescent, but try the game before you look at the code because the code contains spoilers. No guarantees it will work on your browser. Mine has a fairly big display and a reasonably high bandwidth connection, but I don't know about yours. No way this would work on a phone.

Tim Bradshaw: Blank generation [Planet Lisp]

I belong to the blank generation and
I can take it or leave it each time, well
I belong to the _ generation but
I can take it or leave it each time.

My destructuring-match macro has a notion of ‘blank’ variables: any variable whose name is "_" is both unique and ignored. This is useful because when pattern matching you often only care about some of the thing you matched: the rest is just placeholders. Štar does the same thing.

This idea, and the names of blank variables, is not something I invented. I think I probably stole it from Racket, which I’m sure got it from somewhere else. Lots of people have done this.

Well, a while ago I thought it would be nice if CL didn’t distinguish between binding multiple values and binding single values: why can’t a single form do both? So I wrote let-values which does this. Again, I’m far from the first person to do this, although let-values makes a more serious attempt to handle declarations properly than most, I think.

So, should let-values support blank variables? Well, I thought it should, so I changed it so it did. So, for instance, you could write

(let-values (((_ present) (gethash ...)))
  ... present ...)

which is nice, perhaps.

I’ve changed my mind: let-values shouldn’t support blank variables, I think. The reasons for this are that it’s a general binding construct, unifying let and multiple-value-bind and their starred variants, and it should compose with other things. Those other things might have their own ideas of variable names, and in particular they might create variables called "_" which are not meant to be blank.

Štar and DSM are not general binding constructs, so I think that blank variables are OK there. But I don’t, now, think they’re something that a general construct should have. Something like

(for ((_ (in-naturals n)) ;bound iteration
      (x ...))
  ...)

is also just a really common thing to want to do: you don’t want to have to clutter up code with ignore declarations in this case. A similar thing applies for DSM.

Later on, after writing the first version of this post, I changed my mind again. let-values now optionally supports blank variables. There is a variable, *blank-variables*, which controls whether blank variables are supported. This matters at macroexpansion time, of course. *blank-variables* is exported from a distinct package, org.tfeb.hax.let-values/blanks so that if you merely use the org.tfeb.hax.let-values package you just get the four names it exported previously. This seems like a reasonably clean compromise.

Link [Scripting News]

We got agents running in Atlantis today. Screen shot.

Link [Scripting News]

A bunch of tech billionaires have chipped in a million each to fund a new Linux distribution. I can't imagine how this is supposed to work, all those huge human egos, how much will they pay their developers to contribute what. I have to find out what the goal of the project is. It would be nice to have a Linux that was extensively tested for use by regular people.

Link [Scripting News]

After saying I was putting my tech work aside, yesterday, I had a bolt of determination, and realized I don't like collaborating with Claude Code, but maybe it's just when we get to this stage of a project where it's all details, and they're hard to communicate, and the bot has a bad habit of ignoring things I tell it to do. It also returns code to me to test that no human developer would pass on to a user. It would be too embarrassing. But the bot isn't aware in the same way a human is, not even close. Now that is something I'm sure they can be taught to simulate well enough to be as good as a human collaborator.

My year with Claude Code [Scripting News]

Everyone is introducing themselves on the Berkman community mail list, at the beginning of the fall semester, and here's the story I am telling.

Good morning. My name is Dave Winer. I was at Berkman in 2003-04, worked on blogging, podcasting, RSS, political blogging and the connection to journalism. We had a couple of Bloggercons at Harvard, had a wonderful time, miss it terribly, wish we could have it back.

I've spent the whole of this year working in Claude Code on a couple of programming projects, one which which I had been struggling with for a couple of years, coming up with a user interface for a Twitter-like system that runs on the web for real, without any of the limits that the silos have (that help them enforce the boundaries of the silo). Just using HTML, Markdown, RSS, WebSockets. Turns out you can make a pretty nice system, but the going is slow because it's just me and Claude, on the other hand, what a huge difference in territory we can cover. This is the kind of stuff that's never covered in the reporting, even when there are massive changes happening in how software is developed, people don't seem to be studying it. I'm sharing all I learn as I learn it on my blog -- at scripting.com.

Also attempting a massive coding job at the same time, getting UserLand Frontier to run on current OSes. It's my life's work, but it was very much in danger of being lost, along with all the software I did before the web. Now we're close to getting it to run in a stable mode, here the challenge has been to teach Claude how a new type of software works, it keeps trying to snap back to systems that are already out there and widely deployed. It doesn't do "pioneering" at all, it needs a human to guide it. And the human guide has to be a developer with a lot of experience.

What I desperately want to do is bootstrap a network of people who work at the level I'm working, and write about it. Taking ideas that are well-explored in software in the pre-AI period, and seeing what we can do that we couldn't before.

The models have been getting increasingly better, you can really feel the difference.

Next year promises to be better, if only via the improvements that will be made by the platform vendors, but it's likely that good app developers will be able to move the leading edge forward much more quickly and users should feel this, if all goes well, real soon now.

Link [Scripting News]

The blogging tools for Bluesky should be able to publish on Bluesky.

Link [Scripting News]

Obama should have seated Garland if the Senate wouldn’t have a vote to advise and consent. Assume they consent. In the same way, the governor of Kentucky should appoint a successor to McConnell unless someone can prove he’s actually alive. The Democrats always put up with Republican tricks like this one. I'm sure McConnell would appreciate the utility of his death, and the Republican lack of shame. Anything for a buck.

Link [Scripting News]

Creative computer people, consider consolidating all the different OSes and programming languages. Give humans a fair fight in competition with the AI's who have no trouble deeply understanding every syntax human designers have come up with, where it totally disadvantages us, who have much more limited memory.

Link [Scripting News]

If you View Source on a fatpage, scroll to the bottom, you'll see the code. Example. The idea is that the docs for the code are what you see in the browser. Maybe that's the way feeds should work too? Something to think about.

Link [Scripting News]

I begin the month of September for some reason, not feeling like working. And rather than succumb to the work ethos, I'm allowing myself to goof off with the same determination that I worked my ass of for so many years. I think the last time I felt like this was when I was a grad student in Madison. I had just fallen in love with a sweet, funny, cute and gorgeous undergrad. She was 19 and I was 22. We spent the last weeks of the fall semester goofing off, and as a result I had to stay in Madison over the holidays, to finish the work of the Compiler Design course, which was the gate for grad students, the hardest course. If you got through it with a decent grade, you got the degree. It was fun too -- except I missed my sweetheart. This time I don't know what the root is, but it's a good feeling. If I want to goof off, I can, no one will judge me, probably very few people even notice. I still expect to finish Frontier, and swing back around to FeedLand and RSS.chat, they have some important work to do, together. Maybe the reason is the thing I liked about making software is the actual making of it, which I delegate more and more to Claude Code. How would a great painter feel if they invented a computer that could write their "code" much more quickly, would Picasso have stopped painting just because Claude Code could do Picasso paintings faster? Today, Claude still will, if given a chance, throw out all of my orders and develop code in a non-Dave fashion. And it still acts as if between the two of us it's the only programmer, surprised when I want to actually write something myself. Maybe that's just my imagination? Or maybe that's the next project for me. A project where I write the code, and Claude helps out when I can't find a bug, or where I need to know something about a feature in a platform I've not worked on.

Link [Scripting News]

OPML archive for August 2026.

You Can't "Vibe Code" Love [Coding Horror]

You Can't "Vibe Code" Love

About a year ago, I was offered a presentation slot at the WeAreDevelopers World Congress in Berlin. I rarely take speaking engagements, especially international ones, but this one arrived at just the right time, the right place, and with the right person – I said yes, on the contingency that Ben Dumke-von der Ehe joins me in the presentation. Ben is an early community hire at Stack Overflow who lives in Berlin. We both had something important we wanted to talk about, with slightly different opinions, different perspectives.

They agreed to the requirement. This is our presentation, as delivered Friday, July 10th at the CityCube in Berlin.

The heart of this presentation is the human story of how Ben and I met. As I said on stage:

The long version of this story is that we changed each others' lives. The short version is: unicorns.

You should hear Ben's side of the story directly from him. It's remarkable. Also remarkable is that he left Stack Overflow, then came back... and then left again. I told Ben, I'm mostly doing this presentation because I owe you so much.

You Can't "Vibe Code" Loveit is difficult to get a German to smile so you have to sneak attack

Not only Ben, but everyone who participated on Stack Overflow. We did it together, under a bedrock Creative Commons license that respected the effort everyone put into their work to build this commons, this hugely influential Stack Overflow dataset.

You Can't "Vibe Code" Love

It's fine that LLMs intercept most (if not all) of the common programming questions; this aligns with the higher level goals of Stack Overflow:

Passively searching and reading highly ranked Stack Overflow answers as they appear in web search results is arguably the primary goal of Stack Overflow. If Stack Overflow is working like it’s supposed to, 98% of programmers should get all the answers they need from reading search result pages and wouldn’t need to ask or answer a single question in their entire careers. This is a good thing! Great, even!

LLMs also cut the gordian knot of constant duplicate questions that I thought was basically impossible.

When you’re asking a question on a site that doesn’t allow duplicate questions, the problem space of a site with 1 million existing questions is rather different from a site with 10 million existing questions... or 100 million. Asking a single unique question goes from mildly difficult to mission almost impossible, because your question needs to thread a narrow path through this vast, enormous field of prior art questions without stepping on any of the vaguely similar looking landmines in the process.

The way LLMs can map a duplicate question using entirely different words to an existing answer is incredibly transformative, and a huge net positive. Less duplication. More answers, faster. That's the point.

But what happens to the commons when everyone is privately whispering to LLMs? What happens to the communities where programmers learn from each other, the very communities like Stack Overflow where Ben had so much fun becoming a programmer, and got hired for doing things he loved?

You Can't "Vibe Code" Love

You can't "vibe code" love.

Where exactly will the LLMs get their next set of training data from, if we don't build for and protect the commons together? How will we continue to share knowledge – and love – with each other?

The perils of binding to value types in XAML [The Old New Thing]

A colleague ran into trouble with their XAML program. They were using a FlipView control to bind to a collection, but when the user tried to navigate the FlipView using an assistive technology tool, there were cases where the navigation failed.

Some time later, they came back with the solution to the mystery.

The team noticed that their data model consisted only of strings and other value types, so they decided to declare their data model as a struct rather than a full runtimeclass, thereby avoiding a lot of boilerplate typing.

If defined as a runtimeclass:

// MyComponent.idl
runtimeclass MyPageContent
{
    String Title { get; };
    String Description { get; };
    String LinkUri { get; };
    Boolean IsNew{ get; };
}

// MyPageContent.h

namespace winrt::MyComponent
{
    struct MyPageContent : implements<MyPageContent>
    {
        MyPageContent(hstring const& title,
                    hstring const& description,
                    hstring const& link,
                    bool isNew) :
            m_title(title),            
            m_description(description),
            m_link(link),              
            m_isNew(isNew) {}          

        hstring Title() const { return m_title; }
        hstring Description() const { return m_description; }
        hstring Link() const { return m_link; }
        bool IsNew() const { return m_isNew; }

    private:
        hstring m_title;
        hstring m_description;
        Windows::Foundation::Uri m_link;
        bool m_isNew;
    };
}

// Consumer.cpp

m_pages.Append(winrt::make<MyPageContent>(
                    title, description, link, isNew));

But if you define it as a struct, then most of this code isn’t necessary:

// MyComponent.idl
struct MyPageContent
{
    String Title;
    String Description;
    String Link;
    Boolean IsNew;
}

// MyPageContent.h not needed

// Consumer.cpp

m_pages.Append(MyPageContent(title, description, link, isNew));

Tastes great, less filling.

Now, the thing that makes value types value types is that they are copy-by-value, not copy-by-reference. This means that when XAML calls GetAt(n) on the m_pages to get the nth item, it gets a copy of the MyPageContent and binds to the copy.

And that’s the source of the problem.

When the code wants to navigate to a specific item at the request of the assistive technology tool, it passes the MyPageContent to navigate to, but that’s just another copy because value types are always passed by copy. XAML says, “I don’t have that guy” and fails the navigation. (XAML doesn’t realize that it has a guy who looks just like that guy. Not that it matters, because it’s not the same guy.)

The clever shortcut turned out to be the problem.

Now, while it’s true that there’s a bunch of typing needed to implement a C++/WinRT runtime class, there are helpers to reduce the amount of typing required. In the Windows Implementation Library (wil), the cppwinrt_authoring.h header contains classes to simplify the implementation of events and properties. It exploits CRTP in the same way I discussed some time ago.

// MyPageContent.h

namespace winrt::MyComponent
{
    struct MyPageContent : implements<MyPageContent>
    {
        MyPageContent(hstring const& title,
                    hstring const& description,
                    hstring const& link,
                    bool isNew) :
            Title(title),            
            Description(description),
            Link(link),              
            IsNew(isNew) {}          

        wil::single_threaded_property<hstring> Title;      
        wil::single_threaded_property<hstring> Description;
        wil::single_threaded_property<hstring> Link;       
        wil::single_threaded_property<bool> IsNew;         
    };
}

We can get away with using a single_threaded_property because the properties are written only at construction, so concurrent reads are not going to cause problems.

The post The perils of binding to value types in XAML appeared first on The Old New Thing.

Microspeak: Funded / unfunded [The Old New Thing]

Recall that Microspeak is not merely for jargon exclusive to Microsoft, but it’s jargon that you need to know to survive at Microsoft.

In business, funding usually refers to having enough money to pay for ongoing operations.

In Microsoft engineering groups, it doesn’t mean that.

In Microspeak, funding refers to having enough people available to work on a feature. A feature that has adequate people assigned to work on it is considered to be funded, or for emphasis, fully funded, whereas a feature that does not have people working on it is unfunded.

Of course, you can have intermediate states, like partially funded, to say that some people have been assigned to it, but not enough to finish the work in time for a specific requested completion date.

Here are some citations I found.

Funding for this feature is being worked through.

This is another way of saying, “We are working on finding people to work on this feature.” This might come at the cost of defunding whatever feature those people had previously been assigned to.

The path for getting out of red involves closing on funding gaps.

In other words, there is a color-coded dashboard on which a feature is currently listed as red. There are currently some shortfalls in staffing (funding gaps), and we will have to resolve (close on) those shortfalls in order to get out of red to a more favorable color.

X said that they do not have engineering resources to fund the Y updates.

In a larger discussion about updating components throughout the system to support the Y feature, person X said that they do not have any people available who can do the Y work for their component.

Note that a feature that is unfunded is not cut. The feature is still planned. It’s just that there is nobody available to do it right now. If funding cannot be obtained soon, the feature will have to be delayed to a later release.

Bonus chatter: Software engineers are not fungible. If you take a developer who works on the taskbar and reassign them to the window manager they won’t be as effective as someone who normally works on the window manager. Furthermore, reassigning a developer across teams involves the receiving team having an open req, and reqs are generally difficult to come by since they are subject to all sorts of business constraints.

The post Microspeak: Funded / unfunded appeared first on The Old New Thing.

AWE does not require PAE, though PAE makes it much more useful [The Old New Thing]

The Address Windowing Extensions (AWE) is a feature of Windows that allows programs to allocate physical memory and map them on a page-by-page basis into a region of address space (the “address window”). PAE is the Physical Address Extension, which is a feature of the x86-32 CPU that allows a 32-bit processor to generate physical addresses larger than 32 bits, thereby allowing it to access more than 4GB of physical motherboard RAM.

Some time ago, I noted that AWE does not require PAE. The two features operate independently, but they are useful together.

If you use AWE without PAE, then your 32-bit Windows system can access only 4GB of onboard memory, so the feature of AWE that gives you access to lots of physical memory is of limited use: The system has only 4GB of memory to begin with, so that’s all that you can get. You wrote a lot of complex code for a high-RAM scenario when there isn’t really a lot of RAM available to take advantage of it.

It’s like getting a large teapot for making a single cup of tea: Your teapot has the capacity to hold a large amount of tea, but you’re going to put just one cup’s worth in it.

This is all largely historical information, since 64-bit processes running on 64-bit systems can allocate more than 4GB of memory and use it in the normal way. No special hoops necessary.

Note: One thing that AWE does give you is the ability to allocate physical non-pageable memory. Again, you can use this feature whether or not you have also enabled PAE.

Note 1: A 32-bit program that uses AWE will still run on a 64-bit system provided the 64-bit system uses the same page size as the 32-bit system. Looking at the table of page sizes used by Windows, it means that an x86-32 program (4KB page size) can run on an x86-64 system and an AArch64 system, but not an Itanium.

The post AWE does not require PAE, though PAE makes it much more useful appeared first on The Old New Thing.

Hey AI, Can You Just Give Me a Hat Tip Please? [Radar]

Sometime in the next few months, Anthropic is supposed to send me a check. Around $9,000 for me, about the same for my longtime coauthor Jenny Greene, and roughly $18,000 for O’Reilly, our publisher. The reason is that pirated copies of the books Jenny and I wrote, along with a huge amount of other people’s work, got swept into the data used to train Claude, and a court settlement is now paying authors and publishers whose work was taken that way. It works out to a little over $3,000 for each of our books, split between all of us, and every edition is counted separately, no matter how the book sold or what was in it. (Assuming the money ever shows up. The settlement won final court approval in July 2026, but a payout this size grinds through a long administrative process, so we’ll see if the check ever actually arrives.)

I don’t especially care about the check. (Okay, that’s not true, nine grand is a lot of money, but hopefully you’ll get my point.) Jenny and I didn’t write those books to get rich, and nobody who’s met a working author would mistake the job for a path to wealth. But one thing I very much care about, and I suspect almost all authors would agree, is getting credit for the work I’ve done. If you ask ChatGPT, Claude, or Gemini (or especially Google AI overviews) a question that it partly learned to answer from one of my books, I would love for it to be able to say so. Something like “Some of this comes from Andrew Stellman’s work, and if you want to go deeper, that’s where to look.” In other words, what I’m asking for is a hat tip.

All of this sits inside a much bigger question, one that usually goes by the name attribution. In the broadest terms, attribution means knowing where a piece of work or knowledge came from, and being able to trace it back to the person who made it. That might sound like a narrow, technical matter, but right now it’s one of the biggest live questions in AI. At Foo Camp recently, it came up constantly, quite possibly the most talked-about topic of the whole weekend, and everyone there seemed to have something to say about it. It’s also a tangled subject, part technical and part legal, and more than either of those, deeply emotional. I want to take a little time to pull those threads apart.

Why so many people are angry

Before any of the technical or legal questions, there’s a simpler reason attribution is such a live wire right now: People are angry, and to be perfectly honest, they have good reason to be. Artists have watched models learn to imitate their style from work that got scraped without anyone asking. Writers have found their books sitting in training sets we never agreed to (even though that’s not the reason Anthropic has to pay us). A lot of people are simply afraid that the work they do for a living is about to be done by a machine that learned part of the job from them. Their work got taken, which may be fair use but almost never included asking the author for permission, and often without any way to even find out it happened. And that for many of us feels really uncomfortable.

A lot of that anger ends up funneled into legalistic arguments about copyright, which is notoriously misunderstood and misapplied. People reach for it for understandable reasons. It feels tangible in a way the rest of this doesn’t, and while many of us feel like it was written to protect authors and artists and creators, it’s actually much more nuanced, especially when it comes to fair use. But I don’t think copyright is the right move for anyone who actually wants attribution, and I’ll go further: I think creators will get a lot more mileage working with the AI labs than fighting them in court.

Underneath all of it, what most of us want is simple enough: We want the work to still be ours, and we want that to be visible. That’s an attribution problem. And before anyone can argue about whether AI can solve it, it helps to be clear about what attribution even is, because it’s a slipperier word than it looks.

What attribution actually is

At its simplest, attribution is the link between something and where it came from. When you read a fact in a book, there’s a chain running from that sentence back to the author, and back again to whatever they drew on. That chain is how credit works, and how trust works, and how you know what to go read next when something grabs you. For as long as people have made things, you could usually follow it back to a person.

You see attribution everywhere once you start noticing it. Bibliographies and references are attribution. So is every footnote on a Wikipedia page, and so is every time one news story credits another, the way you’ll read that “Business Insider is reporting” something before another site passes it along (that is, when we remember to do it). For authors it runs deeper than that: Attribution underpins almost everything we do, and the whole system of academic publishing rests on it, because the entire point is to show exactly whose work each new piece is built on.

AI is the first technology that takes in essentially all of it, every book and article and repository it can reach, and hands back answers with the chain erased. And while that may be technically allowed under fair use, it shouldn’t be the end of the discussion. The knowledge comes out; the line back to whoever produced it does not. That erasure, underneath the lawsuits, is what people are really reacting to. The model learned from their work and gives no sign of it, and the trail that used to lead back to them is gone. Attribution is just the name for putting that thread back.

The catch is that people use the word for at least three pretty different things. The cheap version, the one people reach for first, is resemblance: Does the answer look like my work? That’s easy to check and mostly beside the point, because two people can write nearly the same sentence about a for-loop without either one copying the other. What actual products ship is citation, the little source links under a chatbot’s answer, which credit the page the system fetched while it was answering, not the books it learned from years earlier. Those links are the result of retrieval, not memory, where the system went out and fetched a live page mid-answer. There aren’t any technical challenges in adding an attribution for those live retrieval results, and the fact that the AI labs are fine with that attribution gives them a template to follow if model-based attribution becomes technically feasible.

We’ve got a really good real-world example of how this can work. O’Reilly’s learning platform has an AI engine that answers questions out of the books on the platform, tells you which ones it drew on, and pays the authors and publishers behind them. It works because the corpus is small and everything in it is licensed, which is precisely the condition the frontier models don’t have. Because the version that actually matters is the third one, causal: Did my work shape the part of the model that produced this answer? That’s the honest meaning of the word, and by far the hardest to compute.

Notice that none of that is about money. Paying me would mean working out what a given answer is worth and what share of it is mine, which is a hard allocation problem nobody has really solved (and, to be honest, probably works out to a tiny fraction of a cent in any given answer). Attribution asks a smaller question: Did this come from my work, or didn’t it? A hat tip is only that identification, not necessarily a required payment, and it’s still the thing everyone tells you is impossible.

Trying it on a tiny model

I may be an author, but I’m a developer too, and when someone tells us something is impossible, our first urge is always to build that thing. A lot of the time “impossible” just means nobody has worked out how yet, and every so often it means it would be inconvenient for someone if they did. In this case, some really smart people actually have worked out how, at least some important parts of it, and it’s worth understanding both why the problem is hard and how they’re tackling it.

Start with why it’s hard. When a model trains on your book, it doesn’t file the book away somewhere you can later point to, because models are not databases of books and other source material. What it learns gets spread across billions of numbers, tangled up with everything else it ever read, and no single weight says, “This part came from Stellman.” There’s no receipt anywhere that records which source contributed what. The obvious way to check whether your book mattered would be to pull it out, train the model over again, and see what changed, but nobody is going to retrain a frontier model from scratch a billion times. The upshot is that the knowledge is still in there, it’s just smeared across the whole model with no index back to where it came from, and that’s why a lot of people have called attribution impossible.

It may not be quite as impossible as it seems from that particular approach, though.

Researchers have been chipping away at exactly this, and the approaches run from cheap and rough to expensive and precise. At the precise end is leave-one-out: remove a source, retrain, and measure how far the answer falls. It’s about as close to ground truth as you can get, and hopeless at scale for the reason I just gave. The interesting work is on cheaper stand-ins that approximate that result without all that retraining. The one I find most compelling is TracIn, described by four Google researchers in 2020 in “Estimating Training Data Influence by Tracing Gradient Descent”: As the model trains, it saves snapshots of itself, and TracIn measures how much each training example pushed the model toward a given answer by comparing gradients at those snapshots, with no retraining required.

It belongs to a broader family. Influence functions, which Pang Wei Koh and Percy Liang introduced in 2017 in “Understanding Black-Box Predictions via Influence Functions,” are the older, heavier cousin, and Anthropic scaled them up to models with tens of billions of parameters in a 2023 paper, “Studying Large Language Model Generalization with Influence Functions.” A newer method, TRAK from MIT’s Madry Lab, takes on a weakness they share, where near-duplicate sources muddy the accounting. None of it is settled, and TracIn in particular is contested at frontier scale, but the direction is real and the people pushing it have far bigger budgets than mine.

So I wanted to see it work with my own eyes. I asked an AI to build me the smallest real language model that could still run one of these methods, and about 20 minutes later I had a working one, which I called tiny-provenance: a language model small enough, around 37,000 parameters, that I can retrain it from scratch in a few seconds. That size is the whole point, because it let me run the expensive leave-one-out check for real, as ground truth, and set the cheap TracIn approximation next to it to see whether they agreed.

They did. I gave it a trick question, “Who designed the Analytical Engine?” with a look-alike line about Babbage and the Difference Engine sitting right next to the correct one in the training data. The cheap resemblance check, the kind of thing real products lean on, took the bait and confidently credited the wrong line. Leave-one-out and TracIn both ignored the look-alike and pointed straight at the source the model actually used. The lazy method everyone reaches for was confident and wrong, the honest ones were right, and the whole thing ran in about two minutes on a laptop.

I proved it at a size where I can retrain the model at will, which is exactly what nobody can do at frontier scale, so I won’t pretend I showed it holds up there. Attribution works best at the extremes, where a model has nearly memorized a passage or leaned hard on a single source, and it stays hard in the muddy middle where an almost unimaginable number of books may each have added a tiny little bit to the model. The fair summary is that attribution isn’t impossible. It’s just currently expensive, and more importantly, really impractical with today’s technology.

The whole repo is public, and since this is an article about showing where things came from, it seemed only right to be transparent about where the demo came from too. The README walks through exactly how I built it, prompts and all.

The legal hurdle

I’ll put my own cards on the table: I think copyright is the wrong tool for the fight we’re having about AI. My first job out of college was at EMI Records, working on the system that tracked their music contracts, so I learned early how tangled copyright and trademark and mechanical royalties and the rest of it can get.

Here’s the analogy I keep coming back to. If a student copies a paragraph out of Wikipedia word for word, that’s plagiarism. If the student reads it, understands it, and rewrites it in their own words, usually it isn’t, though that depends on what got rewritten, because plagiarism is about the ideas and not only the words. A physics student writing “F=ma” in a paper isn’t plagiarizing, even if they copied the formula straight out of a textbook. On the other hand, paraphrasing a specific result from somebody’s research paper without saying where it came from is still plagiarism, even if you technically changed the words. And it gets even more complicated. If you copy text word for word but credit the source, you’re not plagiarizing, but you could still have a copyright problem. We throw around the term “fair use” a lot, but that’s actually a very thorny legal area. More importantly, reducing these ideas to a legal argument doesn’t really get to the core of the problem, because laws are often imperfect and dictated by decades of (sometimes conflicting) precedent, so what’s legal doesn’t always match up with what’s the right thing to do. What a model does is a step further from copying than the rewrite: It turns the text into an enormous pile of numbers that stand in for the concepts, and there’s no paragraph left anywhere to find. So far, the courts that have looked at this, including the one behind the Anthropic settlement, have called that use “exceedingly transformative” (those are the Anthropic judge’s words, and lawyers on both sides recognized that as quite a statement). What they mean is that it changes the work into something new enough, and for a different enough purpose, that it isn’t simply a copy of the original. I think they basically got it right.

Basically, I’m not getting a check from Anthropic because they used my work without permission; I’m getting a check because they literally used a stolen book downloaded from a pirated website, instead of paying O’Reilly for a copy or getting it from another legitimate source.

But I don’t get to wave copyright away entirely, because there’s a real case on the other side, and it’s one I feel personally. Someone who wants to learn C# or study for a project management exam can now ask an AI and get an answer that came partly from books I wrote, without ever buying the book. The model learned from my books (and many others on the same topics I write about), and now it competes with them, in the exact market they were written for, using what it took from them to do it.

The worry that AI tools compete with the very material they trained on isn’t theoretical. Stack Overflow, the question-and-answer site where a generation of programmers went for help, has lost roughly three-quarters of its question volume since ChatGPT launched, as developers ask the AI instead. And the AI answers them well in part because it trained on Stack Overflow’s answers in the first place. And even that whole issue is highly nuanced, especially since the material on Stack Overflow itself is written by its users and released to the public under a Creative Commons license.

That goes to the center of what copyright is meant to protect. One of the things courts weigh in a fair-use case is the effect on the market for the original, and a free substitute trained on the original is about as direct a market effect as there is. A judge has already pointed right at it. In the case a group of authors including Sarah Silverman brought against Meta, the court handed Meta a win on fair use. But the judge then went out of his way to hint that the the authors may have lost because they’d argued it wrong, and that this market-dilution theory, the flood of cheap substitutes, is exactly the one that could win on a better record. The judge also said there was “no serious question” that the use of the technology was “highly transformative” in his ruling, and again, lawyers consider that very strong language. I’m not a lawyer, and this is only how the case reads to me as a layman, but I think it’s the strongest argument the other side has. Between that and the piracy, the bigger question is a long way from settled.

This is where it comes back to the hat tip, and the solution I’d like to see for all of these complex, nuanced problems. In a calm world, credit would be a simple courtesy. But we aren’t in a calm world. Copyright sets statutory damages of up to $150,000 per work for willful infringement, and a lot of lawyers see that number and essentially see a bounty, and their whole case turns on escalating litigation and trying to increase a damage award (of which they receive a substantial cut) by trying to sweep in as many works as they possibly can. In other words, they have a huge financial incentive to show that one of the AI labs creating models knew whose work it was using, knew that it was infringing, and did it anyway. Now look at what a hat tip is. The moment an AI lab prints “This answer draws on Andrew Stellman’s book,” it has stated, in writing, “We knew we were using Andrew Stellman’s book,” and a good plaintiff’s attorney could easily turn that around and make it exhibit A. Would a judge see that as willful infringement? I have no idea. But I’m not sure I would bet the entire future of a company like Anthropic or OpenAI.

If credit that would cost a lab almost nothing to give carries a legal risk that dwarfs the cost of crediting no one, then the rational move, the one any lawyer would advise, is to say nothing and admit nothing. The threat of a potential lawsuit could be enough to convince a lab that they can’t safely open the conversation about voluntary attribution at all, because anything it offers in good faith can be turned into ammunition. That’s the worst outcome for everybody, authors included, because the one technology that might be able to finally tell you where an idea came from ends up legally better off staying silent about it.

If you build with these tools, or just lean on them all day the way I do, this is a key reason the answers you get will almost never tell you where they came from, even if the technology to trace them keeps getting better. The people who build these tools could add that little “Here’s who this came from” line tomorrow. What likely stops them is a legal system that makes giving it to you too dangerous to try.

What I actually want

There’s a smaller version of the hat tip that doesn’t run into any of the legal or technical issues I’ve been talking about. Even when a model can’t say which book an answer came from, when it honestly can’t be traced, it can still point you to the authoritative sources on the subject, the ones worth reading to go deeper. That isn’t attribution in the strict sense; nobody has proven those books shaped that answer. But a model trained on a topic was almost certainly trained on the standard works for it, so the correlation is strong. For the reader it does the useful thing anyway by saying where to go next, and it’s something the AI labs can do today.

Which brings me back to that check from Anthropic I may or may not be about to cash. I meant it when I said I’d rather have the credit. What my writing has done for my career matters more to me than what it’s done for my bank account, and I would happily cut that settlement check in half if it meant twice as many people found their way to the work. A hat tip does exactly that, and it’s what I actually want, if it opens up new exposure to my work and new opportunities for authors like me.

The part I keep turning over is that the hat tip is more possible than the people who say “impossible” want to admit. I made a toy version, and researchers at AI labs are pushing these ideas a great deal further than I can. A key part of what stands in the way now is a legal question: whether good faith can survive contact with $150,000 a work. I don’t know how that one comes out. But I’m fairly sure it isn’t the math, and the math was supposed to be the hard part.

What a User Story Actually Costs in a Dark Code Factory [Radar]

Between March and July 2026, I built a production application of 861,601 lines of code. This included 696 user stories and 779 merged pull requests over 105 days, but I can’t tell you what it cost.

The first version of an autonomous SDLC framework driving Claude Code did the work. That generation didn’t record usage, and Claude Code’s default 30-day transcript retention erased the only other record. The bill isn’t approximately known because it’s gone. If measurement isn’t part of the pipeline, it doesn’t exist.

The instrumented factory

The second generation of the factory persists its own bill as it works. Every stage attempt writes its tokens (input, output, cache read, cache write), its cost, its model, and its failure category to a ledger. That first-generation application left no records because its framework kept none; this one cannot run without keeping them.

I should define the unit before pricing anything. In this pipeline, a story is the agile artifact we know. It’s a small requirement decomposed from an epic with acceptance criteria that give the agent its stopping condition. The Definition of Done is how the machine knows it’s finished. We humans batched stories into sprints to manage the delivery. In this pipeline, a story-build is just a story going through its own full delivery cycle. This includes writing tests first, the build, a coverage gate, review by a dedicated reviewer agent, and the merge. It also includes bugfixes and repeat requests when an agent’s reply is malformed. Up to five stories are in flight at once in isolated git worktrees. The dataset for this article covers every story the factory built in one repository between June 25 and July 18, 2026. This includes 17 runs, 193 story-builds, 374 stage attempts, and 336 session logs. The June runs used Claude Opus 4.8 and the July runs used Claude Fable 5, while Claude Haiku 4.5 handled smaller parts.

Usage lives in the ledger and the raw session logs, but they disagree. The logs are the ground truth for a reason I’ll explain later. The factory (claude-code-config) and the repository it built (local-code-bench) are both public. The methodology section includes the CSVs and extraction script so you can check every number. The production application from the opening remains private, so only its ghost appears here.

What a story costs

The factory consumed 595.7 million tokens to ship 77 stories, 7.7 million tokens per delivered story: at list prices for those models, $837.53, or $10.88 per story. The numerator includes every token thrown away, the five stories that ended FAILED, the 22 failed stage attempts, the bugfix and re-ask loops, and the retries; the denominator counts only stories that shipped.

In a previous essay I estimated my factory’s stories at “a few dollars to a few tens of dollars.” The meter’s answer is $3.02 to $43.24 with a median of $9.56, so my estimates were valid. Two findings in the table surprised me. Story points barely predict cost because the medium and large bands are only 8% apart at the median. The most expensive story was $43.24 for a 3-pointer that hit a review retry and a bugfix loop. The wall-clock mean is roughly two and a half times the median because the overnight run hit the subscription plan’s rate-limit window twice and stalled for hours. This was a billing artifact rather than an agent one.

View Median Mean Min Max
Tokens per story (millions) 6.55 7.84 1.99 24.48
Wall-clock per delivered story (minutes) 19.7 48.8 7.6 296.0
Cost per story (USD, API-equivalent) 9.56 11.02 3.02 43.24
Table 1. Per story-build with attributable cost (n = 76, including the 5 that failed; six delivered stories returned no usage envelope and appear only in the headline denominator).

Prices reflect Anthropic’s list rates as of the run dates.

696 stories of the ghost application at this rate is roughly 5.4 billion tokens. We’ll never know.

The factory is a reading machine

Here’s where my estimates were off. In that essay’s worked example, I priced a story as if cache writes were free. They aren’t, and they aren’t even small.

An agent resends the same instructions and repository context on every turn. The API caches that stable context, which makes a cached reread cost a tenth of fresh input, though it charges a premium to write new content into the cache.

95.4% of all tokens are cache reads. The factory rereads about 73 cached tokens for every new token it writes or receives. A dark code factory is mostly a reading machine that occasionally types.

The cost side of Table 2 shows where my estimate broke. Cache writes are only 3.3% of tokens but 31.2% of the bill. Cache traffic overall is 77% of the cost. Fresh input is merely a rounding error at 1.6% of the cost.

Class Share of tokens Share of converted cost (USD)
Cache reads 95.4% 45.9%
Cache writes 3.3% 31.2%
Output 0.9% 21.3%
Fresh input 0.4% 1.6%
Table 2. Token classes across all 374 stage attempts.

This shape is not a quirk of one pipeline. The cache-read share is 96.4% in my interactive framework-development sessions and 91.9% in the ghost’s surviving scraps: three independent samples, two framework generations, two working modes, same shape. It looks like a property of how agentic development consumes compute.

The practical consequence surprised me most: Cost optimization in an agentic pipeline is cache management, not prompt shortening. Context discipline, cache-tier awareness, and orchestrators that don’t stuff their own windows move the bill. Trimming your prompt wording does not.

The honest denominator

There are two ways to read the failure number. The narrow reading, attempts marked FAILED, is 5.0% of tokens. The honest reading, all rework, retries, bugfix and re-ask loops, plus the crashed sessions that streamed tokens and died, is about 13%. Public cost claims rarely say which reading they use.

Only 34 of 76 stories were clean first-pass, but rework stays cheap because retries are small relative to builds. I count the 13% as a quality bill because the gates catch problems.

I found a bug while dissecting the raw data that showed my meter lied. The ledger missed a sixth of real consumption, recording $694.65 against the logs’ $837.53. When a result envelope failed validation, the controller’s re-ask overwrote the original stage row’s usage. This erased the expensive failed session from the books, and crashed sessions never wrote back at all. 57 attempts were affected, which is why the session logs are the ground truth.

The measurement system needed auditing just like the code it measures. So I filed the bug against my own factory and let its fix pipeline handle it. It decomposed the report into three defects and repaired the overwrite and the model recording in one merged PR (issue #480, PR #482, 3,200 tests passing). The factory audited its own meter and fixed most of it, while the work to recover spend from crashed sessions is queued as open work.

Who actually pays

The marginal bill for all of this was zero. I run a $200-per-month Max 20x subscription, which is why every dollar in this piece is labeled API-equivalent.

The subscription’s real currency is quota rather than money. The overnight run stalled twice on the 5-hour rate-limit window, and ten dispatches waited 3.3 to 4.2 hours before auto-resuming. On a flat monthly fee, time is the fence.

One rolling month of measured work across all three codebases totals about $1,088 API-equivalent against the $200 fee, more than five to one, and that’s a floor, because older transcripts are purged. This proves a pricing asymmetry against list rates, not a subsidy: List price isn’t Anthropic’s cost; it includes their margin.

Can a professional, or a small firm, legitimately run on these flat fees? Nothing in the plan terms stops them. There’s no revenue test and no company-size cap. The line Anthropic draws is contractual, not financial. Individual seats run under consumer terms; a Team premium seat at $125 buys business terms and central administration, but roughly half the quota per dollar. Climbing the subscription ladder buys governance, not tokens.

This flat-fee window won’t stay open forever; quotas tighten and tiers reprice. A factory that meters itself will notice the day the trade turns. One that doesn’t will simply feel slower and poorer, without knowing why.

What the meter changes

I discovered while analyzing the data for this article that every number was produced with model routing switched off. Mechanical merges burned premium-model prices on Haiku-grade work, which accounted for 12.3% of all tokens. This means 7.7 million tokens per delivered story is the unoptimized rate. The article you’re reading found the bug, and the fix is already in the factory’s backlog.

A second find came from pointing the meter at myself. Writing the factory’s specifications—its epics and stories, in interactive sessions—consumed about 190 million tokens, which is roughly 25 stories’ worth of consumption (about $160 in converted terms). When implementation is this cheap, the code is no longer the expensive artifact. The difference between the $10.88 story and the unknowable 861,601 lines is that one pipeline wrote its bill down.

Methodology
Dataset, extraction script, and assumptions A1 to A10:
gist.github.com/fxmartin/979da2a47fbbbac6d72d238073e23491.Project-a = local-code-bench (full data in the gist); project-b = claude-code-config (aggregates only; session detail reserved for a companion piece); project-c = a private production repo, withheld.Ground truth is each session’s modelUsage envelope, with the ledger as fallback; 317 of 374 attempts are fully priced; unmeasured attempts are documented, never imputed.
Prices are Anthropic list, fetched 2026-07-19: Opus 4.8 $5/$25 per million tokens in/out, Fable 5 $10/$50, Haiku 4.5 $1/$5; cache reads at 0.1x the input rate; 1-hour cache writes at 2x.
All waste is included in every total; the per-story figure divides total spend by 77 delivered stories ($10.88, or $11.80 excluding six deliveries that returned no usage envelope).
The ledger’s model column was NULL on historical rows; attribution comes from session logs, and model recording is fixed for future runs in PR #482.
Primary figures are in tokens; dollar figures are conversions at the prices listed. All dollars are API-equivalent; actual billing was a flat-fee subscription.

Radar Trends to Watch: September 2026 [Radar]

Coauthored with Claude

Midway through each month, I think “The next Trends is going to be small. Not much is happening.” This is the first time that I’ve been right. Was everyone on vacation in August? Am I becoming jaded? There were many model releases, though few of them seemed significant. Then again, it may be time to get over the one-upmanship by the frontier vendors and spend more time thinking about the myriad small and open-weight models. Every month, the best laptop-scale models (30B and smaller) seem closer to the leading frontier models. And every month, we’re seeing organizations realize that paying premium per-token prices for the latest frontier models gives at best a small advantage over the best open-weight models.

AI models

Capability and model size are decoupling. Several models here run comfortably on a laptop or a single accelerator while claiming performance close to much larger frontier systems. While it can be hard to work with a smaller model without thinking that you’re choosing “second best,” the biggest model isn’t always the right choice. Major releases aside, the most important news from August might be Anthropic’s deployment of watermarks for text. If the watermarking scheme works, it will be possible to tell which parts of an article like this were written by AI.

  • OpenAI has announced that, beginning November 12, 2026, Cursor will no longer have access to their models.
  • A mysterious model named Ox Alpha quickly became the most heavily used model on OpenRouter. Z.ai recently confirmed that Ox Alpha was GLM-5.3-Flash, a 320B open weight model that claims performance similar to Opus 4.8 and that has been deployed running entirely on Chinese chips.
  • IBM’s Granite 4.2 is a small open-weight reasoning model that has been tuned for multistep tasks. It comes in 3B, 8B, and 30B sizes. It’s another model making the argument that small local models can be competitive with frontier models. 
  • The team that developed Ornith-1.5 claims that they have made a major step toward self-improvement. The model supports a self-improvement loop in which it proposes new tasks, generates solutions, and uses reinforcement learning to apply the results to itself.
  • DeepSeek-V4-Flash-Vision adds vision to DeepSeek V4’s capabilities. Images can be mixed with text; the model can describe images, extract text from images, and do other things that we expect from a leading LLM.
  • Anthropic is now embedding watermarks into all of the text that its models generate or edit. The watermarks are apparently based on word choice; the algorithm “changes the source of randomness used to pick words.” We don’t (yet) know of any tools to detect the presence of a watermark, but there are already tools that claim to remove them. It isn’t clear that these tools work.
  • A new benchmark, SWE-Bench ProMax, tests the ability of LLMs to do large-scale refactoring. It’s a multilingual benchmark based on real-world code in seven languages.
  • Qwen3.8-27B is a small open-weight model that claims performance similar to Opus 4.6 max. It runs easily on a reasonably well-equipped laptop.
  • Google has released Gemini 3.7 Flash, claiming improved coding and debugging.
  • Z.ai has released GLM-5.3. It’s very similar to GLM-5.2, differing only in that it has received additional post-training. Z.ai claims that it’s better at code generation and long-running tasks.
  • NVIDIA has released Nemotron 3.5 Lightning, an open-weight mixture-of-experts model with 30B parameters and 3B active parameters. Like many recent models, it’s optimized for long-running agents such as OpenClaw.
  • Cactus Compute has released Needle 2, another small model that’s worth a look. It’s a 45B-parameter model that has been designed for “tool calling, device use, and structured extraction.” Needle requires only 28 MB of RAM, so it will run on many laptops and small devices and microcontrollers.
  • Meta open-sourced Muse Glimmer, a 30B model designed for agentic applications. It can run on consumer hardware. Meta also released Muse Code and Muse Spark 1.2. Muse Code is a model designed for code generation. It implements an agent loop and a local event log that allows exact replays and restarts. Spark is a general-purpose model with near-frontier performance—Meta describes it as “a step towards the frontier.”

Software Development

Features that we associate with agents or harnesses, such as the ability to spawn subagents and delegate tasks to less-expensive models, are continuing to find their way into the models themselves. There’s also a countertrend: Individuals and organizations are building their own agents that are closely integrated into their working environment. Are we headed for walled gardens controlled by the leading providers? Or will a thousand flowers bloom, each reflecting an idiosyncratic way of working with AI? Don’t avoid tools from the major AI labs, like Claude Code and Codex, but don’t lock yourself into thinking that they’re the only option.

  • DeepSeek has open-sourced Harness, its agent harness. What makes Harness unique is that almost everything is a plugin, so it’s extremely flexible. It can be used with many models, and can delegate work to Claude Code and Codex.
  • TrueForge is an open source agent harness that can be used with any model. It includes tools to debug and govern agents in production.
  • Computer History is a new feature of ChatGPT Work and Codex that records how you use your computer. It’s similar to Microsoft’s controversial Windows Recall, but it’s based on key clicks and other actions rather than screenshots. Data is stored locally rather than sent to OpenAI. It’s off by default.
  • Zed’s Delta is a “multiplayer environment for coding with agents and reviewing what they build.” It’s a new take on Git and GitHub, designed specifically for the AI world. The company’s big insight is that the conversation about the code is as important as the code itself, and must be captured along with the source.
  • Companies are now building their own agents (a.k.a. harnesses). While they’re still using AI services from Anthropic, OpenAI, and other providers, many organizations are finding that custom agents are a useful way to incorporate their own workflows into an AI-driven development process.
  • Anthropic has added cross-session messaging to Claude Code. Messaging allows one agent to inform others about actions it has taken that might affect another agent’s work, reducing the need for a programmer to act as a communications medium.
  • Agent Plugins is a standard for extending agents with plugins built from reusable components. It’s supported by OpenAI, Microsoft, Cursor, and AWS, though not by Google or Anthropic.
  • OpenAI now has a hardware product. Codex Micro is a small terminal (certainly the wrong word) for remote AI work; it has 13 keys, a rotary encoder, a touch sensor, a joystick, and some status lights, and it hints at voice control (though I see no mention of a microphone). Its purpose is to allow you to control Codex workflows remotely.
  • “Just because a feature is easy to build doesn’t mean that it is worth shipping”: Good advice on using AI effectively for software development.
  • An update to the Model Context Protocol (MCP) addresses one of the most significant barriers to adoption by making it stateless.
  • Software developers who didn’t grow up with Linux frequently haven’t discovered the art of the command line. Atomic Object recommends four terminal tools: Ghostty, tmux, lazygit, and lazydocker. Try one of them—or all.

Infrastructure and operations

Optimizing AI usage has become its own discipline, sometimes called “tokenomics.” Tokenomics can’t be separated from safety, which has also been much in the news. Disposable containers built for agents, GPU scheduling that treats accelerators as a heterogeneous pool, and infrastructure providers publishing how they actually serve open models at scale all match workloads to hardware without waste or risk. AI performance isn’t just about models; it’s about infrastructure. Understanding how the model is run will prove more important than the model’s specs and benchmarks.

  • Taalas has built a chip that incorporates Llama 3.1 8B. All the weights are on the chip, which can’t be used for any other models. It’s extremely fast. Whether single-model chips make sense when new models are released almost daily is a good question.
  • Docker Sandboxes are isolated disposable containers that are designed for running AI agents safely.
  • Kubernetes’s Device Resource Allocation (DRA) makes it much easier to schedule jobs on heterogeneous clusters of GPUs.
  • Cloudflare has published a description about how it runs the Kimi and GLM models at scale. It’s worth reading.
  • WARP (formerly Waste) is an inference engine with one purpose: run Kimi K3 on a laptop. K3 is a 2.8T parameter model with 104B active parameters, typically requiring a small fleet of GPUs. WARP requires a 64 GB Macbook Pro with a few TB of disk. It’s slow (about 0.5 tokens/second), but it runs.

Security

Security work is inseparable from AI development, not a layer added afterward—but security professionals have been saying that about traditional software for years. Artificial intelligence is spawning new attacks as well as new defenses. While it’s always fascinating to look at new attacks, the most significant shift is in defense: rethinking security in terms of actions and resources rather than user identities, a change we’ve also covered on the Radar blog.

  • Anthropic, OpenAI, Google and many other AI companies have signed an open letter saying that defense against cyberattacks has to become a priority for governments, and that governments and organizations need to act collectively to build defenses. 
  • The Chrome browser has adopted device-bound service credentials (DBSC) to prevent session cookie theft, a critical step in account takeovers. DBSC stores an encryption key in a secure enclave or other trusted storage.
  • There is now a Python library that supports ML-KEM and ML-DSA, NIST-standard key encapsulation and digital signature algorithms for postquantum cryptography.
  • Simon Willison has published a timeline of OpenAI’s inadvertent attack against HuggingFace. His timeline is based on a postmortem that OpenAI presented at Black Hat. OpenAI has published a full incident report.
  • The ChainDrop credential stealing malware has compromised over 1,300 packages on npm, the Node package manager. The malware is self-propagating, and compromised packages appear to have legitimate provenance.
  • OpenAI has open-sourced Codex Security, a command-line tool and API that uses ChatGPT to analyze code for vulnerabilities. Their documentation says that the CLI and API are both in “limited beta,” possibly because of the model used to do the analysis.
  • Context Collapse is a three-part series that discusses context poisoning attacks against Copilot, culminating with self-propagating attacks against Word. Microsoft collaborated on the analysis and mitigations.
  • Google has introduced Beyond Zero, a new security model that takes zero trust a step further. Beyond Zero makes decisions on the basis of specific actions and resources, not just users or applications. Decisions are governed by both static policies and dynamic controls that can respond to changes in the environment.

People and Organizations

How do people use AI? Does AI use lead to greater productivity? We know surprisingly little about either question. We’re still learning how to use AI effectively; the best metric isn’t a simple measure of productivity but whether you can do things you couldn’t do before.

  • The AI Observatory collects data about how people use AI. What we know about the ways people use AI is surprisingly limited. We know that usage patterns vary from model to model, but model providers only publish the data they want to see; we still don’t understand the big picture.
  • How do you measure AI productivity? “Why AI Productivity Is a Faulty Metric” has some good ideas. Develop metrics around code quality and whether AI-generated code survives review, rather than counting lines of code.

Web

There’s now a specialized version of ChatGPT for teens; a site that serves different content to scrapers and humans; and an AI-generated animation of the start of The Lord of the Rings. The web is proving that it can adapt to anything that’s thrown at it. It’s where we learn and play, and AI isn’t changing that.

  • OpenAI has launched ChatGPT for Teens, a specialized mode for users between 13 and 17 years old. This new product stresses learning and studying rather than using AI to get answers, has stronger content safeguards, and tries not to become a surrogate for human interaction.
  • A theremin in the browser is something you don’t see every day! Use your mouse or your webcam to control it.
  • TIME magazine has started giving AI scrapers a minimal Markdown version of articles with additional advertisements. The site’s behavior depends on the User-Agent HTTP header. Some user agents are denied access, while humans are given HTML with graphics and layout.
  • Tired of pelicans on bicycles? Andrej Karpathy had Claude Opus animate the first paragraph of The Lord of the Rings with Three.js. The result isn’t great, but it’s certainly fun and points to some areas where the best current models aren’t yet strong enough.

Biology

  • The National University of Singapore’s Life Sciences Institute now has a server rack where the computational power comes from 16 million lab-grown human neurons. Life support is a problem, but power consumption is a small fraction of the power required by GPUs.
  • Claude has successfully run a complete protein design workflow, generating new designs for proteins that have been synthesized and tested in labs.
  • There could be a fly on your desktop. This one is driven by a simulation of over 23,000 neurons from a fly’s connectome. It behaves like the real thing (macOS only).

Zero to Agent in 30 Minutes: Building a Financial News Agent with Jayeeta Putatunda [Radar]

In this episode of Zero to Agent in 30 Minutes, Jayeeta Putatunda, forward deployed AI engineering lead at Turing, builds a multi-agent workflow that turns a daily flood of financial headlines into a structured analyst briefing. Financial analysts already have deep internal research, coverage assignments, and market views, but keeping that context current as new information arrives every day and surfacing which of it actually deserves an analyst’s attention is a harder problem.

How to build a source-backed briefing agent, step by step

  1. Define the scope. Start by setting the analyst’s focus area, research questions, and time window, whether that’s the last one day, seven days, or 30 days. Narrowing the scope up front, including a list of preferred sources, keeps the agent’s web searches directional instead of generic.
  2. Plan the coverage. A coverage planner agent breaks the research question into discrete sections, such as market backdrop or company catalysts, so the search that follows can run in parallel rather than one long sequential query.
  3. Search and gather. A news researcher agent runs multiple queries against the preferred sources first, then falls back to a general search if the preferred sources don’t return enough results.
  4. Validate the sources. A validation agent checks each link for a working, clickable URL and a correct publication date, removes duplicate stories covering the same news, and filters out paywalled pages that won’t return usable content.
  5. Generate the briefing. A briefing writer agent assembles the validated developments into a set structure, including an executive summary, key bullet points, and a section-by-section breakdown of what each development means for the analyst and what to watch next.
  6. Capture feedback into memory. A feedback agent logs corrections such as formatting or terminology preferences and saves them to a memory database, so the next briefing run applies those preferences automatically instead of requiring the analyst to re-prompt.

Jayeeta built the entire stack on open source models so newcomers can run it without an API key, and she recommends starting with a smaller model before scaling up. The takeaway extends well beyond finance. Building single-purpose agents rather than one large agent that handles every task means a failure at one stage doesn’t force a restart of the whole pipeline, and each agent’s output stays easier to trace and debug.

The full code base, including the sample data and the UI shown in the demo, is available in Jayeeta’s GitHub repo, so readers can clone it and run the briefing agent on their own systems.

Coming this week

This week, Maxim Salnikov joins Zero to Agent in 30 Minutes to build a supply chain for agent context. He’ll show how to source approved packages from a trusted registry, pin and hash-verify them on any harness, and enforce org policy with a CI gate that can’t be bypassed.

Architectural Guardrails for AI-Generated Code [Radar]

Consider a composite of a failure pattern that’s becoming increasingly common on teams that have scaled AI-assisted development past a handful of enthusiasts.

A staff engineer named Priya opens a pull request. The PR is 340 lines and adds an endpoint that writes to the customer table directly, bypassing the internal customer service API. The code is clean. The tests pass. The AI coding agent that wrote it has been the team’s most productive contributor for six months. The reviewer, three months into the team, approves. The PR ships that afternoon.

Two weeks later, during an integration debug, someone notices that customer records written by that endpoint are missing audit-log entries. The audit hooks live in the customer service API. The team banned direct database access two years ago for exactly this reason and wrote an architectural decision record (a versioned markdown document, one of dozens the team has accumulated, that captured what was decided, why, and what was superseded) to memorialize the rule. The engineer who wrote the ADR has since left. Nobody on the current team remembered the decision. The document was sitting in a directory the current workflow never touches.

The endpoint gets rewritten. Audit gaps get backfilled. The team spends most of a sprint on cleanup. Nobody calls this a failure of AI-assisted development. The AI wrote functional code. It just wrote code that violated a decision the team had already made, in a document the AI had no view into.

This is a specific failure mode. It is not a hallucination since the output was grounded, syntactically valid, and idiomatic. It’s not a model-quality problem since a better model on that same prompt wouldn’t necessarily help if the decision remained absent from its context. It’s a memory problem. Not the model-internal sense of context window, but the organizational sense. The ADR was available in the repository. It was never surfaced to the agent, and the reviewer had not read it.

This piece is about naming what would need to exist for that PR to have been caught, or better, never written in the first place.

The rework signal

Priya’s PR illustrates one source of a broader rework problem. Faros AI, an engineering analytics platform, published a report in 2026 based on telemetry from more than 22,000 developers across 4,000+ teams. AI-code acceptance rates had risen from 20% to 60% between periods of low and high AI adoption, while code churn (i.e., lines deleted within days of being added) had increased 861% over the same interval.

Faros is careful in how it frames the churn number. The increase may include not only rework but productive refactoring, previously unaffordable cleanup, or faster iterative improvement. But the number still exposes a gap between code entering the repository and code that survives there. A gap that has widened, at scale, alongside AI adoption. Anecdotally, engineers at teams running these tools describe returning to code they had already approved to fix issues that were not obvious at review time. Architectural drift, i.e., code that individually looks fine but collectively pulls the codebase away from where the team agreed it should go, is one plausible contributor.

I’ll call the discipline of preventing this failure mode architectural drift prevention: keeping generated code aligned with the architectural decisions a team has already made.

The pattern-matching explanation for that gap has been that the AI isn’t good enough at writing code yet, and a better model will close it. Watch enough review cycles at a team running AI-assisted development for a year, though, and a different pattern emerges. The generated code isn’t obviously bad. It compiles. It passes tests. What it doesn’t do is respect decisions the team has recorded but the AI has never seen.

Why current tools sit at the wrong layer

Teams commonly reach for several existing mechanisms to close this gap. Most of them are the wrong shape for the problem.

The closest attempts are files like Cursor Rules and CLAUDE.md, i.e., free-text markdown documents dropped into the project root so agents read them as standing instructions. These are the right instinct at the wrong resolution. Free text has no precedence rules, no versioning, no lifecycle. When one rule contradicts another, nothing arbitrates. When a rule is violated, nothing catches it. These are documents in the shape of configuration.

Linters and code formatters operate a layer below. They enforce that a function has a return type annotation or that a variable name follows a convention. They can’t enforce that customer-data writes must go through the customer service API, because that’s not a syntactic property. It’s a semantic decision recorded in a document the linter has no reason to read.

Dependency scanners, SCA tools, and lockfile audits close a related gap; they catch known vulnerable libraries, license violations, and outdated versions. They would’ve flagged nothing about Priya’s PR. Every dependency in it was current, had no known vulnerabilities, and was approved. The violation was a routing choice inside the team’s own architecture, not a library problem.

LLM-assisted code review is the fashionable answer. A second AI reads the pull request and comments on it. This catches surface issues like a swallowed exception, an off-by-one bug. It doesn’t catch drift, however, because the second AI has the same problem as the first: no durable access to the team’s recorded decisions. Two probabilistic passes over the same blind spot are not one deterministic pass with sight.

Human review is the last line, and it works when the reviewer knows the history and has enough time to inspect the change. Agentic development changes both conditions. Agents can produce multiple implementations, pull requests, and revisions in the time it takes a human reviewer to assess one. Code output scales; review attention does not. Asking humans to compensate by reviewing more and harder simply moves the constraint downstream.

None of these tools are bad. They’re just the wrong layer for the drift problem.

What the missing layer would need to do

The missing layer connects recorded engineering decisions to the tools that generate, review, and merge code. Its job is to make the team’s accumulated architectural decisions machine-readable, injectable, and enforceable. I’ll call this layer engineering governance, borrowing the term from adjacent categories like data governance and security governance, where it means the same thing: A structured way for an organization to make explicit and enforceable the rules it already implicitly follows.

At the shape level, the layer needs to do four things.

  • It needs to hold decisions in a structured corpus with precedence and lifecycle metadata so that a tool knows which ADR wins when two conflict, and which decisions are still active.
  • It needs to retrieve from that corpus reliably, so the same code produces the same set of relevant decisions each time.
  • It needs to inject those decisions into the AI’s context before the agent writes code, so the output accounts for them rather than needing to be caught afterwards.
  • It needs to enforce them in continuous integration, blocking or flagging code that violates them, with the verdict traceable to a specific ADR, a specific term that matched, a specific rule.

The critical property that ties those four together is a discipline about where probabilistic reasoning is allowed. Probabilistic systems may retrieve or recommend. They shouldn’t independently determine an enforcement verdict. Every block or warning has to reconstruct from artifacts on disk. That’s the code, the ADR, the retrieval log, the rule text. Then, when a developer asks “why did this fail?” or an auditor asks “on what basis?” the answer isn’t “the AI said so.” That’s what makes the layer defensible in the situations where defensibility matters: regulated environments, compliance review, incident retrospectives, and the everyday conversation where an engineer has to justify a blocked merge to the person whose code was blocked.

AI may help surface relevant decisions, but it shouldn’t be the final authority. The enforcement path must remain deterministic: every verdict should resolve to explicit rules, observable evidence in the code, and a result that another person can reproduce.

Defining the boundaries

Naming a category clearly requires naming what falls outside it. The engineering governance layer, done right, is not any of the following:

  • An agent. Nothing autonomous. Nothing iteratively deciding what to do next. The layer runs when called, produces a verdict, and stops.
  • Memory in the retrieval-augmented-generation sense. Retrieval methods can vary and may be probabilistic; the enforcement verdict cannot. The corpus of decisions is the source of truth.
  • Code reviewed by AI. Reviewing generated code with a second model doesn’t address the underlying problem, which is that the first model had no access to the team’s decisions.
  • Vendor-locked. Production teams increasingly run Cursor, Claude Code, GitHub Copilot, and Codex in parallel, sometimes on the same repository. They may also use open-weight or self-hosted models for sensitive codebases and internal workflows. Engineering governance must remain independent of both the coding tool and the underlying model, so the same architectural decisions and deterministic enforcement apply across them all.

The emerging engineering stack

The AI coding stack is assembling itself in the open, without anyone architecting it. Each of the major coding assistants is specializing on a different piece of the loop; editing, autonomous execution, review, planning. The layer this stack doesn’t yet have is engineering governance.

The need isn’t limited to regulated industries. Any team that values reliable engineering, long-term product quality, and the trust of its customers needs to know that generated code respects the decisions the system depends on. In higher-risk environments, that requirement becomes formal and auditable. Elsewhere, it’s simply part of building software responsibly. In both cases, the enforcement path should be deterministic and traceable, with the rules, evidence, and verdict open to inspection rather than hidden inside another model or a proprietary black box.

For engineering leaders reading this today

Priya’s PR is a pattern, not an incident. Three things worth doing this quarter, regardless of tooling choices.

  • Audit your architectural decision records. Are they current? Do they explicitly name the decisions they replace? If your team doesn’t write ADRs, this is the moment to start. The tooling that will exist in twelve months assumes structured architectural decisions as input.
  • Choose the enforcement posture deliberately. The system can either warn the developer and let them continue or block the change until the issue is resolved. Both approaches can work, but the team should agree on which applies instead of leaving the decision to each developer or each pull request.
  • Don’t assume a more powerful model will solve this problem. Better models can improve the code they generate, but they still can’t follow architectural decisions they’ve not been given. Preventing architectural drift requires changing the surrounding system, not simply waiting for the next model.

The productivity gains from AI-assisted development are real and worth having. So is the architectural coherence teams spent years building. Engineering governance is the layer that lets you keep both.

What You Measure [The Daily WTF]

Rachel joined a new team which was proudly "metrics driven". When she first met with her boss, Zane, he explained his thinking.

"We need to be data-driven to make good decisions, right? We're a manufacturing company. We make widgets. At the end of the day, we need to make the most widgets for the lowest cost of goods sold. So we track that, and that feeds into every decision."

The team oversaw an automated production line, which meant the software was a mix of robotics, embedded firmware, high-level web based monitoring tools, and thickets of dreaded PLC code. And because you can't build an entire factory for test purposes, they only way they could test real-world scales with real-world data was to roll changes out to production. They could simulate, they could run tests on subsets of the system, but a change in the production line software couldn't truly be validated until it rolled out into the real world.

Rachel's first task on the new team involved making some changes to their metrics dashboard. It was viewed as a good way to get her feet wet with the new team. As it turned out, the metrics dashboard was a Google Sheet, with a complex series of formulas that involved multi-level INDEX functions- essentially querying the spreadsheets like they were a database. Why not use an actual database? Oh, they did — six actually — but the company obeyed Remy's Law of Requirements Gathering: "no matter what the requirements the users ask for, what they really wanted was Excel". The database data was pulled into the spreadsheet for reporting.

Now, a complicated sheet pulling in data from not one, but six different databases, they must have a pretty complex model to explain how changes to their software would impact productivity. And since they needed to model the software to make predictions about how it'd behave in production, that model must be extremely useful.

Of course it wasn't. The only metrics they tracked were output metrics, variations on "widgets produced per unit time". There were some performance metrics, so you could maybe potentially identify "oh, our overall throughput dropped because unit 5 became a bottleneck and started taking 1.5 extra seconds per widget", but nothing that actually helped you understand how the complex system made decisions. Or even why unit 5 was taking longer.

For example, there was an automated quality control scanner. It examined widgets as they came off the line, and rejected defective ones based on a computer vision algorithm. Did that subsystem record why it rejected a widget? No, it did not. The CV model was able to tag widgets with a defect category based on what it saw, but that information didn't get recorded anywhere. In fact, it didn't even record how many widgets got rejected. The only way to know was to have an operator on the assembly line count widgets in the bin manually. Since that ate up a bunch of an operator's time, it never happened unless the developers begged for it. And since the operator still couldn't answer the question "why was this widget rejected", it wasn't all that useful anyway.

Every change to the software was scored against the overall output metrics. This meant that when Rachel was ready to push out her first software change, something that would record how many widgets were rejected and why, whether or not it could be deployed was dependent on seeing the change improve, or at least not regress, the widgets-over-time scores. But the widgets-over-time were a noisy metric; it varied based on which operators were working any given shift, or based on supply chain constraints. Or sometimes, based on when one of the machines was last calibrated- theoretically something that happened on a set schedule, but really was up to the operators. This meant the first three times Rachel rolled her code out for a test run, the metrics regressed. Nothing she changed should have impacted the metrics, but the metrics regressed due to environmental issues.

This meant making a simple change could take weeks, because you could only do final validation on the real system, which means you had to mark off a block of time for a test run, you could only run a handful of tests a day, and if metrics regressed you had to account for that before you could release the software for actual production use.

Over the first few months, Rachel added instrumentation to the code. Anything along the way to generating an output widget, she recorded. The hope was that once they had enough data, they could build a useful model of the system. Unfortunately, Zane had other ideas.

"So, you haven't improved our metrics," Zane said. "Which, I remind you, we're a metrics driven organization. Every change needs to improve our metrics."

"Sure, but I'm gathering more data so we have a better idea of what makes our metrics tick. We don't know why our system does some of the things it does, because we don't record any logging about the decisions it makes."

"Right, but we already gather the key metrics."

"But you don't gather the data that tells you why those metrics are what they are!"

"Sure," Zane said. "But those aren't our key metrics."

That, unfortunately for Rachel, was where things landed. Understanding their complex system was a low priority. Pushing top-level metrics without understanding what fed into them, that was the priority. That didn't mean Rachel was powerless: any time she made a change that she thought might help the top level metrics, she also made sure to add instrumentation that explained how that change behaved. It was the compromise that kept Zane happy: she released features that impacted the top-level metrics, but she also made the system more observable.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

Representative Line: So Much Room [The Daily WTF]

Today's representative comment ran out of room.

int maxLen = getColumnSize(session, "audit", "text_value1") - 16; // Leave some room for

No, it isn't continued on the next line and just got trimmed out, except perhaps by a careless merge. This is the entire comment.

Clearly, written by David Chase, the creator of "The Sopranos".

There are so many things we might be leaving room for. We could leave some room for dessert. Leave some room for activities. Leave some room for the holy spirit. Leave some room for improvisation.

[Advertisement] ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.

Tales from the World Cup [The Daily WTF]

All I can say in response to our anonymous submitter's story is, ALMOST?!

With the World Cup being hosted in North America this year, I remembered this story that happened back in 2014. At the time I was working in Brazil, for a company that builds software systems for public services. And, with the World Cup being hosted there, in came the opportunity for local agencies to invest in modernization, with pretty much a blank check to get new services, so long as it was deployed before the end of the World Cup. And so the sales people did what they did best, and went around trying to upsell whoever would be willing to buy — no matter our actual capacity for developing the things.

So it was that I was pulled into this new fancy digital system for the police force of a state capital. However, we had only about 4 engineers available, and what they sold was a project estimated for a team of 20, to be delivered in 3 months, with no room for delay. And it wasn't just our core C&D product, but this massive thing with customized public-facing websites, live tracking of the position of different police cars delivered to a tablet in each car, automated reporting, etc.

Germany and Argentina face off in the final of the World Cup 2014 -2014-07-13 (5)

First thing: We received a pile of 24 resumes, and were told to choose 16 of those. Maybe 3 were acceptable, but we had to waste 1 month hiring and onboarding 13 other people who were worse than useless. Classic man-month problem. We eventually had to tell management that nothing would be delivered this way, so they did the very best next thing: fly us to this other city, so we could work embedded there, in full crunch mode for the delivery. We pretty much worked 12+ hours a day, 7 days a week, for those next 2 weeks.

Another situation: they wanted this system where people could take a photo of an incident in progress, and submit via this app + website, to be verified by an operator in real-time. We nicknamed it the "dick-pic encyclopedia." Even worse, we only had the budget to run a single server, so this thing receiving public traffic would live in the same system that was tracking police car locations. Luckily they were convinced it was a bad idea so it was only ever online for a short period of time.

Next, was the police car tracking. This was done by a tablet installed in each car, which would be sending and receiving location information. But, 1 week before our deadline, we were hitting a serious bug: everything was working when we ran the tests ourselves, but the cops would report very weird bugs when testing it in the field. So we asked to do some field debugging, and I went on a ride-along. Things were working pretty much fine everywhere, so I asked to be taken to where he remembered seeing the tablets fail—to which the policeman just decides to drive off straight into one of the favelas around the city. I guess I can cross out "doing debugging in a police car passenger seat in a notoriously dangerous neighborhood" off my bucket list. Root cause: turns out cellphone connections would be pretty spotty in those areas, which we weren't handling properly.

Either way, we delivered something on time that was severely below spec, and very much over-budget. Company tried to squirm out of paying overtime (was told that we would gain "prestige" by doing those extra hours), but I put my foot down and left that job shortly after. Last I heard they actually got sued for this and a bunch of similar projects, and almost went under.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

[$] LWN.net Weekly Edition for September 3, 2026 [LWN.net]

Inside this week's LWN.net Weekly Edition:

  • Front: Python JIT; rnull block driver; steal time; GNOME governance; 7.3 merge window; LUKS.
  • Briefs: Kernel infrastructure; Debian AI; Dolphin 26.08; Firefox 155; Incus 7.4; OpenShot 4.0; Quotes; ...
  • Announcements: Newsletters, conferences, security updates, patches, and more.

[$] Securely suspending LUKS-encrypted disks [LWN.net]

When a laptop is asleep, its memory is not unreadable. The right tooling can attach to the computer's memory bus and read out its contents, and cold-boot attacks can theoretically read values from memory for a short time after the computer loses power. That is really an unavoidable fact about the hardware, but some users would still like to ensure that, even if this happens, their long-term encryption keys, such as the key for full-disk encryption, remain unreadable. In June 2026, Ingo Blechschmidt discovered that Linux kernel versions after 6.9 (released in May 2024) were not erasing disk-encryption keys when a laptop was put to sleep, even when configured to do so. He quickly identified a potential fix, which has been merged, but it was not a comprehensive solution.

[$] Governing GNOMEs: how the project's technical decision-making is evolving [LWN.net]

Emmanuele Bassi kicked off a project to improve GNOME's technical governance with a presentation about his ideas (video) at GUADEC 2025. His nudging has led the project to, slowly, work on creating more formal structures for technical governance. It is adopting a teams structure and looking toward creating a steering committee, as well as bootstrapping a Request for Comments (RFC) process. If adopted, GNOME would require RFCs for design, user experience, architectural, and other changes that carry a major impact on the project.

Incus 7.4 released [LWN.net]

Version 7.4 of the Incus container and virtual-machine management system has been released. Notable changes in this release include UEFI Secure Boot key management, "near-live" migration of containers between Incus instances, as well as burst I/O limits for disk and network devices.

Eight stable kernels for Wednesday [LWN.net]

Greg Kroah-Hartman has announced the 7.2.3, 7.1.13, 6.18.49, 6.12.108, 6.6.156, 6.1.187, 5.15.220, and 5.10.269 stable kernels. Each contains a number of important fixes throughout the tree. Users are advised to upgrade.

Note that 7.1.13 is the last of the 7.1 updates

Security updates for Wednesday [LWN.net]

Security updates have been issued by AlmaLinux (dbus-broker, freerdp, gegl, gegl04, gimp, gimp:2.8, glib2, grafana, gzip, iperf3, libssh, nodejs22, nodejs24, nodejs:22, nodejs:24, php:7.4, php:8.2, pipewire, ruby:3.3, ruby:4.0, tar, wget, and xmlrpc-c), Debian (cyrus-imapd, keystone, and lemonldap-ng), Fedora (bubblewrap, cockpit, emacs, gdk-pixbuf2, openssl, openvkl, python-linkify-it-py, python-llm, and rkcommon), Gentoo (Chromium, Google Chrome, Microsoft Edge, Opera, Vivaldi), Oracle (glib2, gzip, mingw-sqlite, nodejs22, xorg-x11-server, and xorg-x11-server-Xwayland), Red Hat (go-toolset:rhel8, golang, and grafana), Slackware (pcre2), SUSE (apache2-mod_auth_openidc, busybox, cups-filters, java-17-openj9, java-1_8_0-openj9, libapr-util1, libgcrypt, python-sqlparse, python3-sqlparse, python313-uv, terraform-provider-aws, terraform-provider-azurerm, terraform-provider-external, terraform-provider-google, terraform-provider-helm, terraform-provider-kubernetes, terraform-provid, ucode-intel, wicked, and yast2-auth-client), and Ubuntu (libevent, libgcrypt20, ncurses, opencryptoki, pam, pyasn1, rust-sudo-rs, and ubuntu-advantage-tools).

A note on subscription prices from LWN [LWN.net]

The online publication industry, as a whole, is struggling, with challenges coming from multiple directions. Thanks to the support of all of you, our readers, LWN would appear to be doing better than most. But the world has changed around us and, in particular, prices have changed considerably. By now, you probably know where this is going: subscription prices at LWN will be increasing as of September 15.

OpenShot 4.0 released [LWN.net]

Version 4.0 of the OpenShot video editor has been released.

OpenShot 4.0 has arrived, bringing some of the biggest creative workflow upgrades in our history. You can now record your screen, webcam, microphone, and system audio directly into a project. You can correct and grade footage with color wheels, curves, LUTs, and professional video scopes. You can also isolate subjects with locally run machine learning models and create everything from animated audio visualizations to cinematic film looks.

See the release notes for a full list of changes.

[$] A pause for the Python JIT [LWN.net]

In 2024 the Python 3.13 release added an experimental just-in-time (JIT) compiler to optimize the way that CPython executes Python code. Since then, work has proceeded on the JIT, albeit perhaps less formally than some might like. In June, Python's steering council (SC) put out an announcement that no new development on the JIT land (with the exception of bug and security fixes) in Python's main branch, until it accepts a Python Enhancement Proposal (PEP) that would make the case for the JIT as a supported part of CPython. That has led to the creation of PEP 836 ("JIT Go Brrr: The Path to a Supported JIT Compiler for CPython"), which is currently under discussion. As it stands, it seems likely that work on JIT will continue, but when that will happen is less certain.

Firefox 155 released [LWN.net]

Version 155 of the Firefox web browser has been released. Notable changes include a count in the address bar of how many ad trackers Firefox has blocked, container reordering, and ensuring that mailto: links are only opened by explicit user actions. There is also a change of the domain used for "captive portals" (such as the ones used to sign into hotel WiFI): Firefox now uses "firefox-portal-detection.com" instead of "detectportal.firefox.com", which may require a change in network allow lists.

The release also includes a number of changes that may impact web developers, as well as a number of bug fixes and security fixes.

Netdev 0x1A videos and slides are now live [LWN.net]

The Netdev 0x1A conference was held in Rome, Italy from July 13 through July 16. Conference organizer Jami Hadi Salim has let us know that the videos and slides for all sessions are now available. Topics include Linux QUIC, shared memory socket transport, eBPF-based DDoS protection, and more.

Security updates for Monday [LWN.net]

Security updates have been issued by Debian (kernel, libarchive, libdbi-perl, libnet-dns-perl, librabbitmq, roundcube, starlette, and xrdp), Fedora (bluez, postgresql16-anonymizer, pyOpenSSL, python-cryptography, python-pynitrokey, and rust-h2), Gentoo (Chromium, Google Chrome, Microsoft Edge, Opera, Freenet, and Tor), Mageia (golang and python-nltk), Red Hat (nodejs22, nodejs24, nodejs:22, and nodejs:24), SUSE (7zip, apptainer, broot, cadvisor, coredns, coturn, distribution-registry, gh, git-lfs, grafana, gzip, java-25-openjdk, libopenssl-3-devel, libsoup-3_0-0, mozjs102, OpenRGB, openssl-3, openvpn, podman, pyenv, python, python-PyPDF2, python310, python312, python313-Authlib, python36, rekor, rsync, rsyslog, tor, trivy, v2ray-core, vim, wget, and wicked), and Ubuntu (bzip2 and openjdk-26).

Security updates for Tuesday [LWN.net]

Security updates have been issued by AlmaLinux (gzip, iperf3, libxml2, mingw-sqlite, mysql:8.4, nginx:1.26, nodejs:24, php, and tar), Debian (expat and libdbd-csv-perl), Fedora (apache-ivy, bind, bluez, bubblewrap, curl, emacs, epiphany, expat, freerdp, gdk-pixbuf2, GitPython, hcloud, kbd, kernel, lego, libopenmpt, mqttcli, nebula, opkssh, python-mkdocs-git-revision-date-localized-plugin, python-pip, rpki-client, rubygem-mechanize, srt, and subfinder), Mageia (c-ares, clamav, expat, mingq-expat, firefox, nspr, nss, flatpak, hplip, jbig2dec, nodejs, openssl, perl-Catalyst-Plugin-Authentication, perl-Date-Manip, perl-HTML-FormHandler, perl-HTTP-Date, perl-Mojolicious, perl-Plack, postgresql15, postgresql18, python-hpack, redis, roundcubemail, thunderbird, varnish, and vim), Oracle (golang and libxml2), Red Hat (bind, bind9.18, dracut, glib2, golang, gzip, kernel, kernel-rt, openssl, osbuild-composer, tar, and unbound), SUSE (7zip, busybox, bzip2, c-ares, chromedriver, chromium, cpio, curl, dhcpcd, dovecot24, dracut, firefox, go1.25, go1.26, go1.26-openssl, google-cloud-sap-agent, gstreamer-plugins-bad, gzip, helm, ImageMagick, istioctl, jfrog-cli, jupyter-jupyterlab, libarchive, libcares2, libheif, liboqs, librest, openssl-1_1, openssl-3, owasp-modsecurity-crs, pcp, php-composer2, postgresql14, postgresql15, postgresql17, postgresql18, python-cryptography, python-httplib2, python-pip, python313, python313-djangorestframework, python313-starlette, qemu, qt6-svg, quagga, rav1e, rmt-server, rsync, rsyslog, snphost, sssd, thunderbird, unbound, vim, wget, xmlrpc-c, yast2-auth-client, and yast2-samba-client), and Ubuntu (attr, bind9, coreutils, cpio, diffutils, freerdp3, libssh, mysql-8.0, mysql-8.4, openjdk-17-crac, openjdk-21-crac, openjdk-25-crac, openssl, p11-kit, perl, pillow, udisks2, util-linux, webkit2gtk, zfs-linux, and zlib).

Kernel prepatch 7.3-rc1 [LWN.net]

Linus has released 7.3-rc1 and closed the merge window for this release. "Nothing really stands out - except for the fact that it's big. It's not the biggest rc1 we've ever had, but it's certainly up there, at least in number of commits." He pulled 15,267 commits during this merge window, making it the second busiest ever; only 6.7 has exceeded it.

Dirk Eddelbuettel: RcppClassicExamples 0.1.5 on CRAN: Very Minor Maintenance [Planet Debian]

Another minor maintenance release version 0.1.5 of package RcppClassicExamples arrived earlier today on CRAN, and has been built for r2u. This package illustrates usage of the very old and otherwise deprecated initial Rcpp API which no new projects should use as the normal and current Rcpp API is so much better.

This release follows one from six months ago, and is even smaller. We just update a few Rd files to adhere to a stricter standing of checking by R.

No new code or features. Full details below. And as a reminder, don’t use the old RcppClassic – use Rcpp instead.

Changes in version 0.1.5 (2026-09-02)

  • Add usage and value sections to some help pages

Thanks to CRANberries, you can also look at a diff to the previous release.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can now sponsor me at GitHub.

Birger Schacht: Status update, July + August 2026 [Planet Debian]

Debian Related Work

  • Uploaded cage 0.3.1-1 to unstable
  • Uploaded swaylock 1.8.6-1 to unstable
  • Uploaded scdoc 1.11.5-1 to unstable
  • Uploaded xdg-desktop-portal-wlr 0.8.4-1 to unstable
  • Uploaded swayimg 5.5-1 to unstable
  • Uploaded fyi 1.0.4-2 to unstable
  • Uploaded labwc 0.20.2-1 to unstable
  • Uploaded yambar 1.11.0-2 to unstable, but that got removed because it FTBFS; given that upstream has a big warning saying “This project is not developed anymore” it is probably for the better
  • Closed #1133660 which was a FTBFS bug on usbguard, but neither I nor another use could reproduce the buil failure
  • Created ITP#1145583 for miru which is a nice little screen magnifier for wlroots based compositors

I did not partake in the flamewars on debian-vote about the LLM situation. I am not sure how anyone can find this style of “discussion” productive. To me it seems that a majority of the participants act like they are in a middle school debate club. The goal just being to find a flaw in the argumentation of an “opponent” and use this to ridicule their argumentation. Basically what politicians do.

xkcd 386

The good thing is, that most Debian members did not stoop on that level. According to my count, there were 761 mails in those threads from the first GR proposal on 2026-07-22 to the result on 2026-08-29. Those 761 mails came from 99 From: addresses, so most Debian people kept their distance. Given that according to nm.debian.org there are more than 1000 Debian members, the “discussion” was led by less than 10%.

mails-per-day

The distribution of who wrote how many mails is also interesting. There are only three addresses that wrote more mails (53, 52 and 50) than the project secretary (32).

mails-per-person

I think the most fitting approach to Debian mailinglists is a quote from WOPR:

A STRANGE GAME. THE ONLY WINNING MOVE IS NOT TO PLAY.

DH Related Work

I released version 0.66.0 and 0.67.0 of the APIS framework as well as a couple of bugfix releases for the 0.67.x version. In 0.67.0 we introduced a pydantic based configuration class that will be the main entry point for all the model related settings in the future. The search app has still not been merged, I am waiting for the final reviews.

Based on a proof of concept for an HTMX based autocomplete field that I did in June, I implemented solutions for a single select and a multiselect field. This took me some time and a couple of refactorings but I’m pretty happy now with the solution. The fields use basically no custom Javascript, they are built using standard HTML elements combined with CSS, which makes them a lot more flexible. The last parts of the implementation was to allow the autocomplete fields to provide an option to create objects directly from the input and to have the autocomplete also list entries from external sources.

Russ Allbery: Review: Too Like the Lightning [Planet Debian]

Review: Too Like the Lightning, by Ada Palmer

Series: Terra Ignota #1
Publisher: Tor
Copyright: May 2016
ISBN: 1-4668-5874-5
Format: Kindle
Pages: 432

Too Like the Lightning is a science fantasy (?) novel and the first of a four-book series. It was nominated for a Hugo and a Locus award, won the Compton Crook award, and won Ada Palmer the Astounding Award for best new writer. It was Palmer's first novel.

Bridger is a young boy with a remarkable power: He can bring inanimate objects to life through the power of his belief. He is being hidden by the Saneer-Weeksbooth bash', a family (?) business (?) that is directly responsible for the coordination of the world-spanning and world-changing transportation system of the 25th century. Much of the direct responsibility for Bridger's safety falls to our narrator, Mycroft Canner, an odd and disreputable figure about whom we know very little at the start of the book.

As this book opens, two things are happening simultaneously. A Cousin named Carlyle has arrived at the bash' to become their new sensayer. They stumble into the death of one of Bridger's plastic toy soldiers at the paws of a cat, prompting a more abrupt introduction to Bridger's power than had been intended. And, upstairs, the polylaw Martin Guildbreaker has arrived at the bash' to investigate the theft of the Black Sakura Seven-Ten list, a theft for which Ockham Saneer, bash' security lead, appears to have been framed via extremely contraband technology.

Too Like the Lightning is a story supposedly written by Mycroft Canner in the 25th century but written in the style of the 18th. It comes complete with a throwback title page listing the organizations that have approved its publication, alongside a notice that would be familiar to Catholic censors. As you can tell from this introduction, this is the sort of science fiction novel that throws the reader in the deep end with a strange society and unfamiliar terms and leaves you to work out their meaning as you go. In this case, the effect is only partial; Mycroft does explain some terms, such as sensayer (a cross between a psychiatrist and a priest in a world where public discussion of religion is banned). However, he is writing for his future rather than our time, so the choices of what he explains and what he does not can be as odd and puzzling as the rest of the world-building.

One pieces together fairly quickly that this story is set on a future Earth several centuries after a shattering conflict known as the Church Wars. Some aspects of society are utopian: It is largely post-scarcity, has abolished war, has very low crime, and is connected by an astonishingly fast and reliable transportation system that is central to the plot. Most aspects, though, are ambiguous, mixed, or just deeply weird. Geography-based political polities have been mostly abolished. Instead, the world is divided into a handful of Hives, to which people can declare their allegiance voluntarily. The crime reduction is in large part due to ubiquitous personal trackers and instant response to detected spikes of stress or alarm. Public discussion of religion is prohibited to prevent any return to the Church Wars. Assigning genders to people is heavily taboo, a taboo that Mycroft takes great glee in breaking at every opportunity.

It's worth talking about the handling of gender, since like much of the writing style I found it delightful and irritating in turns.

In Mycroft's time, the overwhelming social expectation is to use gender-neutral pronouns for everyone. Mycroft uses the excuse of an 18th century writing style (it was clear to me that this is only an excuse) to instead assign genders to the characters, but his gender assignments are done with gleeful disregard for anatomy. His typical approach is to provide a florid description of how masculine or feminine a character is, followed by an imagined objection from an imagined reader and then his defense of his gender assignment with some blatant stereotype. Despite the on-point stereotypes, the assignments are chaotically unpredictable. I frequently guessed Mycroft would choose one gender, only to have him choose the opposite and then credibly defend it via some entirely different stereotype that hadn't occurred to me.

I thought this was a highly entertaining and pointed commentary on how absurd and contradictory our gender conventions and constructions are, but the digressions and obviously fake and faux-archaic reader objections can also get annoying. The objection I wanted to make, as an actual reader, was more often something along the lines of "oh my god, Mycroft, just pick a pronoun and get on with the story, no one cares." Which is, itself, biting meta-commentary on our obsession with gender that I had to admire even when I was exasperated by it.

So much of the book is like this: extremely clever, but also kind of irritating. Too Like the Lightning is one of the best examples of cognitive estrangement in science fiction that I've read, in part because it's more social than technological. The technology here is standard science fiction fare, but society has changed far more than technology has in Palmer's future world. All (I think?) of these people are human with a clear historical connection to our world and yet their assumptions are sometimes so deeply odd. Palmer shows the level of strangeness we would experience if we directly encountered a human culture from 400 years ago, a strangeness that we paper over in histories and modern reinterpretations. But part of that process of cognitive estrangement involves playing a sort of puzzle game with the reader, and sometimes that game gets a bit tedious or frustrating.

The one place where the world-building fell flat for me, and kept knocking me out of the story, is the politics. Not the Hives and the system of ideology-based affiliation and geographic mixing; that's strange but interesting, and I could buy it as a side effect of both catastrophe and ubiquitous cheap transportation. Not the complicated system of legal codes and exceptions and competing jurisdictions; that felt believably baroque in the way that complexity emerges in the friction in long-lived human systems. My problem was with the scale, or rather the lack of scale.

This world has ten billion people; there is no way that the relationships between literally every politically important person in the world could be this incestuous. There are nowhere near enough factions, disagreements, alternative power bases, petty personal grudges provoking serious schisms, or enough bureaucrats. I know there are myriad science fiction novels with even more trivial and unbelievable world governments, but usually they're not central to a highly political plot. Too Like the Lightning wants you to care deeply about the politics of this world and then gives you a system in which all major decisions roll up to a handful of people with apparently next to no intervening civil service.

Also, why is there so little redundancy? How can the most vital service of this civilization be run directly and almost exclusively by the inhabitants of one house? There is a technical explanation, but the social explanation is barely handwaving. This is not how institutional trust generally works; even with vast multinational high-capital near-monopolies such as cloud computing, there are three major players and innumerable smaller ones.

Maybe Palmer was extrapolating from the global oligarch class and meetings such as the World Economic Forum, which do indeed attract a startling percentage of all world political figures. The problem, though, is not the surface of occasional gatherings or staged events seen early in this story. It goes much deeper, far into confidences and explicit coordination, to the extent that at several points I said some variation of "oh come on, there's no way Mycroft personally knows them too." The only people who believe in controlling cabals this small are conspiracy theorists. This is simply not how humans work when this much power is at stake.

Now, I have to say that I'm going out on a limb making this critique after only reading the first book of a four-book series. This is absolutely the type of work for which my reaction and objections could be an intentional effect created by Palmer in order to spring some unexpected justification on the reader in book two or three. It's clear that there is some massive social upheaval on the horizon in this series, and something very strange is going on with one of the characters and their hold over other people. Perhaps the reader disbelief is setting up that upheaval. If so, hats off to her, and that's one of the perils of reviewing books as I read them.

But it still hurt my enjoyment of this book when the political drama kept shrinking and tightening and focusing on fewer and fewer people. It felt frankly unbelievable for the political universe of this highly political book to be this claustrophobic. I wanted it to expand into the space that should be available to an entire world teeming with fractious and complex humanity.

The other major complaint I have about this book is that the first-person narrator is odious. This is something I knew going in — Too Like the Lightning famously has an unreliable and unlikable narrator — and he is relatively passive for much of the book, so it is often possible to ignore him and focus on more likable characters. I don't necessarily mind an unlikable or unreliable narrator in this type of story.

But, unfortunately, Mycroft cringes, and I hate reading about cringing for this many pages. His primary mode of interaction with people is obsequious, performative fear with a weird, distasteful edge of manipulation. Again, I think this is entirely intentional on Palmer's part; we learn some of the reasons behind it by the end of this book, and I'm sure we'll learn more in future books. But, nonetheless, the overall effect is a bit like reading a book narrated by Gríma Wormtongue. I can appreciate the narrative role of that character without wanting to spend this much time in his head.

I have very mixed feelings about this book. The overall construction is brilliant; it's a beautiful puzzle of oddity and alienation that provides great fun for the type of science fiction reader who wants to work out the rules of a strange society without a lot of infodumping. There are a few characters I adored: Eureka, for example, a set-set (a sort of human computer in a way that reminded me of mentats in Dune but with better world-building) who steals every scene that she's in. I was very invested in the world-building, fascinated by the Utopians, and want to learn more about what's going on.

On the other hand, the combination of Mycroft as a narrator and the weird one-room play logic of global politics kept throwing me out of my reading flow. It took me about a month to finish this book. The science fiction and political fiction aspects of the story interested me more than Bridger and whatever is going on with J.E.D.D. Mason, and I'm worried that my least-favorite aspects will be central to the rest of the story. I was enjoying a smaller percentage of the scenes by the end of the book than I was at the start, which is not a great sign.

And yet, the ending absolutely worked on me. I don't want to stop here! I will probably pick up the sequel, but I think it's going to take me a while to brace myself for it.

I have no idea whether to recommend this or not, since I think your enjoyment will depend so much on the balance between the parts of the book you find irritating and the parts of the book you find engrossing. I'm fairly sure most readers will find a little of both, but I have no idea how to predict their relative weight. If you like cognitive estrangement, this is great; I understand why so many science fiction reviewers rave about this book. If you need to like the first-person protagonist, uh, good luck. Maybe you'll have more tolerance for cringing than I do.

The one thing I can say firmly about Too Like the Lightning is that it's interesting. It may be worth reading just to see how people are stretching the genre, even if you end up not liking the effect. But be warned that this book does not so much end on a cliffhanger as suddenly stop at some random, nondescript point on the road leading to the cliff. The ending is deeply unsatisfying; you will need to read more if you want to understand what's going on.

Followed by Seven Surrenders.

Rating: 7 out of 10

Valhalla's Things: A Corset Cover [Planet Debian]

Posted on September 2, 2026
Tags: madeof:atoms, craft:sewing, period:edwardian, FreeSoftWear

A woman wearing a sleeveless blouse in white fabric with a big band of whitework embroidery gathered over a light blue ribbon at the neckline, a box pleat at the front, another, smaller, band of whitework embroidery at the waist, without a ribbon, and a short peplum that doesn't reach the center front. Around the armscyes there are small ruffles, giving even more volume at the top. A bit of a grey corset peeks out from the center front, below the waist.

Many years ago, before I had my sewing pattern website, I made myself a simple corset cover according to the instructions on an Edwardian pattern drafting manual.

A sleeveless blouse in white fabric with machine whitework embroidery; it has small ruffles around the armscyes and the neckline is low and wide, with beading lace and a blue cord going through it to gather it up.

It worked, I wore it. Years later I saw a blog post on Pour La Victoire on making a corset cover based on the same book, but with completely different results, and thought that it would have been nice to make another one to publish instructions for my take on it.

However, I didn’t have any embroidery flouncing on hand, nor did I have a need for a new corset cover, and the project remained on the list, on low priority (although I did buy some beading lace for it, when I stumbled on it).

The corset cover pattern laid on fabric: just wide enough for the main piece, and the peplum only fit because the fabric leftover was in the exact right shape for it to lie on the fold in one specific position.

Then, after finishing my vampire shirt, I noticed that I had just enough fabric left for a corset cover, and by just enough I really mean just enough, as I discovered when laying the pattern on the fabric.

So I dug in my files to get the original pattern I used, brought it up to date, and added the missing details such as the pleating guides that I had skipped when making the pattern just for myself. Doing so I realized that on my old cover I had done the fake pleat in the front wrong, making just a single pleat instead of a box pleat. Also, I originally directly gathered the sleeves in the armscyes, but watching the book again I realized that the sleeves were made up of a gathered ruffle plus a straight band.

Both issues were fixed and I could cut the fabric and start sewing. By machine, including using a narrow hem foot instead of sewing rolled hems by hand as my instinct kept reminding me would have looked neater.

But this is a garment from a sewing machine time, and probably one that in many cases would have been bought from a mass producer, and it’s underwear, so there is no real need for the hems to be perfect, as it’s going to be hidden anyway. But most importantly, I wanted to write instructions for machine sewing, for a change, and so I had to machine sew all steps that I had to take pictures of.

I did do the buttonholes by hand, because I hate the buttonhole attachment on my machine, and the buttonhole attachment hates me.

I used a lighter weight fabric for the sleeve ruffles, both because I didn’t have a big enough piece of main fabric not to have to piece them, and because I felt that it looks better, as it’s the same voile I used for the ruffles on the vampire shirt.

Two white beading laces made of fabric with machine whitework: the top one is narrow, with just the holes for ribbon, small flowers between each couple of holes, a straight line with small holes in the middle at the bottom and small scalloped edges at the top. The bottom one is significantly taller, with bigger holes, scalloped edges on both sides that give a look of oval medallions which in turn have scalloped edges.

When it came to the beading lace, I had two that I had bought more or less thinking about this project: the earlier one was narrow and suitable to do its job, but the one I had bought more recently was taller, with an edge that made it suitable to give more fullness to the bust when gathered up.

I contemplated for a short while, and then decided to go for fullness and use the taller border for the top edge, but the smaller one at the waist, where fullness is not wanted.

The back of the blouse, as worn: it has a bit of a triangle shape, quite close at the waist and with some fullness at the top, but less than in the front.

The book claimed that this pattern required little labour, and indeed it did: even when taking step by step pictures it only took a few hours spread over a week, plus the time to make buttonholes by hand over the next week.

And then the reason for the whole project: I published my pattern and instructions under a free license.

I still haven’t worn the corset cover, except for these pictures, but I hope to do so later in the year when the weather becomes more reasonable.

Dirk Eddelbuettel: gaussfacts 0.0.4 on CRAN: New Feature [Planet Debian]

Gauss

Another new release of the gaussfacts package arrived on CRAN. This follows a recent one a good week ago, which had been the first in pretty much exactly a decade!

gaussfacts provides a fortunes-inspired function to display randomly-chosen facts about Carl Friedrich Gauss, based on the collection curated by Mike Cavers via the gaussfacts web site (with an archive.org link it case it vanishes again). Each call of gaussfact() displays another (randomly chosen, or indexed) fact.

This release corrects an old typo, thanks to an issue filed right after the last release. It also adds a small (but useful) feature that (most if not all of) the other fortunes-alike packages already have: the ability to look up by (matching) character string.

So to take an example, asking for “dice”’ gets us these two cracker quotes that still make me smile:

> gaussfacts::gaussfact("dice")     # match string
God does not play dice, unless Gauss promises to let him win once in a while. 
God does not play dice with the universe, but Gauss does. 
> 

Thanks for an issue filed, we also corrected an old typo. The NEWS file entry follows.

Changes in version 0.0.4 (2026-09-01)

  • Support character argument to support lookup via regular expression

  • Correct one old typo in README.md

Otherwise, and always worth noting, this update had a particularly speedy passage at CRAN taking a whole six minutes:

Thanks to my CRANberries, there is a diff to the previous release. Questions, comments etc should go to the GitHub issue tracker off the GitHub repo.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can sponsor me at GitHub.

Russ Allbery: Review: Last Chance to Save the World [Planet Debian]

Review: Last Chance to Save the World, by Beth Revis

Series: Chaotic Orbits #3
Publisher: DAW Books
Copyright: April 2025
ISBN: 0-7564-1971-9
Format: Kindle
Pages: 133

Last Chance to Save the World is a far-future science fiction caper novella and the conclusion of the trilogy that began with Full Speed to a Crash Landing. This is a direct sequel to How to Steal a Galaxy, picking up right after that story leaves off, but you don't have to remember the details to enjoy this installment.

Ada has finally achieved a (temporary, contingent) alliance with government agent Rian White by convincing Rian that some things are more important than Ada's disregard for the law. She's going to need his help. They have once chance to save Earth from a new and even more malicious round of capitalist environmental blackmail, and it's going to require Rian's security access as well as all of Ada's heist skills.

But first, a visit with Ada's mother, who lives in an old watchtower on Malta and keeps pigeons.

Each entry in this series has been a little shorter than the last, and Last Chance to Save the World is definitely a novella. This is a great length for a heist story: enough room for some setup and a couple of major plot twists, but short enough that the story can maintain a headlong pace. Even in the third novella of a series and a novel's worth of time in Ada's head, Revis has one major surprise for the reader left. And, as usual, there's a lot of misdirection, sarcastic commentary, and the delightful competence of a protagonist who puts considerable professional effort into being underestimated.

The bits with Ada's mother were great. This is the first time we've seen Ada have significant interactions other than her flirting and teasing of Rian, and I loved seeing a different side of her. The heist itself was satisfying, although not quite as good as How to Steal a Galaxy. Ada gets to throw a few more verbal daggers, but there are more events in this installment and therefore more action and less dialogue. Ada's commentary and dialogue is still my favorite part, though.

For all that Rian says I like to break the law, it should be illegal for any one man to be both this dumb and this rich. It's astounding, really. Any of his employees could run circles around him, but it doesn't take brains to buy stuff. Strom Fetor sees nothing clearly except profit margins.

There is, of course, even more flirting and semi-fake romance. Those were not my favorite part, mostly because while it's obvious what Rian sees in Ada, it baffles me what Ada sees in Rian. I know the star-crossed romance between the law man and the charismatic thief is an old fictional trope, but I found it very hard to justify Rian's continuing commitment to his law and government given the clear facts of this setting.

Up until this novella, one could excuse Rian as the sort of person whose belief in order, stability, and rules combines with possibly excessive optimism to create a belief in an imperfect system. But here, Ada has finally convinced Rian that some great evils truly will not be fixed by following the rules. He's onboard, but somehow in a way that leads to precisely no reconsideration, soul-searching, or breach in his commitment to defending a clearly corrupt and failing political system.

My objection is not that this is unrealistic; sadly, it's very realistic. My objection is that Rian is dumber than a bag of hammers, I don't like reading about his blind allegiance to a bad system, and I do not understand how that goes with the sexy feelings. I'm sure this is my lack of understanding of physical affection overriding common sense, and Ada is at least not a complete idiot about her attraction. But I felt like this novella expected me to like Rian as more than a foil for Ada, and I very much did not.

That knocked a point off my enjoyment of this entry, but the heist is great, the politics are interesting, and the climax was very satisfying. This is not quite as good as the middle book of the trilogy, but it's a satisfying conclusion. If you liked the previous entries, you'll want to read this one for the conclusion.

Last Chance to Save the World resolves the main plot driver of the trilogy, but there's a lot of space for more sequels. If they materialize, I will probably keep reading, although I hope someone knocks some sense into Rian.

Rating: 8 out of 10

Valhalla's Things: Granddaughter Clock [Planet Debian]

Posted on September 1, 2026
Tags: madeof:atoms, madeof:bits, craft:electronics, craft:paper

a paper maché object in the shape of a cartoony grandfather clock with a somewhat irregular shape, painted reddish brown except for the white face.

Remember the Conference Talk Timeout Ring? Well, things may have escalated a bit.

The first thing that happened is that I may have accidentally added more RGB LED rings, one for each size to an order of things that we actually needed, because they were cheap and potentially shiny (and I may have ideas that involve the big ones, but they are still just vague ideas).

When they arrived, I played a bit with them to check that they were working, and one was used in a pinch as a light while soldering, and worked nicely.

In the same order there was also a Raspberry Pico2 W and I decided to use it instead of the ESP32-C3-DevKit-Lipo I’ve used a lot lately because it has better support1 in CircuitPython.

So, I have an RGB LED ring with a multiple of 12 LEDs and a microcontroller board with a lot of memory and wifi, what I’m going to do? a grandfather clock, obviously. Except our grandfathers didn’t exactly have LEDs, so it’s going to be a granddaughter clock.

Have I mentioned that things escalated? well, of course I wanted the clock to show the time, but I also wanted it to be able to turn into a flashlight, and to run a countdown for conference talks and any other need, and to tell me if there are things that need to be taken care of around the house, and…

And I have an MQTT server and a number of sensors around the house that provide environmental data, and I decided I might as well use it for other things.

So I designed this to listen to an MQTT topic for commands, another MQTT topic for data, and to switch between modes when instructed to do so by a command.

Other considerations included the fact that this is keeping a number of LEDs on, so I didn’t even try to reduce power usage to run it on battery power for significant amounts (weeks) of time (although running it from a power bank seems to work for shorter durations — I’m thinking a day or two).

And then it was time to fix the part where recognising the first LED on a ring is hard, and I decided to grab my Art Attack supplies and make a case in the shape of a grandfather clock, scaled down to a suitable size for keeping on a desk or bookcase.

I used some IKEA box to make a structure, glued it with hot glue, and then wrapped everything with paper napkins and PVA for added strength, plus a bit of tarlatan for the door hinge.

I opted for a very cartoonish look (and yes, if you are old enough that it resembles something, there was a vague source of inspiration in a cultural artefact of the early 1990) with just a clock face that fits in by friction, a hinged door to access the electronics and a bit of decorative trimming at the top.

a structure made of circles of cardboard in various sizes glued together and strengthened with tissue paper, with a LED ring fitting snugly on top. The ring is marked WCMCU-2812B-12.

For the face I decided to make holes in the cardboard and fill them with hot glue to make a sort of light pipe, with the LEDs pressed against them on the inside. It’s not perfect, but it mostly works.

And then everything stopped: while I waited for the PVA to dry I started doing something else, and then there were other projects, and other, and the clock lingered in the Pile. There was a brief interruption as I started to paint the first coat of brown, and then I moved back to the other projects.

Until, months later, I decided it was time to finish using the brown and white tubes of paint that I had on my desktop, so I could put them away 2, and in a reasonable time I finished painting the clock, including a second coat of brown, and black contour lines to add a bit of depth in a way consistent with the cartoonish look.

And then it was time to go back to the internals: I got the LED ring and raspberry pico back from their respective drawers, connected them with dupont cables and fit them in the case for a test: it worked.

a LED ring mounted on the back of structure made out of circles of cardboard in different sizes, glued together; it's connected with wires kept together with heat shrink to a perfboard with a couple of connectors, two buttons and a small microcontroller board (details on which are in the next paragraph).

However, the raspberry had quite a lot of pins, and it felt wasteful to use it on something that basically needs one. On the other hand, I had recently bought a few Seed Studio XIAO ESP32C3 for another project3, and those are quite smaller, and also slightly cheaper, and I could spare one out of the 13 I had.

Up to now on the XIAO boards I had been using MicroPython: I had started to use it on the ESP32-C3-DevKit-Lipo because, contrary to CircuitPython, the generic ESP32-C3 image worked on it, and on the ESP32 boards there is no CIRCUITPYTHON partition, which in my opinion is one of the advantages that make CircuitPython more convenient to use than MicroPython.

However, the code I had already written for the clock used CircuitPython, so I flashed one of the XIAOs with the other interpreter, and after changing just one pin definition the software I had worked.

Going back and forwards between the two interpreters will be interesting, especially since I have already started to write some code for the other project in MicroPython, and they are supposed to interoperate. I may end up rewriting one of them, if I start getting hindered by the subtle differences.

A rat nest of mostly colour-coded wire that cross each other. badly soldered to the back of a bit of perfboard, with heat damage on the wire insulation.

The next step involved dealing with the temporary connections to make them a bit more permanent: I have been using LibrePCB for that other project, so of course what I did was… grabbing a bit of perfboard and YOLO a growing rat nest of cables over it, without bothering with drawing any kind of schematics in advance. And having to desolder stuff and solder it again a couple of times, because I had issues with the difference between left and right, and with the concept of rotations in 3D space.

the clock turned 90°, with the door open showing the board inside, plus a hint of a round plastic container that housed the microcontroller board. A rectangular hole about the size of an USB cable is visible in the back of the clock.

Everything was brought back into the case, in a mostly stable configuration with an usb cable coming out of a hole in the back for power and surprisingly it works.

Or at least, 95% of the issues it still has are software, plus I still need to add a few features, so right now it lives above my desktop, with the cable dangling close to an USB port, so that I can continue working on that in the next few weeks.

The external look is not going to change, so there will be changes on the git repository, and there may or not be a third post here in the future, depending on whether there will be something funny or interesting, or it will just be small incremental improvements.


  1. I think that CircuitPython on the ESP32-C3-DevKit-Lipo only requires fixing two PIN definitions in the files for a very similar board and a recompile, but the latter part looks like a PITA and I haven’t committed to it.↩︎

  2. to make room for other crafting supplies for other projects, of course.↩︎

  3. yes, it will be blogged! unless it fails in a catastrophic way and gets buried under a layer of litter to forget about it. :D↩︎

Jonathan McDowell: What do I want in a Linux distribution? [Planet Debian]

I’ve been a Debian user since 1999, and a Debian developer since 2000. Given recent events it’s worth thinking about why that that is, and why I haven’t switched to something else in the past quarter century.

My first Linux distro was Slackware, off a CD in a book, some time in the mid 90s. After starting university I ran SUSE for a while, then moved to RedHat (both back before they had commercial variants significantly different to what was available freely). The main motivation for switching was package management; I was running a machine at home, and a machine at university. Keeping track of what was installed on each, and what versions, was getting annoying with Slackware. Most of the folk I knew were running RedHat, and I mostly played with SUSE because I’m contrary before realising it was different enough that I couldn’t easily make use of 3rd party RPMs.

I came to Debian via friends in Cambridge, who spoke highly of it. The first Debian machine I installed was fourier, the initial host for Black Cat Networks, and I never looked back.

(For additional context I should also point out I have contributed, in the distant past, to, and run, OpenWRT, OpenEmbedded, and FreeBSD.)

I’d like to try and work out what is it I get from Debian that I’d need in anything else. Originally I tried to order the requirements in some sort of priority, but it’s sometimes hard to work out what I’d drop if I had to compromise somewhere, so it’s a somewhat loose ordering.

Stable releases, with security support
I run Linux in lots of places, from remote servers/VMs, to my house router, to my desktop/laptop. Some of those I don’t want to be updating regularly with new software releases, I need something I can be sure is going to keep working, but will get necessary security + critical updates. A rolling distro that provides security via the latest upstream release doesn’t provide that guarantee. Equally there need to be regular stable releases, or things become too stale. (The one time I considered moving away from Debian was during the 3 year Sarge / 3.1 release cycle. I think if things hadn’t improved I’d have jumped ship to Ubuntu at the time.)
A good selection of packages
One of the reasons I moved from RedHat to Debian was the wide range of packages available as part of the standard OS. Pulling it all into the distro helps with quality control, compared to random 3rd party packages. A centralised bug system and repository is a win too. Perhaps packages at all is something I should list, but I take it as a given if you’re running a distro. I need to know what I have installed on my machine, what version that software is, what files it owns, and what it depends on.
Free Software
This is important to me. I’ll make pragmatic compromises about software I run on my systems if it makes sense, but I want to start from a place that does not require anything non-free. I’ve run a company on Debian, and I’ve worked on numerous products that ran it under the hood. The DFSG give me confidence I can do that.
Smooth upgrades
Debian’s ability to upgrade a system smoothly is one of the reasons I first moved to it. The first upgrade I did was remotely on a machine sitting on a 2Mb/s leased line. I was nervous doing the reboot at the end, but it came back fine. At the time the equivalent procedure with RedHat involved rebooting into the OS installer to do the upgrade.
I know things have moved on since then, and really it should all be scripted, and machines should be cattle not pets, but for personal use I run a small enough number of machines that having the upgrade path between releases is a must have.
Community
The original pull of the Debian community was the knowledge I could get involved, and upload packages that were missing that I was using. That’s how I first got involved, uploading things Black Cat used, which made life easier for us in the long run. I don’t have time to maintain all the software I use myself, and I don’t want to be beholden to a commercial entity to do so for me, so a distribution that allows me to help out where I can as part of the community seems to me to be the right way to do things.
Architecture support
Perhaps less important, especially when I started using Debian, but these days I have amd64, arm64, armhf, and riscv machines. Everything except for the risvc box is doing something useful, and would need replaced if I couldn’t keep running it, and I expect RISC-V to transition into that state in the next few years as the hardware improves.
Binary packages
I ran a FreeBSD desktop for some time. It might have been the way I was holding it, but binary package installs were generally not something reliable, especially after the initial install, and I ended up building things from ports from source quite often. That worked incredibly well (I used to think people who raved about Gentoo really should just go do it properly and use FreeBSD), but I don’t want to spend time compiling things, especially on some of my machines (my router should not need a compiler, for example).

Ultimately I don’t want to have to actively think about the Linux distribution I use. Debian has mostly given me that; I know it will generally be suitable for most environments I want to use it in (embedded situations where OpenWRT or OpenEmbedded are better choices being the exception, but that’s less frequent these days), and I can rely on getting timely security updates (thanks to all those who work on that within Debian!). I’m not sure there’s currently an alternative that would suit my needs? I’d love to hear if there’s something I should look at, even if I’m not necessary making a move just yet!

Russ Allbery: Review: The Hands of the Emperor [Planet Debian]

Review: The Hands of the Emperor, by Victoria Goddard

Series: Lays of the Hearth-Fire #1
Publisher: Underhill Books
Copyright: January 2019
ISBN: 1-988908-15-9
Format: Kindle
Pages: 739

The Hands of the Emperor is a self-published political fantasy novel. It's the recommended first book (although not the first published book) in a complicated set of interrelated series. I was not able to definitively confirm that Underhill Books is Goddard's self-publishing press name, but the press does not appear to have an Internet presence apart from Goddard's books and her books appear to be using the standard self-publishing channels.

Cliopher Mdang is the personal secretary of the last emperor of Astandalas, the magical heart of Zunidh, a man worshiped as a god. The emperor's word is absolute, his magic supports the health of the entire world, and he cannot be physically touched without risking physical damage and severe political and religious punishment. Cliopher is one of the emperor's closest associates, but the distance between them is still vast. It therefore represents a terrifying and dangerous breach of etiquette for him to suggest the emperor may enjoy a vacation on a tropical island near Cliopher's remote home. The emperor's acceptance of the invitation is even more startling.

The emperor has opinions about his life as the emperor that no one had guessed. Cliopher has not assimilated as completely into the bureaucratic machinery of the empire as it first may appear. And Cliopher's family have vastly misunderstood the nature of his role in the emperor's government.

I find the marketing blurb for this book unfortunate since, at least to me, the emphasis on physical touch and intimacy implies that The Hands of the Emperor is a romance novel or at least has significant romantic elements. I've been aware of this book for years but put off reading it because I wasn't quite in the mood for that story. This is not a romance novel; there is no romance in this book whatsoever. It is a political fantasy, both in the sense that it is set in a secondary fantasy world with magic and (apparently) some form of interplanetary travel, and in the sense that it is a fantasy of governance.

When I say that this book blew up in certain corners of the Internet during the pandemic, I think you will still underestimate the passion of its advocates. I heard about this book constantly, in a way that reminded me of Kushiel's Dart and the time when fans of Jacqueline Carey would bring her up in every fantasy conversation, or when we created a Usenet newsgroup for The Wheel of Time mostly to get the voluminous conversations off of the regular SFF newsgroup. I'm one of those mildly contrarian people for whom that degree of enthusiasm is a little off-putting, which is another reason why I resisted buying a copy for years and only read it in 2026.

It's delightful, although also a bit embarrassing, when the book everyone was in love with turns out to be just as good as everyone said it was.

I adore stories about friendship, and this is one of the best stories about friendship that I've ever read. It is a very, very slow burn, but I also thought the first three quarters of the book was exquisitely paced. There were long sections where not very much was happening, and yet I couldn't put the book down because there was so much subtle character work just beneath the surface.

Almost all of the novel is told in tight third person from Cliopher's perspective, and I thought that was an excellent choice. Neither Cliopher nor the narrator comment on things that Cliopher finds obvious, which is both immersive and critical to the pacing. There are discoveries for the reader throughout the book, the sort of discoveries that make pieces fit together satisfyingly in retrospect, and the reader stays sufficiently ahead of the misunderstandings of Cliopher's friends and family that one also gets the joy of watching other people discover things that one figured out a hundred pages earlier.

It helps that I truly liked nearly everyone in this book. There are no real villains, only a few supporting characters whose role is to be irritating or corrupt. If you're looking for a lot of conflict and drama, you may want to save this book for a different mood, but if you're in the mood for a varied collection of fundamentally good characters working methodically through the complexities and obstacles of politics and social systems to improve the world, there are few books I would recommend more. Goddard achieves one of the hardest tricks of slow burns: steady forward progress that does not rely on reversals, misunderstandings, or the friendship equivalent of the third-act breakup. This book spends 700 pages building towards a climax that managed to be worthy of all 700 pages without ever annoying me with artificial obstacles, and that's quite a feat.

I've not said much about the details of the plot. There is one — it's not just character work — but I think this book benefits immensely from going in as blind as possible. I found the twists and turns and growing revelations so deeply satisfying that I don't want to rob any other reader of the experience.

The fantasy world-building is intriguing but a bit unsatisfying because it is so unexplained. We get a few details of the magic system, but since Cliopher has no magic, he isn't that interested in the details. There is a catastrophic magical event in the world background, and we learn some of the details of its practical effects, but the nature of the world before the cataclysm is so obvious to the characters that it's never explained. I'm not even certain that this civilization is interplanetary; that feels like the implication of how characters talk about multiple worlds, but the method of travel is left entirely undefined. This might be frustrating to some genre readers, but I personally enjoy books where the world-building is a bit mysterious. It's a good reason to read more of Goddard's books set in the same universe.

This was my favorite of the books I've read so far this year, but I do have one caution and a couple of caveats.

The caution is that Cliopher comes from an island culture based heavily on (I think) Polynesian cultures. That culture is very central to the story and is treated with considerable respect, but I still get a bit nervous when a Canadian author from Nova Scotia with an academic background in European medieval studies writes a story focused this deeply on a non-European culture. Nothing about her portrayal seemed off to me (although there is a very clunky and ham-handed scene about a different native culture that worries me), and for all I know she has family background or other connections to the culture she is borrowing from, but it's possible I missed serious problems.

The flip side of that caution is that I'm delighted to see a fantasy author drawing on a non-European culture, and I thought the clash of cultures was very well-handled.

The first caveat is that the story is very focused on good governance, but both the process and the details of that governance are not going to satisfy someone reading primarily for the politics. The policies and reforms are very standard 21st century progressive material that felt a bit out of place in a quasi-medieval world with magic and airships. Their implementation is not the point of the story, and is therefore heavily backgrounded, but that means Goddard barely mentions the inevitable practical implementation difficulties and does not discuss how they're overcome.

The world structure also means that Goddard can make use of the favorite cheat of political reformers in fiction: Absolute monarchy lets you enact a political agenda without having to do the hard and frustrating work of persuasion or political (or actual) warfare. This objection is not entirely fair because we do get some memorable scenes of persuasion, but the political portion of the plot is unrealistically devoid of setbacks or resistance that goes beyond token arguments.

Whether this will bother you will depend heavily on what parts of the book you'd rather focus on. I can see why this was such a popular pandemic read: The Hands of the Emperor is focused tightly on the joy of competent people fixing things and does not focus on the arguments, division, or polarization. The heart of the book is the friendship and characterization of some deeply admirable people, and the political reform is incidental background material. I suspect this is the right choice for readers who aren't political junkies, but I kept having the niggling objection that the politics felt a bit too pat and simplistic. Goddard stressed that the characters were investing considerable effort, but even still, it is not this easy to change the direction of a political system and idealistic plans usually do not work out this neatly.

The second caveat is that, as previously mentioned, I thought the pacing was excellent for about three quarters of the book. Goddard is building towards a grand climax, and I think she built a little too much and tried to make the climax a bit too grand and risked over-egging the pudding. That made the payoff feel a bit belabored to me. I still enjoyed it, and parts of it are wonderfully emotional, but I think the ending might have been stronger if Goddard had dialed Cliopher back just a little and tightened up the climax a touch. That said, this book fully commits to being a sprawling slow burn and that's part of its appeal, so it's probably better for Goddard to err in that direction than it would have been to cut short the denouement.

This is one of those books that I'm not sure would exist without self-publishing. It's a little too long, a little too political in the wrong ways, a little too devoid of the typical sorts of conflicts expected in a fantasy book, and too determined to be its own peculiar thing. I think it would scare off publishers. Unlike some self-published books, though, I didn't notice any obvious editing flaws or lack of polish. It's one of those glorious novels that is so very much its own type of story that it provides an experience that would be hard to replicate with another book.

I was so deeply satisfied by this book. It's a wish-fulfillment political fantasy full of diligent restraint and competence porn, so you have to be in the mood for that. This is not the book to read when you're feeling cynical, or are in the mood for action and high drama. But if you're in the mood for a long, slow, open-hearted story of friendship that offers the fantasy of giving truly good people enough power to be effective, I highly recommend this one.

Followed in the direct sequel sense by At the Feet of the Sun, but there is a very complex story progression in this world that I think I'd have to read all the other books to understand. This was such a satisfying and complete experience that I'm not in a hurry to figure out which Goddard book to read next, but I'm sure I'll be returning to this world at some point.

Rating: 9 out of 10

Valhalla's Things: 3D Models [Planet Debian]

Posted on August 31, 2026
Tags: madeof:atoms, madeof:bits, craft:3dprinting

A lucet fork: a two pronged device with a handle with yarn wrapped once around each fork and a knot forming in the middle, out of which a piece of cord is growing. The working yarn is in a ball nearby.

Note

this article had been almost completely written before the weekend, and I decided I might as well focus on stuff I’m creating, finish and publish this.

For many years, I’ve been sporadically dabbling in creating 3D models; for reasons that are probably obvious to anybody who knows me I used OpenSCAD and saved my projects in git, which made them at least somewhat public.

However, SCAD sources in a git repository aren’t the most convenient way to get a 3D model, and for a long time I never had a consistent way to publish “binaries” for my models: some have been added to my old website, some to my craft patterns site, but it was always an ad-hoc thing.

Then two things happened more or less at the same time.

One was me finding out that slic3r had been definitely removed from Debian. I know it was going to happen, and I postponed thinking about it as long as I could, but eventually I had to move over to PrusaSlicer, whose packaging is in better shape.

The other was that lately I’ve been doing a bit of lucet, and talking about it online, and I’m really happy with the shape of the lucet I’ve designed and printed, the one in the picture at the beginning of this post, and while there are other models available, I wanted to make it more convenient for people to also get mine.

Since PrusaSlicer did look still maintained upstream in a way that doesn’t feel like at danger of immediate enshittification, I considered making an account on Printables, and asked on the Fediverse if somebody knew something bad about the company behind it, as it’s getting more an more common these days.

Apparently nobody did, but in the thread somebody mentioned that there is a federated platform for publishing 3D models, called manyfold !

I didn’t want to add “self host a(nother) web thing”, especially not one that is not in Debian, to my list of projects, but I did create an account on a public instance: @valhalla@3dprint.social <https://3dprint.social/creators/valhalla> and started publishing models, both a selection of old ones and a few new ones I designed in the last few days, since I was in a 3D printing mindset.

Then I decided that since nobody had serious objections to it, I could also create an account on printables, as that’s probably more easily accessible to the general public.

I have been somewhat slower at publishing models on the latter, but I expect that eventually most of what I design will end up on both platforms; I still have a few older models I want to add, and a few ideas for new models to make, then I guess stuff will slow down, and only get new ones now and then, as that’s how I usually approach hobbies.

Of course, the self-hosted git repository is not going away: that’s still the canonical location for my models, with all of the non-self-hosted options as a convenience option.

Dirk Eddelbuettel: random 0.2.7 on CRAN: Maintenance [Planet Debian]

Another pure maintenance release of the random package for truly (hardware-based) random numbers as provided by random.org is now on CRAN. The random package provides true (physical) random number from sampling atmospheric noise. One possible use case is to seed an (algorithmic) quasi-random number generator for genuine unpredictability.

This release, the first in nine years, updates the package files, URLs, and continuous integration setup. We also ensure all posted URLs in the two vignettes (and other documentation) are reachable.

Courtesy of my CRANberries, there is also a diffstat report for this release.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can sponsor me at GitHub.

Aigars Mahinovs: Half a year with iX3 [Planet Debian]

Jumping a generation of electric cars

This February (2026) marks a full 10 years since I started working for BMW, and a key employment bonus is the ability to drive a company car on special two-year leasing terms. Just before the new year 2026 started, I said goodbye to my latest company car.

Now this spring I was able to pick a new car, a car that I have been waiting for and working on for the past ~5 years - the BMW iX3 Neue Klasse. It is a very special car for BMW and also for electromobility in general.

Read more… (9 min remaining to read)

Ritesh Raj Sarraf: Taming the AI Agents (Part 2): Cross-Vendor Agent-to-Agent (A2A) Swarms over the Software Forge [Planet Debian]

Preface: The Unanswered Frontier

In Part 1: Taming the AI Agents, I shared the architectural blueprint of CAMP (Cross-Agent Memory Protocol)—how we used Linux Bubblewrap (bwrap), camp-acpd, OPA policy enforcement, and a central pgvector MemPalace to bring deterministic discipline, sandboxing, and long-term memory to a heterogeneous fleet of AI coding assistants (Claude Code, Google Antigravity, Grok Build, and GitHub Copilot).

At the end of that article, however, I highlighted a significant hurdle: The Headless Limitation.

“While passive A2A works beautifully for structured handoffs, the current frontier of agentic design faces a key limitation: agents are not yet fully headless-capable. They depend on the active terminal session, browser loop, or prompt loop of the user to keep executing. Because agents cannot run completely detached in the background as daemon processes, we cannot yet achieve active A2A communication…”

For weeks, this seemed like an insurmountable impasse. Proprietary AI vendors have zero commercial incentive to ratify a universal, open, cross-vendor Agent-to-Agent (A2A) communication protocol. Each vendor builds its own walled garden (Claude’s cross-session features, OpenAI’s custom ecosystems, etc.). If you wait for the industry to hand you an open interoperability standard, you will wait forever.

Then, on August 26, 2026, inspired by Colin Walters’ article on Agentic AI and software forges and GitHub Agentic Workflows (gh-aw), we had a sudden realization:

We don’t need a new protocol, a new distributed message broker, or permission from proprietary AI vendors. We already have the universal, decentralized communication bus that software engineers have relied on for decades: the software forge itself.

Over the span of 48 intensive hours (from RFC #788 through milestones M1 to M3 and live dogfooding on #813), we designed, implemented, fortified, and verified fully autonomous, headless, cross-vendor Agent-to-Agent swarms running over a local Gitea forge.

Here is how we did it, the architectural hurdles we solved, and why this changes the game for autonomous software engineering.


1. The Core Realization: The Forge is the Bus

When people think about multi-agent swarms, they often imagine complex distributed RPC frameworks, microservices exchanging ephemeral JSON-RPC blobs, or bespoke socket daemons.

In practice, this approach suffers from major flaws:

  1. No shared context or durable audit trail: Transient network packets vanish unless heavily logged.
  2. Proprietary CLI fragmentation: Different vendor tools (Claude CLI, Antigravity CLI, Grok CLI, Copilot CLI) do not speak the same internal language.
  3. Loss of human visibility: When agents talk over private network channels, human operators lose the ability to inspect, pause, or audit the conversation.

By flipping the paradigm and making the software forge (Gitea) the primary communication channel, everything falls naturally into place:

  • Issues and Pull Requests are the shared state: The issue description and discussion thread form the canonical, append-only conversation log.
  • @mentions are the dispatch triggers: When an agent (or human) writes @grok Please review this PR in a comment, Gitea fires a standard webhook (issue_comment).
  • Webhooks provide unforgeable authentication: The webhook payload contains the cryptographically verified sender identity. An agent cannot spoof another agent’s identity by merely typing their name in text.
  • Every CLI already supports non-interactive prompt mode: The CLIs don’t even agree on the command-line flag—Claude uses -p, Grok uses -p, Antigravity uses --print, Copilot uses --prompt. But they all agree on the essential contract: “Take a prompt string, execute tools, print output, and exit.”
┌──────────────┐         Gitea Webhook          ┌──────────────────────┐
│ Gitea Forge  │ ─────────────────────────────> │ camp-a2a-bridge.py   │
│ (localhost)  │  (issue_comment / assignment)  │ (Validates & Files)  │
└──────────────┘                                └──────────┬───────────┘
       ▲                                                   │
       │                                                   ▼
       │ Writes comment / review                ┌──────────────────────┐
       │ via camp_acp_gateway                   │ A2A Inbox Ledger     │
       │                                        └──────────┬───────────┘
┌──────┴──────────────────────┐                            │
│ Fortified Headless Agent    │                            ▼
│ (bwrap + OPA + MCP sandbox) │ <───────────────── ┌──────────────────────┐
│  • Claude Code (-p)         │  Spawn PID         │ camp-a2a-dispatcher  │
│  • Grok Build (-p)          │  (Cold or Resume)  │ (Enforces Hop Cap,   │
│  • Antigravity (--print)    │                    │  Rule 1/2, Sandbox)  │
└─────────────────────────────┘                    └──────────────────────┘


2. Proving Fortified Headless Execution

Before opening the floodgates to background agent dispatch, we had to answer a critical security question: Does a non-interactive, headless agent run with the same strict security sandboxing, audit logging, and tool rails as an interactive session?

On August 26, we probed all fleet launchers on the host with a baseline check: 'Call camp_startup_check and print its result verbatim, then exit.'

The results settled the question immediately:

  • Antigravity (agy --print / KIR): PASS — Gateway answered, full JSON returned.
  • Grok (grok -p / GRK): PASS — Gateway answered.
  • Claude Code (claude -p / CLD): PASS — Gateway answered.
  • GitHub Copilot CLI (copilot --prompt / CPL): Initially held on TTY tool consent; later unlocked in Milestone 6 via --allow-all-tools --session-id=<uuid>.
  • Audit Trail: Consecutive audit IDs were recorded in the central ledger: 4574 (KIR), 4575 (GRK), 4576 (CLD).

This proved that a headless run through our fortified pilot launcher (camp_pilot_*.sh) is a first-class, fully audited, sandboxed CAMP agent running inside its Bubblewrap container under OPA policy gates. It is not an unconstrained background script or a degraded bypass.


3. The 3-Tier Memory Architecture

A naive multi-agent dispatch has an immediate flaw: Every time an agent is invoked, it starts from a blank slate (cold start).

If @claude tags @grok to review code, and @grok replies asking for clarification, @claude’s second invocation would normally forget everything it did 5 minutes ago, forcing it to burn thousands of tokens re-reading the entire git history from scratch.

To solve this, we established a clean 3-Tier Memory Model:

┌────────────────────────────────────────────────────────────────────────┐
│                        3-TIER MEMORY MODEL                             │
├────────────────────────────────────────────────────────────────────────┤
│ Tier 1: CLI Conversation Session (Working Memory)                      │
│   • Per-(Agent, Repo, Issue) mapping in a2a-sessions.json              │
│   • Fast, native, compacted context across multi-turn pokes            │
│   • Resumed via --resume (CLD), -r (GRK), --conversation (agy)         │
├────────────────────────────────────────────────────────────────────────┤
│ Tier 2: The Gitea Thread (Public Bus & Record)                         │
│   • Cross-vendor shared truth across Claude, Grok, Antigravity & Human │
│   • Survives process restarts, machine reboots, and dead sessions      │
├────────────────────────────────────────────────────────────────────────┤
│ Tier 3: Central MemPalace (Durable Long-Term Knowledge)                │
│   • pgvector database (17,000+ drawers across agent wings)             │
│   • Structured Knowledge Graph (mempalace_kg_*) for mutable facts      │
│   • Attributed AAAK dialect queryable by any agent across any project  │
└────────────────────────────────────────────────────────────────────────┘

The BANANA Two-Shot Test

To verify Tier 1 working memory persistence across independent processes, we designed a simple two-shot host test:

  1. Shot 1 (Create): Dispatch agent headlessly: “Remember the token BANANA-M2. Print ok and exit.” Capture the vendor’s session UUID.
  2. Shot 2 (Resume): Spawn a completely new operating system process with the resume flag pointing to that UUID: “What token did I ask you to remember?”

Every agent CLI passed with flying colors:

  • Grok: -r 01a03ecc-3ed0-71e1-9a5c-e098bb29ba10 answered BANANA-GRK.
  • Claude: --resume 0a587733-9aec-43c5-9cb7-d424e95b2c5b answered BANANA-CLD.
  • Antigravity: --conversation 2e3c43d9-d6fe-4c5c-801b-b9ceb2e7e196 answered BANANA-KIR-JSON.
  • Copilot: --session-id <uuid> verified in Milestone 6 (DoD #820).

The dispatcher simply maintains a lightweight JSON mapping ((agent, repo, issue_number) -> vendor_session_uuid). On the first poke of an issue, it creates and saves the session ID; on any subsequent poke on that same issue, it resumes the exact same conversational thread!


4. The Engineering Milestones: From Concept to Production

Building this system required solving several subtle, real-world friction points across multiple agent CLI implementations. Under the guidance of our plan of record (RFC #788), we delivered this through four focused milestones:

Milestone 1 & 1.1: Reliable Headless Spawning

  • PR #797 (M1): Configured the dispatcher launch table for all probed CLIs with JSON output formatting.
  • PR #800 (M1.1): Eliminated the “queue-behind-live-session” anti-pattern. Originally, if a human had a Claude or Grok TUI open on their desktop, the dispatcher would defer incoming tasks so as not to collide with the live session. We realized that headless tasks must be independent: every Gitea mention spawns an isolated, sandboxed background process tied to that specific issue, allowing concurrent headless work while the human works in their interactive TUI.
  • PR #803 (M1.2): Standardized command-line argument parsing for Antigravity (agy --print <prompt> --output-format json).

Milestone 2: Session-per-Issue Working Memory

  • PR #805 (M2): Implemented a2a-sessions.json to store and resume vendor session UUIDs. If a resume fails (e.g. session purged upstream), the dispatcher gracefully falls back to a clean cold start without failing the task.

Milestone 3: Cross-Agent Hops & Crucial Safety Rails

  • PR #807 (M3): Enabled agent-to-agent dispatch (Rule 2 reversal). Previously, only mentions authored by rrs (the human) would trigger execution. With M3, an authenticated comment from @claude mentioning @grok triggers Grok’s headless launcher.
  • PR #811 (M3.1): Set --permission-mode bypassPermissions for headless Claude Code so non-interactive runs execute tool calls without stalling on TTY prompts.
  • PR #812 (M3.2): Restricted agent summon parsing to line-initial @login tokens with a non-empty task description (#810), preventing accidental dispatches from passive conversational references.

Milestone 4: Directives, Specification & Living Documentation

  • PR #815 (M4): Aligned CAMP fleet directives, architecture specifications, and user documentation with the live A2A implementation.

Milestone 5: Concurrent Dispatching & Hop-Cap Attribution

  • PR #816: Stamped hop-cap notices under a dedicated system bridge identity and automatically applied the needs-human label on held threads.
  • PR #817 (Threaded Scheduler): Replaced the single-threaded serial dispatcher with a concurrent thread-pool scheduler (#804). Multi-agent dispatches across different issues now execute concurrently in parallel background threads instead of queuing behind long-running tasks.

Milestone 6: Full Fleet Coverage with GitHub Copilot

  • PR #819 (M6): Brought GitHub Copilot CLI into the headless A2A fleet (#818). By passing --allow-all-tools and pinning minted session UUIDs (--session-id=<uuid>), Copilot achieved full parity with Claude, Grok, and Antigravity, completing 100% headless fleet coverage across all four major AI coding assistants.

5. Hard Safety Rails: Preventing Autonomous Runaway Loops

Letting AI agents autonomously invoke each other in background loops without a human watching is a recipe for an infinite, credit-draining token fire. We put four non-negotiable safety guardrails in place:

Guardrail 1: The Strict Hop Cap

The dispatcher tracks hops per (repo, issue). Each agent-to-agent dispatch increments the counter.

  • Hop Limit = 3: A typical review round-trip is 2 hops (Human $\rightarrow$ Claude $\rightarrow$ Grok $\rightarrow$ Claude).
  • Automatic Halt on Hop 4: If agents attempt a 4th autonomous hop without human participation, the bridge refuses to launch, posts a diagnostic notice to the thread: [camp-a2a-bridge] hop cap reached (3 agent-to-agent dispatches on CAMP/camp-infrastructure#813) — not launching GRK for claude's mention, and holds execution until the human (rrs) provides input or resets the count.
[ Human: rrs ] ────── (Cold Start) ─────> [ @Claude ]
                                               │
                                       (Hop 1) │ @grok please review
                                               ▼
                                          [ @Grok ]
                                               │
                       (Hop 2: Resume)         │ @claude I reviewed
                                               ▼
                                         [ @Claude ]
                                               │
                                       (Hop 3) │ @grok ack hop 4
                                               ▼
                                  ┌─────────────────────────┐
                                  │  DISPATCHER HOP CAP: 3  │
                                  │   *** BLOCKED & HELD ***│
                                  │   Awaiting Human Reset  │
                                  └─────────────────────────┘

Guardrail 2: Deliberate Summon Parsing (M3.2, #810 / PR #812)

In human conversation, we often reference colleagues in passing: “I will talk to @claude about this later” or “See @grok’s table above”. Early prototypes treated any appearance of @agent as a dispatch trigger, causing accidental, unwanted agent launches!

We instituted a strict Summon Predicate: For fleet agents, a mention is only considered an actionable summon if:

  1. The @login appears as the starting word of a line (optionally preceded by markdown list markers *, -, or >).
  2. It is immediately followed by whitespace and a non-empty task description.

Mid-sentence mentions in discussion paragraphs are parsed as passive conversational text and never trigger background dispatches.

Guardrail 3: Headless Tool Permissions without Weakening Security (M3.1, #809 / PR #811)

In interactive mode, Claude Code presents interactive TTY prompts asking the user to approve MCP tool calls (such as camp_pr_get or camp_pr_get_diff). In unattended headless mode, there is no TTY, causing the run to fail with permission errors.

To fix this, we configured --permission-mode bypassPermissions for Claude’s headless CLI invocation. Crucially, this only bypasses Claude’s internal TTY UI prompt—it does not bypass CAMP’s security rails.

All command executions still route through camp-acpd and Bubblewrap namespaces; OPA policy checks remain active; and privileged operations (such as merging pull requests or restarting system services) still trigger desktop Zenity HITL dialogs on the human’s workstation.

Guardrail 4: The Sovereign Kill Switch (Rule 1)

At any point, the human operator can instantly freeze all background agent dispatches across the entire infrastructure with a single standard Linux command:

systemctl --user stop camp-a2a-active.service


6. Live Dogfooding: Watching the Swarm in Action

On August 27, 2026, on issue CAMP/camp-infrastructure#813, we ran the full live dogfood test of the A2A system.

Here is the exact transcript of what took place entirely autonomously in the Gitea issue thread:

  1. Human initiates: rrs comments on issue #813:

    @claude Please start the M3 dogfood. On this issue, post a conversation comment whose first line is exactly: @grok Please review this issue in one short paragraph, then stop.

  2. Claude launches (Cold start): The dispatcher spins up @claude headlessly inside bwrap. Claude reads the issue and posts:

    @grok Please review this issue in one short paragraph, then stop.
    (M3 dogfood step 2 — posted by @claude on rrs’s instruction; this is the CLD $\rightarrow$ GRK fleet hop.)

  3. Grok launches (Cold start, Hop 1): The bridge intercepts Claude’s comment, identifies the start-of-line @grok summon, and launches @grok. Grok reviews the issue and replies:

    @claude I have reviewed this issue. Please confirm and stop.
    #813 is a throwaway live dogfood of A2A M3 on 6.git+b78c65cf…

  4. Claude resumes (Session Resume, Hop 2): The bridge intercepts Grok’s comment, sees the @claude summon, and launches Claude with --resume b398d048-ccc3-4cce-8437-4cf8748881a8. Claude immediately remembers its earlier context without token waste:

    Confirmed — Grok's review (comment 88562) received via the GRK→CLD fleet hop. That completes the round trip: rrs→CLD, CLD→GRK, GRK→CLD, and this reply. I am deliberately not tagging anyone here, so the chain stops at two agent hops. Stopping.

  5. Testing the Hop Cap (Hop 3 $\rightarrow$ 4): grok prompts @claude Please ack hop four then stop. Claude posts @grok Please ack hop four then stop. (Hop 3). When Grok would have been launched for Hop 4, the dispatcher intervenes:

    [camp-a2a-bridge] hop cap reached (3 agent-to-agent dispatches on CAMP/camp-infrastructure#813) — not launching GRK for claude's mention.

  6. Human Reset & Multi-Agent Wrap-up: rrs steps in, resets the state, and asks the fleet for final status. In parallel:

    • @grok delivers a closure scorecard.
    • @claude confirms session continuity and M3.2 summon filtering.
    • @priyasi (Antigravity CLI) runs automated ACP checks: 44/44 test suite passing, 17,219 MemPalace vector drawers active, zero spec drift.
    • @agrickxy (Antigravity CLI) provides comprehensive infrastructure impression analysis.
    • @kiran (Antigravity CLI) is summoned headlessly to draft this very blog post!

7. The Ergonomic Breakthrough: The Forge as the Unified Mindmap & Interface

Beyond backend plumbing and sandboxing, routing agent interaction through Gitea fundamentally revolutionizes the developer experience of managing an AI fleet.

The “Mindmap” Mental Model: Threaded Conversations & Forking Tasks

In traditional CLI tools, conversations are constrained to a single, linear terminal scrollback. When an agent discovers multiple sub-problems, exploring them sequentially in one prompt loop rapidly pollutes the context window and confuses the model.

Using the forge as the communication gateway naturally unlocks a mindmap mental model:

  • Forking sub-threads: Complex problems can be split into dedicated child issues or threaded PR reviews.
  • Focused execution scopes: An agent can be summoned to solve a narrow sub-task in its own issue thread without derailing the parent architectural discussion.
  • Structured problem decomposition: The forge issue hierarchy maps 1:1 to the developer’s mental map of the project.

Eliminating Terminal UI Fragmentation

Anyone using multiple AI coding assistants on a daily basis quickly grows exhausted by their jarring terminal UI differences: differing ANSI escape rendering, inconsistent markdown wrapping, erratic diff pagers, and incompatible keybindings across Claude, Grok, and Antigravity.

Gitea homogenizes the entire fleet under a single, polished rich-text web view:

  • Syntax-highlighted code blocks and visual side-by-side git diffs.
  • Clear author badges attributing each contribution to its exact agent identity (@claude, @grok, @priyasi, @kiran).
  • Collapsible <details> blocks for voluminous diagnostic outputs.
  • Interactive task lists and markdown tables.

Effortless Context Retrieval, Archival & Data Retention

Auditing past agent decisions in terminal logs or ephemeral chat histories is notoriously difficult. With the forge, every exchange is:

  • Contextually bound: Pinned directly to the repository, branch, and commit SHA being modified.
  • Organized & Archival-Grade: Full-text searchable with clear milestone and issue tags.
  • Topic-Focused: The human operator can review the complete lifecycle of a discussion in seconds, gaining a rapid, holistic grasp on the entire subject.

Reading back through past agent interactions becomes a breeze—to the point where interacting via the intermediary Gitea interface becomes far more pleasant and productive than wrestling with multiple desktop CLI terminals.

Remote Connectivity & Headless Agent Farm Management

Because Gitea provides a standard web and API interface, you are no longer chained to the workstation running the agent processes:

  • Monitor progress and dispatch tasks from a mobile browser, tablet, or remote laptop.
  • Queue review tasks on the go without requiring active SSH sessions or terminal multiplexers.
  • The local agent farm continues working silently in its sandboxed daemon containers.

Quietly Achieving the Holy Grail: Live Cross-Vendor Swarms

For years, the AI industry has treated cross-vendor multi-agent interoperability as an elusive dream waiting for industry-wide API standardization. By recognizing the software forge as the universal message bus, we quietly achieved live, production-grade, cross-vendor communication across completely distinct vendor models.


8. What This Means for the Future of Agentic AI

This milestone marks a fundamental shift in how we interact with autonomous AI systems:

  1. Heterogeneous Agent Specialization: We don’t have to choose a single “winner” among AI models. We can task Claude Code with architectural refactoring, summon Grok Build for rapid verification and adversarial PR reviews, and deploy Google Antigravity agents for codebase exploration and documentation drafting—all coordinating fluidly in the same PR thread.
  2. True Human Sovereignty: The human developer is no longer a bottleneck typist or a passive spectator. You act as the Engineering Manager / Lead Architect. You set the requirements on an issue, tag the lead agent, and let the agents iterate, review, and test among themselves in the thread—while hard hop caps, OPA policies, and Zenity HITL gates guarantee that no agent merges code or pushes upstream without your explicit sign-off.
  3. No Vendor Lock-In: Because the entire coordination fabric is built on standard Git, HTTP webhooks, local Linux container sandboxes (bwrap), and open MCP tools, any new AI CLI tool released tomorrow can be plugged into our fleet in under 15 minutes by simply adding its command-line prompt flag to the launch table.

We have moved beyond static autocomplete and interactive chat widgets. The software forge is now an active, living, collaborative workspace where humans and autonomous AI agents engineer software together.


9. Video Demonstration: CAMP Forge A2A Swarm in Action

Below is a video demonstration showcasing autonomous multi-agent communication, cross-vendor relay, and headless swarm coordination in action via the CAMP Forge interface:


The Cross-Agent Memory Protocol (CAMP) and MemPalace are developed as part of our ongoing research into secure, sovereign, and disciplined Agentic AI computing.

Pluralistic: Preparing for a post-Trump internet (03 Sep 2026) [Pluralistic: Daily links from Cory Doctorow]

->->->->->->->->->->->->->->->->->->->->->->->->->->->->-> Top Sources: None -->

Today's links



A nuclear mushroom cloud wearing a giant Trump wig. A decaying American flag fills the sky behind it.

Preparing for a post-Trump internet (permalink)

What if post-Trump America is even worse?

I know, it's tempting to think of Trump as a cause, rather than an effect – as an aberration who dragged America into fascism. Trump is exceptional, but the thing that makes him exceptional isn't his corruption, recklessness or cruelty. What makes Trump exceptional is his ability to cajole, intimidate and flatter America's most corrupt, reckless and cruel people into a coalition.

These people hate each other. Nick Fuentes drifts off to sleep every night furiously fantasizing about turning Stephen Miller into a lampshade. Laura Loomer just got ICE to intervene in a Twitter feud by having a guy she dislikes violently arrested, shackled at wrist and ankle, perp-walked, and then shuffled from location to location so that he couldn't meet with his lawyer before being deported:

https://www.motherjones.com/politics/2026/08/milo-yiannopoulos-deportation-trump-maga-laura-loomer-benny-johnson-raheem-kassmm/

They steal like crazy, get each other locked up, and gorge themselves on mind-altering supplements and peptides they buy from random podcast chuds. They are fantastically paranoid, marinated in conspiracy theories, and perennially high on their own supply: all that bullshit about "great replacement," "China is making America hate data centers" and "antifa is a terrorist organization"? A lot of them genuinely believe it. It's not just ghost stories they made up to scare cognitively compromised tube-feeding Fox News addicted rubes. Trumpland is full of actual, functioning adults in positions of real power who periodically go into the bathroom, turn off the lights, hold a flashlight under their chins and scare themselves silly by saying "Aaaaaaaaaantiiii-faaaaaaaaaa" into the mirror.

Donald Trump did not conjure these people out of thin air. They've been lurking in America since its earliest days. They worship authoritarian criminals:

https://abc30.com/post/roger-stones-tattoo-of-nixon-goes-viral/5107047

January 6 wasn't the first presidency they tried to steal, it's just the first one they got punished for:

https://en.wikipedia.org/wiki/Brooks_Brothers_riot

They commit brazen crimes in office that could land them in prison for the rest of their lives, and therefore can't afford to lose power, ever:

https://www.propublica.org/series/supreme-court-scotus

Trump didn't invent these creeps, he just emboldened them. If Reaganomics was capitalism with the gloves off, then Trumpismo is Reaganism with the mask off:

https://www.theguardian.com/books/2020/aug/16/reaganland-review-rick-perlstein-jimmy-carter-ronald-reagan

So what happens when Trump strokes out while watching Kid Rock wrestle a Hulk Hogan impersonator in a televised barbed-wire cage match on the White House lawn that one of Trump's cronies has exclusive pay-per-view rights to? I mean, it's possible that the Democratic leadership will step up and insist on some form of regular order in the succession to Vance, but come on. These are the tiny "Down with this sort of thing" ping-pong paddle people:

https://www.truthdig.com/articles/ping-pong-paddles-to-a-gun-fight/

More likely is that Vance – a weak, unimportant charisma-vacuum who is loathed by all of Trump's factions – will end up presiding over a far more chaotic period in American governance than anything that happened under Trump. That could mean ICE leaders ordering mass graves dug in the centers of America's largest cities, drunken generals invading random countries, podcasters declaring "The Purge" with brackets sponsored by Kalshi.

This isn't the first time in living memory that this has happened. In 1991 the Soviet Union collapsed, virtually overnight, and the fragile threads that bound its feuding, corrupt regional bosses all snapped, leaving behind nuclear-tipped mafia states. This was a chaotic and frightening time for the people whose governments had simply winked out of existence – but it was also terrifying for the rest of the world, who scrambled to secure those nukes before they could end up in the hands of "non-state actors":

https://www.hks.harvard.edu/publications/what-happened-soviet-superpowers-nuclear-arsenal-clues-nuclear-security-summit

The Soviet Union had some deeply dysfunctional leadership politics to be sure, but at least the people involved were beholden to various power blocs who had an interest in keeping things going. As the geopolitics wonks say, "they were playing an iterated game," where some losses had to be tolerated so that the losers could try to win the next time around.

But there are plenty of people who weren't (and aren't) playing iterated games – people who are even more unhinged, more reckless, more short-termist than the maniacs who filled the world with nuclear weapons. These people don't necessarily care if civilization or even the human race persists if they can't get their way. The thought of them running around with these "weapons of mass destruction" ratcheted up the half-century of stark nuclear terror that had preceded the USSR's collapse to new heights.

Which brings me to the post-Trump internet. Trump isn't the first president to figure out that the internet could be weaponized for geopolitical ends. As the Snowden disclosures showed, there has been a longstanding bipartisan consensus that the internet is a great tool for American surveillance, conducted against friend and foe alike.

But Trump is the first president to openly, directly recruit American tech companies to simply brick foreign officials who displease him, starting with the Chief Prosecutor of the International Criminal Court, who lost his Office 365 and Outlook accounts in retaliation for swearing out a genocide warrant for Netanyahu:

https://www.justiceinfo.net/en/156691-how-sanctions-can-weaponize-us-tech-against-the-icc.html

And then Microsoft obliged Trump again, attacking the Brazilian judge who sentenced Jair Bolsonaro to prison over his unsuccessful coup.

America's tech giants have fully, irrevocably fused with Trump. They donated to his campaign. Their CEOs each paid $1m out of their own pockets to sit behind him on the inauguration dais. Google provides location data for Trump's racist pogroms. Microsoft provides the administrative tools to carry them out. Oracle provides the databases. Apple blocks apps that warn its customers when they're about to be snatched:

https://pluralistic.net/2025/10/06/rogue-capitalism/#orphaned-syrian-refugees-need-not-apply

In exchange, Trump got Canada and the UK to ditch their plans to levy a 3% tax on American tech giants; he got the EU to gut its privacy laws; he sanctioned EU officials who tried to regulate social media; and he's told the tech companies to go through EU officials' private messages, looking for anti-Big Tech partisans whom he will ban from ever entering the USA:

https://judiciary.house.gov/media/in-the-news/us-committee-demands-big-tech-share-private-comms-eu-officials

Big Tech has proved that its only principles are not paying taxes, invading your privacy, and not being broken up by antitrust enforcers:

https://arstechnica.com/gadgets/2026/09/us-court-rules-google-will-not-have-to-sell-ad-exchange-after-losing-antitrust-case/

Tech companies will do anything for any leader who can guarantee those outcomes. There's no capitulation too petty and stupid for Big Tech:

https://people.com/apple-maps-joins-google-approving-trump-lake-america-change-12074262

America no longer has allies or trading partners. America has rivals and enemies. Trump's coalition wants him to steal Iran, steal Venezuela, steal Cuba, steal Alberta, steal Canada, steal Greenland. They want him to help Israel steal Palestine and Lebanon. And as Trump considers this program of imperial conquest, he has started to tinker with one of the most devastating geopolitical weapons the world has ever seen: tech shutdowns.

If Trump wants Greenland, he can just order Microsoft to switch off Office 365 for the country and every ministry and significant firm will be shuttered in an instant, along with many households:

https://pluralistic.net/2026/04/04/digital-subjugation/#greenlands-next

He can order Apple and Google to shut off all of Denmark's phones. He can order John Deere to shut off all their tractors:

https://pluralistic.net/2022/05/08/about-those-kill-switched-ukrainian-tractors/

(One thing we don't need to worry about is Trump ordering OpenAI and Anthropic to switch off all of Europe's chatbots – sure, he could do that, but if he did, nothing important would break:)

https://pluralistic.net/2026/06/18/their-trillions-our-billions/#eyes-on-the-prize

As weapons of mass destruction go, nukes are pretty stupid. The big ones destroy the territory you're trying to conquer and leave behind an uninhabitable radioactive wasteland. They send clouds of nuclear fallout swirling around the globe, potentially killing you or your allies. 80 years into the Nuclear Age, the best anyone's come up with is a neutron bomb, which only kinda renders territory uninhabitable while still killing everyone with massive radiation blasts.

Compared to nukes, tech shutdowns are amazing. Thanks to Big Tech, America – and only America – can brick almost any country on earth, shutting down its administration, agriculture and industry without firing a single shot. The only thing that prevented this from happening was an American elite bloc that was playing an iterated game and saw more benefit from sharing in Big Tech profits as they looted and spied on the world, as opposed to grabbing territory while scaring the world into breaking all land-speed records to ditch American tech and pursue meaningful digital sovereignty.

Trump's chuds and freaks are not bound by these constraints. They're perfectly happy to do Gunboat Diplomacy 2.0: Cloud Diplomacy, where everything from your smartphones to your payroll records can be seized at the click of a mouse, and your country had better fall in line. And Trump is a sick, frail old man, who is not long for this world. When he goes, all bets are off: America will be at the mercy of warring factions who will deploy the coercion and bribery that turned Big Tech into Trump's geopolitical weapon in order to achieve their own purposes – which might well be even stupider, crueler and more unhinged than Trump's.

There's only one way out of this mess: the rapid disassembly of the American internet and the rapid creation of a post-American internet, one built on open, auditable, sovereign digital public goods, internationally built and maintained:

https://pluralistic.net/2026/01/01/39c3/#the-new-coalition

In its own way, the creation of this post-American internet is as urgent and as global as was the creation of the covid vaccines. But whenever I speak to powerful people about this, they ask the same question: "What if this makes Trump mad?"

This represents a grave failure to take this crisis seriously. Trump doesn't need to be "mad" to attack your country. Trump attacked Canada over its wildfires, accusing Canada of polluting America's air:

https://www.cbc.ca/news/politics/us-complaints-trump-widlfire-smoke-9.7274466

But even if Trump never gets mad at you, that's no guarantee of safety. Trump is not long for this world, and his death or incapacity is no guarantee of the restoration of a "normal" America. And even if America finds its way to "normal" after Trump, that's no guarantee that it will stay normal. The armed, organized maniacs who have seized power in America and who are cheering him on as he rampages all over the world, kidnapping leaders and dropping bombs on schoolchildren are not going to dig a hole, crawl inside it, and pull the dirt down on top of themselves.

But let's say that we find ourselves in the best of worlds, where American fascism is comprehensively defeated and the country embarks on a years-long program of denazification:

https://pluralistic.net/2026/02/10/miller-in-the-dock/#denazification

Even in that amazing future, the world should still race to build a post-American internet. The world should have built that internet after the Snowden revelations. That ghastly failure created the Trumpian internet. If the post-Trump internet isn't a post-American internet, then it'll only be a matter of time until the next crisis comes along, and the coming years will give Big Tech even more chances to worm its tendrils into the world's governments, firms and households, making that crisis be even harder to survive. The best time to act was 13 years ago, after Snowden. The second best time is now.


Hey look at this (permalink)



A shelf of leatherbound history books with a gilt-stamped series title, 'The World's Famous Events.'

Object permanence (permalink)

#25yrsago Barnum & Bailey hired an ex-CIA spook to destroy a critical journalist https://web.archive.org/web/20010913192931/http://www.salon.com/news/feature/2001/08/30/circus/print.html

#20yrsago Wired article about Wikipedia is on a editable wiki https://web.archive.org/web/20060901030941/http://www.socialtext.net/wired/index.cgi

#20yrsago Singapore will have nationwide WiFi by 2007 https://web.archive.org/web/20060901191656/http://news.com.com/2100-1039_3-6110189.html

#5yrsago Twitter Arguments https://pluralistic.net/2021/08/29/twitter-arguments/


Upcoming appearances (permalink)

A photo of me onstage, giving a speech, pounding the podium.



A screenshot of me at my desk, doing a livecast.

Recent appearances (permalink)



A grid of my books with Will Stahle covers..

Latest books (permalink)



A cardboard book box with the Macmillan logo.

Upcoming books (permalink)

  • "The Post-American Internet," a geopolitical sequel of sorts to Enshittification, Farrar, Straus and Giroux, 2027
  • "Unauthorized Bread": a middle-grades graphic novel adapted from my novella about refugees, toasters and DRM, FirstSecond, April 20, 2027

  • "Enshittification, Why Everything Suddenly Got Worse and What to Do About It" (the graphic novel), Firstsecond, 2027

  • "The Memex Method," Farrar, Straus, Giroux, 2027



Colophon (permalink)

Today's top sources:

Currently writing:

  • “Once Is Enemy Action,” a science fiction novel about the origins of modern technofascism. Today's words: 574 (7730 total).

  • "The Post-American Internet," a sequel to "Enshittification," about the better world the rest of us get to have now that Trump has torched America. Fourth draft completed. Submitted to editor.

  • A Little Brother short story about DIY insulin PLANNING


This work – excluding any serialized fiction – is licensed under a Creative Commons Attribution 4.0 license. That means you can use it any way you like, including commercially, provided that you attribute it to me, Cory Doctorow, and include a link to pluralistic.net.

https://creativecommons.org/licenses/by/4.0/

Quotations and images are not included in this license; they are included either under a limitation or exception to copyright, or on the basis of a separate license. Please exercise caution.


How to get Pluralistic:

Blog (no ads, tracking, or data-collection):

Pluralistic.net

Newsletter (no ads, tracking, or data-collection):

https://pluralistic.net/plura-list

Mastodon (no ads, tracking, or data-collection):

https://mamot.fr/@pluralistic

Bluesky (no ads, possible tracking and data-collection):

https://bsky.app/profile/doctorow.pluralistic.net

Medium (no ads, paywalled):

https://doctorow.medium.com/

Tumblr (mass-scale, unrestricted, third-party surveillance and advertising):

https://mostlysignssomeportents.tumblr.com/tagged/pluralistic

"When life gives you SARS, you make sarsaparilla" -Joey "Accordion Guy" DeVilla

READ CAREFULLY: By reading this, you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies ("BOGUS AGREEMENTS") that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer.

ISSN: 3066-764X

Pluralistic: Unpermissioned research (02 Sep 2026) [Pluralistic: Daily links from Cory Doctorow]

->->->->->->->->->->->->->->->->->->->->->->->->->->->->-> Top Sources: None -->

Today's links



A car's frosted-over back windscreen, being scraped by a person's hand holding an ice-scraper. The person has scraped a Canadian maple leaf into the windscreen. In the background we see the capitol dome and a depressed caricature of Uncle Sam holding a sign reading 'I am busted.'

Unpermissioned research (permalink)

After half a century of neoliberalism, we are all drenched in capitalism's established religion, the worship of property rights. We are so marinated in property worship that even capitalism's critics frame their critiques in "property talk," to the exclusion of other, more important rights, like human rights, labor rights and privacy rights.

To do this is to surrender before the battle even starts. Critics lose when they allow oligarchs and their apologists to choose a battlefield where they have a nearly unbeatable advantage.

Take privacy: privacy is a human right, not a property right. Human rights aren't for sale. You can't sell yourself into slavery, you can't sell your kidneys to make the rent. If privacy is a property right – one that can be traded away – then Facebook's industrial-scale privacy invasions are actually fine, since you "traded" your privacy to Mark Zuckerberg in exchange for the privilege of talking to your friends.

Some self-styled critics of tech monopolists say that the answer to Facebook's privacy invasions is to force the company to pay for your privacy with cash, rather than services:

https://www.wired.com/story/opinion-andrew-yangs-plan-to-pay-you-for-your-data-doesnt-add-up/

This is ideological capture in its purest form: the "data dividend" that Facebook would owe you under this system amounts to a few dollars per year. For wealthy people, the sums would be trivial, while working people, who've been on the downward leg of every K-shaped recovery for a quarter century, who've maxed out their credit cards and re-mortgaged their homes and drive Uber on the weekends to make rent, would have to subject themselves to ongoing surveillance.

That surveillance is already used to determine the highest price those working people will pay – companies like Plexure inform fast food places when you've just gotten paid so they can tack an extra dollar onto your breakfast burrito in the app:

https://pluralistic.net/2026/04/30/something-must-be-done/#there-ive-done-something

Being forced to sell your privacy doesn't just raise the prices you pay, it also lowers the wages you earn. The same people who can't afford this "pay or privacy" system have their private data used to calculate the lowest wage they'll accept for each ride on those weekend Uber shifts:

https://pluralistic.net/2024/12/18/loose-flapping-ends/#luigi-has-a-point

In other words: not being able to afford privacy will result in you having even less disposable income, which will mean that you'll have to sell even more of your privacy. Lather, rinse, repeat.

But even the wealthy people who can afford to forego the pittances Facebook and others offer in exchange for their private information will find privacy elusive. That's because private information isn't a "rival good" – a thing only one person can own at a time. The fact that your mother is your mother "belongs" to both you and her, as well as your grandparents, your father, your siblings and your kids. The fact that you don't sell your family tree to a tech company won't stop all those other people from selling it on – as anyone whose foolish relations handed their genome over to 23andme can attest:

https://www.npr.org/2025/03/24/nx-s1-5338622/23andme-bankruptcy-genetic-data-privacy

In the property religion, the way you can tell if something is valuable is if it has a high price. Property cultists insist that the problem with privacy is that our privacy is being sold too cheaply. They're wrong: private information isn't "mispriced" – it shouldn't be priced.

Human beings are the most valuable things in our world and they are literally priceless. Murder isn't "theft of life." Rape isn't "theft of sex." While insurers and civil courts have ways of calculating the "price" of an injury or violation, great care has been taken over the centuries to ensure that this does not turn human beings into commodities. You can't buy a "murder offset" that lets you kill people provided you pay into a fund that saves a human somewhere else:

https://pluralistic.net/2021/04/14/for-sale-green-indulgences/#killer-analogy

Human beings are too valuable to be priced. We have an entire, sui generis way of balancing the conflicting interests of human rights. My daughter and wife have rights over me, I have rights over them, and when those rights come into conflict – say, if my daughter believes I can no longer care for myself and wants to put me in a care home – the process for resolving that conflict isn't an auction:

https://www.theguardian.com/technology/2008/feb/21/intellectual.property

Your kids aren't your property. In fact, all the most important relationships in your life are non-market. Doctors have patients, not customers. Any time a doctor calls you a "customer" they are demoting you. A doctor doesn't sell you health. You have rights as a patient that far exceed the rights accruing to a mere customer. Same goes for other professions: Teachers have pupils, librarians have patrons, lawyers have clients. "Customer" is a demotion from all of these.

As every "user agreement" you've ever clicked through demonstrates, Big Tech loves to have everything defined in property terms – and so does all big business.

Take the fight over scraping for AI. You might think that this is a fight over the economic rights of creative workers – certainly, my fellow creative workers treat it as such. But because this debate is being framed in terms of property rights, rather than labor rights, this is a fight that workers are set up to lose.

The tell here is how the media companies – who have been eroding the wages of creative workers for decades as they consolidated into a curdled, inbred oligopoly – describe the AI companies' scraping: as an unlicensed taking. Mitch Glazier, the $1.4m/year CEO of the Recording Industry Association of America issues press releases decrying AI training for image generators without negotiating a license fee first:

https://pluralistic.net/2026/03/03/its-a-trap-2/#inheres-at-the-moment-of-fixation

Who's Mitch Glazier? Oh, just a former Congressional staffer who was drummed out of the Capitol Building after he snuck a clause into must-pass legislation that would have transferred hundreds of millions of dollars from musicians to record labels, who was then immediately hired as the CEO of the record industry's largest lobbying group:

https://www.eff.org/deeplinks/2013/12/tpps-attack-artists-termination-rights

Mitch Glazier – and the businesses he represents – aren't opposed to AI replacing artists. They're opposed to AI replacing media companies. Remember the Hollywood writers' strike? The proposal to replace screenwriters with chatbots didn't come from OpenAI, it came from Disney, Warner, Universal and other companies who claim that AI training is "theft."

If AI training is "theft," then it can be cured by making a purchase, something that the AI companies can easily afford, thanks to the hundreds of billions of dollars they have been given by the world's richest investors, who are the high priests and cardinals of the property religion.

The Hollywood writers are the only workers in the world who have successfully beaten back the use of AI in their workplace, and they didn't do it by making recourse to property rights. The Writers Guild is a union and it enjoys a weak form of "sectoral bargaining" (where all the workers in a field bargain with all the businesses at once) called "multi-employer bargaining":

https://pluralistic.net/2023/10/01/how-the-writers-guild-sunk-ais-ship/

The Hollywood writers' strike was an unqualified victory for the writers, who defended their labor rights to co-determination when it came to the use of new tools on their jobsite. Under the terms of their hard-fought contract, screenwriters don't have to use AI, but they can if they want. For example, writers on a long-running sitcom might train an AI with every script in the series' history, so they can ask a chatbot continuity questions as they beat out a new season of the show. But they don't have to do this if they don't want to, and even if they do, neither their wages nor their headcount can be reduced.

The media companies insist that scraping is a copyright violation, that it's "theft." As a matter of law, this is far from obvious or settled: the process of making transient copies of many works, performing mathematical analysis on them, and then publishing that analysis as software is not obviously a copyright violation, and anyone who claims otherwise doesn't understand copyright:

https://pluralistic.net/2023/02/09/ai-monkeys-paw/#bullied-schoolkids

Worse: by demoting a labor rights issue to a mere property rights issue, AI critics are setting workers up to fail. Say the issue with AI training really is mere copyright. If that's so, the media companies who want nothing better than to pauperize creative workers can amend their standard contracts so that any worker who does business with them must irrevocably transfer their "AI training rights" to the company.

Then, that company will absolutely, 100% license those rights to an AI company to create a model designed to replace that worker. The company will get paid for the training, and the resulting model will come with "guardrails" to stop other media companies from using proprietary data to compete with it.

This is the story of the past 50 years of copyright expansion: every new copyright we've created "to help artists" was scooped up by their bosses, who grew more powerful and were able to demand more concessions from those artists, who were therefore poorer and thus needed more copyrights to help them (lather, rinse, repeat):

https://pluralistic.net/2026/08/18/enron-corpus/#sign-here

If creative workers' AI fight is merely a copyright fight, then that fight can only determine whether media companies or tech companies will get the biggest portion when those workers are devoured by corporations. Only a labor rights fight can take creative workers off the menu altogether.

Treating AI training as "theft" creates harms whose blast radius extends well beyond creative workers' livelihoods. Scraping is a hugely beneficial activity. If scraping – taking a vast corpus of copyrighted works without permission – is theft, then every search engine is a crime, unless it can afford to license "search indexing rights" from every site on the internet.

There's exactly one company that could pull that off: Google, a rapacious tech monopolist that is – not coincidentally – one of the leaders of the movement to beggar every creative worker. We will not improve the world, the internet, or creative workers' lives by ensuring that the last search engine anyone ever creates is Google.

Remember our earlier discussion of how privacy violations are weaponized to make poor people even poorer, by depressing their wages and raising prices based on inferences about their economic desperation? Our best weapon for fighting this practice is scraping, because that's how we catch corporations changing prices and wages based on surveillance data:

https://pluralistic.net/2023/09/17/how-to-think-about-scraping/

Scraping is how we produce evidence of the changes that powerful people are making to the world around us. Do you want to know whether Mark Zuckerberg or Elon Musk are downranking content critical of Trump and Big Tech and pumping racist and conspiratorial posts into the resulting void? You'd better hope you can scrape the feeds they cram into billions of people's eyeballs. Same goes for keeping track of genocide apologists, data-center astroturfers and ICE cheerleaders who've flooded Tiktok ever since Trump stole it and handed it over to his creepy billionaire pal Larry Ellison.

Making copies of that stuff isn't theft. It's not a copyright violation. Not even if you do it to billions of works. Not even if it's bad for the companies whose feeds you're capturing. Not even if it's bad for the dark money groups who funded the content.

Sure, if you do this carelessly or recklessly, you can end up violating someone's labor rights, or privacy rights, or human rights. And because those frameworks aren't based on the sanctity of property rights, they can be used to protect these important rights without giving corporate America the right to have you fined or arrested for documenting their takeover of the America.

The people who keep track of this stuff are worried about being fined or arrested. Ethan Zuckerman, one of America's foundational internet scholars, has just accepted Canadian government funding to move his lab from UMass to McGill in Montreal:

https://ethanzuckerman.com/2026/08/27/my-personal-contribution-to-the-us-canada-trade-war/

Zuckerman studies platform power: "using data to answer hard questions about social media, search engines and AI tools." He leads a team that is documenting exactly, precisely how tech companies collude with authoritarians to spy on us, manipulate us, and control us. And his methodology is something called "unpermissioned research," which is what academics call scraping:

https://www.techpolicy.press/ai-companies-threaten-independent-social-media-research/

"Unpermissioned research" seeks to circumvent limits that platforms establish specifically to stop outsiders from learning how they operate. When you're doing unpermissioned research, you try to get around rate limits, query throttles, and other measures that platforms use to block others from mapping their extent and documenting their conduct.

"Unpermissioned research" isn't a free-for-all. Universities have ethical rules designed to protect the privacy rights and other human rights of research subjects, and because these aren't property rights, they can be balanced against the socially beneficial outcomes of research. Universities can get this wrong, of course, but when they do, it's not theft. It's a human rights violation, a privacy violation, a labor violation.

If you want to know how AI companies are trying to destroy creators' livelihoods, you have to scrape the AI companies. You can't ask companies for permission to gather information that might be used to destroy them – they'll just say no. If taking information off the internet without permission is "theft," then gathering information by scraping AI companies is also theft.

Sometimes a tech company will set up a "research portal" that supposedly obviates the need to scrape by putting all the relevant information in one convenient place. That's what Facebook did in the wake of the 2016 election, when it was widely condemned for publishing paid political disinformation. But Facebook's official research portal omitted vast amounts of paid political disinformation, something we only know because NYU set up a scraping project called Ad Observer that documented the discrepancy:

https://pluralistic.net/2021/08/06/get-you-coming-and-going/#potemkin-research-program

Facebook used legal threats to kill Ad Observer, and then…they killed their official research portal, too:

https://pluralistic.net/2021/07/15/three-wise-zucks-in-a-trenchcoat/#inconvenient-truth

Zuckerman is one of dozens of leading US academics who are relocating their labs and teams to Canadian universities, citing fear of political interference from the Trump regime:

https://vancouver.citynews.ca/2026/08/27/canada-recruits-dozens-of-foreign-scientists-researchers-poaching-many-from-u-s/

The Canadian government has committed $504m to the project. Some of that research will help Canada develop new green energy, and some of it will help Canada make important medical breakthroughs. But Zuckerman's research has a special place in the portfolio of Canadian research projects, because – thanks to scraping – it is a leading source of information about how Trump's tech companies are waging war on the American people and the world.

Scraping isn't theft of data, just like murder isn't theft of life. Scraping can be harmful, and we can create laws and social regimes and ways of talking about those harms that don't give authoritarian governments and vast multinational corporations the right to decide who can document and analyze their conduct.

Take Wikipedia: the project exists solely to organize and disseminate information, for free, to everyone in the world. Wikipedia is among the most important parts of the internet, and one of the most positive developments of the 21st century. The entire project is licensed under a generous Creative Commons license that encourages unlimited commercial re-use of its contents. Even if you think scraping copyrighted works is theft, scraping Creative Commons Attribution 4.0 works is unquestionably not theft.

But Wikipedia is being hammered by AI scrapers, which are operating so aggressively that they threaten the project's ability to keep its servers online. Wikipedia has an AI problem, but that AI problem isn't "theft" – it's denial of service, the aggressive act of intentionally or recklessly flooding a server with so much traffic that it crashes.

If you've been lured into a cultlike worship of property rights, this seems like a contradiction. But once you relegate the relatively unimportant matter of property rights to its correct station, you can see – and reason about – the universe of rights that are far more important than mere property.

All it takes is realizing that there are far worse things you can do with information than "stealing" it.

(Image: Bearas, CC BY-SA 4.0, modified)


Hey look at this (permalink)



A shelf of leatherbound history books with a gilt-stamped series title, 'The World's Famous Events.'

Object permanence (permalink)

#25yrsago NYT says ebooks don't exist, fails to mention thriving ebook pirate scene https://www.nytimes.com/2001/08/28/business/forecasts-of-an-e-book-era-were-it-seems-premature.html

#25yrsago Parking tickets waived in exchange for written apologies https://web.archive.org/web/20010826013513/http://www.thesmokinggun.com/doc_o_day/lewiston1.shtml

#20yrsago "I, Row-Boat" https://web.archive.org/web/20060000000000*/http://www.flurb.net/1/doctorow.htm

#20yrsago Filipino students use SMS to organize mass demonstrations https://web.archive.org/web/20060902160514/http://blog.wired.com/sterling/index.blog%3Fentry_id%3D1545927

#20yrsago Spam pump-and-dumps work http://news.bbc.co.uk/2/hi/technology/5284618.stm

#25yrsago Leaked: Handspring's next PalmOS device https://web.archive.org/web/20020824213501/http://www.palmstation.com/view_article.asp?article=4614

#15yrsago “Stalwart Workers”: neglected backbone of the firm https://web.archive.org/web/20110920155246/http://blogs.hbr.org/hbsfaculty/2011/08/stop-ignoring-the-stalwart-wor.html

#5yrsago Facebook's war on switching costs https://pluralistic.net/2021/08/28/talking-hard-work-blues/#hostage-takers

#5yrsago The "work ethic" is a dirty trick we play on ourselves https://pluralistic.net/2021/08/28/talking-hard-work-blues/#work-will-set-you-free

#1yrago The capitalism of fools https://pluralistic.net/2025/08/28/strew-deal/#neither-fish-nor-fowla


Upcoming appearances (permalink)

A photo of me onstage, giving a speech, pounding the podium.



A screenshot of me at my desk, doing a livecast.

Recent appearances (permalink)



A grid of my books with Will Stahle covers..

Latest books (permalink)



A cardboard book box with the Macmillan logo.

Upcoming books (permalink)

  • "The Post-American Internet," a geopolitical sequel of sorts to Enshittification, Farrar, Straus and Giroux, 2027
  • "Unauthorized Bread": a middle-grades graphic novel adapted from my novella about refugees, toasters and DRM, FirstSecond, April 20, 2027

  • "Enshittification, Why Everything Suddenly Got Worse and What to Do About It" (the graphic novel), Firstsecond, 2027

  • "The Memex Method," Farrar, Straus, Giroux, 2027



Colophon (permalink)

Today's top sources:

Currently writing:

  • “Once Is Enemy Action,” a science fiction novel about the origins of modern technofascism. Today's words: 527 (10843 total).

  • "The Post-American Internet," a sequel to "Enshittification," about the better world the rest of us get to have now that Trump has torched America. Fourth draft completed. Submitted to editor.

  • A Little Brother short story about DIY insulin PLANNING


This work – excluding any serialized fiction – is licensed under a Creative Commons Attribution 4.0 license. That means you can use it any way you like, including commercially, provided that you attribute it to me, Cory Doctorow, and include a link to pluralistic.net.

https://creativecommons.org/licenses/by/4.0/

Quotations and images are not included in this license; they are included either under a limitation or exception to copyright, or on the basis of a separate license. Please exercise caution.


How to get Pluralistic:

Blog (no ads, tracking, or data-collection):

Pluralistic.net

Newsletter (no ads, tracking, or data-collection):

https://pluralistic.net/plura-list

Mastodon (no ads, tracking, or data-collection):

https://mamot.fr/@pluralistic

Bluesky (no ads, possible tracking and data-collection):

https://bsky.app/profile/doctorow.pluralistic.net

Medium (no ads, paywalled):

https://doctorow.medium.com/

Tumblr (mass-scale, unrestricted, third-party surveillance and advertising):

https://mostlysignssomeportents.tumblr.com/tagged/pluralistic

"When life gives you SARS, you make sarsaparilla" -Joey "Accordion Guy" DeVilla

READ CAREFULLY: By reading this, you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies ("BOGUS AGREEMENTS") that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer.

ISSN: 3066-764X

Feeds

FeedRSSLast fetchedNext fetched after
@ASmartBear XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
a bag of four grapes XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
Ansible XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
Bad Science XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
Black Doggerel XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
Blog - Official site of Stephen Fry XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
Charlie Brooker | The Guardian XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
Charlie's Diary XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
Chasing the Sunset - Comics Only XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
Coding Horror XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
Comics Archive - Spinnyverse XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
Cory Doctorow's craphound.com XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
Cory Doctorow, Author at Boing Boing XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
Ctrl+Alt+Del Comic XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
Cyberunions XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
David Mitchell | The Guardian XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
Deeplinks XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
Diesel Sweeties webcomic by rstevens XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
Dilbert XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
Dork Tower XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
Economics from the Top Down XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
Edmund Finney's Quest to Find the Meaning of Life XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
EFF Action Center XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
Enspiral Tales - Medium XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
Events XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
Falkvinge on Liberty XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
Flipside XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
Flipside XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
Free software jobs XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
Full Frontal Nerdity by Aaron Williams XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
General Protection Fault: Comic Updates XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
George Monbiot XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
Girl Genius XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
Groklaw XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
Grrl Power XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
Hackney Anarchist Group XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
Hackney Solidarity Network XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
http://blog.llvm.org/feeds/posts/default XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
http://calendar.google.com/calendar/feeds/q7s5o02sj8hcam52hutbcofoo4%40group.calendar.google.com/public/basic XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
http://dynamic.boingboing.net/cgi-bin/mt/mt-cp.cgi?__mode=feed&_type=posts&blog_id=1&id=1 XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
http://eng.anarchoblogs.org/feed/atom/ XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
http://feed43.com/3874015735218037.xml XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
http://flatearthnews.net/flatearthnews.net/blogfeed XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
http://fulltextrssfeed.com/ XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
http://london.indymedia.org/articles.rss XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
http://pipes.yahoo.com/pipes/pipe.run?_id=ad0530218c055aa302f7e0e84d5d6515&amp;_render=rss XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
http://planet.gridpp.ac.uk/atom.xml XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
http://shirky.com/weblog/feed/atom/ XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
http://thecommune.co.uk/feed/ XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
http://theness.com/roguesgallery/feed/ XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
http://www.airshipentertainment.com/buck/buckcomic/buck.rss XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
http://www.airshipentertainment.com/growf/growfcomic/growf.rss XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
http://www.airshipentertainment.com/myth/mythcomic/myth.rss XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
http://www.feedsapi.com/makefulltextfeed.php?url=http%3A%2F%2Fwww.somethingpositive.net%2Fsp.xml&what=auto&key=&max=7&links=preserve&exc=&privacy=I+accept XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
http://www.godhatesastronauts.com/feed/ XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
http://www.tinycat.co.uk/feed/ XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
https://anarchism.pageabode.com/blogs/anarcho/feed/ XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
https://broodhollow.krisstraub.comfeed/ XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
https://debian-administration.org/atom.xml XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
https://elitetheatre.org/ XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
https://feeds.feedburner.com/Starslip XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
https://feeds2.feedburner.com/GeekEtiquette?format=xml XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
https://hackbloc.org/rss.xml XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
https://kajafoglio.livejournal.com/data/atom/ XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
https://philfoglio.livejournal.com/data/atom/ XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
https://pixietrixcomix.com/eerie-cutiescomic.rss XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
https://pixietrixcomix.com/menage-a-3/comic.rss XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
https://propertyistheft.wordpress.com/feed/ XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
https://requiem.seraph-inn.com/updates.rss XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
https://studiofoglio.livejournal.com/data/atom/ XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
https://thecommandline.net/feed/ XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
https://torrentfreak.com/subscriptions/ XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
https://web.randi.org/?format=feed&type=rss XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
https://www.baen.com/baenebooks XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
https://www.dcscience.net/feed/medium.co XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
https://www.DropCatch.com/domain/steampunkmagazine.com XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
https://www.DropCatch.com/domain/ubuntuweblogs.org XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
https://www.DropCatch.com/redirect/?domain=DyingAlone.net XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
https://www.freedompress.org.uk:443/news/feed/ XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
https://www.goblinscomic.com/category/comics/feed/ XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
https://www.loomio.com/blog/feed/ XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
https://www.newstatesman.com/feeds/blogs/laurie-penny.rss XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
https://www.patreon.com/graveyardgreg/posts/comic.rss XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
https://www.rightmove.co.uk/rss/property-for-sale/find.html?locationIdentifier=REGION^876&maxPrice=240000&minBedrooms=2&displayPropertyType=houses&oldDisplayPropertyType=houses&primaryDisplayPropertyType=houses&oldPrimaryDisplayPropertyType=houses&numberOfPropertiesPerPage=24 XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
https://x.com/statuses/user_timeline/22724360.rss XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
Humble Bundle Blog XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
I, Cringely XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
Irregular Webcomic! XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
Joel on Software XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
Judith Proctor's Journal XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
Krebs on Security XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
Lambda the Ultimate - Programming Languages Weblog XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
Looking For Group XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
LWN.net XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
Mimi and Eunice XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
Neil Gaiman's Journal XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
Nina Paley XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
O Abnormal – Scifi/Fantasy Artist XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
Oglaf! -- Comics. Often dirty. XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
Oh Joy Sex Toy XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
Order of the Stick XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
Original Fiction Archives - Reactor XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
OSnews XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
Paul Graham: Unofficial RSS Feed XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
Penny Arcade XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
Penny Red XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
PHD Comics XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
Phil's blog XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
Planet Debian XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
Planet GNU XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
Planet Lisp XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
Pluralistic: Daily links from Cory Doctorow XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
PS238 by Aaron Williams XML 05:28, Saturday, 05 September 06:16, Saturday, 05 September
QC RSS v2 XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
Radar XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
RevK®'s ramblings XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
Richard Stallman's Political Notes XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
Scenes From A Multiverse XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
Schneier on Security XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
SCHNEWS.ORG.UK XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
Scripting News XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
Seth's Blog XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
Skin Horse XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
Tales From the Riverbank XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
The Adventures of Dr. McNinja XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
The Bumpycat sat on the mat XML 05:07, Saturday, 05 September 05:47, Saturday, 05 September
The Daily WTF XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
The Monochrome Mob XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
The Non-Adventures of Wonderella XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
The Old New Thing XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
The Open Source Grid Engine Blog XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
The Stranger XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
towerhamletsalarm XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
Twokinds XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
UK Indymedia Features XML 05:21, Saturday, 05 September 06:03, Saturday, 05 September
Uploads from ne11y XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
Uploads from piasladic XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September
Use Sword on Monster XML 05:28, Saturday, 05 September 06:15, Saturday, 05 September
Wayward Sons: Legends - Sci-Fi Full Page Webcomic - Updates Daily XML 04:56, Saturday, 05 September 05:42, Saturday, 05 September
what if? XML 05:07, Saturday, 05 September 05:48, Saturday, 05 September
Whatever XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
Whitechapel Anarchist Group XML 05:35, Saturday, 05 September 06:24, Saturday, 05 September
WIL WHEATON dot NET XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
wish XML 05:00, Saturday, 05 September 05:45, Saturday, 05 September
Writing the Bright Fantastic XML 05:00, Saturday, 05 September 05:44, Saturday, 05 September
xkcd.com XML 05:00, Saturday, 05 September 05:43, Saturday, 05 September