I'm sitting here working and just caught a handful of really bad decisions by the agent, one right after the other, cascading from an assumption that was incorrect. My ideas and architecture are sound in this codebase! Are those things simply to remain in the code if they work 'good enough', or are there consequences right around the corner?
I have found including this in my AGENTS.md to be quite transformative in this regard:
> Always use an aggressive red/green TDD-approach. It is critical to remember that in the red phase, things like module/exports import failures due to trying to import file paths that don't yet exist, exports that don't yet exist, etc. is not valid TDD. For valid TDD, the test cases must actually run. For this, you must create stubs of the expected modules and exports in the red phase, so that the test cases actually run and fail on the test case assertions themselves. In some cases, when using this approach, once in a while some of the red phase test cases might "incidentally" pass, and this is ok. Before running red phase tests you should always make predictions about the number of test cases you expect to fail/pass -- this count is not the number of test files or test suites, but rather the number of test cases. By performing these red phase expected counts of passing/failing test cases, it will help you catch errors in your prior reasoning quickly and efficiently.
> Always use a proof-driven, scientific method-based approach to validate hypotheses, assumptions, and conclusions: define the smallest falsifiable hypothesis, create or identify a reproducible failing case, gather direct evidence, make the smallest targeted change, and then re-run the same proof to confirm the issue is fixed. Avoid speculative fixes, broad rewrites, or changing multiple variables at once. When possible, preserve the reproduction as a regression test before implementing the fix. Consider that when gathering evidence, additional logging and durable files can be very helpful.
> The strict TDD and proof-driven approaches described above could be described as "proof-driven development". Try to internalize and generalize these concepts, as they are broadly applicable.
Is this for llm purposes? In many forms of TDD a compile error is key to the red phase. And you are going from red to green before asserts even exist is part of the process.
But that does come with tradeoffs, and it's not the right thing for every project. But when it does work it does increase the amount of work you get out in the same time
The problem here is that the LLM hallucinates, so
* it will tell that something is a bad idea, even when it is not. * it will miss good ideas.
But here is the thing. Even discussing with a rubber duck can do wonders to your thought process. So may people who are noticing the usefulness of this procedure might be actually just doing a slightly better rubber ducking...
The LLM will often miss the most obvious simplifications. And if I ask it to present me with six approaches how we could solve a problem, chances are we will settle on number seven or eight, both my ideas after rejecting all the other six. But those first six were still valuable for coming up with the version we actually settle on. Making the rubber-duck talk is genuinely useful.
And the rubber duck is actually pretty good at the localized grunt work, so you can spend more time talking with it about big-picture stuff
Honestly, I've found that the architecture described to and by LLMs is always a more rosy picture than what is actually generated, no matter how many times you do an adversarial review. It's less visceral than in image generation, but the pattern is the same -- the broad strokes seem fine but the details are awful.
Is that something recent? I’ve been doing this for years, even in high school where we were asked essays on contrast between different viewpoints.
I don’t need LLM to do this. It’s the 101 of any engineering process to not rush with the first thought you have and indeed try to explicitly explore the solution space and base your decisions according to defined tradeoffs.
How much of the source code of the compiler you use did you read? How much of the source code of the standard library of your chosen language did you read? What about the dependencies?
How much of the source code of a huge codebase does the average developer read? I don't think any human alive has read the majority of code in huge codebases like Word, Windows, Linux, etc.
For almost every developer, the majority of the code you use every day, whether in software you use or actual code you're shipping, is not code you've ever read. And no one seems to have a problem with it, because we've built lots of processes around this. It's only when the code is written by an AI and not a coworker or random library author that people seem to have a problem.
And I get it! AI wasn't very good at writing code two years ago. Maybe even a year ago. I think it's good now, but maybe you don't - ok, that's fine, maybe it'll only live up to your standards in a year or two or ten. But that doesn't seem to be what people are arguing, it's not "AI isn't good enough", it's "how can we possibly ship code we never read", and my point is that we've all been doing this for our entire careers.
AI/Vibecoding breaks this social trust, hence the general aversion to using those codebases or bringing LLM code in. It's not really about the general quality of the agents. It's about the code no longer being reviewed and understood by a human. How can one place trust in that? Unit tests don't replace careful review and considerate design.