Why LLMs Need Source Code, Not Documentation
Coding agents were trained to read and modify codebases, not human documentation. When Arnaldi started using AI for Effect library development 8 months ago, adding the library to node_modules or a gitignored folder didn’t work. Agents skip both by default. Cursor doesn’t index gitignored files. Models trained on codebase operations aren’t optimized to look at node_modules with the same frequency as first-party code.
The fix: clone the library repo directly into the project so it looks like first-party code. The model treats it as its own codebase and reads it.
Strict Tooling as a Signal Floor
Arnaldi initialized a Bun project with Vitest, then swapped the default TypeScript compiler for TSGO, Microsoft’s experimental Go-based rewrite, to get faster type-checking via a native LSP. He confirmed the setup live with the TSGO compiler live setup (20:24). The critical move: set every TypeScript diagnostic from warning to error.
When all diagnostics are errors, the LLM cannot pass code that has any type warning it might otherwise ignore. A warning in an AI-driven project is a silent mistake the model will repeat across every file it touches.
Context Management and the agents.md Contract
With the project committed, Arnaldi added the Effect v4 repository as a git subtree under .repos/effect/ and wrote an agents.md pointing the AI at it. Before writing any feature code, the AI reads the Effect source, extracts patterns, and saves findings to files like patterns/http-api.md and patterns/sql.md. Each coding session opens in a fresh context window to prevent earlier decisions from contaminating later ones.
“if our job is not to write code” – Michael Arnaldi
Our job, he argued, is to configure the repository so the model can operate well on it.
ESLint as a Back-Pressure Loop
When the model produces bad patterns, Arnaldi’s response is not a better prompt. It’s a new ESLint rule. His accountability repository has thousands of lines of custom rules accumulated this way: ban as unknown as X, ban unknown (the model found never as a workaround, so he banned as entirely), ban SQL generic type parameters, force branded ID types so a userId and an orderId can’t be swapped silently.
“babysitting a junior developer” – Michael Arnaldi
Every specific rule has a story. If a rule feels oddly precise, the model did that.
Building the HTTP API from Zero Knowledge
Starting from zero Effect knowledge, Arnaldi gave GPT-5 a single prompt: build a CRUD Todo API with OpenAPI documentation and SQLite storage. The AI read patterns/http-api.md, explored the cloned Effect repo, and produced a working server with route-level schema validation, a 404 TodoNotFound error schema, and a live OpenAPI endpoint. After Arnaldi confirmed the working OpenAPI endpoint (79:32), tests had already passed.
One remaining issue: the model used plain strings for IDs. The next lint rule was obvious.
Durable Workflows for Long-Running AI Operations
A registration flow writes to a database, then sends a confirmation email. If the server crashes between those two steps, the email never goes out. The system is missing a guarantee. Effect Cluster solves this with durable workflows that survive server restarts, using the same approach as Temporal.
Arnaldi’s argument: once AI is in the stack, every operation takes minutes instead of milliseconds. At 10-millisecond response times, a server rarely crashes mid-request. At 60 seconds, it will. Even 10 users running AI-driven processes will see failures.
Notable Quotes
just clone the [ __ ] repo, which is Michael Arnaldi · ▶ 13:08
if our job is not to write code Michael Arnaldi · ▶ 48:50
babysitting a junior developer Michael Arnaldi · ▶ 1:09:10
Key Takeaways
- Clone library source into the project as a git subtree — agents read it as first-party code.
- Set every TypeScript diagnostic to error; warnings are lies the model will repeat.
- Write ESLint rules to ban each bad pattern the AI produces, not just once but permanently.