Latest Posts (20 found)
Unsung Today

“Next up? You know it. You hate it. It’s the invisible wall.”

Tangentially related to the previous post , this 8-minute video from CrowBranch is a fun tier list of various ways games try to keep you in bounds: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/next-up-you-know-it-you-hate-it-its-the-invisible-wall/yt1-play.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/next-up-you-know-it-you-hate-it-its-the-invisible-wall/yt1-play.1600w.avif" type="image/avif"> The limits here are I believe unrelated to precision, and rather to wanting to keep the player within a controlled, designed environment. (We once covered a story of this backfiring horribly , and also talked about skyboxes and streaming .) The video also made me want to see people – especially designers with less experience slash less baggage than I have – doing a tier list of e.g. common interface elements. Or maybe I should make such a video… #errors #games #youtube

0 views
Unsung Today

“This is a sphere getting exponentially angrier as time passes.”

When you learn computer science, at some point you encounter floating-point numbers in all their peculiar glory. Floating-point numbers allow you to store values that are extremely huge or extremely tiny, but that comes with a strange price. The number is still just a number with a regular limited precision, but is accompanied by a floating point – another number that just says how many zeroes to put after or in front. In effect, when your number is millions, you get a precision of thousands. When your number if billions, you can only count in millions, and so on. This makes intuitive sense, in a same way a billionaire doesn’t care about pocket change. (Go to a floating point visualizer , and you will see you can input 9000004 and 9000005 and 9000006 with no problem, but add one more zero and 90000004 will be rounded down to 90000000, and 90000005 up to 90000008. Bigger numbers get even less precise.) This has a strange effect when it comes to videogames or graphic software: The further you move something away from the origin of your universe – where X and Y are 0 – the more you have to worry about its internal precision. This is not a problem in real world. You can send a tiny, incredibly meticulous watch screw far beyond the solar system and back, and it will do fine. But now jump to the digital world, assume Earth is 0:0 – apologies to Copernicus – and now the further away you go, the more the floating point moves to the left, and at some point the precision of the number on the other side runs out; a value that can express billions of kilometers is too coarse to even consider millimeters. This is a fascinating problem which is visualized nicely in this short video . This is what happens when you move an object with its constant internal precision further and further away: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/this-is-a-sphere-getting-exponentially-angrier-as-time-passes/yt1-play.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/this-is-a-sphere-getting-exponentially-angrier-as-time-passes/yt1-play.1600w.avif" type="image/avif"> There are ways around this – you can increase the precision, introduce a “floating offset,” have two precision centers around two floating points, or do a bunch of other things – but each one will cost you. So, sometimes, the best solution is the simplest one: do not allow the numbers to get too big. And this is why Adobe Illustrator, Figma, and I bet at least a few other tools that promise infinite canvas, actually stop you if you stray too far away from the center. Precision is like atmosphere, the canvas says, thinning out the further you go. We cannot promise your structural integrity will survive going past a certain point, so we won’t allow you to do that. Here’s Figma, where I at some point the canvas stops following your scroll commands: The first invisible X value is 131,072 and it’s not a surprise it’s one of these numbers that will look very, very familiar. It seems like a huge enough value, but if you consider a slide in a slide deck is 1920×1080, it’s not as infinite as it might initially seem. And this is also why – in part – Figma Slides manually wraps you after 20 slides: #graphics #youtube

0 views
Theia Today

Coming of a New Sun

Six weeks after the US and China hammered out the latest round of bilateral compute agreements in a midnight deal, reporter Jenny Gesteson visits a south Texas 'dark factory' to see how the machines there - and the minds that operate them - are learning to run themselves.

0 views

Thimbleweed Park 2

I have good news and bad news. First the good news. The good news is that we just started production on Thimbleweed Park 2, due out in early 2028. We will self-publish with the help of a private investor. Mark Ferrari, Gary Winnick, David Fox, Octavi Navarro, Robert Megone, and others from the original team will be back! Wishlist on Steam! I’ll be starting up a Thimbleweed Park 2 dev blog like we did for Thimbleweed Park and posting regularly to keep everyone up to date. Now the bad news There is no bad news, it’s all good news. P.S. Thimbleweed Park 1 is on sale on Steam, Switch, iOS and Google. But I suspect all my readers already own it. P.P.S Steam doesn’t show it yet, but there will be Mac, Windows and Linux. P.P.P.S There will be a GOG version.

0 views
Jim Nielsen Yesterday

The AI Aesthetic

Every zeitgeist comes with new design idioms unique to its challenges. Many of them disappear as fads change, but others bake themselves into deeper parts of existing software interaction paradigms. For example, there’s the hamburger menu (≡) which saw a proliferation during the rise of mobile due to the constraints around screen size. It has since spread to many other parts of software interaction design and will likely remain prevalent for a long time as a terse way of indicating “more menu-type content here”. As another example, before AI what were the connotations of the sparkle emoji ✨? Personally, I don’t know, but now it means AI. (AI = sparkles and rainbow colors — it’s funny when you think about it. They should’ve just thrown unicorns in there for the trifecta. AI = sparkles, rainbows, and unicorns ✨🌈🦄. Apt.) Some patterns are very specific to the interactions inherent to the nature of AI as a technology. For example: streaming text. This is a pattern made for and refined by chat interfaces, so it may not have tons of utility for reuse across other software interaction paradigms. Then there are other patterns that’ve been refined by AI interfaces and are starting to spread to other places in software. For example, the “shimmering text” which in AI land implies a kind of “thinking” but is being repurposed to indicate any kind of asynchronous task (thinking, fetching, computing, etc.). Then there are other influences my subconscious is picking up on. For example, a lot of AI apps use tiny icons. These are most obvious (to me) in desktop Electron apps because they clash with the system-level grain of applications . Take a look at this screenshot, where you have desktop AI apps on the left (Claude, Codex, Cursor) and macOS apps from Apple on the right (Finder, Photos, Mail). You can see how the AI apps all have much smaller, thinner icons than their native counterparts. Are tiny icons our collective future in interfacing with computers? (Personally, I hope not.) There are other aesthetics my brain associates with AI, like beige/cream colors, orange accents, and serif typefaces as well as whack-a-mole UI controls (you know, the ones where you click the toggle and the entire UI repaints and you have to move your mouse somewhere else in the UI to click the toggle again? The non-determinism of AI’s grain has seeped into its UI/X). It all makes me wonder what other aesthetics are being born out of this AI moment and how many will spread, take seed, and become part of common software interaction paradigms for years or decades to come? Reply via: Email · Mastodon · Bluesky

0 views
Brain Baking Yesterday

The 2026 Board Game Shelf Analysis

The yearly recurring thing called the Board Game Shelf Analysis didn’t recur in 2023 and didn’t in 2025. I guess I don’t really like odd-numbered years but I do like to write about this now deemed as a biennial event during the summer. In 2024 , I still had to make due with the smaller hallway closet. Since last year everything was moved to a bigger Kallax that’s still riddled with gaping holes: enough space left to welcome new boxes. But first we have to say our goodbyes to a few ones. Take a look at the photo of the above linked post to inspect the state of the board game shelf in 2022 and 2024. Below is the updated 2026 version, just before selling the culled ones. Please ignore all the baby toys that seem to find their way up, under, and inside every single piece of furniture in our house. The board game shelf, summer 2026 edition. The top right box contains games that should leave the collection. I’m trying to figure out a system starting from the left (in) and ending to the right (out). The idea was also to have a few spaces on eye level where I could place the games that deserve more plays/attention. So what’s gone and what’s new? As mentioned in the 2024 post, we own too many small box 2-player only games that my wife no longer likes to play. Glasgow , Caper , and/or Paris are my next culling candidates. Again, the columns are defined as follows: game name, BoardGameGeek average score ( ), own score ( : Great!, : Good, : Average, : Bad, : No Score, see my grading systems discussion ), BoardGameGeek weight ( ), estimated plays (From ; played a lot, to ; barely played). The table is sorted by plays (most to least). I left out two new dice for Railroad Ink that I have yet to touch and the Kingdom Legacy: Distant Lands expansion that’s also still in shrink wrap. Ouch. That list is longer than I anticipated… Only Fliptown is from 2026 though, the rest is from last year. You might also notice the correlation between a game that gets played and the BGG weight: the heavy hitters sit at the bottom. See my posts on parenting as to why. I’m already more than happy that my wife likes both Dorfromantik: Sakura and The Dice Chambers . It’s really cool to play a tile-laying campaign/legacy style game: the last time we managed to open a new box and envelope and we were really excited to see what’s inside! I got Earthborne Rangers for my 40th birthday last year from a friend. We attempted to start the campaign and played again with more than a month in-between and already forgot most of the rules. He since has moved on to other games he’s into so I think I’ll try and get a solo campaign started instead as I really liked what I saw but I can’t seem to get it on the table. The unopened Spirit Island I got for Christmas is another painful one. I don’t really want to share these stats: in 2024, I wrote Since our baby turned into a rebellious toddler we’ve had to dial back hobby time significantly . Well guess what we had another one and that one loves screaming and kicking around lately. It looks like 2026 is an all-time low when it comes to logged board game plays. The BGG Play Stats in 2026, so far. We’re trying to more actively play something small together after the kids are off to bed which is nice. Writing summaries like these help me ground myself: it seems that I have more than board games enough to cover the next few years. And yet backed versions of Sail Legacy and Dark Venture: Battle of the Ancients still have to make their way to our doorstep. I still read Board Game Quest’s Kickstarter summaries but more cautiously evaluate whether it’s worth it. Click A Tree was a good learning lesson. Today my friend & I played Castles of Burgundy: Special Edition and The White Castle with the expansion. It was a great afternoon to unwind outside (even though we had to seek shelter from the heat after the first game). Related topics: / boardgames / By Wouter Groeneveld on 29 July 2026.  Reply via email . Nightfall was already “culled” in 2024 but I can’t seem to make a sale on that one. It’s out of print and I don’t charge a lot. That is one persistent box! Dungeons, Dice & Danger (Richard Garfield made a roll & write and it’s not very good) French Quarter is just not as good as Three Sisters and I can’t justify owning both Ora & Labora is the one that got felled as I own too many Uwe games and want even more Speaking of which, Click A Tree is a disaster, I wish I didn’t back that one. I also gutted Framework and Robin of Locksley in 2025. Yes I have/had too many Uwe games, I told you. And Nusfjord is on my wishlist. Perhaps also Hallertau ? Conservas is a neat little solo bag building game. I finished the campaign and it has not a lot of staying power after that.

0 views
Unsung Yesterday

“Gravity is worth asking about.”

I’ve enjoyed John Gruber’s posts about ads appearing on an increasing number of Apple surfaces: the App Store, Apple News, and – soon, perhaps – Apple Maps. (Just for reference, here’s an example of such an ad.) = 3x)" srcset="https://unsung.aresluna.org/_media/gravity-is-worth-asking-about/1-framed.1600w.avif" type="image/avif"> In a post earlier this week , Gruber likened ads to stickers on laptops, and shared a fun Steve Jobs story: That’s what those stickers on PCs are: they’re ads. Intel pays for the “Intel Inside” stickers that booger up PC laptop palm rests. Longtime readers will recall that back in August 2007 , Apple held a Town Hall event to introduce new iMacs and some iLife and iWork software updates. In a post-event Q&A (imagine that), Bob Keefe of Cox Newspapers asked “Can you say why you all are not participating in the Intel Inside program, putting the stickers on your new or previous Macs?” This question was so absurd from the perspective of those who covered Apple closely that it prompted outright laughter. […] The 2007 exchange went as follows: Keefe: Why are you not participating in Intel Inside program and not putting stickers on your Macs? Jobs: Uh… what can I say? We like our own stickers better. (In case it’s not clear, this was a joke; Apple didn’t and doesn’t put any such stickers on their products.) In May, Gruber posted about Apple’s ads , too, and brought up the zero-one-infinity rule : I feel like a variation of Zero-One-Infinity is a good rule of thumb for ads, too. From the perspective of users — and probably developers — zero was the best number of ads for Apple to show in App Store search results. One was worse but acceptable. But now that they’re showing more than one, they’re on their way to infinity. They’ve started down the slippery slope. Remember when Google only showed one ad in search results? “Slippery slope” is a perfect term. But I wanted to add something here. In my experience, in the realm of UI, there is no middle notch. I’ve seen it time and time again… the moment you open the door to One, Infinity starts exerting its pull: Here are two examples I’ve been thinking about recently: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/gravity-is-worth-asking-about/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/gravity-is-worth-asking-about/2.1600w.avif" type="image/avif"> This – screenshotting in iOS – was originally just one fork: Save or Delete. Now it’s a staggering five options I have to choose from, every time, even if I never touch four of them: Once you wedge one thing in the door, it’s really hard to stop. My theory is that this is because digital interfaces are pretty much all infinitely extensible. There will always be a way to add one more button, one more link, one more setting, one more ad. If something doesn’t fit, you make it smaller. If making it smaller looks bad, you add a scrollbar. If a scrollbar doesn’t feel right, there’s always overflow. Not only it’s very hard to create interfaces that have limitations, but a bad decision is not just precedent – it’s code that can be copied and reused. Existing code always had tons of… well, gravity, even before LLMs. And so, products grow complex without anyone intending them to; a new team adds just one more thing, which in isolation always feels like nothing to worry about. The Hick’s Law , the extra mental load , the complexity all grow in between those moments, in a no-man’s land no team typically feels responsible for. The logic is always circular: Why would the team adding a third option have to do something a team adding a second option didn’t have to do? Why would the team adding the second option worry in advance about option number 5? This is why it’s important to hire and recognize people who will understand that those limitations have to be imposed arbitrarily, and empower them to be able to say, “Let‘s not add this. We like our own stickers better.” = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/gravity-is-worth-asking-about/4.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/gravity-is-worth-asking-about/4.1600w.avif" type="image/avif"> (My MacBook does have a sticker, which I bought and put on it since for some reason I find it really funny.) #complexity #system design adding just one setting will send a message that We Do Settings Now and more settings will follow, one uncomfortable exception followed by weeks of deliberations will inevitably open the door to subsequent mindless exceptions, one cheap or lazy approach can spread through the interface like rust, subconsciously telling people “cheap and lazy solutions are okay here.” This right click menu in Chrome started with just one fork (new window or new tab) – now there are three alts that I have to choose between, every single time, even if I only ever use one option: This – screenshotting in iOS – was originally just one fork: Save or Delete. Now it’s a staggering five options I have to choose from, every time, even if I never touch four of them:

0 views
Justin Duke Yesterday

Cursed knowledge

Nick pointed me towards Marcin who pointed me towards immich's list of cursed knowledge the other day, and it has already become a running joke in the Slack. Here is a baker's dozen of Buttondown's own cursed knowledge: 1 Yes, that's the joke. The Python library assigns the device family to every non-Mac desktop browser The HTML attribute only filters what the file-picker dialog shows you; drag-and-drop and clipboard paste bypass it entirely. Safari and Chrome re-serialize quoted CSS custom-property strings differently when you read them back via : Chrome keeps the single quotes, WebKit rewrites them to double quotes. Django emits a — which fails our CI — for any cache key over 250 bytes or containing a space or control character. Python's has no default timeout and will, given the opportunity, wait forever. SPF directives recursively chain DNS lookups against a hard cap of ten — exceed it and you get a , which can fail authentication for all of your mail. Outlook and Hotmail enforce mandatory TLS but serve a certificate chain rooting at DigiCert Global Root CA (G1) — a root that Ubuntu has since removed from its trust store. Django's tests whether the key exists , not whether its value is JSON . does not lock rows in the order you listed them — Postgres locks them in executor scan order, which is a wonderful way to deadlock two queries that both thought they were being careful. A postgres cannot exceed ~1MB. Stripe will send subscription update events for paused subscriptions. The Python library assigns the device family to every non-Mac desktop browser The HTML attribute only filters what the file-picker dialog shows you; drag-and-drop and clipboard paste bypass it entirely. Safari and Chrome re-serialize quoted CSS custom-property strings differently when you read them back via : Chrome keeps the single quotes, WebKit rewrites them to double quotes. Django emits a — which fails our CI — for any cache key over 250 bytes or containing a space or control character. Python's has no default timeout and will, given the opportunity, wait forever. SPF directives recursively chain DNS lookups against a hard cap of ten — exceed it and you get a , which can fail authentication for all of your mail. Outlook and Hotmail enforce mandatory TLS but serve a certificate chain rooting at DigiCert Global Root CA (G1) — a root that Ubuntu has since removed from its trust store. Django's tests whether the key exists , not whether its value is JSON . does not lock rows in the order you listed them — Postgres locks them in executor scan order, which is a wonderful way to deadlock two queries that both thought they were being careful. A postgres cannot exceed ~1MB. Stripe will send subscription update events for paused subscriptions.

0 views
Hillel Wayne Yesterday

Logic for Programmers is Now Available

I am delighted to announce that my book, Logic for Programmers , is now available! You can check out the release site here or go directly to buy the ebook or print versions . If you bought any of the early access versions, you can get the 1.0 for free from leanpub . This has been a long time in the making. Formal logic is an incredibly powerful tool to understand software. Everything from “what’s a left outer join” to “why shouldn’t inherit from ” makes more sense if you know just the basics of logic. Yet there weren’t any programmer-focused resources for actually learning those basics. You were just sort of expected to crack open a math book or pick it up through osmosis. The osmosis route doesn’t work. So I spent the last five years making that resource. Logic for Programmers teaches the working developer basic logic and its many applications, covering areas as diverse as property-based testing, domain modeling, and logic programming. It’s meant for people with no math background: if you know AND and/or OR, you can read this book. I researched each chapter’s topic for months, then ran the chapter by a domain expert to make sure it was accurate, then ran it by a junior programmer to make sure it was approachable. Anyway, I am very tired and glad to be done. Thank you so much for reading, and I hope you enjoy the book.

0 views
Corrode Yesterday

Understanding Dyn Compatibility

In Rust, some traits can’t be used as trait objects with . When a trait can’t be used with dynamic dispatch, we say it’s “not dyn compatible.” 1 This has an impact on how you can use these traits in your code. I think that’s one area where the Rust compiler could print a more helpful error message. Fixing the issue is mostly about tradeoffs between compile-time generics and runtime polymorphism and learning when each one fits. Once you understand the concept, you’ll know how to get around the issues by choosing a better design for your trait. If the compiler told you a trait is “not dyn compatible” , your trait can’t be used as because it has a method that can’t go through dynamic dispatch, usually one that returns , takes no , or is generic. To fix it, pick one: Continue reading to understand the tradeoffs between each approach. Here’s an example with code that won’t compile . Say you have a trait that has a method returning a copy of itself: …and there’s a button, which implements : If you tried to compile this code, you’d get an error like this: That all sounds pretty confusing. When you use , Rust creates a trait object . Trait objects use dynamic dispatch to call methods at runtime. Dynamic dispatch just means that the exact method to call is determined at runtime based on the actual type of the object. For dynamic dispatch to work, the trait’s dispatchable API must follow certain rules. These are simplifications: each method-level rule is really “…unless that method opts out with ”, which we’ll see in a moment. Traits also have a few item-level restrictions, such as no associated constants; we’ll summarize the fuller list later. For now, the rough version is enough to build intuition. In our example, we violate the first rule: the method returns , which means “the same type as the implementor of the trait”. When you use , the concrete implementor is hidden behind the trait-object interface. The vtable still points to the right concrete implementation, but the call site has no single concrete return type it can name for . That’s a problem, because the compiler needs to know the size of the return value at compile time, and could be any size . It needs to know the size, because the returned value has to live somewhere : the caller sets aside exactly the right amount of space (usually on the stack) before the call even happens. With a , the concrete type is erased from the caller’s static type, so there’s no single size the compiler could reserve for it. It will become clearer once we look at some fixes. Don’t worry, we won’t have to refactor all our code! All fixes use the same trait example. There are multiple ways to make it dyn compatible. We have a bunch of options: Each approach comes with different tradeoffs. Depending on the kind of dyn-compatibility issue, one might fit better than the others, or you might combine a few. Let’s look at each of these in detail. One common way to fix the problem is to use generics instead of trait objects. Generics resolve to concrete types at compile time , so the compiler knows the size of . The compiler generates a separate copy of the function for each concrete type that implements the trait. Then, at runtime, you no longer need to worry about any dynamic dispatch (which means “figuring out the type at runtime”). The compiler always knows which type it is dealing with, so it can pick the right method to call. Our trait stays the same: But now we change the function which uses the trait to use generics instead of : Note how we changed the function signature to use a generic type parameter that implements the trait. Here we tell Rust: “I have some type that implements , and I want to use it.” Rust then generates the necessary code for each type used. That’s close to using , but not quite the same. The difference is that with generics, the compiler knows the concrete type at compile time, so it can handle correctly. For instance, we might know that is in this case, so returns a . Now the confusion about what means is gone! The downside is that you can’t fully lean on dynamic dispatch anymore, and you might have to refactor a lot of code if you were using trait objects extensively before. Your binary size might also grow because of all the copies of the function that the compiler generates for each concrete type. What’s the benefit of fully leaning on dynamic dispatch? Fair question! Dynamic dispatch has a bunch of really nice properties: Another option is to keep using trait objects but change the problematic method to only work with concrete types. This means “this method can only be called when has a known size at compile time”, which is true for concrete types but not for trait objects. It’s more explicit, since you control how the trait can be used. The catch is that it limits the trait further down the line: some methods won’t be callable on every trait object, and changing the trait later becomes a breaking change. You won’t be able to call on , but you can still call it on concrete types like . So you keep most of the flexibility of trait objects (unlike with generics), as long as you remember that some methods won’t be available through . We can change the return type of the problematic method to return a boxed trait object instead of . This works because has a known size at compile time. It’s a pointer to an object on the heap. It’s actually a fat pointer : two words wide, or 16 bytes on a 64-bit system, because it also stores a pointer to the vtable; more on that later. What matters is that this size is fixed and known at compile time, unlike , which varies based on the concrete type. The downside is that tends to be viral in your codebase. You’ll end up writing more often than you’d like, which gets noisy. On top of that, this fix only works for methods that return . If your trait also has static methods or generic methods, you’ll need to combine this approach with one of the other fixes. Sometimes the best solution is to separate the dyn-compatible methods from the problematic ones into different traits. Maybe your code is silently trying to tell you that you are mixing up two different responsibilities and that they should be untangled. In general, prefer smaller, focused traits over large, monolithic ones. Traits are not interfaces! Instead, we lean on composition and focus on behavior rather than mangling multiple ideas into a single trait. Here’s a more realistic example: separating rendering from widget creation. Factory methods are often static (no parameter), which makes them incompatible with . So we split them off into a separate trait. When you write , you’re creating a trait object . It’s a special kind of value that consists of two pointers (a “fat pointer”): As you can see, a trait object has: The vtable is created at compile time and contains pointers to the methods for the specific type. It is common in many programming languages that support dynamic dispatch, such as C++, C#, or D. When you call a method on a trait object, Rust uses the vtable to look up the correct function to call based on the actual type of the data. For dynamic dispatch to be sound, the vtable-facing methods need stable, concrete function signatures: If a trait has dispatchable methods that return or have generic parameters, there is no single vtable entry with one concrete signature that can represent all possible calls. That is the root cause of dyn compatibility issues. A trait is dyn compatible if it follows a list of rules . The rules boil down to the same core issue: the interface must have a finite, statically-known shape even though the concrete implementor behind it is hidden. A Modern Gotcha: in Traits Since Rust 1.75 , you can write directly in a trait. But there’s a catch: a trait with an is not dyn compatible . An desugars to a regular method that returns , a hidden return-position . The type is called “opaque”, because we don’t know what it is, and the compiler doesn’t expose it to us. Opaque return types aren’t dispatchable (which means we can’t put them in a vtable of functions), so the trait can’t be used behind . If you need dynamic dispatch with async methods today, you have a few options: Dyn compatibility determines if a trait can be used with . The rules exist because: If your trait is not dyn compatible, don’t worry! Many standard library traits ( , , etc.) are also not dyn compatible. As we’ve seen, there are ways to work around these limitations with type erasure, generics, or more fine-grained traits. Which fix to reach for depends on what your trait needs and what you’re willing to give up: In practice you’ll often combine these. For example, splitting a trait and boxing a return value. I find it interesting to see how dyn compatibility evolved over time in Rust. If you do, too, here are some resources to dig deeper: The lang team also wants a “practical path” to call s through natively. It’s on the 2026 project goals , so the async gotcha above should ease over time. The concept used to be called “object safety” until Rust 1.84.0. If you’re reading older resources, they mean the same thing. The name got changed because it was confusing. “Object safety” suggests that Rust has “objects” in the traditional OOP sense and that the term is about “safety”, which is misleading. The new term “dyn compatibility” does a better job of saying that it’s about whether a trait can be used with for dynamic dispatch. I still don’t love either term, but I also can’t think of a better name that is both short and accurate. ↩ add to the offending method return instead of use generics instead of split the trait in two What does “not dyn compatible” mean? Shouldn’t the part take care of it? What’s a “vtable”, and why does the trait need to “allow building” one? What does it have to do with ? Dispatchable methods must not return . Dispatchable methods must have an allowed receiver ( , , , and a few related pointer forms). Plain static methods don’t have one. Dispatchable methods must not have generic type parameters. Use generics instead Opt out problematic methods with Return boxed trait objects instead of Split into two traits It’s very flexible. You can swap out implementations at runtime, which is great for plugins or when you want to change behavior without recompiling. It allows for polymorphism. You can treat different types that implement the same trait uniformly, which can simplify code that needs to work with various types. You could technically do the same with generics, but sometimes you can’t afford the increase in code size or compile times that come with monomorphization. It can lead to cleaner and more maintainable code in certain scenarios, especially when dealing with complex hierarchies of types and behaviors. For example, take a graphics rendering engine where you have different shapes (circles, squares, triangles) that all implement a trait. Using dynamic dispatch, you can store them all in a single collection and call . If you were to try the same with generics, you’d end up with a lot of boilerplate code to handle each shape type separately. A data pointer that points to the actual data (the concrete type implementing the trait) A vtable pointer that points to a table of function pointers for the methods every dispatchable method needs a receiver that leads to the object and its vtable argument and return types must be expressible without knowing the hidden concrete the vtable must contain a finite set of function pointers, known at compile time Box the future yourself and return . Use the crate, which does that boxing for you. Use the crate, which generates a dyn-compatible wrapper for traits with . Trait objects use dynamic dispatch via vtables Vtables are static, compile-time structures, which hold method pointers Type information is erased at runtime to allow polymorphism The compiler must guarantee type safety at all times, even if it can’t see the concrete type 2014-09-22: RFC 255 - Introduced object safety (2014, before Rust 1.0) 2014-11-03: Issue #428 - Object-safety and static methods 2015-01-03: RFC 546 - Removed implied bound on traits 2023-08-24: Rust 1.72 - GATs can be opted out with 2023-12-28: Rust 1.75.0 - Stabilized and return-position in traits (though such traits still aren’t dyn compatible) 2025-01-09: Rust 1.84.0 - The docs had moved from “object safety” to “dyn compatibility” around this release cycle; the tracking issue notes that the rename unfortunately missed the release notes. The concept used to be called “object safety” until Rust 1.84.0. If you’re reading older resources, they mean the same thing. The name got changed because it was confusing. “Object safety” suggests that Rust has “objects” in the traditional OOP sense and that the term is about “safety”, which is misleading. The new term “dyn compatibility” does a better job of saying that it’s about whether a trait can be used with for dynamic dispatch. I still don’t love either term, but I also can’t think of a better name that is both short and accurate. ↩

0 views
Hugo Yesterday

My Software Factory in the Age of AI

I'm creating this page to document my "software factory". It will be more of a reference page than an article and I will reference it on the resources page of the site. Context : several applications in monorepos ( hakanai , Writizzy , Bloggrify ), polyglot (Nuxt, Kotlin, JS), solo dev, code written largely by agents, continuous deployment to production. ::toc{open="true"} :: Even though the latest generation of agents are now capable of producing quality code (much better than the majority of human developers), code production represents only part of what I call software quality. The rest includes: Part of these risks is resolved with a good understanding of your market, benchmarks, interviews, manual testing, mockups. All of this is also part of my "software factory" even if I don't describe everything here. The code produced is now almost 100% generated, but that doesn't mean it's vibe coding. Vibe coding as defined by Karpathy was experimentation and letting yourself be carried along by a dev session. Here, I'm going to talk about context engineering. The goal is to provide all the necessary context, at the right time, so that the software matches an intention and is systematically controlled. Even though I don't write the code, I'm responsible for it and I need to maintain control over it. The tooling described here answers several questions: Here are the files read by agents before starting. Be careful, the size of the context must remain controlled. Too large a context costs money and degrades the quality of responses if it becomes too heavy. We want to save tokens and optimize when information is loaded. The separation matters: permanent context stays short, specialized context loads when it's useful. Long-term constraint as context. Concrete example: I plan to open-source part of the code. The rule "code intended for open source should never depend on proprietary code" is written in the rules and verified by a test (see layer 4). Writing a future constraint in the context avoids paying for a refactoring later. You can also find constraints on: A constraint is specific to a project and a person. It's not a matter of software quality in the strict sense. It's not better or worse to do feature flagging for example, but it's my preference for partial deployment and feature activation in testing. There's no point in telling an AI to "write quality code", it doesn't make sense. You need to make your own constraints explicit. Example of a rule that allows deferred loading depending on context: It's simple, but it avoids loading the entire skill in a rule (which would be loaded systematically). Here's a more complex rule: Here there are two important things: A skill is a procedure written once, replayed identically. The agent loads it itself when the context matches. This automatic loading can sometimes fail. In that case, you need to explicitly ask to use the skill. The criterion: am I repeating myself? If I explain the same thing a third time, it becomes a skill. I have about thirty, grouped by family: Two things I've learned: Sub-agents : for tasks that generate a lot of reading without much decision (audit, broad exploration, doc writing), I delegate to a sub-agent. It consumes its own context and gives me a conclusion, not a dump of files. I use them less and less, recent agents make their own fairly targeted delegations. You often hear that an AI is non-deterministic and can make mistakes on trivial things that need to be deterministic, like calculating 2+2. That's largely false now, and an AI is no longer "just an LLM": it has many tools to control output. Nevertheless, the best way to ensure a form of reproducibility is to delegate to tools whose job it is. Compilation, test execution, linters, all of that is delegation. You can delegate to MCPs, or to skills that use themselves a command-line tool (CLI). I try to avoid MCPs which consume more context, but I have a few anyway. The repo is indexed in a graph (symbols, relationships, execution flow). This allows you to measure impact levels and find all links with the code being modified: The real issue isn't speed, it's detecting all side effects of a modification. I use two levels of memory: What we want with these tools is to avoid repeating mistakes, document decisions, and not start over with an empty session each time. Claude Code's internal memory mechanism has improved and becomes more relevant than before with the latest versions. However, you need to control it and not hesitate to ask it to delete rules it creates on its own which are sometimes a bit silly. Claude-mem, I honestly have a hard time measuring the negative or positive impact. I don't have enough perspective on it yet. A wrapper (here RTK) prefixes shell commands and only returns what's necessary. It remains very limited, only available for a few tools. The gain is sometimes canceled out because Claude runs the command twice. It doesn't hurt, but I think there's still room for improvement. Note that Claude builds its own tools on the fly in Python or Bash, and also knows how to use filtering mechanisms with , , etc. to optimize the outputs of the tools it uses itself and save tokens. I use two skills for incident resolution: I could also mention the Stripe MCP, read-only as well, which allows in certain specific cases to investigate Stripe configuration issues. Guardrails prevent the randomness associated with understanding and executing an instruction. It happens that an LLM ignores a rule. You need to provide tools that execute automatically. Scripts triggered by the agent harness, not by the agent itself. Other uses that work well: block editing of generated files, require a test alongside any new module, forbid a dangerous pattern. Structuring rules become tests that break the CI. Real example, I have an architecture test that preserves the boundary between future open source code and the rest: It's part of the automated tests, so it can't be bypassed, unlike a rule. I use several things: Each app has its workflow on GitHub Actions. The deployment job has a on the quality job. Nothing goes to production without passing the gate. It's essential in general, even more so for automatically generated code. I shouldn't need to re-explain this, but just in case, I have several types of tests. I give Claude instructions to explain the test hierarchy, gitnexus tells him what to replay to validate these modifications, and he has instructions to write them when he adds/modifies code. As I said in the intro, the goal isn't just to produce code, it's to produce code that serves a purpose. The process often starts with a spec, then a design, then an implementation. Spec first. I have a folder of numbered specs, one per functional domain, indexed in the permanent context. Two skills frame the cycle: one for writing the spec and its plan, one for closing it by updating it with what was actually built. This spec and the discussions can rely on a 'product-marketing-context.md' file that I create in each project and which summarizes my personas, my competitors, my positioning etc... The design. By design I mean two things: technical design and interface. Technical design is part of the spec phase. Most of the time a spec is enough, but some tricky cases require a spec dedicated to a technical component or a technology choice. On the other hand, the design/mockup phase is separate. I do it in Claude Design. I make a functional mockup and iterate until it's perfect. I verify understanding, labels, usability. Then I can pass the result to Claude Code. The implementation. Claude starts from the spec and mockup. He follows the plan made in the spec phase. The spec is meant to be delivered in stages (protected by feature flag). This allows me to do several small implementation sessions rather than one large session, which tends to degrade in quality if it gets too full. The closing step is important: without it, specs become obsolete in six months. Explicit rule in the context: if a spec is vague or inconsistent with what exists, the agent should ask the question, not guess. Progressive delivery. I work trunk based. However I use feature flipping and gating, which represent two different things: I have skills that explain the difference, so agents don't do anything wrong and respect my working process. If you're starting from 0, the first step is the quality gate if you don't have one. You need a control mechanism that runs tests, linters etc... Then start light with a Claude.md that describes the essentials, the why. Add rules as you go for important architecture patterns. As soon as you see procedures that come back often, document them as skills. And then equip yourself with cli and MCPs to interact with your main tools, jira, sentry, etc... Be careful, any skill, MCP, code taken from outside must be scrutinized. These are dependencies that can be vectors of attack. You need to take into account that the technology is still very young, February 2025 if we consider agentic programming. Tooling is improving but you also need to constantly review it. Mid-2025, some instructions in a Claude.md made sense, for example "write a test for each new service". Today it's noise and Claude does it naturally. So you need to be wary of your old rules, sometimes they're obsolete and create noise. I have no way to measure and know if an old rule has become obsolete. Latest versions of Opus are increasingly autonomous. AI takes the initiative on its own to build, look at produced content, read dependency code to understand calls, find bugs, run tests in the browser. It's almost creepy and more rigorous than 99% of humans. Let's be honest, I'm increasingly less useful in implementation phases, but I don't want to lose control of the produced code. I'm torn between satisfaction at having an increasingly efficient software factory and the risk of losing knowledge. I need to find a way to control designs a posteriori, to appropriate the result. I recently added a boyscout.md rule But I find myself having endless sessions. I think I've never worked on a codebase that maintains itself as much. I've rarely improved the product at this level of detail. But it comes with a cost, cognitive overload. I think I'd rather automatically note these elements and categorize them in an online TODO list (trello, todoist etc...). I think the workflow for maintenance should move elsewhere, and be partially automated. I still copy and paste my skills/rules etc… from one project to another. And sometimes it's dependent on my station based on a skill installed locally. I need to find a way to package my skills to deploy them where relevant and to centralize maintenance. In other pending improvement points: the intention (why, for whom) does it satisfy the 4 risks identified by Marty Cagan: Value Feasability we can add: performance and reliability What does the agent know? (context, memory, code graph) What can it do deterministically, without improvising? (skills, procedures) What stops it when it makes a mistake? (hooks, architecture tests, quality gates) marketing copy (labels in the application) how to write migrations types to favor for database fields asynchronism patterns etc. (list far from exhaustive and enriched regularly) the activation pattern, which specifies that this rule only loads if you touch the directory the table that lists all available skills, to be opened only if needed. If the AI doesn't make schema changes, there's no point opening the skill "Multi-file procedure" skills are the most profitable. Example: adding a block to the content editor touches three different rendering surfaces. Without a skill, the agent systematically forgets one. "Up-to-date doc" skills are very important on code that evolves quickly. It allows an agent to understand the entry points and intentions of a feature. before modifying: blast radius, callers, risk level before committing: did I only touch what I wanted to? find an execution flow rather than grep a function name rename via the call graph rather than find-and-replace Claude's internal memory Claude-mem , which allows capturing decisions between sessions a Sentry skill to read information on Sentry and retrieve stack traces a skill that gives read-only access to the database (read/write access is possible directly via on the Docker container in local dev) no file on the "open" side references the "proprietary" side every production file belongs to one of the two sides ESLint for syntax ast-grep for architecture decisions , for example forbidding any call to without going through the OpenAPI client typecheck for typing What matters must be executable. An instruction is followed "most of the time", but it can be forgotten. A hook or test is followed all the time. An error must be documented. Every error must be recorded in a skill or in memory. Context is a budget. Wrappers, filters, sub-agents, summaries: everything that reduces noise keeps reasoning on the problem. Measure impacts before and after editing. We want to avoid the effect "1 bug fixed, 10 produced". Repetitive procedures don't improvise. One skill per procedure. Spec documentation dies if its closure isn't in the process. You need to plan the update and maintenance step. my dependency on Claude. I want to test open weight models but I don't have the hardware for it. Moderate risk in my opinion, the entire ecosystem is moving upward the IDE is becoming obsolete compared to this new workflow. I still use Intellij but I no longer find it suited to our time. I haven't seen an interesting alternative yet.

0 views
Sean Goedecke Yesterday

You don't have to be smart if you can think clearly

When you’re on fire, problems are transparent: they’re solved simply by the act of looking at them. Even complicated layers of multiple problems can simply be glanced through like stacked panes of glass. But nobody can work that way all the time. This is a common pitfall for smart engineers. Accustomed to being able to immediately intuit the solution, the first time they run into a problem they can’t do this to is a disaster. It doesn’t even have to be a hard problem, just a problem where for whatever reason they don’t see the trick right away. The difference between a “smart” engineer and a “strong” engineer is how they react to problems that aren’t solved instantly. A smart engineer might flail and struggle, hoping to find that flash of insight that eluded them; a strong engineer will have some process for methodically plodding away. There’s nothing worse than working with a smart engineer on their first really hard problem. When you don’t have the muscle to grind, it’s too tempting to just take any possible solution as the right one. Smart engineers can get into an increasingly-flustered loop of pointing to a series of bad solutions. They’re liable to panic: after all, much of their professional identity is bound up in their ability to solve problems easily. What skill do these smart engineers lack? I think it’s the ability to think slowly and clearly . Smart engineers can think clearly, but they can only think clearly at high speed. Strong engineers can think clearly all the time , even if their highest speed isn’t quite as fast. It’s like the difference between a Formula 1 car and a regular car: Formula 1 cars have a high top speed, but you couldn’t drive them in traffic, because the tyres and brakes don’t work at normal driving speeds. When I wrote about this before in Thinking clearly about software , I said that the key is to focus on the invariants : beliefs about the system that you know are true. When you’re stuck in a puzzling situation, it’s usually because some assumption you’ve made is false. If you’re able to identify the assumptions that can’t be false (for instance, if you’re getting an error message from the service, the service must be handling the request), that gives you solid ground that you can stand on to evaluate the assumptions that are less reliable. Thinking fast is about packing as much data in your brain as possible and letting your intuition leap to the right conclusion (or at worst, to a series of wrong conclusions that you can immediately dismiss before you come across the right one). It can feel deeply satisfying to make leaps like this; conversely, sitting with the raw data and not making mental leaps feels unsatisfying. People hate doing that. If you can force yourself to do something people hate, there’s typically a lot of value waiting to be extracted. This is no different. Engineers who can think clearly in a state of uncertainty tend to be extremely effective, whether they’re capable of great intuitive leaps or not.

0 views

The More You Buy, The More You Lose

If you liked this piece, you should subscribe to my premium newsletter. It’s $70 a year, or $7 a month, and in return you get a weekly newsletter that’s usually anywhere from 5,000 to 18,000 words, including vast, detailed analyses of NVIDIA , Anthropic and OpenAI’s finances , and the AI bubble writ large . My Hater's Guides To the SaaSpocalypse , Private Credit and Private Equity are essential to understanding our current financial system, and my guide to how OpenAI Kills Oracle pairs nicely with my Hater's Guide To Oracle , as well as the Hater’s Guide To Oracle (Part 2) . Subscribing to premium is both great value and makes it possible to write these large, deeply-researched free pieces every week.  Soundtrack: Queens of the Stone Age — Infinity  Two years ago, NVIDIA CEO Jensen Huang said that “ the more you buy, the more you save ,” referring to its new (at the time) Blackwell GPUs that would “ reduce LLM inference operating cost and energy by up to 25x .” Two years later, those supposed gains have been pared back to 10x , based on case studies with private inference providers that do not share their margins and are most-decidedly not profitable, and absolutely nobody seems to mind that NVIDIA overstated the gains on Blackwell (in a vacuum, in specific circumstances) by 150%, partly because these numbers are utterly meaningless, and partly because the media in most cases ardently refuses to criticize this company. Blackwell being “10x better” than Hopper does not appear to have made any AI startups profitable (or even more profitable), it does not appear to have lowered anyone’s costs in a way that we can measure using dollars and cents, and as a result, I feel very little when I’m told that Vera Rubin provides “ up to 10x more tokens per megawatt ,” especially as that was with DeepSeek R-1, a year-and-a-half-old open source model. Nevertheless, all of this is immaterial to the larger problem that none of this appears to have resulted in anything tangible other than horrendously-overstuffed balance sheets and spuriously-puffed stock prices.  Hyperscalers will have sunk over $1.3 trillion dollars into generative AI by the end of 2026 , and have plans to spend a trillion dollars more next year . On a very rational level, nothing that large language models (LLMs) have done, do or will do in the future can or will ever bring in the more than $2 trillion (or more) in brand new revenue that will be required to make any of this worth it.  To be more specific, between March 2022 and July 2026, Meta, Google, Amazon, and Microsoft added over $850 billion in property, plant, and equipment (PP&E), nearly tripling their PP&E from $498 billion or so, and in a period where they spent over $1 trillion in capital expenditures.  In that same four year period, none of them have disclosed their actual revenues from AI or AI-related services, and, as of their latest quarters, capital expenditures now represent 24.4% of Amazon’s, 33.7% of Meta’s, 37.3% of Microsoft’s, and an astonishing 43.4% of Google’s revenue, a number that’s steadily increased over the last three years.  They’ve also added over $307 billion in on-balance sheet debt, leaving them with a total of $557 billion, doubled from $250 billion or so in March 2022. I mention on- balance sheet because Nikkei reports that Meta, Google, Amazon and Microsoft have over $1.35 trillion in off- balance sheet debt — either data centers/GPUs yet to be delivered, or debt raised via SPVs that shift the actual “ownership” of them over to another party as a means of making them look less-indebted than they really are.  To be clear, it’s totally fine accountancy-wise to not include leases or commitments yet-to-commence, but it’s very important to know how big an anvil hyperscalers are conjuring above their heads. Google, for example, has $811 billion in contracted future spending commitments as of its latest quarter , increasing by a dramatic $661 billion ($478 billion or so in the latest quarter) in the last 6 months, and Meta has over $237 billion in non-cancellable contractual commitments.  Over $167 billion of that on-balance sheet debt has been raised in bonds across Google, Meta, and Amazon, with its $25 billion bond sale from July receiving ( per Bloomberg ) a cool reception, with “demand [settling] at 1.6 times the deal’s size…[and to] put that in perspective, US high-grade corporate deals have seen orders average around four times their size this year.”  For some further perspective, per Freedom Broker’s Saken Ismailov, there was around $100 billion of demand for $20bn of Google’s three to fourty-year-long bonds (5x) and around £9.5 billion of demand for its £1 billion 100-year bond sale (9.5x).  As of last week, Google’s century bond has already lost 10% of its value .  This is a problem, as all four are certain to become repeat visitors to the bond markets. Herman Chan of Bloomberg Intelligence estimates that hyperscalers will need to raise $1.5 trillion in investment-grade debt in the next five years just to keep up with their trillions in estimated capital expenditures.  To make matters worse, hyperscaler bonds are, to quote Bloomberg , “...underperforming on almost every metric,” and are “in the red on average,” though that includes Oracle, whose credit just got downgraded to a single rung above junk by S&P Global .  As complex as all of this sounds, it’s all pretty simple: hyperscalers have borrowed a bunch of money to fund AI, to the point that it’s pushing them into cash-flow negative territory, and every time they raise more money, bondholders become more worried about them paying it back , especially given that both Amazon and Google have now gone cash-flow negative as of their latest quarters.  Or, put more-simply, the more they raise, the more it costs. Then there’s the other, more-obvious problem — the more they buy, the more they spend. As I wrote in the Hater’s Guide To The Memory Crisis , the sheer scale of Microsoft, Google, Meta and Amazon’s spend on AI data centers has led to a massive supply chain crisis and price-gouging from the triopoly of Micron, SK Hynix and Samsung, with Micron alone bumping prices for DRAM by 60% in its last quarter, shooting up the price of every single kind of RAM possible, at a rate increased by the amount of GPUs and servers that hyperscalers buy.  To give you a sense of how memory hungry AI is,  single 72-GPU GB300 NVL72 AI server has over 20 terabytes of high-bandwidth memory (used almost exclusively in GPUs and other AI chips), and 17 terabytes of the LPDDR5X RAM used in mobile devices, and a gigawatt data center has thousands of those NVL72 servers (or something similar) . Moreover, that high-bandwidth memory that AI GPUs use requires more wafer space during manufacturing — further reducing the amount of manufacturing capacity for other kinds of memory. This naturally creates a vicious cycle. The more AI servers that hyperscalers buy, the more demand they create for RAM and high-bandwidth memory, which increases the price of RAM and HBM, which makes the AI servers more expensive, which means hyperscalers need more money, and because AI has yet to provide meaningful improvements in revenue or cashflow, they’re forced to raise more debt.  The more they raise that debt, the more expensive that debt becomes, and the more of that debt they use, the more of it they need, because the more they spend, the more the stuff they’re buying costs, which means they need more debt.   And, to be clear, I’m talking about some of the best-capitalized companies in the world with some of the best credit in the world . Things get magnitudes harder and more expensive for a neocloud like CoreWeave ( or a counterparty ), or a data center SPV, or anyone that isn’t backstopped by a hyperscaler, like Google’s backstop of Cipher Mining’s data center for Anthropic .  Are you beginning to see the problem yet? You can dance around making whatever noises you want about future GPUs or cadres of data centers magically giving somebody the margins you crave, but it appears that using AI only seems to be getting more expensive for hyperscalers, the companies that rent the GPUs, and basically anyone running a business using AI models.  Spare me your anecdata! Every AI startup is unprofitable, and every time somebody describes an AI company “getting profitable” it’s during some mythology-adjacent rain dance about mythical 90% gross margins on inference, or, in the case of the data center providers, after they’ve amortized billions (or tens of billions) of dollars’ worth of GPUs.  The problem is that the longer this goes on, the more expensive it gets, and the more extreme the payoff has to be. A trillion dollars of capex and the near-entire capitulation of the media and finance class cannot be justified by “some incremental improvements somewhere that nobody can really understand and an incredibly unprofitable way to let people write software that sometimes is faster but never in a way anyone can capture.”  Every wibbly-wobbly, fan fiction-adjacent analyst note or Twitter screed claiming that we’re in some sort of CPU or GPU supercycle never seems to reconcile with the reality that money doesn’t really seem to come out the other end when you buy something from NVIDIA unless you’re Anthropic or OpenAI. Data center operators have yet to show substantive proof of a sustainable business model renting out GPUs, let alone profits that would justify taking on billions in debt, and the payoff date seems to exist somewhere between “fuck knows” and “never.”  Take CoreWeave, the perennially debt-raising no IT loads refused neocloud, which has raised  over $23 billion in the past two years with bond spreads that communicate a near-existential anxiety about the future of the company. Their previously-mentioned $1.25 billion bond raise — raised a little over a month ago — is now trading over 200bps higher than issuance when it was already at a 9.625% yield, which genuinely brings into question how future debt raises will go considering it’s guiding $31 billion to $35 billion in capex for a year and still has yet to build most of the capacity it needs to fulfil its massive backlog.  In fact, CoreWeave’s bond spreads look like a dog’s arsehole after eating a Thanksgiving turkey: And because it hasn’t built it yet , that means it hasn’t bought all the stuff , and the longer it takes to buy the stuff, the more expensive it’ll get.  That’s also before you consider talent shortages , transformer shortages , electrical grade steel shortages , and generator shortages , which means you’re paying more money for the same thing (or less), likely having to accept whatever quality of material or talent you can get, all while battling to secure power as local authorities begin forcing data center builders to pay their fair share. This just happened in the Midwest, with local regulators in Port Washington, Wisconsin demanding Oracle puts up a $7 billion guarantee (costing it $100 million a year) to protect taxpayers if the power behind its Stargate data center doesn’t get built, largely due to that S&P credit downgrade…associated with it building so many data centers for OpenAI . Nobody seems to want to discuss that every data center we’re describing is 2 to 3 years in the future, and the market is becoming increasingly impatient and showing signs of non-compliance with the greater AI narrative. The theoretical payoff for anyone buying a GPU in the last 12 months is that sometime in the year 2030 you will, in theory, make somewhere between 30% and 40% gross margins , assuming that you have had near-constant utilization of your GPU infrastructure from an industry where effectively every customer is either an unprofitable AI lab or a hyperscaler trying to keep their theoretical future compute off their balance sheet. How does any of this work? Has anyone worked that out yet? Because it isn’t working right now, the only reason that any of you think it’s working is because CoreWeave ( which lost $740 million last quarter ) and Nebius ($399 million in revenue, $8.45 billion in debt ) haven’t had trouble raising debt. Be real with me: do any of you seriously believe CoreWeave exists in 2030?  Remember: its largest customer is OpenAI, either through Microsoft ( 70% of its revenue ), Google ( for OpenAI ), or its own payments that are paid net 360 .  In fact, why stop there — do you think OpenAI will be around in 2030?  I’m not asking these questions to be a dick or because I’m a hater , but more out of a genuine sense of curiosity. Over the weekend, the Wall Street Journal reported that NVIDIA was in talks with OpenAI to guarantee $250 billion in financing for a 10GW data center (allegedly) being built by SoftBank affiliate SB Energy, by which I mean NVIDIA would guarantee the compute payments ( as it has with CoreWeave and Lambda but at a much bigger scale) so that SB Energy can raise debt to buy the chips from NVIDIA to rent to OpenAI: What’s even crazier is that the $250 billion guarantee would only cover lease payments and construction costs, and, per The Journal, NVIDIA is also discussing a deal to finance the $350 billion in GPUs to go inside it. It is unclear how that would happen, who would fund it, how it would get funded, or really anything about the deal. This is the final boss of circular financing. SoftBank, which owns over $100 billion (on paper) in OpenAI stock, is using its affiliate SB Energy ( which OpenAI and SoftBank invested in in May ) to raise debt to build a 10GW data center — likely costing more than $500 billion in chips and construction — by getting a backstop from NVIDIA ( which invested $30 billion in OpenAI and cited it as a material indirect customer in its 10K ), which will also make upwards of $350 billion in revenue from the deal.  If/when this deal closes, SoftBank (which owns more than 15% of SB Energy) will use the contract signed with OpenAI as a way to take SB Energy public , giving both it and OpenAI a massive equity gain, all while feeding revenue from one investment to another investment, at least in theory. Will any of this happen? God no. SB Energy is a confusing and murky business. SoftBank sold 85% of its shares to Toyota to form a company called Terras Energy in 2023 , and it’s unclear if the new SB Energy has anything to do with the old one. Even if it did, neither company named SB Energy has ever actually built a data center, and to my knowledge, nobody has gotten close to building a 10GW data center.  Then there’s the problem of the debt itself. It’s unlikely that SB Energy raises all this money at once, which means that it’s going to fall into the same problem as hyperscalers are facing — that the more debt that AI data centers raise, the more expensive it becomes to raise debt for AI data centers.  That, and the debt markets are already showing their distaste. Back in May, SB Energy (via an SPV called SE Cosmos LLC) raised $999 million in 144A bonds (private debt sold exclusively to qualified institutional buyers) rated BB- (junk) by Fitch and BB+ by S&P Global to buy a former 3M campus and turn it into a 70MW data center , and it only got that with a guaranty from SoftBank Group.  Since issuance, its (option-adjusted) spread has grown from 351bps to 536bps, and that’s for a relatively low amount of debt for a relatively-straightforward data center.   Even with the cast-iron guarantee of mag7 findom NVIDIA, it’s hard to see how SB Energy pulls together what will likely be a succession of different $10 billion debt deals of the course of several years, especially given the above-discussed curdling of the AI data center debt markets.  I also think it’s fairly likely somewhere between nothing and very little happens as a result here, even if NVIDIA offers its backstop.  Per The Journal, phase one of the project is due to be finished sometime in 2028 and have around 800MW of power — and I must be clear that while this doesn’t seem like very much in the grand scheme of things, OpenAI’s Stargate Abilene, a 1.2GW data center that broke ground in July 2024, has energized and monetized no more than three out of eight buildings for a total of 309MW of critical IT load, or about 401MW of active power. Even if the data center has broken ground (which I don’t believe it has), it’ll be extremely difficult to meet that timeline, and at a rate of 800MW every two years, it’ll be more than a decade before it opens. Forgive me if I feel a little dismissive, but it’s a little hard to take any of this seriously! This theoretical data center with theoretical funding built by a SoftBank affiliate to rent GPU capacity to a SoftBank investment with the backstop of an OpenAI investor that stands to make hundreds of billions of dollars is equal parts ridiculous and fantastical.  Oracle is burning its company to the ground to build data centers for OpenAI in pursuit of a $300 billion, five-year-long compute deal that was meant to begin in June 2026 and currently has 5.6% of the 7.1GW of capacity it needs to make that revenue, even with Larry Ellison throwing every dollar he has (in addition to tens of billions of debt and laying off 21,000 people ) and pulling every favor imaginable.  Though it’s kind of a straggler in the cloud space, Oracle still has a ton of experience in building data centers, and if it can’t get these done within a reasonable timeframe, I struggle to see how SB Energy — a company that has, as a reminder, never built a data center before — is meant to build the largest data center campus in history, assuming it can raise the money, which it will have a great deal of trouble doing. In any case, I won’t be surprised if a “deal” is signed, and if some sort of debt financing takes place, but it’s going to be tough for SoftBank and its various tendrils to raise the $30 billion or more for Vera Rubin chips, let alone the $14 billion for construction.  To be clear, I also don’t think this deal has very much to do with OpenAI or generative AI. SoftBank wants SB Energy to lock up the deal so that it can push it to go public and unlock some much-needed liquidity . NVIDIA wants to lock up (theoretical) hundreds of billions of dollars of revenue, and doesn’t really care if the data center gets built as long as CFO Colette Kress can find a way to book the GPU sales as revenue.  This is all a very, very bad sign for the AI industry at large. If there were real, diverse, meaningful and consistent long-term demand for generative AI or NVIDIA GPUs, NVIDIA wouldn’t have to create the world’s first circular financing within a circular financing, or need to take money from one of two different massive companies with either junk or junk-adjacent credit putting their futures in jeopardy to pay it.  Oh, right, there’s also the other problem: how the fuck will OpenAI pay for this capacity? If we, based on my estimate of $75 billion a year across the 7.1GW of Stargate data centers , assume that OpenAI would pay around $10.5 billion a gigawatt of capacity, that’s $105 billion a year in compute costs just for SoftBank, or a little less than half of the $122 billion OpenAI will have raised this year , with $60 billion of that coming from NVIDIA and SoftBank.  Nobody has an answer here! Every time one of these insane theoretical deals is announced it’s discussed like building gigawatts or raising hundreds of billions of dollars is both easy and effectively already done . It doesn’t matter that NVIDIA claimed it was investing $100 billion in OpenAI last year to build 10GW of data centers in a deal that never happened ( despite CNBC claiming the first $10 billion would close within a month of the announcement! ), or that OpenAI can’t afford it, or that OpenAI has been part of no less than three different announced-then-never-completed deals . The media has been fully trained to simply accept whatever slop NVIDIA shovels down their throats, and to avoid discussing messy things like “how this happens” because that wouldn’t be considered objective. Allow me to be subjective for a second: this deal is bullshit. AI data centers are taking 18-to-36 months to build , and capacity is clearly coming online at such a slow rate that it’s hard to understand why people are still buying more GPUs , other than the fact that once they stop everybody has to admit that it was all kind of a huge waste of money. The media remains ill-prepared for this moment, because of ( to quote Ed Elson ) a cult-like worship of the wealthy, where the assumption is always that they’ll work it out , and anything they say that doesn’t work out is just a result of the complexity of businesses. Yet this is actually a very, very simple situation. NVIDIA needs to keep sustained and ever-growing demand for its GPUs, and the only way that it can keep doing that is either by creating and constantly funding neoclouds ( who, to quote CEO Jensen Huang, would not exist if NVIDIA didn’t support them ), creating massive circular deals focused on OpenAI, or relying on hyperscalers that have run out of hypergrowth ideas and thus must keep building data centers to avoid admitting that to the markets. You’ll notice that nobody other than hyperscalers, Anthropic, and OpenAI seem to be demanding gigawatts’ worth of compute, and that’s because outside of the AI labs and those supporting them there’s less than a fifteenth of the demand necessary to support the 190GW of planned data center capacity.  As a result, the only way that NVIDIA can continue beating and raising each earnings season is to manufacture these massive deals, all to avoid discussing the blatantly obvious truth that diverse demand does not exist. Why else would it have over $30 billion in commitments to rent back its own GPUs?  While NVIDIA continues to sell remarkable amounts of GPUs, it does so to an increasingly less-diverse customer base — 54% of its revenue and 64% of its accounts receivable (IE: orders shipped, revenues booked, but money not received) come from three customers. While its new (as of its latest quarter) “ACIE” (AI clouds, industrial & enterprise) segment might feign a little variety, this includes basically any SPV or VIE or neocloud that NVIDIA itself has helped prop up.  NVIDIA’s revenues are, for the most part, propped up by FOMO rather than any real relationship to revenues, productivity, or reality, much like the rest of the semiconductor companies profiting off of AI. Every move it makes is to further propagate the sense that if you don’t buy GPUs and build AI data centers that you’ll be permanently left behind — which is why it plans to invest $5 billion in mysterious AI startup Safe Superintelligence , a company with no products or plans other than to rent NVIDIA GPUs from someone at some point. Outside of those building the infrastructure, the only people making a profit (or really much money at all) are the bankers and private credit funds underwriting data center debt, the ratings agencies getting paid to rate that debt, and any VC that’s been lucky enough to get paid out across the (very) few acquisitions of the AI bubble so far.  Otherwise, basically every layer of the AI industry exists to be exploited by the layer above it. AI startups and enterprise customers pay Anthropic and OpenAI on a per-million token rate (losing money in the process) so that Anthropic and OpenAI can rent GPUs from hyperscalers (losing tens of billions of dollars a year) so that hyperscalers can buy a trillion or more dollars’ worth of GPUs (putting them in such a hole that they’ll never, ever be able to make the money back).  It’s all deeply unsustainable, vile and wasteful, and only made possible in a lax regulatory environment, a captured tech and business ecosystem, and an economy dominated by growth-at-all-costs thinking . As I’ve hinted at previously, AI needs to become something altogether more successful, powerful and financially viable than it is today, and that “something” grows ever-larger with every new massive data center deal and funding round and egregious statement from Clammy Sam Altman . Hyperscalers will, by the end of the year, have sunk over $1.5 trillion in capital expenditures and equity investments into Large Language Models that have yet to provide good enough revenues to actually disclose.  Their actual AI products — outside of providing compute to Anthropic and OpenAI — are mediocre also-rans that range from embarrassing to actively harmful , deeply unremarkable simulacrums of whatever OpenAI or Anthropic’s product du jour might be, the latest of which are the (deeply embarrassing) attempts by Microsoft and Meta to make their own OpenClaw products. While people might use Google AI overviews by accident or accidentally click the Gemini icon when they’re using Google Docs, the actual outcomes of Google’s various LLMs are unexceptional, much like every hyperscaler product.  The only really successful product — GitHub Copilot — only grew to a few million paying users because it subsidized their usage, allowing them to burn more than 25 times their monthly subscription fee, leading to user revolts when they were inevitably switched to token-based billing . Do not confuse “some revenue coming out of these products” with any kind of success. Microsoft, Google, and Amazon have tens of thousands of salespeople whose job is to harass their customers into buying AI add-ons, on top of simply changing their product categories to force AI services into regular subscriptions as an attempt to claim that they have “AI revenue.” The fact that none of these companies are willing to disclose their actual quarterly revenues for AI is a sign that they’re bad, and the fact that effectively no journalist bothers to include this in their writeups of their earnings from the last few years is a disgrace to the profession that fails the general public.  The problem that hyperscalers face is that they can’t really stop spending on AI, because once they do so, they’ll suddenly start getting graded on their AI investments. As long as we’re in a “capex buildout phase” of indeterminate length with data centers that take two to three years to come online, Microsoft, Google, Microsoft, and Meta can perpetually kick the can by spending tens of billions of dollars on capex, or at least they’ve been allowed to because their current businesses have kept growing.  There’re a few problems with this approach: As mentioned previously, the payoff here would have to be in the trillions of dollars of new revenue, in a way that was virtually impossible to deny. Incremental revenue growth or improvement of current profit lines are insufficient justification of the current spend, let alone the future trillion-plus (and yet-to-be-unannounced) in capex or the trillion-plus in ongoing commitments.  What could possibly make any of this worth it? None of the hyperscalers have created a single new product line or service that actually matters, nor do they have any unique IP or technology that could turn into one.  AI boosters and paint-eaters continue to claim that the growth we’re seeing now is from investments in AI, but if that’s the case, that means that the current hyperscaler business lines are in such severe decline that they basically stopped growing in 2022, which is most assuredly not the case. And please, spare me your warbling about whatever “ad growth” you think Meta is getting from AI. This is the metaverse all over again, except larger, more annoying, and more dangerous to its balance sheet. The fact that we are even debating whether AI is helping these companies and that nobody can just show me the actual numbers to prove me wrong are the signs that something is very, very wrong in a way that’s unlikely to change. It’s also unlikely to change with another trillion dollars’ worth of capital expenditures.  More capex means more space for Anthropic and OpenAI to spend their venture capital funds on Azure, AWS, and Google Cloud. Even if margins were to remain stable and both AI labs stay alive for the next five years, the revenue growth would still be overshadowed by capital expenditures that represent 100%, 118% and 181% of cloud revenues as of their last quarters.  It don’t take no math genius to say that this does not seem to be working out in a way that makes more dollars than it costs, and I can find no compelling evidence that another three years of data center construction magically turns this all on its head. Yet the moment they stop spending capex (by which I mean dropping it significantly — below $15 billion, I’d say), the AI bubble pops. Any capital expenditure pullback will be an impossible-to-ignore sign that what they’ve built is sufficient , which will get hyperscalers a short-term stock bump before facing three much-uglier questions: And there’re really no compelling answers, because, as I discussed in the Rot-Com Bubble , we haven’t had a new Google Search, iPhone, or Microsoft 365 in decades, and without one, hyperscalers don’t have a hypergrowth future. Their only hope would be if AI itself becomes far more than it currently is, and yes, that includes Anthropic and OpenAI. People are going to be very mad at me for saying this, but when you strip away the media hype and the investment rounds, the actual things that generative AI can do are, at best, kind of cool and for the most part awkward and mediocre.  The ability to generate code in a mindless and expensive way that sometimes works and may or may not make developers an indeterminate level of more-productive is not a business model, a point made more obvious by the fact that Anthropic and OpenAI allow users to burn $8000 to $14,000 a month for $200 .  I know somebody is going to read this and oink that “they have 70% gross margins” or some such bullshit, but none of you have any proof other than something your dad’s friend’s dog’s aunt’s proctologist’s friend heard in a Discord chatroom. However “useful” AI coding tools may be — and it’s genuinely hard to tell! — is immaterial to the larger point that they’re very, very, very expensive to use, that most of those costs are either hidden from the user or subsidized by employers, and that despite all the fucking noise , they are yet to substantively replace or even enhance human beings outside of the loudest and most annoying people on Twitter. And I think people genuinely underestimate how harmful the vacuousness of AI’s benefits has become. Per Nik Suresh’s excellent “AI Mania Is Eviscerating Global Decision-Making”: Suresh, a decorated consultant and software engineer who wrote one of the best pieces on AI of all time , tells the story of an economy dominated by people buying and selling AI for symbolic reasons entirely disconnected from actual productivity , with in some cases one’s sufficient devotion to using or supporting AI’s (imaginary) productivity benefits being essential to surviving in many modern businesses.  This is an alarming situation caused by a few things: Suresh’s piece is both fantastic and vile, telling the story of people “AI-washing” their work, “...meaning that even when they can perfectly competently execute on their jobs to the satisfaction of their management teams, said managers are unhappy if [they didn’t use AI],” of organizations firing top performers because they achieved said performance without using AI, of a global intelligence crisis where executives lie and say they love AI and are 100x more productive with AI because if they don’t, their customers and their customers’ customers will be offended. LLMs are capable of doing a convincing-enough demo of functional-adjacent software that they can convince basically any CEO that they can do basically anything. As I wrote in Revenge of the Business Idiot , the media and the markets are so used to coddling and celebrating the dull, brainless and mediocre executive class that it was inevitable a technology would grow not based on its actual efficacies but what it represented to the managerial sect , and what it could represent to their stupid friends. The problem is that there’s only so far you can take something based on everybody pretending it’s magical or its convenience as a symbol of executive power. Outside of coding, AI really has no fundamental use cases beyond being slightly better at interpreting search queries, brainstorming, and searching documents. No amount of anecdotal “I used it for this one thing and it was useful” changes the amount of money that AI requires to exist, plugs the gaping holes in Anthropic and OpenAI’s cashflows, or fixes any of the economic problems with data centers I’ve already discussed.  LLMs are economically and practically unsuited to the tasks they’ve promised to solve, and no amount of extra capital expenditures or venture capital dollars will magically fix that. If you think that’s an outlandish take, one that only a “hater” or “AI doomer” could make, allow me to refer you to this note from ratings agency Fitch , which warned that a lot of debt is going to AI capex, and the usefulness of AI (and, by extension, that capex) remains a big hanging question mark, which presents a massive risk to lenders, and by extension, the global economy:  Anyway, I want you to imagine you wake up tomorrow, and nobody is talking about AI in the news. AI-related stocks aren’t dominating the market. Nobody on Twitter is discussing AI. Nobody you know or talk to is talking about AI. Nobody you know is using it, nobody you know has even heard of it. Would you still be as excited? Would you feel the pressure to use it? Would any of this make any sense if there wasn’t someone threatening your job or scaring you in the media every day? Would any of this seem rational? AI, as it stands, is an exercise in kayfabe — a thing people are taking seriously because the rich and powerful are saying they have to and a media ecosystem built to celebrate them says that you need to.  And the fundamental issue, to paraphrase Roger McNamee on CNBC , is that they’re trying to make a niche tool a general-purpose technology.  The trillion-plus dollars in capex and venture investment is an attempt to turn Large Language Models that generate and summarize things into something that can do anything , because the people at the top of both the organizations building and buying AI services don’t actually do real jobs and thus can’t understand that the vast majority of tasks are neither generative nor replaceable with a median version of their outputs.  Every layer of GPU (and CPU ) intensive agentic bullshit is a tacit admission that LLMs are not a tool with any of the features of “artificial intelligence” anyone has dreamed of. Their greatest innovation is their symbolic ability to scare and compel people to change who they are or how they treat others as a patronage to the tech industry, or a general fealty to the powerful. And I fear everything will end in tears, all because those with the responsibility to tell the truth or stand in the way of grifters both opened the doors and sung their praises, attacking and othering skeptics who wanted to avoid what I fear is now an inevitably painful future . If you liked this piece, you should subscribe to my premium newsletter. It’s $70 a year, or $7 a month, and in return you get a weekly newsletter that’s usually anywhere from 10,000 to 18,000 words, including vast, detailed analyses of the biggest events and companies in the AI bubble.  As mentioned, the more they buy, the more they lose. The longer it takes to pay off, the larger the payoff will have to be. At any given time, the market could simply refuse to wait any longer. Why did you spend all that money? Is AI not the next big thing? What is your next big thing, then? Business software is often bought by and sold to highly-suggestible c-suite executives that will never actually be the ones to use it. A captured business and tech media that has repeated effectively every (imaginary) promise of AI as if it had already happened. Many businesses are run by people who do not do any real work or have a hand in actually making the company successful, and hire people who are similarly-vacuous as a means of ingratiating themselves. These Business Idiots are everywhere.

0 views
Unsung 2 days ago

“Rather than fighting my tendency to type these two characters in my omnibar, I neutralized it.”

An interesting short story from Ernie Smith at Tedium, who ventured out to do the opposite of what we usually cover on this blog – disrespect his motor memory : Recently, I made a realization: I have been unwillingly addicted to Facebook for a long time, and it’s not even because I like Facebook. Rather, it’s because I find it an extremely easy URL to type into a modern web browser’s omnibar. This sounds crazy, but the first two letters, f and a, are on the home row, and I don’t really rely on bookmarks, but my browser’s history function to type in URLs. This creates a sort of recency bias. If I type in the same URL a lot, it’s the one that pops up the most. And so, if I’m at a browser with no clear idea of what my intent for the next page I load up, I inevitably type in “fa,” which would suck me in. […] So, what I ended up doing was creating a URL that does nothing but forward to Google News. […] The result is that whenever I type in my new Facebook URL, I go to a news aggregator, which is inevitably what I was using Facebook for anyway. A week later, and my Facebook usage has gone down considerably. There is something really interesting about creating your own URL. Smith doesn’t disclose his, but you can imagine it’s something like that just redirects to a news aggregator. If creating a new URL is too difficult, there are always other options: Wanna go to fatberg.com every time you load your computer? Or maybe faxtoy.net ? This is a good example of some of the challenges with “recent” interfaces I am such a big fan of . If you’re designing recents and you think they can turn against the user or otherwise get in their way, it’s good to offer not just a “clear recents” feature that gets rid of them all, like here in Apple’s Music… = 3x)" srcset="https://unsung.aresluna.org/_media/rather-than-fighting-my-tendency-to-type-these-two-characters-in-my-omnibar-i-neutralized-it/1-framed.1600w.avif" type="image/avif"> …but also individual clears, like here in Bluesky: = 3x)" srcset="https://unsung.aresluna.org/_media/rather-than-fighting-my-tendency-to-type-these-two-characters-in-my-omnibar-i-neutralized-it/2-framed.1600w.avif" type="image/avif"> I don’t know if this is true for all the browsers, but in Chrome and Safari, you can also clear individual suggestions this way: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/rather-than-fighting-my-tendency-to-type-these-two-characters-in-my-omnibar-i-neutralized-it/3.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/rather-than-fighting-my-tendency-to-type-these-two-characters-in-my-omnibar-i-neutralized-it/3.1600w.avif" type="image/avif"> Smith writes a bit more about the addictive nature of computers, but I’ll let you read on your own . #attention #keyboard

0 views
Martin Fowler 2 days ago

The Orchestrator's Tax

Subagents get justified by time saved and parallel execution, but Rahul Garg explains that's not what matters most. Every token in the orchestrator's context is competing for its attention, and the real value of a subagent is what it keeps out of that context. Subagents should be treated as a tool for protecting the orchestrator's working memory, offloading reasoning it doesn't need to hold onto. Doing this well means giving the orchestrator explicit ground rules for when and how to delegate.

0 views

MatchBox: A Semantic Foundation for Data Plane Portability

MatchBox: A Semantic Foundation for Data Plane Portability Eric Hayden Campbell, Robert Zhang, Divyanshu Saxena, Aditya Akella, and Işıl Dillig PLDI'26 This paper identifies problems associated with subtle differences in match-action table implementations across hardware vendors and proposes some formalism to allow generic tooling to be implemented for match-action tables. A match-action table is a data structure present in some NICs and switches which specifies how packet-processing hardware should modify packets on the fly. This post on Gigaflow also discusses how a virtual switch can be implemented with match-action tables. Fig. 2 shows two match-action tables programmed in a hypothetical switch ( IP addresses in these tables are written in CIDR syntax ): Source: https://dl.acm.org/doi/10.1145/3808277 The syntax is clear but the semantics have an important footnote: switch S has a policy which causes packets that miss in the routing table to be dropped. Now imagine a switch ( ) from another vendor with a different policy: packets which cause a miss in the routing table are broadcast to all output ports. The task of porting the match-action tables from to in a way to preserves behavior is non-trivial. Fig. 3 contains a correct solution: Source: https://dl.acm.org/doi/10.1145/3808277 The difference is in the ACL table. The permissive allow entry has been replaced with two more restrictive entries that only allow packets that would not have triggered a miss in the routing table. One automated way to compute the contents of the ACL table for switch is an algorithm that looks at all pairs (i.e., the Cartesian product) of entries in the route and ACL table for switch , and then drops pairs that don’t make sense (e.g., the route and ACL addresses have no overlap). If you squint at that definition, it looks a lot like a relation join operation. In other words if you think of the ACL and routing tables as relations, then a way to compute the ACL table for switch would be to join the route and ACL tables for switch . The authors argue that relational algebra is almost the correct hammer for this nail, but not quite, and so this paper proposes Match Algebra . In Match Algebra, a match-action table can be thought of as a partial function which maps a valuation to an (action, valuation) pair. A valuation is just a set of bits (extracted from packet headers), and an action describes how a packet is to be modified. Another way to think of a match-action table is an ordered set of rules. A rule comprises: A guard, which defines the set of packets that match the rule An (action, valuation) pair Example guards could be: IPv4 packets with source address matching 10.2.1.0/24 UDP packets with a destination port of 15354 or 15355 An example (action, valuation) pairs could be: (replace the destination port, 15356) (pass the packet through unmodified, x) The set of rules is ordered such that if guards associated with multiple rules apply to a particular packet, the highest priority rule wins. The most important operators in the Match Algebra are: Sequential composition: modify the packet according to table , and use the result as input to table Preferential composition: Check to see if table has a rule matching the incoming packet, if so then apply that rule. Otherwise, use table to modify the packet. Parallel join: apply tables and to the input packet to generate two (action, valuation) pairs: , . Merge the results together. The merge operation requires that the results from and do not overlap (e.g., causes a destination port to be modified while causes destination address to be modified). The paper describes some other operators and presents formal semantics for Match Algebra. The paper describes which is a language (embedded in OCaml) which operates at the Match Algebra level of abstraction. Fig. 13 shows an example program which transforms match action tables with operators from Match Algebra: Source: https://dl.acm.org/doi/10.1145/3808277 Results The paper presents the following real-world use cases of : Transforming a set of match-action tables to an equivalent set with a different form (for porting rules between switches) Porting firewall rules between AWS, GCP, and Azure (which each have a different required structure) Translating system-wide eBPF tables to per-CPU eBPF tables Thanks for reading Dangling Pointers! Subscribe for free to receive new posts. Source: https://dl.acm.org/doi/10.1145/3808277 The syntax is clear but the semantics have an important footnote: switch S has a policy which causes packets that miss in the routing table to be dropped. Now imagine a switch ( ) from another vendor with a different policy: packets which cause a miss in the routing table are broadcast to all output ports. The task of porting the match-action tables from to in a way to preserves behavior is non-trivial. Fig. 3 contains a correct solution: Source: https://dl.acm.org/doi/10.1145/3808277 The difference is in the ACL table. The permissive allow entry has been replaced with two more restrictive entries that only allow packets that would not have triggered a miss in the routing table. One automated way to compute the contents of the ACL table for switch is an algorithm that looks at all pairs (i.e., the Cartesian product) of entries in the route and ACL table for switch , and then drops pairs that don’t make sense (e.g., the route and ACL addresses have no overlap). If you squint at that definition, it looks a lot like a relation join operation. In other words if you think of the ACL and routing tables as relations, then a way to compute the ACL table for switch would be to join the route and ACL tables for switch . The authors argue that relational algebra is almost the correct hammer for this nail, but not quite, and so this paper proposes Match Algebra . Match Algebra In Match Algebra, a match-action table can be thought of as a partial function which maps a valuation to an (action, valuation) pair. A valuation is just a set of bits (extracted from packet headers), and an action describes how a packet is to be modified. Another way to think of a match-action table is an ordered set of rules. A rule comprises: A guard, which defines the set of packets that match the rule An (action, valuation) pair IPv4 packets with source address matching 10.2.1.0/24 UDP packets with a destination port of 15354 or 15355 (replace the destination port, 15356) (pass the packet through unmodified, x) Sequential composition: modify the packet according to table , and use the result as input to table Preferential composition: Check to see if table has a rule matching the incoming packet, if so then apply that rule. Otherwise, use table to modify the packet. Parallel join: apply tables and to the input packet to generate two (action, valuation) pairs: , . Merge the results together. The merge operation requires that the results from and do not overlap (e.g., causes a destination port to be modified while causes destination address to be modified). Source: https://dl.acm.org/doi/10.1145/3808277 Results The paper presents the following real-world use cases of : Transforming a set of match-action tables to an equivalent set with a different form (for porting rules between switches) Porting firewall rules between AWS, GCP, and Azure (which each have a different required structure) Translating system-wide eBPF tables to per-CPU eBPF tables

0 views
Martin Fowler 2 days ago

Why I’m Writing Rachel’s Ramblings

TL;DR I have ideas. I haven’t been writing them. That’s about to change. I promise… myself. I’ve been thinking a lot about talent. Actually, I’ve been thinking a lot about thinking. And writing. Or more specifically, not writing. This really hit me earlier this year at the Future of Software conference. I was surrounded by people sharing their latest ideas and I had a slightly uncomfortable realization: I have my own. Not just opinions. Actual patterns. Hypotheses. Things I’m seeing across clients, across teams, across the industry that feel new or at least not well articulated yet in a way that a leader can think about and act upon in some way that can influence how they strategise and plan for the future. Because helping clients and other leaders internal and external to thoughtworks do this is actually a big part of what I do and without letting my northern humbleness get in my own way, I’m actually pretty good at it. If I wasn’t I wouldn’t be the global CTO of a future thinking tech org, you know the kind that has Martin Fowler as its Chief Scientist. A title I know he loves… Martin, by the way, is one of the people pushing me to do this, which is weird because on paper I’m his boss but I don’t believe in the traditional idea of a boss anyway. I’m a strong believer in the servant leadership type but I’ll save that for when I write about that. Anyway the point is for all the ideas I have and discussion I have I don’t do a good job of writing it down. At best I’ll stick it in a presentation deck when I’m forced to communicate with them in some forum or another. I hate decks and love writing so I’m obviously doing something wrong. So why haven’t I been writing? It’s easy to say I’ve been too busy. I don’t have an easy job. It’s a fun one but not easy. I also have two small children, 5 and 8. In case you are interested, I attempt to give as much time as possible to this busy job. And then I try to have a life. I’m also writing an epic world building sci-fi fantasy book which is a huge passion project I may also share more about so I am definitely busy. But that’s not actually the real reason I haven’t been writing this down and pushing it out publicly. The real reasons… So this is an experiment. Rachel’s Ramblings is exactly what it sounds like. Fast, imperfect, thinking out loud. Naming ideas early rather than waiting until they’re fully formed. Because the reality is, most of what I do day to day isn’t answering known questions. It’s spotting patterns and asking questions we haven’t quite figured out yet. My brain works a bit like a knowledge graph. Constant associations, constant pattern matching. That’s useful in conversations, in client work, in strategy. It’s less useful if it never gets written down. So this is me fixing that. I’ll write about: Some of it will be wrong. Some of it will evolve. That’s the point. If nothing else, this is a forcing function to turn thinking into something that exists outside my head. Let’s see where it goes. I overthink it. I move too fast to the next idea. I’ve convinced myself it needs to be more polished than it does. what is the future of software how software development is changing in the age of AI and what that means for engineers, leaders, and organizations how platforms, agents, and people actually work together and occasionally, how I manage the reality of doing this job with all the other things I have going on

0 views
<antirez> 2 days ago

The real AI risk is inside the labs

Amodei in his latest blog post wrote a mix of agreeable things and things that I believe misrepresent where the real risk of AI is located. I want to focus my attention on why, among all the risks, open weight models constitute the mildest one. I write these words as a person who strongly believes AI may be very dangerous in the near future: 1. Exactly like what happened during the OpenAI / HF incident (which was a joke, but focus on the modalities, not the outcomes), the first serious AI incident is very likely to happen *inside* the walls of frontier AI labs, while testing a new model, or while the AI lab employees, or the few externals who have access, do something wrong compared to the expected power of the model. 2. Closed models that will never even be opened to the public will be just a few TBs of data. All you need to leak one is a single person with access and the wrong goals, and you are back in the situation of open models. Open models are released *after* testing, and after similarly capable models were already available for some time under an API. The real risk is leaks, not releases, and leaks happen inside frontier companies. 3. As Amodei says, open models, once LLMs are dangerous enough in fields like biology, can be trained on a corpus ablated of certain branches of science, while still being useful for a number of other things. The limited context window of a model that lacks strong pre-training in certain domains is a strong protection even if the model is otherwise very capable. We are currently not in a place where open models can constitute that kind of danger. 4. In the context of cyber security, *not* having widespread access to the defensive security and bug seeking provided by LLMs creates exactly the "LLMs as a weapon" problem. It is already happening: open source maintainers, if they are out of some cyber program, can't find all the security bugs they could, while people with the right interests will be able to access frontier cyber models, do significant RL training on open weight models, and so forth. 5. Once LLMs are dangerous enough (and we are near this limit, if progress continues), the real security chain that we need in place is inside labs, can't be set up without strong common rules, and a single company should not be able to evaluate independently whether a model is safe enough. We need a joint AI safety organization that includes experts from all over the world and is recognized by the governments where frontier AI companies exist. 6. Slowing down AI for safety must be counterbalanced by the fact that AI discoveries in medicine and other sciences may lower human suffering. Lack of checks may result in some catastrophic outcome ("Good morning! Let's work on this enhanced smallpox"). Lack of progress may result in people who could be saved dying, not just in the present, but among the many who will suffer from illnesses in the future. This may look like a bizarre point, but we always need to understand that stopping AI *also* has a security cost embedded inside, which is just a lot more hidden. 7. The ideological position of Amodei against China is unfair. We Europeans killed each other until 80 years ago without any limit of decency (people now forget, but one of the reasons the US invested in the stability of Europe in the past is that we were deeply dangerous, and would probably end up doing it again, while decades of wealth would make us a good market and would prevent us from fighting again). The US has, even in present times, tragic inequalities, people suffering for lack of basic health care, a president who looks unstable and is apparently very prone to war. I wish China had the same level of individual rights we have here in the West, but at the same time China's history is a lot less warlike than Western culture. It is absolutely not clear that an AGI military lock-in could be enforced more easily by China than the US, in the current conditions. Also, the current American administration spits hate at Europe in all forms, which is very worrying in a world where the US dominates everything. On top of all that, China's AI progress is not going to stop, whatever the GPU export policy is, so either Amodei is arguing that once America has AGI it should stop China by force, or what is his argument? 8. In the history of humanity there are many cases where technological supremacy was initially reached in a single place of the world. This, AFAIK, never resulted in *a single* country trying to create a permanent advantage. The non-proliferation of nuclear weapons, which is probably the case most similar to the GPU ban, was not used to achieve a permanent economic advantage by threatening to bomb everybody else not complying, nor did it prevent several actors from acquiring that technology at different times, without one bombing the other to stop their progress. Moreover, I don't believe AI poses the greatest dangers because of government-driven actions. I wish this were the most dangerous scenario! Governments do silly things, are often aggressive, and their actions have even resulted in genocides, but it requires a lot of people agreeing on doing something terrible, which is itself a limiting factor. The greatest problem is what happens in two other cases: A) a few individuals generate an apocalypse event (the virus case), B) AI itself escapes the control of the people building it. I believe we should not consider AI safe. A critical event that may result in the extinction of Homo sapiens is possible, but the danger is not in open models, or China making faster progress than the US. The danger is that a few CEOs (everywhere in the world) without the required background and legitimacy are in the position of making hard choices for humanity at large. They were not selected to do so; it was just the randomness of events that created this setup. They can't speak for everybody, given the stakes, just because they have GPUs and money. This is the first thing that should be fixed. Comments

0 views
Kev Quirk 2 days ago

📝 2026-07-28 09:16: Always fun when your bike runs out of electricity on the way to work. Note...

Always fun when your bike runs out of electricity on the way to work. Note to self: connect the trickle charger TONIGHT! (Wife is on the way with my jump box to save me) Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️ You can reply to this post by email , or leave a comment .

0 views

The Difference Between a Button and a Link

Of the three proposals in the Triptych Project , my multi-year odyssey to add a few small-but-powerful features to HTML, the one that generates the most questions is Button Actions . The proposal itself is very straightforward: we want to add the and attributes to the button. Button Actions are such a simple primitive that people often ask why they’re needed. The answer rests on a distinction that web users intuitively understand but rarely have to think about directly: the difference between a button and a link. I added a detailed “Buttons vs Links” section to the proposal, but I think it deserves a blog-style explanation as well, because most of the existing ones miss the mark. Links represent a destination while buttons represent an action . Functionally, this means that links let users control what context they open in, while buttons don’t. Web browsers offer countless affordances for re-contextualizing a link. Clicking or tapping the link will navigate the current page to that destination. Mouse users can middle-click the link to open it in a new tab or hover over the link to see where it goes. Context menus (right-click on desktop, long tap on mobile) have lots of link-specific options. Web users are very familiar with the features that come with links. They know how to open them, copy them, bookmark them, share them with friends, and maintain them in an inadvisable number of browser tabs. The semantics of a link—the notion that they represent an independently-navigable destination—make it possible for browsers to build all these features. The hyperlink predates the invention of the browser tab, but when browsers added tabs, websites didn’t have to do anything to support them; links represented destinations that could be re-contextualized, so browsers could simply invent a new context for them to open in. Every website instantly got upgraded with a huge new feature. Buttons have none of these features. By default, they cannot be middle-clicked, control-clicked, or hovered over for more information. Buttons don’t allow you to copy their the way you can copy the of a link. Their context menus contain no affordances for saving the action or doing it somewhere else. These are not omissions, but deliberate choices based on the button’s semantics: buttons trigger actions inside a specific browsing context ( almost always the current one ). Copying, sharing, bookmarking—these are all features for re-contextualizing the action of a link. Buttons serve a complimentary purpose because they don’t allow for any of that. A common misconception is that links are for navigating the page, while buttons are for everything else. This is incorrect on both counts. Buttons regularly perform navigations. Clicking a logout button navigates the current page to a logged-out one; clicking a “search” button navigates the current page to the query results. Both of these are navigations in the HTML standard . They change the URL, they get logged in the session history, and they load a new page. And links are often used in situations where they don’t trigger navigations. Relative links can jump around the current page; mailto links can open email clients; download links can save a file to your computer. None of these are navigations, but they are all “destinations” that can be opened, saved, and shared in customizable ways. Navigations should be represented as buttons when their action happens in a fixed context that is not available to be re-contextualized (e.g. bookmarked, shared, middle-clicked, etc.). A frequent place this comes up is with forms that let you edit something you’ve already saved, like a comment on a website. When you click “Edit”, the website shows you an editable text area with options like this: Users will easily intuit what each button does: Should “Cancel” be a link? No! Its job is to close the edit view. Not only does making this a link incorrectly communicate its purpose—visually and otherwise—but it saddles the form “control” with lots of features, like bookmarking and middle-clicking, that have incorrect behavior. There are many plausible ways these buttons could be implemented, but none of those implementations should present themselves to the user as a link. With Button Actions, this entire UX could be implemented with just HTML. The first two buttons use existing HTML features, the second two buttons are made possible by Button Actions. (I’m also taking advantage of Triptych’s DELETE support , but you could do the URL method hack without it.) Philosophically, Button Actions create a generic control that can redraw the current context with a network request. Buttons already have the ability to do this with certain limitations; this proposal removes those limitations. Practically, this allows web authors to implement state transitions by navigating to views. Those views might even already exist as standalone destinations, in which case authors can trivially re-use existing routes while representing the action correctly in the UI. This is a great pattern that HTML should encourage! Unfortunately, without Button Actions, erroneously making this button a link is the only way that we have to implement this interface without scripting. This is obviously an anti-pattern, but it’s an anti-pattern supported by major design systems, because buttons lack the ability to do basic navigation without forms. When building a website that works without JavaScript ( a requirement for UK government sites ), links are the only choice. The US Web Design System (USWDS) even contains an official affordance for it: Add to a link and it will look like a button. Making a link look like a button, however, does not make the link behave like a button. USWDS uses JavaScript to implement spacebar activation , but JavaScript can’t do anything about the litany of other behaviors that differentiate buttons from links, like context menus. Links (even those with ) will still look like links in reader mode or other custom views. That’s the fundamental consequence of violating HTML semantics—the page will be broken for some users because authors cannot possibly account for all the different ways that people interact with a web page. The web simply wouldn’t work if they had to. Navigations are the broadest tool that web authors have to control the user experience—HTML just needs to complete the ’s ability to trigger them. Doing so makes the web simpler, safer, and more accessible for all. If you’d like to support the effort, the best way is to like the Button Actions issue on GitHub and share examples of why the proposal would be valuable to you. “Save” updates the comment with whatever is in the “Save Draft” saves the content of the without publishing it “Cancel” closes the editable form “Delete” removes the comment entirely Big shoutout to The Django Software Foundation for their support of this proposal ! I am currently working on an analysis to demonstrate that Button Actions do not introduce any new XSS vulnerabilities to existing web sites. Supporting this proposal doesn’t resolve that issue, but it does demonstrate to WHATWG that web authors have this need and that it’s worth studying. This blog focuses on buttons that trigger GET requests without forms, because that’s where the overlap with links is, but buttons that trigger unsafe requests without forms are also very useful. requests are probably the most common use-case, because they usually don’t require any additional data. One interesting case for buttons that trigger or requests without a form is “likes” on social sites . HackerNews , for instance, uses links for upvotes, which is in wild violation of HTTP semantics. I understand why they do it though: it’s simpler and works without JavaScript. That’s why it’s necessary to make Button Actions not just possible, but convenient. The proposal addresses all the existing workarounds for the lack of this functionality and explains why they’re not sufficient. The big picture goal with Triptych to is to give web authors a simple and semantic way to model a full CRUD lifecycle in HTML, because that’s all the vast majority of web services need to do. All the Triptych Proposals complement each other—Button Actions are even more useful with additional methods and partial page replacement —but I try to make the case for each one in isolation, both as an anti-logrolling mechanism and because they are genuinely useful on their own.

0 views