<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dcterms="http://purl.org/dc/terms/"><channel><title>Pau Friedman · pau.fm</title><description>Essays, notes, and useful links by Pau Friedman.</description><link>https://pau.fm</link><language>en-US</language><atom:link href="https://pau.fm/rss.xml" rel="self" type="application/rss+xml"/><item><title>I wonder how the Kafka microservices for that low-volume CRUD app are going.</title><link>https://pau.fm/blog/2026/09/15/kafka-microservices</link><guid isPermaLink="true">https://pau.fm/blog/2026/09/15/kafka-microservices</guid><description>I wonder how the Kafka microservices for that low-volume CRUD app are going.</description><pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I wonder how the Kafka microservices for that low-volume CRUD app are going.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Inspired by Claude Fable 5.1 solving the 370-year-old Cyphral Distich, I asked…</title><link>https://pau.fm/blog/2026/09/14/a-message-from-my-good-friend-ted-cruz</link><guid isPermaLink="true">https://pau.fm/blog/2026/09/14/a-message-from-my-good-friend-ted-cruz</guid><description>Inspired by Claude Fable 5.1 solving the 370-year-old Cyphral Distich, I asked it to decrypt a message from my good friend Ted Cruz.</description><pubDate>Mon, 14 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Inspired by
&lt;a href=&quot;https://www.vals.ai/blogs/fable-solves-cyphral-distich&quot;&gt;Claude Fable 5.1 solving the 370-year-old Cyphral Distich&lt;/a&gt;,
I asked it to decrypt a message from my good friend Ted Cruz.&lt;/p&gt;
&lt;div class=&quot;short-media&quot; data-count=&quot;2&quot;&gt;&lt;a class=&quot;short-media__item&quot; data-pswp-height=&quot;1242&quot; data-pswp-width=&quot;1104&quot; href=&quot;https://pau.fm/images/blog/ted-cruz-cipher.webp&quot;&gt;&lt;img src=&quot;https://pau.fm/images/blog/ted-cruz-cipher.webp&quot; alt=&quot;The Zodiac Killer’s 340-character cipher: a dense grid of hand-drawn letters, circles, triangles, and crosshair symbols&quot; decoding=&quot;async&quot; height=&quot;1242&quot; loading=&quot;lazy&quot; width=&quot;1104&quot;&gt;&lt;/a&gt;&lt;a class=&quot;short-media__item&quot; data-pswp-height=&quot;1242&quot; data-pswp-width=&quot;1104&quot; href=&quot;https://pau.fm/images/blog/ted-cruz-cipher-claude.webp&quot;&gt;&lt;img src=&quot;https://pau.fm/images/blog/ted-cruz-cipher-claude.webp&quot; alt=&quot;Claude Code running Fable 5.1. The prompt reads “solve this message that ted cruz sent me” with an attached image. The reply is “API Error: 400 Output blocked by content filtering policy”. Baked for 39s.&quot; decoding=&quot;async&quot; height=&quot;1242&quot; loading=&quot;lazy&quot; width=&quot;1104&quot;&gt;&lt;/a&gt;&lt;/div&gt;

</content:encoded><category>short</category></item><item><title>Commodities want to be cheap</title><link>https://pau.fm/blog/2026/09/14/commodities-want-to-be-cheap</link><guid isPermaLink="true">https://pau.fm/blog/2026/09/14/commodities-want-to-be-cheap</guid><description>Frontier models are expensive to create and cheap to reproduce, so tokens are becoming a commodity. Commodities want to be cheap, and the labs know it.</description><pubDate>Mon, 14 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I came up with a phrase recently, while thinking about the price of AI tokens: &lt;strong&gt;commodities want to
be cheap&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I mean it in the neoliberal sense. Once something becomes standardized, substitutable, scalable, and
widely produced, competition starts attacking the margin. Producers can differentiate, constrain
supply, bundle, brand, regulate, or monopolize, but the underlying pressure remains. A commodity
wants to collapse toward the lowest sustainable price.&lt;/p&gt;
&lt;p&gt;The phrase obviously inherits its structure from Stewart Brand’s “information wants to be free.” I
had always understood Brand’s line mostly as a claim about censorship: information is easy to copy
and distribute, therefore attempts to contain it eventually fail. But the original argument was more
economic. Information wants to be expensive because it is valuable, and free because the cost of
reproducing and distributing it keeps falling.&lt;/p&gt;
&lt;p&gt;Tokens are in exactly that position. They are becoming a commodity. The expensive part is creating
the frontier model; once a capability exists, inference gets cheaper, hardware improves, models get
smaller, distillation transfers capability downward, and competitors attack whatever margin remains.
Chinese labs add another source of pressure: whatever American frontier labs spend discovering,
firms with lower costs and fewer reasons to protect incumbent margins have every incentive to
reproduce and commoditize.&lt;/p&gt;
&lt;p&gt;This is why the current argument over slowing AI development is economically interesting. Dario
Amodei’s recent call to
&lt;a href=&quot;https://darioamodei.com/post/we-must-pace-the-frontier&quot;&gt;“pace the frontier”&lt;/a&gt; explicitly asks
governments to require common standards and enable coordination among frontier labs; a less
charitable reading is that the incumbents are asking the state to protect them from the economics of
their own product. Sam Altman and Elon Musk have publicly supported the proposal, which makes sense:
all three are vulnerable to the same commoditization pressure.&lt;/p&gt;
&lt;p&gt;The labs spend enormous amounts of energy resisting this process. They differentiate models, create
switching costs, build ecosystems, control distribution, restrict access to weights, and try to
preserve technological leads. They do this for the same reason every producer resists
commoditization: tokens are a commodity, and commodities want to be cheap.&lt;/p&gt;
</content:encoded><category>essay</category></item><item><title>Constraint over convention</title><link>https://pau.fm/blog/2026/09/10/engineering-discipline-in-the-slop-era</link><guid isPermaLink="true">https://pau.fm/blog/2026/09/10/engineering-discipline-in-the-slop-era</guid><description>Coding agents produce more code than your team can safely absorb. The answer is not more careful engineers: it is engineering discipline made executable, for humans and machines.</description><pubDate>Thu, 10 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;aside&gt;&lt;p&gt;&lt;strong&gt;Ed. note:&lt;/strong&gt; This post was &lt;a href=&quot;https://sonora.cx/blog/engineering-discipline-in-the-slop-era&quot;&gt;originally published on Sonora&lt;/a&gt;.&lt;/p&gt;&lt;/aside&gt;&lt;p&gt;Software has entered the Slop Era.&lt;/p&gt;
&lt;p&gt;The cost of producing plausible code has collapsed, but the cost of knowing whether that code
belongs in your system has not. Every engineering team using coding agents now trivially generates
more code than it can responsibly absorb.&lt;/p&gt;
&lt;p&gt;Slop is code that is locally reasonable but globally careless: the fifth copy of a helper function,
a try/catch block that hides an error from the error reporter, a session-scoped lock behind a
transaction pool, a migration that runs cleanly yet undermines the application’s security model.
Slop survives casual review because every line looks plausible, but introduces risk because it lacks
knowledge of the system around it.&lt;/p&gt;
&lt;p&gt;These problems existed before the Cambrian explosion of code generation. The naive response then, as
now, was to demand more careful review. That does not scale. &lt;strong&gt;The answer to the Slop Era is not
more careful engineers, but engineering discipline made executable.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By discipline, I don’t mean heroics, process theater, or a longer approval chain. I mean taking the
judgment a strong engineer carries in their head and putting it into the environment, dependency
graph, lint rules, types, tests, comments, and deployment path. The system should supply missing
context, reject known mistakes, contain the blast radius, and preserve the reason behind old
decisions.&lt;/p&gt;
&lt;p&gt;The answer to the slop problem ends up looking a lot like what the best engineering teams have been
doing for the past decade: turning convention into constraints. This is not a special set of
guardrails for agents - what’s good for humans is good for machines. Both make locally plausible
mistakes when they lack context; the difference in the Slop Era is that agents hit these problems
often enough to make the return on fixing them impossible to ignore.&lt;/p&gt;
&lt;p&gt;Sonora tests whether that discipline can keep up with output. Over the last sixty days, I merged 257
pull requests into &lt;code&gt;main&lt;/code&gt;, over six per day on working days. Across the team, 761 PRs landed, an
average of sixteen per shipping day, with a peak of 34. We are a team of five engineers. I remember
entire months at a prior startup, with a much larger team, that did not ship close to what we now do
in a day.&lt;/p&gt;
&lt;p&gt;Six PRs in a day would be meaningless if they were six typo fixes. Sonora’s codebase is barely a
year old and already runs close to 1 million lines of TypeScript across thirty packages, and a
single PR routinely spans a migration, worker jobs, UI, tests, and docs. That is the real stress
test: can the system absorb a change that wide without requiring me to inspect every boundary by
hand? I’m not typing six times faster. The repository is doing more of the remembering, checking,
and rejecting before the change reaches me.&lt;/p&gt;
&lt;p&gt;The governing idea is &lt;strong&gt;make it cheap to be wrong&lt;/strong&gt;. AI did not invent this discipline, but it
changed the discount rate: work that used to pay back once a sprint now pays back dozens of times a
day.&lt;/p&gt;
&lt;h2 id=&quot;whats-good-for-humans-is-good-for-machines&quot;&gt;What’s good for humans is good for machines&lt;/h2&gt;
&lt;p&gt;Fast feedback. One command that does the thing. Errors that explain what to do next. Comments that
record why an obvious alternative failed. These were good engineering practices before coding
agents, but agents make their value visible because they exercise the system far more often.&lt;/p&gt;
&lt;p&gt;Start with the development environment. An agent will confidently reason from whatever world you
give it. If that world has the wrong port, a drifting Node version, or somebody else’s database, a
green test can certify fiction.&lt;/p&gt;
&lt;p&gt;Our environment is a &lt;a href=&quot;https://nixos.org&quot;&gt;Nix&lt;/a&gt; flake. Node, Postgres, Redis,
&lt;a href=&quot;https://www.pulumi.com&quot;&gt;Pulumi&lt;/a&gt;, gcloud, kubectl, &lt;a href=&quot;https://www.shellcheck.net&quot;&gt;ShellCheck&lt;/a&gt;, and the
rest of the toolchain are pinned. Entering the repo starts its services. Ports are allocated per
checkout and exported as environment variables, so multiple copies of Sonora can run side by side
without sharing a database or guessing who owns port 5432.&lt;/p&gt;
&lt;p&gt;This is what loading the repo looks like:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;https://pau.fm/_astro/ec.snl5l.css&quot;&gt;&lt;script type=&quot;module&quot; src=&quot;https://pau.fm/_astro/ec.g1fg5.js&quot;&gt;&lt;/script&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e6edf3;--1:#1f2328&quot;&gt;╭──────────────────────────────────────────────────────────────╮&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e6edf3;--1:#1f2328&quot;&gt;│ 🦊  sonora dev                                               │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e6edf3;--1:#1f2328&quot;&gt;│                                                              │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e6edf3;--1:#1f2328&quot;&gt;│   ▴ Postgres   127.0.0.1:5432                                │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e6edf3;--1:#1f2328&quot;&gt;│   ▴ Redis      127.0.0.1:6379                                │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e6edf3;--1:#1f2328&quot;&gt;│   ▴ Mailpit    127.0.0.1:1025  →  http://127.0.0.1:8025      │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e6edf3;--1:#1f2328&quot;&gt;│   ▴ App        http://app.sonora.localhost:3000              │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e6edf3;--1:#1f2328&quot;&gt;│   ▴ Worktrees  grove · grove --once snapshot                 │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e6edf3;--1:#1f2328&quot;&gt;│   ▴ Turbo      shared · read-only                            │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e6edf3;--1:#1f2328&quot;&gt;│                                                              │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e6edf3;--1:#1f2328&quot;&gt;│ ✓ ready to build  ·  run pnpm dev                            │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e6edf3;--1:#1f2328&quot;&gt;╰──────────────────────────────────────────────────────────────╯&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The banner is for humans, and we suppress it in non-interactive shells, but the port assignments are
still exported as &lt;code&gt;$PGPORT&lt;/code&gt;, &lt;code&gt;$REDISPORT&lt;/code&gt;, and &lt;code&gt;$PORT&lt;/code&gt;. Our &lt;a href=&quot;https://agents.md&quot;&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/a&gt; tells
coding agents to use those variables instead of guessing the defaults. Before every shell command, a
hook puts the agent inside &lt;code&gt;nix develop&lt;/code&gt;, so when it runs &lt;code&gt;pnpm test&lt;/code&gt;, it gets the same pinned Node
and dependencies I do, along with that worktree’s own Postgres.&lt;/p&gt;
&lt;p&gt;Humans are pretty good at noticing when an environment is wrong. We see an unexpected port or
version, swear a little, and adjust. But agents are more likely to accept what they see as fact and
build the next ten steps on top of it. A passing test in the wrong environment is worse than a
failing one because it sends the rest of the work in the wrong direction.&lt;/p&gt;
&lt;p&gt;This is also why I have become more opinionated about monorepos. An agent can work only with what
exists in its checkout. Put the worker in one repository and the app in another, and any change that
spans both becomes a coordination problem. Humans compensate with memory, Slack, and meetings, while
agents guess. Neither is a good use of time.&lt;/p&gt;
&lt;p&gt;Sonora keeps the application, worker, database package, infrastructure, documentation, supporting
tools, and marketing site in one repository. Even this post is a Markdown file in the same repo. The
app, worker, database package, and Pulumi infrastructure are all TypeScript, so changes across those
boundaries stay in one type system. One recent change added cost visibility to workflows. It touched
27 files across a database migration, worker code, pricing logic and tests, the workflow builder,
the credits settings page, and two architecture docs. It was one product change, so it was one PR. I
did not need to coordinate three repositories or remember which part had shipped.&lt;/p&gt;
&lt;p&gt;Keeping everything together does not mean every change runs every test or deploys every application.
&lt;a href=&quot;https://turborepo.com&quot;&gt;Turborepo&lt;/a&gt; already knows the dependency graph. CI uses it to determine which
packages need checking, and the deployment pipeline uses it to determine whether production code
changed. Editing this post republishes the marketing site and stops there. Without that filtering,
changing this sentence would run the entire application suite. We lean on the dependency graph to
keep changes isolated and checks targeted.&lt;/p&gt;
&lt;h2 id=&quot;conventions-are-stronger-as-constraints&quot;&gt;Conventions are stronger as constraints&lt;/h2&gt;
&lt;p&gt;Conventions aren’t actionable in their natural state. They’re just a shared understanding; a piece
of advice. Teams have spent a decade trying to make a codebase read as though one person wrote it.
That consistency now has a functional purpose: agents learn from the nearest example. Engineering
discipline becomes executable when violating the convention produces immediate, specific feedback.
The job is to move judgment out of reviewers’ heads and into mechanisms that can reject a change. We
use this ladder:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://pau.fm/images/blog/engineering-discipline-inline.webp&quot; alt=&quot;Five paper markers on a folded landscape, each carved with a shape and labelled prompt, skill, hook, lint rule, and type, with a fox on the path running left to right&quot;&gt;&lt;/p&gt;
&lt;p&gt;A prompt is advice for one task. A skill is reusable advice. A hook runs without being asked. A lint
rule rejects a bad pattern. A type makes the invalid state unrepresentable. When the same correction
&lt;a href=&quot;https://blog.codinghorror.com/rule-of-three/&quot;&gt;appears three times in review&lt;/a&gt;, I try to move it one
rung to the right.&lt;/p&gt;
&lt;p&gt;Every coding agent starts by reading &lt;code&gt;AGENTS.md&lt;/code&gt;. It is the standing prompt for the repository, a
way to give every agent the same starting context, but still only the first rung on that ladder.
Ours is 356 lines, most of them recording decisions we do not want to relitigate: &lt;code&gt;/api/*&lt;/code&gt; is
reserved for a future public API; every form prevents duplicate submissions; use this primitive
rather than inventing another one.&lt;/p&gt;
&lt;p&gt;As a prompt, &lt;code&gt;AGENTS.md&lt;/code&gt; can explain what to do and why. But it can’t stop anyone from doing the
opposite. For decisions we care enough about, the build says no. We have 22 custom
&lt;a href=&quot;https://oxc.rs/docs/guide/usage/linter.html&quot;&gt;oxlint&lt;/a&gt; rules in a package called &lt;code&gt;vibes&lt;/code&gt;, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;no-catch-500&lt;/code&gt; stops a handler from swallowing an error and hiding it from Sentry.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;require-job-group-in-loop&lt;/code&gt; catches queue fan-outs that could let one tenant monopolize the
workers.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;no-session-advisory-lock&lt;/code&gt; rejects session-scoped Postgres locks because we run
&lt;a href=&quot;https://www.pgbouncer.org&quot;&gt;PgBouncer&lt;/a&gt; in transaction mode.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;no-as-unknown-as&lt;/code&gt; rejects the &lt;code&gt;as unknown as T&lt;/code&gt; double assertion, which disables type checking
without narrowing anything.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;any&lt;/code&gt; is also an error outside tests. Both are ways to opt out of the type checking we chose
TypeScript for. The linter does not care whether the code came from me, a teammate, or an agent. It
fails in the same place and explains both the danger and what to do instead. Once we have paid to
learn a rule, enforcing it should not depend on the next reviewer remembering it.&lt;/p&gt;
&lt;p&gt;Exceptions are explicit. A one-line suppression names the rule and gives the reason:
&lt;code&gt;// oxlint-disable-next-line jsx-a11y/no-autofocus -- intentional focus on dialog open&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The most common signature of machine-generated slop is entropy. The fifth copy of a helper function
can be correct and still make the system worse because it introduces more maintenance cost, CI
execution time and surface area for drift. Yet no human reviewer remembers every similar helper
either. Our &lt;code&gt;vibedupes&lt;/code&gt; utility, built on &lt;a href=&quot;https://github.com/mizchi/similarity&quot;&gt;similarity-ts&lt;/a&gt;,
compares function syntax trees to detect functionally duplicate code. It checks changed functions on
each PR and runs a full-repository scan weekly. We tuned it until a match meant “fork” rather than
“similar shape,” because an ignored check is worse than no check at all.&lt;/p&gt;
&lt;p&gt;That tuning threshold is still a judgment call, and the next person needs to know why we drew the
line at 90% similarity. Which brings me to comments.&lt;/p&gt;
&lt;p&gt;I owe comments a mea culpa. For most of my career, I believed good code should explain itself and
that a long comment was evidence of a bad abstraction. I still believe that when the comment merely
narrates what the code does. But no function name can tell you why four test shards are faster than
eight in this repository, why a threshold is &lt;code&gt;0.90&lt;/code&gt; instead of &lt;code&gt;0.85&lt;/code&gt;, or which production incident
made a particular constraint necessary. Some of the comments I value most today are longer than
younger me would have tolerated because they preserve history, not mechanics.&lt;/p&gt;
&lt;p&gt;There is no clever solution to comment rot. We make comments local, concrete, and falsifiable. A
useful comment sits beside the decision and names the benchmark, incident, or rejected alternative
behind it. Whenever the constraint can be expressed as a test, lint rule, or type, that mechanism
does the enforcing; the comment explains why it exists. “Be careful here” will rot. “Four shards,
not eight, because the critical path moves below 56 seconds” gives the next engineer something they
can verify.&lt;/p&gt;
&lt;p&gt;The threshold in &lt;code&gt;vibedupes&lt;/code&gt; has exactly that kind of comment:&lt;/p&gt;
&lt;!-- prettier-ignore --&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;pre data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#8B949E;--1:#616972&quot;&gt;// Tuned against this repo: at 0.85/5 lines the report fills with `toNumber` and&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#8B949E;--1:#616972&quot;&gt;// one-line chart validators. Raising both leaves the forked-function findings.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#8B949E;--1:#616972&quot;&gt;// 0.90 is where the pairs still read as copies rather than as functions that&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#8B949E;--1:#616972&quot;&gt;// merely share a shape — every fork family we set out to catch scores above it&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#8B949E;--1:#616972&quot;&gt;// (the three rate limiters are 99.33%, the four Snowflake JWT builders 99.59%).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#FF7B72;--1:#CA212D&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--0:#E6EDF3;--1:#1F2328&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#79C0FF;--1:#0550AE&quot;&gt;DEFAULT_THRESHOLD&lt;/span&gt;&lt;span style=&quot;--0:#E6EDF3;--1:#1F2328&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FF7B72;--1:#CA212D&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#E6EDF3;--1:#1F2328&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#A5D6FF;--1:#0A3069&quot;&gt;&quot;0.90&quot;&lt;/span&gt;&lt;span style=&quot;--0:#E6EDF3;--1:#1F2328&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#FF7B72;--1:#CA212D&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--0:#E6EDF3;--1:#1F2328&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#79C0FF;--1:#0550AE&quot;&gt;DEFAULT_MIN_LINES&lt;/span&gt;&lt;span style=&quot;--0:#E6EDF3;--1:#1F2328&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FF7B72;--1:#CA212D&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#E6EDF3;--1:#1F2328&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#A5D6FF;--1:#0A3069&quot;&gt;&quot;15&quot;&lt;/span&gt;&lt;span style=&quot;--0:#E6EDF3;--1:#1F2328&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Without that history, lowering the threshold looks prudent. A new engineer and an agent share the
same failure mode here: locally sensible reasoning without the history. The comment puts the history
at the one place both are guaranteed to see it.&lt;/p&gt;
&lt;p&gt;Documentation works the same way. It lives beside the code, and source comments link to it by path.
The job-group rule points to the concurrency architecture doc. A person or agent can follow that
link while working instead of guessing what somebody once wrote in a wiki. Context that cannot be
reached from the checkout is not dependable context.&lt;/p&gt;
&lt;h2 id=&quot;fast-feedback-is-a-safety-feature&quot;&gt;Fast feedback is a safety feature&lt;/h2&gt;
&lt;p&gt;Executable discipline has to be fast. When feedback is slow, people batch changes and work around
checks; agents burn cycles or form wrong conclusions. A high-output repository must say no quickly,
specifically, and as close as possible to the mistake. We make checks fast not by dropping them, but
by testing the narrowest set of things that a change could break, and by not recomputing answers we
already trust.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pnpm check&lt;/code&gt; is one command. CI uses Turborepo’s &lt;code&gt;--filter=&apos;...[origin/main]&apos;&lt;/code&gt; to test only affected
packages rather than the entire monorepo. A marketing-site change does not wait for more than a
thousand application test files. Locally, &lt;code&gt;pnpm check:min&lt;/code&gt; applies the same idea to the current
diff. It asks Turborepo which packages the change can affect, then lets Vitest follow the module
graph to the relevant tests. Changing a single utility might run only one test file, taking just a
second or two, while changing a root configuration file will run the whole suite. Skipping
unnecessary work is the programmer’s kind of laziness.&lt;/p&gt;
&lt;p&gt;When the application suite does need to run, its thousand-plus test files are sharded and run in
parallel across multiple jobs, each with its own Postgres instance. This gives us parallelism
without shared-database contention or cross-test interference. Nine out of ten PRs are green or red
in under six minutes; the median CI run takes about three and a half minutes.&lt;/p&gt;
&lt;p&gt;The other large win is refusing to repeat work. CI publishes successful task results to a shared
Turborepo cache that developers and agents can read but not write. A passing check from my Mac
should not be allowed to convince Linux CI that it can skip the same check. After every merge,
another workflow warms the cache for the exact tree on &lt;code&gt;main&lt;/code&gt;, so pulling an unchanged main branch
and running &lt;code&gt;pnpm check&lt;/code&gt; takes about a second.&lt;/p&gt;
&lt;p&gt;Fast feedback keeps changes small. Fast checks catch the failures we know how to test. For
everything else, we bias toward changes we can reverse. Feature flags make large changes reversible
in production. Every feature flag records the date it entered the registry; after thirty days, an
experiment is marked stale unless it is explicitly permanent, a category reserved for entitlements
and policy controls. The default assumption is ship it, judge it, then delete it or make it the
default.&lt;/p&gt;
&lt;p&gt;We apply the same idea to schema changes: add a nullable column, backfill it, then enforce
&lt;code&gt;NOT NULL&lt;/code&gt;. We use two or three PRs even when the whole change would compile as one. Each step is
easier to test, review, pause, and reverse.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The decomposition that makes a change safe is the same decomposition that makes it
parallelizable.&lt;/strong&gt; A change small enough to reason about is small enough to hand to an agent, review
in minutes, and revert without ceremony. The careful version is the one that moves faster.&lt;/p&gt;
&lt;h2 id=&quot;every-pull-request-gets-an-automated-review&quot;&gt;Every pull request gets an automated review&lt;/h2&gt;
&lt;p&gt;Static checks work best when we already know how to name the failure. There is still a middle ground
between “the compiler rejects it” and “a human happens to notice”: a change can compile, pass every
test, and still leave a stale assumption somewhere else in the repository. That is where automated
code review earns its keep.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.greptile.com/&quot;&gt;Greptile&lt;/a&gt; reviews every Sonora pull request against the rest of the
repository. It reads &lt;code&gt;AGENTS.md&lt;/code&gt;, architecture docs, and rules retained from previous reviews
instead of treating the diff as its whole world. When a new picker component called the React Router
&lt;code&gt;fetcher.submit&lt;/code&gt; from native buttons, it checked the implementation against the form-submission
rules in &lt;code&gt;AGENTS.md&lt;/code&gt; and caught that duplicate submissions were not prevented. The next commit moved
those rows to our shared &lt;code&gt;SubmitButton&lt;/code&gt; with an explicit pending state. In another PR, it connected
an additional database checkout to a previous, documented pool-exhaustion incident and told us to
share an existing transaction. Both are mistakes a line-by-line reading of the diff could easily
miss.&lt;/p&gt;
&lt;p&gt;It also gets things wrong. It once complained that 200ms and 300ms animation durations bypassed our
motion vocabulary when those were exactly the values the vocabulary prescribed. We replied, and it
withdrew the comment. Automated review is a second reader, not an oracle. A finding has to describe
a real failure mode well enough for us to verify it.&lt;/p&gt;
&lt;p&gt;Review quality falls when a PR bundles unrelated work. Keeping each change cohesive gives Greptile,
and the human after it, less irrelevant context to sort through.&lt;/p&gt;
&lt;p&gt;A good automated-review finding should eventually make itself obsolete. If it catches the same class
of mistake more than once, that is evidence to move the rule to the right on the ladder: from
repository guidance to a hook, lint rule, or type. Automated review is useful in the gap, while the
rule still depends on context we have not yet learned how to encode.&lt;/p&gt;
&lt;h2 id=&quot;make-the-repository-remember&quot;&gt;Make the repository remember&lt;/h2&gt;
&lt;p&gt;Engineering discipline compounds when each failure changes the path of the next change. On August 3,
roughly 9,500 ungrouped sibling jobs contended on one database row. They exhausted the statement
timeout, and their retained error text filled &lt;a href=&quot;https://valkey.io&quot;&gt;Valkey&lt;/a&gt; until workers could no
longer boot.&lt;/p&gt;
&lt;p&gt;The postmortem changed the system in several places. The fan-out path got a grouping primitive. The
concurrency behavior got an architecture doc. &lt;code&gt;require-job-group-in-loop&lt;/code&gt; now rejects the pattern
that caused the incident, and its header comment records the date and consequence. The next engineer
sees that history while writing the loop, not after opening another postmortem.&lt;/p&gt;
&lt;p&gt;That is discipline made executable: the incident changed the queue primitive, the documentation, and
the set of programs the linter will accept. We paid for the lesson once. Not every failure deserves
a lint rule; the durable response may be a type, a test, a different queue topology, or a smaller
deployment. “Be more careful next time” is not durable.&lt;/p&gt;
&lt;p&gt;That is how my job has changed. The repository settles formatting, imports, and approved primitives
before a PR reaches me, leaving review for the spec and intent. The more important question is why
the repository needed me to catch something.&lt;/p&gt;
&lt;p&gt;Six merged PRs a day is not the target. It is a side effect of making confidence cheaper. The metric
I care about is the time between “I know what I want” and “it is in production, and I am not
nervous.”&lt;/p&gt;
&lt;p&gt;The Slop Era will reward the team with the best engineering discipline, not the best prompt. What’s
good for humans is good for machines: trustworthy evidence, explicit decisions, fast feedback,
isolated work, and a codebase that remembers why. Machines do not need a separate discipline. They
need ours, made executable. Build the discipline into the system.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Gabriel Al-Harbi and Max Schwenk for providing feedback on drafts of this essay.&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>essay</category></item><item><title>Paying for Spotify subsidizes Europe for being awful at technology.</title><link>https://pau.fm/blog/2026/09/09/subsidizing-europe</link><guid isPermaLink="true">https://pau.fm/blog/2026/09/09/subsidizing-europe</guid><description>Paying for Spotify subsidizes Europe for being awful at technology.</description><pubDate>Wed, 09 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Paying for Spotify subsidizes Europe for being awful at technology.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Correctness is not intelligence</title><link>https://pau.fm/blog/2026/09/08/correctness-is-not-intelligence</link><guid isPermaLink="true">https://pau.fm/blog/2026/09/08/correctness-is-not-intelligence</guid><description>AI excels where answers can be verified, but real intellectual progress depends on abstractions that make the world easier to understand.</description><pubDate>Tue, 08 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://openai.com/index/navier-stokes-solution/&quot;&gt;OpenAI’s Millennium Problem result&lt;/a&gt; demonstrates
that AI is advancing fastest in domains with strong validation. In math, a proposed result can be
checked, and formal proofs make that validation nearly perfect. The model can search an enormous
space of possible constructions, discard failures, and eventually produce something provably
correct. The same pattern explains progress in coding (the Bun Rust rewrite), games (unambiguous win
or loss), and other domains where there is a cheap, reliable signal for success.&lt;/p&gt;
&lt;p&gt;But validation is not the same thing as understanding. The actual result of Navier–Stokes is
effectively inconsequential.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-result&quot; id=&quot;user-content-fnref-result&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; We care because trying to answer the question might produce a
theory of why solutions behave as they do. Mathematics, like computing, advances by building
abstractions that compress many particular observations into a smaller number of concepts: the right
definition, invariant, equivalence, or structure suddenly makes a whole family of results
intelligible.&lt;/p&gt;
&lt;p&gt;This is not what happened here. OpenAI spent an enormous amount on compute, reportedly millions,
pursuing a perfectly verifiable objective, and its model searched its way to a gigantic, bespoke
proof without discovering much reusable conceptual structure at all. In fact, earlier work reduced
the search space enough to make the entire project tractable.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-credit&quot; id=&quot;user-content-fnref-credit&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; The result is still
knowledge—we know something we did not know before—but it may be a strange kind of knowledge:
expensive to produce, difficult to understand, and not obviously useful for making future problems
substantially easier.&lt;/p&gt;
&lt;p&gt;AI seems superhuman in domains with verifiers. It’s far from clear whether it can build useful
abstractions where no such verifier exists. Human intellectual progress is not usually a sequence of
isolated correct answers. We invent models that make the world simpler to reason about. If AI can
reliably discover concepts and theories that reorganize entire fields, it will represent a much
deeper form of intelligence than producing arbitrarily difficult, formally validated results.&lt;/p&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-result&quot;&gt;
&lt;p&gt;We do not really care whether the answer was “true” or, as it turned out, “false.” &lt;a href=&quot;#user-content-fnref-result&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-credit&quot;&gt;
&lt;p&gt;That earlier work came from several human mathematicians whom OpenAI decided not to credit. &lt;a href=&quot;#user-content-fnref-credit&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content:encoded><category>essay</category></item><item><title>I don’t have code access yet.</title><link>https://pau.fm/blog/2026/09/03/ruby-1-9-3</link><guid isPermaLink="true">https://pau.fm/blog/2026/09/03/ruby-1-9-3</guid><description>I don’t have code access yet. But I have reason to believe they’re on Ruby 1.9.3 and Rails 2.3.</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I don’t have code access yet. But I have reason to believe they’re on Ruby 1.9.3 and Rails 2.3.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>I asked Claude to do something and it produced a twelve-week plan.</title><link>https://pau.fm/blog/2026/08/28/claude-estimates</link><guid isPermaLink="true">https://pau.fm/blog/2026/08/28/claude-estimates</guid><description>I asked Claude to do something and it produced a twelve-week plan. I asked again later. Two and a half to three and a half hours.</description><pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I asked Claude to do something and it produced a twelve-week plan. I asked again later. Two and a
half to three and a half hours.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Our new quality person believes quality is everyone’s responsibility.</title><link>https://pau.fm/blog/2026/08/21/quality-is-everyones-responsibility</link><guid isPermaLink="true">https://pau.fm/blog/2026/08/21/quality-is-everyones-responsibility</guid><description>Our new quality person believes quality is everyone’s responsibility. I, too, believe that my job is everyone else’s responsibility.</description><pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Our new quality person believes quality is everyone’s responsibility. I, too, believe that my job is
everyone else’s responsibility.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Engineers at Percy got a rubber stamp for their one-year anniversary gift.</title><link>https://pau.fm/blog/2026/08/15/engineer-anniversary-gift</link><guid isPermaLink="true">https://pau.fm/blog/2026/08/15/engineer-anniversary-gift</guid><description>Engineers at Percy got a rubber stamp for their one-year anniversary gift. Perfect.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Engineers at Percy got a rubber stamp for their one-year anniversary gift. Perfect.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>If you ever used DSA interviews, your fraud is now exposed</title><link>https://pau.fm/blog/2026/08/14/if-you-ever-used-dsa-interviews-your-fraud-is-now-exposed</link><guid isPermaLink="true">https://pau.fm/blog/2026/08/14/if-you-ever-used-dsa-interviews-your-fraud-is-now-exposed</guid><description>DSA interviews replaced judgment with ritual. Now that machines have solved the ritual, companies still using it are exposing that they never knew how to hire engineers.</description><pubDate>Fri, 14 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you ever used data structures and algorithms interviews to hire software engineers, your fraud is
now exposed.&lt;/p&gt;
&lt;p&gt;DSA interviews were never a good proxy for engineering, and this was blindingly obvious to anyone
who had ever shipped software. They were a crutch: a way to avoid the hard work of judging whether a
person actually brought useful skills to a team. Google designed them for a specific problem—hiring
engineers at enormous scale to work on enormous-scale problems. You copied the visible part, and
LeetCode became a substitute for any critical thinking you might otherwise have had to do.&lt;/p&gt;
&lt;p&gt;Candidates responded rationally, of course. They studied the test. An entire curriculum emerged
around problems most engineers rarely encountered in actual work and now, increasingly, never will.
Success reflected time, coaching, pedigree, and familiarity with the ritual at least as much as
engineering ability.&lt;/p&gt;
&lt;p&gt;The fact that you could “study” for the interview should have made the farce obvious. Instead,
programmers wrapped the whole thing in meritocratic language and enjoyed the smug satisfaction of
admitting only people willing and able to jump through their inane hoops into the little cabal.&lt;/p&gt;
&lt;p&gt;How many lines of code have you written in the past year? If it’s more than zero, ask yourself why.
The valuable work was already problem framing, systems understanding, judgment, verification, and
tradeoffs. Now that is increasingly the whole job. Why are you hiring a human based on their ability
to perform a task that machines have effectively solved?&lt;/p&gt;
&lt;p&gt;If you are still running DSA screens in 2026, you are admitting that you never had a serious theory
of how to hire engineers in the first place.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Disclaimer: as a hiring manager, I have never once given a candidate a DSA interview, because I
always thought they were incredibly stupid. I was right all along and now there is incontrovertible
proof.&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>essay</category></item><item><title>Two tech workers live together long enough and their sprints start to…</title><link>https://pau.fm/blog/2026/08/08/sprints-synchronize</link><guid isPermaLink="true">https://pau.fm/blog/2026/08/08/sprints-synchronize</guid><description>Two tech workers live together long enough and their sprints start to synchronize.</description><pubDate>Sat, 08 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Two tech workers live together long enough and their sprints start to synchronize.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>I like to imagine these huts are New York’s solution to the housing crisis.</title><link>https://pau.fm/blog/2026/08/02/new-york-housing-solution</link><guid isPermaLink="true">https://pau.fm/blog/2026/08/02/new-york-housing-solution</guid><description>I like to imagine these huts are New York’s solution to the housing crisis.</description><pubDate>Sun, 02 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I like to imagine these huts are New York’s solution to the housing crisis.&lt;/p&gt;
&lt;div class=&quot;short-media&quot; data-count=&quot;1&quot; data-orientation=&quot;portrait&quot; style=&quot;--short-media-aspect: 1350 / 1800; --short-media-intrinsic-width: 1350px&quot;&gt;&lt;a class=&quot;short-media__item&quot; data-pswp-height=&quot;1800&quot; data-pswp-width=&quot;1350&quot; href=&quot;https://pau.fm/images/blog/new-york-housing-solution.webp&quot;&gt;&lt;img src=&quot;https://pau.fm/images/blog/new-york-housing-solution.webp&quot; alt=&quot;Two rooftop water towers outside a New York apartment window&quot; decoding=&quot;async&quot; height=&quot;1800&quot; loading=&quot;lazy&quot; width=&quot;1350&quot;&gt;&lt;/a&gt;&lt;/div&gt;
</content:encoded><category>short</category></item><item><title>At some point, “tech podcast” came to mean “Android phone show.” Specifically…</title><link>https://pau.fm/blog/2026/07/26/tech-podcasts</link><guid isPermaLink="true">https://pau.fm/blog/2026/07/26/tech-podcasts</guid><description>At some point, “tech podcast” came to mean “Android phone show.” Specifically, shitty Android phones you’ll never buy.</description><pubDate>Sun, 26 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;At some point, “tech podcast” came to mean “Android phone show.” Specifically, shitty Android phones
you’ll never buy.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Imagine if engineers pretended to be salespeople.</title><link>https://pau.fm/blog/2026/07/20/mandatory-sales-hackathon</link><guid isPermaLink="true">https://pau.fm/blog/2026/07/20/mandatory-sales-hackathon</guid><description>Imagine if engineers pretended to be salespeople. They would write random sales pitches they stole from SEO blogspam, insist they be emailed to customers, then hold a mandatory sales hackathon twice a year.</description><pubDate>Mon, 20 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Imagine if engineers pretended to be salespeople. They would write random sales pitches they stole
from SEO blogspam, insist they be emailed to customers, then hold a mandatory sales hackathon twice
a year.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Python has load-bearing whitespace.</title><link>https://pau.fm/blog/2026/07/13/load-bearing-whitespace</link><guid isPermaLink="true">https://pau.fm/blog/2026/07/13/load-bearing-whitespace</guid><description>Python has load-bearing whitespace.</description><pubDate>Mon, 13 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Python has load-bearing whitespace.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Love hack weeks.</title><link>https://pau.fm/blog/2026/07/07/hack-weeks</link><guid isPermaLink="true">https://pau.fm/blog/2026/07/07/hack-weeks</guid><description>Love hack weeks. Very inspiring to half-ass something you know will get thrown away.</description><pubDate>Tue, 07 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Love hack weeks. Very inspiring to half-ass something you know will get thrown away.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Lines of code means something now</title><link>https://pau.fm/blog/2026/07/06/lines-of-code-means-something-now</link><guid isPermaLink="true">https://pau.fm/blog/2026/07/06/lines-of-code-means-something-now</guid><description>When coding agents make typing cheap, code volume becomes a rough measure of how much implementation work an engineer can successfully orchestrate.</description><pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The received wisdom among enlightened software engineers is that lines of code is a terrible measure
of engineering productivity. Good engineers produce less code, not more: they delete things, find
abstractions, avoid unnecessary systems, and spend large amounts of time on work that is not visible
in diffs. LoC mostly rewards visible activity rather than engineering value.&lt;/p&gt;
&lt;p&gt;Coding agents change this in an uncomfortable way. The scarce resource is no longer typing code; it
is specifying, directing, validating, and integrating work. If one engineer can use agents to ship
five integrations, migrate a subsystem, add tests, fix a dozen bugs, and clean up old infrastructure
while another ships one feature, the first engineer probably did produce more. The fact that this
output materializes as a much larger quantity of code is no longer incidental. My view is that LoC
is now a rough proxy for how much implementation surface an engineer can successfully orchestrate.&lt;/p&gt;
&lt;p&gt;It is probably still not a sufficient metric. Generated code can be redundant, brittle, or wrong,
and the highest-leverage work still happens one level up: choosing the right architecture, defining
boundaries, deciding what not to build, and determining whether any of this creates business value.
But I think that there is now substantial signal where previously there was not. In an agentic
engineering environment, once quality and system-level outcomes are held constant, “how much code
did this person ship?” is suddenly a much more reasonable question.&lt;/p&gt;
</content:encoded><category>essay</category></item><item><title>Claude gave me a four-week implementation plan.</title><link>https://pau.fm/blog/2026/06/30/four-week-implementation-plan</link><guid isPermaLink="true">https://pau.fm/blog/2026/06/30/four-week-implementation-plan</guid><description>Claude gave me a four-week implementation plan. I knocked it out in two days.</description><pubDate>Tue, 30 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Claude gave me a four-week implementation plan. I knocked it out in two days.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>I found a venture capitalist with his SAT score on his LinkedIn profile.</title><link>https://pau.fm/blog/2026/06/24/sat-score-on-linkedin</link><guid isPermaLink="true">https://pau.fm/blog/2026/06/24/sat-score-on-linkedin</guid><description>I found a venture capitalist with his SAT score on his LinkedIn profile.</description><pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I found a venture capitalist with his SAT score on his LinkedIn profile.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>I asked Google to set a two-minute, thirty-second timer.</title><link>https://pau.fm/blog/2026/06/17/google-timer</link><guid isPermaLink="true">https://pau.fm/blog/2026/06/17/google-timer</guid><description>I asked Google to set a two-minute, thirty-second timer. “Okay, I’ve started a two-minute timer called ‘30 second.’”</description><pubDate>Wed, 17 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I asked Google to set a two-minute, thirty-second timer. “Okay, I’ve started a two-minute timer
called ‘30 second.’”&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>The owner of my neighborhood teriyaki restaurant is wearing a GitLab T-shirt.</title><link>https://pau.fm/blog/2026/06/11/gitlab-teriyaki</link><guid isPermaLink="true">https://pau.fm/blog/2026/06/11/gitlab-teriyaki</guid><description>The owner of my neighborhood teriyaki restaurant is wearing a GitLab T-shirt. Invest.</description><pubDate>Thu, 11 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The owner of my neighborhood teriyaki restaurant is wearing a GitLab T-shirt. Invest.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>The Clay Theorem</title><link>https://pau.fm/blog/2026/06/10/the-clay-theorem</link><guid isPermaLink="true">https://pau.fm/blog/2026/06/10/the-clay-theorem</guid><description>The interesting transition in AI software is not database to chatbot. It is database to engine: software that stores the method of human judgment and performs it continuously.</description><pubDate>Wed, 10 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Most software has historically been a database with a user interface. The user does the actual work
— researching, comparing, deciding, remembering — and the software records the output.&lt;/p&gt;
&lt;p&gt;The first generation of AI products mostly preserved this architecture and added a chat box. Instead
of tracking wines, ask GPT which wine to buy. Instead of maintaining a travel spreadsheet, ask it
where to stay. This is useful, but it is not much of a product idea.&lt;/p&gt;
&lt;p&gt;Clay is interesting because it suggests a different architecture. Airtable gives you rows and
columns and lets you fill in the cells. Clay lets you describe what a column means and has an agent
fill it in for every row. A task that previously required researching 500 companies, applying the
same fuzzy judgment 500 times, and manually recording 500 answers becomes a declarative operation:
define the judgment once, then curate the results. The model is not bolted onto the database; it
changes the relationship between the user and the database. Rows are items, columns are jobs, and
cells are work.&lt;/p&gt;
&lt;p&gt;This is roughly the architecture we are building at Sonora. Customer software traditionally stores
accounts, tickets, calls, notes, product usage, and CRM fields, while humans are still responsible
for synthesizing all of it. Is this account actually at risk? Has this problem happened before? Did
the champion leave? Is this an escalation or just noise? Which customers are asking for the same
thing?&lt;/p&gt;
&lt;p&gt;Those are repeated judgments over a set of customers. Sonora turns them into work the system can
perform continuously across the customer base, using the underlying calls, tickets, email, CRM, and
product data as its substrate. The user defines what matters, corrects the system when necessary,
and increasingly curates the output instead of manually producing it.&lt;/p&gt;
&lt;p&gt;We celebrated Sonora reaching general availability tonight. A GA party is a chance to stop long
enough to notice what the team has built, and what we celebrated was not a database with a chatbot
attached. It was an engine that can do this work across every customer, continuously. There is much
more to build, but that shift now feels real.&lt;/p&gt;
&lt;p&gt;The interesting transition in AI software is not database → chatbot. It is database → engine.&lt;/p&gt;
&lt;p&gt;Software used to store the output of human judgment. Increasingly, it can store the method.&lt;/p&gt;
</content:encoded><category>essay</category></item><item><title>I would describe Rippling’s aesthetic as “boomer chain letter.”</title><link>https://pau.fm/blog/2026/06/04/boomer-chain-letter</link><guid isPermaLink="true">https://pau.fm/blog/2026/06/04/boomer-chain-letter</guid><description>I would describe Rippling’s aesthetic as “boomer chain letter.”</description><pubDate>Thu, 04 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I would describe Rippling’s aesthetic as “boomer chain letter.”&lt;/p&gt;
&lt;div class=&quot;short-media&quot; data-count=&quot;1&quot; data-orientation=&quot;portrait&quot; style=&quot;--short-media-aspect: 1450 / 1524; --short-media-intrinsic-width: 1450px&quot;&gt;&lt;a class=&quot;short-media__item&quot; data-pswp-height=&quot;1524&quot; data-pswp-width=&quot;1450&quot; href=&quot;https://pau.fm/images/blog/rippling-boomer-chain-letter.webp&quot;&gt;&lt;img src=&quot;https://pau.fm/images/blog/rippling-boomer-chain-letter.webp&quot; alt=&quot;A Rippling payday graphic with cartoon clouds, a rainbow, and the slogan “Rain, rain, go away. It’s payday!”&quot; decoding=&quot;async&quot; height=&quot;1524&quot; loading=&quot;lazy&quot; width=&quot;1450&quot;&gt;&lt;/a&gt;&lt;/div&gt;
</content:encoded><category>short</category></item><item><title>Crypto is the Agile of real life.</title><link>https://pau.fm/blog/2026/05/28/crypto-is-the-agile-of-real-life</link><guid isPermaLink="true">https://pau.fm/blog/2026/05/28/crypto-is-the-agile-of-real-life</guid><description>Crypto is the Agile of real life. Fake work invented to enrich a sleazy grifter class.</description><pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Crypto is the Agile of real life. Fake work invented to enrich a sleazy grifter class.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>I love the term “pre-owned.” Like somebody already did the work for you.</title><link>https://pau.fm/blog/2026/05/22/pre-owned</link><guid isPermaLink="true">https://pau.fm/blog/2026/05/22/pre-owned</guid><description>I love the term “pre-owned.” Like somebody already did the work for you. What a relief! It’s pre-owned, so I don’t have to worry about it.</description><pubDate>Fri, 22 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I love the term “pre-owned.” Like somebody already did the work for you. What a relief! It’s
pre-owned, so I don’t have to worry about it.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>On a long enough timeline, all internet banter is meta-banter.</title><link>https://pau.fm/blog/2026/05/15/internet-meta-banter</link><guid isPermaLink="true">https://pau.fm/blog/2026/05/15/internet-meta-banter</guid><description>On a long enough timeline, all internet banter is meta-banter.</description><pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;On a long enough timeline, all internet banter is meta-banter.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>MacRumors is stepping in to help people who don’t know when fall is.</title><link>https://pau.fm/blog/2026/05/09/macrumors-explains-fall</link><guid isPermaLink="true">https://pau.fm/blog/2026/05/09/macrumors-explains-fall</guid><description>MacRumors is stepping in to help people who don’t know when fall is.</description><pubDate>Sat, 09 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;MacRumors is stepping in to help people who don’t know when fall is.&lt;/p&gt;
&lt;div class=&quot;short-media&quot; data-count=&quot;1&quot; data-orientation=&quot;landscape&quot; style=&quot;--short-media-aspect: 1424 / 166; --short-media-intrinsic-width: 1424px&quot;&gt;&lt;a class=&quot;short-media__item&quot; data-pswp-height=&quot;166&quot; data-pswp-width=&quot;1424&quot; href=&quot;https://pau.fm/images/blog/macrumors-explains-fall.webp&quot;&gt;&lt;img src=&quot;https://pau.fm/images/blog/macrumors-explains-fall.webp&quot; alt=&quot;MacRumors explaining that fall runs from September to December and usually coincides with Apple’s busiest release period&quot; decoding=&quot;async&quot; height=&quot;166&quot; loading=&quot;lazy&quot; width=&quot;1424&quot;&gt;&lt;/a&gt;&lt;/div&gt;
</content:encoded><category>short</category></item><item><title>I install really basic shit through Homebrew.</title><link>https://pau.fm/blog/2026/05/02/homebrew-dependencies</link><guid isPermaLink="true">https://pau.fm/blog/2026/05/02/homebrew-dependencies</guid><description>I install really basic shit through Homebrew. Then one day I discover I have 248 packages. Love to upgrade aws-sdk-cpp.</description><pubDate>Sat, 02 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I install really basic shit through Homebrew. Then one day I discover I have 248 packages. Love to
upgrade &lt;code&gt;aws-sdk-cpp&lt;/code&gt;.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Losing three percent every day has an upside.</title><link>https://pau.fm/blog/2026/04/26/the-good-news-about-a-three-percent-drop</link><guid isPermaLink="true">https://pau.fm/blog/2026/04/26/the-good-news-about-a-three-percent-drop</guid><description>Losing three percent every day has an upside. The absolute value keeps getting smaller.</description><pubDate>Sun, 26 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Losing three percent every day has an upside. The absolute value keeps getting smaller.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Whenever literally anything happens in the world, I wait for Slack.</title><link>https://pau.fm/blog/2026/04/19/take-time-for-yourself</link><guid isPermaLink="true">https://pau.fm/blog/2026/04/19/take-time-for-yourself</guid><description>Whenever literally anything happens in the world, I wait for Slack. I’m not okay until I see some VP post “it’s okay to take time for yourself.”</description><pubDate>Sun, 19 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Whenever literally anything happens in the world, I wait for Slack. I’m not okay until I see some VP
post “it’s okay to take time for yourself.”&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Hate your career long enough and AI displacement starts to sound pleasant.</title><link>https://pau.fm/blog/2026/04/13/quietly-hated-your-career</link><guid isPermaLink="true">https://pau.fm/blog/2026/04/13/quietly-hated-your-career</guid><description>Hate your career long enough and AI displacement starts to sound pleasant.</description><pubDate>Mon, 13 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hate your career long enough and AI displacement starts to sound pleasant.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Tradeoffs are real</title><link>https://pau.fm/blog/2026/04/11/tradeoffs-are-real</link><guid isPermaLink="true">https://pau.fm/blog/2026/04/11/tradeoffs-are-real</guid><description>Political rhetoric promises abundance by hiding the bill. A serious policy argument names the benefits, the costs, and who gets each.</description><pubDate>Sat, 11 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Tradeoffs are real. This is an obvious statement, which makes it strange how much political rhetoric
is organized around denying it.&lt;/p&gt;
&lt;p&gt;Political scientists usually define populism as a conflict between “the pure people” and “the
corrupt elite,” while technocracy claims authority through expertise and problem-solving. But the
important policy consequence is simpler: once every problem has a villain, every constraint starts
looking like sabotage.
(&lt;a href=&quot;https://www.cambridge.org/core/journals/government-and-opposition/article/populist-zeitgeist/2CD34F8B25C4FFF4F322316833DB94B7&quot;&gt;Mudde&lt;/a&gt;,
&lt;a href=&quot;https://www.cambridge.org/core/journals/american-political-science-review/article/abs/will-vs-reason-the-populist-and-technocratic-forms-of-political-representation-and-their-critique-to-party-government/58444AC41CD6B6A4116F12CFF2585E15&quot;&gt;Caramani&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;On the left, corporate power and the rich are why we cannot have generous public services, high
wages, cheap housing, and cheap energy all at once. On the right, elites, immigrants, bureaucrats,
and the deep state are why we cannot have low taxes, secure borders, strong communities, cheap
housing, and a booming economy all at once. Different enemies, same promise: if the right people
were in charge, nothing would have to give.&lt;/p&gt;
&lt;p&gt;Sometimes the villains are real. They still do not repeal budget constraints, supply constraints, or
second-order effects. Scarcity can be distributed unfairly without being invented by the people who
benefit from that distribution.&lt;/p&gt;
&lt;p&gt;Policy is where denying this gets expensive.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rent control protects current tenants. It can charge some of that protection to future tenants. A
&lt;a href=&quot;https://www.nber.org/papers/w24181&quot;&gt;San Francisco study&lt;/a&gt; found that rent control increased
covered tenants’ likelihood of remaining at their address by nearly 20 percent, while landlords
reduced rental housing supply by 15 percent.&lt;/li&gt;
&lt;li&gt;Greater trade integration supported growth and poverty reduction in many developing countries.
Increased import competition from China also produced persistent losses in employment and earnings
in some American labor markets. The beneficiaries and the casualties are both real.
(&lt;a href=&quot;https://documents1.worldbank.org/curated/en/726971467989468997/pdf/97607-REPLACEMENT-The-Role-of-Trade-in-Ending-Poverty.pdf&quot;&gt;World Bank&lt;/a&gt;,
&lt;a href=&quot;https://www.nber.org/papers/w21906&quot;&gt;Autor, Dorn, and Hanson&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Environmental review catches real harms. It can also delay clean-energy projects for years. A
&lt;a href=&quot;https://www.rff.org/publications/reports/how-long-does-it-take-national-environmental-policy-act-timelines-and-outcomes-for-clean-energy-projects/&quot;&gt;recent study&lt;/a&gt;
found average environmental-impact-statement timelines of 27 months for solar projects and 45
months for wind projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In each case, both things are true. Which matters more is a values question. Pretending one of them
is not happening is not conviction. It is refusing to do the arithmetic.&lt;/p&gt;
&lt;p&gt;A tradeoff is not an argument against a policy. It is the argument the policy has to answer.&lt;/p&gt;
&lt;p&gt;By a tradeoff sensibility, I do not mean centrism or splitting the difference. Sometimes the right
answer is to pay the cost. Sometimes it is to stop paying it. The discipline is to count the cost
before announcing that it is free.&lt;/p&gt;
&lt;p&gt;The obvious objection is correct: “it’s complicated” is also the house style of everyone defending a
status quo that suits them. But there is a tell. Deflection invokes complexity and stops. Analysis
names the assumptions, the distributional effects, and the evidence that would change the
conclusion. Nobody hiding behind complexity volunteers to go through the elasticities.&lt;/p&gt;
&lt;p&gt;The fiscal debates of 2009 and 2021 show the risks in opposite directions. In early 2009,
&lt;a href=&quot;https://www.brookings.edu/articles/why-the-stimulus-package-may-be-too-weak-to-fix-the-economy/&quot;&gt;critics warned&lt;/a&gt;
that the proposed stimulus might be too weak for the size of the recession. In early 2021,
&lt;a href=&quot;https://www.brookings.edu/articles/the-macroeconomic-implications-of-bidens-1-9-trillion-fiscal-package/&quot;&gt;economic analyses&lt;/a&gt;
projected that the American Rescue Plan could push output above its pre-pandemic potential; San
Francisco Fed researchers later
&lt;a href=&quot;https://www.frbsf.org/research-and-insights/publications/economic-letter/2021/10/is-american-rescue-plan-taking-us-back-to-1960s/&quot;&gt;estimated&lt;/a&gt;
that it could add about 0.3 percentage points to annual inflation through 2022. Subsequent
&lt;a href=&quot;https://www.brookings.edu/articles/what-caused-the-u-s-pandemic-era-inflation/&quot;&gt;research&lt;/a&gt;
attributed the inflation surge to both strong demand and supply disruptions, with their relative
importance changing over time.&lt;/p&gt;
&lt;p&gt;You can dispute the estimates. That is the point: the dispute is stated in terms that evidence can
resolve. Output gaps. Multipliers. Supply constraints. Inflation. Put numbers on them and let
reality grade the test.&lt;/p&gt;
&lt;p&gt;The real advantage of a tradeoff sensibility is not that it always gets the answer right. It is that
when it gets the answer wrong, the assumptions are visible, the miss has a size, and the model can
be updated.&lt;/p&gt;
&lt;p&gt;The anti-tradeoff alternative is emotionally easier. When reality fails to deliver every promised
good at once, find another villain.&lt;/p&gt;
&lt;p&gt;Tradeoffs are real. Scarcity is not a conspiracy. A politics that will not say who pays is not
offering abundance. It is hiding the bill.&lt;/p&gt;
</content:encoded><category>essay</category></item><item><title>Americans for Common Cents was funded by the zinc lobby.</title><link>https://pau.fm/blog/2026/04/06/common-cents</link><guid isPermaLink="true">https://pau.fm/blog/2026/04/06/common-cents</guid><description>Americans for Common Cents was funded by the zinc lobby. Of course it was.</description><pubDate>Mon, 06 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Americans for Common Cents
&lt;a href=&quot;https://publicintegrity.org/politics/saving-the-penny-makes-cents-for-zinc-backed-front-group/&quot;&gt;was funded by the zinc lobby&lt;/a&gt;.
Of course it was.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>WeWork replaced its in-app snack-buying software with a generic Square terminal.</title><link>https://pau.fm/blog/2026/03/30/wework-snack-terminal</link><guid isPermaLink="true">https://pau.fm/blog/2026/03/30/wework-snack-terminal</guid><description>WeWork replaced its in-app snack-buying software with a generic Square terminal. It was a hundred times better. This is why you let technology companies make the software.</description><pubDate>Mon, 30 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;WeWork replaced its in-app snack-buying software with a generic Square terminal. It was a hundred
times better. This is why you let technology companies make the software.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>It’s funny when DJs turn every knob while the music is clearly unaffected.</title><link>https://pau.fm/blog/2026/03/24/dj-knobs</link><guid isPermaLink="true">https://pau.fm/blog/2026/03/24/dj-knobs</guid><description>It’s funny when DJs turn every knob while the music is clearly unaffected.</description><pubDate>Tue, 24 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;It’s funny when DJs turn every knob while the music is clearly unaffected.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>I’m so market-pilled I don’t think it’s possible to be overpaid.</title><link>https://pau.fm/blog/2026/03/17/marketpilled</link><guid isPermaLink="true">https://pau.fm/blog/2026/03/17/marketpilled</guid><description>I’m so market-pilled I don’t think it’s possible to be overpaid. You both agreed to the salary.</description><pubDate>Tue, 17 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’m so market-pilled I don’t think it’s possible to be overpaid. You both agreed to the salary.&lt;/p&gt;
</content:encoded><category>short</category></item><item><title>Locality of context over separation of concerns</title><link>https://pau.fm/blog/2026/03/16/locality-of-context-over-separation-of-concerns</link><guid isPermaLink="true">https://pau.fm/blog/2026/03/16/locality-of-context-over-separation-of-concerns</guid><description>Coding agents strengthen the case for locality: organize code so the context needed to change it is nearby, rather than scattered across architectural layers.</description><pubDate>Mon, 16 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;htmx has a useful idea called
&lt;a href=&quot;https://htmx.org/essays/locality-of-behaviour/&quot;&gt;“locality of behavior”&lt;/a&gt;: the behavior of a piece of
code should be obvious from looking at that piece of code. A button that says &lt;code&gt;hx-get=&quot;/clicked&quot;&lt;/code&gt;
tells you what clicking it does. You do not need to find the event listener, trace a dispatch into a
store, inspect some middleware, and discover that a plugin registered three directories away is what
actually makes the request.&lt;/p&gt;
&lt;p&gt;This is usually framed as a principle for humans. Local behavior is easier to understand because
less of the program has to fit in your head at once. But coding agents make the idea more
interesting, not less. An agent does not begin a task with a mature mental model of the repository.
It constructs one by searching, opening files, and deciding which clues deserve another search.
Every jump is both a context cost and another chance to miss the mechanism entirely.&lt;/p&gt;
&lt;p&gt;Separation of concerns is often implemented as separation by technical category: components over
here, state over there, network requests in a service, validation in a schema folder, and side
effects in middleware. Each directory looks tidy while a single product behavior is smeared across
all of them. The architecture has separated the code without separating the concern. A concern is
usually closer to “cancel a subscription” than to “all the functions which issue HTTP requests.”&lt;/p&gt;
&lt;p&gt;Locality does not require inlining every implementation. The htmx essay makes the useful distinction
between inlining behavior and surfacing its invocation. A function can hide complicated machinery
while its call site still makes the dependency obvious. The same is true of authorization, database
access, or a background job: centralize the policy, but make its participation visible where the
behavior is defined. Abstraction should hide machinery, not causality.&lt;/p&gt;
&lt;p&gt;Agents sharpen the economics of that distinction because context is finite. Anthropic describes
effective context engineering as finding the
&lt;a href=&quot;https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents&quot;&gt;smallest set of high-signal tokens&lt;/a&gt;
that produces the desired result. A codebase is therefore not just a program; it is a context
retrieval system. Co-located tests, nearby comments, explicit dependencies, and feature-oriented
folders help an agent retrieve the right evidence cheaply. Registries, implicit conventions, and
spooky action at a distance force it to reconstruct an invisible graph before it can safely change a
line.&lt;/p&gt;
&lt;p&gt;There are still good reasons to put some things far away. A security invariant should not be copied
into every endpoint merely to improve locality; it should be encoded once in a boundary, type, or
check that cannot be bypassed. Shared implementation belongs behind a stable interface. The test is
not whether all relevant code occupies one file, but whether the local code reveals which larger
rules govern it and gives the reader an obvious path to them.&lt;/p&gt;
&lt;p&gt;Separation of concerns remains a means, not a goal. The more useful default for a world of coding
agents is &lt;strong&gt;locality of context&lt;/strong&gt;: code that changes together should be understandable together.
Every architectural hop consumes attention; good architecture compresses the explanation of a change
into the same neighborhood as the change itself.&lt;/p&gt;
</content:encoded><category>essay</category></item><item><title>Hello.</title><link>https://pau.fm/blog/2026/03/15/hello</link><guid isPermaLink="true">https://pau.fm/blog/2026/03/15/hello</guid><description>Notes on how AI is changing software development, plus the occasional dog photo.</description><pubDate>Sun, 15 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I came of age when blogging was cool. I always wanted to blog consistently, but I squarely fit into
the wide swathe of the curve of people that habitually start and abandon blogs every few years.&lt;/p&gt;
&lt;p&gt;But these days I’m finding myself with quite a lot to say: software development is evolving rapidly
because of AI, and I want to catalog that shift as it happens. What gets easier and what gets
harder? What are the limits of the tools, and which of those limits will actually stick around? What
does the work even look like now, or in a decade?&lt;/p&gt;
&lt;p&gt;Expect essays, notes, links, and occasional updates drawn mostly from my work. There will be lots of
opinions and maybe some dog photos.&lt;/p&gt;
&lt;p&gt;Thanks for reading, and enjoy your visit to my &lt;a href=&quot;https://xkcd.com/148/&quot;&gt;wobsite&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>essay</category></item></channel></rss>