Founder @CohesiveSystems, Prev: Co-founder/CTO @AlvysTeam, First engineer → VPE @JetTechnology acq. by @Walmart

Del Mar, CA
Joined May 2008
Leo Gorodinski retweeted
When I was writing Unreal Engine 1, my time was divided as follows: - Around 30% went to seriously deep coding on hard problems: assembly language texture mappers, C++ BSP trees, data persistence, object oriented systems design, and networking. - Around 70% was just typing and refactoring large bodies of code needed for a complete engine feature set. This was not hard, and while I was doing it my mind was mostly on the deeper coding topics, thinking and planning for what's next. It didn't feel much different from vibe coding today, except that it was just me typing code on an IBM Model M keyboard rather than prompting it and reviewing the results. So, it has always seemed perfectly logical that we would rely on AI for that 70%, once the AI could do it with a similar quality standard as we could, which has never been perfection. It came as no surprise that, after a few years of AI model evolution, it was able to take the reigns on that 70% and free up programmers' time for more valuable tasks. What's more of a surprise is the emergence of AI as a sort of insta-Carmack able to solve hard technical problems quite cleverly and often cleanly, and that it's able to reason about and work in complex 3D scenes both by operating the tools and by directly understanding the raw data files. I abandoned assembly language in 1998 when out-of-order CPUs made much simpler C/C++ code faster, and never I missed it. If prompting through architectural documents, concept art, and design plans can transcend typing code and tweaking vertices, that will enable developers to spend their time on higher-level, higher value technical and creative tasks. What matters is the end product, whether it's a game or an engine. Anything developers can do to try out more ideas and make better software and games faster is a win for everyone.
976
1,644
394
18,786
1,603,170
Agents make code cheap. Understanding the system is still the bottleneck. Cohesive is a language for describing systems: their rules, workflows, and guarantees. People and agents work from the same model. Machines check and compile it. Here’s a brief introduction.
2
3
67
This builds on years of work by Spivak and others: databases as functors, backprop as lens composition, dynamical systems as polynomial coalgebras. Training a neural net and simulating physics fit into one framework. The heat and wave equations are a neat example: the same arrangement gives dissipative or oscillatory dynamics, depending on how you read it. Lenses, two way interfaces like forward and backward passes, have been studied categorically for decades. The new part is internalizing them: lenses become objects in the same mathematical world as the systems they connect, instead of external wiring. And it runs: a neural net and a bunch of particles both compile to executable state machines. Whats the point of all this? To build complicated systems, even autonomous ones, from parts and composition rules you understand.
7
252
Get you a language that can do both (docs and code).
Documentation is officially dead. Code and Slack are the source of truth (have always been). Codex can reconstruct a "view" into the system on demand, and tailor it to the viewer. No point in maintaining docs that will become stale the moment they are published.
3
185
Most attempts at software factories are like swapping steam engines for electric motors in plants still laid out for steam.
Our new obsession with Software Factories is weird. We've spent decades arguing what we do: is creative, doesn't fit the model of a factory, that software can't be built on production lines, and that we're not interchangeable resources. Now we're trying to prove the opposite and build software factories.
2
152
Agreed. We should be much bolder in our pursuit of abstractions. For 20+ years we’ve heard sermons on the law of leaky abstractions and along the way it became an excuse to give up. So we keep reinventing roughly the same languages and frameworks, a few knobs moved around. Lawvere once remarked that foundations had become preoccupied with sermons on incompleteness and impossibility. Software has developed its own pathology. Fine. Let it leak. Then figure out why it leaks and refine the semantics. Agents make that search dramatically cheaper.
My hot take from chatting to @poteto is that we should use MORE abstractions in the AI age You can use them (combined with harsh lint rules) to reduce the design space available to the agent and constrain them only to good decisions. Combined with the fact that high-leverage abstractions let you do more with less code - so, more token efficient. Plus, unwinding the damage from a bad abstraction is much cheaper with agents. This runs counter to a lot of folks thinking that agents just want to read the raw code. They can, but they're not maximally efficient that way. Be braver! Design abstractions.
1
5
286
Agreed on the value of programs. But “any migration is but a prompt away” goes too far. We still need an intermediate language between us and the machine. English is expressive but underspecified. Machine code is precise but divorced from the semantics we care about. That said, I doubt Rust or C++ is the right IR. There’s also a tactical matter: useful mechanisms should be captured and reused, not regenerated each time.
Replying to @dhh
The value of programs going forward will be the collection of decisions and designs that encapsulates "what does it do and how does it do it". There is no more long-term value in a Rust code base than there is in any other. Any migration is but a prompt away.
3
289
Verification power is bounded by the representation in which the system is expressed.
I'm seeing a lot of euphoria about how Opus 5.5 is good at TLA+, and this means that all software will soon be formally verified. As a person who loves TLA+ so much he wrote a book on it, I want to throw a particular cold shower on people's enthusiasm by talking about the limits of what you can actually verified with it. The high level simplification is that TLA+ sees a system as a set of "behaviors", or possible sequences of states. For example, the pseudocode "pick a random number from 1-3 and decrement it to 1" has three behaviors: `{3 -> 2 -> 1, 2 -> 1, 1}`. From here, there are two basic kinds of TLA+ properties: - `[]P` means that `P` is true in *all states* of *every behavior*. - `<>P` means that `P` is true in *at least one state* of *every behavior*. `[]P` is immediately useful as an **invariant**, or something that always be true of your system. This is things like "your data is never corrupt" or "there's always at least one server online." `<>P` is a little more abstract, but for technical math reasons I won't get into here, can be stacked with `[]` to create really complex and useful properties. `<>[]P` represents things like "the algorithm eventually converges on the right answer", `[]<>P` things like "if two data stores desync, they will eventually resync", and `[](P => <>Q)` things like "If a message is put on the queue, it's eventually processed by a worker". Really cool stuff! These primitives were chosen to make a wide array of properties useful. And if we're clever, we can do all sorts of more complex properties, like bounded time constraints and history properties. But we're always constrained to 1) define a logical formula 2) over individual behaviors, and 3) check that all behaviors satisfy that formula. So some things that we *cannot* express in TLA+: - Possibility and reachability properties: that it's always possible to *make* P true, even if you don't actually decide to. Things like "I can always shut down the computer" or "A user can always change their password". These can't be expressed with `<>P` because that's "for all behaviors, P happens at least once", we actually want "for all behavior prefixes, there is at least one behavior where P happens at least once". - Hyperproperties: properties that are defined over two or more traces. These are things like "painting a car red doesn't make it faster" or "users cannot infer secret data by observing public data". We can't do these because TLA+ only looks at one behavior at a time. - Statistical properties: 95% latency is 1ms. Impossible because most of these are hyperproperties. - Properties about if a system is robust against code changes. Impossible because, uh, you have new behaviors now. Some of these are solvable in different logical formalisms. CTL can do reachability, PRISM can do statistical properties, etc. Those have their own tradeoffs and limitations, though, and no system can do everything. Others are solvable with a lot of cleverness tailored to the specific spec, like lifting a model into a hypermodel. But these are insanely inefficient and make your "clever spec" diverge significantly from the real world system, so introduce a lot more opportunity for things to go wrong. The core problem, though, is (1): properties are logical formula. If we don't know how to express a system property as a logical formula, we can't verify it. 99% of the properties we care about fall under this. The information on the site is easy for a user to find. Our LLMs behave as we expect them to. Our application can't be used to break the law. TLA+ (and Quint and Lean and Rocq) are near-useless here, no matter how clever you are. Don't get me wrong: `[]P` and `<>P` represent a huge range of useful properties and TLA+ is incredible at finding awful concurrency bugs. But there's a lot it fundamentally can't do and we shouldn't believe that it will solve all our worries about software bugs. And the same goes for all other formal verification languages, too.
1
4
190
The SDLC increasingly optimizes for access to human attention. Complexity gut checks are still something humans do better than agents, perhaps because, for now, we haven’t found a good way to express many of those judgments explicitly.
Code reviews today are mostly about gut checking if the complexity is worth the benefits.
3
183
Code reviews today are mostly about gut checking if the complexity is worth the benefits.
11
40
12
624
32,724
Yes, you can implement durable execution with object storage and a library, and that’s very elegant. But some workflows make that expensive quickly: large state, frequent reloads, high duty cycle, etc. This suggests separating workflow semantics from execution strategy. Define the process once, then realize it with S3 durability or a long-running VM, depending on the workload.
The right architecture for durable execution depends on the size of the state, the cost of unloading and reloading it, the type of state, the duty cycle, and the mutation rate. The right answer could be long-running VMs, local snapshots, remote snapshots, S3, a DB, etc.
146
Vibe coding runs into the same wall every abstraction eventually does: generated artifacts are not the same as system meaning. The next layer is explicit semantics…something closer to a new language/compiler rather than just piles of generated code.
The Sutro team has spent the last five years doing deep engineering to build secure and reliable software. They’re now becoming part of Lovable.
1
1
5
471
Interesting paper: resource-centric control (pods, deployments, services) is the wrong layer for governing agents. They propose an intent-aware control plane: intent, policy, capability, context, decision, execution plan, plus a decision artifact recording why one plan won. That feels directionally right. The next useful abstraction for agentic systems may not be another resource model, but a model of decisions, authority, and effects.
1
116
More capable agents and more compute can automate implementation, but they can’t resolve semantic ambiguity from insufficient information (underdetermination). Agentic engineering needs semantics to elicit and accept intent, make that accepted meaning the source of both implementation and verification, and use simulation and runtime evidence to validate it against real world conditions, while focusing human attention on the decisions that actually require judgment.
1
2
152
SQL is great when all the data is in one database and the query-composition problem is simple. But real applications need to dynamically compose queries and pull and join data across heterogeneous sources. We need something with SQL’s declarative, domain-specific nature, but with a richer composition model and first-class access to heterogeneous data sources.
Somehow a 100-line SQL query is considered unmaintainable, but splitting the same logic across five services and a message queue is considered architecture.
2
277
Take this one step further: why should the agent program primarily in Rust at all? Rust is excellent when ownership, memory safety, and low-level control are central. Often, they aren’t. If agents are doing the translation, define a language for the domain itself (e.g., entities, relations, processes, transitions, invariants, capabilities). Make those definitions first-class and checkable, then lower them into Rust, C#, SQL, infrastructure, etc. Now you have accepted system meaning you can verify implementations against, and a basis for closing the conformance gap. The interesting language for agents may increasingly be the one that captures system semantics, not implementation mechanics.
At some point, developers are going to abstract away their relationship with the programming language entirely. Many already have. You pick the one that gives the best feedback to the model and produces the fewest surprises in production. This is why Rust is rising. The developers now excited about Rust would never have learned it themselves. It's a pain in the ass to write and takes forever to master. Now that LLMs write it well, the calculus changes. Better type feedback, fewer bugs, faster runtime - what's not to like? If you're not really reading the code anyway, who cares what language it's written in?
3
203
When I offer useful input to my coding agent 😂
3
123
Really interesting direction. I wonder how far this can be pushed beyond individual programs/kernels. Could we define sufficiently strong semantics for an entire system, including interactions between components, and then let a stochastic optimizer lower that into an optimized distributed realization across one or more nodes? The verification problem gets much harder, but the possibility seems fascinating. I think so.
"openai engineer explains /why/ he didn't need to understand the kernel line by line" 🙃 we're doing compilers 2.0
1
196