<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mat Weiss</title>
    <description>The latest articles on DEV Community by Mat Weiss (@matweiss).</description>
    <link>https://dev.to/matweiss</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F994946%2F2107b19e-bba0-4076-94bd-dbd1e6e7f2a9.png</url>
      <title>DEV Community: Mat Weiss</title>
      <link>https://dev.to/matweiss</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/matweiss"/>
    <language>en</language>
    <item>
      <title>Your Compiler Is Missing from the Party</title>
      <dc:creator>Mat Weiss</dc:creator>
      <pubDate>Thu, 30 Apr 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/matweiss/your-compiler-is-missing-from-the-party-4bf1</link>
      <guid>https://dev.to/matweiss/your-compiler-is-missing-from-the-party-4bf1</guid>
      <description>&lt;p&gt;Handwriting code is the new cursive. AI agents write code competently, and they're improving fast. My recent agentic work spans refactoring C++ machine learning libraries, writing CLIs in Rust, building web apps in ASP.NET, and shipping mobile apps in Flutter. For the mechanical parts — scaffolding, boilerplate, repetitive transformations — agents handle it well. I've used them to write entire features on their own as well.&lt;/p&gt;

&lt;p&gt;It makes you wonder, if the agent writes the code, is the language is an implementation detail — and the intuition makes sense: why care about syntax you'll never type? But the language isn't just what the agent writes in. It's what the compiler checks, what the human reviews, and what determines how fast the feedback loop closes. Agentic coding raises the stakes for language design, and points toward specific properties a language should have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Better Compiler Feedback Multiplies Agent Productivity
&lt;/h2&gt;

&lt;p&gt;My agentic coding experience has varied by language. Part of that is training data — AI models have seen more code in some languages than others. But the larger factor is whether mistakes are caught at compile time or runtime, which determines how quickly the loop closes.&lt;/p&gt;

&lt;p&gt;In Rust, when an agent generates something wrong, the compiler identifies the exact location, names the violated constraint, and usually suggests a fix. The agent iterates on that feedback directly — no execution required. When checks happen at runtime instead, there's an extra round-trip: generate code, execute tests, parse results, feed output back to the agent. More wall time per iteration, more tokens spent on test output instead of code. Same agent, longer loop, higher cost per correction. And those runtime checks are only as good as the inputs that exercise them. Communities built around runtime-checked languages know this well — it's why they invest heavily in defensive testing, property-based tools like &lt;a href="https://hypothesis.readthedocs.io" rel="noopener noreferrer"&gt;Hypothesis&lt;/a&gt;, and comprehensive test suites. But even thorough tests depend on the paths you think to exercise. A compile-time check flags the error unconditionally.&lt;/p&gt;

&lt;p&gt;This isn't a judgment on any particular language — it's a property of where in the cycle errors surface. The industry has started redesigning CLI tools for agents — Trevin Chow's &lt;a href="https://trevinsays.com/p/7-principles-for-agent-friendly-clis" rel="noopener noreferrer"&gt;seven principles for agent-friendly CLIs&lt;/a&gt; captures the pattern: structured output, unambiguous interfaces, clear error signals. The same thinking applies to compilers. The compiler is the agent's primary feedback surface — and most compilers were designed before agentic coding existed.&lt;/p&gt;

&lt;p&gt;Better compiler output is the starting point. The deeper question is what classes of mistakes the compiler can catch. The best current compilers handle memory errors (Rust), type mismatches (TypeScript), and null dereferences (Kotlin). Entire categories of domain mistakes remain invisible: unhandled operation outcomes, invalid state transitions, missing field mappings when converting between data representations. These aren't obscure edge cases — they slip past review and surface in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Development Model Needs a Third Party
&lt;/h2&gt;

&lt;p&gt;Our current approach to AI coding is a two-party arrangement: humans describe intent, agents write code. Somebody is missing the party.&lt;/p&gt;

&lt;p&gt;The danger isn't that AI writes bad code. It's that humans lose the ability to evaluate what AI writes — and the two-party model accelerates this. The volume of AI-generated code is already outpacing review capacity; the trend is toward reviewing less, not more. That makes the compiler more load-bearing, not less. A smarter AI doesn't close this gap on its own — even the best engineer benefits from code review, because independent verification catches what self-consistency misses. The same principle applies to generated code, except the stakes are higher: the reviewer understands less of the codebase with each generation cycle.&lt;/p&gt;

&lt;p&gt;The Rust model points at the answer: compiler-enforced properties rather than runtime hopes. The question is whether we can extend that from memory safety to operational semantics. Expanded compiler checking gives us a basis for trusting AI-generated code — not because the AI earned that trust, but because an independent third party verified the structural claims. Checks and balances: human + compiler + AI, each with a distinct responsibility.&lt;/p&gt;

&lt;p&gt;The human defines the operation's shape: its outcomes, state transitions, data projections. The AI generates the implementation body. The compiler stands between them, rejecting anything that violates the declared structure. This changes what a developer needs to review. The programmer's job is to get the declaration right — to ensure the outcome variants are exhaustive, the state transitions are valid, the field projections are accurate. That's the work only a human can do: verifying that the declaration honestly represents the domain. Once that's done, the compiler owns enforcement everywhere.&lt;/p&gt;

&lt;p&gt;The languages most of us work in weren't designed for the assumption that you'd be reading tens of thousands of lines generated by someone else, at volume, under time pressure. That's the new reality. The closer a language's constructs map to domain concepts, the less translation the reader's brain performs — and the faster a developer can audit generated code for correctness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Domain Knowledge Belongs in the Declaration
&lt;/h2&gt;

&lt;p&gt;The common thread between better compiler feedback, the three-party model, and cheaper review is semantic content — how much meaning the language lets you encode, and how much of that meaning the compiler verifies.&lt;/p&gt;

&lt;p&gt;Current compilers have limited capability to check domain rules. Your service calls a payment gateway — the response can mean charged, declined, fraud-held, or gateway failure. Most languages give you a status code and a body; whether you distinguish "declined" from "fraud hold" depends on your discipline, not the compiler. A &lt;code&gt;User&lt;/code&gt; has twenty fields; an API response should expose five of them. Derive the response type by hand, add a field to &lt;code&gt;User&lt;/code&gt; next quarter, and now you're trusting every downstream DTO to have been updated.&lt;/p&gt;

&lt;p&gt;The convention of documenting this is everywhere — Javadoc's &lt;code&gt;@throws&lt;/code&gt;, Python's &lt;code&gt;Raises&lt;/code&gt;, OpenAPI's response schemas. The problem is that none of it is compiler-visible. You can document four outcomes and handle three. The gap stays invisible until production. Here's a typical pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * @throws DeclinedError
 * @throws FraudHoldError
 * @throws GatewayError
 */&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;chargeCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChargeRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;gateway&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PaymentGateway&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Receipt&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The return type promises a &lt;code&gt;Receipt&lt;/code&gt; — that's the happy path. The three failure modes live in a JSDoc comment the compiler will never read. A caller that ignores all three error cases compiles without a warning. The information is there, but it's decorative.&lt;/p&gt;

&lt;p&gt;Here is the same operation in Ruuk, a language designed to include this information where the compiler can verify it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="n"&gt;chargeCard&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ChargeRequest&lt;/span&gt;
    &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt;
    &lt;span class="n"&gt;outcomes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Charged&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nc"&gt;Receipt&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Declined&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nc"&gt;DeclineReason&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;FraudHold&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nc"&gt;ReviewId&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;GatewayError&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nc"&gt;ErrorDetail&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This declares not just inputs but what role each plays (&lt;code&gt;payload&lt;/code&gt; is the data being acted on, &lt;code&gt;via&lt;/code&gt; is the external system being called) and what outcomes the caller must handle. If you call &lt;code&gt;chargeCard&lt;/code&gt; and don't handle the &lt;code&gt;FraudHold&lt;/code&gt; outcome, it doesn't compile. The meaning you would have put in a comment is now visible to the compiler — and enforced by it.&lt;/p&gt;

&lt;p&gt;The same declaration that gives the compiler more to verify also makes the code faster to cold-read. A developer scanning AI-generated code can evaluate &lt;code&gt;chargeCard&lt;/code&gt;'s shape in seconds: what it takes, where the data goes, what can go wrong. No implementation diving required.&lt;/p&gt;

&lt;p&gt;This design direction asks developers to formalize what they already know — it's on the whiteboard, in the docs, in comments scattered through the codebase. You already know your payment operation has four possible outcomes. The language asks you to type that in. The compiler takes it from there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Agentic coding hasn't reduced the importance of language design — it's exposed where it needs to grow. The properties that improve the agentic loop are the same ones that improve human review: more meaning in the syntax, more verification in the compiler, less translation between what the code says and what the domain demands.&lt;/p&gt;

&lt;p&gt;That points toward a class of language, not a single answer. Ruuk is my attempt to build one — designed from the start for the world where agents write the code and humans verify the shape. Hopefully it won't be the only attempt, and competition here is genuinely good. The industry needs more people thinking about this problem.&lt;/p&gt;

&lt;p&gt;The articles that follow make the design concrete. The next piece is a fast tour of the OCaml/F# syntax Ruuk builds on — enough to read the examples without getting lost. After that: how operations and outcomes give the compiler visibility into failure modes, and how projections enforce structural rules when data crosses boundaries. The chargeCard declaration above is the destination. The series shows how you get there.&lt;/p&gt;

&lt;p&gt;Ruuk is pre-alpha. What I can show right now is the thinking behind it — and a place to engage with the design before it solidifies. If the ideas in this article resonates, follow along on &lt;a href="https://github.com/ruuk-lang/ruuk" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and weigh in on the discussions. The best languages get shaped by the people who care about the problems they solve.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>software</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Code Intelligence Is Being Retrofitted. Ruuk Builds It In.</title>
      <dc:creator>Mat Weiss</dc:creator>
      <pubDate>Fri, 17 Apr 2026 12:01:48 +0000</pubDate>
      <link>https://dev.to/matweiss/code-intelligence-is-being-retrofitted-ruuk-builds-it-in-1nb</link>
      <guid>https://dev.to/matweiss/code-intelligence-is-being-retrofitted-ruuk-builds-it-in-1nb</guid>
      <description>&lt;p&gt;&lt;em&gt;A response to Thoughtworks Technology Radar Vol. 34, Blip 18: Code Intelligence as Agentic Tooling&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.thoughtworks.com/radar/techniques/summary/code-intelligence-as-agentic-tooling" rel="noopener noreferrer"&gt;Blip 18&lt;/a&gt; of the April 2026 Thoughtworks Radar names a real problem: AI coding agents are effectively blind to the meaning of the code they operate on. The Radar's answer is richer tooling — LSP integrations, OpenRewrite's Lossless Semantic Tree, JetBrains MCP servers.&lt;/p&gt;

&lt;p&gt;That's the practical path for mainstream languages. But it's still using the AST to &lt;em&gt;infer&lt;/em&gt; intent. What would it look like to use the AST to &lt;em&gt;see&lt;/em&gt; it?&lt;/p&gt;

&lt;p&gt;Ruuk — a language I'm designing — takes a different position: the constraints worth enforcing should be in the language itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the AST Cannot Tell You
&lt;/h2&gt;

&lt;p&gt;Take a typical enterprise operation: approving an order. In Java, an agent with full LSP access sees something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ApprovalResult&lt;/span&gt; &lt;span class="nf"&gt;approveOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderId&lt;/span&gt; &lt;span class="n"&gt;orderId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CSR&lt;/span&gt; &lt;span class="n"&gt;csr&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orderStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// ... validation logic&lt;/span&gt;
    &lt;span class="c1"&gt;// ... state transition&lt;/span&gt;
    &lt;span class="c1"&gt;// ... outcome handling&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent knows the function name, its signature, its call sites, and the types it touches. What it doesn't know is more consequential:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;order&lt;/code&gt; must be in &lt;code&gt;Created&lt;/code&gt; state for this call to be valid. Calling it on a &lt;code&gt;Cancelled&lt;/code&gt; order is a logic error, not a type error — the compiler won't catch it, and neither will the agent.&lt;/li&gt;
&lt;li&gt;There are exactly two outcomes — &lt;code&gt;Approved&lt;/code&gt; and &lt;code&gt;Rejected&lt;/code&gt; — and callers must handle both. The agent has to read the implementation to find out.&lt;/li&gt;
&lt;li&gt;This is an instantaneous state transition, not a long-running process. That distinction matters for error handling and compensation strategy. The function signature doesn't say.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;orderStore&lt;/code&gt; is being mutated — it's an entity undergoing state change, not a read-only data source. The agent can't tell that from the call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modern Java closes some of these gaps. Sealed classes and pattern matching (Java 21+) give you exhaustive outcome handling. Some languages go further: TypeScript's discriminated unions and Rust's typestate patterns encode more intent into the type system. But even in those languages, the precondition that the order must be in &lt;code&gt;Created&lt;/code&gt; state remains a convention, not a compiler-checked constraint. The resource mutation role is still invisible. The state machine is still implicit. They moved the needle on &lt;em&gt;what can happen&lt;/em&gt;; they didn't touch &lt;em&gt;what must be true before&lt;/em&gt; or &lt;em&gt;what kind of change is occurring&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;An agent can reconstruct those properties for any well-written function by reading its implementation and tests. The problem is scale. Across a codebase of thousands of operations, inference compounds uncertainty. It fails hardest on the code that needs agents most: legacy systems, inconsistent patterns, missing tests. Structural declarations don't degrade. The thousandth operation is as machine-readable as the first.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Ruuk Exposes at Declaration Time
&lt;/h2&gt;

&lt;p&gt;In Ruuk, the same operation looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Created&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Approved&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Shipped&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Delivered&lt;/span&gt;

&lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="n"&gt;approveOrder&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Created&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;OrderStore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;performs&lt;/span&gt; &lt;span class="nn"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Created&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Approved&lt;/span&gt;
    &lt;span class="n"&gt;outcomes&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Approved&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Approved&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Rejected&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything the Java version hid is in the declaration. The precondition is in the type: &lt;code&gt;Order&amp;lt;Created&amp;gt;&lt;/code&gt;. Passing an &lt;code&gt;Order&amp;lt;Cancelled&amp;gt;&lt;/code&gt; is a compile error. The state transition is explicit in the &lt;code&gt;performs&lt;/code&gt; clause. The outcomes are enumerated, and the compiler verifies that every call site handles both. The &lt;code&gt;subject&lt;/code&gt; role marks the order as the entity being changed; the &lt;code&gt;goal&lt;/code&gt; role marks the store as the mutation target, distinct from a read-only data source.&lt;/p&gt;

&lt;p&gt;The compiler checks these declarations against the implementation. If the function body transitions to a state that doesn't match the &lt;code&gt;performs&lt;/code&gt; clause, it won't compile. If you add an outcome variant without updating call sites, they won't compile. Declarations can't drift from reality because they're verified at compile time, then erased. Zero runtime cost.&lt;/p&gt;

&lt;p&gt;That's a meaningful difference from design-by-contract predecessors like Eiffel and JML, where contracts were primarily runtime-checked or relied on external verification tools. In Ruuk, the declaration &lt;em&gt;is&lt;/em&gt; the constraint, and the compiler enforces it statically.&lt;/p&gt;

&lt;p&gt;I designed it this way because the information always existed. Every team I've worked with on enterprise applications knew their preconditions, their state machines, their failure modes. They just had no place to put that knowledge where the compiler could use it.&lt;/p&gt;

&lt;p&gt;From this declaration alone, an agent can answer — without reading one line of implementation — every question the Java version left open. The Radar points to the AST and the richer Lossless Semantic Tree as the right representations for agent tooling. Those capture structure: how code is organized, what the syntactic relationships are. Ruuk's declarations go further — they capture &lt;em&gt;meaning&lt;/em&gt;: what must be true, what can happen, and what kind of change is occurring.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Could an Agent Do With This?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Impact analysis.&lt;/strong&gt; When &lt;code&gt;Order&lt;/code&gt; gains a new field, an agent can ask: which projections include this field? A Ruuk projection is a typed, compiler-checked subset of a resource's fields. &lt;code&gt;CustomerOrderView = Order only { id; customer; total }&lt;/code&gt; declares exactly which fields downstream consumers can see. Finding every projection affected by a schema change is a structural query, not a grep through the codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outcome coverage.&lt;/strong&gt; Which operations have outcomes stubbed with &lt;code&gt;todo&lt;/code&gt;? In Ruuk, &lt;code&gt;todo&lt;/code&gt; is a compiler-tracked placeholder, not a comment. Which call sites are missing a handler for a specific variant? The answers are compiler-verified facts, not heuristic inference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State machine queries.&lt;/strong&gt; A resource like &lt;code&gt;Order&lt;/code&gt; carries its current state in its type: &lt;code&gt;Order&amp;lt;Approved&amp;gt;&lt;/code&gt;, &lt;code&gt;Order&amp;lt;Shipped&amp;gt;&lt;/code&gt;. The compiler knows which operations are valid for which states. What transitions are reachable from &lt;code&gt;Order&amp;lt;Created&amp;gt;&lt;/code&gt;? What operations apply when the order is in transit? The answers come from the declared lifecycle, queryable and independent of implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Role-based refactoring.&lt;/strong&gt; An agent told to "add audit logging to every operation that mutates order state" doesn't need to read method bodies. It queries the declared &lt;code&gt;subject&lt;/code&gt; role across every operation, identifies the affected call sites, and makes the change. The semantic structure tells it exactly where to edit and what contract to preserve.&lt;/p&gt;

&lt;p&gt;In each case, the agent spends fewer tokens reconstructing context and gets closer to a correct edit on the first pass. That's a ceiling that better tooling can't raise if the language never captured the information.&lt;/p&gt;




&lt;p&gt;Blip 18 asks how to make agents smarter about existing code. That's the right question for existing codebases, and the Radar's answers are practical.&lt;/p&gt;

&lt;p&gt;Ruuk is exploring a different one: what happens when the language itself captures enough domain semantics that agents — and humans — can reason from declarations alone?&lt;/p&gt;

&lt;p&gt;That's a bet on language design, not tooling. Ruuk is in early development, and none of this has been tested at scale with real agents. But I believe the overhead pays for itself: what Ruuk asks you to declare is what you already know. The cost isn't in knowing your preconditions and state machines. It's in not having a compiler that checks them.&lt;/p&gt;




&lt;p&gt;The language design is documented on &lt;a href="https://github.com/ruuk-lang/ruuk" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, where I'm using Discussions to think through design decisions in the open. I also write about Ruuk's design rationale here on &lt;a href="https://dev.to/matweiss"&gt;dev.to&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>software</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
