# Nikhil Verma — CTO, AI & LLM Systems > CTO at The Non-Functional Co. Building AI compliance for regulated finance. Writing on LLM agent reliability, memory, and determinism. This file contains the full text of every blog post, newest first. # Passing taste to AI models > AI models write like an overly confident human who has never failed in life. These are the instructions, examples, checker loops, and code constraints I use to make them follow my taste, including where they still fail. Published: Jul 17, 2026 · https://nikhil-verma.com/blog/passing-taste-to-models/ If you meet someone and they have a slightly annoying way of talking, you barely notice. Talk to them every hour, every day, for a month... that tiny tic starts to feel like a cut. When you use AI models that often, their tics become super grating too. Each model has a certain smell in the way they communicate. My theory is that this comes from training models to succeed. There is no established evidence for it yet. Post-training, fine-tuning, and reinforcement learning reward successful-looking outputs and push the model away from failed ones. That leaves the shipped model very practiced at sounding right. Humans fuck up all the time. We carry those failures into the next attempt, and that is how we get good at things. A shipped model's weights are frozen, so it cannot fail for you today and become a better model tomorrow. It ends up sounding like an overly confident human being who has never failed in life: headstrong, charging into every problem, bluffing when it is not certain. Imparting taste to models is hard. I have not solved it, and I am suspicious of anyone who says they have. I use several techniques, and parts still fail. ## Where the smell comes from Think about how a human writes. You make notes, write a draft, and polish the shit out of it. You cut what does not belong, add what is missing, and keep going until it reads properly. A transformer emits one token, feeds the chain back through itself, and emits the next until the text ends. Thinking modes give it room to revise before answering, which helps. I still don't think that simulation is the same as carrying your own failed drafts into the next one. Wikipedia's editors maintain a page called [Signs of AI writing](https://en.wikipedia.org/wiki/Wikipedia:Signs_of_AI_writing), built from cleaning up thousands of AI-written edits. It lists words such as delve and tapestry, "not X, but Y" constructions, em-dashes everywhere, and inflated claims. A specific fact such as "inventor of the first train-coupling device" becomes "a revolutionary titan of industry."[^wiki] Their explanation is regression to the mean. The model picks language that could apply to the widest range of cases, so the writing becomes generic while the claims get bigger. I think that explains the generic smell, while training for successful-looking answers explains the confidence. One paper investigates why models say "delve" so much; a follow-up traces some word overuse to learning from human feedback.[^delve] ![Four differently shaped AI models produce the same orange form while a human compares their nearly identical work](/images/passing-taste-to-models/house-style.webp) Ordinary readers detect AI text at roughly coin-flip accuracy in controlled studies. Heavy LLM users reach around ninety percent.[^russell] After seeing the same constructions every day, you start spotting them everywhere. ## The mental model I use I picture an AI model as a headstrong person who does not learn. Once a model ships, the learning I can influence happens through its context window, which people call in-context learning. It struggles with that too. Dump a massive rant on somebody and say "follow all of this," and they will forget parts of it. Models do the same thing. ## Writing taste I start with a global instructions file. I use Claude Code, but other agent CLIs have their own version of this. Mine explains who I am and how I work. One of its most important instructions came from a repeated failure. I dictate almost everything because my typing never kept up with my thinking. Speech-to-text sometimes gets words wrong. The model used to take those words literally and run with them. I added an instruction that says this user dictates, work out the intended meaning from context, and ask when you still don't understand. I also give the maker and checker an 80/20 rule. Eighty percent of the finished post has to come from my words, usually from these dictated rants. The remaining twenty percent is organization: fixing typos and mistakes, formatting and laying out the post, bridging gaps, and finding references. The result sounds like me because most of it is me, while the AI does the time-consuming production work around it. Sparse instructions pull the model back towards its trained average. If you give it nothing, you get its usual style. Examples carry more taste than instructions, so I show it writing I like, writing I rejected, and the difference between them. Its next draft sounds more like me. I still have to correct it because the taste has to keep coming from me. I also name the tics. My writing skill has a growing list of banned patterns. Whenever the model produces one, I flag it and add the example to the rule. Then I ask the model to correct itself, update its instructions, and try again from a fresh context. No correction is guaranteed to stick. Its chance depends on the model and how I wrote the instruction. Some weeks after I banned the "not X, but Y" template, I found it on Wikipedia's list as one of the strongest tells. Hundreds of editors cleaning up AI text and one annoyed person dictating blog posts had found the same tic. I can also package a correction as a command. Dillon Mulroy has a three-line skill called `bro`: restate your last message, stop using jargon, and say it simply, like one human talking to another.[^bro] When an agent asks a dense engineering question, he invokes `bro` and gets the same question in plain speech. The larger stop-slop skill removes predictable filler across a whole response.[^stopslop] `bro` steers the model towards Dillon's voice, while stop-slop removes common filler and leaves the voice to you. Maker-checker is the most involved technique I use. One model writes with my style guide in its context. It does a reasonable job and still fucks up. A second model starts with fresh context and checks the work. Tell a model that its job is to find problems and it will find them, because finding them is how it succeeds. The best version would use models from different companies, with different training and biases, like bringing a different person into a review. Most single-vendor CLIs make that difficult. Pi allows each subagent to use a different provider.[^pi] In practice, I usually use the same provider for both. The fresh checker still catches things the maker missed. I have not measured how much a different provider would improve it. ![One robot makes an orange object while a fresh checker robot inspects it against a short list, with a human watching and three rounds marked between them](/images/passing-taste-to-models/maker-checker.webp) The checker also nitpicks things that don't matter. I ask it to rank findings by severity, and the maker only applies the high and critical ones. If the maker is unsure, it asks me. I cap the loop at about three rounds so the agents cannot keep correcting each other forever. I sit outside the loop and watch it... when it goes haywire, I step in. ## Coding taste Taste in code is the architectural choices you make while solving a problem. You can smash your head through a brick wall or hire a wrecking ball; both will give you an opening. Models will solve the same problem five different ways, so one of my first instructions is: don't reinvent patterns. Before introducing something new, grep the codebase because it probably already has a way to do this. ![One AI model smashes through a brick wall while another studies a plan for a clean opening made with a wrecking ball](/images/passing-taste-to-models/coding-taste.webp) Most coding conventions are implicit. Teams rarely write down the order of functions, constants, types, and exports in a file. A human reads the code and thinks, okay... this is how we do things here. A model does not reliably make that jump. I run a separate session that scans the codebase, finds those conventions, and adds them to the project's agent instructions. I also turn some preferences into code. I ask the model to write static checks, then run them after file changes or in CI. The preference still applies when nobody remembered to put it in the context. When the shape of a solution matters, I give it that shape upfront. I describe the classes and methods I expect, then add high-level pseudocode. The model does a better job because it has an outline and does not have to make up shit. When I use all of these, the model fucks up less. I still have to supply the taste and catch what gets through. ## Design, where I still lose Writing and code are easier for me to steer because I can give the model the instructions, examples, conventions, and checks as text. Design is where I still lose. Front-end skills, screenshots, and design systems have not fixed it completely. I was building an app and had a good design in my head. I described it through speech-to-text, the model built a UI from my words, and the result looked nothing like the picture. I did a bad job there. The picture in my head became a paragraph of dictated text, and that paragraph was all the model got. I found similar designs online, took screenshots, and gave them to the model as references. The result captured the essence of those designs, but it could not merge their intent with the thoughts and feelings I had in my head. The part that was mine never made it through. There are now tools aimed directly at this problem. The open-source Taste Skill reads the brief, sets controls for layout variation, motion, and density, then applies rules against common model defaults: purple gradients, centered heroes, repeated feature cards, and cards that serve no hierarchy.[^taste-skill] This is the design version of my banned writing patterns. Somebody notices the same failures, names them, and gives the model better instructions. Alex Kehr's Taste gets closer to personal taste. You save screenshots you like, and it extracts the colors, type, spacing, shapes, and composition into a profile. It also records designs you reject, and your ratings of generated screens feed into the next version of the profile. The profile can then travel into Codex or Claude as a skill or through MCP.[^taste-profile] This matches what I have found with writing: examples and rejected examples carry more than a paragraph of instructions. It also leaves my question open. A profile can record that I like rounded corners. Can it transfer why this corner feels cozy in this interface? That is the part I still don't know how to pass. Without references, GPT and Codex models keep giving me boxes inside boxes inside boxes. They show buttons that should only appear on hover and expose complexity that should stay hidden until somebody needs it. They choke on minimalism and progressive exposure. The tightest constraint is a design system where the model can only compose existing components. It sits at the far end of the [constraint spectrum](/blog/constraint-spectrum) I wrote about before. It can give me a correct UI that still lacks taste. Constraints alone have never given me a pleasant interface. Once I let the model get creative, I am back to hoping. ![A human imagines and evaluates an interface through sight and feeling, while a model generates a sequence of tokens ending in uncertainty](/images/passing-taste-to-models/human-and-model.webp) I think the failure comes from how humans design. A human can close their eyes and picture an interface that does not exist. Then they look at the screen and feel whether it matches. Your eyes move across the layout, you notice whether the lines align, and a rounded corner can feel cozy while a sharp one feels alert. The bouba/kiki experiment makes this visible. In the original study, 95% of participants called the rounded shape "bouba" and the spiky one "kiki." Later studies found the same bias across languages and in infants.[^bouba] Human senses mix together, and design taste uses that mixture. People with aphantasia cannot voluntarily picture an image in their mind.[^aphantasia] Ask them to imagine an apple and they see nothing. The models we use for design feel similar to me. I cannot know what happens inside them that corresponds to cozy or alert. I give them words and images, and they predict an output. The surprising part is that they produce reasonable designs at all. The banned-pattern skill I described above checked this draft. A separate checker then found places where the writing had turned "the model fucks up less" into "problem solved." A mistake becomes an instruction, and the instruction raises the chance that the model gets it right next time. It never removes the need for me to supply the taste. Design is where that gap is easiest to see. ## Addendum after a second human review A human read this again after the maker-checker loop finished and found more problems. Some sentences went further than what I knew. I had said model producers try to prevent a house style, and that similar interfaces prove a shared reinforcement-learning history. I cannot know either from the outside, so those claims came out. The checker did not always invent problems; more often it found real things that did not matter, so I changed that to nitpicking. I had also repeated conclusions and separated ideas that belonged together. I made those fixes by hand. I removed claims I could not support, narrowed claims based on my own experience, joined related sentences, and cut explanations that added nothing. The agents caught patterns because I told them which patterns to catch. I still had to read every sentence and decide whether it meant what I meant. --- [^wiki]: Wikipedia, [Signs of AI writing](https://en.wikipedia.org/wiki/Wikipedia:Signs_of_AI_writing). Worth reading in full, including its own caveats: the list is descriptive, humans are individually bad at this, and merely patching the surface signs makes detection harder without making the writing better. [^delve]: Juzek & Ward, [Why Does ChatGPT "Delve" So Much?](https://aclanthology.org/2025.coling-main.426.pdf) (COLING 2025), and their follow-up, [Word Overuse and Alignment in Large Language Models: The Influence of Learning from Human Feedback](https://arxiv.org/pdf/2508.01930). [^russell]: Russell, Karpinska & Iyyer, [People who frequently use ChatGPT for writing tasks are accurate and robust detectors of AI-generated text](https://aclanthology.org/2025.acl-long.267/) (ACL 2025). Casual readers perform near chance; heavy users reach roughly 90% accuracy. [^bro]: [Dillon Mulroy's `bro` skill](https://x.com/dillon_mulroy/status/2069948648381673809). The entire skill: "Restate your last message. Stop using jargon and speak coherently. State it more simply and concisely, like one human talking to another." [^stopslop]: [stop-slop](https://skillsllm.com/skill/stop-slop), a widely used skill that strips predictable AI writing patterns: filler, throat-clearing, emphasis crutches. [^pi]: [Pi](https://pi.dev/), an open agent harness supporting 15+ model providers; its [subagents extension](https://pi.dev/packages/pi-subagents) allows a per-agent model override, so a checker can run on a different provider than the maker. [^bouba]: The [bouba/kiki effect](https://en.wikipedia.org/wiki/Bouba/kiki_effect): Ramachandran & Hubbard (2001), building on Köhler's takete/maluma experiments from 1929. [^aphantasia]: [Aphantasia](https://en.wikipedia.org/wiki/Aphantasia): described by Francis Galton in 1880, named by Adam Zeman's team in 2015 after their study of patients unable to form voluntary mental images. [^taste-skill]: Leonxlnx, [Taste Skill](https://github.com/Leonxlnx/taste-skill). The current default skill reads the brief, adjusts design variance, motion, and visual density, and contains explicit rules against common AI interface patterns. [^taste-profile]: Alex Kehr, [Taste](https://www.alexkehr.com/projects/taste). It turns saved screenshots, rejected designs, and ratings into a versioned profile that exports to Claude and Codex skills or MCP. --- # The Constraint Spectrum: how the made earns the trust of the born > Generation is cheap now and verification is the bottleneck. A field guide to the constraints that make AI-written software trustworthy, at every phase of the SDLC you already know. Published: Jul 15, 2026 · https://nikhil-verma.com/blog/constraint-spectrum/ In the past year my team shipped software written almost entirely by AI agents. We shipped plenty of bad features, and some code I'm not proud of, but so far nothing the agents wrote has taken production down. Some of that is luck. Most of it is that we never give the agents the chance to be untrustworthy. For scale: this is one small team, one product, about a year of working this way. That's the entire evidence base, so price everything below accordingly. This post is a map of "never give them the chance." I've written about [how my day-to-day work changed](/blog/how-id-do-engineering-next-year) when agents got good; this is the system underneath that change. I call the system the constraint spectrum: at every phase of the software lifecycle you already know, there is a menu of constraints running from soft nudges to hard guarantees, and you dial each one by the cost of being wrong. The subtitle of this post is borrowed from a Thinking Machines essay I loved, which describes building technology "that lets the born and the made walk the road together,"[^tml] and trust is what has to be earned for that walk to work. ## The asymmetry ![A small robot pouring out a mountain of orange cubes while a human examines a single cube through a magnifying glass](/images/constraint-spectrum/asymmetry.webp) AI can produce work faster than you can check it, and the problem isn't even new. Brandolini's law, the "bullshit asymmetry principle," says the energy needed to refute nonsense is an order of magnitude bigger than the energy needed to produce it.[^brandolini] An unreliable narrator is exhausting to argue with: they've got infinite nonsense, you've got a handful of facts to check it against, and they don't beat you on the merits, they just bury you. An LLM used carelessly is an unlimited-nonsense machine, and a human reviewer is exactly the kind of overwhelmed fact-checker that loses. Computer science has its own version of this. Hand me a program in a normal language and, honestly, I usually can't tell you what it does without running it; that's the halting problem sitting underneath. Shrink the language down far enough, into a domain-specific one, and I can tell it's correct just from how it's built. Unmesh Joshi made this argument well on Martin Fowler's site, and his sharpest line applies to everything below: "The problem is not merely code generation complexity, but verification complexity."[^joshi] But there's an underlooked fact on the other side of the ledger. The same models that produce slop are very good at spotting patterns, because pattern recognition is close to what they are. This year one of these models found 271 security vulnerabilities in Firefox, including a bug that had been sitting in the code for twenty years.[^fable] So an LLM can produce nonsense at scale, and a separate LLM with a clean context and a clean goal can spot nonsense at scale. Bounce them off each other, stack them on the tooling we've had for decades, and by the time a human enters the picture, most of the work is already done. Bun showed what this looks like at scale. In May 2026 its runtime got rewritten from Zig to Rust, about a million lines in eleven days, by 64 agents working as implementers and reviewers, with the old TypeScript test suite as the judge.[^bun] It shipped with 19 known regressions and caught flak for leaning on `unsafe`, and that's the trade in plain sight: at a scale no human could have reviewed, the test suite held back the catastrophic breakage, let nineteen smaller bugs through, and those got found and fixed in the open. METR measures the length of task a model can complete on its own, and that horizon has been doubling roughly every seven months since 2019, faster since 2023.[^metr] Every doubling means more work happening between human check-ins, more surface nobody has read. The constraints are coming either way; the question is whether you install them before the failure or after it. One note on the word you might have expected here: harness. A harness is one agent's bundle of picks from these menus. The spectrum is the menu itself. ![A hand planting a small orange seed](/images/constraint-spectrum/seed.webp) ## Planning: the seed Everything downstream of your idea is capped by the quality of your idea. The maker and checker agents can refine and polish, but the model will only follow the train of thought you gave it; if the thought is really bad the model might push back, but most of the time your input quality is the ceiling of your output quality, and that doesn't usually change. So the first constraints apply to the seed. I dictate my intent as a long, detailed rant rather than a one-line ticket, and the rant is literal: my typing never kept up with my thinking, so my prompts start as speech, through a dictation app called Handy.[^handy] A spoken rant carries the context a ticket strips out, and this phase is entirely about context. I keep taste artifacts where agents can read them: examples of what good looks like to me, in writing, in design, in code. The sparser your instructions, the more a model regresses to the average of everything it was trained on; examples pull it toward yours, and they work at the moment of inference, no fine-tuning required.[^icl] And knowledge lives where agents can grep it. Agents are very good at finding context if you let them, and letting them search plain files usually beats configuring a connector into every tool. We built an open-source tool, [notion-sync](https://github.com/nonfx/notion-sync), that syncs Notion to the file system in both directions, so the documents humans edit in Notion sit in the repo as plain files that any agent can search like code. The quality gates[^gates] at this phase exist to stop weak seeds. Our spec-writing agent refuses to start if the tools and context it needs are not enabled, because we once watched it write a spec anyway with half its context missing. And it is instructed to grill the user: keep asking questions until you fully understand what needs to be done. A vague idea gets interviewed, not accepted at face value. ![Two robots at desks separated by a wall, one writing, one grading against a checklist](/images/constraint-spectrum/exam.webp) ## Requirements and design: the spec This is where we run our purest maker-checker setup,[^makerchecker] and the design that matters most is who gets to see what. The maker is a skill any developer invokes on their machine. It interviews you, researches the knowledge base, and writes the spec. Every spec ships with an HTML mockup, because we found it hard to visualize what a spec meant from words alone. The mockup is dummy HTML with mock data, built on our design system so the UI looks consistent, and it doubles as a light prototyping stage: anyone can pull it, run it, and argue about the actual thing instead of arguing about sentences. The checker exists only in the CI pipeline. There is no way to chat with it and no way to influence it.[^judge] It never sees my original rant, only the maker's output. The maker, in turn, knows only a paraphrased version of the checker's rubric, so it can't write to the test. Think of preparing for an exam: the maker has the practice tests, so it knows roughly what's expected, but it is not the examiner, and the checker is the real exam. You know the guidelines; you don't get to grade yourself. And because it all runs through GitHub, the checker sees the diff of each new revision sitting right next to the verdict it gave last round. Models aren't deterministic: give the same spec to the same checker twice and the notes come back slightly different each run. Without that memory a fresh checker basically re-argues the whole spec every time; with it, each round actually goes somewhere. The score comes back broken out by dimension instead of one lump number, so you can see where the spec is strong and where it's thin, not just how it did overall. And there's a hard cap: three rounds of maker-checker, then humans have to step in and brainstorm. It trips maybe once a month, usually when the feature is genuinely complicated, and that is the system working as intended. The machine loop hands the hard ones back. Maker-checker isn't just for specs, though. It's a horizontal wrapper you can apply at almost any phase: plans, code in the middle of a milestone before a pull request even exists, tests. It burns more tokens on purpose (the internet calls that token maxxing[^tokenmaxxing]), and it's a slider you set by how much the work matters, with a soft ceiling on what more checking can buy. ## Implementation: the build The dial for the code itself runs from soft to hard. Prompts and few-shot examples sit at the soft end. Then self-documenting code, with one rule I insist on: agents must document the why, not the what. The code already tells you what it's doing, and three months later the why is the only thing you'll wish you had. Then lint rules and type checks, which hard-fail the pipeline. We use [OXLint](https://oxc.rs/) and write our own custom rules, and the best part of owning the rules is who writes them now: when a model messes something up, we ask the model to write the lint rule that makes its own mistake impossible to repeat. Our custom rules read like a diary of model habits: one bans re-validating request parameters by hand inside a route handler, because models kept adding belt-and-braces checks for things the route's schema already guarantees, and duplicated checks drift. Another stops imports from reaching deep into another module's internals, because models will happily couple to anything they can see. Then schemas and structured outputs, where the model's answer must parse or it doesn't exist. The shape of the work is a constraint too. Big features get built as vertical slices that fit together like Tetris, each slice independently testable, rather than as a waterfall where everything collapses together at the end. Each slice arrives as a draft pull request that I review as a human, a loop I walked through, flowchart included, in [the previous post](/blog/how-id-do-engineering-next-year). The far end of this dial is a DSL, a language constrained enough to be correct by construction. I don't write DSLs for my day job and I'm not telling you to; it's a reference point that shows which direction "harder" points. But we borrow the idea where it pays. In our production systems, agents never see database UUIDs: a wrapper converts every UUID to a short reference on the way in, and every reference back to a UUID on the way out. I built it after watching models [invent identifiers with total confidence](/blog/llms-unreliable-narrators-uuid-hallucination), and it's the purest example I have of the hard end of the spectrum: not a guardrail that catches the failure, but a constraint that makes the failure impossible, because the vocabulary the failure needs has been removed. That single wrapper is a large part of why [a harness can make a small model reliable](/blog/reliable-small-llm-agent-harness), and why we can run much less intelligent models than we otherwise could. ## Testing: the proof Unit tests and smoke tests carry over from the old world unchanged. Property-based testing gets more useful, not less. You tell it the shape of an input and let it hammer at that shape.[^property] Say something's supposed to be an email: it'll fling a hundred thousand ugly emails at your parser and find out whether it actually holds, which is exactly the beating AI-written code should take before a user gives it one. Evals are the newer member of the family, and ours run every day, which turns model drift from a vague worry into an alarm that fires. They also chase a goal I'll write about separately. Evals are mostly discussed as a way to compare models against each other, and that's fine if you're the one producing the models, but maybe 90% of the conversation belongs to the producers. We're consumers, and a consumer's eval has a different job: minimize the variation in your product across models, and tune for the least intelligent model that still clears the bar, because a customer arriving with a weaker model shouldn't get a subpar product. Getting there is hard work. A less intelligent model has less autonomy, so you chew the food for it, the way birds do for their chicks: take the big workflow an intelligent agent could figure out on its own, break it into small, heavily constrained slices, and chain them. The checker agents work at this phase too: one AI impartially catches issues and another fixes them, in a recursive loop, stacked on all the static tooling above. This stack is what made the biggest refactor I did this year boring, in the best sense. We migrated our entire Vue component library from `.vue` single-file components to TypeScript TSX, using agents plus static migration tools I built: the static tools converted what they could mechanically, and the agents took care of the rest. Because the test coverage was good going in, around 95% of the work landed without a single bug. What actually bit us were migration artifacts, global Vue and Nuxt configuration changes, and some minor class-ordering issues. Almost everything else worked out of the box. And the human samples. Review depth scales with stakes: business-critical code gets every line read, normal code gets sampled, isolated throwaway code sometimes gets no reading at all, because realistically, [nobody honestly reads every line anyway](/blog/how-id-do-engineering-next-year). What agents change is that you can choose the sample. On one large dataset-building job, I have a committee of agents judge the items and route the ones where they disagree into my review pile, thirty at a time. Machine-learning researchers named this pattern query by committee three decades ago;[^qbc] the difference now is that the committee costs pennies. Sometimes I flip the strategy, because the committee itself might carry biases, and take twenty purely random items instead. My comments on those samples then become the golden examples that future agents get prompted with, so each round of human judgment compounds back into the machine. ![A round vault door slightly ajar, a small orange cube rolling through](/images/constraint-spectrum/blastdoor.webp) ## Deployment: the blast door Nothing here makes the work any less wrong. What it does is make being wrong cheap, so a mistake costs you a rollback instead of a night. Big changes live on lab branches with preview deployments, so they never touch main until they've been walked through. Features ship behind flags that default to off. Releases are reversible. And the approval model is inverted: approved by default, veto as the action. If someone wants to be unblocked, they are unblocked; if someone disagrees, they can step in at any time and say no, let's change this. That flip is a big reason we've been able to grow the team fast: nobody sits around waiting to be let through a gate, and someone steps in only when they spot a real problem. Google's whitepaper describes a cousin of this idea as "conditional LGTM";[^google] ours goes further, because rejection is treated as the exception rather than approval as the gate. The inversion is only safe because every constraint earlier in the pipeline has already done its job. You could be shipping something dangerous, and because the guardrails are in place, through process and through technology, you're safe. ## Acceptance and maintenance: where reality answers The first constraint here technically straddles the line between acceptance and maintenance, and I don't much care where it gets filed, because it's the only rule in this post with no exceptions: a human actually uses the feature. Whatever the AI built, someone on the team uses it the way a customer would and checks that it makes sense and that it's tastefully done. I've called this the taste test before: someone made food, and you taste it. The second is the audit trail. Every AI call our agents make, system prompt, messages, tool calls, and tool outputs, is stored in a plain Postgres table. That table is what makes our agents durable in the first place: load the rows and you can replay any conversation and continue it. The same table is how we debug, because "the agent botched this tool call four times this week" becomes a query instead of a hunch, and bad tools get found and fixed instead of quietly retried forever. It's where we mine golden examples for future prompts, and it's raw material for evals, because the agent's own best runs are a test set nobody had to write. When something misbehaves in production, and for us it has mostly been infrastructure rather than agent output, you can trace almost every single thing that was done. ## The capability envelope Everything so far constrains what agents did. One layer constrains what they can do, and it's the reason my honest answer to "tell me about a time an agent did something it shouldn't have been able to" is that it has never happened, or at least that nothing of the sort has ever surfaced in the audit trail, and not because the models are polite: we don't leave the option open. The envelope bounds what an agent can be tricked into doing, not whether it can be tricked. Prompt injection that stays inside granted permissions is a real risk, and it belongs to the checker's half of the house, which I'll get to. On a developer's machine, the agent is an extension of the developer. It executes with your credentials, so whatever you cannot do, it cannot do either; if you don't have admin on the cloud account, neither does your agent. It's a very natural sandbox, and it means the blast radius of an agent is never bigger than the blast radius of its human. In production the sandbox is explicit. Tools are JSON schemas and structured API calls, and when an agent must run code, it runs inside [just bash](https://justbash.dev/) or [QuickJS in WebAssembly](https://github.com/sebastianwessel/quickjs), where it can compute without touching anything else. Permissions stay bound to the invoking user: if an intern uses our production agents, the agent holds the intern's tokens and nothing more. You cannot convince an agent to delete something you aren't allowed to delete. It will try, and it will get permission denied. And every major provider lets you set budget caps at the organization level. We use them quite literally; they're what lets us go to bed knowing we will not wake up broke. ## Gradients and booleans A mindset runs underneath all of this, and it took me a while to say it plainly: don't think about any of it in terms of pass and fail. I never say this maker-checker run worked and that one failed. Real life is way too messy for that. It's almost always about conveniences and inconveniences, about having a day where most things were efficient, and failing is a very strong word for what actually happens. Outcomes live on a gradient, and the more time you spend at the better end of the gradient, the better your life becomes. The tripwires are different. The checker either has its tooling or it rejects; the flag is off until someone turns it on; the third round either ends with agreement or with humans in a room. Outcomes I judge on a sliding scale. The tripwires don't slide; they either fire or they don't. ## Choosing your point No two tasks deserve the same dial settings, and the dial is the cost of being wrong. Estimation changed shape here too: days-based estimates stopped making sense when things started happening in hours, but t-shirt sizing works again. A rough size, a criticality call (an experimental feature, by default, cannot be critical), and a sense of how many decisions are hiding inside the feature: those knobs pick the path. A throwaway internal tool barely staffs the counters. I've shipped things where I wrote zero lines and reviewed zero lines, and only sampled the output (the taste test still happened; using the thing is not the same as reading its code). The real product staffs every station. Business-critical work reaches for the hard end of each column, up to reading every line, and that tier keeps shrinking, because the guardrails are what shrink it. The full decision tree, with the flowchart, is in [the previous post](/blog/how-id-do-engineering-next-year). ## What constraints can't buy There is a boundary, and it's worth being honest about it: constraints buy correctness, and correctness is not taste. I can force an agent onto a style guide, and it will sometimes violate it. I can force it onto a design system where it may only use components that exist, which is about as close to a DSL as design gets. What comes out is correct, and it still isn't pleasant. Models choke on the judgment calls of good interfaces: when not to show a button, what to hide behind progressive disclosure, when less is more. You can often tell which model built a design, because designs from the same model share the DNA of its training. With today's models, no matter how many constraints you put on one, you can get a correct UI, but you can't get a pleasant UI. For now, that part stays with the born. ## A note from the maker's side One admission for a post that leans this hard on maker-checker: I've written all of it as a maker, a developer talking about shipping. The checker's half of the house, supply-chain provenance, prompt-injection hardening, data privacy, the licensing of generated code, deserves its own field guide from someone wearing that hat, and its reading list is already excellent.[^ssdf] [^owasp] [^ncsc] ## Where to start on Monday If you adopt one constraint per phase this month, these are the ones I'd pick, cheapest first: - **Planning:** write your next feature request as a spoken rant instead of a one-line ticket, and make your docs greppable from the repo. - **Requirements:** before anything gets built, have one agent write the spec and a second agent with a fresh context review it. Two sessions, zero tooling. - **Implementation:** take the last mistake an AI made in your codebase and have the AI write the lint rule against it. Then tell your agents to document why, never what. - **Testing:** point property-based testing at your most fragile parser or transform. - **Deployment:** put your next feature behind a flag that defaults to off. - **Maintenance:** log every agent call somewhere you can query. A single database table is enough. None of these need a platform or a budget, and each one is a click of the ratchet, which is the last thing I want to tell you about. ![A ratchet gear hoisting an orange cube up a set of steps](/images/constraint-spectrum/ratchet.webp) ## The ratchet Everything above fits on one page: ![The Constraint Spectrum: six SDLC phases with their constraint menus and quality gates, two horizontal layers (the maker-checker wrapper and the capability envelope), the cost-of-being-wrong dial, and the ratchet feeding failures back as new constraints](/images/constraint-spectrum/diagram.svg) None of the quality gates in that diagram were designed up front. Every gate began life as a failure. The spec writer and the spec checker started out as two skills on the same machine, and one day someone accidentally invoked the checker inside the maker's chat. The output got drastically worse, because a model that can see the goal will bend its judgment toward it; the checker turned agreeable. That failure is why the checker now lives only in the CI pipeline, where nobody can talk to it. The refuse-to-start gate exists because a developer once ran the spec writer without the right tooling connected, and it happily wrote a spec with half its context missing. The grill-the-user instruction exists because agents used to take a vague idea at face value and just run, and the output can't be better than the input. The three-round cap exists because the loop once needed a human and didn't ask for one. The purest version of the loop lives in our lint setup: the model that made the mistake gets asked to write the rule against it. Each failure pushed us toward the bad end of the spectrum. Each constraint we installed pushed us back, one click, and the click holds.[^rv] The next time an AI gets something wrong in your codebase, don't just fix it. Ask which constraint would have made that failure impossible, and install it. Every failure converts into one permanent click up the spectrum, and if you do that for a year, you'll have a constraint spectrum of your own. The born and the made are going to walk the road together either way. Constraints are how the made earns it. --- [^tml]: I found the image in Thinking Machines Lab's [The Future Worth Building Is Human](https://thinkingmachines.ai/blog/the-future-worth-building-is-human/) (2026), but "the born and the made" is older: Kevin Kelly opened [Out of Control](https://kk.org/mt-files/outofcontrol/ch1-a.html) with it in 1994, in a chapter literally titled "The Made and the Born." Good images get borrowed; this post's subtitle borrows it again. [^makerchecker]: [Maker-checker](https://en.wikipedia.org/wiki/Maker-checker), a central authorization principle in the information systems of financial organizations, closely related to the four-eyes principle. [^brandolini]: [Brandolini's law](https://en.wikipedia.org/wiki/Brandolini%27s_law), coined by Alberto Brandolini in 2013. An observation rather than a theorem, but it has held up painfully well. [^joshi]: Unmesh Joshi, [LLMs and DSLs](https://martinfowler.com/articles/llm-and-dsls.html) (2026), on martinfowler.com. [^fable]: Anthropic's Claude Mythos, reported in [The Hacker News](https://thehackernews.com/2026/06/anthropic-releases-claude-fable-5-its.html): 271 vulnerabilities in Firefox, including flaws 15 and 20 years old. [^bun]: Simon Willison, [Rewriting Bun in Rust](https://simonwillison.net/2026/Jul/8/rewriting-bun-in-rust/), and The Register's [coverage of the merge](https://www.theregister.com/devops/2026/05/14/anthropics-bun-rust-rewrite-merged-at-speed-of-ai/). [^metr]: METR, [Measuring AI Ability to Complete Long Tasks](https://metr.org/blog/2025-03-19-measuring-ai-ability-to-complete-long-tasks/), and the accelerated estimate in their Time Horizon 1.1 update (January 2026). [^handy]: [Handy](https://github.com/cjpais/Handy): free, open source, fully offline speech-to-text. Plenty of similar apps exist; I just haven't had a reason to switch. [^gates]: "Quality gate" is standard CI/CD vocabulary: a set of measurable pass/fail conditions at a pipeline checkpoint. See [SonarQube's definition](https://docs.sonarsource.com/sonarqube-server/quality-standards-administration/managing-quality-gates/introduction-to-quality-gates). [^judge]: The isolation isn't superstition. Models measurably [favor their own generations](https://arxiv.org/abs/2404.13076), and LLM judges carry [known biases](https://arxiv.org/abs/2306.05685) (position, verbosity, self-enhancement) that a clean context and a rubric are there to fight. [^icl]: In-context learning, first characterized at scale in [Language Models are Few-Shot Learners](https://arxiv.org/abs/2005.14165) (Brown et al., 2020). Examples are a form of soft constraint the model picks up at inference time. [^property]: [fast-check](https://fast-check.dev/) for TypeScript, [Hypothesis](https://hypothesis.readthedocs.io/) for Python. [^qbc]: [Query by committee](https://en.wikipedia.org/wiki/Active_learning_(machine_learning)) (Seung, Opper & Sompolinsky, 1992), from the active learning literature. [^tokenmaxxing]: [Built In's explainer](https://builtin.com/articles/ai-tokenmaxxing) covers both the slang and the corporate leaderboard stories that made it famous in April 2026. [^google]: Google, [The New SDLC With Vibe Coding](https://www.kaggle.com/whitepaper-the-new-SDLC-with-vibe-coding) (May 2026), and its spec-focused companion, [Spec-Driven Production Grade Development](https://www.kaggle.com/whitepaper-spec-driven-production-grade-development-in-the-age-of-vibe-coding). Useful papers, with the caveat that the later chapters lean promotional about Google's own tooling. [^ssdf]: NIST [SP 800-218](https://csrc.nist.gov/pubs/sp/800/218/final) (the Secure Software Development Framework) and [SP 800-218A](https://csrc.nist.gov/pubs/sp/800/218/a/final), its generative-AI addendum. [^owasp]: [OWASP Top 10 for LLM Applications](https://genai.owasp.org/llm-top-10/). LLM06, "Excessive Agency," is the risk the capability envelope speaks to, and only the permissions half of it; LLM01, prompt injection, is the checker's territory. [^ncsc]: NCSC/CISA, [Guidelines for Secure AI System Development](https://www.ncsc.gov.uk/collection/guidelines-secure-ai-system-development), endorsed by agencies from 23 countries. [^rv]: NIST's framework asks for exactly this loop in its Respond to Vulnerabilities practices: root-cause every failure and feed the fix back into the process, not just the code. --- # How I'd do engineering for the next year > Between December 2025 and July 2026, AI agents stopped asking me for the next step. What changed, where the trend is going, and how I'm changing the way I build software to get ahead of it. Published: Jul 14, 2026 · https://nikhil-verma.com/blog/how-id-do-engineering-next-year/ Until recently, an AI agent would do a few things, then stop and ask me questions, or ask me for the next steps. Somewhere in the last six months that changed: now it just runs, until it genuinely cannot go any further. There was no lightning-bolt moment for me. It was a collection of moments, a slow creep. You're working along, and one day you catch yourself thinking: hang on... the task that took me some time a couple of months back was now completed almost autonomously by this AI agent. And then it happens again a few weeks later, with something bigger. Here's what that creep did to my work: in roughly the last year, I've written fewer than a hundred lines of code by hand. I don't really write code anymore; I review it. And lately I don't even review every line; I sample it. Since you probably don't know me: I've spent almost twenty years building web applications and user-facing products, several of those managing teams of ten-plus people, including products with millions of users at Bumble. This post is about what changed between December 2025 and July 2026, where the trend is going, and how I'm changing the way I do engineering to get ahead of it. Compressed into one thought: the rules have changed, and people who think clearly and write clearly are going to matter more than ever. ## Three eras in three years First, AI was a good autocomplete and not much else. Then came about a year of closely-directed work, the Copilot era: genuinely useful, but you had to direct it tightly: look at these three files, change this function to behave like this, put this UI component here, follow that reference file. If you did that, it did a pretty good job. Honestly, it felt like things wouldn't change much from there. Then, over a few weeks in late 2025, the frontier labs shipped a wave of models[^willison], and agents stopped needing step-by-step instructions. They started taking high-level *intent* and carrying it over hours of work. Why? My hypothesis (and it is only a hypothesis) is that while humans were closely directing AI through the Copilot era, the AI companies were learning from that interaction. We were acting as quasi-agents, and the agents learned from us. The standard account from people who train these systems is different: reinforcement learning on verifiable rewards, meaning models trained against outcomes like "the tests pass" in sandboxed environments.[^rlvr] The two stories aren't mutually exclusive, and either way the result is the same: the agents stopped needing me between every step. ## My job is a factory now My work has turned into a car factory. If you hand-build a car, you inspect every piece, every gear. If you have smart workers on an assembly line, you direct instead of build, but you still check everything that comes off the line. The stage after that is where I live now: one agent makes, another agent checks, and my job is directing. I'm an orchestrator, there are minions doing the work, and I'm sampling their output and providing the taste. Diligence doesn't disappear, it becomes random sampling: random lines, random areas, enough distribution to catch what usually goes wrong. The move that makes it compound: everything sampling catches gets converted into static enforcement (a lint rule, a code-review instruction, a pipeline check) so the same mistake can't happen again. Google's recent whitepaper lands on the same rule: "add a rule every time the agent does something it should not do again."[^google] Probably the most important thing I've learned this year: the loop you run depends entirely on what you're building. ## Different context, different judgments ![Flowchart: a new task arrives, gets sized by criticality and t-shirt size, then splits: the experimental path loops prompt → agent builds → sample the output without ever opening the code; the real-product path runs rant → plan → milestones, vertical slices, a draft PR reviewed by a human at a depth scaled to stakes. Every path ends at a mandatory human taste test.](/images/how-id-do-engineering-next-year/flowchart.svg) Before any work starts, a few knobs get set: how critical is this to the business (an experimental feature, by default, cannot be critical), how big is it, how many decisions are hiding inside it. Days-based estimation doesn't work anymore, because things happen in hours, but t-shirt sizing actually works now. You get a rough size and pick a path. **The throwaway path.** For quick internal tools and interim artifacts, I've written zero lines and *reviewed* zero lines. I jump literally from my prompt to the output: prompt, agent works, I sample the output, go again. The code is never opened. I know how reckless that sounds; I'll come back to why I don't think it is. **The real-project path.** For the codebase I actually live in, I'm more involved, because I don't want the models drifting in the wrong direction. The loop becomes: I do the rant, I do the plan, I break the plan into reviewable milestones. (The rant is literal: my typing never kept up with my thinking, so prompts start as speech through a dictation app called Handy.[^handy]) The milestone loop is honestly a bit funny: the agent writes the code and opens a draft pull request against me, using my own account; I go in as a human, review my own pull request, leave comments in GitHub, and tell the agent I've left comments for it. Big features get built as vertical slices that fit together like Tetris, each slice testable on its own, the whole thing done when the slices line up, not as a waterfall where everything collapses at the end. **The floor under every path.** Whatever the AI builds, a human actually has to *use* the feature. You are the taster. Someone made food; you taste it, you check whether it's tastefully done, whether it makes sense. This part is mandatory. Between those extremes, review depth scales with stakes. Business-critical code, I read all of it. Non-critical, I read some. Isolated one-offs, sometimes none at all. Different context, different judgments. ## Nobody reads every line This is where I part ways with the official advice. Google's whitepaper, which agrees with almost everything else in this post, says plainly: review every line the agent produces that is going to ship.[^google] I don't think that's realistic, for two reasons. The first: AI is really, really good at pattern recognition. Distill the patterns a reviewer should look out for, and one AI can impartially catch issues while another fixes them, in a recursive loop, combined with tooling we've had for years: static analysis, linters, type checkers, test runners, smoke tests, property-based testing, fuzzing. The agents can help you *write* those tools too. With good enough guardrails, you don't have to stress about reading every single line. It's a combination of tools, not one person sitting on a laptop with nothing else in place. The second is more uncomfortable: realistically, no human being honestly reads every line of code they review. I know this is controversial, and most people will say they do. But almost every engineer I've worked with has admitted, at some point, that they didn't read everything. They sampled it, checked the conventions, looked hard at the critical parts they knew about, and approved. We've been sampling all along, just without the guardrails we have now. And it's not like every line of code is headed for a nuclear or medical facility. Applying the right depth of review in the right context has always been the actual job. The tier of code where you read everything is real, but it's shrinking, and guardrails are what shrink it. I've seen this play out at scale twice this year. In public: Bun rewrote roughly a million lines of Zig into Rust in eleven days, using 64 parallel agent instances in an implementer/reviewer pattern, with its TypeScript test suite as the conformance harness.[^bun] It shipped with 19 known regressions (since fixed) and drew fair criticism for its heavy use of `unsafe`. I'm including those deliberately, because they make the point: the test suite caught what mattered. On my own team: we migrated our entire Vue component library from `.vue` single-file components to TypeScript TSX (still Vue as the framework) using AI plus static migration tools I built. The static tools converted what they could mechanically, the agents took care of the rest. With good test coverage going in, I'd estimate 95% of the work landed without a single bug; what bit us were migration artifacts (global Vue and Nuxt configuration changes) and some minor class-ordering issues. (I've written about the TSX setup [in a previous post](/blog/vue-without-the-vue-files).) The counter-evidence: a widely-cited METR study found experienced developers using AI took 19% *longer* on certain tasks, mostly verifying and correcting AI output.[^metr-rct] I can't argue with their data, but it doesn't match anything I've seen, and I think the difference is the guardrails. What I've seen is prototyping going from weeks to hours, almost a J curve. At Bumble, on a highly experimental platform, these tools would have let us ship ten times the experiments. If verification is where the time goes, verification is what you should industrialize, which is the rest of this post. ## The curve is accelerating Everything above already happened. The reason I'm confident it keeps going is the trend line: METR tracks the length of task, measured in human-professional time, that models complete autonomously, and that horizon has been doubling roughly every seven months since 2019, *accelerating* since 2023.[^metr] The Bun rewrite is one point on that curve. Extrapolate twelve months, and the question stops being whether the agent can do the task, and becomes whether your engineering team is set up to direct and verify that much output. If I were running a ten-person team, here's what I'd change on Monday morning. ## What I'd change Monday morning **Everyone runs agents in parallel.** You can direct multiple tasks at once now; one agent per person leaves most of the value on the table. **The agents move off laptops.** When your laptop closes, your agents die; on a cloud environment they keep running. We attach with tmux, and recently I've been trying out Herdr.[^herdr] **Onboard agents like employees, but respect the context.** An agent with no guidance does whatever it wants, but stuffing its context with your documentation fails just as drastically. Context is precious; don't pollute it. What works: self-documented code that records the *why*, and a knowledgebase the agent can grep when it decides it needs more. **Force the why.** Agents love to narrate *what* they're doing, but the code already tells you that. Force them to document *why*: the thing you need three months later, staring at a line and wondering why it was written in the first place. **Gate on evals, not demos.** Almost everybody should have an internal eval for what they're building; a passing demo tells you very little about how the thing behaves the rest of the time.[^google-evals] **Review from altitude.** AI reviewers take the boring layer (style violations, easily-exploitable security gaps) and your review moves up to architecture, reusability, data structures, the bigger patterns. You're allowed to zoom out. A developer becomes an architect now, and that's a huge thing. **On hiring: I don't have an answer.** Hiring has become difficult, because every portfolio project is now vibe-coded, so you have no idea what you're looking at. You have to somehow evaluate taste: how much care and attention went into the work. We've struggled with it, and I won't pretend otherwise. ## The discipline: fighting brain rot I'd be lying if I ended on the prescriptions, because the hardest problem on that Monday morning is me. These models make it so easy to not read anything and just ship. You have to actively fight yourself, and I struggle with this personally. The temptation: prompt something, barely test the output, say "yep, ship it", because the models are good enough that whatever they produce will *mostly* work, and the saved time feels like it buys the next feature, the next experiment, the next side project. But it leads to complete brain rot, for both the agent and for you. You lose all sense of what's actually being built: an old man yelling at the cloud, making claims about your own system without verifying that any of them back up. Google's paper puts it well: AI "multiplies both your strengths and your weaknesses."[^google-culture] The taste test, a human actually using the thing, is what keeps that multiplier pointed the right way. ## Code as a compiled artifact Everything above is my plan for the next year. Here's where I think it goes a couple of years out. I don't write binary. I don't write assembly. I don't even write C. Node and Chrome are built on C, which becomes assembly, which becomes something I've never once needed to look at, and I just write JavaScript on top. With the next generation of agents, I think the whole codebase becomes almost like a compiled artifact. Just as I don't read assembly today, you won't need to read the code agents produce. It will be some internal representation in their latent space. Someone will say: but you're becoming dumb. Which is true, but I'm also dumb now. I don't know assembly, and somehow I still write TypeScript and do useful work. It's not a one-to-one mapping, of course. But when your code gets compiled, most of the time (and I want to stress *most of the time*) you don't care what bytes it compiled to, because it works and everything is fine. Similarly, give an agent a detailed specification and guardrails, and most of the time the code it produces just works, as expected. Neither case means you go blind; it's always context. If your application is high-performance and the compiled code isn't performing, you start investigating. If your prompted code isn't good, you do the same thing: you dig down into it. So the rules change a lot. Your ability to think clearly, to write clearly, to communicate clearly becomes the important thing, because good thinkers and good writers can impart their taste, their wisdom, and their vision, and the agents do the work. That's the bet I'm making for the next year. I'm writing it down so that next July I can come back and check whether any of it backed up. --- [^willison]: Gemini 3 Pro (Nov 18, 2025), GPT-5.1 Codex-Max (Nov 19), Claude Opus 4.5 (Nov 24), and GPT-5.2 (December). Simon Willison's [2025: The year in LLMs](https://simonwillison.net/2025/Dec/31/the-year-in-llms/) is the best chronicle of the wave. [^rlvr]: Nathan Lambert's writing at [Interconnects](https://www.interconnects.ai/) is the clearest explanation of reinforcement learning with verifiable rewards, a term his team coined. [^google]: Google, [The New SDLC With Vibe Coding](https://www.kaggle.com/whitepaper-the-new-SDLC-with-vibe-coding) (May 2026), by Addy Osmani, Shubham Saboo and Sokratis Kartakis; there's an [author's summary on Osmani's blog](https://addyosmani.com/blog/new-sdlc-vibe-coding/). A genuinely useful paper, with the caveat that its later chapters lean promotional about Google's own tooling. [^handy]: [Handy](https://github.com/cjpais/Handy): free, open source, fully offline speech-to-text. Plenty of similar apps exist, with new ones every month; I just haven't had a reason to switch. [^bun]: Simon Willison, [Rewriting Bun in Rust](https://simonwillison.net/2026/Jul/8/rewriting-bun-in-rust/), and The Register's [coverage of the merge](https://www.theregister.com/devops/2026/05/14/anthropics-bun-rust-rewrite-merged-at-speed-of-ai/). [^metr-rct]: METR, [Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity](https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/) ([paper](https://arxiv.org/abs/2507.09089)). Worth noting the study used early-2025 tools (Cursor with Claude 3.5/3.7 Sonnet), from before the autumn wave this post is about. [^metr]: METR, [Measuring AI Ability to Complete Long Tasks](https://metr.org/blog/2025-03-19-measuring-ai-ability-to-complete-long-tasks/): the ~7-month doubling time, revised faster in their Time Horizon 1.1 update (January 2026). [^herdr]: [Herdr](https://herdr.dev/): an agent-aware terminal multiplexer: tmux that understands agents, showing at a glance which are blocked, working, or done. [^google-evals]: "Set the bar at the eval, not the demo." (The New SDLC With Vibe Coding, p. 44.) [^google-culture]: "AI is a force multiplier — and it multiplies both your strengths and your weaknesses." (The New SDLC With Vibe Coding, p. 47.) --- # How I am using Vue with Typescript 7 today > Write Vue components in plain TSX: you keep the reactivity system that makes Vue great, and TypeScript 7 type-checks them natively, today. Published: Jul 10, 2026 · https://nikhil-verma.com/blog/vue-without-the-vue-files/ TypeScript 7 shipped this week. The Go-native compiler, the one with the order-of-magnitude speed claims, is now just `typescript@7` on npm. And buried in the announcement is a caveat that reads like bad news for Vue developers: tools that embed TypeScript into their own language services — Volar among them — can't use it yet, so "workflows that use Vue, MDX, Astro, Svelte and others will likely not yet be able to leverage TypeScript 7." Our Vue app has been on the native compiler the whole time. Every component, type-checked by TypeScript 7's toolchain, on GA week, no plugins, no waiting for anything to be ported. We write Vue in `.tsx` files. The reason that works points at a misconception about what Vue actually *is*, and the payoff goes well beyond one fast compiler. ## The .vue file was always optional Say "Vue" and most people picture a `.vue` file: a `