Shellsharks Blogroll - BlogFlock 2026-04-30T11:57:01.801Z BlogFlock Adepts of 0xCC, destructured, fLaMEd, Trail of Bits Blog, Aaron Parecki, Westenberg, James' Coffee Blog, gynvael.coldwind//vx.log (pl), joelchrono, Evan Boehs, cool-as-heck, Kev Quirk, Posts feed, Sophie Koonin, <span>Songs</span> on the Security of Networks, cmdr-nova@internet:~$, Werd I/O, Johnny.Decimal, Robb Knight, Molly White, Hey, it's Jason!, Terence Eden’s Blog Published on Citation Needed: "President Trump’s $TRUMP memecoin is preparing to launch a “Coin Club” membership scheme" - Molly White's activity feed 69f290ee2c82a908e0f06023 2026-04-29T23:14:54.000Z <article class="entry h-entry hentry"><header><div class="description">Published an issue of <a href="https://www.citationneeded.news/"><i>Citation Needed</i></a>: </div><h2 class="p-name"><a class="u-syndication" href="https://www.citationneeded.news/trump-coin-club" rel="syndication">President Trump’s $TRUMP memecoin is preparing to launch a “Coin Club” membership scheme </a></h2></header><div class="content e-content"><div class="media-wrapper"><a href="https://www.citationneeded.news/trump-coin-club"><img src="https://www.citationneeded.news/content/images/size/w1200/format/webp/2026/04/trump-coin-club.png" alt="Members only • Limited access $TRUMP Coin Club - invitation-only luxury suites at the biggest sporting events in the world, private dinners, and the most elite and extraordinary experiences. Get on the list apply now"/></a></div><div class="p-summary"><p>The website promises “elite and extraordinary experiences” as part of the newest scheme to revive a token that’s down 97% from its peak and still falling.</p></div></div><footer class="footer"><div class="flex-row post-meta"><div class="timestamp">Posted: <a class="u-url" href="https://www.citationneeded.news/trump-coin-club"><time class="dt-published" datetime="2026-04-29T23:14:54+00:00" title="April 29, 2026 at 11:14 PM UTC">April 29, 2026 at 11:14 PM UTC</time>. </a></div><div class="social-links"> <span>Also posted to:</span><a class="social-link u-syndication mastodon" href="https://hachyderm.io/@molly0xfff/116490510315315421" title="Mastodon" rel="syndication">Mastodon</a><a class="social-link u-syndication bluesky" href="https://bsky.app/profile/molly.wiki/post/3mko7smlw3c24" title="Bluesky" rel="syndication">Bluesky</a></div></div><div class="bottomRow"><div class="tags">Tagged: <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/crypto" title="See all feed posts tagged "crypto"" rel="category tag">crypto</a>, <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/donald_trump" title="See all feed posts tagged "Donald Trump"" rel="category tag">Donald Trump</a>.</div></div></footer></article> Building with love, and paying for it - Werd I/O 69f28585825c3600019fc9a5 2026-04-29T22:31:50.000Z <img src="https://storage.ghost.io/c/18/7c/187cc681-d3f3-49fc-87de-b01d06b76821/content/images/2026/04/getty-images-_jv6aqe6DOQ-unsplash-1.png" alt="Building with love, and paying for it"><p><em>A quick note before this one: this post isn&#x2019;t intended as commentary on any internal conversations at ProPublica. We care a lot about sustainability, fundraising, and memberships! But this piece has a broader focus.</em></p><p>I remember the comment like it was yesterday. The social networking platform I was building had already been used by major non-profits, universities, Fortune 500 companies, and even governments. It was created in the public interest and distributed in such a way &#x2014; under an open source license, with accessible code &#x2014; that anyone could pick it up and use it. And we dared to think about an underlying business model.</p><p>&#x201C;Nobody pays for open source,&#x201D; the comment read. &#x201C;You should do this for the love of it.&#x201D;</p><p>I was aghast. I <em>was</em> doing it for love! I could have been paid an order of magnitude more money if I&#x2019;d made a career in big tech. Public interest technology was not a choice I made for glory or riches.</p><p>&#x201C;Can I buy food with love?&#x201D; I asked my cofounder.</p><p>He shook his head (and maybe mentally rolled his eyes). The answer was, no. I could not.</p><h3 id="the-funding-problem">The funding problem</h3><p>Everyone who&#x2019;s building something, even if it&#x2019;s in the public interest, needs to find a way to make it sustainable, both as a project and for themselves. That means, as much as some of us might hate it, we have to talk about money sometimes.</p><p>I&#x2019;ve worked in public interest tech and public interest media. It turns out they both have the same funding problem: they&#x2019;re doing something good that makes an impact, and putting it out into the world for free. There&#x2019;s no paywall or subscription fee for the core product. That means finding funding for it is an uphill battle. Versions of the same conversation are happening in both communities, in spaces like <a href="https://atmosphereconf.org/?ref=werd.io">Atmosphere Conf</a>, the <a href="https://ona26.journalists.org/?ref=werd.io">Online News Association Conference</a>, at <a href="https://fediforum.org/?ref=werd.io">FediForum</a>, and online.</p><p>Public interest media has a stronger funding stack: donors and foundations with fixed theses. Support for public interest tech is much thinner. But even this media funding is primarily aimed at the big players; startup newsrooms have a much harder time finding funding. Elizabeth Hansen Shapiro&#x2019;s <a href="https://mediaimpactfunders.org/resources/rebuilding-local-journalism-at-scale-a-field-level-analysis-of-infrastructure-needs/?ref=werd.io">analysis of media impact funders</a>, widely-circulated in the industry, made a recommendation that <a href="https://dicktofel.substack.com/p/learning-from-the-press-forward-infrastructure?ref=werd.io">she characterized to Dick Tofel this way</a>:</p><blockquote>[We need to] really take stock of what are the solutions that are out there that are working, that are ready to scale, that have a track record or that we have some confidence could grow into next generation field infrastructure, and then we basically pick winners.</blockquote><p>The report is an important public good in itself, and <a href="https://mediaimpactfunders.org/a-field-level-view-of-local-journalism-infrastructure/?ref=werd.io">its core recommendation to build shared infrastructure for news</a> is vital. But it&#x2019;s also important to consider what happens if you&#x2019;re not one of the winners that funders pick. It&#x2019;s not that funders should fund <em>everyone</em> &#x2014; that&#x2019;s obviously not tenable. But there&#x2019;s a real risk that picking winners starves the experimental edges where new models actually emerge. Given that some of the most interesting startup local newsrooms and infrastructure tend to be more representative than incumbents, reaching underserved markets and perspectives that might not fit within a funder&#x2019;s worldview, there&#x2019;s a real potential gap.</p><p>The same dynamics are at play in public interest tech. Social media platforms like X have become less safe for people from vulnerable communities. As a direct result, many people have fled to platforms like Mastodon where they can have smaller, more controllable networks that lead to safer spaces to find likeminded people and have conversations with them. There are a great many Mastodon instances specifically provided for communities that might be under threat elsewhere. Mastodon has become infrastructure used by millions of people, including journalists and at-risk communities.</p><p>And it has very little money. There is some grant funding here and there, and some revenue trickling in from its services operation. But institutional funders have bypassed it, and <a href="https://joinmastodon.org/sponsors?ref=werd.io">the donors page is thin</a> given the level of use it receives. 2024 was a transformative year, and it received &#x20AC;2.2M &#x2014; up from &#x20AC;545k the previous year. That new revenue largely came from <a href="https://blog.codinghorror.com/?ref=werd.io">Jeff Atwood</a>, cofounder of Stack Exchange. Those millions of users are served by six members of staff and a network of volunteers. That funding was great, but such a dependence on major donors is always an existential risk: there is no guarantee they will continue to give.</p><p>Meanwhile, Bluesky PBC is often put in the same category as Mastodon but is different in important respects; for one thing, while Mastodon is a non-profit, Bluesky is venture-funded. To date, it <a href="https://bsky.social/about/blog/03-19-2026-series-b?ref=werd.io">has raised over $123M</a> across three funding rounds in order to build and grow its platform, based on the decentralized AT Protocol. That might seem like a counter-example, but that funding was largely predicated on the Bluesky network&#x2019;s potential scale and its position as the custodian of AT Protocol; other companies who are actually building on that protocol, in that ecosystem, are having a very hard time finding funding. Even if Bluesky PBC funds some of them, that&#x2019;s another dependence: a financial form of centralization that puts their future sustainability at risk if Bluesky itself ever goes away or pivots. Bluesky has its own goals, and its own investors who will seek a financial return.</p><p>Many newsrooms, of course, are in exactly the same place: dependence on a small number of major funders who, as we&#x2019;ve heard, increasingly are being encouraged to pick winners and consolidate on them. And open source software and news share a major characteristic: they&#x2019;re freely available and very few people want to pay to support them.</p><p>For public interest innovators, I think there are two related questions to answer:</p><ul><li>How can this risky dependence on a few large funders be reduced?</li><li>How can more money be brought into the ecosystem overall?</li></ul><p>These imply a third, prerequisite question, whether for a newsroom or public interest tech:</p><ul><li>What is its real value to its community?</li></ul><h3 id="optimizing-your-ask-or-growing-the-base">Optimizing your ask or growing the base</h3><p>Increasing the funding that comes from small donors or customers can both make an initiative less dependent on big donors <em>and</em> bring in money that was otherwise unclaimed. But to do that, we need to take something that people have been reluctant to pay for and figure out what is valuable enough to them that they might.</p><p>If a public interest innovator with an established community &#x2014; Mastodon, people building on AT Protocol, local newsrooms &#x2014; wants to raise money quickly, it has two fundraising concentrations to choose from. It can either find a lot more people to bring into its community, some of whom will hopefully pay (assuming it has an established way for someone to do that); or it can look at its <em>existing</em> community, people who are already committed and loyal, and figure out how to more effectively ask <em>them</em> for money.</p><p>Of course, a thriving organization should be doing both, but if you&#x2019;re resource-strapped, you can probably only concentrate on one. So where to begin?</p><p>If you increase the base, you get more people in the door. But if you haven&#x2019;t optimized how you ask people for money, you&#x2019;re leaving increasingly larger amounts of money on the table. It&#x2019;s also potentially a slower burn to bring lots more people in than to get to know your existing community better. I think starting there &#x2014; optimizing your ask for your existing community &#x2014; is the right first move for anyone on a restricted budget. Today, <a href="https://joinmastodon.org/reports/Mastodon%20Annual%20Report%202024.pdf?ref=werd.io">fewer than 1% of Mastodon users donate</a>. Increasing that number to 5% would exceed the entirety of its 2024 revenue. By way of comparison, <a href="https://current.org/2017/09/with-new-app-a-startup-wants-to-make-donating-to-public-radio-easy/?ref=werd.io">around 10% of public radio listeners donate</a>. Public radio has far more mature fundraising expectations and infrastructure, but the potential is there.</p><p>To optimize the ask, you need to understand what the value is to your community to begin with. Here&#x2019;s the thing that&#x2019;s sometimes difficult to accept: the reason they&#x2019;re there may be substantially different from the reason you built it to begin with.</p><p>A non-profit newsroom may have been established to publish pointed investigative journalism that couldn&#x2019;t find a home elsewhere. And that work is clearly core to its existence. But it&#x2019;s possible that people are driven to donate, and excited about promoting it, not so much of the journalism as such but because of the cathartic feeling that someone is <em>doing something</em> in a world where they feel powerless. The journalism is the &#x201C;how&#x201D;, but the driving &#x201C;why&#x201D; for them is to feel like they&#x2019;re punching up. As a result, while asking people for money to keep doing journalism might yield some donors, asking people for money to keep holding the powerful to account, or to speak up for an underheard community that doesn&#x2019;t feel like it has a voice, is likely to yield more.</p><p>This idea also applies for public interest tech. The people <em>building</em> Bluesky might be excited to be creating a decentralized protocol and an open source platform, but it&#x2019;s not a given that the people already <em>using</em> Bluesky care all that much about that. For them, it might be more important that there&#x2019;s a real alternative to big tech platforms. The Mastodon team might be excited to build a federated platform using open source principles, but Mastodon <em>users</em> might feel more invested in the idea that their social channels are independent from US interests.</p><p>The truth is, you don&#x2019;t know until you ask them. Tech has promoted the idea that you should statistically instrument everything and survey your users at scale; this is useful beyond a certain community size, but it doesn&#x2019;t capture the stories of the people in the community who love what you&#x2019;re doing. Particularly when you&#x2019;re small, the biggest thing you can do is get on the phone and get to know members of your community, 1:1, conversationally. Understanding your community and optimizing your ask means doing a lot of human-scale research and gathering the points of view of people who care about you. It&#x2019;s never &#x201C;would you pay for this?&#x201D;; it&#x2019;s &#x201C;why are you here?&#x201D;</p><p>And it turns out that&#x2019;s <em>also</em> important for widening the base. Once you&#x2019;ve optimized the ask by understanding your community, you can use those same insights to improve your messaging and optimize your value to people who haven&#x2019;t joined your community yet, too.</p><p>None of this absolves you from creating an amazing product. You do that with an adjacent skill: figuring out what your community really needs and providing it better than anyone else. The newsroom actually has to do great journalism that makes the impact it claims to. Your public interest tech platform has to be a better solution for the people that use it to the alternative. But the way it <em>emotionally</em> lands is important: it&#x2019;s how you ask for money more effectively.</p><p>If you&#x2019;re solving a real problem for real people well, connecting to their actual needs, and landing with them emotionally in a way that makes them want to support and promote your work, and if you&#x2019;re making impact while doing so, that will also do work towards attracting those larger, institutional funders and prove that your ecosystem is worth supporting. It won&#x2019;t solve the problem on its own: there needs to be both outreach and institutional reform. But it will certainly help tune a project&#x2019;s storytelling for funders.</p><p>The onus shouldn&#x2019;t just be on innovators. Funders can and should do work here too: by providing more resources to help public interest innovators to connect with their communities and do this human-centered work, they can increase their impact and broaden the collection of initiatives they could potentially support. If they&#x2019;re picking winners, they need to continually interrogate what a &#x201C;winner&#x201D; actually is, and which communities they&#x2019;re learning from. Otherwise they will pick solutions from the same old communities and innovators, leaving other communities that could really use their help unaddressed.</p><h3 id="buying-food-with-love">Buying food with love</h3><p>When my cofounder and I were asked to do our work for the love of it, we had three weeks of funding left. The situation was getting dire.</p><p>We could easily have given up, but that&#x2019;s not what we did. Instead, we reached out to people in the community who had picked up our software and really got to understand them. (Quickly. Money was running out.)</p><p>Our ambitions &#x2014; decentralized social networking, not unlike Mastodon&#x2019;s today &#x2014; were not important for our community. The technical ideology of our work mattered for us, but not for them. What they <em>did</em> want to do was create safe spaces to learn from each other. And that&#x2019;s what we doubled down on.</p><p>From that low point, our conversations helped us to acquire new customers, and eventually, build products that helped us move from a hand-to-mouth bootstrapped operation into one that had real money in the bank. There was certainly more we could have done &#x2014; you never stop learning &#x2014; but connecting to the emotional core of our community helped us rapidly improve.</p><p>We might be excited about the work. The people we impact are excited about the effect the work has on them. Those are two distinct ideas &#x2014; and learning the difference can be make or break.</p> Note published on April 29, 2026 at 2:10 PM UTC - Molly White's activity feed 69f2114bcc098e890d542f8f 2026-04-29T14:10:19.000Z <article><div class="entry h-entry hentry"><header></header><div class="content e-content"><p>yep, that just about covers all possible options</p><div class="media-wrapper"><a href="https://storage.mollywhite.net/micro/580d24d71f56bc6aea5d_Screenshot-2026-04-29-at-10.07.13---AM.png" data-fslightbox=77cfb23f594b8adbe9dc><img src="https://storage.mollywhite.net/micro/580d24d71f56bc6aea5d_Screenshot-2026-04-29-at-10.07.13---AM.png" alt="CoinDesk headline: Price of bitcoin could go higher or ‘can go to zero,’ says Czech central bank governor" /></a></div></div><footer class="footer"><div class="flex-row post-meta"><div class="timestamp-block"><div class="timestamp">Posted: <a class="u-url" href="https://www.mollywhite.net/micro/entry/202604291007"><time class="dt-published" datetime="2026-04-29T14:10:19+00:00" title="April 29, 2026 at 2:10 PM UTC">April 29, 2026 at 2:10 PM UTC</time>. </a></div></div><div class="social-links"> <span> Also posted to: </span><a class="social-link u-syndication mastodon" href="https://hachyderm.io/@molly0xfff/116488393355711412" title="Mastodon" rel="syndication">Mastodon, </a><a class="social-link u-syndication bluesky" href="https://bsky.app/profile/molly.wiki/post/3mknbobbuce2h" title="Bluesky" rel="syndication">Bluesky</a></div></div><div class="bottomRow"><div class="tags">Tagged: <a class="tag p-category" href="https://www.mollywhite.net/micro/tag/crypto" title="See all micro posts tagged "crypto"" rel="category tag">crypto</a>. </div></div></footer></div></article> That terrible Signal exploit has been fixed. We have journalism to thank for it - Werd I/O 69f20f19825c3600019fc99e 2026-04-29T14:00:57.000Z <p>Link: <a href="https://www.404media.co/apple-fixes-bug-that-let-fbi-extract-deleted-signal-messages-after-404-media-coverage/?ref=werd.io"><em>Apple Fixes Bug That Let FBI Extract Deleted Signal Messages After 404 Media Coverage, by Joseph Cox at 404 Media</em></a></p><p>You may remember <a href="https://werd.io/fbi-extracts-suspects-deleted-signal-messages-saved-in-iphone-notification-database/">the story about the bug in Apple&#x2019;s on-device notifications database that allowed the FBI to retrieve the content of Signal messages</a>. It&#x2019;s good to see that it was treated as a genuine bug &#x2014; and fixed.</p><p><a href="https://bsky.app/profile/signal.org/post/3mk4krp33bk27?ref=werd.io">Signal announced the change on Bluesky</a>:</p><blockquote>&#x201C;We are very happy that today Apple issued a patch and a security advisory. This comes following 404 Media reporting that the FBI accessed Signal message notification content via iOS despite the app being deleted.&#x201D;</blockquote><p>That&#x2019;s good, because as the linked post notes, this had been actively used in court:</p><blockquote>&#x201C;They were able to capture these chats bc [because] of the way she had notifications set up on her phone&#x2014;anytime a notification pops up on the lock screen, Apple stores it in the internal memory of the device.&#x201D;</blockquote><p>There&#x2019;s no doubt in my mind that the widespread coverage and outrage over the issue helped encourage Apple to fix it quickly. I&#x2019;m grateful for the journalism and glad it was resolved.</p> Let's Get Digging! - Terence Eden’s Blog https://shkspr.mobi/blog/?p=70665 2026-04-29T11:34:23.000Z <p>As part of my quest to try new things I decided to dig for treasure in my local park.</p> <p>The wonderful folks at <a href="https://digventures.com/">DigVentures</a> allow members of the public to assist with archaeology projects in their local area. We arrived on a sunny Thursday to find a couple of areas of <a href="https://digventures.com/projects/lesnes-abbey/">Lesnes Abbey</a> cordoned off, with the turf taken up, and a set of tools waiting for us.</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/lesnes-abbey.webp" alt="Trenches cut out of the ground. A row of volunteers are bent over." width="2048" height="1152" class="aligncenter size-full wp-image-70691"/> <p>After a suitable health-and-safety briefing and some instruction on the tools, we got cracking. I was slightly sceptical that we&#39;d find anything digging only a few centimetres of dirt. The professionals reassured us that we&#39;d all find something.</p> <p>After scrabbling around for ages, I was feeling despondent. I found some interesting stones, some underwhelmed worms, and some prehistoric crisp packets - but nothing else.</p> <p>And then.</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/Tray-of-finds.webp" alt="A shallow plastic tray filled with old tile." width="2048" height="1536" class="aligncenter size-full wp-image-70692"/> <p>CBM - Ceramic Building Material - tiles started popping out of the ground. Big orange chunks of ancient tiles were <em>everywhere</em>. My mate Cam and I also found some with holes in them - evidence of them being used on a roof.</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/tezza-and-cam.webp" alt="Two grinning buffoons hold up a bit of old tile." width="2048" height="1536" class="aligncenter size-full wp-image-70697"/> <p>A surprising number of oyster shells were present - the discarded detritus of someone&#39;s lunch from hundreds of years ago. I even found a tiny bone (assessed as non-human, thankfully. Apparently that comes with a hell of a lot of paperwork!).</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/things.webp" alt="Some shell and bone resting on an old tile." width="2048" height="1536" class="aligncenter size-full wp-image-70693"/> <p>Gorgeous! And then, something shiny! Was it metal? Sadly, no. A chunk of pottery apparently. I kept digging, sraping, hoeing, looking, and then I found <em>more</em> shiny!</p> <p><video width="720" height="1280" src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/shiny.mp4" muted="" autoplay="" loop=""></video></p> <p>The local pottery expert reckoned it was <a href="https://en.wikipedia.org/wiki/Creamware">18th Century salt-glazed creamware</a>.</p> <p>You can take a look at the <a href="https://digventures.com/projects/lesnes-abbey/timeline/">DigVentures Timeline</a> or the <a href="https://www.facebook.com/lesnesabbey/posts/pfbid02GtHhdPh6QUur8zGA1QeCMjSutovyLy84XiCorMUk3Js9EZcyX6HA4Ug4NetktbRCl">Lesnes Abbey Facebook page</a> to see more photos of what we all found.</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/pointing.webp" alt="Me and another volunteer pointing excitedly into the dirt." width="1010" height="758" class="aligncenter size-full wp-image-70696"/> <p>It was a brilliant day out - I never realised just how close under our feet you can find history. It was also a physically demanding day, lots of kneeling on the ground, heaving speades, dragging wheelbarrows, etc.</p> <p>If they&#39;re running something near you, <a href="https://digventures.com/get-involved/">please get involved with DigVentures</a></p> <img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=70665&amp;HTTP_REFERER=Atom" alt="" width="1" height="1" loading="eager"/> Who knows that you blog? - Kev Quirk https://kevquirk.com/who-knows-that-you-blog 2026-04-29T11:27:00.000Z <div class="link card"><h2>Who knows that you blog?</h2><p class="post-author">by David Jamieson</p><p>David talks about his reluctance to share details about his blog with a colleague, and asks whether other people with blogs tell their friends and family.</p><p><a class="button" target="_blank" href="https://forkingmad.blog/who-knows-that-you-blog/">Read post ➡</a></p></div><p>I saw this post in my RSS reader this morning, followed by a <a href="https://thatalexguy.dev/re-who-knows-that-you-blog">reply from Alex</a>, so I thought I'd add my own opinion to the mix.</p> <p>I'm similar to David and Alex - I'm not forthcoming with the fact that I have a blog, but I don't hide it either. I think that's mainly because most of my friends and family won't really care about what I write here, so it's a pointless exercise.</p> <p>I know there are a couple of friends who read what I write regularly, and I'm not sure how they came across my blog - like I said, I don't advertise it. Having said that, my real name is Kev Quirk, so if anyone who knows me searches for my name, I imagine this blog would be close to, if not <em>the</em>, top hit.</p> <p>When people ask me about my hobbies, I tend to say <em>"I enjoy writing"</em> rather than <em>"I have a blog."</em> And I think that's because of the negative connotations blogging has with the general public.</p> <p>I think some people tend to put "bloggers" in the same bucket as <em>influencers</em>, or <em>podcasters</em>. Which isn't the case - many of us bloggers have no aspirations of influencing anything, we just like to share out thoughts on a medium we control. If it comes up in conversation though, I'll nonchalantly say that I have a blog.</p> <p>Anyway, that's my response. <strong>Who knows that you blog?</strong></p> <div class="email-hidden"> <hr /> <p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p> <p>You can <a href="mailto:19gy@qrk.one?subject=Who%20knows%20that%20you%20blog%3F">reply to this post by email</a>, or <a href="https://kevquirk.com/who-knows-that-you-blog#comments">leave a comment</a>.</p> </div> Extending Ruzzy with LibAFL - Trail of Bits Blog https://blog.trailofbits.com/2026/04/29/extending-ruzzy-with-libafl/ 2026-04-29T11:00:00.000Z <p>LibAFL is all the rage in the fuzzing community these days, especially with LLVM’s libFuzzer being placed in <a href="https://llvm.org/docs/LibFuzzer.html#status">maintenance mode</a>. Written in Rust, <a href="https://www.s3.eurecom.fr/docs/ccs22_fioraldi.pdf">LibAFL claims</a> improved performance, modularity, state-of-the-art fuzzing techniques, and <a href="https://github.com/AFLplusplus/LibAFL/tree/0.15.4/crates/libafl_libfuzzer">libFuzzer compatibility</a>. For these reasons, I set out to add LibAFL support to <a href="https://github.com/trailofbits/ruzzy">Ruzzy</a>, our coverage-guided fuzzer for pure Ruby code and Ruby C extensions. This gives Ruby developers and security researchers access to a more advanced and actively maintained fuzzing engine without changing how they write their fuzzing harnesses.</p> <p>Ruzzy was <a href="https://blog.trailofbits.com/2024/03/29/introducing-ruzzy-a-coverage-guided-ruby-fuzzer/">originally built</a> on top of LLVM’s libFuzzer, so using LibAFL’s compatibility layer should be easy enough. However, digging around in the internals of complex systems is never quite as simple as it seems. In this post, I will investigate some of the deep plumbing inside these fuzzing engines, take a detour into executable and linkable format (ELF) files, and ultimately add LibAFL support to Ruzzy.</p> <h2 id="building-with-libafl_libfuzzer">Building with libafl_libfuzzer</h2> <p>Ruzzy currently supports Linux, so I use a <a href="https://github.com/trailofbits/ruzzy/blob/v0.7.0/Dockerfile">Dockerfile</a> for development and for production fuzzing campaigns. To that end, using a similar Dockerfile for LibAFL support is the simplest integration point. LibAFL provides excellent <a href="https://github.com/AFLplusplus/LibAFL/tree/0.15.4/crates/libafl_libfuzzer#usage-as-a-standalone-library-for-ccetc">documentation</a> and build scripts to use it as a standalone library. We need to build LibAFL as a standalone library because Ruzzy uses <a href="https://llvm.org/docs/LibFuzzer.html#using-libfuzzer-as-a-library">libFuzzer as a library</a>.</p> <p>Following along with the standalone <code>libafl_libfuzzer</code> documentation, and with the <a href="https://github.com/AFLplusplus/LibAFL/blob/0.15.4/crates/libafl_libfuzzer_runtime/build.sh"><code>build.sh</code></a> script in hand, we can build <code>libFuzzer.a</code>. This is the archive that will ultimately be linked into Ruzzy’s C extension and used to fuzz our target. Here are the relevant lines from our new Dockerfile:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-dockerfile" data-lang="dockerfile"><span class="line"><span class="cl"><span class="c"># Install Rust nightly via rustup</span><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">RUN</span> wget -qO- https://sh.rustup.rs <span class="p">|</span> sh -s -- <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> -y <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --default-toolchain nightly <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --component llvm-tools<span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">ENV</span> <span class="nv">PATH</span><span class="o">=</span><span class="s2">&#34;/root/.cargo/bin:</span><span class="si">${</span><span class="nv">PATH</span><span class="si">}</span><span class="s2">&#34;</span><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="c"># Clone LibAFL</span><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">RUN</span> git clone --depth <span class="m">1</span> https://github.com/AFLplusplus/LibAFL /libafl<span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="c"># Build libFuzzer.a from LibAFL&#39;s libfuzzer runtime</span><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">WORKDIR</span><span class="w"> </span><span class="s">/libafl/crates/libafl_libfuzzer_runtime</span><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">RUN</span> bash build.sh</span></span></code></pre> <figcaption><span>Figure 1: Building LibAFL’s libFuzzer.a (Dockerfile.LibAFL)</span></figcaption> </figure> <p>This all goes smoothly and gives us our desired output: <code>libFuzzer.a</code>. Next, we need to make a slight tweak to Ruzzy’s mechanism for determining a <code>fuzzer_no_main</code> library. Using <code>fuzzer_no_main</code> and <code>-fsanitize=fuzzer-no-link</code> is libFuzzer’s <a href="https://llvm.org/docs/LibFuzzer.html#using-libfuzzer-as-a-library">standard mechanism</a> for fuzzing code that provides its own <code>main</code> function. This makes sense for interpreted languages because the interpreter, well, brings its own <code>main</code>.</p> <p>To accomplish the desired flexibility in Ruzzy, we simply need to prioritize an ENV variable, if present, that specifies the <code>fuzzer_no_main</code> library path, then fall back to Clang’s defaults if not:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line hl"><span class="cl"><span class="no">FUZZER_NO_MAIN_LIB_ENV</span> <span class="o">=</span> <span class="s1">&#39;FUZZER_NO_MAIN_LIB&#39;</span> </span></span><span class="line"><span class="cl"><span class="o">...</span> </span></span><span class="line hl"><span class="cl"><span class="n">fuzzer_no_main_lib</span> <span class="o">=</span> <span class="no">ENV</span><span class="o">.</span><span class="n">fetch</span><span class="p">(</span><span class="no">FUZZER_NO_MAIN_LIB_ENV</span><span class="p">,</span> <span class="kp">nil</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line hl"><span class="cl"><span class="k">if</span> <span class="n">fuzzer_no_main_lib</span> </span></span><span class="line"><span class="cl"> <span class="no">LOGGER</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&#34;Using </span><span class="si">#{</span><span class="no">FUZZER_NO_MAIN_LIB_ENV</span><span class="si">}</span><span class="s2">=</span><span class="si">#{</span><span class="n">fuzzer_no_main_lib</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">unless</span> <span class="no">File</span><span class="o">.</span><span class="n">exist?</span><span class="p">(</span><span class="n">fuzzer_no_main_lib</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="no">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">&#34;</span><span class="si">#{</span><span class="no">FUZZER_NO_MAIN_LIB_ENV</span><span class="si">}</span><span class="s2"> file does not exist: </span><span class="si">#{</span><span class="n">fuzzer_no_main_lib</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nb">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">end</span> </span></span><span class="line hl"><span class="cl"><span class="k">else</span> </span></span><span class="line"><span class="cl"> <span class="n">fuzzer_no_main_libs</span> <span class="o">=</span> <span class="o">[</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;libclang_rt.fuzzer_no_main.a&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;libclang_rt.fuzzer_no_main-aarch64.a&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;libclang_rt.fuzzer_no_main-x86_64.a&#39;</span> </span></span><span class="line"><span class="cl"> <span class="o">]</span> </span></span><span class="line hl"><span class="cl"> <span class="n">fuzzer_no_main_lib</span> <span class="o">=</span> <span class="n">fuzzer_no_main_libs</span><span class="o">.</span><span class="n">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">lib</span><span class="o">|</span> <span class="n">get_clang_file_name</span><span class="p">(</span><span class="n">lib</span><span class="p">)</span> <span class="p">}</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="o">&amp;</span><span class="ss">:itself</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">unless</span> <span class="n">fuzzer_no_main_lib</span> </span></span><span class="line"><span class="cl"> <span class="no">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">&#34;Could not find fuzzer_no_main using </span><span class="si">#{</span><span class="no">CC</span><span class="si">}</span><span class="s2">.&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="no">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">&#34;Please include </span><span class="si">#{</span><span class="no">CC</span><span class="si">}</span><span class="s2"> in your path or specify </span><span class="si">#{</span><span class="no">FUZZER_NO_MAIN_LIB_ENV</span><span class="si">}</span><span class="s2"> ENV variable.&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nb">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">end</span> </span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre> <figcaption><span>Figure 2: Allowing an ENV override for the fuzzing library (ext/cruzzy/extconf.rb)</span></figcaption> </figure> <p>Now, let’s build Ruzzy with LibAFL’s <code>libFuzzer.a</code>:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-dockerfile" data-lang="dockerfile"><span class="line"><span class="cl"><span class="c"># Copy LibAFL&#39;s libFuzzer.a from builder stage</span><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">COPY</span> --from<span class="o">=</span>libafl-builder /libafl/crates/libafl_libfuzzer_runtime/ libFuzzer.a /usr/lib/libFuzzer.a<span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="c"># Point Ruzzy at LibAFL&#39;s libFuzzer instead of clang&#39;s built-in</span><span class="err"> </span></span></span><span class="line hl"><span class="cl"><span class="err"></span><span class="k">ENV</span> <span class="nv">FUZZER_NO_MAIN_LIB</span><span class="o">=</span><span class="s2">&#34;/usr/lib/libFuzzer.a&#34;</span><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">WORKDIR</span><span class="w"> </span><span class="s">ruzzy</span>/<span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">COPY</span> . .<span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">RUN</span> gem build<span class="err"> </span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">RUN</span> <span class="nv">RUZZY_DEBUG</span><span class="o">=</span><span class="m">1</span> gem install --development --verbose ruzzy-*.gem</span></span></code></pre> <figcaption><span>Figure 3: Building Ruzzy with LibAFL using a custom FUZZER_NO_MAIN_LIB (Dockerfile.LibAFL)</span></figcaption> </figure> <p>However, this produces the following error:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">INFO -- : Using FUZZER_NO_MAIN_LIB=/usr/lib/libFuzzer.a </span></span><span class="line"><span class="cl">DEBUG -- : Search for libclang_rt.asan.a using clang-21: success=true exists=false </span></span><span class="line"><span class="cl">DEBUG -- : Search for libclang_rt.asan-aarch64.a using clang-21: success=true exists=true </span></span><span class="line"><span class="cl">DEBUG -- : Search for libclang_rt.asan-x86_64.a using clang-21: success=true exists=false </span></span><span class="line"><span class="cl">DEBUG -- : Creating /usr/lib/llvm-21/lib/clang/21/lib/linux/libclang_rt.asan-aarch64.a sanitizer archive at /tmp/20260320-20-683d0b </span></span><span class="line"><span class="cl">DEBUG -- : Merging sanitizer at /tmp/20260320-20-683d0b with libFuzzer at /usr/lib/libFuzzer.a to asan_with_fuzzer.so </span></span><span class="line hl"><span class="cl">/usr/bin/ld: /usr/lib/libFuzzer.a(libFuzzer.o): .preinit_array section is not allowed in DSO </span></span><span class="line hl"><span class="cl">/usr/bin/ld: failed to set dynamic section sizes: nonrepresentable section on output </span></span><span class="line hl"><span class="cl">clang++-21: error: linker command failed with exit code 1 (use -v to see invocation) </span></span><span class="line"><span class="cl">ERROR -- : The clang++-21 shared object merging command failed. </span></span><span class="line"><span class="cl">*** extconf.rb failed ***</span></span></code></pre> <figcaption><span>Figure 4: Failure linking libFuzzer.a</span></figcaption> </figure> <p>The key error here is “<code>.preinit_array</code> section is not allowed in DSO.” This was a new one for me. What is a <code>.preinit_array</code> section, and what is this error trying to tell me? The relevant <a href="https://refspecs.linuxbase.org/elf/gabi4+/ch5.dynamic.html#init_fini">ELF documentation</a> states the following:</p> <blockquote> Finally, <mark>an executable file may have pre-initialization functions.</mark> These functions are executed after the dynamic linker has built the process image and performed relocations but before any shared object initialization functions. <mark>Pre-initialization functions are not permitted in shared objects.</mark><br> ...<br> The DT_PREINIT_ARRAY table is processed <mark>only in an executable file; it is ignored if contained in a shared object.</mark> </blockquote> <p>So dynamic shared objects (DSOs) cannot contain a <code>.preinit_array</code> section. This is exactly what the error told us. <code>.init</code>, <code>.ctors</code>, <code>.init_array</code>, and <code>.preinit_array</code> are all mechanisms for running code before <code>main</code> starts in an ELF binary. Exploring each of these and the order in which they’re run is beyond the scope of this post (see <a href="https://maskray.me/blog/2021-11-07-init-ctors-init-array">this explanation</a>), but suffice it to say we need to sidestep this <code>libafl_libfuzzer</code> implementation detail. Here’s how LibAFL and libFuzzer differ in this regard:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ objdump -h /usr/lib/libFuzzer.a <span class="p">|</span> grep <span class="s1">&#39;init_array&#39;</span> </span></span><span class="line hl"><span class="cl"><span class="m">3100</span> .init_array <span class="m">00000228</span> ... </span></span><span class="line hl"><span class="cl"><span class="m">5047</span> .preinit_array <span class="m">00000008</span> ... </span></span><span class="line"><span class="cl"><span class="m">32136</span> .init_array.00099 <span class="m">00000008</span> ... </span></span><span class="line"><span class="cl"><span class="m">37083</span> .init_array.90 <span class="m">00000010</span> ... </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">$ objdump -h libclang_rt.fuzzer-aarch64.a <span class="p">|</span> grep <span class="s1">&#39;init_array&#39;</span> </span></span><span class="line hl"><span class="cl"> <span class="m">40</span> .init_array <span class="m">00000008</span> ... </span></span><span class="line"><span class="cl"> <span class="m">57</span> .init_array <span class="m">00000008</span> ... </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">$ objdump -h libclang_rt.fuzzer_no_main-aarch64.a <span class="p">|</span> grep <span class="s1">&#39;init_array&#39;</span> </span></span><span class="line hl"><span class="cl"> <span class="m">40</span> .init_array <span class="m">00000008</span> ... </span></span><span class="line"><span class="cl"> <span class="m">57</span> .init_array <span class="m">00000008</span> ... </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">$ objdump -h libclang_rt.fuzzer_interceptors-aarch64.a <span class="p">|</span> grep <span class="s1">&#39;init_array&#39;</span> </span></span><span class="line hl"><span class="cl"> <span class="m">21</span> .preinit_array <span class="m">00000008</span> ...</span></span></code></pre> <figcaption><span>Figure 5: .init_array vs. .preinit_array in LibAFL vs. libFuzzer</span></figcaption> </figure> <p>The figure above shows that LibAFL’s archive contains both <code>.init_array</code> and <code>.preinit_array</code> sections whereas Clang’s libFuzzer splits them across different files. Since LibAFL uses the <a href="https://github.com/AFLplusplus/LibAFL/blob/0.15.4/crates/libafl_targets/src/libfuzzer/FuzzerInterceptors.cpp#L1-L13">same interceptor code</a> as Clang, it also defines the same <a href="https://github.com/AFLplusplus/LibAFL/blob/0.15.4/crates/libafl_targets/src/libfuzzer/FuzzerInterceptors.cpp#L199-L200"><code>.preinit_array</code></a>. The problem is that LibAFL provides <a href="https://github.com/AFLplusplus/LibAFL/blob/0.15.4/crates/libafl_targets/Cargo.toml#L37"><code>libfuzzer_no_link_main</code></a> and <a href="https://github.com/AFLplusplus/LibAFL/blob/0.15.4/crates/libafl_targets/Cargo.toml#L39"><code>libfuzzer_interceptors</code></a> features, but we cannot easily toggle them at build time.</p> <p>This leaves us with two options: the proper solution, which is to propose a change upstream that allows these features to be toggled at build time, and the hacky, make-it-work solution. I wanted to keep moving forward and see this work end-to-end, so I started with the hacky solution. This required having a trick up our sleeve: GNU <code>ld</code> enforces the <code>.preinit_array</code>-in-a-DSO constraint, but LLVM <code>ld</code> does not. So we can modify Ruzzy’s build procedure to allow passing a user defined <code>ld</code> path at build time:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="cl"><span class="gh">diff --git a/Dockerfile.LibAFL b/Dockerfile.LibAFL </span></span></span><span class="line"><span class="cl"><span class="gh">index 5d0f9516..df6be2e2 100644 </span></span></span><span class="line"><span class="cl"><span class="gh"></span><span class="gd">--- a/Dockerfile.LibAFL </span></span></span><span class="line"><span class="cl"><span class="gd"></span><span class="gi">+++ b/Dockerfile.LibAFL </span></span></span><span class="line"><span class="cl"><span class="gi"></span><span class="gu">@@ -54,9 +54,12 @@ RUN echo &#34;deb http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-$LLVM_VERSION </span></span></span><span class="line"><span class="cl"><span class="gu"></span> &amp;&amp; echo &#34;deb-src http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-$LLVM_VERSION main&#34; &gt;&gt; /etc/apt/sources.list.d/ llvm.list \ </span></span><span class="line"><span class="cl"> &amp;&amp; wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key &gt; /etc/apt/trusted.gpg.d/apt.llvm.org.asc </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="gi">+# Install lld alongside clang. LibAFL&#39;s libFuzzer.a contains a .preinit_array </span></span></span><span class="line"><span class="cl"><span class="gi">+# .preinit_array section that the GNU linker rejects in shared objects. </span></span></span><span class="line"><span class="cl"><span class="gi">+# lld handles this correctly. </span></span></span><span class="line"><span class="cl"><span class="gi"></span> RUN apt update &amp;&amp; apt install -y \ </span></span><span class="line"><span class="cl"> build-essential \ </span></span><span class="line"><span class="cl"> clang-$LLVM_VERSION \ </span></span><span class="line"><span class="cl"><span class="gi">+ lld-$LLVM_VERSION \ </span></span></span><span class="line"><span class="cl"><span class="gi"></span> &amp;&amp; rm -rf /var/lib/apt/lists/* </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> ENV APP_DIR=&#34;/app&#34; </span></span><span class="line"><span class="cl"><span class="gu">@@ -69,6 +72,10 @@ ENV LDSHARED=&#34;clang-$LLVM_VERSION -shared&#34; </span></span></span><span class="line"><span class="cl"><span class="gu"></span> ENV LDSHAREDXX=&#34;clang++-$LLVM_VERSION -shared&#34; </span></span><span class="line"><span class="cl"> ENV ASAN_SYMBOLIZER_PATH=&#34;/usr/bin/llvm-symbolizer-$LLVM_VERSION&#34; </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="gi">+# Use lld for linking. LibAFL&#39;s libFuzzer.a contains a .preinit_array section </span></span></span><span class="line"><span class="cl"><span class="gi">+# that the GNU linker rejects in shared objects. lld handles this correctly. </span></span></span><span class="line"><span class="cl"><span class="gi">+ENV LD=&#34;lld-$LLVM_VERSION&#34; </span></span></span><span class="line"><span class="cl"><span class="gi">+ </span></span></span><span class="line"><span class="cl"><span class="gi"></span> ENV MAKE=&#34;make --environment-overrides V=1&#34; </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> ENV ASAN_OPTIONS=&#34;symbolize=1:allocator_may_return_null=1: </span></span><span class="line"><span class="cl">detect_leaks=0:use_sigaltstack=0&#34; </span></span><span class="line"><span class="cl"><span class="gh">diff --git a/ext/cruzzy/extconf.rb b/ext/cruzzy/extconf.rb </span></span></span><span class="line"><span class="cl"><span class="gh">index 6f474e62..260fcae6 100644 </span></span></span><span class="line"><span class="cl"><span class="gh"></span><span class="gd">--- a/ext/cruzzy/extconf.rb </span></span></span><span class="line"><span class="cl"><span class="gd"></span><span class="gi">+++ b/ext/cruzzy/extconf.rb </span></span></span><span class="line"><span class="cl"><span class="gi"></span><span class="gu">@@ -19,6 +19,7 @@ LOGGER.level = ENV.key?(&#39;RUZZY_DEBUG&#39;) ? </span></span></span><span class="line"><span class="cl"><span class="gu"></span>Logger::DEBUG : Logger::INFO </span></span><span class="line"><span class="cl"> CC = ENV.fetch(&#39;CC&#39;, &#39;clang&#39;) </span></span><span class="line"><span class="cl"> CXX = ENV.fetch(&#39;CXX&#39;, &#39;clang++&#39;) </span></span><span class="line"><span class="cl"> AR = ENV.fetch(&#39;AR&#39;, &#39;ar&#39;) </span></span><span class="line"><span class="cl"><span class="gi">+LD = ENV.fetch(&#39;LD&#39;, &#39;ld&#39;) </span></span></span><span class="line"><span class="cl"><span class="gi"></span> FUZZER_NO_MAIN_LIB_ENV = &#39;FUZZER_NO_MAIN_LIB&#39; </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> LOGGER.debug(&#34;Ruby CC: #{RbConfig::CONFIG[&#39;CC&#39;]}&#34;) </span></span><span class="line"><span class="cl"><span class="gu">@@ -66,6 +67,7 @@ def merge_sanitizer_libfuzzer_lib(sanitizer_lib, </span></span></span><span class="line"><span class="cl"><span class="gu"></span>fuzzer_no_main_lib, merged_outp </span></span><span class="line"><span class="cl"> &#39;-ldl&#39;, </span></span><span class="line"><span class="cl"> &#39;-lstdc++&#39;, </span></span><span class="line"><span class="cl"> &#39;-shared&#39;, </span></span><span class="line"><span class="cl"><span class="gi">+ &#34;-fuse-ld=#{LD}&#34;, </span></span></span><span class="line"><span class="cl"><span class="gi"></span> &#39;-o&#39;, </span></span><span class="line"><span class="cl"> merged_output </span></span><span class="line"><span class="cl"> ) </span></span><span class="line"><span class="cl"><span class="gu">@@ -145,5 +147,6 @@ merge_sanitizer_libfuzzer_lib( </span></span></span><span class="line"><span class="cl"><span class="gu"></span> $LOCAL_LIBS = fuzzer_no_main_lib </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> $LIBS &lt;&lt; &#39; -lstdc++&#39; </span></span><span class="line"><span class="cl"><span class="gi">+$DLDFLAGS &lt;&lt; &#34; -fuse-ld=#{LD}&#34; </span></span></span><span class="line"><span class="cl"><span class="gi"></span> </span></span><span class="line"><span class="cl"> create_makefile(&#39;cruzzy/cruzzy&#39;) </span></span></code></pre> <figcaption><span>Figure 6: Allow a user-specified ld binary</span></figcaption> </figure> <p>And now the Docker build works! But building the fuzzing libraries, Ruby C extension, and Docker image is only the first step. We still have to run the fuzzer, which comes with its own set of challenges.</p> <p>As for the proper fix I mentioned earlier, we did propose it upstream in <a href="https://github.com/AFLplusplus/LibAFL/pull/3734">this pull request</a>. Once that’s merged, we can run the build script with <code>--cargo-args &quot;--no-default-features --features no_link_main&quot;</code> and avoid the <code>ld</code> hack. Now, on to running the fuzzer.</p> <h2 id="fuzzing-with-libafl">Fuzzing with LibAFL</h2> <p>Ruzzy includes its own <a href="https://github.com/trailofbits/ruzzy/blob/v0.7.0/ext/dummy/dummy.c">“dummy” C extension</a> for testing the fuzzer and making sure everything is working as expected. We can use this to test out our LibAFL changes and make sure they’re working properly. After building the fuzzer and finally being able to start it, I got the following error:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ docker run --rm ruzzy-libafl -runs=100000 </span></span><span class="line"><span class="cl">thread &#39;&lt;unnamed&gt;&#39; (9) panicked at src/fuzz.rs:275:5: </span></span><span class="line hl"><span class="cl">No maps available; cannot fuzz! </span></span><span class="line"><span class="cl">note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace </span></span><span class="line"><span class="cl">fatal runtime error: failed to initiate panic, error 2786066624, aborting </span></span><span class="line"><span class="cl">/usr/local/bundle/gems/ruzzy-0.7.0/lib/ruzzy.rb:15: [BUG] Aborted at 0x0000000000000009 </span></span><span class="line"><span class="cl">ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [aarch64-linux] </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">-- Control frame information ----------------------------------------------- </span></span><span class="line"><span class="cl">c:0005 p:---- s:0022 e:000021 l:y b:---- CFUNC :c_fuzz </span></span><span class="line"><span class="cl">c:0004 p:0011 s:0016 e:000015 l:y b:0001 METHOD /usr/local/bundle/gems/ruzzy-0.7.0/lib/ruzzy.rb:15 </span></span><span class="line"><span class="cl">c:0003 p:0008 s:0010 E:001390 l:y b:0001 METHOD /usr/local/bundle/gems/ruzzy-0.7.0/lib/ruzzy.rb:28 </span></span><span class="line"><span class="cl">c:0002 p:0010 s:0006 e:000005 l:n b:---- EVAL -e:1 [FINISH] </span></span><span class="line"><span class="cl">c:0001 p:0000 s:0003 E:000940 l:y b:---- DUMMY [FINISH] </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">-- Ruby level backtrace information ---------------------------------------- </span></span><span class="line"><span class="cl">-e:1:in &#39;&lt;main&gt;&#39; </span></span><span class="line hl"><span class="cl">/usr/local/bundle/gems/ruzzy-0.7.0/lib/ruzzy.rb:28:in &#39;dummy&#39; </span></span><span class="line hl"><span class="cl">/usr/local/bundle/gems/ruzzy-0.7.0/lib/ruzzy.rb:15:in &#39;fuzz&#39; </span></span><span class="line hl"><span class="cl">/usr/local/bundle/gems/ruzzy-0.7.0/lib/ruzzy.rb:15:in &#39;c_fuzz&#39; </span></span><span class="line"><span class="cl">...</span></span></code></pre> <figcaption><span>Figure 7: Runtime error when starting the fuzzer</span></figcaption> </figure> <p>The key error here is “No maps available; cannot fuzz!” This <a href="https://github.com/AFLplusplus/LibAFL/blob/0.15.4/crates/libafl_libfuzzer/runtime/src/lib.rs#L552-L569">LibAFL error</a> occurs when the <a href="https://clang.llvm.org/docs/SanitizerCoverage.html">SanitizerCoverage</a> state is not initialized properly. To understand this discrepancy between LibAFL and libFuzzer, we must first understand what SanitizerCoverage is and how it works.</p> <p>SanitizerCoverage tracks code coverage information during a fuzzing campaign to improve performance. Simple heuristics like “if we’ve discovered new code coverage, then continue to mutate relevant inputs to better explore these code paths” are powerful fuzzing primitives. The underlying theory is that higher code coverage results in more crashes and bugs (I’m oversimplifying, but you get the point). To that end, a fuzzing engine needs a mechanism for initializing and tracking coverage information.</p> <p>SanitizerCoverage offers a variety of ways to track coverage information, all of which require a mechanism to initialize state at the beginning of a fuzzing campaign. For example, <a href="https://clang.llvm.org/docs/SanitizerCoverage.html#introduction">the documentation</a> offers <code>pc-guard</code>, <code>8bit-counters</code>, <code>bool-flag</code>, and <code>pc-table</code> tracing mechanisms, each with a corresponding <code>init</code> function. These <a href="https://github.com/llvm/llvm-project/blob/llvmorg-22.1.1/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp#L76-L80"><code>init</code> functions</a> are eventually lowered and represented as <a href="https://github.com/llvm/llvm-project/blob/llvmorg-22.1.1/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp#L1155-L1157"><code>.init_array</code> entries</a> in ELF files (<code>.init_array</code> strikes again). This means that, ultimately, coverage initialization functionality is called when the DSO is loaded at runtime.</p> <p>Back to the error at hand: why is LibAFL saying “No maps available; cannot fuzz!” while LLVM’s libFuzzer starts up just fine? The key distinction is that libFuzzer lazily allows new coverage counter arrays to be included at runtime and does not complain if none exist at startup. LibAFL, however, requires them to be defined when the fuzzer starts. Compare the following sequence of events:</p> <ul> <li>LibAFL <a href="https://github.com/AFLplusplus/LibAFL/blob/0.15.4/crates/libafl_libfuzzer/runtime/src/lib.rs#L605"><code>LLVMFuzzerRunDriver</code></a> <ul> <li>Calls <a href="https://github.com/AFLplusplus/LibAFL/blob/0.15.4/crates/libafl_libfuzzer/runtime/src/lib.rs#L694"><code>fuzz::fuzz</code></a></li> <li>Calls <a href="https://github.com/AFLplusplus/LibAFL/blob/0.15.4/crates/libafl_libfuzzer/runtime/src/fuzz.rs#L271-L274"><code>fuzz_with!</code></a></li> <li>Checks if coverage counters exist</li> </ul> </li> <li>libFuzzer <a href="https://github.com/llvm/llvm-project/blob/llvmorg-22.1.1/compiler-rt/lib/fuzzer/FuzzerDriver.cpp#L934"><code>LLVMFuzzerRunDriver</code></a> <ul> <li>Calls <a href="https://github.com/llvm/llvm-project/blob/llvmorg-22.1.1/compiler-rt/lib/fuzzer/FuzzerDriver.cpp#L652"><code>FuzzerDriver</code></a></li> <li>Eventually calls <a href="https://github.com/llvm/llvm-project/blob/llvmorg-22.1.1/compiler-rt/lib/fuzzer/FuzzerDriver.cpp#L923"><code>Fuzzer::Loop</code></a></li> <li>Does not check if coverage counters exist</li> </ul> </li> </ul> <p>So coverage <code>init</code> functions are called at DSO load time, after which the fuzzing engine may or may not check for their existence depending on implementation. To fully understand the cause of this error, we have to go back and better understand how Ruzzy runs its “dummy” C extension. The Ruzzy Docker image runs the “dummy” code by default via its entrypoint:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="ch">#!/bin/bash</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="no">LD_PRELOAD</span><span class="o">=</span><span class="err">$</span><span class="p">(</span><span class="n">ruby</span> <span class="o">-</span><span class="n">e</span> <span class="s1">&#39;require &#34;ruzzy&#34;; print Ruzzy::ASAN_PATH&#39;</span><span class="p">)</span> <span class="p">\</span> </span></span><span class="line hl"><span class="cl"> <span class="n">ruby</span> <span class="o">-</span><span class="n">e</span> <span class="s1">&#39;require &#34;ruzzy&#34;; Ruzzy.dummy&#39;</span> <span class="o">--</span> <span class="s2">&#34;$@&#34;</span></span></span></code></pre> <figcaption><span>Figure 8: Docker image entrypoint (entrypoint.sh)</span></figcaption> </figure> <p><code>Ruzzy.dummy</code> corresponds to the following code:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">fuzz</span><span class="p">(</span><span class="n">test_one_input</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="no">DEFAULT_ARGS</span><span class="p">)</span> </span></span><span class="line hl"><span class="cl"> <span class="n">c_fuzz</span><span class="p">(</span><span class="n">test_one_input</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span> <span class="c1"># STEP 3: Call Ruzzy.c_fuzz (in C extension)</span> </span></span><span class="line"><span class="cl"><span class="k">end</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line hl"><span class="cl"><span class="k">def</span> <span class="nf">dummy_test_one_input</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="c1"># STEP 4: Eventually call Ruzzy.dummy_test_one_input</span> </span></span><span class="line"><span class="cl"> <span class="c1"># This &#39;require&#39; depends on LD_PRELOAD, so it&#39;s placed inside the function</span> </span></span><span class="line"><span class="cl"> <span class="c1"># scope. This allows us to access EXT_PATH for LD_PRELOAD and not have a</span> </span></span><span class="line"><span class="cl"> <span class="c1"># circular dependency.</span> </span></span><span class="line"><span class="cl"> <span class="nb">require</span> <span class="s1">&#39;dummy/dummy&#39;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">c_dummy_test_one_input</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="k">end</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line hl"><span class="cl"><span class="k">def</span> <span class="nf">dummy</span> <span class="c1"># STEP 1: Call Ruzzy.dummy</span> </span></span><span class="line hl"><span class="cl"> <span class="n">fuzz</span><span class="p">(</span><span class="o">-&gt;</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="p">{</span> <span class="n">dummy_test_one_input</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="p">})</span> <span class="c1"># STEP 2: Call Ruzzy.fuzz</span> </span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre> <figcaption><span>Figure 9: Ruzzy.dummy call chain (lib/ruzzy.rb)</span></figcaption> </figure> <p>If you’re searching for the bug, then the body of <code>dummy_test_one_input</code> may provide a hint. The issue here is that <code>require 'dummy/dummy'</code> is called too late. This <code>require</code> statement is actually loading the compiled Ruby C extension shared object. Remember what we learned above about loading shared objects? This shared object contains an <code>.init_array</code> function that initializes the coverage counter state. libFuzzer lazily uses coverage counter state, so it is not so sensitive about the ordering of events. LibAFL, however, requires that this state already be initialized before it begins fuzzing.</p> <p><code>Ruzzy.dummy</code> calls <code>fuzz</code> with a lambda that calls <code>dummy_test_one_input</code>. But because <code>dummy_test_one_input</code> is passed in a lambda and not invoked until the fuzzer starts, LibAFL errors out in the call to <code>c_fuzz</code> (<code>c_fuzz</code> calls <code>LLVMFuzzerRunDriver</code>). This makes sense given that the initial Ruby error traceback pointed at <code>c_fuzz</code>. So we end up with a quite minimal patch:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="cl"><span class="gh">diff --git a/lib/ruzzy.rb b/lib/ruzzy.rb </span></span></span><span class="line"><span class="cl"><span class="gh">index d5e9ae61..be5f8339 100644 </span></span></span><span class="line"><span class="cl"><span class="gh"></span><span class="gd">--- a/lib/ruzzy.rb </span></span></span><span class="line"><span class="cl"><span class="gd"></span><span class="gi">+++ b/lib/ruzzy.rb </span></span></span><span class="line"><span class="cl"><span class="gi"></span><span class="gu">@@ -25,6 +25,11 @@ module Ruzzy </span></span></span><span class="line"><span class="cl"><span class="gu"></span> end </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> def dummy </span></span><span class="line"><span class="cl"><span class="gi">+ # Load the instrumented shared object before calling fuzz so its coverage </span></span></span><span class="line"><span class="cl"><span class="gi">+ # maps are registered before LLVMFuzzerRunDriver starts. Some fuzzer </span></span></span><span class="line"><span class="cl"><span class="gi">+ # runtimes (e.g. LibAFL) require coverage maps to exist upfront. </span></span></span><span class="line"><span class="cl"><span class="gi">+ require &#39;dummy/dummy&#39; </span></span></span><span class="line"><span class="cl"><span class="gi">+ </span></span></span><span class="line"><span class="cl"><span class="gi"></span> fuzz(-&gt;(data) { dummy_test_one_input(data) }) </span></span><span class="line"><span class="cl"> end </span></span></code></pre> <figcaption><span>Figure 10: Ruzzy.dummy initialization patch</span></figcaption> </figure> <p>With the <code>ld</code> and initialization patches, LibAFL finally works (!):</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ docker run --rm ruzzy-libafl -runs=100000 </span></span><span class="line"><span class="cl">... </span></span><span class="line"><span class="cl"> (CLIENT) corpus: 3, objectives: 0, executions: 7593, exec/sec: 0.000, </span></span><span class="line"><span class="cl">size_edges: 12/21 (57%), edges_stability: 11/11 (100%), edges: 12/21 (57%) </span></span><span class="line"><span class="cl">================================================================= </span></span><span class="line hl"><span class="cl">==9==ERROR: AddressSanitizer: heap-use-after-free on address 0xfcbfab6655c0 at pc 0xffffab9c1888 bp 0xffffee4ce430 sp 0xffffee4ce428 </span></span><span class="line"><span class="cl">READ of size 1 at 0xfcbfab6655c0 thread T0 </span></span><span class="line hl"><span class="cl"> #0 0xffffab9c1884 in _c_dummy_test_one_input /usr/local/bundle/gems/ ruzzy-0.7.0/ext/dummy/dummy.c:18:24 </span></span><span class="line"><span class="cl">...</span></span></code></pre> <figcaption><span>Figure 11: Ruzzy fuzzing with LibAFL</span></figcaption> </figure> <p>This AddressSanitizer output shows that LibAFL starts cleanly and quickly finds the intentional bug in <code>dummy.c</code>. The heap-use-after-free in the dummy C extension confirms the full pipeline is working: instrumentation, coverage tracking, tracing, and crash detection are all functioning as expected.</p> <h2 id="try-out-ruzzy-with-libafl">Try out Ruzzy with LibAFL</h2> <p>We recently released <a href="https://github.com/trailofbits/ruzzy/blob/main/CHANGELOG.md#080---2026-04-27">version 0.8.0</a> of Ruzzy, which includes LibAFL support. Give it a spin on your next Ruby project or audit. I worked with Claude on implementing this improvement, and sometimes it would race so far ahead to the finish line that it would take me two days to catch up. Getting a working implementation is still the end goal, and reverse engineering a patch is a lot easier after it <em>is</em> working, but deeply understanding the patch is valuable too. I learned a lot about ELF binaries, fuzzing engine internals, linkers, and compilers throughout this process. LLMs are a useful tool not only for getting stuff done, but also for understanding the world around us.</p> <p>If you’d like to read more about fuzzing, check out the following resources:</p> <ul> <li>Our <a href="https://appsec.guide/docs/fuzzing/">fuzzing chapter</a> in the Testing Handbook</li> <li><a href="https://blog.trailofbits.com/2024/02/23/continuously-fuzzing-python-c-extensions/">Continuously fuzzing Python C extensions</a></li> <li><a href="https://blog.trailofbits.com/2020/06/05/breaking-the-solidity-compiler-with-a-fuzzer/">Breaking the Solidity Compiler with a Fuzzer</a></li> </ul> <p>As always, <a href="https://trailofbits.com/contact/">contact us</a> if you need help with your next Ruby project or fuzzing campaign.</p> Computing as a social activity - destructured https://destructured.net/computing-as-a-social-activity 2026-04-29T04:00:00.000Z <p>Much of the software that we encounter on a daily basis, including the bulk of the infrastructure on which the internet runs, is grounded in a decades-old paradigm called “Free and Open Source Software.” FOSS developers distribute their work under permissive licenses that allow others to use, share, modify and redistribute the resulting code for free. LLM use threatens that paradigm, in part by <a href="(https://www.zdnet.com/article/why-open-source-may-not-survive-the-rise-of-generative-ai/)">unleashing a deluge</a> of difficult-to-evaluate, vibe-coded contributions, but perhaps more critically, by eroding FOSS’s social component.</p> <p>Historically, FOSS has always been more than just a way of organizing labor and distributing software. It’s a paradigm that makes possible a vision of computing as a broad, collaborative social activity, an impromptu latticework of individual people contributing their knowledge, creativity and work into a communal pool of resources that can be built upon and directed toward diverse human ends. Something like the Linux ecosystem is impressive not just because it packages together the work of thousands of people into a software environment that can be operated for free, but maybe even more so because it serves as a visible artifact of a decades of social organization and interaction between people scattered all across the globe, communicating with one another, contributing to one another’s projects, teaching one another and reviewing one another’s code, everyone benefiting from one another’s largesse and interests.</p> <p>By using LLMs to reduce their dependence on other humans, developers risk abandoning that social foundation. They work through roadblocks not by interacting with other developers on forums, but by asking a model trained on a millions of StackOverflow posts. They review code that no one has written, or submit code that will be reviewed by no one. Until now, FOSS has been conducted as a conversation, humans responding to other humans in the formal languages of code and project management, but increasingly it’s a conversation conducted between chatbots.<sup id="fnref:1" role="doc-noteref"><a href="https://destructured.net/computing-as-a-social-activity/#fn:1" class="footnote" rel="footnote">1</a></sup></p> <p>None of that is explicit in FOSS, of course, so there’s a need for a complementary principle that makes it explicit. Like FOSS, it should shift emphasis away from output as the sole standard for assessing value, redirecting attention to the means that lead to that end. It could be as straightforward as CASA — Computing As a Social Activity. The idea being to insist upon and prioritize practices that maintain the status of software as the vehicle and occasion for human-to-human connection.</p> <div class="footnotes" role="doc-endnotes"> <ol> <li id="fn:1" role="doc-endnote"> <p>The transition from subscription to usage-based billing for LLM use, which appears to have <a href="https://github.blog/news-insights/company-news/github-copilot-is-moving-to-usage-based-billing/">begun in earnest</a>, will no doubt slow that trend. <a href="https://destructured.net/computing-as-a-social-activity/#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p> </li> </ol> </div> On wintering. - Westenberg 69f162b58ca1cd0001c84d57 2026-04-29T01:54:43.000Z <div class="kg-card kg-cta-card kg-cta-bg-grey kg-cta-minimal " data-layout="minimal"> <div class="kg-cta-content"> <div class="kg-cta-content-inner"> <div class="kg-cta-text"> <img src="https://www.joanwestenberg.com/content/images/2026/04/lincoln-1863-gettyimages-177602038-1377722101.jpg" alt="On wintering."><p><span style="white-space: pre-wrap;">This newsletter is free to read, and it&#x2019;ll stay that way. But if you want more - extra posts each month, no sponsored CTAs, access to the community, and a direct line to ask me things - paid subscriptions are $2.50/month. A lot of people have told me it&#x2019;s worth it. </span></p> </div> <a href="https://www.joanwestenberg.com/#/portal/signup/69328a08ef56a90001ae60df/monthly" class="kg-cta-button " style="background-color: #000000; color: #ffffff;"> Upgrade </a> </div> </div> </div> <p>Abraham Lincoln rode home from Washington in December 1849, with what looked like the end of his career packed into his luggage. He&apos;d served one term in the House, alienated his constituents by opposing the Mexican War, and lost his shot at a federal Land Office appointment.</p><p>He went back to Springfield to practice law, a near-broken man. And, for nearly 5 years, he barely participated in national politics.</p><p>He rode the Illinois circuit, argued patent disputes, and taught himself geometry from Euclid by candlelight in coach inns. He read newspapers obsessively; he read Shakespeare and the King James Bible until he could quote either from pretty much any starting point.</p><p>The folks who saw him in those years said he looked...tired.</p><p>When he returned to the spotlight, in October 1854, the Kansas-Nebraska Act had cracked the country open. Lincoln walked onto the stage at Peoria and spoke for 3 hours straight. The man who&apos;d been a country lawyer that morning was a national figure by midnight.</p><p>Six years later, he was president. </p><p>Lincoln&apos;s lost years are the part of the biography American children skip past in school; they get the rail-splitter, the beard, the debates, the war, the emancipation, the address, the assassination.</p><p>But the 5 years we skip over are the whole ballgame. </p><p>They rebuilt the instrument.</p><p>The English writer Katherine May coined the modern usage in her 2020 book <em>Wintering</em>, but the idea is older than the word. Russian peasants called the long quiet stretches between harvests <em>zima</em> and treated them as a season for weaving, sleeping, repairing tools, and telling stories. Japanese Buddhist monasteries built whole liturgies around rohatsu sesshin, the seven-day winter retreat that closes the year. Foragers like the !Kung and the Hadza, spent something like 4 hours a day on subsistence and the rest on&#x2026;rest.</p><p>Productivity is a recent invention; wintering is not.</p><p>Cormac McCarthy published <em>Blood Meridian</em> in 1985 to a shrugging response. The New York Times reviewed it in a single column. He&apos;d been writing in El Paso for years, broke and largely forgotten. Friends thought he&apos;d peaked. Then in 1992 <em>All the Pretty Horses</em> came out, won the National Book Award, sold half a million copies, and the back catalog got reissued. McCarthy hadn&apos;t been recovering. He&apos;d been finishing something the culture wasn&apos;t ready for in 1985 and was ready for by 1992.</p><p>He&apos;d been wintering.</p><p>Daniel Day-Lewis stopped acting in 1997 and apprenticed as a cobbler in Florence. He came back, played Bill the Butcher in <em>Gangs of New York</em>, and won an Oscar. He stopped again. Came back. Won another Oscar. Stopped again, and by all reports has actually stopped this time, though I wouldn&apos;t bet on it. The cobbler years were how he reset the instrument.</p><p>In the long winter, organisms route metabolism inward.</p><p>Trees pull resources out of leaves, drop the leaves, and push the sugars down into root systems. Bears don&apos;t sleep, exactly. Their core temperature drops a few degrees, their metabolism halves, and they cycle slowly through fat reserves while their kidneys learn to recycle urea into protein. They come out in spring with their bones still mineralized and their muscles roughly intact, which is something no human has yet figured out how to do. What the bear performs is one of the most metabolically sophisticated tricks in the animal kingdom.</p><p>The Romans understood that a field left fallow for a season produced more in the next cycle than one worked continuously. Norfolk farmers in the 18th century made it a four-course rotation: wheat, turnips, barley, clover, with the clover restoring nitrogen the wheat had pulled out. The land that looks unused is doing the most useful work.</p><p>People who winter well are doing something analogous. They route attention inward and downward, into the parts of the system that don&apos;t show up on the surface. They read, they revise, they take long walks they can&apos;t account for, and they think the same thought 400 times until it cracks.</p><p>Most of what gets published, shipped, posted, and announced is washed off the rocks within a quarter. The people doing it are running on a treadmill that resets their position to zero every Monday. They have to keep producing to stay visible, and visibility is how they earn the right to keep producing.</p><p>It&apos;s a closed loop, and it generates very little compound interest.</p><p>The winterer is off the loop. They aren&apos;t maintaining a position because they don&apos;t have a position to maintain.</p><p>In the short term, you pay dearly for it.</p><p>People forget you exist. Calls dry up. Old collaborators stop replying. Younger versions of you lap you in the standings.</p><p>The benefit is that you can do work that takes longer than a quarter, and longer than a year, and longer than 5 years, because nobody is auditing the line item.</p><p>Charles Darwin came back from the <em>Beagle</em> voyage in 1836 with the rough outline of natural selection in his head. He published <em>On the Origin of Species</em> in 1859. The intervening 23 years included long stretches when he wrote almost nothing in his theory notebooks, partly because he was sick, partly because he was writing 8 volumes about barnacles, and partly because he understood the case had to be airtight. When he finally published, the argument was so heavily fortified that the church spent the next 50 years trying to find a hairline crack and failing.</p><p>If Darwin had published in 1840, he might be a footnote. His 23 years of comparative silence were the moat.</p><p>Robert Caro started his Lyndon Johnson biography in 1976. He&apos;s published 4 volumes of an intended 5. He&apos;s now 90. He moved to the Texas Hill Country to live among the people Johnson grew up with, because he thought he couldn&apos;t write about a man without inhabiting his weather. Each volume took roughly a decade. The publishing world treats him as a slow eccentric. Anyone who&apos;s read the books knows he&apos;s running a different clock, on a different scale, and that no one currently working at speed is going to produce anything close.</p><p>Plenty of people stop and produce nothing. The graveyard of failed comebacks is large, and wintering is dangerous as a strategy because most attempts at it collapse into actual stagnation.</p><p>The difference between the two is invisible from the outside, until the end.</p><p>The reason the wintering few register as dangerous, when they re-emerge, is that they have something the still-busy don&apos;t have: a center of gravity. They&apos;ve spent enough time alone with a single problem to develop actual opinions about it, opinions that don&apos;t move when other people push on them. In a culture optimized for constant repositioning, conviction is a structural advantage. The market doesn&apos;t know how to price it.</p><p>The winterer has been watching while you weren&apos;t looking. They&apos;ve watched the consensus shift, watched the mistakes pile up. When they come back, they come back with reads you can&apos;t get from inside the swirl, because the swirl makes you stupid.</p><p>The philosopher Hannah Arendt, writing in <em>The Life of the Mind</em> in the 1970s, described thinking itself as a form of withdrawal. You can&apos;t think and act at the same time, she said, because thinking pulls you out of the stream of ongoing events. She was suspicious of people who claimed to do both at once.</p><p>The British psychiatrist Anthony Storr, in <em>Solitude</em> (1988), made the case that the most original work of major figures often came out of long isolated stretches. Newton in plague-year Cambridge. Wittgenstein in Norway. Kafka in Z&#xFC;rau. Beckett in his Paris apartment with the curtains drawn. Storr wasn&apos;t romanticizing it; the isolated stretches were often miserable, sometimes pathological. But the work that came out of them had a density that wasn&apos;t available to people doing it part-time.</p><p>Any culture that systematically punishes withdrawal is going to lose its most concentrated thinkers to either burnout or invisibility. The modern knowledge economy, with its ambient pressure to post, ship, and stay in the conversation, is a machine for producing exactly that loss. The people we&apos;ll wish we had in 15 years are, right now, being shamed into producing slop they don&apos;t believe in, because the alternative is to drop out, and dropping out reads as failure.</p><p>The winterers who survive this will be those who can tolerate looking like they failed. This is a real and rare psychological skill, and most people don&apos;t have it. It requires you to be okay with the wrong kind of silence around your name for years. It requires you to pass on small wins that would re-establish your position. It requires you to bet that what you&apos;re working on is worth more than what you&apos;re giving up, when the only person who can evaluate the bet is you, and you might be wrong, and you&apos;ll only know in 7 years.</p><p>Lincoln didn&apos;t know in 1851 that he was wintering.</p><p>He thought he was finished.</p><p>He told his law partner William Herndon that his political career was over, and he believed it. And then his country produced an emergency that demanded exactly the kind of mind he&apos;d been nurturing, and he was the man of the hour whose hour had finally come.</p><p>The people who appear to have stopped, in any given year, are mostly people who have actually stopped. But small fraction of them are doing the other thing. </p><p>Our world produces emergencies on a reliable schedule; when the next one comes, watch who walks out of the woods.</p> <div class="kg-card kg-cta-card kg-cta-bg-grey kg-cta-minimal " data-layout="minimal"> <div class="kg-cta-sponsor-label-wrapper"> <div class="kg-cta-sponsor-label"> <span style="white-space: pre-wrap;">SPONSORED</span> </div> </div> <div class="kg-cta-content"> <div class="kg-cta-content-inner"> <div class="kg-cta-text"> <p><span style="white-space: pre-wrap;">Westenberg is designed, built and funded by my agency, Studio Self. Reach out and work with me:</span></p> </div> <a href="https://www.thisisstudioself.com/?ref=joanwestenberg.com" class="kg-cta-button " style="background-color: #000000; color: #ffffff;"> Work with me </a> </div> </div> </div> Published on Citation Needed: "No new trial for Sam Bankman-Fried" - Molly White's activity feed 69f13ad9cc098e890d542f25 2026-04-28T22:55:21.000Z <article class="entry h-entry hentry"><header><div class="description">Published an issue of <a href="https://www.citationneeded.news/"><i>Citation Needed</i></a>: </div><h2 class="p-name"><a class="u-syndication" href="https://www.citationneeded.news/sbf-new-trial-denied" rel="syndication">No new trial for Sam Bankman-Fried </a></h2></header><div class="content e-content"><div class="media-wrapper"><a href="https://www.citationneeded.news/sbf-new-trial-denied"><img src="https://www.citationneeded.news/content/images/size/w2000/format/webp/2026/04/sbf-denied.png" alt="Bankman-Fried’s motion for a new trial, overlaid with a red “denied” stamp"/></a></div><div class="p-summary"><p>The former CEO of FTX has essentially no realistic avenues left to avoid his 25-year prison sentence</p></div></div><footer class="footer"><div class="flex-row post-meta"><div class="timestamp">Posted: <a class="u-url" href="https://www.citationneeded.news/sbf-new-trial-denied"><time class="dt-published" datetime="2026-04-28T22:55:21+00:00" title="April 28, 2026 at 10:55 PM UTC">April 28, 2026 at 10:55 PM UTC</time>. </a></div><div class="social-links"> <span>Also posted to:</span><a class="social-link u-syndication mastodon" href="https://hachyderm.io/@molly0xfff/116484786466869365" title="Mastodon" rel="syndication">Mastodon</a><a class="social-link u-syndication bluesky" href="https://bsky.app/profile/molly.wiki/post/3mkloecw7ps2q" title="Bluesky" rel="syndication">Bluesky</a></div></div><div class="bottomRow"><div class="tags">Tagged: <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/ftx" title="See all feed posts tagged "FTX"" rel="category tag">FTX</a>, <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/sam_bankman_fried" title="See all feed posts tagged "Sam Bankman-Fried"" rel="category tag">Sam Bankman-Fried</a>.</div></div></footer></article> Should something change? - Joel's Log Files https://joelchrono.xyz/blog/should-something-change 2026-04-28T15:30:00.000Z <p><em>This is a pretty personal post btw, not dark or anything but it may not be up your alley to have my ramblings and questions get to you or something.</em></p> <p>A few weeks ago my mom had a talk with me, when she discovered my videogame collection. To be clear, it was not even hidden, you only have to enter my bedroom and look to the right, something she has done before, my guess is she never stopped to count them or she didn’t think those boxes were all games, whoops.</p> <p>She was worried about me, and talked about how I need to focus on the right things and stop getting distracted by the internet and videogames, and that I should not be spending so much money of it. She doesn’t know how much I actually spent, but well let’s just agree that it’s not insignificant.</p> <p>I do also agree with the time investment/getting distracted part. I do waste time on YouTube, and even if I mostly stick with the fediverse for social media, it still can be a bit of a timesink. I definitely could do without some of the impulse purchases I’ve made before.</p> <p>But calling videogames a distraction doesn’t sit right with me. They have plenty of positives, but I don’t think I need to talk about that here.</p> <p>One of her questions was about what do I even do sitting in front of a computer most of the time, once I arrive home from work, especially when it’s been a while since I’ve gone to the gym too. Yes it’s YouTube, and scrolling on social media, maybe some PC games here and there or some graphic design on Inkscape. I’ve never been clear about it, “I’m just using it”, I say, whenever I am working on my blog, writing or editing a post. I use a window manager on Linux, so it’s always easy to switch my screen to a browser or whatever. Sometimes I don’t mind to show the editor though, they don’t read that closely.</p> <p>I don’t have to hide the stuff, to be honest, if my parents stumbled upon any post from my archive, they wouldn’t find anything new about me or something that would change the way they see me, the only difference is they’d know I share it online, when I don’t talk much in person about things that interest me. That reminds me of another post I wrote a while ago about <a href="https://joelchrono.xyz/blog/explaining-hobbies-is-weird/">how terrible I am at explaining my hobbies</a>. Either way, the face I show to the people in real life is not too different to here. I try to be honest.</p> <p>Writing for me is a hobby and a bit of a ritual by now, no matter how fancy I try to explain why I write on a blog post, I don’t know how I would say it in real life. I feel that spending time typing out words that are not a novel or something that makes money doesn’t make sense to most people, it’s not productive I guess? Even less so when I don’t even care for ads and sponsored content—<em>I wouldn’t mind reviewing a handheld or getting a steam code every once in a while though ;)</em></p> <p>Back to videogames for a bit, it’s true that there are plenty of experiences more important than them, sometimes they can become an escape, and while that isn’t wrong, acknowledging reality matters, I don’t want to trick myself otherwise. I should be looking forward and actively work towards achieving something more. Perhaps it’s kind of a cliche but I do want to save up for a home, I do want to find a partner to share my life with, get married, and form my own family, I want to go through the good and the bad moments all of that entails, so many questions and things to experience. I want to live a good life, and that shouldn’t just be on the web, or just videogames or writing, but people, community, life.</p> <p>But even then, <em>videogames are awesome</em>, I love to play them and to experience them, the variety of stories I get to live through, the challenges I manage to overcome, the mechanics and puzzles and gameplay I learn and even master sometimes. I think it’s possible to have both things so I don’t see myself ever leaving them completely.</p> <p>I look at my dad who didn’t grow up with games and refuses to play them nowadays, and like, yes, he’s cool and he does read a lot and other things, but I want to also show my kids how to appreciate videogames from the ground up. There’s some pretty cool dads out there which are also a model for me, but nobody is perfect, so I parse through the examples of those that come before me and that I’ve met during my life, to grow myself according to some ideal. I may never reach it, but getting close is enough.</p> <p>Yep, my kids will be playing SNES and GBA games before they learn what polygon-based graphics are, they’ll be getting stories from JRPGs and get used to waiting for their turn to move while the enemies still attack you, they’ll get used to a couple buttons and a d-pad before they need to use dual analog sticks. Eventually we’ll get to Halo and they will understand that you don’t need a run button to have fun in first-person shooters.</p> <p>Reading and writing too, they spark so much, they inspire so much. Before bed I will read for them, stories from Jules Verne and C.S Lewis, like I did. They’ll learn how to solve the Rubik’s cube and all of that. They will have their own pens and learn cursive writing and know a world before whatever the future is. At least that’s what I’d like, but it doesn’t have to be any of that, I think I just want them to love learning.</p> <p>Woah look at me, talking about what’s yet to come. It’s so weird, but I guess it’s something I’d like. If they want to do something else or lack any interest on anything of what I have to show and teach them, I will still try to guide them, but I’ll have to accept their choices, and love them regardless, it’s okay too. Maybe this is one of those posts I wouldn’t want my parents to read, why am I typing all of this out anyway?</p> <p>I remember, I was looking for ideas online and just saw the way <a href="https://robertbirming.com/start-writing/">Robert starts a writing session</a> and thought I may as well do the same, just another ramble of thoughts flowing one after another without any particular structure, and well now I am revealing a bit of what my hopes are.</p> <p>I guess there’s a bit of a barrier to express myself fully in person. I am, after all, an introvert. I still barely talk during lunch with my coworkers, preferring to scroll on my phone instead or read some manga. I still don’t go out that much and if I do, it’s just to go by myself to some public space and read there instead of talking or meeting people. It’s not like I’m about to change who I am just yet though… I guess I could say I’ll try but not even sure how to start I guess.</p> <p>Are videogames a deterrent on my progress? Is writing the same? I’ll spend less money on videogames sure, I already have a big backlog anyway so. Should I write a little less and experience more? Should I spend my free time in other things? I don’t particularly feel the need to. I eventually want to make a trip somewhere, like Japan, or Canada or some European country, Spain could be fun too I don’t know.</p> <p>What’s this post about? How will I even title it? I talked about so many things from gaming being a good thing for me, to blogging and writing being things I don’t mention much and how I don’t want people around me to know I do it even if I don’t care that much, to building a family in the future and raising mini versions of me who will get into my hobbies and my wife’s too of course but ideally we’ll share some of them and…. I’ll just stop rambling about it all for now.</p> <p>I’ve been working for two years now doing the same thing, and I guess that’s a totally normal thing too, I get good money, I don’t get overworked, I am building up on vacation days and the like. It’s all good, do I want more? Would that help? I don’t really want to rattle things that much, but I wonder if I’m stuck in a bit of a cycle. I have been thinking about the next step for a while, I don’t know which is it, or maybe I do and I just don’t want to take it yet, I like how things are, even though I feel something should change.</p> <p>This is day 58 of <a href="https://100daystooffload.com">#100DaysToOffload</a>.</p> <p> <a href="mailto:me@joelchrono.xyz?subject=Should something change?">Reply to this post via email</a> | <a href="https://fosstodon.org/@joel/idcomments">Reply on Fediverse</a> </p> Stop Ubuntu Resetting Your Icon Theme When Toggling Dark Mode - Kev Quirk https://kevquirk.com/stop-ubuntu-resetting-your-icon-theme-when-toggling-dark-mode 2026-04-28T13:55:00.000Z <p>The <a href="https://github.com/PapirusDevelopmentTeam/papirus-icon-theme/">Papirus icon theme</a> is my favourite - I've used it for years and it continues to work beautifully. So while I've been <a href="https://kevquirk.com/update-2-on-the-framework-saga">rebuilding my Framework 13</a>, it was one of the first things I installed.</p> <p>But there's a problem, dear reader. You see, I'm a proud <a href="https://kevquirk.com/is-dark-mode-such-a-good-idea">light mode</a> person, but I regularly switch to dark mode when working in the evening. However, Ubuntu has this silly bug where it switches back to the default Yaru icon theme whenever one switches between light and dark mode.</p> <p>Annoying.</p> <p>On my previous machine I had a cronjob running every minute that simply checked the theme and switched it to Papirus if it was Yaru. That worked fine, but wasn't the most elegant solution.</p> <p>So, this time I did more research and came up with a slightly more elegant <del>fix</del> workaround.</p> <h2>How to "fix" it</h2> <p>Ok, it's pretty simple. It consists of a small script that runs whenever Ubuntu flips between light/dark mode, then 0.2 seconds later, switches the icon theme back.</p> <p>Far from perfect, but it's better than a script that runs every minute the machine is running.</p> <p>To do this, create a new script at <code>~/.local/bin/watch-darkmode.sh</code> with the following contents:</p> <pre><code class="hljs language-bash">gsettings monitor org.gnome.desktop.interface color-scheme | <span class="hljs-keyword">while</span> <span class="hljs-built_in">read</span> -r line; <span class="hljs-keyword">do</span> <span class="hljs-keyword">if</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$line</span>"</span> | grep -q <span class="hljs-string">"prefer-dark"</span>; <span class="hljs-keyword">then</span> sleep 0.2 gsettings <span class="hljs-built_in">set</span> org.gnome.desktop.interface icon-theme <span class="hljs-string">'Papirus-Dark'</span> <span class="hljs-keyword">elif</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$line</span>"</span> | grep -q <span class="hljs-string">"default"</span>; <span class="hljs-keyword">then</span> sleep 0.2 gsettings <span class="hljs-built_in">set</span> org.gnome.desktop.interface icon-theme <span class="hljs-string">'Papirus'</span> <span class="hljs-keyword">fi</span> <span class="hljs-keyword">done</span></code></pre> <p>You need to make the script executable, so run this next:</p> <pre><code class="hljs language-bash">chmod +x ~/.<span class="hljs-built_in">local</span>/bin/watch-darkmode.sh</code></pre> <p>Next thing is create a <code>.desktop</code> file that tells GNOME to automatically start the script when we log in:</p> <pre><code class="hljs language-bash"><span class="hljs-comment"># Create the file</span> nano ~/.config/autostart/watch-darkmode.desktop <span class="hljs-comment"># Paste this into the nano window</span> [Desktop Entry] Type=Application Name=Watch Dark Mode Exec=/home/YOUR-USERNAME/.<span class="hljs-built_in">local</span>/bin/watch-darkmode.sh Hidden=<span class="hljs-literal">false</span> NoDisplay=<span class="hljs-literal">false</span> X-GNOME-Autostart-enabled=<span class="hljs-literal">true</span></code></pre> <p class="notice">Remember to change <code>YOUR-USERNAME</code> on the <code>Exec=</code> line to whatever your Ubuntu username is.</p> <p>That's it! Log out, and back in again, and the script should be doing it's thing in the background. So the next time you switch between light and dark mode, your fancy-pants icon theme should persist.</p> <div class="email-hidden"> <hr /> <p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p> <p>You can <a href="mailto:19gy@qrk.one?subject=Stop%20Ubuntu%20Resetting%20Your%20Icon%20Theme%20When%20Toggling%20Dark%20Mode">reply to this post by email</a>, or <a href="https://kevquirk.com/stop-ubuntu-resetting-your-icon-theme-when-toggling-dark-mode#comments">leave a comment</a>.</p> </div> The workload of AI - destructured https://destructured.net/workload-ai 2026-04-28T04:00:00.000Z <p>One of the fundamental deceptions of AI is that it reduces work. It looks that way only because you receive the output through a very narrow aperture, creating the illusion of ease.</p> <p><a href="https://anatomyof.ai/">Anatomy of an AI System</a> is a fantastic resource that strips away that illusion. The patient accumulation of detail exposes how “each small moment of convenience — be it answering a question, turning on a light, or playing a song — requires a vast planetary network, fueled by the extraction of non-renewable materials, labor, and data.”</p> <p>One of the principal functions of consumer-grade AI is to shift the burden of all that work onto other people. It is an insidious technology precisely because it makes the end user complicit in vast externalities. For most operations, AI requires more work than simply doing the task yourself. By obscuring your view of that work, AI makes it Someone Else’s Problem.</p> <p>That critically undermines “I only use it for small things” as a justification. It’s the accumulation of small things that makes some technologies so destructive. Cars wouldn’t do nearly so much structural and environmental harm if we only used them for the occasional long trip. It’s the multiple daily drives to points within walking, bicycle, or mass transit distance that have the biggest impact on our health and the shape of our communities.</p> <p>Likewise, the accumulation of idle prompts, of small tasks, of tweaks and casual experiments and revisions offloaded to a process designed to shield you not just from the work involved but also from an awareness of the work involved — these all contribute to a burgeoning strain on communities both far away and closer to home than we sometimes suspect.</p> Tomodachi Life, Werewolves and Heliocentrism - W17 - Joel's Log Files https://joelchrono.xyz/blog/2026-w17 2026-04-28T03:25:57.000Z <p>Did you know I kinda always forget what to write in the main, regular section of these weeknotes? The structure I usually type these things is something like: introduction, games, books or manga I reading, shows/movies/anime I watched, youtube and blogposts, leaving the regular notes at the end! It’s a bit weird to do it in such a way but I can’t help it. I guess it also speaks about the kinds of things that I write about with more ease, I don’t know.</p> <ul> <li> <p>🏠 I have been home alone since Wednesday and I must admit this is probably the most irresponsible I’ve been when staying by myself. I usually do the dishes every day, but this time I let them build up for a couple of days before cleaning them, evil stuff.</p> </li> <li> <p>🏰 We were so close to playing Land of Eem this weekend, but we didn’t plan it out at all and half of us forgot to bring our character sheets and I didn’t have backups and the printer didn’t work anyway so… yeah. We played some <em>Uno Liar’s</em> instead, and a new game in the next item of this list!</p> </li> <li> <p>🐺 We finally were enough to go for a play of a certain game everyone knows but that it’s a little hard to start given the necessary amount of players: <strong>Werewolves</strong>. Specially <a href="https://www.youtube.com/watch?v=WcjbTgc28n0">The Werewolves of Miller’s Hollow</a>, which is a very nice set with some pretty cool rules to it. I got it at the same time as <em>Coup</em>, but we just couldn’t play it until today. I was a little afraid that everyone would not be up for it, but in the end, we played it like 6 times, and we hard an absolute blast! I only hope more friends join us next weekend.</p> </li> <li> <p>👔 There was this important meeting at work where everyone wore fancy formal office wear and I was wearing a hoodie and we took a photo and I was put at the back to hide it. Honestly I felt really embarrased about missing that email mentioning the dress code, that was definitely cringe. At the same time I think it was no big deal, still got a bit of teasing from my workmates though.</p> </li> <li> <p>🧱 I ended up buying another Lego set, this time because of <a href="https://polymaths.social/@clayton/statuses/01KQ5Z7CMPZ9A0KV8562ATSPEA">Clayton</a>, it’s the DeLorean from <em>Back to the Future!</em>. It’s not the super expensive version at least.</p> </li> </ul> <h2 id="watching">Watching</h2> <p>Hear ye, hear ye. For I have witnessed one of the most important works of anime in recent years. I am talking about <strong>Orb: On the Movements of the Earth</strong>, an absolutely stunning piece of art where we follow the journey of Rafal, a young kid who wants to understand the truth, a young kid who loves space, and wants to become an astronomer.</p> <p>Eventually, he’ll stumble upon a heretic, a man who believes in the forbidden idea of <a href="https://en.wikipedia.org/wiki/heliocentrism">Heliocentrism</a> who, before his execution, plants the idea of his mind to pursue the truth: the earth moves.</p> <p>The journey that follows is one of the most beautiful, tragic and thought-provoking I’ve had the privilege to watch. So much so I want to watch it again, knowing what I learned is yet to come and how everything fits and connects.</p> <p>It’s an epic tale that mixes history and legend, that explores humanity, our place in Earth, the beauty of creation, the nature of God, why belief remains or why society doesn’t need it. Reason, faith, naturalism, progress. So many incredible dialogues, speeches, and exchanges of ideas, or censorship, blindness, and persecution. Many moments here left me absolutely speechless, and this show got me to cry more than once. This is art, this is humanity, curiosity, and our endless pursue for knowledge.</p> <p><a href="https://www.youtube.com/watch?v=xd_7ybA16SU">Check this speech</a> light on spoilers, and tell me you aren’t interested to see more…</p> <details> <summary>Transcript of the speech</summary> <p>As a disciple of the Church, I know I shouldn’t use these words lightly. But I can’t think of any other way to express it. Reading and writing… are like miracles.</p> <p>Of course, I don’t mean they’re the same as the miracles performed by our saviour!</p> <p>Still, reading and writing are amazing. Using letters, a person can cross space and time. I might shed tears reading the news from 200 years ago, or laugh at rumors from 1000 years ago. Isn’t that unbelievable?</p> <p>Our lives are trapped, beyond our control, in this day and age. But when I read, the great figures from the past engage me in conversation. At that moment, I can escape the present.</p> <p>Thoughts put into writing remain after we are gone, and they might spur someone into action far in the future. What else could you call that, but a miracle?</p> </details> <h2 id="gaming">Gaming</h2> <p>Every single day of the week until the weekend arrived, I played <strong>Metal Gear Solid: Peace Walker</strong>. At first, I was enamoured by the mechanics and the stealth, the voice acting and all of the stuff I already wrote about, but I have to say, I’ve really gotten to like these characters quite a lot. I’ll be honest, I’ve been looking at gameplay of this game to see stuff that I should be doing and realizing how little of the game I knew back when I first tried it.</p> <p>For example, there’s a whole arsenal of goods that I never unlocked because I followed the main story and ignored most of the side quests and the rather deep management simulator that happens between missions. There were also weapons I never knew how to use, like the chaff grenade, which is extremely useful to disable enemy machinery and confuse the AI bosses’ circuits, making them much easier to target too.</p> <p>The story, which I didn’t really know much of, has managed to get a grip on me anyway. I’ve been told there’s a lot of lore on this series, and that it’s also very confusing, but this particular game is filled with melancholy and regret, and the delivery and writing here have managed to transmit that very well, even if I didn’t play through the moments this game brings to memory. All in all, a super enjoyable journey so far.</p> <p>After such a mature and expertly made videogame, I decided to buy <strong>Tomodachi Life: Living the Dream</strong> on a whim. This is one of the most trending games right now! A sort of dollhouse game where you can create Miis of whoever you want, from people you know in real life, to celebrities or characters from videogames, and see how they interact with each other! I’ve been having a lot of fun, even made Miis of a couple of fediverse friends like <a href="https://benjaminhollon.com">Amin</a> and <a href="https://doserver.top">Daniel</a>. I’ve also created a few others from characters from games, shows and anime, such as <a href="https://en.wikipedia.org/wiki/Lucca_Ashtear">Lucca</a>, <a href="https://en.wikipedia.org/wiki/Aya_Brea">Aya Brea</a>, <a href="https://en.wikipedia.org/wiki/Ada_Wong">Ada Wong</a>, <a href="https://en.wikipedia.org/wiki/Claire_Redfield">Claire Redfield</a>, <a href="https://en.wikipedia.org/wiki/Big_Boss_(Metal_Gear)">Big Boss</a>, <a href="https://en.wikipedia.org/wiki/Zuko">Zuko</a>, and <a href="https://en.wikipedia.org/wiki/Frieren_(character)">Frieren</a>. There have been a couple IRL friends included, of course, which I won’t name here.</p> <p>Lastly, I had a brief session of <strong>Metroid Fusion</strong>, where I defeated Serries, the water serpent boss that was taken over by the X virus, and I managed to get the Speed Boost power-up! Nothing more than that, though.</p> <h2 id="reading">Reading</h2> <p>I completed <em>The Indomitable Captain Holli</em>! the novella from <strong>Clarkesworld Magazine #211</strong>, and it was incredibly enjoyable, so much so I almost want to write a separate review for it. But I won’t, you really should give it a read, especially because it’s <a href="https://clarkesworldmagazine.com/larson_04_24/">available for free</a> on Clarkesworld’s website!</p> <p>I’ve continued on with my manga obsession and read up to chapter 289 of <strong>Fly Me To The Moon</strong>, which continues to be very funny and entertaining!</p> <p>Lastly, a new contender, a rom-com titled <strong>Smoking Behind the Supermarket with You</strong>, featuring Sasaki, a hardworking middle-aged guy stuck in the corporate ladder, whose often goes to the supermarket to see Yamada’s smile, a young cashier working there who seem rather friendly and innocent.</p> <p>After Susuki goes for a smoke, he’s approachted by Tayama, a cool-loking young lady—who is actually an alter-ego of Yamada, but looks and acts way different—who invites him to smoke and chat together, while also sussing out his intentions to see if he’s not just a creepy old guy. An unusual relationship follows from there! I’ve read 42 chapters already (including a bunch of shorter bonus chapters).</p> <h2 id="around-the-web">Around the Web</h2> <p>I didn’t feel like writing actual summaries this time around, I already wrote too much on the sections above, byee.</p> <h3 id="blog-posts">Blog posts</h3> <ul> <li><a href="https://schafe-sind-bessere-rasenmaeher.de/mindfulness/do-you-want-to-build-a-treehouse/">Do you want to build a treehouse?</a> - Yes, I want to build a treehouse.</li> <li><a href="https://thatalexguy.dev/im-glad-i-enjoy-older-stuff">I’m Glad I Enjoy Older Stuff</a> - Yes, I am glad I enjoy it too.</li> <li><a href="https://axxuy.com/blog/2026/i-also-got-an-xteink-x4/">I Also Got An Xteink X4</a> - Yes, you are very welcome my friend.</li> <li><a href="https://ellesho.me/page/website/now/#personal-homepage-tips">personal homepage tips</a> - yes, Elle has lot’s of good tips.</li> </ul> <h3 id="youtube">YouTube</h3> <ul> <li><a href="https://youtu.be/5XFtpdy4wos">Why Nintendo almost got rid of Miis</a> - They are back with Tomodachi Life so I’m happy.</li> <li><a href="https://youtu.be/7EVZpW9Rdwk">The Most Important Tiny Decision In Tech History</a> - I kinda didn’t like this video, but I also don’t know if I can debate it.</li> <li><a href="https://youtu.be/k1a1fZSjpXA">Was Link’s Pink Hair Really a Mistake?</a> - Apparently it wasn’t, weird stuff.</li> <li><a href="https://youtu.be/D6MhZDKGBas">Vampire Crawlers Demands Your Attention</a> - Very good video essay.</li> </ul> <p>This is day 57 of <a href="https://100daystooffload.com">#100DaysToOffload</a></p> <p> <a href="mailto:me@joelchrono.xyz?subject=Tomodachi Life, Werewolves and Heliocentrism - W17">Reply to this post via email</a> | <a href="https://fosstodon.org/@joel/116480425550947292">Reply on Fediverse</a> </p> Peace, Quiet, and No Signal - Hey, it's Jason! https://grepjason.sh/2026/peace-quiet-and-no-signal 2026-04-28T00:00:00.000Z A visit to dark sky country! Just peace, quiet, and no cell signal. The Loop: everything has happened before, and everything will happen again - Westenberg 69efe2d5b3831a0001f7f772 2026-04-27T22:38:38.000Z <div class="kg-card kg-cta-card kg-cta-bg-grey kg-cta-minimal " data-layout="minimal"> <div class="kg-cta-content"> <div class="kg-cta-content-inner"> <div class="kg-cta-text"> <img src="https://images.unsplash.com/photo-1669843136865-ec263be282d8?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDMxfHxjaXJjbGV8ZW58MHx8fHwxNzc3MzI5MDg4fDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" alt="The Loop: everything has happened before, and everything will happen again"><p><span style="white-space: pre-wrap;">This newsletter is free to read, and it&#x2019;ll stay that way. But if you want more - extra posts each month, no sponsored CTAs, access to the community, and a direct line to ask me things - paid subscriptions are $2.50/month. A lot of people have told me it&#x2019;s worth it. </span></p> </div> <a href="https://www.joanwestenberg.com/#/portal/signup/69328a08ef56a90001ae60df/monthly" class="kg-cta-button " style="background-color: #000000; color: #ffffff;"> Upgrade </a> </div> </div> </div><p>In February 1637, a single tulip bulb in Haarlem sold for 5,200 guilders - the price of a canal house on the Keizersgracht // ten times the annual salary of a skilled craftsman. The bulb was a Semper Augustus, streaked white and flame-red, and the buyer never saw it. He bought a piece of paper representing a future flower, and within 3 weeks, the market collapsed. Men who had mortgaged their workshops to buy futures on something they would never hold went home to explain it to their families. Within a century, the Dutch and English were back, inside the South Sea Company, whose directors had printed prospectuses for an undertaking they refused to describe. Within two centuries, French investors were holding the worthless scrip of John Law&apos;s Mississippi Scheme, which had promised them a share of Louisiana gold that didn&apos;t exist. By the 1840s it was railway shares, with one in ten English investors buying into lines that were never built. By the 1920s it was radio stocks. By the late 1990s it was dot-com. By 2008 it was tranched American mortgages, rated AAA by people paid by the banks that issued them. By 2021 it was JPEGs of monkeys. By 2026, it was AI stocks.</p><p>Every one of these episodes was preceded by someone writing a book about how the last one could never happen again, and every single one ended with the same sentence murmured like a prayer on the way up:</p><p><em>This time is different.</em></p><p>&#x2026;But it never is.</p><p>Is it?</p><h2 id="the-claim-i-want-to-make%E2%80%A6"><strong>The claim I want to make&#x2026;</strong></h2><p>Humans do near-identical things, over and over again, across history. And we do it because our cognitive equipment hasn&apos;t changed - the brain running a 21st-century civilization is a Paleolithic brain, shaped by 200,000 years on the savannah and another 10,000 years in small agricultural settlements, and it fears the same things our ancestors feared, and it wants the same things they wanted, and it fails in the same ways.</p><p>The loop itself is, in fact, our operating system.</p><p>Everything else, the political systems, the technologies, the languages, the ideologies, is the application layer. Applications change, but the operating system doesn&apos;t. When an application throws the same error message in Rome, in Berlin in 1933, in Phnom Penh in 1975, and on a Saturday afternoon in a suburban American town in 2024, the error sits in the kernel - <em>and the kernel is not getting patched.</em></p><h2 id="the-bubble"><strong>The bubble</strong></h2><p>The financial bubble (and by that I mean <em>every</em> financial bubble) is the cleanest version of the loop there is. Prices rise, greed overrides caution, debt piles on debt, and the floor gives way. Within ten years the same people, or their children, do it again. And again. And again.</p><p>Every bubble is catalogued and studied before the next one begins. Charles Mackay wrote <em>Memoirs of Extraordinary Popular Delusions and the Madness of Crowds</em> in 1841. The book became a bestseller among the same London financiers who would soon be pouring money into Latin American mining schemes that required them to invest in countries they couldn&apos;t find on a map. In 1929, Irving Fisher, one of the most published economists in America, declared that stocks had reached a permanently high plateau - and the crash began nine days later. In 2005, Alan Greenspan testified to Congress that American housing prices reflected local conditions and there was no nationwide bubble. In 2008, there was. The brain has a failure mode around probabilistic risk: it discounts low-probability catastrophic outcomes in favor of high-probability mild gains, it reads social consensus as information, and its dopamine circuit rewards the anticipation of gain more reliably than the gain itself.</p><p>The hunt feels better than the meal.</p><p>Humans pretty reliably miscalculate risk at every step of the process, but somehow the profession of finance is built on the assumption that markets aggregate these miscalculations into wisdom. They don&apos;t. They aggregate them into stampedes, and herd cognition does the rest. When everyone around you is buying, the cost of not buying is financial + social. You miss the gain, and your neighbor gets rich, and your brother-in-law mentions it at dinner. The brain treats this as a threat to status, and status, in primate terms, is survival. Solomon Asch&apos;s conformity experiments in 1951 showed that ordinary people will deny the evidence of their own eyes rather than disagree with a confident group, and bubbles are Asch experiments with money on the line.</p><p>Every bubble ends with the same discovery, which is that the asset was never worth what it traded for; every bubble starts, though, from the matching belief that this time, it is.</p><h2 id="the-strongman"><strong>The strongman</strong></h2><p>The strongman arrives on schedule, and the preconditions are consistent. A frightened middle class + institutions that have stopped delivering + an establishment that has lost the trust of the people it governs. Put those pieces in a room together and within a decade someone walks in who promises to cut through all of it. Caesar in 49 BCE. Napoleon in 1799. Mussolini in 1922. Hitler in 1933. Per&#xF3;n in 1946. A catalogue since then that hardly needs naming. The strongman is a phenotype; he&apos;s what the interaction between primate dominance hierarchies and political instability produces. Chimpanzee troops have alpha males, and human societies have them too. Under stable conditions, the alpha position is distributed across institutions, softened by law, and rotated by elections. Under unstable conditions, the position re-concentrates around a single body. Frans de Waal watched the same sequence play out among captive chimpanzees at Arnhem; Hannah Arendt watched it play out among human beings in the twentieth century. The mechanics were the same. The stakes differed only in body count.</p><p>Apparently, the human brain under stress doesn&apos;t want deliberation; it wants authority. Uncertainty burns more energy than bad news, and so the prefrontal cortex tries to resolve ambiguity, and when it fails, it hands control to older circuits that prefer a simple answer to the right answer - any right answer. MRI studies of people presented with ambiguous political images show amygdala activation patterns close to indistinguishable from fear responses; the feeling of not knowing whether your world is safe is, in brain-chemistry terms, very close to the feeling of being in danger.</p><p>And, sooner or later, there will always someone willing to supply the simple answer. The man who says he alone can fix it believes it, because the crowd that believes it first has already told him so; what his opponents call a lie, he experiences as a revelation. The feedback loop between a frightened population and a would-be strongman runs on the same neurology in both directions: he needs them as much as they need him, and they produce each other.</p><p>The cycle tends to run thirty years from collapse to collapse. Long enough for the generation that lived through the last strongman to die, and short enough that their grandchildren are available // ready // willing to repeat the experiment.</p><h2 id="the-scapegoat"><strong>The scapegoat</strong></h2><p>When a society is in pain, it finds someone to blame. Rarely the structure. Rarely the people who benefit most from the structure. Always someone weaker, someone already marginal, someone who can be sacrificed without the majority feeling the cost. Jews in medieval Europe during the Black Death, when entire communities were burned alive on the accusation that they had poisoned wells, and Jews again in Weimar Germany during the hyperinflation. Catholics in Elizabethan England, hunted by priest-catchers who were paid by the head, and Chinese merchants in Indonesia in 1965, and again in 1998. Tutsis in Rwanda in 1994, 800,000 dead in a hundred days, killed with machetes by neighbors who had lived next door for generations. Muslims in post-9/11 America. Immigrants, always, everywhere.</p><p>The mechanism was described by Ren&#xE9; Girard, a French literary critic who argued that violence against the innocent is the engine of social cohesion. His book <em>Violence and the Sacred</em> in 1972 laid out the structure: a community in conflict with itself discovers that it can reconcile by turning collectively on a single victim, and all that the victim has to be is unanimous. Guilt is beside the point, which is the part of this I find hardest to sit with; once the blow lands and the crowd goes quiet, the community feels cleansed. Girard&apos;s work sits uncomfortably among the more respectable social sciences because it says something his colleagues didn&apos;t want to hear: the crowd&apos;s sense of unity is purchased with the body of someone who didn&apos;t deserve to die, and the mechanism doesn&apos;t give a shit about ideology. It works for medieval Catholics, for Jacobin revolutionaries, for Nazi party members, for Twitter mobs. The crowd needs its victim, and the victim needs to be innocent enough that the guilt of destroying him is too heavy to carry, which is why the sacrifice must be followed by denial.</p><p>The scapegoat loop is neurology under pressure. The brain performs in-group and out-group sorting in under 200 milliseconds, before conscious perception arrives - a feature of human vision that kept small bands of primates alive on the savannah. A stranger at 40 meters could be trade or death. You didn&apos;t have time to think it through. Demagogues know this, or they feel it, which amounts to the same thing. They weaponize a perceptual shortcut human beings can&apos;t turn off, and they provide a face for a pain that has no face. The crowd does the rest.</p><h2 id="the-invention-that-eats-its-children"><strong>The invention that eats its children</strong></h2><p>The printing press was going to democratize knowledge. And it did! But first, it launched two centuries of religious war. Johannes Gutenberg pressed his first Bible in 1455. By 1517, Luther&apos;s theses were being reproduced across Europe in weeks, and by 1618, the Thirty Years&apos; War had begun. By its end in 1648, a third of the German-speaking population was dead. Elizabeth Eisenstein&apos;s <em>The Printing Press as an Agent of Change</em> in 1979 documented how the technology that was supposed to bring light to the masses also industrialized the production of astrology, witch-hunting manuals, and anti-Semitic pamphlets. The press amplified everything, including the things its advocates hoped it would abolish.</p><p>Radio was going to educate the masses. It gave Hitler a direct line to every kitchen in Germany, and Father Coughlin a direct line to thirty million American listeners in the 1930s, and Radio Rwanda the tool it needed to coordinate a genocide in 1994. Television was going to create an informed electorate - but it simultaneously created a visual electorate, which turned out to be a different thing. Marshall McLuhan saw all of this in <em>Understanding Media</em> in 1964 and was called a charlatan for saying so.</p><p>Social media was going to connect the world.</p><p>Well, it has, and the connection is the problem.</p><p>Every new tool that reshapes a society follows the same arc: it gets pitched as utopia, adopted before anyone understands it, panicked about ten years too late, and regulated (badly) ten years after that. By the time the culture has a theory of what the tool does, the social fabric has already been re-stitched around it, in a structural mismatch between the speed of technological change and the speed of social adaptation. The brain adopting a new tool has never been the brain that understands its second-order effects, because the lag is biological. The telegraph took 50 years to saturate the industrialized world, but the internet took 20, and the smartphone took 10.</p><p>And generative AI has taken half of that to be near-ubiquitous&#x2026;</p><p>The adaptation lag stays constant, meaning each new technology is more disruptive than the last. We&apos;re adopting tools - right now - that will shape the next century without having metabolized the last century&apos;s tools; the printing press hasn&apos;t been fully understood, radio hasn&apos;t been understood, television hasn&apos;t been understood, and the side effects of social media are being &quot;lived&quot; through in real time by people who haven&apos;t yet admitted what it&apos;s doing to us.</p><h2 id="the-war-that-ends-all-wars"><strong>The war that ends all wars</strong></h2><p>Humans don&apos;t go to war despite knowing what war does, they go to war because the knowledge of what it does fades, even though it technically exists. Nobody forgot the pain of WW1. It just became less vivid&#x2026;</p><p>The generation that fought swears never again, and their children believe them, but their grandchildren might not. By the fourth generation, war is an abstraction, something that happened to other people, in old photographs, with outdated weapons. William Tecumseh Sherman spent his last years giving speeches against war to audiences who listened attentively, and then sent their sons to Cuba in 1898.</p><p>The French generation that survived 1918 built the Maginot Line because it couldn&apos;t imagine living through another Somme, but their sons were overrun by a tactic that didn&apos;t exist when the walls were poured, by an enemy they had forgotten to fear. Robert McNamara, the architect of the Vietnam War, produced a documentary in 2003 called <em>The Fog of War</em> in which he admitted that the policies he had designed had been wrong for reasons he actually understood at the time.</p><p>The film was released during the invasion of Iraq; the lessons were on screen, broadcast to millions, but the tanks kept rolling.</p><p>You can teach someone that fire burns, but you can&apos;t make them feel the heat. A lesson that can&apos;t be felt won&apos;t prevent the behavior it describes. Wilfred Owen wrote <em>Dulce et Decorum Est</em> in 1917 about the sweet lie that dying for your country was noble. The poem is taught in every British secondary school; it has stopped zero wars. The interval between great-power wars in Europe from 1648 to 1945 averaged around forty years. That&#x2019;s how long it takes for the generational memory of the last war to fade from the bodies of the people who vote in the next one. The post-1945 peace in Europe is the longest stretch in recorded history, which means we have a decade or two before the generation that could say &quot;I remember&quot; no longer exists in political life.</p><p>What happens then, is what always happens.</p><h2 id="the-moral-panic"><strong>The moral panic</strong></h2><p>Witches in Salem, 1692, where twenty people were executed on evidence so thin the colony issued an apology within a generation. Catholics in Elizabethan London. Comic books in the 1950s, after Fredric Wertham&apos;s <em>Seduction of the Innocent</em> triggered a US Senate investigation and forced the creation of the Comics Code Authority. Rock and roll. Dungeons &amp; Dragons, where a generation of American parents were convinced their children were being recruited into a satanic cult by a dice game. Video nasties in 1980s Britain. The Parents Music Resource Center, chaired by Tipper Gore in 1985, running hearings against heavy metal. Rap music. Violent video games after Columbine. Social media. TikTok. Transgender rights. I feel like I&#x2019;m reciting a depressing cover of We Didn&#x2019;t Start the Fire&#x2026;</p><p>The moral panic follows the same sequence every time. A new thing emerges that the older generation doesn&apos;t understand, and someone somewhere claims it&apos;s destroying children. The media amplifies the fear, and legislation follows. The panic burns out.</p><p>Then, twenty years later everyone agrees it was overblown.</p><p>Then, the next one begins.</p><p>The moral panic is a reaction to a loss of control; it&apos;s the terror that arises when a parent, or a culture, realizes the next generation is building a world they can&apos;t enter. The target changes every twenty years, but the terror doesn&apos;t change at all. The sociologist Stanley Cohen named the phenomenon in 1972 in <em>Folk Devils and Moral Panics</em>, writing about British seaside brawls between mods and rockers. The book could have been written about anything. A manufactured villain, a media cycle, a legislative response disproportionate to the threat etc, maps cleanly onto every subsequent panic, including the ones he couldn&apos;t have predicted. QAnon is a moral panic. So is the 1980s satanic-ritual-abuse craze that it grew out of, during which adults were sent to prison for crimes that forensic evidence later showed had never occurred. A panic doesn&apos;t have to be wrong to be a panic. It just has to be out of proportion, and they almost always are.</p><h2 id="the-empire"><strong>The empire</strong></h2><p>We all think our specific empire is the exception.</p><p>Rome believed it was eternal. The Chinese dynastic system believed in the Mandate of Heaven as a stable arrangement between rulers and cosmos, which is why each new dynasty claimed to have received the mandate from the last. The British believed their empire was a civilizing force that would last centuries. The Americans believe they&apos;re not an empire at all. Every imperial project follows the same arc: expansion driven by economic need, sold to the public as ideology. Overextension, and the cost of maintenance exceeding the benefit of possession. Internal rot funded by external extraction, and the slow or sudden loss of the periphery while the center insists everything is A-OK.</p><p>Edward Gibbon began publishing <em>The Decline and Fall of the Roman Empire</em> in 1776, the same year the American colonies declared independence from the British. Joseph Tainter&apos;s <em>The Collapse of Complex Societies</em> in 1988 argued that civilizations fail when the marginal return on complexity flips negative, which is a technical way of saying that empires break when each new administrative layer costs more than it adds. The Romans kept adding layers until the layers collapsed under their own weight, and eery subsequent empire has done the same.</p><p>Empire is an emergent property of human social organization at scale. Dominance hierarchies scale, as they always have, and they always produce the same endpoint: a system too large to govern, too expensive to maintain, too proud to contract voluntarily. The final stage is denial. The senators in Honorius&apos;s Rome debated traditional agricultural policy in 410 CE while the Visigoths were sacking the city; the Ottoman Porte in 1911 was still issuing decrees about the administration of the Balkans after it had lost them; the bureaucrats of the Third Reich set a record for how many memos they were writing and sending in 30 days or so befoe Hitler&#x2019;s suicide; the British government after Suez spent a decade insisting that the empire was managing an orderly transition, a phrase that meant nothing because nobody was managing anything; the Soviet Politburo in 1988 was discussing the modernization of Cuban sugar exports while their own economy imploded.</p><p>When the center begins to legislate the future of a periphery it no longer controls, the collapse is already underway.</p><h2 id="the-god-cycle"><strong>The God cycle</strong></h2><p>Religions rise when the existing structures of meaning collapse. They institutionalize, they accumulate power and wealth, they become the thing they were founded to resist and they calcify. A new crisis of meaning arrives, and a new religion, or reformation, or spiritual movement rises up to replace them. The cycle runs from the Axial Age (Karl Jaspers&apos;s name for the period between 800 and 200 BCE when Confucius, the Buddha, Zoroaster, the Hebrew prophets, and the pre-Socratics emerged, each proposing a new relationship between the human and the cosmos) through the European Reformation, the First and Second Great Awakenings in America, the political religions of the 20th century, and the current explosion of secular faith substitutes - from Wellness to Bitcoin.</p><p>The true believers in CrossFit and the true believers in early 4th-century Arianism have more in common than either would like to admit. So do the adherents of long-form supplement protocols and the followers of Girolamo Savonarola, who burned the vanities in Florence in 1497 and was himself burned at the stake a year later. The impulse to purify the self through ritual deprivation is older than any of the current practitioners know - Bryan Johnson is reinventing the early Christian ascetic and selling it as biometrics. The brain requires narrative. When one narrative fails, it doesn&apos;t default to a net-zero narrative, it just grabs the nearest replacement, however ragged. This = a neurological need for meaning and coherence that no rational framework has ever been able to satisfy. The experiments of Michael Gazzaniga on split-brain patients in the 1960s showed that the left hemisphere of the human brain will manufacture an explanation for any observed behavior, including behaviors it didn&apos;t cause, rather than admit it doesn&apos;t know.</p><p>The brain won&apos;t tolerate a gap in the story, and if you don&apos;t give it a religion, it will invent one. The content of belief changes but the need for it doesn&apos;t, which is why the most confident atheists end up sounding the most religious. It&#x2019;s the same apparatus, different idol.</p><h2 id="the-exhaustion"><strong>The exhaustion</strong></h2><p>Deforestation in Mesopotamia by 2000 BCE left the fields salt-crusted and the population migrating; soil depletion in Roman North Africa turned the granary of the empire into desert within three centuries; the residents of Easter Island cut down every tree on the island, lost the ability to build canoes, and were reduced to eating the dead by the time Europeans arrived in 1722; the 19th-century guano trade reshaped Pacific geopolitics around bird excrement until the deposits ran out. Whale oil, coal, petroleum, silicon, compute, housing etc. And on it goes.</p><p>Every civilization finds a resource, builds itself around that resource, burns through it, and either collapses or scrambles for the next; it&#x2019;s temporal discounting, the brain&apos;s systematic undervaluation of future consequences relative to present rewards, running at civilizational scale. The Atlantic cod fishery off Newfoundland was fished every year for 500 years, and then, in the decade after 1992, it collapsed and has never returned.</p><p>The Canadian government knew the catch was unsustainable in the 1980s, but the boats went out anyway. They had mortgages to pay. Every generation knows it&apos;s borrowing from the future, but no generation stops. The cognitive machinery that would allow them to care enough doesn&apos;t exist.</p><h2 id="the-revolution-that-becomes-the-thing-it-replaced"><strong>The revolution that becomes the thing it replaced</strong></h2><p>The French revolutionaries executed a king and installed an emperor.</p><p>The Bolsheviks overthrew a tsar and built a new one, with secret police larger and more thorough than the Okhrana had ever been. The Iranian revolution deposed the Shah in 1979 and produced a theocracy whose morality police have arrested more women than SAVAK ever did. The anticolonial movements across Africa and Asia expelled foreign rulers and produced domestic dictators within a generation. The tech companies &#x201C;disrupted&#x201D; monopolies and became monopolies. Every revolution promises a break from the past and delivers a reproduction of it.</p><p>This is close to structural; the act of seizing power requires the construction of hierarchies, the concentration of authority, and the suppression of dissent, the exact things the revolution was against. The tools of liberation turn out to be the tools of control&#x2026;they have to be, because they&apos;re the only tools that work.</p><p>Robespierre in 1793 believed he was defending liberty by executing 17,000 people in ten months. By the time the guillotine took him too, in July 1794, the mechanics of the Terror had built a state apparatus more centralized than anything Louis XVI had commanded. Milovan Djilas, once a senior official in Tito&apos;s Yugoslavia, wrote <em>The New Class</em> in 1957 from his prison cell, describing how the communist revolution had produced a bureaucratic elite with privileges indistinguishable from the aristocracy it replaced. He was right, which is why he was in prison.</p><p>The revolution is in the method; you can&apos;t win by being peaceful against a state that isn&apos;t, and you can&apos;t build by refusing to govern. But the moment the revolutionaries become the government, they become the state, and the state has structural interests. Those interests don&apos;t care who&apos;s running it. George Orwell, who had seen the Spanish Civil War up close in 1937, understood this well enough to write <em>Animal Farm</em> about it in 1945 and <em>Nineteen Eighty-Four</em> about it in 1949. Both books are taught in schools, and both are cheerfully ignored in practice. The revolutionaries who most need to read them are always the ones who believe the books can&apos;t possibly be about them&#x2026;</p><h2 id="the-cassandra"><strong>The Cassandra</strong></h2><p>Every loop has someone who sees it coming, and they&apos;re never believed.</p><p>The evidence is strong, but the warning is unwelcome, and unwelcome beats true...</p><p>Jeremiah in Jerusalem before the Babylonian conquest was ridiculed in the temple courts, and thrown into a cistern, only to be vindicated after the fact by the destruction of everything he had warned about. Cato the Elder ended every speech with <em>Carthago delenda est</em> until his colleagues stopped listening. Churchill in the 1930s, was frozen out of government, still warning about German rearmament to a House of Commons that preferred to discuss cricket. Eugene Stoner testified before Congress in the 1960s about the inadequacy of the M16 rifle he had designed, and the Pentagon ignored him until American soldiers in Vietnam started being found dead with their rifles in pieces in their hands. The climate scientists of the 1980s, whose testimony was televised and archived and treated, for four decades, as the background noise of cable news. The economists who called the 2008 crash, including Raghuram Rajan at Jackson Hole in 2005, and were told by Larry Summers that their analysis was &quot;slightly Luddite.&quot; The epidemiologists who warned about pandemic preparedness in 2015, whose reports were filed, then forgotten, then pulled off the shelf in March 2020 when there was no longer time to act on them.</p><p><em>Accurate prediction doesn&apos;t lead to prevention.</em></p><p>The reason is part political: acting on a warning is expensive, and ignoring it is free, up until it isn&apos;t. But it&#x2019;s equal parts cognitive: the brain treats unfamiliar threats as less real than familiar ones, regardless of probability. Shark attacks over car crashes; plane crashes over heart disease; terrorist attacks over obesity. The risks that kill us are not the risks that frighten us, because the brain evolved in an environment where the frightening things were almost always the things that killed us, and we haven&apos;t updated the pattern.</p><p>Cassandra herself, in the <em>Iliad</em> and the <em>Aeneid</em>, was cursed by Apollo to always tell the truth and never be believed. Virgil gave her the line: <em>insani Vatis verba</em>, &#x201C;the words of a madwoman.&#x201D; Even without divine curse, the outcome is the same: truth has rarely been sufficient.</p><h2 id="the-loop"><strong>The loop</strong></h2><p>The loops are caused by the species. Bad luck, bad leaders, and bad cultures show up in every story but they don&apos;t generate the pattern. The pattern is downstream of the brain that produces the stories. That&apos;s the argument.</p><p>But can the loops be broken?</p><p>So far, the answer is discouraging; but they have occasionally been lengthened. The interval between crises has been extended, the damage mitigated, and the recovery accelerated. The post-1945 international order bought 80 years of relative peace in Europe by building institutions designed to resist the strongman loop - a massive, landmark accomplishment, but an accomplishment with an expiration date, because the institutions are only as good as the generation running them, and that generation is dying off in real time.</p><p>The bubble loop has been shortened in some respects by regulation and lengthened in others by cheaper borrowing; the scapegoat loop has been softened in many places by norms of tolerance, which the current decade is stress-testing; the empire loop has been delayed for the United States by a combination of military spending and currency dominance, neither of which is permanent; the invention loop has been accelerated by every successful attempt to regulate it, because the regulation creates markets for jurisdictional arbitrage that didn&apos;t exist before.</p><p>We&apos;re very good at making the loops run faster.</p><p>We&apos;re not so good at stopping them.</p><p>The loops persist because the brain persists, and you can build a fence around a feature of human cognition. You just can&apos;t. The loops are a tendency of the species, and you can push back against a tendency within limits that go only so far.</p><p>Seeing the loop while you&apos;re inside it is a good deal harder than it sounds. Every bubble feels like a new era, and everyone saying otherwise sounds like a total bore. Every strongman feels like a savior, at least until the night he stops taking questions, and every scapegoat feels like a real enemy, because your cousin lost his job last month and somebody <em>has</em> to have taken it. Every war feels necessary. Every panic feels justified. Every empire feels eternal and every new God feels true. Every resource looks infinite right up until it isn&#x2019;t. Every revolution feels pure for about eighteen months. Every Cassandra looks hysterical.</p><p>Every mistake of the past was made by people who were certain they weren&apos;t making it.</p><p>The move, if there is one, is the move the Trojans couldn&apos;t make, the one the Weimar voters couldn&apos;t make in 1932, the one the subprime borrowers couldn&apos;t make in 2007, the one the American cod fleet couldn&apos;t make in 1991. Treat the thing that feels obviously true with the utmost suspicion. Look for the loop in the direction you most want to walk. Ask whether the people you most agree with are the same people who would have agreed with the crowd at every previous iteration of this same mistake. It won&apos;t save you - but it might slow you down. The loop is older than any of us, and the loop has been true for 10,000 years. I think it will be true tomorrow. The only thing we get to decide is what we do with the knowledge in the interval between now and whichever loop is already closing around us.</p> <div class="kg-card kg-cta-card kg-cta-bg-grey kg-cta-minimal " data-layout="minimal"> <div class="kg-cta-sponsor-label-wrapper"> <div class="kg-cta-sponsor-label"> <span style="white-space: pre-wrap;">SPONSORED</span> </div> </div> <div class="kg-cta-content"> <div class="kg-cta-content-inner"> <div class="kg-cta-text"> <p><span style="white-space: pre-wrap;">Westenberg is designed, built and funded by my agency, Studio Self. Reach out and work with me:</span></p> </div> <a href="https://www.thisisstudioself.com/?ref=joanwestenberg.com" class="kg-cta-button " style="background-color: #000000; color: #ffffff;"> Work with me </a> </div> </div> </div> Update #2 on the Framework Saga - Kev Quirk https://kevquirk.com/update-2-on-the-framework-saga 2026-04-27T13:41:00.000Z <p>In case you hadn't heard (it's all I've been going on about for a couple weeks, so you probably have heard - sorry) <a href="https://kevquirk.com/i-may-have-killed-my-framework-13">I spilled coffee on my Framework 13</a>, then after lots of testing and cleaning, I confirmed that <a href="https://kevquirk.com/update-on-my-coffee-ridden-framework-13">the main board was dead</a>.</p> <p>The new main board was delivered this morning, so I went ahead and got it fitted to the chassis. Problem is, I'd pissed about the partitions on the 2TB NVMe so I could dump my install on the 1TB NVMe in <a href="https://kevquirk.com/thinkpad-t480-initial-thoughts">my new ThinkPad T480</a>. I tried booting up and fixing the 2TB NVMe, but it was screwed, so I cut my losses and went for a re-install of Ubuntu 24.04 instead.</p> <p class="notice">I'm aware that Ubuntu 26.04 LTS has been released, but I prefer to wait for the first point release before upgrading.</p> <p>After 10 minutes or so, the plucky little Framework was alive!</p> <p><img src="https://kevquirk.com/content/images/update-2-on-the-framework-saga/new.webp" alt="new install" /></p> <p>So I spent most of the day (on my day off) configuring the fresh Ubuntu install back to how I had it before. Luckily the ThinkPad is working great, so I could use that as a reference to get everything pretty much exactly the same. After 3 or so hours work, we're back up and running with all my apps, data, and config restored.</p> <p><img src="https://kevquirk.com/content/images/update-2-on-the-framework-saga/done.webp" alt="done" /></p> <h2>Another issue</h2> <p>While setting up the laptop, I noticed that there was an issue with the screen. At first I thought it was just some residue from coffee-gate, but on closer inspection it looks like the bottom corner has somehow de-laminated.</p> <p><img src="https://kevquirk.com/content/images/update-2-on-the-framework-saga/screen.webp" alt="screen" /></p> <p>I <em>know</em> this wasn't caused by the coffee spillage, as the stain would be brown. Plus the laptop would smell. I'm wondering if it's some isopropyl alcohol, or contact cleaner, from when I cleaned it out.</p> <p>The only other explanation is that it has de-laminated due to the heat in the conservatory, but I doubt it. It doesn't get <em>that</em> hot in there, and it's only April.</p> <p>This is the second problem I've had with screens on the Framework. The bottom of the screen de-laminated <a href="https://kevquirk.com/my-first-week-with-the-framework-13">just a week after I got the laptop</a>. I thought it was a fluke, and Framework support sent me a replacement immediately, but this has me thinking that the screens just aren't that good.</p> <p>Can anyone else who has a Framework 13 confirm if they've had issues with the 2880x1920 display?</p> <h2>Final thoughts</h2> <p>Anyway, this is the last update in the saga. For all intents and purposes the Framework is now repaired. I'm waiting to hear back from Framework support to see if they have any recommendations, but if not, I'll probably have to buy a new screen too.</p> <p>It's lovely to be back typing this post on the Framework. I've really missed this laptop, and the typing experience.</p> <p>Geez this has been one expensive mistake! Take note, people - if you drink coffee around your computers, keep a lid on the cup!</p> <div class="email-hidden"> <hr /> <p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p> <p>You can <a href="mailto:19gy@qrk.one?subject=Update%20%232%20on%20the%20Framework%20Saga">reply to this post by email</a>, or <a href="https://kevquirk.com/update-2-on-the-framework-saga#comments">leave a comment</a>.</p> </div> All You Fascists (Bound to Lose) - Werd I/O 69ef661a825c3600019fc959 2026-04-27T13:39:32.000Z <img src="https://storage.ghost.io/c/18/7c/187cc681-d3f3-49fc-87de-b01d06b76821/content/images/2026/04/Woody_Guthrie_2.jpg" alt="All You Fascists (Bound to Lose)"><p>I&apos;ve had &quot;All You Fascists (Bound to Lose)&quot; in my song rotation for a little while &#x2013; for, you know, <em>reasons</em>.</p><p>Bette Midler&apos;s getting some coverage for her cover, so I thought I&apos;d round up some other versions I like very much.</p><p>To begin with, here&apos;s that Bette Midler cover:</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/uBj57ivPsxQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="ALL YOU FASCISTS (Bound to Lose) Music Video Bette Midler"></iframe></figure><p>This <a href="https://www.resistancerevivalchorus.com/?ref=werd.io" rel="noreferrer">Resistance Revival Chorus</a> with Rhiannon Giddens version is probably my favorite: upbeat and alive.</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/dWUa7aAIfLE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="Resistance Revival Chorus with Rhiannon Giddens &quot;All You Fascists Bound To Lose&quot;"></iframe></figure><p>The <a href="https://www.billybragg.co.uk/?ref=werd.io" rel="noreferrer">Billy Bragg</a> version with <a href="https://wilcoworld.net/?ref=werd.io" rel="noreferrer">Wilco</a> is really strong too: </p><figure class="kg-card kg-embed-card"><iframe width="200" height="150" src="https://www.youtube.com/embed/SFPL97m2dsw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="All You Fascists"></iframe></figure><p><a href="https://www.yahoo.com/entertainment/music/articles/nina-hagen-live-forever-133000223.html?ref=werd.io" rel="noreferrer">Nina Hagen&apos;s</a> father Hans was a Holocaust survivor held at Moabit, and her paternal grandparents were murdered at Sachsenhausen. This is therefore a very personal cover:</p><figure class="kg-card kg-embed-card"><iframe width="200" height="150" src="https://www.youtube.com/embed/FMDgqMdpBMs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="All You Fascists Bound to Lose"></iframe></figure><p>Here&apos;s <a href="https://anidifranco.com/?ref=werd.io" rel="noreferrer">Ani DiFranco</a> with <a href="https://zeoboekbinder.com/?ref=werd.io" rel="noreferrer">Zoe Boekbinder</a>, <a href="https://www.gracieandrachel.com/?ref=werd.io" rel="noreferrer">Gracie and Rachel</a>, and <a href="https://www.dianepatterson.org/?ref=werd.io" rel="noreferrer">Diane Patterson</a> - all artists I love:</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/BbjCtIaMwBg?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="Boundalose - Ani DiFranco w/ Zoe Boekbinder, Gracie and Rachel, and Diane Patterson live on the Mall"></iframe></figure><p>And finally, here&apos;s the great <a href="https://woodyguthrie.org/?ref=werd.io" rel="noreferrer">Woody Guthrie</a>, one of my heroes, singing the original:</p><figure class="kg-card kg-embed-card"><iframe width="200" height="150" src="https://www.youtube.com/embed/VwcKwGS7OSQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="Woody Guthrie~ All You Fascists Bound To Lose"></iframe></figure> Theatre Review: Hadestown ★★★★★ - Terence Eden’s Blog https://shkspr.mobi/blog/?p=70681 2026-04-27T11:34:27.000Z <p><img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/hadestown-poster.webp" alt="Poster for Hadestown featuring a hand holding a budding flower." width="256" class="alignleft size-full wp-image-70682"/> Anaïs Mitchell has created something magical. I felt like giving a standing ovation after every song. Just pure theatrical joy delivered by a cast who know how to squeeze every drop of emotion from an audience.</p> <p>Perhaps it was sitting right at the front of the stalls, but the opening of Hadestown feels like dinner theatre; almost cosy in its intimacy. The first act is so <em>busy</em> - there are a hundred-and-one things happening on stage that it occasionally becomes overwhelming. The second act is slightly more intimate, but no less dazzling.</p> <p>Having the musicians on stage lends to the feel of being in a nightclub. The stereo separation makes it easier to pick out the various musical threads and brings a lovely texture to the songs. Also, who knew a trombone could steal a show?</p> <p>Lots of the cast sing in their natural accents. A roaring northern Hades versus a Mancunian Orpheus makes for quite the thrilling combination. Having subsequently listened to the Broadway cast recording, it is amazing what a positive difference it makes.</p> <p>And, yes, the obligatory revolve spins the performers on a near-constant merry-go-round. When I am King of the West End, the revolve will be banned for the laze cliché that it is!</p> <p>A stunning show with a killer soundtrack and a delightful set of performers.</p> <p>I&#39;ve written before about how the <a href="https://shkspr.mobi/blog/2024/12/the-art-of-the-pre-show-and-post-show/">pre-show and post-show experience</a> shapes an event. The Lyric theatre is generously sized, so plenty of space to mill about before the show, rather than being crammed into a tiny bar. The toilets weren&#39;t in <em>too</em> bad a condition. Once again, no set dressing in the liminal spaces. Would it have been so hard to mock up some travel posters for the eponymous station? Or have something for people to take photos with?</p> <p>The <a href="https://nimax-theatres.mytoggle.io/shop/hadestown-cocktails-at-the-lyric-theatre">themed cocktail menu was inventive</a> but shockingly expensive, even for London prices. The programme is only a fiver and, unlike other West End shows, is full of interesting information and not just an excuse to cram in adverts - excellent value for money.</p> <p>After the curtain call, we get a few more minutes with the musicians, which was delightful. On the way out there was no leaflet offering a discount on return visits (unlike <a href="https://shkspr.mobi/blog/2026/04/theatre-review-avenue-q/">Avenue Q</a>). There is, apparently, a &#34;Hadestown Passport&#34; which you can get stamped every visit - although I didn&#39;t see any evidence of that.</p> <img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=70681&amp;HTTP_REFERER=Atom" alt="" width="1" height="1" loading="eager"/> Implicit and explicit A.I. - destructured https://destructured.net/explicit-implicit-ai 2026-04-27T04:00:00.000Z <p>In a <a href="https://discourse.ubuntu.com/t/the-future-of-ai-in-ubuntu/81130">recent forum post</a> about Canonical’s plans for Ubuntu, technical lead Jon Seager has drawn a useful distinction between “implicit” vs. “explicit” AI. Explicit, in his schema, denotes AI features that present as AI features, e.g. deploying an AI agent. Implicit features, by contrast, look like the sort of features that were available before AI, but work differently under the hood. Segar frames this in terms of cognitive load: “Implicit AI is about enhancing existing operating system features with the use of AI, without introducing new mental models for users.”</p> <p>His example is “first-class speech-to-text and text-to-speech,” which could be enhanced using LLMs, but without changing the surface-level operation of TTS as a feature. He elaborates:</p> <blockquote> <p>I don’t see these as “AI features”, I see them as critical accessibility features that can be dramatically improved through the adoption of LLMs with minimal (if any) drawbacks. Much of this can be achieved with local inference using open source harnesses and open weight models, which are both accurate and efficient for this use case.</p> </blockquote> <p>Which seems innocuous enough. After all, who isn’t in favor of accessibility? (That, no doubt, is why dedicated AI boosters so often use accessibility features to a11y-wash the less savory aspects of the technology, like its <a href="https://destructured.net/ai-money-environmental-cost">environmental costs</a>.) But does AI-enhancement to TTS features really need to be implicit? And what do we lose when it is?</p> <p>Consider the case of a patient making a support call to their insurance company. Technically, AI can now handle such calls, but their reliability is subject to the vagaries of LLM search and summary functions, which are often dubious, to say the least. Yet, the ability of AI chatbots to produce convincingly human-sounding responses means that auditory cues may not be sufficient to inform the caller that they should change their mental model of the call as a source of guidance. They may reasonably believe that they’re talking to an actual human with the judgment and training required to help them navigate the health insurance system, which may lead them to accept as reasonable some responses that they would have doubted had they known that they were output from an LLM.</p> <p>The important point here is that our hypothetical caller’s confusion is a direct result of the very feature Seagar cites as a good candidate for implicit deployment. The ability of an AI phone agent to replicate human speech is a direct application of text-to-speech voice synthesis. Implicit deployment may seem unproblematic when you focus on the use case of a hearing-impaired person deliberately opening a TTS app, but the same implicit features can wind up misleading the user with potentially serious consequences.</p> <p>The change of context makes implicit deployment almost inherently misleading, a fact that can be exploited by companies that want to be less than wholly transparent with their customers. As a practical matter, we do see AI features being deployed both implicitly and explicitly (as well as in a third class we could call “ambiguously”), and the decision of which approach to take almost always appears to favor the deployer, rather than the end user. Thus, some companies rely on improved voice synthesis and response variability to present a human face to callers, even as they remove human agents from support positions. Making the transition implicit — or, at least, ambiguous — helps obscure and soften the caller’s loss of human contact, along with any attendant loss of agency they might have had in the process of sorting out their healthcare. This practically inverts the <a href="https://ssir.org/articles/entry/the_curb_cut_effect">curb cut effect</a>: Even cases where implicit deployment feels helpful (like TTS for accessibility), it turns out there are significant use cases that entail potentially severe consequences for the end user.</p> <p>I characterized Seagar’s distinction as “useful,” but there’s two sides to that coin. One side is that it gives us terminology for identifying differences in how AI is being deployed, which we can then adapt to the purposes of socially responsible tech criticism. The other is that potentially gives deployers a permission structure for misleading or deceptive practices, like replacing human phone support with undisclosed AI systems, under the auspices of deploying an “implicit AI feature.”</p> <p>So when is implicit deployment legitimate? Almost never. The burden of making AI use explicit is almost always less severe than the potential consequences that could arise from not knowing that a feature uses AI. Therefore, AI deployment should only be implicit when the intent is to deceive. In all other cases, developers should err on the side of caution by deploying AI features only when the AI use can be made explicit.</p>