Aaron Francis (Try Hard Studios / faster.dev) is a Laravel educator and developer who runs faster.dev, a platform focused on AI-assisted development for experienced engineers. He co-hosts the Mostly Technical podcast and has been building and teaching in the Laravel space for over a decade.
- X/Twitter: @aarondfrancis
- faster.dev
- YouTube
AI is a pattern matching machine
AI does not understand a codebase. It pattern matches against its training data and whatever is in context. It mirrors the quality level of whatever code it sees. Inconsistent patterns, multiple approaches to the same problem, or low-quality code in the codebase will be reproduced and compounded.
This is commonly called "AI slop": code that looks correct on the surface (consistent naming, tests present, documentation written) but lacks architectural coherence. It is harder to spot than bad code written by a human because it still looks polished.
AI has no memory of past mistakes or awareness of deprecated patterns in a specific codebase. Each generation is a fresh pattern match against whatever is in context.
References:
Write deterministic checks to enforce AI into a box
Rather than relying on prompt files like AGENTS.md or CLAUDE.md to guide AI
behaviour, the preference is deterministic enforcement via linting rules, static
analysis, and architecture tests that fail the build if the AI produces code that
violates standards.
Aaron's own framing from LinkedIn: "Deterministic guards > AGENTS.md". His coding
agent kept hand-rolling checks for things that already had existing functions in
the codebase. Adding more rules to AGENTS.md is a soft constraint the model can
ignore. A failing lint check is not.
Relevant tools for Laravel/PHP:
Laravel Pint - code formatter built on PHP CS Fixer, ships with new Laravel
projects. Configurable via pint.json.
PHPStan / Larastan - static analysis. Larastan adds Laravel-specific understanding of Facades and Eloquent. Level 5 is a reasonable starting point.
Pest architecture tests - enforce structural rules such as "controllers must not contain business logic" or "all service classes must implement an interface". These fail like any other test.
Rector - automated refactoring tool. Can enforce patterns and handle version upgrades.
References:
- Aaron Francis on LinkedIn
- Building a Code Quality Pipeline in Laravel - DEV Community
- Laravel Code Quality Tools - Honeybadger
- faster.dev - Init Commands and Guardrails
Single ingress layer / interfaces
All entry points to a system should adhere to a defined interface. If AI generates code that needs to interact with a service or module, it is forced through the defined contract rather than directly accessing implementation details or producing its own approach.
This is a standard software design principle applied specifically as a constraint on AI generation. If the interface is the only public surface, the AI has less opportunity to bypass it.
Pest architecture tests can enforce this. A test can fail if any class in a given namespace directly instantiates a concrete implementation instead of depending on an interface.
Every mistake becomes a rule
When AI produces code with a problem (wrong pattern, wrong library, wrong approach for the codebase), encode the fix as a deterministic rule so it cannot happen again rather than just correcting it manually and moving on.
This matches Aaron's approach on faster.dev: updating init and rules files so the same issue is caught automatically on the next generation. A practical implementation is maintaining a list of patterns the AI consistently gets wrong in a specific codebase and turning each one into a linting rule or a Pest architecture test.
References:
"Slop it out" - iterate from there
Generate a rough first pass from the AI without over-constraining the generation, then apply human judgment and the deterministic checks above to shape it into production-quality code. Trying to write a perfect prompt that produces perfect output adds overhead that often outweighs just generating, reviewing, and correcting.
Keep AI in boxes
The overall frame of the talk. AI produces better results when operating within well-defined boundaries: specific tasks, constrained interfaces, deterministic checks on output. Less constrained contexts lead to inconsistent patterns, bypassed abstractions, and code that works in isolation but does not fit the codebase.
Boxes in practice:
- Interfaces that enforce ingress points
- Linting rules and static analysis configured to fail on violations
- Pest architecture tests that enforce structural constraints
- Scoped tasks rather than open-ended generation
References:
Notes from Laravel Live UK 2026.