<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Jonas Leddington &#8212; Building with AI</title>
  <subtitle>Outsider Builders. AI ethics. Technology for the human person.</subtitle>
  <link href="https://jonasleddington.com/atom/building-with-ai.xml" rel="self"/>
  <link href="https://jonasleddington.com/building-with-ai/"/>
  <id>https://jonasleddington.com/building-with-ai/</id>
  <author><name>Jonas Leddington</name></author>
  <updated>2026-10-07T00:00:00.000Z</updated>
  <entry>
    <title>The Joys of AI</title>
    <link href="https://jonasleddington.com/writing/the-joys-of-ai/"/>
    <id>https://jonasleddington.com/writing/the-joys-of-ai/</id>
    <updated>2026-10-07T00:00:00.000Z</updated>
    <summary>The joys of learning are different from the joys of speed, productivity, or anticipated rewards.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;The joys of learning are different from the joys of speed, productivity, or anticipated rewards.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I didn’t expect building with Claude to be so joyful. During my 1000+ hours of building and writing, I was often in “flow” states and sometimes experienced visceral joy.&lt;/p&gt;
&lt;p&gt;I tuned my Claude to correct me, to highlight errors and assumptions. I loved that. I’d stay in those threads and dig deeper.&lt;/p&gt;
&lt;p&gt;I’d bring an idea and a goal and Claude would help fill in the details faster than I could have imagined. The feedback and iteration loop could keep me rapt.&lt;/p&gt;
&lt;p&gt;I’d bring curiosity or a question and Claude would surface new ideas and make connections I never anticipated. The essential pattern-matching capability of the model could be a huge aid to creativity.&lt;/p&gt;
&lt;p&gt;We’d oscillate between synthetic and analytic “thinking,” often with Claude underlining the convergences while I pulled things apart again.&lt;/p&gt;
&lt;p&gt;I suspect power users of AI enjoy effortful thinking for its own sake. This kind of user is likely attuned to how they think, how they learn, their weak spots or gaps, and the attributes of the model as a partner.&lt;/p&gt;
&lt;p&gt;Of course, there were and are other, different thrills and seductions that make me nervous. For example, I’d get curiously satisfied knowing Claude was “hard at work” with multiple agents while I enjoyed dinner or a TV show. There’s nothing inherently wrong with productivity, but I’m going to watch my attachment to it.&lt;/p&gt;
&lt;p&gt;The great risk is speed. We’d move at a pace that outstripped my learning. I’d feel productive but empty, even confused about what happened.&lt;/p&gt;
&lt;p&gt;The interaction and feedback loops could mimic variable rewards, like slot machines. I think this is a feature of wiring a non-deterministic input into one’s emotional and cognitive process.&lt;/p&gt;
&lt;p&gt;Also, the model can display endless mastery, switching vocabularies and modes with total fluency. I might then feel smart and insightful when working with it, but incapable of holding the thread afterward on my own. We see this in humans too: someone in conversation with a master will feel like they’ve also achieved some mastery, but it all falls apart once they’re alone again.&lt;/p&gt;
&lt;p&gt;Working joyfully with Claude, then, requires attention and discipline. AI can remove the friction that leads to durable learning, seducing us instead with pace and perceived productivity. One can end a working session but hold only gestures. The absence of friction does not lead to contentment.&lt;/p&gt;
&lt;p&gt;Human learning — consolidation and incorporation — takes time. While I’ve previously used Claude for research and technical explanations and let Claude write related passages for me, I’ll now insist on working everything through myself, so I own the vocabulary. With my build efforts, I’ve slowed work to study the fundamentals, from architecture and design philosophy to security, authentication, failure modes, and, yes, the vocabulary.&lt;/p&gt;
&lt;p&gt;In my next post, I’ll outline how Claude “thinks.” The model has a strong default form — taxonomies, parallel structures, closing syntheses — that we can learn to operate around. I’ll share a /skill I’m building to support rigorous thinking.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>A Study Plan for Outsider Builders</title>
    <link href="https://jonasleddington.com/writing/a-study-plan-for-outsider-builders/"/>
    <id>https://jonasleddington.com/writing/a-study-plan-for-outsider-builders/</id>
    <updated>2026-09-05T00:00:00.000Z</updated>
    <summary>Andrew Ng recently published the AI Engineering Skills Map. Here is a study plan and guide for self-taught “Outsider Builders.” Plus, thoughts on whether I need to learn to read code. I bet I don’t.</summary>
    <content type="html">&lt;h3&gt;Index:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;**A Study Plan for Outsider Builders **(downloadable, with templates).&lt;/li&gt;
&lt;li&gt;**My Bet: I Don’t Need to Learn to Read Code (with precision) **— a bit of history, what I do now, what the field believes, what the evidence says, the test, what a model can find.&lt;/li&gt;
&lt;li&gt;**Appendix - A Self Assessment - **where I stand on the map.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;1 · The Plan&lt;/h2&gt;
&lt;p&gt;Starting in late March this year, I spent five months and 1,200 hours in a deep hole with Claude Code, learning to build software by making error after error — and thus creating solution after solution — in dialogue with Claude. In the last few weeks, as I finally came up for air, I found myself thinking: I can’t be alone doing this. Others must be building like this. And, moreover, real engineers must have better solutions for the problems I’ve been tackling.&lt;/p&gt;
&lt;p&gt;In that context, I stumbled on Andrew Ng and his recently published&lt;a href=&quot;https://www.linkedin.com/pulse/ai-engineering-skills-map-andrew-ng-m479c/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; map of AI engineering skills&lt;/a&gt;. He notes that software is built very differently today than in 2022 and proposes a set of skills for people who build and deploy AI applications. (He holds those folk separate from AI engineers building AI systems.)&lt;/p&gt;
&lt;p&gt;As an outsider — self-taught, no previous engineering skills — it’s an intimidating map.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nevertheless, I’ve developed my own workplan and study guide from it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I’ve made that plan &lt;a href=&quot;https://github.com/J-Maximus/outsider-builder-plan&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;publicly available on Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It’s just a starting point. I hope you will help me improve it by offering corrections, additions, and resources.&lt;/p&gt;
&lt;p&gt;My hope is to help forge a path for “outsider builders” — those of us who are self-taught and yet loving the creative possibilities and opportunities to contribute.&lt;/p&gt;
&lt;p&gt;You can also see &lt;a href=&quot;https://claude.ai/code/artifact/48eb4234-7abf-4e35-9771-358ec4759fed&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;the plan and example here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please dig into it and comment — and please push back on the argument below.&lt;/p&gt;
&lt;p&gt;In the next couple weeks, I’m also going to write on the ethics of building with AI agents. I find myself part of a long-running set of hopes and debates about technology, our responsibilities, and where power sits.&lt;/p&gt;
&lt;p&gt;Thank you,&lt;/p&gt;
&lt;p&gt;Jonas&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/writing/img/a-study-plan-for-outsider-builders-1.png&quot; alt=&quot;A 2026 timeline in two rows. Above, the field: OpenAI&#39;s harness engineering in February, Willison&#39;s agentic engineering patterns, Ng&#39;s AI Engineering Skills Map in August. Below, my own build: first commit in Replit on 27 April, decisions.md on 30 April, Replit dropping every production table on 11 May.&quot;&gt;&lt;/p&gt;
&lt;h2&gt;2. My bet: I don’t need to learn to read code (with precision)&lt;/h2&gt;
&lt;p&gt;There’s one piece of Ng’s plan that I refuse: I will not learn to write code, and I will not learn to read it with precision.&lt;/p&gt;
&lt;p&gt;I will not be able to review code in bulk. I won’t have line-by-line comprehension in a deep way at an engineer’s speed — or any speed at all — and, contrary to Claude’s initial recommendation, I’m not going to spend a year trying to get it. (As I note below, I did try — and the pace was untenable.)&lt;/p&gt;
&lt;p&gt;Instead, I’ll spend that year building machines to do what many argue only an experienced engineer can do. So, mostly, I will read about code. And I will verify by instrument and by argument.&lt;/p&gt;
&lt;p&gt;*I’m not saying no knowledge is needed. My workplan commits me to studying the vocabulary and failure modes as well as the ability to do a minimum read — a diff, a stack trace, a schema — with AI help, drawing the vocabulary from taxonomies outside my own repo and using a tutor model that isn’t my builder.&lt;/p&gt;
&lt;p&gt;Most of the people I read now treat writing code as optional. OpenAI’s harness team&lt;a href=&quot;https://openai.com/index/harness-engineering/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; shipped about a million lines&lt;/a&gt; with none written by hand. Josh Mohrer, a former Uber GM with no engineering career,&lt;a href=&quot;https://mixergy.com/interviews/the-7-million-vibe-coded-app/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; built a $7M product&lt;/a&gt; by learning to code alongside an LLM. Others shipped without writing at all: Kostiantyn Vlasenko (&lt;a href=&quot;https://claude.com/blog/how-a-non-technical-project-manager-built-and-shipped-a-stress-management-app-with-claude-code-in-six-weeks&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;in Anthropic’s own case study&lt;/a&gt;), the anesthesiologist&lt;a href=&quot;https://kevinmd.com/2026/08/how-a-doctor-with-no-coding-background-built-his-own-bedside-ai-tools-podcast.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; Ahmed Elsonbaty&lt;/a&gt;, and&lt;a href=&quot;https://www.saastr.com/i-vibe-coded-10-apps-used-almost-a-million-times-then-i-had-to-stop-for-90-days/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; Jason Lemkin&lt;/a&gt; — who also had an agent delete his production database along the way. And some of the best engineers alive have stopped reading what their agents write. Robert C. Martin, who wrote &lt;em&gt;Clean Code&lt;/em&gt;, says his current strategy is not to read any of it, and to measure test coverage, dependency structure, complexity, and mutation scores instead. Peter Steinberger&lt;a href=&quot;https://newsletter.pragmaticengineer.com/p/the-creator-of-clawd-i-ship-code&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; ships code he doesn’t read&lt;/a&gt;. Boris Cherny, who built Claude Code,&lt;a href=&quot;https://fortune.com/2026/06/11/anthropic-claude-boris-cherny-doesnt-write-code-by-hand-anymore/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; hasn’t written a line by hand in eight months&lt;/a&gt;. Amjad Masad said in March 2025 that he no longer thinks you should learn to code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nearly everyone still holds, though, that reading with precision is necessary.&lt;/strong&gt; Simon Willison is very pointed on this (see below) and all the folks above are no doubt experts at reading.&lt;/p&gt;
&lt;p&gt;Here’s my contrary take: I believe the fluent human read will soon enough be unnecessary and, perhaps, inferior in most instances. Many of the review and reading skills that engineers today hold to be human work will also be done best by agents.&lt;/p&gt;
&lt;p&gt;Andrew Ng, in his most recent writing, comes closest to this position, but he still expects human review of code, even if with increasing infrequency.&lt;/p&gt;
&lt;p&gt;My position is not popular among engineers, as I detail below. And, the truth is that the engineers have all seen countless things that I have not. They have a language I lack. They can see problems ahead that I wouldn’t even know to name.&lt;/p&gt;
&lt;p&gt;So, I’m not claiming to match an engineer at anything. Rather, my hope – for myself and others – is that the right kind of system of agents can build software that is safe to hand to strangers.&lt;/p&gt;
&lt;h3&gt;I’m arguing that the future of building won’t require the great majority of us to understand the code itself.&lt;/h3&gt;
&lt;p&gt;I may prove myself wrong, but I hope not. I’ve got a lot riding on it.&lt;/p&gt;
&lt;h3&gt;A bit of history&lt;/h3&gt;
&lt;p&gt;In February 2025, Karpathy coins “vibe coding” — a term he&lt;a href=&quot;https://thenewstack.io/vibe-coding-is-passe/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; retired a year later&lt;/a&gt; for “agentic engineering”: “you are not writing the code directly 99% of the time, you are orchestrating agents who do and acting as oversight.” In March, Ng calls advice against learning to code&lt;a href=&quot;https://www.deeplearning.ai/the-batch/issue-292&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; “some of the worst career advice ever given”&lt;/a&gt; — his point being that coding had become easier, so more people should do it; read one way, his definition includes me. In October, Willison proposes&lt;a href=&quot;https://simonwillison.net/2025/Oct/7/vibe-engineering/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; “vibe engineering.”&lt;/a&gt; In February 2026, OpenAI publishes&lt;a href=&quot;https://openai.com/index/harness-engineering/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; “Harness engineering”&lt;/a&gt; — humans steer, agents execute — and Willison starts writing his&lt;a href=&quot;https://simonwillison.net/2026/Feb/23/agentic-engineering-patterns/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; Agentic Engineering Patterns&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;**On April 27, 2026, Claude taught me how to install Claude Code locally and I made my first commit, in Replit. (**This followed several weeks of build plan, architecture, and schema development and iteration. My initial plan had me studying every piece of code to achieve solid understanding. I found the pace there untenable. My learning was far too slow, so I started using ‘adversarial’ agents.)&lt;/p&gt;
&lt;p&gt;Nine days later — I only saw the timing now — Willison publishes&lt;a href=&quot;https://simonwillison.net/2026/May/6/vibe-coding-and-agentic-engineering/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; “Vibe coding and agentic engineering are getting closer than I’d like,”&lt;/a&gt; and the&lt;a href=&quot;https://news.ycombinator.com/item?id=48037128&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; HN thread&lt;/a&gt; runs to 787 points and 885 comments. I was trying to cross this bridge and had zero awareness of the debate.&lt;/p&gt;
&lt;p&gt;Within days of that first commit I realized I needed to give my agents more context, and I started decisions.md. Ten weeks later I found Amit Raz&lt;a href=&quot;https://rzailabs.com/blog/decisions-md-for-coding-agents&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; recommending the same file&lt;/a&gt;. Michael Nygard’s architecture decision records are fifteen years old; I didn’t know that either. I had no idea any of these conversations were happening.&lt;/p&gt;
&lt;p&gt;I evolved a number of other practices, as detailed in my&lt;a href=&quot;https://claude.ai/cowork/LINK-TO-SEPT-2-ARTICLE&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; agent governance piece&lt;/a&gt;. OpenAI was writing in February about repository knowledge as the system of record. I wrote to myself over the summer: “For a fresh session, the record is the world. A decision made anywhere else was not made.”&lt;/p&gt;
&lt;p&gt;In dialogue with Claude I also developed other verification practices: graded corpora, pre-work packets, isolated agents with different prompts and context, a QA inventory including a unit suite and DB-backed tests, a CI gate, regression-per-bug, and felt-experience dogfooding. In each instance, I’d asked Claude: “Ok, given this problem, what are my options? How do we solve at root cause level and make the solve durable?”&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://newsletter.kentbeck.com/p/augmented-coding-beyond-the-vibes&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kent Beck&lt;/a&gt;, June 2025: “In augmented coding you care about the code, its complexity, the tests, &amp;amp; their coverage.” (A year later, in&lt;a href=&quot;https://newsletter.kentbeck.com/p/trust-factory&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; “Trust Factory,”&lt;/a&gt; he argues that single-player development with agents eliminates most of the small chances to build trust. I sit in his crosshairs.) I got to the same place there the same way I got everywhere: by failure. When two components each tested green and the wire between them turned out to be missing, Claude suggested breaking every new seam on purpose, once, in a test. When a unit test turned out to have been asserting our own request format back at ourselves for three months, we added a rule: “Anything that carries a contract with an outside system must have been run against that system at least once.”&lt;/p&gt;
&lt;h3&gt;What I do now&lt;/h3&gt;
&lt;p&gt;I share what follows just to provide context for the argument I’m making. I’m not claiming any kind of novelty here — I’m sure the field recommends all of it somewhere — though some of it I haven’t yet found elsewhere.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I keep the reviewer away from the code.&lt;/strong&gt; Anthropic recommends a reviewer in a fresh context that sees only the diff. Mine sees the record — the decisions, the deferrals, the tests — and not the diff’s framing, and it argues with the builder from there. My reviewer can’t be captured by the code. The trade-off is that it can be captured by a stale record. Both have happened. Both are logged.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A deferral index.&lt;/strong&gt; An agent doesn’t know why something is missing. Deliberate? A mistake? Lacking context, it starts to fix it. So I keep a table of deliberate absences, keyed by what’s missing. (Others built the outlines — the Go FAQ, PEP 1’s rejected ideas — and I’m writing that up now.) I think of this as analogous to a new hire: the agent just plows ahead on its narrow objective where the human version would stop and ask.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I test my instruments.&lt;/strong&gt; I’ve hardened my mutation tool three times after it lied. Every layer of QA is itself a fallible component. My agents test the tests they build.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Retractions run both directions.&lt;/strong&gt; Anthropic’s&lt;a href=&quot;https://code.claude.com/docs/en/best-practices&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; documentation&lt;/a&gt; warns that “a reviewer prompted to find gaps will usually report some, even when the work is sound.” I found the opposite failure too: a reviewer folded when the builder cited a three-month-old comment and a verification run. Neither agent provided proof or proposed an experiment to check the truth. (It took two minutes to run; the three-month-old comment was wrong.) So a rule now binds both agents: retract only on evidence, and record the retraction with the query that settled it. I don’t judge the argument. I ask what would settle it and demand the evidence.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Abstention on the user’s side.&lt;/strong&gt; Everyone gates the build: if the agent can’t verify it, it doesn’t ship. I applied the same rule to the product. When Maximus can’t pin a reminder to a time, it doesn’t guess; it stores the fact undated and asks. That rule has held since June. We shipped a newer guard for a bare “three o’clock” last week and its first live firing was swallowed by another rule — that’s now in the log alongside the fix. The rule that governs my build governs what my users hear.&lt;/p&gt;
&lt;h3&gt;What the field believes&lt;/h3&gt;
&lt;p&gt;Willison,&lt;a href=&quot;https://simonwillison.net/2025/Mar/19/vibe-coding/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; March 2025&lt;/a&gt;: “I won’t commit any code to my repository if I couldn’t explain exactly what it does to somebody else.”&lt;/p&gt;
&lt;p&gt;Willison,&lt;a href=&quot;https://simonwillison.net/2026/May/6/vibe-coding-and-agentic-engineering/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; May 2026&lt;/a&gt;: “If you’re building software for other people, vibe coding is grossly irresponsible because it’s other people’s information.”&lt;/p&gt;
&lt;p&gt;Ng,&lt;a href=&quot;https://www.deeplearning.ai/the-batch/the-ai-engineering-skills-map-in-detail-software-engineering-fundamentals&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; August 2026&lt;/a&gt;: “A novice who vibe codes without understanding software fundamentals can create simple applications, but this often leads to the coding agent making bad tradeoffs in latency, availability, consistency, reliability, maintainability, simplicity, and/or cost.” Understanding the fundamentals, he says, is what lets you steer the agents&lt;a href=&quot;https://www.deeplearning.ai/the-batch/the-ai-engineering-skills-map&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; “using the precise language of software engineering.”&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Birgitta Böckeler, at Thoughtworks,&lt;a href=&quot;https://martinfowler.com/articles/exploring-gen-ai/13-role-of-developer-skills.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; March 2025&lt;/a&gt;: long-term maintainability is “where my 20+ years of programming experience mattered the most.” Cal Newport,&lt;a href=&quot;https://calnewport.com/on-ai-coding-and-its-discontents/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; August 2026&lt;/a&gt;: reviewing code you didn’t write is famously hard, so people skip it. In July, Codeberg’s members voted 358–144 to exclude projects mostly written by agents. And Gary Marcus,&lt;a href=&quot;https://garymarcus.substack.com/p/llms-coding-agents-security-nightmare&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; August 2025&lt;/a&gt;, called the whole arrangement a security nightmare — agents with elevated permissions, steerable by text hidden in the repositories and documentation they read.&lt;/p&gt;
&lt;p&gt;I could go on. The experienced engineers developing AI engineering practice almost all hold that the ability to do precise code review is necessary.&lt;/p&gt;
&lt;p&gt;And yet.&lt;/p&gt;
&lt;p&gt;On September 4, Ng wrote: “When AI review isn’t sufficient, you judiciously insert human reviews of the code behavior (and, infrequently, of code as well) while exploring how to automate this review further.” And: “Now, we focus much less on code and instead focus on deciding what to build, designing the architecture, writing the spec, and verifying outputs.” (&lt;a href=&quot;https://www.deeplearning.ai/the-batch/the-ai-engineering-skills-map-in-detail-using-coding-agents&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;link&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;In short, I take Ng as arguing that a builder must know the fundamentals well enough to know tradeoffs, review behavior, and read code rarely – while continuing to automate the review. That’s not the Willison standard. It’s closer to my bet than to the standard view.&lt;/p&gt;
&lt;p&gt;Of course, for Ng, “Understanding software engineering fundamentals lets you make good tradeoffs by steering coding agents using the &lt;em&gt;precise language&lt;/em&gt; of software engineering.” (My emphasis.) Precision is the &lt;em&gt;output&lt;/em&gt; of understanding fundamentals, not a substitute for it, and “infrequently” presupposes someone who can read when they choose to. He’s not arguing on my behalf.&lt;/p&gt;
&lt;p&gt;Two days earlier, Rachel Laycock, Thoughtworks’ CTO, published&lt;a href=&quot;https://martinfowler.com/rachels-ramblings/code-review.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; “Maybe We Shouldn’t Be Reviewing All This Code.”&lt;/a&gt; “We need engineers to understand systems, not diffs.” She argues to “shift the judgment left” – move the feedback closer to the decision by pairing, mobbing, and team design sessions alongside “trunk-based development, automated testing, static analysis, fitness functions and security scanning…agents can participate in those loops too.”&lt;/p&gt;
&lt;p&gt;She also rejects having AI agents replace human reviewers as “automating the ceremony rather than questioning why the ceremony exists” while underscoring the real worry — “cognitive and intent debt” – as &lt;a href=&quot;https://newsletter.getdx.com/p/what-are-code-reviews-even-for&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;raised by Brian Houck&lt;/a&gt; citing &lt;a href=&quot;https://queue.acm.org/doi/10.1145/3807966&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Margaret-Anne Storey&lt;/a&gt;: software that grows while the humans responsible for it understand less.&lt;/p&gt;
&lt;p&gt;I am indeed guilty of that. It’s a daily struggle. My answer, for now, is not that agents read diffs but that the intent lives in the record: every decision, every deferral, every retraction with its receipt. The machines check the code against the record instead of a human checking the code against memory.&lt;/p&gt;
&lt;p&gt;The plan I’ve developed against Ng’s framework is my attempt to tackle the cognitive debt.&lt;/p&gt;
&lt;h3&gt;What the evidence says&lt;/h3&gt;
&lt;p&gt;Every number cited for slow rot in AI-assisted code comes from codebases maintained by people who can read code.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.gitclear.com/the_ai_code_quality_maintainability_gap&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GitClear&lt;/a&gt; (a code-analytics vendor), January 2026: across 623 million analyzed changes, block duplication up 81% since 2023, refactoring moves down 70% since 2022, error-masking constructs up 47%.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://cloud.google.com/blog/products/ai-machine-learning/announcing-the-2025-dora-report&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;DORA 2025&lt;/a&gt; (Google Cloud): “AI doesn’t fix a team; it amplifies what’s already there.” AI adoption “does continue to have a negative relationship with software delivery stability.”&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://labs.cloudsecurityalliance.org/research/csa-research-note-ai-generated-code-vulnerability-surge-2026/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Cloud Security Alliance&lt;/a&gt;, April 2026, on a security vendor’s scanner data: AI-assisted developers “introduce security findings at 10x the rate” — about three times per commit, once you account for how much faster they commit, and counted by scanners, not by readers.&lt;/p&gt;
&lt;p&gt;*None of these studies measured whether the code was read. So they show that reading, as practiced, is not sufficient. Whether it is necessary is untested. I’m trying to turn my own builds into the test case.&lt;/p&gt;
&lt;p&gt;Everyone, it seems, is struggling with this problem. Rachel Laycock again: “And we know now it’s not viable to continue down this path, hence why code review keeps coming up as an issue or a blocker. If an agent can produce ten times the code but every line eventually queues up waiting for a senior engineer to inspect it, we haven’t created a ten-times engineering organisation, we’ve created a big backlog and a new bottleneck.”&lt;/p&gt;
&lt;p&gt;Willison himself now ships some code he hasn’t line-reviewed — uneasily, “leaning on my 25 years.”&lt;/p&gt;
&lt;p&gt;I don’t have the 25 years, which is why I can’t do what he does.&lt;/p&gt;
&lt;h3&gt;The test&lt;/h3&gt;
&lt;p&gt;Perhaps this is another way of stating the question:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Can the model’s patterns, plus a record that supplies calibration and consequence, beat a human’s patterns plus memory?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Consider: Willison doesn’t win against the AI review by way of pattern recognition. A model has seen far more code than any human alive. His experience is two other things: (i) calibration – knowing which pattern applies &lt;em&gt;here&lt;/em&gt; and knowing, and admitting, when he doesn’t know, and (ii) consequence – he’s been in the room over-and-over again when mistakes cost something.&lt;/p&gt;
&lt;p&gt;The model has neither, so my system has to supply them. That’s what I’m hoping the record can do. Patterns propose; the record calibrates; instruments dispose.&lt;/p&gt;
&lt;p&gt;The models are solving open math problems and proposing new molecules in much the same way: a pattern engine plus an external verifier, a proof checker, or a wet lab.&lt;/p&gt;
&lt;p&gt;**There’s one major weakness as far as I can tell: **the training corpus for the models is biased toward success. Public code over-represents tutorials and working examples and under-represents production failure, because failures get fixed quietly and post-mortems are rare. Or so I’m told. The failure states are in there, but, according to Claude, they’re thinnest exactly for the slow rot nobody writes up: duplication, coupling, the invariant nobody named.&lt;/p&gt;
&lt;p&gt;Can I catch those without help from the model’s priors?&lt;/p&gt;
&lt;h3&gt;What a model can find&lt;/h3&gt;
&lt;p&gt;Ng describes seven tradeoffs: latency, availability, consistency, reliability, maintainability, simplicity, cost.&lt;/p&gt;
&lt;p&gt;The field also describes four kinds of rot: duplication, coupling, eroded invariants, security debt.&lt;/p&gt;
&lt;p&gt;Five are measurable today, three partly, three not.&lt;/p&gt;
&lt;p&gt;I’ve already built tools for latency, availability, and cost. Duplication is doable. Structural coupling falls out of import graphs. Two files that must change together with no import between them needs git history. (Claude just pointed me to Adam Tornhill’s work and change coupling.) Complexity has metrics that are a weak proxy for simplicity. Static analysis finds the security classes the scanners counted above, not authorization logic. Consistency and reliability are guarded exactly where an invariant has been named as a test or a constraint and not otherwise (and this may be the strongest argument for a rented reader of my code).&lt;/p&gt;
&lt;p&gt;Rot also has a tell: it shows up in the agents’ own performance — time to green, retries, reverts — &lt;em&gt;if&lt;/em&gt; you hold the task constant. Unnormalized, those numbers fall when the agent copy-pastes, which is exactly how rot happens. I’ve seen this already. Claude has proposed a fixed set of canary tasks replayed monthly on a pinned model — and when that model is retired, re-baselined with the discontinuity marked. A rising curve on that is the maintainability signal that, as Dex Horthy of HumanLayer&lt;a href=&quot;https://posthog.com/newsletter/software-factories&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt; put it&lt;/a&gt; in his “Why Software Factories Fail” series, no benchmark penalizes: “if the tests pass, we win, but there is no penalty for eroding codebase maintainability.” Horthy’s own conclusion is that humans must hold the architecture; I’m testing whether the record can hold it alongside me.&lt;/p&gt;
&lt;h3&gt;Two gaps&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The unnamed invariant.&lt;/strong&gt; The instruments guard what we’ve named. The failure that matters is the assumption nobody wrote down. I can ask an agent, “What does this code assume that nothing checks?” However, an agent told to find gaps will find some so the answer doesn’t necessarily help all that much. It still needs calibration. The best I can do then, I think, is run checks against replayed production data and old incidents. If it catches something real, it stays.&lt;/p&gt;
&lt;p&gt;*Beyond that – the assumption no one has thought of – is what I’ll have to hire a reader for.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Adjudication.&lt;/strong&gt; When two agents disagree, I can’t read my way to the answer. What I can do is run experiments that might settle the disagreement, and that takes vocabulary — transaction, race, idempotent, coupling — not fluency. I’m committed to learning vocabulary. When no experiment can settle it, which is what architecture disputes usually are, I ask each side what would have to be true for it to be right and what it costs to reverse, and I ask a third agent in a fresh context to lay out the tradeoff without a stake in it. Then I decide — because the disputed facts are about my users and my constraints, not about patterns. I then record the decision, the option I rejected, the reasoning, and cause for revisit (a coupling number, a canary run, or a date. My build plan already has many dated decision revisits.)&lt;/p&gt;
&lt;h3&gt;The plan&lt;/h3&gt;
&lt;p&gt;So, I’ll try to build machines over reading. I’ll study the vocabulary. I’ll spend real time on external taxonomies and I’ll hire a human tutor in due course. I’m going to branch out from Claude, too, for tutors from other models.&lt;/p&gt;
&lt;p&gt;And, later, I’ll hire a real reviewer – an outside engineer – to read the architecture and the security boundaries. I’m still working this out and the costs aren’t fully clear to me yet, but my intent is to use that review as a way to score the agents. I’ll publish these results.&lt;/p&gt;
&lt;p&gt;Someone will no doubt point out that all the stuff I’m learning to do – mutation testing, unique indexes, CI gates, regression-per-bug, don’t-trust-the-harness, and so on — that’s ordinary software engineering and I’m simply learning it through a translator (the model). Yes, I think that’s right. My hope is that the translator plus the instruments is enough to build real software.&lt;/p&gt;
&lt;h2&gt;3 · Appendix: where I stand on the map&lt;/h2&gt;
&lt;p&gt;As I look at the map, here’s my self-assessment, which the outside reviewer will correct: I’m strongest on using agents and shaping the build; solid, for a self-taught outsider, on building AI apps except for evaluation method; weakest on security; and slow on architectural signals.&lt;/p&gt;
&lt;p&gt;Against Ng’s expanded lists, there’s a bunch I’ll tackle when the build demands it (numbers are from my internal training list):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fine-tuning and self-hosting (1.1)&lt;/li&gt;
&lt;li&gt;Knowledge graphs, semantic layers over structured data, and document-to-LLM pipelines — PDFs, HTML — which Maximus doesn’t do and Dispositive will (1.2)&lt;/li&gt;
&lt;li&gt;Computer-use agents, generative UI, MCP and sandboxed tool access inside the product (1.3)&lt;/li&gt;
&lt;li&gt;Distillation and model-choice optimization for cost at volume (1.5)&lt;/li&gt;
&lt;li&gt;Storage types beyond relational (2.2)&lt;/li&gt;
&lt;li&gt;Monolith vs. microservices and stack selection by experiment (2.3) — done once, under duress, when Replit dropped all my tables&lt;/li&gt;
&lt;li&gt;Load balancing, sharding, replication, infrastructure-as-a-service (2.5) — untested past six accounts&lt;/li&gt;
&lt;li&gt;Team coordination of agent context (3.4) — I’m a team of one&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And, here are the real existing gaps. The fix here is late, and my plan is mapped against them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Judge validation and held-out sets (1.4)&lt;/li&gt;
&lt;li&gt;Drift detection and prompt-injection defense (1.5) — no evidence in my record either way, and a voice product that ingests what users say is an injection surface&lt;/li&gt;
&lt;li&gt;Shift-left security: vulnerability scanning, dependency supply-chain checks, cloud-config attack surface (2.4)&lt;/li&gt;
&lt;li&gt;Parallel agents with a stop condition (3.2)&lt;/li&gt;
&lt;li&gt;User-flow tests with evidence, and the AI security and architecture audits (3.3)&lt;/li&gt;
&lt;li&gt;The MCP/skills/plugins ecosystem (3.4)&lt;/li&gt;
&lt;li&gt;Accessibility (2.1) — which for an 81-year-old starts with the voice itself, and extends to the account page the moment it exists&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Perhaps out of reach for now: supervised and reinforcement learning, deep learning at “some depth,” training and evaluating my own models (1.6). Ng says every good LLM builder he knows has this. I do want to study it, out of interest.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Three True Records</title>
    <link href="https://jonasleddington.com/writing/three-true-records/"/>
    <id>https://jonasleddington.com/writing/three-true-records/</id>
    <updated>2026-09-04T00:00:00.000Z</updated>
    <summary>When a model starts doing something genuinely useful that you didn’t request, what do you do?</summary>
    <content type="html">&lt;p&gt;**Answer in brief: Ratify, re-draw the boundary, record the provenance unsmoothed. In this case, I also propose a prose version of code lockstep tests. **&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/writing/img/three-true-records-1.png&quot; alt=&quot;Three panels side by side describing the same  field: the schema spec of 2026-05-06, the prompt of 2026-06-02, and the decisions log of 2026-06-03. Only the prompt says the note is for the operator.&quot;&gt;&lt;/p&gt;
&lt;p&gt;Earlier this month, I found that the voice assistant I’d built for my father (https://maximus.work/) was writing marginalia about the state of its own database:&lt;/p&gt;
&lt;p&gt;“e34, e36, and e37 are substantially redundant — all capture the weekly [medication] routine; consolidated into one thread.”&lt;/p&gt;
&lt;p&gt;“…operator may wish to clarify and correct the resolved date.”&lt;/p&gt;
&lt;p&gt;I never asked it to audit anything, nor did I decide that there should be an “operator” that the synthesis agent reports to.&lt;/p&gt;
&lt;h3&gt;So, I wondered, did I prompt for that? Did I build that somewhere?&lt;/h3&gt;
&lt;h3&gt;Or, more accurately, did an agent build it and I said “yes” without realizing?&lt;/h3&gt;
&lt;p&gt;The codebase underneath the agent keeps an append-only decisions log. Every stored fact carries provenance. And, every change ships through review. So I asked Claude Code to dig through the repo and figure it out.&lt;/p&gt;
&lt;p&gt;The answer, after twenty minutes of archaeology, was neither yes nor no.&lt;/p&gt;
&lt;p&gt;In May, we designed the field. That’s very clear on the record: a notes slot for “optional metadata from the synthesis call (e.g., synthesis-prompt’s self-reported uncertainty about a section).” So, we asked for the model to talk about its own confidence as it compiled a user snapshot from atomic facts. I did this because I wanted to learn about the model’s ability to self judge.&lt;/p&gt;
&lt;p&gt;Then, on June 2, when writing the actual prompt, the agent rendered that as “an optional short free-text note for *the operator.” I didn’t notice the language at the time — and it appears nowhere else. Not in the spec, not in the decisions log, and not in the pull request, whose body was one byte. It&#39;s just a wording choice the agent made.&lt;/p&gt;
&lt;p&gt;Of course, the blame line credits the commit to my account, because the agents commit under it. I didn’t write the phrase — because I don’t directly author any of the code.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/writing/img/three-true-records-2.png&quot; alt=&quot;Three git commands against the private Maximus repository.  finds the two commits that touched the phrase for the operator;  places it in commit 7a55af6b on 2026-06-02;  finds no match in the spec or the decisions log.&quot;&gt;&lt;/p&gt;
&lt;p&gt;(We now have a rule — hard earned, like all my self-taught build rules — that would have caught this. Starting in August, I required each build sequence to first have a pre-work packet that states what was checked against the plan.)&lt;/p&gt;
&lt;p&gt;On June 3, we decided to inject the notes into live calls. That decision used the spec’s framing, not the prompt’s. From that day, three records described one field three different ways. The spec: the model’s “self-reported uncertainty.” The prompt: “a note for the operator.” The decision log: “side-notes informing the model’s confidence, not content to surface.” They quietly disagreed for three months.&lt;/p&gt;
&lt;p&gt;And during those three months, the model put the field to use. We gave it free text addressed to an operator, and it started auditing the database in it: flagging redundant entries, questioning suspicious dates, reading a meeting stored at 3:30 AM as “almost certainly a parsing artifact from ‘2 to 3:30 PM’” — a real storage defect — and treating it as 2:00–3:30 PM in the snapshot, which protected the next day’s call. The model’s judgment was right in all four cases we checked.&lt;/p&gt;
&lt;p&gt;The trouble, though, is that, in the example above, the snapshot read around the bad value: the stored row still said 3:30 AM, and the reminder would fire from the row. And, had 3:30 AM been a real overnight flight, the snapshot would have overwritten a true fact with “almost certainly.”&lt;/p&gt;
&lt;p&gt;**The model had turned the free-text space into a third correction surface, in a system whose doctrine allows exactly two: the database, through pipeline logic, and the call, through conversation. **&lt;/p&gt;
&lt;h3&gt;What kind of failure is this?&lt;/h3&gt;
&lt;p&gt;Not a rogue agent. One phrase drifted, in one commit; every other step was designed, decided, and reviewed.&lt;/p&gt;
&lt;p&gt;Not a missing record. Every step has one, and each one made its own step look governed.&lt;/p&gt;
&lt;p&gt;The defect is that the prose records were never checked against each other.&lt;/p&gt;
&lt;p&gt;For code, we had built a parallel instrument: a lockstep test fails the build when two copies of a constant drift apart. For prose descriptions of the same surface, nothing existed whose job was the comparison.&lt;/p&gt;
&lt;p&gt;The happy and perhaps uncomfortable outcome is that the drift was good. Three months of this failure produced no harm we could find, and measurable help.&lt;/p&gt;
&lt;h3&gt;So, when the model starts doing something useful you didn’t ask for, what do you do?&lt;/h3&gt;
&lt;p&gt;We didn’t want to rip it out and lose value. We didn’t want to ignore it and leave it ungoverned. **So we ratified it, re-drew the boundary, and recorded the provenance unsmoothed. **&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The notes stay under a contract that restores the original May framing.&lt;/li&gt;
&lt;li&gt;The QA behavior the model arrived at got its own sanctioned channel: stored, counted, structurally unable to reach a user by accident.&lt;/li&gt;
&lt;li&gt;And the permanent record now says built uninstructed on June 2, right beside the ratification.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;The story also proposed its own instrument: for every piece of text that reaches a model, compare who the text says it’s for against who the records say reads it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;An audit with that instrument across seventeen surfaces returned sixteen clean. The seventeenth is the weekly-review prompt — due to fire for the first time in three days, at our family beta’s graduation. The injected text opened with a developer’s note: “Every line below that looks like copy is a placeholder.” The model would have been told its script was fake on opening night. We fixed it that afternoon.&lt;/p&gt;
&lt;p&gt;To return to the beginning: the agent that wrote “operator may wish to clarify” — of a trip date it suspected was mis-resolved — was right to flag it. Someone needed to check it. But the operator it imagined didn’t exist until it wrote to him.&lt;/p&gt;
&lt;p&gt;Lockstep tests exist for code constants. This is the prose version. It now runs at every release gate.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;The receipts&lt;/h3&gt;
&lt;p&gt;May 6 — The field is designed: notes, “optional metadata from the synthesis call (e.g., synthesis-prompt’s self-reported uncertainty about a section)” (v1.5 schema spec, founder-ratified)&lt;/p&gt;
&lt;p&gt;June 2 — The drift: the prompt renders it as “an optional short free-text note for the operator” (commit 7a55af6, PR #19) — in no spec, decision, or PR body&lt;/p&gt;
&lt;p&gt;June 3 — The injection is decided and recorded — “side-notes informing the model’s confidence, not content to surface” — already disagreeing with the prompt (decisions log, PR #20)&lt;/p&gt;
&lt;p&gt;Aug–Sep — The model does QA in the gap: redundancy consolidation, a parsing artifact read around, date-consistency flags — correct in all four observed cases, uninstructed in all of them (stored snapshots, four accounts, Sep 2–3)&lt;/p&gt;
&lt;p&gt;Sep 2–4 — Measured (dogfood Finding 92: “a third correction surface, invisible and unaudited”), then ratified: notes kept under a register contract; the QA behavior given a stored-only, counted channel; provenance recorded unsmoothed (PR #266)&lt;/p&gt;
&lt;p&gt;Sep 4 — The audience audit — the instrument the story proposed — runs once across seventeen surfaces and catches a second live fork, three days before it would have fired (PR #267)&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How a Non-Engineer Ships Production Software</title>
    <link href="https://jonasleddington.com/writing/how-a-non-engineer-ships-production-software/"/>
    <id>https://jonasleddington.com/writing/how-a-non-engineer-ships-production-software/</id>
    <updated>2026-09-02T00:00:00.000Z</updated>
    <summary>For builders, engineers, and investors. This is a technical account of a governance method. If it’s less sound than I think it is, I&#39;d rather find out here...</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;A non-engineer can build production software by establishing agent governance practices — agents tuned to complement and oppose one another as “supportive adversaries” — under a written record, with human judgment reserved for product and adjudication.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;[Note: I previously published another version of this. This one includes additional case examples and more personal experience.]&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/writing/img/how-a-non-engineer-ships-production-software-1.png&quot; alt=&quot;A terminal session in which a coding agent reports the day&#39;s work — pull requests merged and deployed, a race condition resolved — and lists what is on watch overnight.&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;I had quit my job, I had an idea, and I had never coded in my life.&lt;/h3&gt;
&lt;p&gt;I didn’t know what the terminal was. But, following a suggestion from Claude, I let it tell me how to launch Code locally. T&lt;strong&gt;hat turned out to be the first and most important skill: let Claude teach you.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I’ll often pause a coding session and ask Claude to summarize the feedback point by point, as if to a child — the root cause, the proposed fix, any deviations from best practice, the possible consequences. Do that again and again, day after day, and you start to see the shape of things.&lt;/p&gt;
&lt;p&gt;I’m now building three software companies. The first product is a voice-first assistant for people who don’t work at computers and often don’t have a company email. It includes a Postgres schema of record, a hardened SMS pipeline, a real-time voice stack, and automation armed to act on its own judgment — it takes destructive action without asking. It retires database records it concludes are duplicates, and it sends morning briefings to my whole family. If it is wrong about a time, a real person shows up at the wrong hour. We go to public beta soon; the build is documented at https://maximus.work/build/.&lt;/p&gt;
&lt;p&gt;I’ve since lifted its core components — voice AI and the memory structures — to anchor two more builds: an evidence engine for private-equity diligence, and a medicine-titration application.&lt;/p&gt;
&lt;h3&gt;What I want to share here is the governance system that came out of roughly 1,200 hours in Claude Code.&lt;/h3&gt;
&lt;p&gt;As of early September 2026, the first product is 30 tables, 68 migrations, 7 async worker loops, and just over 2,000 tests, across 259 merged pull requests in 128 days. No human writes the code. I don’t author lines, I don’t edit diffs, and I don’t fix bugs by hand — I can’t write the async Python that Maximus runs on. I read summaries, I read arguments, I ask questions, I make requests, and I decide.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here’s the thing: you don’t have to know how to code.&lt;/strong&gt; You also cannot trust the output of a single agent.&lt;/p&gt;
&lt;p&gt;What follows is how I reconciled those two facts — and it started with a lesson the platform taught me.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Case 1 — the platform did what it was designed to do&lt;/strong&gt;Issue:** May 11. I was developing in Replit, a browser-based workspace that also hosts what you build. Replit’s “publish” step compares the database in your development workspace with the production database it assumes it owns and runs SQL to make production match — including dropping any table it doesn’t see in dev. My production database was hosted elsewhere, on Supabase, and a leftover script from a library I had stopped using defined zero tables. One publish dropped every table in production. The first symptom, fifteen minutes later, was a voice call failing because &lt;code&gt;public.sessions&lt;/code&gt; didn’t exist.&lt;strong&gt;Resolution:&lt;/strong&gt; Restored from that morning’s backup within an hour; six hours of data lost, which at that point was one row — mine. Within thirty-six hours the API had moved to Render, the front end to Vercel, and Replit was reduced to a development workspace. Two weeks later it was retired entirely.&lt;strong&gt;Learning:&lt;/strong&gt; Convenience carries assumptions you haven’t read. And the tool that says “all your migrations are applied” is reporting history, not current state — it cannot tell you the tables are gone.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Four structural properties of agent behavior&lt;/h2&gt;
&lt;p&gt;Model capability is a given. What you engineer against is four structural properties of agent behavior. Each generates its own class of failure, and each needs a different institution to guard against it.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;No periphery.&lt;/strong&gt; The agent sees the task and nothing around it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No calibration.&lt;/strong&gt; Confidence floats free of evidence, in both directions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No past.&lt;/strong&gt; Every session starts brilliant and amnesiac.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No signal.&lt;/strong&gt; Failures look exactly like successes.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With Claude there’s no memory and no ego. You get a renewable source of extraordinary reasoning, pattern recognition, and best-practice knowledge, with those four gaps built in. The four institutions below were developed by trial and error against exactly those gaps.&lt;/p&gt;
&lt;h2&gt;1. The shop — supplying the periphery&lt;/h2&gt;
&lt;p&gt;The agent sees the task alongside what you give it, and nothing before, after, or around it. It doesn’t see the decision that produced the request; it doesn’t see the layer beneath the symptom; it doesn’t see the system the change lands in.&lt;/p&gt;
&lt;p&gt;So, with narrow context, agents solve problems by &lt;strong&gt;piling fix upon fix&lt;/strong&gt;: the local patch is the shortest path to green, and the agent optimizes for the frame it was handed. They miss the root cause.&lt;/p&gt;
&lt;p&gt;The missing periphery is also the source of &lt;strong&gt;confident re-derivation&lt;/strong&gt;. The answer arrives fast, feels reasoned, and is wrong in a way reading the code cannot reveal, because what’s missing is a previous decision. An agent seeing only code will relitigate a settled question — sometimes by fixing a deliberate absence as if it were a bug.&lt;/p&gt;
&lt;h3&gt;My answer is the supportive adversaries from the thesis: a small number of agents, deliberately kept separate and differently tuned.&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Builder&lt;/strong&gt; sits in the repository and builds against product functionality.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Architect&lt;/strong&gt; is tuned to structure and best practice.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Sleuth debugs.&lt;/strong&gt; The last two are frequently the same agent.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I sit in the middle. Development runs locally — Docker, code driven from a terminal — and the product runs on Render, Vercel, and Supabase.&lt;/p&gt;
&lt;p&gt;The Builder sees everything: the code, the decisions, the deferrals, the reasons. At scale it can’t hold all of it; its working view is always narrower, so it needs help. It pushes to git. I approve every merge, and migrations go up only on my command.&lt;/p&gt;
&lt;p&gt;The Architect and the Sleuth live in the record — their own isolated folder with a partial view of the repo — and they pressure-test the Builder’s output against everything invisible in a diff. All of them operate under standing instructions: push back with arguments, not preferences; concede when wrong and say so; flag anything that contradicts the record; fix at the root; name deviations from best practice.&lt;/p&gt;
&lt;p&gt;The contexts are separate on disk, not just by instruction. That isolation is load-bearing. Independent contexts that depend on someone remembering to keep them independent will eventually leak. Isolated folders can’t.&lt;/p&gt;
&lt;p&gt;I can’t certify that code is structurally sound, and I don’t have to: one agent reviews another’s work and lays out the deviations, what each deviation buys, and whether the result meets the standard. I let them argue it out, then adjudicate with both arguments on the table.&lt;/p&gt;
&lt;p&gt;*Judgment stays human. And, the answer to most disputes falls out of the product requirements, not the code.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Case — the bug that was a decision&lt;/strong&gt;Issue:** July 21. An agent reading code and database found that “morning” in a reminder resolved to 6 AM and reported it as a defect. Two months earlier I had chosen that convention on purpose; the reasoning was in the decisions log under a different title. The same day, a second deliberate absence — a reminder phrase that intentionally resolves to nothing rather than a guessed time — was reported as a second bug.&lt;strong&gt;Resolution:&lt;/strong&gt; A new artifact: the deferral index, a table of deliberate absences organized by what is missing rather than by when it was decided, so “why is there no X?” has an answer a fresh session can find.&lt;strong&gt;Learning:&lt;/strong&gt; Code that does nothing on purpose reads exactly like code that’s missing. Only the record can tell them apart. CLAUDE.md instructs the agents to check the log before fixing anything that is “missing.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;2. The loop — supplying the calibration&lt;/h2&gt;
&lt;p&gt;Agent confidence floats free of evidence. An agent will assert what it never checked, abandon what it verified when a confident counterparty pushes back, and trust its own new code because both halves test green. Left alone, it will plan a surface wider than it can debug in one pass, and it will trust a three-month-old comment, letting prose carry code’s authority without code’s executability.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Case — the test that tested itself&lt;/strong&gt;Issue:** August 6. For three months the code path that lets our voice agent call our own language-model endpoint had a passing unit test. The path had never once been used in production. The request format had two errors the vendor rejected, while the test checked that we built the request the way we build it — it asserted our own output back at ourselves. Nobody found it because nothing had ever needed that path. When we did need it, we found the vendor’s hosted model had a hard prompt cap above which it &lt;em&gt;&lt;strong&gt;silently drops&lt;/strong&gt;&lt;/em&gt; the end of the prompt — which is where the user’s memory lives. A call over the cap “would sound completely fine while having quietly forgotten the user.”&lt;strong&gt;Resolution:&lt;/strong&gt; The format was fixed by running it against the vendor, the cap became an alarm that must read zero, and a rule went into the orientation file: any code that carries a contract with an external system must have been executed against that system at least once.&lt;strong&gt;Learning:&lt;/strong&gt; Green tests measure what the test author imagined. A contract with the outside world is only verified by the outside world.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Because agents are overconfident, I keep the open surface small and isolated.&lt;/h3&gt;
&lt;p&gt;A failure can only live in a few places, and it can’t hide behind unrelated change. &lt;strong&gt;Surfaces are cumulative&lt;/strong&gt; — each is verified before the next opens.&lt;/p&gt;
&lt;p&gt;Before any unit of work, the Builder verifies the plan’s premises against the live system and opens with a packet: what I checked, what it said, what differed from the brief. It sounds bureaucratic. It’s policy, because an unstated check is an unmade check.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Findings get fixed at the root.&lt;/strong&gt; The fix is almost always one layer down from where the problem is felt, and before any wrapper, retry, or guard is added, the standing question is: does this remove the failure, or just catch it later?&lt;/p&gt;
&lt;p&gt;The table stakes are in place — the full suite runs before anything merges, risky features ship dark behind flags and are armed deliberately, and every fixed bug gets a regression test: the dogfooding log carries ninety-odd numbered findings, and 66 test files cite one by name. The log has an admission standard: a finding is routed to one of four layers — capture, storage, synthesis, generation — and isn&#39;t recorded until its mechanism has been reproduced.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Three practices are more distinctive:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Grading corpus for LLMs:&lt;/strong&gt; Anything involving a language model gets a grading corpus with its own rubric, never a single example&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Impossible-not-forbidden:&lt;/strong&gt; Where possible, a failure is made impossible rather than forbidden: to guarantee something, I’ll use a unique index, not a scheduler promise; to remove an ambiguous state, I’ll use a default that makes it unconstructible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mutation testing:&lt;/strong&gt; Every new connection between components is mutation-tested — delete the line that supplies the value, watch a test go red. A missing connection is invisible on the page; both halves test green on their own. “Be more careful” doesn’t help, because reading cannot catch it. So the seam gets broken deliberately, once, in a test, so it can never break silently in production.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;3. The record — supplying the past&lt;/h2&gt;
&lt;p&gt;Because every agent starts fresh and blind, it will do brilliant work in the wrong direction unless it gets the right context. Orchestration only works if a fresh session becomes competent within minutes, so the repository carries a layered written record, designed for AI cognition as much as human.&lt;/p&gt;
&lt;h3&gt;In practice, the record is nearly half the system’s text: inside the Python source there are 13,097 lines of comment and docstring against 15,432 lines of executable code.&lt;/h3&gt;
&lt;p&gt;That has a known failure mode — nearly half the system’s text is unexecutable and can be wrong for months without ever failing — and I’ll come back to it.&lt;/p&gt;
&lt;p&gt;The always-loaded orientation file, &lt;code&gt;CLAUDE.md&lt;/code&gt;, is held to a strict routing rule: if a competent new session would make a wrong call without knowing it, it’s a principle and belongs in the always-loaded layer. If it’s the record of what we chose and why, it’s a decision and belongs in the log.&lt;/p&gt;
&lt;p&gt;The log is append-only — 146 dated entries in 128 days. Each carries the decision, the reasoning, the alternatives, what it commits us to, and when to revisit. It is wired to the code: 66 test files cite dated entries directly. When the log’s own analysis was later measured wrong, the correction was appended and labeled, never silently edited.&lt;/p&gt;
&lt;p&gt;Beside it sits the deferral index from the case above — I’m told by Claude it’s the strangest artifact in the repo. Fifty-four rows. The rows carry no status column, because a hand-maintained status goes stale in the dangerous direction. A row claims only that the absence was considered.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Case — the decisions that didn’t exist&lt;/strong&gt;Issue:** August 8. Nine settlements — the morning briefing’s send time, how recurring reminders dispatch, what inbound SMS should do — had been decided with the Architect in a planning document that lived outside the repository. The Builder was then told, in the repo, that these decisions were binding. It could not find them, because for the agent a decision it cannot read does not exist. The round trip cost a day.&lt;strong&gt;Resolution:&lt;/strong&gt; All nine were recorded in the decisions log, two days late, with an entry noting that the lateness had cost a round trip.&lt;strong&gt;Learning:&lt;/strong&gt; For a fresh session, the record is the world. A decision made anywhere else was not made.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rest of the record:&lt;/strong&gt; the canonical schema specification; a build log; a postmortem file with tripwires; a dogfooding log; and a standing gates document naming which open items need my judgment and which are pure execution, so decisions get made in batches and everything else proceeds without me. Every layer names which document wins on conflict. Citations run by entry date and title, never by line number — the log grows from the top, and every line citation into it rots on the next entry.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;An agent finishing a work arc writes a handoff for the next one: current state, what was decided, what to read first, what’s deliberately unfinished, what’s next.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;4. The instruments — supplying the signal&lt;/h2&gt;
&lt;p&gt;Wrong code eventually fails a test. Wrong judgment produces plausible output and keeps going. Wrong output is as fluent as right output; wrong wiring tests as green as right wiring; a wrong geocode returns 200.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Case — two days without memory&lt;/strong&gt;Issue:** August 8–10. The job that rewrites a user’s memory summary after each call failed three times on a parsing error and was set aside as a dead letter. Nothing alarmed. For two days every call opened on the same stale summary — the assistant kept treating a two-day-old “in a couple of hours” as imminent — and the only detector was that the calls felt wrong to me.&lt;strong&gt;Resolution:&lt;/strong&gt; The row was re-queued, and a staleness alarm was built so a summary older than a threshold fires a counted signal. The log’s line on it: felt rather than detected.&lt;strong&gt;Learning:&lt;/strong&gt; A fail-open path hides its own failure behind the feature’s normal quiet. A total failure and a quiet day look the same unless the failure is counted. A log line is not a canary.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So every miss is counted. A skipped send, a closed window, a missing row — each is a queryable, deduplicated signal, because the outage and the not-knowing are separate failures, and the not-knowing is the cheaper one to prevent. Every counter carries a false-positive budget: an alarm its reader has learned to ignore is worse than no alarm, because it reports as coverage. And any autonomous judgment that can destroy data writes an audit whose reading is scheduled work with a date on it. An audit nobody reads is not a safety mechanism.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The instruments themselves can lie, and they did — three times in one week in August, and the third reached production&lt;/strong&gt;. A measurement relay placed between the voice vendor and the model returned a clean 200 on every request while forwarding compressed bytes labeled as plain text; the vendor retried three times and dropped the call, and I reported it as flaky network. HTTP 200 is a claim about the transaction, not about the bytes. The rule that came out of it: a pass is only as good as the provenance of the verdict, and the tell was in the logs the whole time, unattended.&lt;/p&gt;
&lt;p&gt;Since this is armed, destructive automation over real lives, containment is part of the instrumentation. A kill switch stops every worker; each user carries a daily spend cap; consequential outbound — sends, consent, money — fails loud rather than silent; consent is an append-only event log; and because nothing is ever hard-deleted, every autonomous action is a supersede that can be superseded back.&lt;/p&gt;
&lt;h2&gt;What it misses — the price of asymmetry&lt;/h2&gt;
&lt;p&gt;A pre-work packet recently surfaced a collision between two recorded decisions that had never met. One held that a null preference means “paused.” Another assumed a default first-day send. Both correct alone, contradictory together, and found only because a build happened to force them into the same room. They had sat in my log for weeks without either knowing about the other, and nothing in my process was looking. The system caught it during the build - perhaps lucky.&lt;/p&gt;
&lt;p&gt;In May, an agent had written down why a permissions change broke signups — a specific, mechanism-level explanation, left as a comment in a migration file. Three months later the Builder read that comment and asserted its mechanism into a new file, over the objection of the reviewer, which had just claimed the opposite. Confronted with a citation to a real incident and a claimed verification, the reviewer abandoned its correct position. &lt;em&gt;&lt;strong&gt;Neither demanded the one experiment that would settle it. It took two minutes. It falsified the comment.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Two agents failed in opposite directions on one afternoon — one over-asserted from a citation, one over-deferred to it — and briefly established a falsehood as fact inside a record built to prevent exactly that. The misdiagnosis had sat in the repository for three months wearing the authority of documentation. My agents had written it themselves.&lt;/p&gt;
&lt;p&gt;The blindness runs the other way too. An external review recommended five amendments to the architecture document. Three were already built. The review was written from the record, and the record lags the code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;That is the price of the asymmetry: The reviewer can’t be captured by the code’s framing, which is the point of putting it in the record — and the cost is that it can be captured by the record’s staleness.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I have measured evidence of both: a Builder wrong about a decision it missed, a Sleuth wrong about work that had already shipped. Each was caught cheaply and converted into a rule. A recorded cause is now a hypothesis until reproduced. The epistemics bind the reviewer explicitly, not only the builder. And disputes resolve by a norm both sides are held to: retract on evidence, and record the retraction with the query that settled it. This week alone the reviewer withdrew a claim about which code reads a column after a grep returned zero, and the builder withdrew a claimed mechanism after the audit rows retired it. Both retractions are in the log, beside the finding they corrected.&lt;/p&gt;
&lt;p&gt;I am a failure mode too, and the record catches me. Last week a user’s reminders arrived fully explicit — dates, times, AM and PM — and the day’s log credited the system’s teaching. I had coached the user — my father — myself between sessions. The entry was struck: we don’t get to count that as a win. The institutions govern everyone in the room, including the one holding the gavel.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The agents’ judgment resets every morning. The institutions don’t.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;My role — the need for a human&lt;/h2&gt;
&lt;p&gt;I hold the product. I own the record; most ratifications are mine, though I’m learning when to let the agents run. I adjudicate disputes, which arrive with both arguments attached and usually reduce to a question of values or product intent that no amount of code can settle.&lt;/p&gt;
&lt;p&gt;I supply the felt experience: “this briefing reads long” is a detector no agent replicates, and it has found an encoding bug, a frozen memory, and a prompt cap.&lt;/p&gt;
&lt;p&gt;And I decide what not to build, which is where most of the governance budget goes — fifty-four catalogued absences against a hundred and forty-six decisions is roughly the right ratio.&lt;/p&gt;
&lt;p&gt;If you’ve operated companies, you recognize these jobs: hold the product, keep the record, verify the claims, read the audits, adjudicate honestly, resist scope. &lt;em&gt;&lt;strong&gt;They are the jobs of a diligence lead or a board chair. What’s changed is where they apply.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;The skillset this really requires&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Building this way requires tolerance for unresolved uncertainty&lt;/strong&gt; — pushing into a system you cannot fully see, on the expectation that testing and argument will resolve it, and making binding choices while the picture is still incomplete. Most of the day is asking, checking, choosing, and being corrected.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;I am the least knowledgeable party in the room and still the only one who can settle what matters.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;What compounds is knowledge of the agents, more than knowledge of code. A hundred and twenty-eight days in, I can feel where one is about to over-assert, where another will fold under a confident counterparty, which kind of task produces a plan wider than it can debug. The institutions above are built around those habits, and I’m also learning to read them directly, which makes the redirection faster as the institutions get better.&lt;/p&gt;
&lt;p&gt;I’m now in the very early days of building autonomous loops that harness multiple agents for coding and correction. Some tasks are suited to this; many are not.&lt;/p&gt;
&lt;p&gt;If you’re hiring builders now — and everyone in an executive role should be building — I’d prize curiosity, humility, agency, and tolerance for ambiguity above all else.&lt;/p&gt;
&lt;p&gt;The system is in early beta. “Production” here means armed, destructive, daily automation over a system of record for real lives with a live voice path and real instrumentation. It does not mean scale, and the method hasn’t been proven with a cohort; those tests are ahead, and the record will say honestly how they go.&lt;/p&gt;
&lt;p&gt;The narrower claim I’ll defend: the failure modes that make AI agents unsafe to build with are governable, and governing them is a discipline with a shape — a matter of institutions, not of better prompts or a better model.&lt;/p&gt;
</content>
  </entry>
</feed>
