Latest Posts (20 found)

Do You Trust Apple?

Listen to this post : On July 21, 1999, Steve Jobs did something remarkable at Macworld New York: first he went to Apple.com, then to “CNN Interactive”, then to Disney.com. That wasn’t the remarkable part: what blew the crowd away was when he picked up the just-introduced iBook and walked around while waiting for Disney.com to load. The crowd went wild at the lack of wires: I’m not going to quote this entire product introduction, but I’ve clipped the whole thing for your enjoyment; here are a few pertinent parts of Jobs’ introduction of what he called “AirPort”, and what the rest of the industry called “WiFi”: There is one more thing. The main point of this keynote was the aforementioned introduction of the original iBook: This meant that “one more thing” was in fact not just an extra unexpected product, but an explicit addition to the primary product’s feature set. No wire. What is going on here? We are really excited to announce, in addition to iBook, AirPort wireless networking…It’s a wireless LAN. It runs at 11 megabits per second, and it’s based on industry standards. This is 802.11 wireless networking, and everybody is jumping on board with this thing over the next six to nine months. So all sorts of devices are going to be able to interact with AirPorts. We’re just going to be there first and best, and the specification also incorporates quite a bit of privacy protection, so everything you send out is encrypted. A lot of privacy. We’ve worked with Lucent on this for the last 18 months, hand-in-hand to marry their wireless technology with our ease-of-use technology and to bring the cost of this down for people, because this stuff has been pretty pricey to date. Apple’s selling proposition has, in many respects, never changed: modern technology that is easy to use and private too. So AirPort, what is it? This is the first thing: this is the AirPort base station, and it looks like this, right like that, and so the AirPort base station is really cool… And, of course, industrial design: So what about the computer side of things? Well, iBook is the first computer ever designed right from the start to be optimized for wireless communications, and so right in every iBook are two built-in antennas…Then, we have an AirPort card, a small little card, and the iBook is designed to accept it. So let’s take a look at that. As you know, Apple pioneered this way of adding memory without taking your whole portable apart through simply lifting the keyboard. Well, we have enhanced that now to take an AirPort card, and as you see, there’s a space right there in every iBook ready for an AirPort card, and you can drop one in, just like that, and connect the cable that comes from the antenna. Right? You saw that? I’ll go back. Just connect that cable and push it in, and now your iBook is AirPort functioning. You are on the wireless network. All the software detects the AirPort card and automatically sets it up for wireless networking without going through hours of configuring your computer. It all happens automatically. This has been a major effort on the part of Apple’s hardware and software engineers and also Lucent. This paragraph is a bit extraneous, other than the fact it is personally meaningful: my first Apple computer was an iMac G4, the following all-white generation, with the same AirPort card installation. I remember being amazed at just how easy it was to add wireless . And now, here I am, 22 years later, still using an Apple laptop to write this Article. Two weeks ago I wondered how long I was for the Apple ecosystem ; one product I was definitely not interested in was the then-forthcoming Apple smarthome product: What struck me about Gurman’s article is just how unenthused I am by an Apple smarthome product. Some of this is fatigue from a decade of Siri disappointment and skepticism about the company’s ability to deliver on a voice-centric product. More than that, however, I bristle at the idea of introducing Apple’s constraints to more parts of my life. Those constraints aren’t just about things like full disk access. To the extent that Apple delivers on integration with things like thermostats and door locks is the extent to which they work with 3rd-party device makers; the problem is that third party device makers mostly suck, particularly from a software perspective. Even if Siri were perfect, Apple will have the challenge of delivering an experience that isn’t defined by the lowest common denominator. What I’m much more interested in is controlling the software layer myself. The fact of the matter is that with AI you can decompile almost all existing software — there is a revolution happening in gaming over the past few weeks, as game after game is decompiled to source and ported to any platform you wish — and you can write your own. That means my software that interacts with my agent in the way I want it to for everything; that’s way more exciting than praying Apple delivers the right API and that 3rd-party developers don’t suck. That product is called Apple HomeView , and some prominent Apple observers don’t get the point. John Gruber wrote on Daring Fireball : My skepticism boils down to the question of why anyone would want to add one (or more!) additional ever-present screens to our homes and lives. Phones can stay in our pockets until we need them. Watches remain on our wrists. HomePods can be tucked away unobtrusively in corners, and remain fully useful. HomeView needs to be in a prominent location for its display to serve any practical purpose. Apple’s initial pitch for it doesn’t earn that prominence for me. I understand Gruber’s skepticism, particularly given the product’s truly atrocious introductory video . Beyond the overall stress-inducing nature of the suburban family scene depicted, most of the use cases, as Gruber notes, are nonsensical: to take a particularly egregious example, why would the teenage daughter look at a message from her clandestine boyfriend on the HomeView instead of her iPhone (which has to be present on the network and unlocked in the past several hours for that functionality to even work)? Apple was, in this particular case, trying to show off HomeView’s multi-user capability, which is based on facial recognition, but my biggest takeaway is that maybe highly produced marketing videos sold as product keynotes aren’t the worst idea in the world. In fact, I think that HomeView is pretty compelling. Smarthome functionality is genuinely useful: I have, of course, just laid out five compelling use cases for the HomeView, but it wasn’t hard! These are all real, genuinely useful capabilities for a new home device. And notice what the limiting factor is for the middle three: actually getting different devices to work together reliably. That’s why the other exciting part about Apple’s HomeView announcement actually hearkened back to the original AirPort: Apple Home Collection. From Apple’s press release : Apple today announced Apple Home Collection, a new lineup of smart home accessories — including indoor and outdoor cameras, thermostats, temperature sensors, and a video doorbell and door lock — designed in collaboration with LG Electronics and Schneider Electric. These new accessories are simple to set up starting with one tap with iPhone, and everything is managed through the Apple Home app — no separate app or account required. Each accessory is encrypted end-to-end in Apple Home, so only users and the people they choose can access their home data. Building on the thousands of Works with Apple Home and Matter accessories available today, Apple Home Collection offers customers a new array of recommended products to better understand what’s happening inside and outside their home, manage access, and keep the temperature just right throughout the day. Availability for all products begins in December, with select accessories available starting early 2027. “Apple Home Collection makes it easy to choose smart home accessories with confidence,” said Matthew Costello, Apple’s vice president of Hardware Engineering. “Working closely with industry leaders LG Electronics and Schneider Electric, we designed every accessory to work seamlessly with Apple Home, so managing your home is simple, reliable, and private.” Apple doesn’t have to do everything itself in the home, just as they didn’t have to invent wireless networking in 1999; what they need to do is “marry [partner’s] technology with [their] ease-of-use technology”, and I’m optimistic they’ve done exactly that with LG Electronics and Schneider Electric. The key detail is “no separate app or account required”; that points to deep integration with Apple products, from setup to day-to-day usage. Again, I’m not sure I’m the target customer for this (although the automatically unlocking door locks look awesome); my solution to incompatible or flakey integrations is to use AI to build my own customized software. I’m under no illusions, however, that I am a normal consumer who wants the benefits of technology without the headaches; I trust Apple, more than anyone else, to at least aspire to delivering on that vision, and these 2nd-party partnerships are a great start. The second part where you may trust Apple more than any other company is with privacy. Jobs was talking about privacy as a selling point 27 years ago, and Apple has only doubled down since then. In the case of HomeView specifically there is that facial recognition feature, tied to your own hardware; more broadly, if there is any company you might entrust with tracking your more private spaces it is Apple, both because of promises they make with their technology and also their consistent stance on not using customer data. Indeed, Apple’s privacy umbrella is strong enough that LG’s very sketchy privacy track record is likely to be a non-issue amongst potential customers. From Bloomberg, in 2016 : Apple Inc. has disbanded its division that develops wireless routers, another move to try to sharpen the company’s focus on consumer products that generate the bulk of its revenue, according to people familiar with the matter. Apple began shutting down the wireless router team over the past year, dispersing engineers to other product development groups, including the one handling the Apple TV, said the people, who asked not to be named because the decision hasn’t been publicly announced. Apple hasn’t refreshed its routers since 2013 following years of frequent updates to match new standards from the wireless industry. The decision to disband the team indicates the company isn’t currently pushing forward with new versions of its routers. An Apple spokeswoman declined to comment on the company’s plans. The official end of the line came in 2018 , five years after the last product was released, leaving customers in limbo waiting for updates that never came. That right there is one reason to not trust Apple in the home: the company already decided once that products that didn’t move the needle relative to the iPhone weren’t worth their time, even if delivering an integrated home experience was still something Apple was uniquely positioned to provide. Yes, by the 2010s most people had WiFi access points from their ISPs, or mesh WiFi products from the likes of Eero, but Apple still could have done something useful. For example, one of the biggest challenges in designing a wireless network is that the iPhone aggressively holds onto access points; if Apple had continued to design its own access points it could, even today, provide a superior experience. Alas, the business was deemed to be not big enough to bother. One reason Apple might be more interested this time, however, is the possibility of subscription revenue. Specifically, the cameras in Apple Home Collection will require a paid iCloud+ plan for recorded event history — higher levels for more cameras — which fits in with the company’s focus on services. Apple Music is also natively supported on the HomeView, whereas you’ll need a recently unlocked iPhone to use Spotify. Of course to some this might be another betrayal of trust: Apple used to sell you products, now they want to sell you on-ramps to recurring revenue. Both of these issues of trust, however, pale in comparison to the single biggest question facing HomeView: do you trust Siri to actually work? From Mark Gurman at Bloomberg : Apple Inc.’s new HomeView has been a long time coming — far longer than the company intended. I first reported on the device in January 2023, when Apple was aiming to bring it to market as early as the end of 2024. What should have been a relatively straightforward launch instead turned into a nearly two-year saga of delays. The culprit was Apple’s AI crisis, which left the company without the one piece of technology the HomeView absolutely needed: a working version of its revamped Siri assistant… From the beginning, the HomeView was built around a Siri that could retrieve personal content, distinguish between members of a household and show each person private information. It was also designed to be controlled primarily by voice, rather than through its touch screen. Without a serviceable version of the new assistant, Apple couldn’t deliver the experience it had envisioned. That left the hardware ready to go, but the software nowhere near finished. So Apple postponed the HomeView repeatedly — first until spring 2025, then summer, then fall, and then again throughout 2026 before finally unveiling it this past week. And the hardware betrays its age. With thick bezels, an A18 processor and 8 gigabytes of memory, this is clearly a product conceived years ago. Finished units have been sitting boxed up in warehouses for the better part of a year, waiting for the software to catch up. There is a world where Apple never gives up on AirPort, and instead uses it as a foundation to deliver the integrated smarthome in the late 2010s; in that world Siri’s performance is important but also less pressing given that some number of homes would already be locked in. The second world, which Gurman describes, is one where Apple delivers on the new Siri in 2024 like it planned, and the HomeView is its showpiece experience. This is still a compelling product in that scenario, where integrating information from your iPhone is close to the cutting edge of what AI is capable of. The world we are in in 2026, however, is a much different one. In this world Siri AI has shipped, and while it is more capable than what came before, it is much slower, and makes more mistakes with basic tasks that the deterministic old Siri handled reliably. Moreover, the competitive landscape is dramatically different: agents like Muse, Instinct, Dots, or Grok Bots not only integrate information but actually act on it; new Siri already feels long in the tooth. This is where a foray into the home is particularly challenging. One doesn’t replace one’s thermostat or cameras or doorbells every year; these are one-time purchases meant to last for a long time. Ditto cutting a hole in your wall to mount a HomeView, which certainly makes more sense for many of the product’s core use cases. Making such a commitment, however, means committing to Siri AI as the primary interface, and trusting that Apple will make it good. This is a costly choice, and not just monetarily. The real concern is opportunity cost: committing to a world controlled by Siri AI means forgoing a world controlled by any other AI. That’s too expensive for me; how many consumers, even those who trust Apple to make things work together, and who value the company’s commitment to privacy, will make a similar evaluation? The answer right now, in 2026, is probably not too many, which is to say Apple might have got this product out just in time. I think there is something here, even if Apple’s marketing team doesn’t seem to be able to explain it very well. At the same time, I think HomeView highlights some of the mistakes and shortcomings of former CEO Tim Cook’s tenure; earlier this year when Cook retired I wrote about his impeccable timing , both in terms of when he took over Apple, and also when he stepped down: To that end, it’s right that Cook is stepping down now. Jobs might have been responsible for taking Apple from 0 to 1, but it was Cook that took Apple from 1 to $436 billion in revenue and $118 billion in profit last year. It’s a testament to his capabilities and execution that Apple didn’t suffer any sort of post-founder hangover; only time will tell if, along the way, Cook created the conditions for a crash out, by virtue of he himself forgetting The Cook Doctrine and what makes Apple Apple. The Cook Doctrine states that Apple needs “to own and control the primary technologies behind the products we make”, but Apple doesn’t own and control the models underlying Siri; meanwhile, one of the things that makes Apple Apple is focusing on making great products that customers love. How did Apple’s obsession with services revenue fit in that rubric, particularly when said obsession rose in conjunction with stripping out every part of the business that didn’t move the needle in terms of revenue, even if it made for a better user experience? Privacy, meanwhile, is great as a strategy credit ; what happens when it gets in the way of making products that work? It is true that Apple’s AI approach has the benefit of not moving the needle in terms of costs, at least relative to its big tech peers. It’s possible that just as Apple is partnering with LG Electronics and Schneider Electric on home devices, the company will deliver compelling experiences through its partnership with Google (and surprising thawing with Meta via its Meta Superintelligence Lab ). After all, Apple hasn’t always done everything — Lucent Technologies once featured in a Steve Jobs keynote! The difference is that that was an Apple that was eager to race ahead, not simply catch up; Jobs was planting seeds for the future, seeds that Cook harvested. Cook did make investments that matter, particularly in Apple Silicon (even if that effort started under Jobs), and in wearables; the job for Ternus will be ensuring that Apple’s “ease-of-use” technology is not just easy but actually useful. Years ago I set up a small monitor on the side of our condo’s living room for the kids to play video games; I happened to have a Raspberry Pi on hand, which I used to set up a service called DAKboard . DAKboard showed the time, the weather, the family calendar, and a rotating collection of photos. It has, in the intervening years, been one of our most-used and most-beloved pieces of technology, looked at multiple times a day every day. Thermostats are finicky and hard to use; it’s much better to be able to program them from your phone, or from a touch device. The problem for me in my current home is that my thermostats seem to mysteriously lose their connection to my home automation system every few weeks. Doorbells are critical in a world of e-commerce, especially when it comes to the dreaded “signature required”; incorporating them with your devices, along with a screen to see who is at the door, is a no-brainer. Unfortunately for me my doorbells also seem to get randomly disconnected, and I never notice until I miss a delivery. Cameras are a useful security measure, but only if you can actually view them. The issue is — you guessed it — that they often become inaccessible or are non-intuitive to use, particularly the moment you need them. Sometimes I want to access information without using my hands, like when I am cooking. You can prop up an iPhone or iPad in the kitchen, but what do you do when it goes to sleep in the middle of a recipe?

0 views

Static Analysis for the Uninitialized

I really enjoy learning new things in my free time. Lately I’ve been studying this book on Static Program Analysis . The book is very good, but some of the formulas are quite dense so I like to try writing them out in code. The chapter I’m currently reading (chapter 9) has a section on finding possibly-uninitialized variables using bipartite graphs. I’ve found it to be quite enjoyable, so in this post I would like to describe, in my own words, how to do it. We’ll start by analyzing some code from a toy programming language the book uses called “TIP”, and then we’ll use the techniques we developed to analyze some Ruby code. In other words, we’re going to write a program to analyze programs. We’re really going to be meta-programmers today! The TIP programming language is like a very very simplified version of JavaScript. Below is the code we’ll be analyzing: This example is taken straight from the chapter. In TIP, you declare variables with the keyword kind of like in JavaScript. In chapter 9 of the book, the TIP language only has integers; later chapters add pointers. In TIP, 0 is considered false, and there is a special function that returns an integer input from the user. Each line in the above code has a comment indicating which variables are possibly uninitialized. I keep saying “possibly”, and I’ll explain why later. The first line declares the variables with , and all variables start as “uninitialized” when they are declared. The second line gets input and assigns it to , so now only and are uninitialized. The third line adds and and assigns it to . On this line, is still considered to be “uninitialized” because is uninitialized, and the value of depends on the values of and . The fourth line is an if statement, and whether we take the if statement depends on input from the user. In other words, we can’t statically determine whether this statement is taken or not. The if statement doesn’t impact the “initializedness” of any variables, so all variables maintain their state ( and are uninitialized). If we take the branch, the 5th line will assign a value to , so at that line only is uninitialized. On the 6th line, we can’t know whether the if statement branch executed, so we have to say that and are possibly uninitialized. This is why our analysis is only giving us a “possibly uninitialized” result. If the branch is taken, then will be initialized, otherwise it won’t. But since we can’t know whether the branch will be taken, we have to be conservative and say that may be uninitialized on line 6. These two states, and , form a two element lattice, with on top. The top is the “safe” answer: it’s never wrong to say a variable might be uninitialized, it’s just less precise. When two paths in the code meet, like at the end of the if statement on line 6, we take the higher of the two states (because the less precise decision is also the “safe” one). On one path is initialized, on the other it’s possibly uninitialized, so after the if statement it’s possibly uninitialized. The rules for each line in uninitialized variable analysis are so-called “distributive functions”. For example, take the rule for line 3, . If we feed it the set , we get the same answer as feeding it and separately and then taking the union of the results: . This is just like in math class where we could say . In the case of a two element lattice and an analysis that uses a distributive function, we can represent the variable states using a bipartite graph. The book works out the proof for this, but I’m going to omit it (because I want to get to the coding part). But if you want to see the proof, check chapter 9! A bipartite graph is just a graph with “two sides”. Nodes on one side of the graph will connect with nodes on the other side of the graph, but never with their own side. I imagine it like two football teams tackling each other, each player is a node, and tackling someone else is an edge in the graph. Hopefully the players don’t tackle people on their own team, and they form a bipartite tackle graph! In our case, each node in our graph will represent a variable in the program, and we’ll have one extra node that represents “uninitialized”. For one graph, we’ll double those nodes, and use the edges to represent the flow of data through the code. For example, let’s look at the bipartite graph for the first line, : The node on the left represents the value “uninitialized”. On the line, the “uninitialized” value flows from to the , , and nodes. Next let’s look at the graph for line 2, : In this graph, the uninitialized node flows to itself. The variables and haven’t changed, so whatever value was in and just flow to the other side of the graph. The variable got initialized from , so no value flows to the other side of the graph. The reason no value flows is because we’re tracking “uninitializedness”, and on this line becomes initialized, so the absence of an edge means we got a value. If we repeat this value flow process and then line each graph up next to each other, we’ll end up with a graph like this: A black dot in the variable’s column indicates that the variable is possibly uninitialized at that point. Grey dots and lines indicate paths that don’t occur because the link was severed earlier. The dotted lines indicate alternate paths the code can take; an if statement has two outgoing paths. Looking at the graph we can see that (obviously) uninitialized ( ) is always uninitialized (we don’t bother to print that out because it’s not very helpful). We can also see that the black dots correspond to the “uninitialized variable” comments from the example code. For example, right after , the and variable have a black dot indicating that they are possibly uninitialized. If we assign each variable a number (and reserve 0 as the number for “uninitialized”), we can represent this bipartite graph in Ruby using a bit matrix. The graph needs to store a connection between any of the variables, and an “on” bit represents an “uninitialized” state from our lattice flowing from one variable to another. Since we need to be able to record an edge from any variable to any variable (plus the uninitialized value), the number of bits required is . Our example case has 3 variables, plus the extra variable for “uninitialized”, so we can do it in 16 bits. In practice though, to make accessing the data easier, we’ll align on a byte: The way we use this class is by assigning numbers to variables and then calling with the edges we need. For example, to represent , we need to connect “uninitialized” to the , , and variables. If we’ve assigned them numbers, we can do it as follows: Now we can represent the data flow rules for any line in the program. The next step is we need a way to connect graphs together. To do this, we’ll add another method that takes as input a list of “possibly uninitialized variables” (these are also known as “facts”) and returns a new list of “possibly uninitialized variables” based on the data flow rules for that graph. Since the input variables are just numbers, we can use each one as a row index into our bit matrix. Practically speaking, this means we bitwise OR together the rows for each input variable, and then get the position of the “on” bits in the output. Here is the code for the function: Let’s add a second rule for : In the above rule, just as in the visualization above, we connect the uninitialized nodes, then we connect to itself and to itself. These “self” connections mean “whatever value was in as input, we’re going to pass that along as output”. Now we can use the method and chain the two graphs together: At the start of the program nothing has been declared yet, so the only fact is “uninitialized” itself ( ). If we apply that to the first line, we see that all of the variables are “possibly uninitialized” (as expected). We can take the output of the application and feed it as the input to the next graph, and we see that the uninitialized variables are 2 and 3 (or , and ). Now all we need to do is define the rules for each line of code and apply them, and we’ll be able to calculate which variables are possibly uninitialized! Next we’re going to create a class that lets us record rules for each part of the program. The example code we wrote above works well for straight-line code since we can just apply the data flow rules from each line to the previous line. But the example program we have contains control flow and we’ll need a way to model the “dotted line” from the visualization above. To do that, we’re going to construct a simple control flow graph. A control flow graph (or CFG), is constructed from “basic blocks” where each block contains “straight line code” and ends in either a jump or a return. Each block has up to two outgoing edges, and those edges connect to possible jump targets. There are other ways to define a basic block, but this is my blog, so my rules! First we’ll define a class and a class. The class just holds on to the source line (a string for printing), and a graph representing the rules at that line. The class holds the list of objects that make up the block. It also contains a list of successors (jump targets) as well as predecessors (basic blocks whose jump target is the current block): Next we’ll define a class that has a bunch of helper methods that let us construct a CFG along with a graph for each line. I’m not going to explain all of the lines of the class because I think using the class is a better way to explain it. However, the full source is below. Let’s use the class to define all of the data flow rules for the sample TIP program: First we define a new program class. Then we ask the program class to record a source line of TIP along with the data flow rules for that line of code. I added lots of comments to explain the code, but let’s revisit one excerpt just to make double sure: Here we’re asking the program to record the TIP source code , and the data flow rule for this line is that “uninitialized” flows into , , and . This is exactly the same as the bipartite graph we created above, but this time we’re just recording that graph alongside the TIP source code. After we’ve recorded all of the rules, we call on the program so that it can calculate and set predecessor edges. We’ve got multiple graphs going on here. We’ve got a control flow graph that represents the program overall, and a bipartite graph representing data flow at each line. Our goal is to walk the CFG, and for each block calculate variable definedness at each line. The input state for each block is the union of the output state for that block’s predecessors. In other words, in order to analyze the whole CFG, we only really need to record the final state at the end of each block. Also, each calculation cares what happened in the past . For example, the definedness of the variables at line 2 care about what happened at line 1. This means we have a forward dataflow analysis . Any time the facts we derive depend on what happened in the past, it means we need to move forward through the code. So we define a strategy class that lets us analyze the CFG by moving forward through the code: In the above class, the method takes a basic block, looks up the predecessors for the block, then unions the output of those blocks. The function takes a block and some input (which happens to be the return value of ), and for each line of code in that block computes output facts based on the input. Those output facts are the “possibly uninitialized variables” at that line. Since we really only care about the state of the world at the end of the block, we just use an (a left fold for scheme people) over the code in the block. If, after analyzing all lines in the block, the facts are the same as what we had recorded previously, will return false. Otherwise, it saves the facts for that block and returns true. The method returns all blocks in reverse post-order (the traditional order for doing forward analysis that my grandparents used), and the method returns the successors for a block. We’ve got our CFG, and we’ve got a strategy for iterating the graph and analyzing it. Now we need to actually do the analysis. We discussed earlier that this problem is a two element lattice with a monotonic function (it moves up the lattice, never down). That means it’s perfect for a worklist algorithm. Our worklist algorithm is actually quite simple, it’s just this: Given an iteration strategy, ask for a list of blocks to process. While we have blocks to process, get a block. Ask the strategy for the input facts for that block, then ask the strategy to record output facts for that block given the input. If we learned something new ( returns true), then ask the strategy for children of that block and add the children to the worklist (if they aren’t in the worklist already). After this processing finishes, the hash inside the object will contain possibly-uninitialized variable information for each block. We can iterate over the blocks in the analysis and print out the possibly uninitialized variables for each line: Since we only recorded output information for each block, we have to do some extra processing at the end to print out the facts at each line, but if we run this code we finally get this output: Whew. That was a ton of work. But the good news is that we can reuse this framework for other languages too. I’m not going to explain the intricate details of this code, but we can use Prism to parse Ruby and feed that into our class. The function walks the Prism AST and records a rule for each statement, using the same kinds of rules we wrote by hand for TIP. Just to emphasize this, we wrote all of the data flow rules by hand for TIP, but our Prism code does it automatically based on assignments in the Ruby code. Once we get this into the program class, we can perform the same analysis on this code: (The curly braces are just how our class prints if statements, even for Ruby.) If you actually run this Ruby code, will raise a , because hasn’t been assigned yet so Ruby thinks it’s a method call. That’s exactly the kind of bug this analysis is meant to catch! You can find the full source for this program here . I feel like finding uninitialized variables isn’t that impressive. But the power in the technique here is that we can do any kind of analysis using this framework as long as the facts we track are a finite set, and the transfer functions are distributive (as I mentioned earlier). (The book calls this framework the IFDS framework, though I’ve omitted part of the full framework in this post). For example, we could use this same code to do “taint” analysis: “does this variable hold untrusted data?” If we were to number expressions and perform a backward analysis, we could discover what the book calls “very busy expressions”. A “very busy expression” is an expression that will definitely be evaluated no matter which path the code takes, before any of its variables change. For example: In the above example is considered “very busy” because we calculate it regardless of which branch the if statement takes. That means it is a candidate for hoisting above the if statement. Anyway, I’m having a lot of fun reading this book and I just wanted to share the stuff I’ve learned so far. Have a good day!

0 views

How I am reading more

We live in what is being referred to as a “ post literate society ” in which 40% of Americans did not read a single book last year . This is mind blowing to me, but - I can also see that with screentime (on a phone alone) being somewhere over 5 hours a day , it makes sense where most of everyone’s time is going. However, if we can replace even one of those hours of that screentime with reading books, and that will amount to reading far more than 0 books per year! I generally read around 20 books per year, but I figured that I could do far better than that (and did in 2023 ). That year also coincided with massive personal, spiritual, and professional growth - I don’t think that this is mutually exclusive and is probably correlative. This year, I made a resolution to get back at it, and this is how I am reading more. The most important thing I think nearly anyone can do to read more is reduce screentime on a phone. By simply installing Kindle, KoReader, Libby, AudioBookshelf, MuPDF, or one of many other reading apps, we can use this in lieu of doomscrolling social media and news websites. Going further, we can delete social applications, youtube, and even the browser, and replace any idle time at checkouts, commuting, and where you would historically be “wasting time” with reading and listening to books. We are simply going to “waste time”… better! While I personally don’t subscribe to this method in that I don’t retain nearly as much that is being said in audio form (this is why I don’t consume podcasts, either), some swear by the ability to read while on the go simply by listening to books. If it works for you, then awesome! I just don’t seem to benefit much from audiobooks. I may revisit this though for driving and the gym and update this post if I do use audio more often. My wife hates this one trick! This, for me, has been the biggest eye opener and allowed me to read ~100 pages per day over the past month or so of this experiment. I simply have books lying around in my office, in the living room, my Kobo sitting next to the bed, etc. and instead of picking up my phone, I pickup a book instead. All things are downstream of how we spend our time - time spent reading begets more reading. Some may not like this in that they want to read one book to completion before starting on the next. I personally have anywhere from 5-15 books on the go at once. Off the top of my head, here is a non-exhaustive list of what I have on the go: I find that reading this way is tremendously interesting in that there is “cross-pollination” between domains and a growing connection between all things. You will find authors across time and geographical location discussing the same quote, book, or idea, across domains of theology, physics, computer science, design, art, everything. I then sit and meditate with what I’ve ingested, and create connections of my own. It’s fascinating. Not only this but, it’s a “cheat” in that if I get bored with one book/topic, I just go on to another, in one big circle. Boredom doesn’t mean ceasing to read, just selecting something else that I am actually in the mood for. The very first thing I do in the morning is make the Sign of the Cross and Pray. The very next thing I do is sit down to read. I have started to wake up earlier in order to get the time to myself so I can do this, and it is truly awesome to get an hour or so or reading in before starting work. I read 10 pages, do some pushups and stretching, read 10 more pages, more physical activity, and repeat for about an hour. Most days I get about 30-50 pages in before anything, and I feel that it gets the wheels turning in my mind for writing, creating, etc. as I have always found reading to be “conversational”. I am not usually gung-ho in the morning to immediately begin working, and this has immensely helped my ability to drop into work and the rest of the day. Try it out! If you are so inclined to use applications such as Goodreads or the like, then this can be a fun way to keep track of that which you are reading and “compete” with friends. I’d recommend against giving Amazon all your data, but you do you. I also think that reading has become an extension of social media in that there is an element of “one-uppmanship” which I don’t care to participate in. I personally keep a /reading page on my blog for the current year, and keep track that way. It’s a fun way to discuss books when people can see what you’re reading on your blog and it’s a good conversation starter. I have always hated the rationalization that “reading is too slow”, or that “I have no time to read!” As I said above, if you have time to scroll your phone, you have time to read and converse with the greatest minds that have ever lived. We need to slow down more than ever in this crazy, accelerating world. I find that almost no one sits and chews on ideas anymore, and that is detrimental to the future of humanity if we are not to create polymaths and people of skill. If we don’t have time to read, we don’t have time to grow, and that is simply not true. So, read more! I am thankful that my parents and teachers instilled a love of reading in me from a young age. Truly, one can learn about anything and everything if we only pick up a book and start flipping through. I personally don’t want to live in a post-literate society, I want to discuss these great works and continue to learn from everyone that’s come before, so that is why I choose to keep reading, and to read as much as I possibly can. Try it out for a month, and see how much you fall (back) in love with reading. I think we have all just forgotten how amazing it is to pick up a great book and lose ourselves in the worlds and ideas of another’s mind. As always, God bless, and until next time. If you enjoyed this post, consider Supporting my work , Checking out my book , Working with me , or sending me an Email to tell me what you think. The Brothers Karamazov The Go Programming Language The Art of Unix Programming The Republic An Introduction to the Devout Life The C Programming Language (K&R) Structure and Interpretation of Computer Programs Chruch Fathers Against the Machine The Bible (Everyday, first thing I read) Operating Systems, Three Easy Pieces Computer Systems: A Programmers Perspective Designing Data-Intensive Applications

0 views

What requirements don't you have?

When designing software, the requirements you don’t have are as important as the requirements you do. Identifying what you can compromise on — what can be slow, or stale, or inflexible — is usually the key to an elegant design. For instance, take preforking web servers like Unicorn . Because they lack the feature of shared mutable state between server instances, they can run each server in its own process, which provides isolation for free. Because Unicorn specifically ignores the problem of slow client handling 1 , it can queue requests directly on Unix sockets, drastically simplifying the implementation. Because S3 does not support atomic multi-key updates — you cannot update multiple blobs in a single transaction — it can store data at the blob level however it chooses. That makes it much faster, since reads and writes don’t have to cross storage partitions, and much easier to scale, since less coordination means fewer sources of truth. StatsD uses UDP by default, which means it doesn’t guarantee that every piece of data you send makes it into storage. In exchange for dropping that requirement, it incurs much less network overhead, which is a big advantage for a stats aggregation service that’s constantly shoveling data over the wire. The general design approach of fanning out data to an edge cache buys a lot of speed and scaling by dropping the requirement that data must always be up-to-date. SQLite buys operational simplicity — it can run out of a single file! — by dropping the requirement of concurrent writes. By accepting high tail latency 2 , Cursor can scale their distributed git backend more easily. Well-designed systems turn their weaknesses into strengths. Anyone who’s spent time designing real-world software (or who’s studied distributed systems ) knows that system design is a process of compromise. If you attempt to satisfy every single potential requirement — speed, concurrency, up-to-date data, a simple interface, supporting complex user behaviors — you will fail to design a working system at all. Figuring out what requirements you can relax is difficult because it combines both business and technical expertise . It is technically challenging to identify precisely the level of staleness that a particular design change will allow; it is likewise challenging from a business perspective to determine whether that level of staleness is acceptable to users. In most cases, an engineer who understands the technical side must try and explain it to a product manager, who can make a judgement on the business side. But this is a very difficult partnership to get right. Engineers and PMs have different incentives and little ability to check each other’s work, which makes it hard to build trust . Without trust, the product manager is liable to avoid giving any ground at all 3 , which leaves the design in an impossible state. This is an underappreciated reason why solo developers or startups can sometimes run rings around larger companies. Because the technical and business decisions are united in a single person, they can make design tradeoffs that would be impossible for a large company, enabling them to build systems that are far more elegant and powerful. Knowing what requirements you don’t have becomes far more important when working with coding agents. Frontier models are very capable, but they have all gone through the purifying flames of RLVR : like high-achieving schoolchildren, they are obsessed with satisfying the Grader. On top of that, they have very little business context compared to an experienced human. That often manifests as them catching correctness or consistency “bugs” that are really just hypothetical unsatisfied requirements. For instance, it’s not uncommon for an LLM to casually introduce a mutex or other concurrency mechanism to ensure that two pieces of semi-related data are kept in sync, even if not told to do so. I’ve seen LLMs add weird checks in the middle of request handling to ensure that some already-checked piece of data hasn’t changed mid-flight, even if that wouldn’t successfully prevent the feared TOCTOU bug 4 . LLMs are obsessed with edge cases like “what if the current user loses their admin status in the middle of us handling one of their admin requests?” 5 , or “what if the cache in storage partition A is updated a nanosecond before the one in storage partition B, leading some users to see different data?“. Particularly if run in a loop or told to “make no mistakes”, they will pile on cases like these until they’ve transformed your four-line change into a thousand-line monster. This is why I’m confused by some people’s claims that code review is dead . About half the time I review a large AI-generated change, I notice some unnecessary requirement that makes the diff more complex. When I dig deeper, the LLM invariably introduced this requirement on its own. When working with a cache, I will often spell out in my prompt that I don’t mind the data sometimes being stale or briefly inconsistent between cache instances. When reviewing Golang code, the first thing I do is scan for added mutexes or layers of indirection that don’t look necessary to me. If you allow requirements like these to propagate unchecked through a codebase, they will petrify the system over time. The whole thing will be such a mess of checking and re-checking and holding locks and enforcing consistency that it cannot be scaled at all. Keeping systems elegant requires a ruthless focus: on accepting stale data or occasional tail latency, on avoiding all but critical instances of coordination, and in general on figuring out what requirements you don’t have to satisfy. The problem: if an HTTP request sent by someone with slow internet trickles in one packet per second, does that have to tie up a server process for the whole time? Unicorn’s answer is ‘yes, so put nginx or HAProxy in front of me’. When a read request hits a stale storage node, that node must update itself before responding. I’ve also seen this happen in reverse, where the product manager desperately tries to convince an engineer that some level of stale data is acceptable, while the engineer digs their heels in and insists on the “perfect” system. The consequences are similarly dire. Of course, simply doing a separate check shortens the TOCTOU window instead of removing it. In every single system I’ve worked on, it would be fine to simply carry out (or fail) the admin request: if somebody was allowed to perform some operation 10ms ago, it’s likely not a disaster to let them perform it now. The problem: if an HTTP request sent by someone with slow internet trickles in one packet per second, does that have to tie up a server process for the whole time? Unicorn’s answer is ‘yes, so put nginx or HAProxy in front of me’. ↩ When a read request hits a stale storage node, that node must update itself before responding. ↩ I’ve also seen this happen in reverse, where the product manager desperately tries to convince an engineer that some level of stale data is acceptable, while the engineer digs their heels in and insists on the “perfect” system. The consequences are similarly dire. ↩ Of course, simply doing a separate check shortens the TOCTOU window instead of removing it. ↩ In every single system I’ve worked on, it would be fine to simply carry out (or fail) the admin request: if somebody was allowed to perform some operation 10ms ago, it’s likely not a disaster to let them perform it now. ↩

0 views
Unsung Yesterday

Motor, motor memory

While I didn’t have as much fun with car lights , I experienced another nice motor memory moment last week when using CarPlay. During my drive, I wanted to ask the new Siri something – but as only an occasional driver, and my phone out of sight, I was puzzled as to how to actually invoke it. I did see the new Siri app icon appear in the sidebar on the car’s screen, but tapping on that only showed me a list of prior conversations. Sure, I could probably initiate a new chat by tapping the button in the top right corner, but that corner felt really far away from where I was sitting, and didn’t feel inviting to someone who – just as a reminder – was driving a car at that time: So before giving up, I did one thing that somehow felt very natural – I pressed and held the “home” button in the bottom left corner: And… it totally worked. I feel that with any good motor memory story , your fingers do something seemingly on their own, and then it’s up to you to figure out why they did so. I believe in this case they did so because Apple built a good set of overlapping gestures and expectations: So, kudos to the many designers on sustaining a stable gesture system that lasted decades, and embedded itself in my fingers so well that it felt completely natural to invoke in a situation I really wasn’t allowed to split my attention or play with the interface. (An extra delightful moment in that last video – note how the physical home button and the virtual Siri button match in size.) In many other places – iPhone, Apple TV – you long press a physical button to invoke Siri. Also, on Apple’s touch devices and on Apple TV, “long press” on a touch target has been a consistent entry point to an “advanced function” in a same way right click is on desktop. Lastly, on earlier iPhones asking for Siri was literally a long press of the physical home button:

0 views
Kev Quirk Yesterday

2026-10-18 13:22: Terence Eden asking on Mastodon what people's setups look like. Here's mine - 38" ultrawide...

Terence Eden asking on Mastodon what people's setups look like. Here's mine - 38" ultrawide LG monitor that docks to my Framework 13, Fully standing desk, fish tank and motorbike helmets on the wall. I love my home office, but I do like heading into the office too. 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
Kev Quirk Yesterday

Year 4 at the Smallholding

So today marks the 4th anniversary of us moving to our 2.5 acre smallholding in north Wales. I can't believe it's been 4 years already - it feels like 5 minutes ago that I was writing my 3 years at the smallholding post . Last year's update wasn't as positive as previous years thanks to us having to get a new roof, which cost a shit tonne of money, and caused leaks all over the house. But I'm happy to say that the update for this year is mostly positive. I ended last year's post by saying: If next year I can get the polytunnel and conservatory done, I'll class that as a win. I'd love to get a quad bike for towing the flail too, but again...money. Unfortunately there's no poly tunnel, no insulation in the conservatory, and no quad bike in the barn. Let me explain... In March of this year we decided it would be a good idea to get some goats. My wife had been talking to a goat farmer in mid-Wales for a few months, and we decided the time was right to get some. So we ordered 4 male pygmy goats and brought them home in the back of the car! Our first 4 goats arriving home While we were at the farm, the farmer showed us a beautiful half pygmy, half "normal" goat and her 2 kids, along with a little pygmy goat that followed her around like a lost puppy. We immediately warmed to all of them, but we couldn't fit them in the car, so we had to pass. After a week or so of thinking about them, my wife decided to head back down there and pick them up too. So we ended up with 8 goats all together. I'm really glad that my wife decided to get the second batch, as the mum (now called Betsy) is so friendly and one of my favourite of the group. Betsy being lovely (as usual) We're very lucky to have a pair of stables at the back of our property, one was already used by the chickens, so we setup the other for the goats. However, the stables and surrounding needed some work. We had to: Unfortunately this all took up what little budget we had left following the roof, so the poly tunnel and insulation in the conservatory had to wait. We completed the renovations on the stables and both the chickens and the goats now have a lovely little home that has lots of space, but (more importantly) meets their needs. Goats and chickens on the rock wall Here's a little gallery of how the work progressed on the stables: As well as goats, we decided to add to our flock of chickens, but instead of just buying more we wanted to do it a little differently. We have a rooster now, so all our eggs are fertilised and we decided to try and hatch some eggs instead. We also wanted to get something a little different, so my wife bought some guinea fowl eggs, which we put under a broody hen to see if they would hatch. They did, and we ended up with 5 beautiful (but noisy) guinea fowl. The guinea fowl were a great success - 5 of the 6 eggs hatched. So we decided to attempt the same thing with some of our chicken eggs, especially since a fox had gotten one of the hens and we wanted to hatch some of her eggs. Unfortunately we had no broody hens at the time, so we decided to buy an incubator and cheat. We attempted to hatch 12 eggs, but only 3 were successful unfortunately. We think 2 of them are roosters too, so we will see how that goes as they grow up and undoubtedly challenge their dad. We're thinking about doing it again this spring, but we're worried about having a plethora of roosters and what we will ultimately have to do to them. 💀 Finally I installed some new perches for the chickens to roost on in the evening. Below is a removable shelf that makes things way easier to clean. So at this point we had used up everything we had saved. We had literally nothing in our savings account. Then we noticed that our older dog, Tia, who's 14, was getting very smelly breath and whenever she was chewing her favourite ball, her mouth was bleeding. So we took her to the vets and they told us she had a fairly common type of benign tumour growing in her mouth. Although it was benign, it was very aggressive and if left untreated she would have 6-12 months if she was lucky. And it would be a very uncomfortable end for her. We had to get it looked at, but this was going to cost thousands and in a 14 year old dog, I wasn't sure if it was worth it. The last thing we wanted was to put her through all this only to find out in a few months that she had another terminal condition that would end her life anyway. I know that sounds heartless, but I think at times like this it's important to be practical and take into account how much the dog will suffer, and whether we're doing it for us, or them. She needed a CT scan on her jaw to see if surgery was viable, so we decided to get a full body CT scan done instead. This would give us a good indication if anything else untoward was going on in her body. Lucky for us the CT came back all clear and the surgery on her jaw was viable, so we went ahead. Three operations, 1 infection, and lots of discomfort later for poor Tia, and she's now fully recovered after having around 40% of her lower jaw removed. Unfortunately for her, this means her rather large tongue often dangles out of her mouth these days. But we think she's still gorgeous. As if this wasn't punishment enough, we also got a new puppy, Nelly, at the same time that Tia was going through all this. So managing a sick dog, a new puppy, and keeping 2 kids entertained during their summer holidays really wasn't a fun time. We had bought Nelly way before we knew Tia was sick. The kids knew she was coming, and we had all met Nell multiple times. So although we knew it would be a nightmare, we didn't want to renege on buying her. Let me tell you, dear reader, it was rough . Like, really rough, but we're glad we stuck it out because Nelly is beautiful and such a wonderful addition to our family. Tia's surgery ended up costing us around £6,000 (~$8,000). We already had no money, so it had to go on a credit card, which we will pay off over the next few months. Our plans for year 5 are the same as year 4, I think - we'd love to get a poly tunnel in and the roof in the conservatory insulated so we can use it all year round. But we will need to see how the finances go - hopefully there will be no more unexpected expenses for a little while. We can only hope. In the meantime we continue to enjoy our brood of various animals and the little plot we call home. 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 . Install a land drain and level the ground Extend the hard standing around the stables Get some fencing installed Replace the doors and windows Install ventilation and power Create a "rock wall" for the goats to play on

0 views

Notes on the complex roots of unity

One of the most wonderful aspects of math is how deep we can get by studying seemingly trivial questions. Consider the roots of unity, where "unity" simply means the number 1. Studying the roots of unity usually begins in middle school: what is the square root of 1? Equivalently, what are the solutions to this equation? Well, there are two answers: 1 and -1. Similarly, we can ask the question for higher roots; the third roots are solutions to the equation: And so on. When we’re only dealing with real numbers, that’s pretty much the whole story. For odd-degree roots of 1, the only answer is 1; for even-degree roots of 1, the answer is either 1 or -1. When we extend our domain to the complex numbers, things become much more interesting. By the formal definition , a root of unity is any complex number that yields 1 when raised to a positive integer power n . Rather than looking at all the possible roots of 1, it’s often more useful to discuss the roots for a specific given n : complex numbers z such that z^n=1 . For example, let’s consider n=2 . We’ve already seen that the roots are 1 and -1; these are complex numbers with a zero imaginary part. How about n=4 ? There are four roots: 1, -1, i and -i . For n=3 , the three roots [1] are 1, \frac{-1+i\sqrt{3}}{2} and \frac{-1-i\sqrt{3}}{2} . It’s easy enough to check that these indeed give 1 when raised to the third power, but how do we calculate them in the first place? A complex number with magnitude 1 can be represented in polar coordinates [2] as z=e^{i\theta} . If we raise z to the n -th power, we get: The magnitude of z^n is still 1, which is essential if we want z to be a n -th root of unity. Let’s equate z^n to 1: To find the solutions to this equation, we’ll first want to represent 1 itself in polar coordinates. Let’s use another variable for the angle: What is the value of \phi ? Thinking about the unit circle, \phi is any integer multiple of 2\pi - which we’ll express as 2\pi k for k=0,1,2... : Back to z^n : So the n -th roots of unity are [3] : Let’s begin with n=2 . We have the following roots: As expected. It should be similarly simple to calculate the roots for n=4 ; give it a try. What happens when we multiply some root of unity z_k by itself? Since the magnitude of the root is 1, multiplying by it is akin to a rotation along the unit circle by the root’s angle. For example, consider z_1 from the 3rd roots of unity: Multiply z_1 by itself: If the angle of z_1 is 2\pi/3 , the angle of z_1^2 is 4\pi/3 . Let’s multiply by z_1 once more: The result is 1, as expected (after all, z_1 is a 3rd root of unity). This visualization shows how roots of unity appear on the unit circle and how raising them to powers rotates the roots until finally z_k^n=1 : Select n first; this shows the n -th roots as blue dots on the unit circle. Now you can click any of the roots, and see its powers in the lower plot - drag the slidebar to see the rotations. If you spend some time playing with this, you’ll notice that some roots - for example z_2 when n=6 - go back to 1 when raised to a smaller power than n . We’ll revisit this outcome when we discuss the group-theoretic aspects of roots of unity. As we’ve seen, the roots of unity are evenly spaced along the unit circle on the complex plane. If we connect the roots with straight lines to their immediate neighbors, we’ll notice something interesting: For different values of n\ge3 , we get the Regular Polygons ! It’s pretty easy to prove this if we connect each root with a straight line to the origin. The triangles we get are congruent, because the sides from the origin to the roots are all of length 1, and the central angles are all 2\pi /n . Therefore, both the sides of the polygons and their angles are identical, which makes them regular. Suppose we have the root of unity: For some k and n . If we take the reciprocal of z_k : So z_k^{-1} is also an n-th root of unity. While the powers of z_k are rotating counter-clockwise on the unit circle until they land on 1 for the n -th power, the powers of z_k^{-1} similarly rotate clockwise . z_k^{-1} also happens to be the complex conjugate of z_k : So if we have: As the n -th roots of unity, then: Are also n -th roots of unity. In fact, they are the same roots, because for any given positive k : So enumerating the conjugate roots is the same as enumerating the roots themselves in the opposite order. Let’s look at the set of z_k (roots of unity) for some n : This set - along with the multiplication operation - forms a group . Let’s prove that. Closure: Assume z,y\in\mu_n (so z^n=1 and y^n=1 ). Then: Therefore zy\in\mu_n . Identity: The number 1\in\mu_n , so it can serve as our identity element for the group. Associativity: Taken directly from the associativity of the multiplication operation on complex numbers. Inverse: We’ve just seen in the section on conjugates that z^{-1} is an n -th root of unity when z is. So the inverse exists and is part of the group. Because the operation we have is just complex multiplication, we can trivially derive additional properties, like commutativity. Therefore, the group \mu_n is Abelian . Finally, we can show that the group is also cyclic and discuss its generators . For slightly simpler notation, let’s denote w=z_1 . So the group can be represented as: This makes it obvious that the group is cyclic - all its elements can be expressed as integer powers of w . And w is a generator for the group. But interestingly, w is not the only generator for this group. Any w^k can be a generator, as long as k and n are co-prime. For example, consider the group \mu_6 : Obviously, w is a generator for this group. But w^2 isn’t! If we raise it to various powers we get: Since w^6=1 , the powers of w^2 repeat after just three steps, so they only reach three out of six group elements. But if k and n are co-prime, w^k is a generator; in the case of \mu_6 , we can easily verify that w and w^5 are the only generators. The roots that are generators for the group are also called the primitive roots . Let’s take the n -roots of unity ( n>1 ), denoted as above with: What’s the sum of all these roots? This is just the sum of a geometric series with the first term 1 and common ratio r=w . Therefore: If you look carefully at the visualization shown above - this makes sense geometrically. All the roots of unity are evenly spread around the unit circle, so viewing them as vectors, all components cancel out. How about the sum of roots raised to some integer power k ? Let’s try this for k=2 (assuming n>2 ): Using the same geometric series sum formula (with r=w^2 ), we get: In general, when k is not divisible by n , the sum is 0. But when k is divisible by n , each power becomes: And n of these sum to n . In conclusion: Let’s consider the powers of roots of unity as vectors. We’ll continue using the notation: We’ll begin with the 0-th power vector - each of the roots raised to power 0: Then power 1 - just the roots themselves: Each root raised to power 2: And so on, until power n-1 : To go full linear algebra mode, we’ll collect these vectors into an n\times n matrix: Let’s calculate the inner product of two matrix rows. Recall that when computing the inner product on vectors over \mathbb{C} , we conjugate the second element: But hold on, we’ve just calculated this exact sum in the previous section. We get: Since the vector indices i and j only run over [0..n-1] , this is equivalent to: Which is to say: the vectors v_i and v_j are mutually orthogonal when i\neq j . Since we have a set of n orthogonal vectors in \mathbb{C}^n , these vectors form a basis for \mathbb{C}^n - any vector in this space can be represented as a linear combination of v_i . This fact has far reaching consequences in math and engineering, since it plays a critical part in forming the DFT (Discrete Fourier Transform), and V is also known as the Fourier matrix . But this will be a topic for a separate post. Another fun thing to notice before we’re finished here: the matrix V happens to be symmetric (this is trivial to check by observation). Therefore, its columns are also mutually orthogonal.

0 views
Sean Goedecke Yesterday

Writing is no longer proof of work

Tech companies structurally depend on writing to serve as evidence, in the same way that Bitcoin depends on proof-of-work hashing. However, in the last few years, LLMs have started to undermine this practice. How can writing be like proof-of-work? When I’m writing something at work, it’s not always to communicate an idea. Sometimes it’s because having a piece of writing is useful as evidence : of compliance with some process, of the fact that I put in effort, or of the fact that I know about some topic. Here are some examples. The most obvious instance of writing as evidence is filling out mandatory templates: “risk assessments”, “impact evaluations”, and so on. The purpose of these is rarely to assess risk or evaluate impact. It’s some combination of: It’s a mistake to buckle down and produce an excellent piece of writing here. You simply need to dash off something plausible enough to tick the box. In the kinds of hundred-page reports produced by consultants, writing is evidence of effort . The actual piece of communication is the first page of text (or often not even that). The remaining ninety-nine pages are proof that the first page is well-researched, and that the money spent on hiring the consultancy wasn’t wasted. Another example: if you’re working on a project by yourself, why spend time creating tickets and filling them out? I suppose theoretically someone could read them to get a sense of what you’re doing, but in that case you’ve failed to communicate the project via normal channels: telling people in Slack or in meetings, writing a proposal document, and so on. The tickets are primarily valuable as evidence : proof 1 that you haven’t just been screwing around playing video games. A third subcategory of writing-as-evidence is writing that proves that the writer has understood some topic. The best example of this is reporting. Large organizations function via a tree of nested reports, often called “rollups”. Individual contributors give status updates to their managers, who summarize and combine those into team-level updates for their managers, and so on all the way to the top. One of the reasons for this practice is that it forces each manager to build at least a minimal mental model of what’s going on in their local area. Taking the time to write a status report forces you to wrap your head around each detail, for the same reason that the best way to understand an idea is to try to explain it to someone else. Even if the VP or CEO doesn’t read the rollup, the fact that it exists is evidence that the manager has some grip over their domain. You can think of all these kinds of writing-as-evidence as proof of work . Nobody really cares about the content, they care about the fact that you sat down and wrote it . Of course, this requires a measure of trust. Just like cryptocurrency proof-of-work, if you fake it (for instance, by pasting lorem ipsum into pages 2-100 of your report), you can swindle the rewards without having to actually put in the effort. To avoid fraud, tech companies will typically check some percentage of writing-as-evidence: either reactively, such as when an incident causes people to actually go and read the risk assessment on the PR that broke production, or proactively, by tasking some poor soul with reviewing the consultant report in detail. Blockchains, of course, are able to check the work automatically (for instance, by confirming that the nonce and block data do in fact hash to the claimed value). To break Bitcoin, somebody would have to break SHA-256: to figure out a way to identify in advance what content would hash to a specific value, so you could produce the hash without doing the work. To break writing-as-evidence, somebody would have to figure out a way to generate text on demand, so you could produce the evidence (of compliance, effort or learning) without actually doing the work. Unfortunately, that happened in 2023 . Writing is no longer evidence of anything. LLM-produced writing makes evidence of compliance even more vacuous than it already is. It totally destroys evidence of effort: if you need a hundred-page report, you can generate one with an hour and a few dollars in inference tokens. Evidence of learning is likewise broken, since I can produce a detailed status report full of information that never passed through my mind at all (and certainly was never retained). Of course, this problem isn’t limited to tech companies. Schools and universities rely on writing to serve as evidence of effort and learning, and students are using LLMs to cheat as hard as they can. Many political or regulatory bodies require a certain bar of professional writing in order to filter requests, and are or will be overloaded by LLMs making that kind of writing generally available. Currently we’re suffering through an overhang period where the processes are still in place but everyone knows how to trivially exploit them. It will be interesting to see how organizations adapt. They might: I can’t think of any great options here, which is interesting. If there really is no easy solution to this problem, the overhang period might go on for a while, where nobody is particularly happy with the status quo but there are no good alternatives. In this scenario, individual software engineers are incentivized to exploit the system while they can, and avoid being harmed by other system-exploiters. In other words: don’t trust or waste time poring through LLM-authored documents yourself, but also don’t waste time writing documents by hand that are just intended to serve as evidence 3 . Save that effort for documents that are intended to serve as communication . Why not just look at your code? Code is an illegible metric to non-technical people. Even to technical people it can be tricky to figure out how difficult a piece of code was to write, for the same reason that it’s tricky to assess how difficult a mechanical puzzle is just by seeing it when it’s assembled. But everyone knows roughly how long it takes to write a paragraph of text. Software companies will be reluctant to adopt this, because they see internal LLM adoption as a necessary tool to speed product development. They’re already begging employees to use LLMs; if they start telling them to not use LLMs for writing, that muddies the message. Part of this involves getting good at telling the difference (in other words, getting good at figuring out if anyone is actually going to read the document). There may also be a third emerging category here: texts that won’t be read but also won’t be ignored, because they’re intended for consumption by other LLMs. Employees wanting to demonstrate that they’re taking some incident seriously by introducing new process A legal requirement that companies have developed the least-expensive way to technically satisfy Internal company rules intending to scare lazy or uncommitted engineers away from making dangerous changes Smaller companies trying to role-play processes from larger companies that are doing one of the above Introduce new, harder-to-forge forms of evidence like recording a video or presenting live in a meeting (though this will take more time to consume than written reports) Attempt to mandate that certain forms of writing not be AI-generated (universities already do this 2 ), which will be difficult to enforce Find other ways to track effort, such as asking an LLM to review an engineer’s code and judge how much work they put in Why not just look at your code? Code is an illegible metric to non-technical people. Even to technical people it can be tricky to figure out how difficult a piece of code was to write, for the same reason that it’s tricky to assess how difficult a mechanical puzzle is just by seeing it when it’s assembled. But everyone knows roughly how long it takes to write a paragraph of text. ↩ Software companies will be reluctant to adopt this, because they see internal LLM adoption as a necessary tool to speed product development. They’re already begging employees to use LLMs; if they start telling them to not use LLMs for writing, that muddies the message. ↩ Part of this involves getting good at telling the difference (in other words, getting good at figuring out if anyone is actually going to read the document). There may also be a third emerging category here: texts that won’t be read but also won’t be ignored, because they’re intended for consumption by other LLMs. ↩

0 views

How the AI boom might really end: 5 scenarios

With the Anthropic IPO gathering pace - and chip stocks just posting their longest losing streak since 2008 amid worries about AI debt , I thought it'd be worth writing up some of my thoughts I've put together while thinking through what may happen. By no means is this meant to be exhaustive - just a list of what I think is the most interesting to think through. Before I dive into the scenarios, while I'm sure there are going to be failures and mispricing of asset classes - like any huge investment wave - I think it's worth saying that unlike many bubbles there is an enormous amount of value being created. In essence, I think this is the first time capital can be turned into intelligence. You buy (or borrow money for) GPUs, you get tokens out which represent a growing share of professional service work. I'm certainly biased as a software engineer by trade - the models just get better and better at coding and it's humbling to see it do my previous tasks so quickly and increasingly better than I can do them. And unlike (say) the dotcom boom, which was arguably directionally correct, but far too early, we're seeing mass adoption and huge revenues being generated, far quicker than in the late 90s. So thinking through this, I'd group the scenarios into two categories. Firstly, AI itself doesn't deliver the value promised or gets stopped by external factors. I think these are worth thinking through. The other category - and potentially more likely - is that AI works well, but the value doesn't flow to the people that are putting the money in. I think this is where the unwinding could happen, and arguably is already showing up. While it's hard to argue that the models as is aren't "good" at specific tasks now, it may well be that we hit a scaling wall. Increasing amounts of capex is pumped into model training, but the results are incrementally better. This leads to a "hard" wall on progress until another architecture or approach potentially comes along. This one I'd discount for now. We're seeing no signs of progress slowing, and we're seeing very fast advancement in capabilities. And even if this did happen, most organisations and people aren't using anywhere near their full power. The one watch out though which is a bit more insidious is that the models continue getting better at specific tasks, but start regressing badly in others. I feel Opus 5 was a good example of this - better at coding, but produced infuriatingly hard-to-read prose. Perhaps we'll see models more focused at specific tasks if this gets harder to mitigate (much like the Codex series of GPT models, which then got unified back into the main GPT models). The other major risk with AI is that it ends up doing something bad in the real world. We've already seen the Hugging Face incident as a 'warning shot'. But there are far more catastrophic risks at play - for example, shutting down national infrastructure, or hacking a major financial institution that results in systemic risk across markets. Or, it goes full Skynet. There is no doubt this would cause enormous political upheaval that would lead to very rapid and severe backlash. Where the industry goes after that is hard to see - potentially progress gets frozen, resulting in far fewer orders for GPUs. On the other hand, it's hard for me to see a globally coordinated moratorium on AI given the breakneck competition between (primarily) the US and China. If it happened in China, is the US likely to follow suit? Or would it, instead, be blamed on "defective Chinese" models, and the US continues as is? Equally, if it happens in the US, does China pause or see this as a once in a generation opportunity to leap ahead? I think we are getting dangerously close to an incident that may cause some sort of significant pullback in AI spending. It's certainly hard to predict, and the severity matters a lot - along with human impact. Slightly less science fiction-y would be widespread local or political opposition to datacentre rollouts causing a very widespread pause on new capacity coming on stream. While this is certainly happening - I have a suspicion this could be one of the key battlelines for the 2028 US election cycle - it again would have to be a global ban to have any significant effect. If the US does a ban, projects and investments would quickly shift to other jurisdictions. And I'm almost certain that China would not even entertain any sort of ban like this, which again adds a geopolitical angle to it. Would the US really want to go ahead with a national ban when China already has a commanding lead in electricity capacity (if not semiconductors). As such, I can't see this having a great effect on the deployment as a whole. The real weakness lies in financing these deals. Much like Ørsted needed a $9.4bn rights issue after US stop-work orders on its offshore wind projects spooked its financing, we could quickly see a domino effect of financing failures caused by it. I think this is the standout from where I see the risk and something I've been writing about for a while now. We're in the middle of a brutal inference price war - if you want to read more read my other recent article . This is largely caused by open weights models crossing the threshold of being "good enough" for many tasks. Anthropic releasing Haiku 5.5 at a huge discount - 90% cheaper on short context windows - means that for shorter, bulk tasks, Anthropic & OpenAI are actually as cheap as, or cheaper than, comparable open weights models. This doesn't apply for longer agentic tasks with Haiku - the price jumps 5x once you go over 100K tokens of context. Interestingly, OpenAI is far more aggressive here: GPT-6 Luna only goes up 1.5-2x, and only past 272K tokens. But I was surprised recently to find that no reputable inference provider offers comparable open weights models (e.g. DeepSeek) at any significant discount to Haiku and Luna, which is an enormous change from where we were at the start of the year, where the frontier labs were charging 10-20x more than open weight models. How much this cannibalises their more expensive models is up for debate. They've done the pricing in such a way that for longer agentic tasks, open weight models are still very attractive. But the perpetual price drops must be having some impact on margins, even if it does lead to them (re)taking market share from open weights competitors. So the hope is that they continue cutting prices, but revenue/token growth outstrips that. It is certainly possible - but it shows how fast this market switches that we've now got frontier labs offering this inference at all . The wildcard I would keep though is that while the open weights labs have kept pace, we can't rule out the frontier labs' ability to throw a lot of compute and brainpower at new models. Opus 5.5, for example, is an excellent model for more demanding tasks. And the Chinese labs are clearly short of hardware and facing new export restrictions from the Chinese government. Note that the previous scenario, while catastrophic for the frontier labs if this compression continues, arguably increases demand for semiconductors, memory and the related supply chain. But another risk is that if there are huge efficiency breakthroughs, either through hardware or software/model improvements. This is what killed the telecoms boom in the early 2000s - it wasn't so much that bandwidth growth stopped, but the efficiency of fibre optics far outpaced the demands. So far we've seen a lot of innovation on the model side, but hardware has struggled to keep pace. Discounting all the hype stats that Nvidia etc put out for each new generation [1] , underlying tokens/watt - the best figure to watch - is improving far slower than the headlines suggest. The model efficiency improvements have been pretty amazing to watch. But so far, this has all been put into longer context windows (enabling longer running agentic tasks) and have enabled some of the price decreases we've seen. But, there is a world where a new hardware or software approach does lead, much like DWDM fibre back in the 2000s, to efficiency running far, far ahead of token growth, even taking Jevons paradox into account. My gut says that token demand is growing so fast, and will continue to grow so fast that it will consume all efficiency gains in the near future. The key way to track this I think is not looking at some of the "token cost indexes" that get posted about - this doesn't adjust for the exponential growth in demand - but instead look at the cost of GPUs on the spot market. If we start seeing big , broad drops across all compute types, then that's a clear sign that supply and demand is starting to reach equilibrium and this scenario is starting to play out. There are no doubt many risks to the AI "economy", and it's always easy to point to whatever one is making the most news. But to me the real question is whether AI progress is turning into tangible value. Right now - for me, and many others, the answer is a resounding yes. Token consumption is going through the roof, because as models get better more and more tasks can be executed with AI. And I still think early adopters that are pushing agentic workflows comprise a small single-digit percentage of the professional services market as a whole. But this doesn't mean that the labs making and serving those models take the benefit. History is littered with huge technological advancements which went to consumer surplus , not whoever bet the most capital. And my view is that's what we are seeing right now. The frontier labs are in serious peril of losing margin, and therefore market valuation, to open weights competitors. The important point though is that the frontier labs do not make up the whole market. Tokens need compute, memory and power whether it's a frontier lab or open weights. I see endless analysis of OpenAI vs Anthropic revenue figures. What's far more important to the AI ecosystem is overall revenues. And as the market continues to fragment, it's harder and harder to join that together. Unless AI does hit a wall, open weights may mean the end of the boom in frontier labs valuations. But the underlying supply chains may be doing better than ever. Which is why I think the market has this week backwards. Chip stocks are being punished just as TSMC reports record revenue and says AI demand still exceeds supply . The one caveat is leverage. So much of this buildout is debt-funded that even small changes can unwind far faster, and far more completely, than they should. CoreWeave's credit default swaps hit distressed levels this week on a hot inflation print and a viral chart - not because anyone stopped wanting GPUs. If the AI boom ends, I don't think it ends with fewer tokens. It ends with the same tokens - or far more - flowing to far more people at far lower margins. Nvidia's headline generation-on-generation numbers mostly come from dropping precision (FP8 to FP4), not from the silicon getting more efficient. Halving precision roughly doubles throughput on the same hardware, but you're trading accuracy for speed, and most production inference still runs at FP8 or BF16. Compare like-for-like at FP8 and H100 to Vera Rubin is roughly 2.7x per watt over three generations - about 1.5x a generation. Over the same period power per GPU went from ~700W to ~2,300W, so more than half the per-GPU gain is simply drawing more power through bigger, multi-die packages. Moore's law is slowing, and there's a hard limit to how far you can cut precision. Once both run out, the tok/watt gains have to come from somewhere else. ↩︎ Nvidia's headline generation-on-generation numbers mostly come from dropping precision (FP8 to FP4), not from the silicon getting more efficient. Halving precision roughly doubles throughput on the same hardware, but you're trading accuracy for speed, and most production inference still runs at FP8 or BF16. Compare like-for-like at FP8 and H100 to Vera Rubin is roughly 2.7x per watt over three generations - about 1.5x a generation. Over the same period power per GPU went from ~700W to ~2,300W, so more than half the per-GPU gain is simply drawing more power through bigger, multi-die packages. Moore's law is slowing, and there's a hard limit to how far you can cut precision. Once both run out, the tok/watt gains have to come from somewhere else. ↩︎

0 views
Unsung 2 days ago

“We all hope you have a great week, even if you never buy a Playdate.”

In my inbox, over the years, in no particular order: From: YouTube Premium Subject: YouTube Premium Individual plan price update Email summary: The monthly price is increasing from $13.99 to $15.99. From: 1Password Subject: Important: We’re updating the cost of your subscription Email summary: The annual price is increasing from $35.88 to $47.88. From: GeoGuessr Subject: Upcoming Change to Your GeoGuessr Subscription Email summary: The monthly price is increasing from $4.99 to $6.99. From: DreamHost Subject: Upcoming DreamHost Price Change Email summary: The monthly price is increasing from $13.99 to $16.99. From: Printful Subject: Product and shipping price updates Email summary: Some prices and shipping rates are increasing. The only two emails I could find that were actually honest about the price going up in the subject line, instead of obfuscating it with terms like “change” or “update,” were Apple’s and Panic’s. The former had a subject “Your Subscription Price Increase,” and looked like this: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/we-all-hope-you-have-a-great-week-even-if-you-never-buy-a-playdate/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/we-all-hope-you-have-a-great-week-even-if-you-never-buy-a-playdate/1.1600w.avif" type="image/avif"> The latter was titled “Playdate’s price is about to go up a bit” and looked like this: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/we-all-hope-you-have-a-great-week-even-if-you-never-buy-a-playdate/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/we-all-hope-you-have-a-great-week-even-if-you-never-buy-a-playdate/2.1600w.avif" type="image/avif"> Also note both telling you what the previous price was.

1 views
Unsung 2 days ago

“Hindered by its headline feature”

On his channel about new and old hi-fi equipment, Techmoan profiles a modern Fosi Audio Neo player . Techmoan’s video was originally linked here, but I failed to notice it was an unreleased, patron-only video. If you want to see it, subscribe to Techmoan’s Patreon – it’s worth it! – or wait a few days until the video is released to the public. I will re-link the video then. I’m sorry about that. Fosi Audio Neo apes the iPod. At first glance, it looks exactly the same – a deck-of-cards-sized device with a wheel, and above it a screen showing either the currently playing track, or a hierarchical, textual menu: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/hindered-by-its-headline-feature/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/hindered-by-its-headline-feature/1.1600w.avif" type="image/avif"> = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/hindered-by-its-headline-feature/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/hindered-by-its-headline-feature/2.1600w.avif" type="image/avif"> But the reviewer quickly discovers that the iPod copycat is a disaster in use, its creators accidentally highlighting two important rules: To the first point: iPod actually had five main buttons, not just one. This is most visible in the third generation, which put most of the commands above the wheel: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/hindered-by-its-headline-feature/3.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/hindered-by-its-headline-feature/3.1600w.avif" type="image/avif"> In all the other models, the buttons were integrated around, or even within the wheel: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/hindered-by-its-headline-feature/4.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/hindered-by-its-headline-feature/4.1600w.avif" type="image/avif"> But the modern product only has one button, and that’s too few for all the necessary functionality. Now “going back” means an unnatural long press. The other necessary commands – like pausing, next track, and previous track – are offloaded to an onscreen menu, which means extra modes and focus states that the original iPod didn’t have. By trying to be simple in a naïve way, the creators of the Neo made their device more complicated. As for the details? The new player has no acceleration curve when you scroll fast, which would help you traverse long lists as quickly as short ones. It has no scrollbar to give you a sense of how long the list is. It has no haptic-like beeps to help mesh the fluid rotation with discrete item jumps (your mouse wheel is doing the same thing!). It has no side-to-side transitions to help you orient yourself in the hierarchy. And, the reaction to every click seemed so slow that it made even me, the viewer, anxious. This second aspect is similar to Photoshop vandalizing its dialogs , or CleanShot bulldozing its settings . Here, the new player also underestimates the sophistication and thoughtfulness of the things it aims to copy. The difficult truth is that while software needs to be simple to the user, that simplicity is nothing but complicated to people designing it. (I tried to find a good iPod click wheel explainer, but I couldn’t find any. (There have been a few web approximations over the years, but they also get a lot of nuances wrong.) I wonder if I should create an online iPod simulator, walking designers through all of its important interface details.) “simple” does not mean “fewer things,” simplicity cannot happen without a lot of small details done well.

0 views
Manuel Moreale 2 days ago

35 down, 9 more to go

We’re down to the final four segments, but we only have three walks left to do. The plan for today is to walk segment number 7 and also attach to it the beginning part of number 8. 23km, 870m of ascent, 1250m of descent. Next time, we’ll finish 8th and attach 9th to it, but that’s a problem for future me. I’ll be honest with you, I’m kinda tired of these walks. Especially because this second half stretches across trails I walked countless times before. But I also want to walk the whole loop and visit all these churches, so we won’t stop here. But we’ll move fast this time around. There’s no point in taking a million pictures at this point. The scenery is mostly the same, the overall area is still the same, so we might as well use this as an opportunity to do some cardio training. The humidity is very high early in the morning, but it’s gonna get warm fast. The trail is gonna take us down for a bit, then back up, then all the way down next to the Slovenian border, all the way back up again, and the final stretch is gonna go down again, to the final church of today’s walk and also my car, since it’s parked right next to it. First stop is gonna be the church of San Giovanni Battista (29/44), and on our way there, we see the church of San Paolo Apostolo far in the distance. It would be part of this segment of the loop, but we visited it on my previous walk, as I was walking all the way back to my car. The church of San Giovanni Battista is in an amazing location, and out of the 44, this one’s probably the one I’ve seen the most throughout the years. There’s a lovely short loop that I often walk with the dog, and the view from up here is great. Almost exactly an hour in, and we have reached the first POI I have marked on the map. I’m pleased with the pace so far; this is enjoyable. I’m starting to walk down the trail I mentioned a moment ago when all of a sudden a formidable foe blocks my path: a herd of goats. Well, maybe herd is a bit of an exaggeration since it’s only 6 of them. But these were just out on their own—and were shitting everywhere—and not only did they have no intention to move away from the trail, one of them was not in the mood to let me pass. Love goats, they’re fun. But can also be jerks, and the last thing I need is to find myself fighting a bunch of goats on a rocky trail. Plus, there’s a very convenient alternative trail just around the corner, so better to leave these alone. Down, and down, and down we go, through the woods, without ever encountering a single soul. That’s honestly the best part about walking these trails: it is incredibly rare to see people. It’s just me and nature. And goats, I guess. Through a couple of small villages we go—not a single human being in sight—and around the second church of the day, the church of San Bartolomeo Apostolo (30/44) that sits maybe a few hundred meters from the Slovenian border. We’re just a bit more than 2 hours in, and we have already walked half the distance. But we still have most of the uphill part to walk, so we’ll see if we manage to keep up the pace. Up, and up, and up we go. And up and up the heartbeat also goes. But on our way up with pass next to the third church of the walk, the church of San Tommaso Apostolo (31/44). There’s a house for sale literally right next to the church if you’re interested. Also another one for sale maybe 30 meters before it. If you like quiet places, this is the location for you. In the middle of absolutely nowhere. We’re not even a quarter of the way through this uphill section, so we better keep going. Less than three hours into this walk—and almost 16.5km—we have reached the fourth church of the day, the church of Sant’Antonio da Padova (32/44). This is another one I have visited a bunch of times before, so no point in spending time here considering we still have the last uphill stretch to finish. I knew this was the last challenging part, so it was fun to keep pushing, and I think I peaked at 168bpm. But it’s gonna be almost entirely downhill from now onwards. We take a quick detour to hit the fifth church of the day, the church of San Nicolò (33/44). I wrote about this one in a previous edition of From the Summit . Another one of those churches I visited a lot over the years because it’s another place I walk often with the dog. This would have been the final church of the day, and the normal route would take me west. But we’re going east, and then cut down through the forest to reach what would be the first church of the 8th segment. As predictable, this alternative path takes me through a trail that is overgrown but, oh well, who cares. And just like that we have reached the sixth church of the day, the church of Sant’Abramo Eremita (34/44). Wonderful location, with Mount Matajur always in the background. I have to admit that a few of these churches are placed in lovely locations; this is like the perfect spot to just chill and read a book on a sunny day. I might come up and do that soon; I ordered a bunch of new books just the other day. Final stretch, only a bit more than 1km left to walk and then we’re done for the day. Risked falling on my back on a very slippery and steep part of this final stretch but thankfully I still have good reflexes. A bit more than 4 hours in and we have arrived at our final destination, the church of San Leonardo Abate (35/44). I have to say, going fast made this walk a lot more fun. I might do it again. I’m glad we’re down into single digits; I can smell the end of this loop. And after that, we can focus on walking other places and see things that are not churches! As always, if you want to stalk my walk, here is the data recorded by my watch . See you next time. You love the outdoors and RSS. You're one of the special ones.

0 views
Kev Quirk 2 days ago

2026-10-17 11:37: We had a Hotpoint engineer come out to repair our washing machine yesterday. While replacing...

We had a Hotpoint engineer come out to repair our washing machine yesterday. While replacing the machine, he forgot to connect the waste pipe and we came down to this mess this morning. 😡 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 NIST Elliptic Curves Seeds Bounty Has Been Claimed

We now know how the seeds of the NIST elliptic curves were generated: they’re not the hash of some saucy sentence, but the output of drand48 seeded with the time, which was indeed in 1997–98. John Wood, Henry de Valence, Ava Howell, Zack Voase, Lucy Sweet, Amir Omidi, Paul Crowley, Iain McGinniss, Nicholas Carlini, and Steve Weis from Anthropic solved the riddle and on October 15th, 2026, at 01:07:51 UTC, claimed the full bounty I announced three years ago . They chose to donate the prize to ISRG , the non-profit that operates Let’s Encrypt, tripling its value to $36,864 (36 Ki$). Thank you to Amir Omidi, Chris Palmer, Colm MacCárthaigh, David Adrian, David Anderson, Jeff Hodges, Matt Green, Matthew McPherrin, Paul Kehrer, Ryan Sleevi, and Soatok for contributing to the bounty. This helps fill out a page of cryptographic history, and reinforces our confidence in these critical cryptographic primitives. The NIST elliptic curves (P-192, P-224, P-256, P-384, and P-521) were published by NIST in FIPS 186-2 in 2000. They were generated at random according to ANSI X9.62 by taking an arbitrary seed, hashing it with SHA-1, and using the output to derive some of the parameters. Until this week, we had no idea how those arbitrary seeds were picked. The lore was that Dr. Jerry Solinas, who passed away in early 2023, generated them in 1997 by hashing some English sentences that he later forgot. You can read more in this article by Steve Weis or in the original bounty announcement . Turns out memory can play tricks on everyone: we now know they were instead generated with the POSIX-standard drand48 random number generator. The algorithm is as simple as passing the then-current UNIX timestamp to and then producing one byte at a time with drand48. Each sequence of 20 bytes is tried as a seed following ANSI X9.62 and rejected if the resulting curve is not valid. Some timestamps are used to generate multiple curves, by continuing to try seeds after accepting the first one. I reimplemented the algorithm in Go to verify the claim. Read more in Anthropic’s writeup . There are two additional undocumented criteria beyond the ANSI X9.62 ones, one fairly clear and one that still escapes us. If the bit length of the order n of the resulting curve is more than the bit length of the base field p of the curve, the seed is rejected. (The condition is not the stricter n < p , because prime239v2 has p < n < 2²³⁹.) This leaves us with roughly twice as many valid seeds as were published. We explored a number of explanations for this last bit, and found no good fit. Maybe the same RNG was used to validate seeds, consuming RNG output and skipping some potential candidates, although the “gaps” are not regular. Maybe there was just a bug in one of the algorithms that returned the wrong result half the time; these calculations, which we can now do with off-the-shelf software in minutes, were still very much state-of-the-art in 1997. What does this mean for the security of elliptic curve cryptography based on the NIST curves? Well, even before this discovery there were no serious concerns among practitioners. In Section 3.1 of their 2015 paper “A riddle wrapped in an enigma,” Koblitz and Menezes make a convincing argument that it’s implausible that the NSA could have selected a seed to exploit a weakness that escaped more than 15 (now 25) years of cryptanalysis. However, as reported in a later version of that paper, Daniel Bernstein and Tanja Lange described to Koblitz and Menezes in 2017 a technique that could have exploited 70 bits of freedom in selection of the seed to target a hypothetical class of 2⁶¹ weak prime-order curves. (Bernstein is the author of a competing elliptic curve design, Curve25519.) This contributed to enduring conspiracy theories, which had significant appeal among the non-specialist public (although many have since moved on to other, adjacent, conspiracy theories). All this speculation harmed confidence in robust cryptographic systems and was part of my motivation for the bounty. This week’s findings completely rule out the technique described by Bernstein and Lange. Even if the NSA had been free to pick any timestamp in 1997–98 and any of the first 16 prime-order candidates (which generously accounts for the unexplained rejections), they would have had barely 30 bits of freedom. Not enough to intentionally target a hypothetical small class of weak curves, not enough to embed any kind of NOBUS backdoor. Along with deterministic and hedged ECDSA signing algorithms, formally verified field implementations , and the 2015 complete addition formulas by Renes, Costello, and Batina , this nicely completes the “rehabilitation arc” of NIST elliptic curve cryptography, which I would now personally recommend over Curve25519/Ed25519/X25519. Just in time for them to be retired in favor of post-quantum signatures. P.S. The Anthropic team also figured out how the seeds of the NIST B-curves (the ones over binary fields) were generated, but no one uses those, so who cares. In a FamilyMart in Taiwan I found this delightful dice set. A full roll carries log₂(6²⁰) ≈ 51.7 bits of entropy. Rolling them twice can make a pretty robust cryptographic key! I thought it would be funny to label them as Geomys FIPS 140-3 Entropy Sources (which of course they are not, though we do have one of those) and hand them out as swag. However, I found no way to order them online, so I simply visited over a dozen FamilyMarts and brought home 50 packs. Speaking of swag, I am 100% making stickers with the seeds, and t-shirts for the Anthropic team and the contributors to the bounty. I accept suggestions for other seed-based swag. If you want to catch some, follow me on Bluesky at @filippo.abyssdomain.expert or on Mastodon at @[email protected] .

0 views
Stratechery 3 days ago

2026.42: Home At Last

Welcome back to This Week in Stratechery! As a reminder, each week, every Friday, we’re sending out this overview of content in the Stratechery bundle; highlighted links are free for everyone . Additionally, you have complete control over what we send to you. If you don’t want to receive This Week in Stratechery emails (there is no podcast), please uncheck the box in your delivery settings . On that note, here were a few of our favorites this week. This week’s Stratechery video is on Apple and a Hacker’s Future . What is Apple Doing? On last week’s Dithering, John and I bemoaned Apple’s exit from home appliances in the 2010s; now the company is back and John doesn’t see the point . I think a big problem was Apple’s marketing video; after I explained what Apple was trying to accomplish on Sharp Tech Andrew was almost persuaded to go all in on HomeView. — Ben Thompson SpaceX Continues Eating and Expands Its Appetite.  Elon Musk and SpaceX have continued their spectrum buying spree, and in Tuesday’s update Ben broke down the implications of both the latest deal, as well as recent deals that mobile carriers (and airlines) have done to avoid reliance on SpaceX. This market’s dynamics are fascinating to me, and for SpaceX, what once looked like a play to become the de-facto provider of emergency satellite coverage among mobile providers now looks like a company that’s coming for primary cellular coverage. Come to read about the methods that could make that path viable, and stay to appreciate challenges that make it a quintessential Musk strategy.  — Andrew Sharp Titles, Takes, and the Washington Wizards.  The NBA season begins next Tuesday, and if you want to have a good time preparing this weekend, we’ve got you covered. First, Greatest of All Talk makes the case for eight different potential title winners (although I must warn you that our Knicks repeat case was extremely unconvincing) and runs down our favorite highlights from the preseason. Then, for Friday’s Sharp Text , I played the most dangerous game of all and expressed confidence the Washington Wizards (for the first time in a full decade) while also offering 18 more takes and predictions for the rest of the league. — AS SpaceX Buys More Spectrum, Musk and Market Structure, Distributed Cellular — SpaceX’s mobile strategy is becoming clearly with its latest spectrum purchase, and it might work. Apple HomeView, The New Apple TV, The App Story — The Apple Homeview is official, and the question is how big is the addressable market for expensive devices based on subpar AI. A Conversation With Ari Emanuel About Entertainment and AI — A conversation with Hollywood super-agent Ari Emanuel about his memoir, the impact of AI on Hollywood, and the power of a phone call. A Wizards Public Service Announcement and 18 More NBA Takes — Optimism in D.C. for the first time in a decade, plus predictions, a giant wild card, and Bet Your Mortgage Locks. Meanness and Claude ASML’s New Multibeam Inspection Tool is Familiar IGBTs Took Silicon Power to the Next Level Brussels and Beijing Make a Deal; Weak Holiday Spending Data; Xi’s Reported Rest Breaks; Peak Dove? Tell Me Why They Will, Preseason Highlight Digest, Sizing Up a Loaded Northwest Division Apple Enters the Uncanny Valley, The SpaceX Play for Cellular, Q&A on The Ringer, Smartphones, AI Parenting

0 views

Premium: Venture Capital Is Killing Itself

Soundtrack: Spinnerette — A Prescription For Mankind About fourteen years ago, the government made a mistake that would allow tech companies and venture capitalists to conspire to legally scam millions of retail investors, simultaneously depriving them of good information and spuriously inflating the valuations of every major tech IPO of the last 14 years. On April 5, 2012, President Obama signed the Jumpstart Our Business Startups (JOBS) Act under the auspices of it being “too difficult” for small businesses and startups — though overwhelmingly the latter — to access capital, all while reducing reporting requirements in ways that mostly helped venture capitalists fund and startup founders run businesses in reckless and destructive ways, all sold as a good thing for society.  In simple terms, while the JOBS Act (which was passed with rare bipartisan support) allowed companies to raise more money from more people, it also incentivized companies staying private for longer by eliminating a rule from the 60s that required companies of a certain size — above 500 shareholders and $10 million in assets — to report as if they were public. Per Casual Finance :  As Casual Finance notes, this is the rule that pushed both Facebook and Google to go public — because if you’re going to have to report like a public company, you may as well have access to the public markets: The JOBS act, amongst other changes, made it so that you could have up to 2,000 shareholders (but no more than 499 “ unaccredited ” investors) and, crucially, changed the rules so that employees were no longer counted in the calculation, effectively removing any chance that most startups would ever have to deal with reporting like a public company ever again. The rationale was that having to report like a public company required audited accounts, adding an "unnecessary burden” to fledgling companies, even though “fledgling” here meant “companies worth hundreds of billions of dollars on paper” that absolutely could afford an auditor. Those pushing for the bill also believed that these requirements unfairly punished companies for awarding stock grants, and that public reporting was tantamount to “exposing trade secrets,” as if there was literally no amendment that could’ve been made to anticipate these problems other than “removing reporting anything of any sort.” However minor this change might have seemed at the time, the net result was one of the largest private valuation bubbles in history, because there was (and is) no longer any incentive for a company to go public before it’s “ready,” with “ready” defined as “as much value has been drained from the company as humanely possible.” As Casual Finance noted, when Microsoft went public, it had a market cap of around $500 million, Google $23 billion, and Facebook $100 billion, with their total market capitalization as of writing this sentence sitting at around $10.29 trillion. Anyone investing in any of these IPOs in the first five to ten years of their existence had a chance to multiply their money, because you were able to invest before the companies became massive multiconglomerates with multi-trillion dollar market caps, in turn creating value for millions of households that “took the risk” on investing on an earlier-stage company. These three companies are used as the poster children of why you should invest in a new tech stock — that you’re getting in on the ground floor, with the reward for the risk being that you’d have the chance of a massive multiple. Except that doesn’t really work if the companies wait as long as humanly possible to go public. The reason that Microsoft, Google, Meta, Amazon and all the other famous names in “big IPOs that made early investors a lot of money” was that they had to go public before they’d reached the height of their valuation.  And crucially , their valuations are decided by market forces which, while deranged and emotional, at least are somewhat guided by the underlying financial picture of the company. Today’s startups have their valuations defined entirely based on the whims and fancies of a venture capital sect that makes up a multiple they’re comfortable investing at. That’s how Instinct, a zero-revenue “AI agent” that you text to do stuff, is somehow worth $10 billion — because investors from Sequoia Capital, Benchmark, and Coatue had been willing to give it $1 billion for 10% of the company.  These inflated valuations drain the vast majority of potential opportunity that any investor might have, effectively transferring all the risk for the company’s future onto the public markets while offering very little in return. The days of thousand-percent-or-more returns are long dead, despite every single IPO selling itself on this eventuality , like SpaceX did when it proposed it had a $28.5 trillion total addressable market.  Anthropic’s upcoming IPO has the company demanding a $2 trillion valuation, equivalent to both Meta and SpaceX, based on flimsy promises of $200 billion in annual revenue years in the future and a $30 trillion total addressable market. It is, to quote New Constructs , presenting risks and is positioned to be a far bigger ripoff of the US capital markets, and exists only as a liquidity mechanism so that early investors can multiply their dodgily-valued early investments by selling their shares under the scummiest possible terms. Anthropic and OpenAI’s IPOs pose a genuine threat to any investor that dares entangle themselves with unprofitable, unsustainable AI companies promising the world (or the world’s destruction), all sold under the auspices of potentially buying into the next Facebook, Google or Microsoft. In reality, the kind of growth you’d need from these companies to reach anything close to the returns of those early-stage tech investments would require them to have trillions of dollars a year in revenue and market capitalizations of $20 trillion or more — an impossibility that nobody seems to want to discuss. Yet these rotten incentives have also led to a massive valuation bubble in startup valuations writ large, with the AI bubble being the inevitable result. By allowing private companies to avoid the reporting strictures of the public markets, financial regulations incentivize a kind of venture welfare, keeping companies that cannot borrow money or otherwise sustain themselves through cashflow — you know , bad companies — alive for longer than is natural, never forcing them to become real companies that can survive , with every trip to Sand Hill Road bumping the valuation up further, making any IPO or acquisition much harder to stomach. This wasn’t as much of a problem when venture capital was pumping up software companies and flogging them to the markets or dimwitted private equity firms , but has become a critical situation for the legions of cashflow-negative AI companies with aggressively-inflated valuations.  In a pre-JOBS environment, many of these companies would’ve wilted in sunlight, and, I’d argue, been forced to run businesses that could stand on their own two feet. Instead, as I discussed in last year’s Enshittifinancial Crisis , these companies are more venture-dependent than any other hype cycle in history, and because venture is so excited about the potential , they’re investing at bigger and bigger rounds, creating the largest valuation bubble in the history of technology, including the Dot Com Bubble. Today I am going to aggressively advocate for reforms — if not an outright repeal — of the JOBS act, and call for serious legislative efforts to bring the private markets to heel.   My argument is simple: the current system is built to incentivize rich and powerful people inflating private assets with spurious valuations, harming retail investors, reducing the available capital to good startups, and incentivizing the continued development of bad, unsustainable companies. Venture is no longer a trustworthy vehicle for investment, nor can venture capitalists be trusted to value startups any further. The JOBS act did the literal opposite of what it intended to — fewer tech companies went public, and those that went public did so at oversized valuations pumped up by venture capital, using retail investors as exit liquidity under the flimsy pretense of “getting in on the ground floor.” We are placing outsized trust in a handful of extremely rich and disconnected people and their ability to pick winners, despite the fact that the majority of venture capitalists are fucking terrible at doing so. For over a decade, venture capital has inflated the value of startup after startup, then been surprised again and again as these companies didn’t work out, with the vast majority of “successes” — SpaceX, Snap, Airbnb, and Uber — mostly existing to dump their horrid bags on an unsuspecting public. And by repeating the same cycle — inflating companies based on hype and ever-growing valuations — venture capital is setting itself up for a collapse. Today I’ll explain how it’s happening, and how we might fix what’s left in the end.

0 views
Manuel Moreale 3 days ago

Fitness challenge: what’s next?

Back in early June I blogged about my summer fitness challenge. The two main goals were to lose some weight—from 89.6kg to 85.3kg, the oldest measure I had on record from late 2015—and also to get back into a better shape than I was a decade ago. The weight goal was easily quantifiable; I still have the same exact scale I was using 10 years ago and so it was only a matter of jumping on it every morning and track the progress. As for losing weight, I didn’t really have much of a plan other than not eating like an idiot and moving more. And I guess it worked. I’m now hovering around 82kg, going up or down depending how much I decide to eat—or not to eat—any given day. Last time I was this light I was probably in my late teens. And I think this is the perfect weight for my lifestyle, so I’m planning to stay at this level for the foreseeable future. As for being in better shape, that’s a bit trickier to evaluate. My legs are definitely not as strong as they were back when I was in my mid-20s, but I was also playing A LOT of basketball back then, while now I play exactly zero. I do walk and hike a lot more though, and I overall feel much better. So, success! Both goals achieved. Now what? Now it’s time to start another challenge, and this time it will span 12 months. And that’s because even though I do feel better, I’m nowhere near satisfied with myself and my body. There is so much room for improvement, and I realised that I need to have stupid challenges to keep myself motivated. So this is what’s on the menu for the next 12 months. First, I need better cardio. I have never trained it in my life, and my cardio sucks. The realistic goal I currently have set for myself is to run a 5k in under 25 minutes and with a < 150 HR. There’s also a trail I hiked recently that I’ll go hike again next year, and the goal there is to do the first part in less than an hour. It took me almost two last time. Next, I need to build at least some upper body muscle mass. I hate training upper body, especially because none of the activities I enjoy doing involves upper body strength, but it’s nice to have a balanced body and so I need to take care of that. This is a goal that’s harder to track, but I do have a reference body I’m aiming for, and I am taking progress photos at the beginning of the month, so at the end of the 12 months we can compare and see if I managed to get there. Lastly, I want to improve overall flexibility. I am doing some stretching regularly, but I’ve always had a goal in mind, going back years, and that was to manage to get in full lotus position . So we’re aiming for that in the next 12 months. This is gonna be fun. I don’t plan to constantly write about this because there’s not much to say on a regular basis, but if there’s anything you’re interested in, feel free to email me and ask. Thank you for keeping RSS alive. You're awesome. Connect via email :: Sign my guestbook :: Support for 1$/month

0 views
David Bushell 3 days ago

Cloudflare killed Deno and look I’m on TV!

“Didn’t you already say goodbye to Deno? Get new material!” I know, I know, but not even a week after declaring my friendship over with Deno they actually killed Deno! The runtime is going away, and sorry call me pessimistic, but I highly doubt a community fork of any value will survive for long. We will support the Deno runtime for another year with monthly releases containing bug fixes and security updates. After that year we will end our development of the Deno runtime. Deno is joining Cloudflare - Ryan Dahl There’s even a Fireship video on YouTube! Guess who gets a namecheck? I’m not going to risk embedding Google cookies so here’s a link: “The runtime wars are over… and Node won” (YouTube) . I also found my way into the lead story of JavaScript Weekly . It’s sad but telling that negative opinions and news around Deno has received the most attention. I have nothing new to say (until my Cloudflare exposé) but I do want to look back on my journey with Deno. People who’ve only read my recent posts on Deno assume I was just a hater. Far from the case! I was all-in on Deno and wanted it to succeed. While it’s true that my disdain for what the tech industry has become leaked into my criticism, I’d say it was fair and accurate. The Deno runtime was truly ahead of it’s time. It felt like using Node from the future (now Node today). The runtime was forgotten in favour of whatever tech start-ups do. My doubts grew by mid-2024 but I regained brief optimism with the Deno 2.0 relaunch. I didn’t realise I’d written this many posts: You may have noticed my interest in Bun in my earlier writing. That was before I learned it was not a serious project. We don’t use vibe-coded fash-tech in my house. Deno was my platform for fun side projects (and Advent of Code ). I experimented with many silly ideas. A few turned into something practical that I still use today. The SMTP adventure was a disaster, but technically it worked! My private git LFS server has been rock solid. I actually found a use case for the HTTP proxy (blog post to come). For reasons (sigh), I’m losing interest in publishing open source code and writing tutorials. My self-hosted journey has stalled because I can’t afford anything anymore. Tech sucks now. But I’m finding enjoyment in fighting for an open web (for humans). I’m having fun too blogging more non-technical topics and getting back into design. I am no longer a JavaScript bro and that’s probably a good thing! Thanks for reading! Follow me on Mastodon and Bluesky . Subscribe to my Blog and Notes or Combined feeds. Built with Deno (Mar 2021) Deno Builds on Netlify (Jul 2021) JSR: First Impressions (Feb 2024) JSR: Second Look (Mar 2024) The Deno Package Paradox (Aug 2024) JSR and Deno: Final Review (Aug 2024) Hey! Deno 2 looks fun! (Oct 2024) Deno’s Decline (6 Regions and Falling) (Apr 2025) JSR & Deno One Year Later - Malware?! (Jun 2025) Ditching Deno KV (Jun 2025) 404 Deno CEO not found (Mar 2026) Friendship ended with Deno, now Node is my best friend (Oct 2026) Deno Stream Deck (Oct 2022) The one where I used Deno’s foreign function interface to manage a USB peripheral. SvelteKit and Deno with OAuth and Deploy (Jun 2023) The one where I built and maintained a Deno Deploy SvelteKit adapter. Get in Line, Deno! (Oct 2023) The one where I used Deno’s streaming APIs to efficiently seek lines. Git Granary (Jul 2024) The one where I built a git large file storage server that I still use today. HTTP Tunnel and Proxy in JavaScript (Oct 2024) The one where I piped two streams together to create a simple HTTP proxy. I Let The Emails In (Sept 2025) The one where I wrote a bare bones SMTP server with Deno.

0 views