# Rodrigo N. Isabelo Jr. (Regs) — full text > Rodrigo Isabelo (Regs) — engineering lead and full-stack developer specializing in AI, Laravel, and AWS. Concatenated Markdown for language models. Individual pages also live at the `.md` URLs in `/llms.txt`. --- # Rodrigo N. Isabelo Jr. (Regs) > Rodrigo Isabelo (Regs) — engineering lead and full-stack developer specializing in AI, Laravel, and AWS. An engineering lead who is still in the editor most days, a full-stack engineer at heart who fell in love with AI along the way. I lead by teaching: running workshops, watching the people around me outgrow the roles they came in with. I build what customers actually need, not the cool feature nobody uses. If a user can’t say “finally,” it’s a science project, not a product. ## Pages - [Experience](https://regsisabelo.com/experience.md): Roles and highlights - [Projects](https://regsisabelo.com/projects.md): Selected work - [Stack](https://regsisabelo.com/stack.md): Languages, frameworks, AI, cloud, and engineering tools - [Recommendations](https://regsisabelo.com/recommendations.md): Colleague recommendations - [Certifications](https://regsisabelo.com/certifications.md): Credentials - [Blog](https://regsisabelo.com/blog.md): Field notes ## Metrics - **15+** Engineers led — 5 teams, 8 product families - **16** Projects built — platforms, frameworks, tools - **13** Workshops run — Laravel, testing, security, RAG - **3** Public talks — PSITE, AI Pilipinas, USJ-R ## Talks - [Reverse-engineering AI-generated code](https://www.linkedin.com/posts/rodrigo-isabelo-jr_multiplaitech-aipoweredpeople-usjr-activity-7323630453616214016-aZO-) — USJ-R SCS Days · 29 Apr 2025. Guest talk for 300+ students in the School of Computer Studies. - [Bridging the IT skill gap in the age of AI](https://www.linkedin.com/posts/rodrigo-isabelo-jr_psitenatcon2025-goteam-aipoweredpeople-activity-7308773812047646720-Ks0t) — PSITE National Convention 2025 · Mar 2025. Fireside chat on workforce skills and AI. - [RAG in production](https://www.linkedin.com/posts/rodrigo-isabelo-jr_aipilipinascebu-goteam-multipaitech-activity-7218094427100053504-X15p) — AI Pilipinas Cebu · Jul 2024. Guest talk on shipping retrieval systems, second time with the community. ## Contact - Email: [regs.isabelo@gmail.com](mailto:regs.isabelo@gmail.com) - Site: [https://regsisabelo.com](https://regsisabelo.com) - Role: Engineering lead --- # Experience > Roles and highlights for Rodrigo N. Isabelo Jr. ### Lead of Software Engineering **GoTeam** · May 2025 – Aug 2026 Five teams, fifteen-plus engineers, eight product families — and still the principal author on the systems that matter most. - Directly managing six engineering reports across ten concurrent projects, while maintaining roughly seventy percent hands-on involvement in the codebase to keep architectural decisions grounded in real implementation. - Principal author on a ground-up rewrite of the flagship AI Agent and Workflow Builder platform, from ideation to deployment. - Established engineering code standards, best practices, and agentic engineering workflows — lints, unit testing, and CI/CD pipeline safeguards — raising code quality across every team. - Built observability and troubleshooting utility tools for QA and product teams, and ran workshops to train them on it — cutting engineering intervention on incident escalations by roughly 40%. - Established a clear communication discipline for time-sensitive action items, cutting resolution time significantly with zero repeat escalations since. - Established a cybersecurity protocol across infrastructure and third-party services — zero key leakage and zero operational discrepancies since, preventing any large-scale security breach across the AWS environment. - Authored a forty-seven-document engineering operations handbook, with a clear business continuity plan and structured knowledge transfer, so critical engineering knowledge no longer depends on one person. ### Lead AI Implementation Engineer **GoTeam** · Dec 2023 – May 2025 Built the company’s AI practice from a blank page — three products live in under a year, and a framework that made the next ones faster. - Built the company’s AI practice from zero, shipping three AI products to production within ten to twelve months — all still in active business use today. - Sole-authored the company’s in-house RAG and agentic framework — eight subsystems spanning five model providers and three vector stores — reducing provider migration from a full rewrite to a single configuration change. - Established Pinecone-based retrieval infrastructure ahead of industry adoption, resulting in a data ingestion and retrieval pipeline that still powers five-plus products today. - Established preventive security controls — AWS WAF, CloudTrail alerting, and least-privilege access — as the default posture across the AWS environment. - Designed and implemented a CI/CD pipeline with automated static analysis, testing, semantic versioning, and changelog generation, cutting release cycle time company-wide by an estimated 30%. - Founded and ran an internal engineering workshop series — thirteen sessions on Laravel best practices, security, RESTful API design, and RAG — establishing the team’s working standard from within. - Established OKRs for the team and every product under it, giving each engineer a measurable outcome directly tied to company goals. ### Full-Stack Developer **GoTeam** · May 2021 – Dec 2023 The person who brought AI into the building — first chatbot, first retrieval patterns, the foundation everything after was built on. - Shipped the company’s first AI chatbot using OpenAI and Pinecone, establishing the retrieval pattern that the in-house AI framework was built on two years later. - Extended AI into recruitment and training by building an interview-simulation tool and a presentation-practice tool, both still active in the workflow today. - Started the company’s AI adoption in 2022, a year ahead of the industry’s ChatGPT-driven rush, resulting in research projects that cut manual workload across several departments by an estimated 25%. - Built complex first-party features from scratch, including a form and business-card builder and a Gantt-chart task-management module, while establishing the Vue.js and Laravel coding standards the rest of the team built against. ### Senior Front-end Web Developer **WhiteBelt Inc.** · Oct 2020 – May 2021 Primary front-end owner — and the one who pushed the product toward a real API-driven split. - Rebuilt the front-end architecture around services and models mirroring the back end’s MVC pattern, serving as the primary contributor on every screen shipped during the tenure. - Pitched and led the initiative to fully decouple front end from back end, migrating the product onto an API-driven architecture. ### Front-end Web Developer **AGuyIKnow IT Business Solutions** · Nov 2018 – Oct 2020 Rebuilt how the product’s front-end was structured, then taught the next developers to ship the same way. - Rebuilt an estimated 30% of the product’s front-end infrastructure solo, supervised the junior developers who maintained it, and led internal process improvements that raised the team’s overall output quality. ### Web Developer (Internship) **University of San Jose-Recoletos** · Mar 2017 – Oct 2018 Shipped systems the university still runs — including Bellsys, the campus bell scheduler, years after I left. - Delivered a second system alongside Bellsys — an IoT controller built in Java managing air-conditioning, lighting, and temperature monitoring for the university’s data center. --- # Projects > Selected work by Rodrigo N. Isabelo Jr. ### AI Agent & Workflow Platform (v2) **2025** · [link](https://app.rea.pro) Principal author on the second-generation rewrite of the company’s flagship AI agent and workflow platform — from architecture through production deployment on AWS while v1 continued serving live traffic. Skills: Laravel, Vue.js, AWS ### AI Voice Interview Platform **2025** · [link](https://interviewroom.ai) End-to-end AI voice-interview platform deployed behind Aurora and ElastiCache, shipped with 51 architecture decision records and a full data migration contract. Skills: Laravel 13, Next.js, React, AWS ### In-house RAG & Agentic Framework **2024** Sole-authored framework putting five model providers and three vector stores behind a single configuration switch — changing provider became a config edit, not a rewrite. Skills: Laravel, Pinecone, Qdrant, OpenAI, Anthropic ### AI Customer Support System **2024** AI-first customer support product built on the in-house retrieval pipeline, operational and in daily business use. Skills: Laravel, Nuxt, RAG ### AI Recruitment Screening Tool **2024** Screening tool for talent acquisition with a Position Templates Builder that generates complete job descriptions from a short role overview. Skills: Laravel, Nuxt, LLM ### Company AI Chatbot **2022** The company’s first AI chatbot — established the retrieval patterns later formalized into the in-house AI framework. Skills: Laravel, Vue.js, OpenAI, Pinecone ### Bellsys **2018** Bell scheduling system built for the University of San Jose-Recoletos that remains in use by the institution today. Skills: PHP, JavaScript ### trait.js **—** · [link](https://www.npmjs.com/package/trait.js) JavaScript package solving the single-inheritance limitation of JavaScript, published to the npm registry and used across personal projects. Skills: JavaScript, npm --- # Stack > Tools and skills used by Rodrigo N. Isabelo Jr. Featured items are bold. ## Languages - **PHP** - **JavaScript** - **TypeScript** - Java - **SQL** - HTML - CSS ## Frameworks & Libraries - **Laravel** - **Vue.js** - **Nuxt** - **Next.js** - **React** - Inertia.js - Bootstrap - **Pest** - PHPUnit - PHPStan - Larastan - Laravel Pint - Laravel Sail ## AI & ML - **RAG** - **LLMs** - **AI agents** - Agentic workflows - ReAct loops - Tool calling - Function calling - Embeddings - Vector search - Semantic search - Prompt engineering - Document chunking - Data ingestion pipelines - Model evaluation - **OpenAI** - **Anthropic Claude** - Google Gemini - **Pinecone** - **Qdrant** - Typesense - Algolia ## Cloud & Infra - **AWS** - EC2 - S3 - RDS - **Aurora** - Lambda - CloudFront - API Gateway - ECR - Route 53 - VPC - SQS - ElastiCache - IAM - CloudTrail - CloudWatch - SNS - AWS WAF - Security Groups - ACM - **Laravel Vapor** - Laravel Forge - **Docker** - **Terraform** - Nginx - Linux - Serverless - Load balancing ## Data - **MySQL** - **Redis** - Database schema design - Query optimisation - Data migration - Indexing ## Engineering - **REST API design** - **System design** - Software architecture - **Architecture decision records** - Design patterns - Object-oriented programming - Code review - **Automated testing** - Static analysis - **CI/CD** - Bitbucket Pipelines - GitHub Actions - Git - Semantic versioning - Incident response - Root cause analysis - Production support - Cybersecurity remediation - Secrets management - Least privilege - Technical documentation - Confluence - Jira ## Leadership & Delivery - **Technical leadership** - Team leadership - Mentoring - Coaching - Stakeholder management - Executive communication - Agile - Scrum - Sprint planning - Backlog management - OKRs - Cross-functional collaboration - Knowledge transfer - Succession planning - Onboarding documentation - Public speaking --- # Recommendations > What colleagues say about Rodrigo N. Isabelo Jr. ### Gilbert Quilab *Product Manager* > First thing that comes to my mind is the upskill. Regs is the type of developer that shares best practices to the team, very efficient very effective. Many great things happen, highlighting that enablement of a product manager who just joined, that answers questions very fast and accurately. He basically makes our work very easy. Easy going, a teacher, a great leader, skillful. AI skill, logical mindset. ### Riza Antonio *Product Support Specialist* > Regs and I have worked together on multiple projects. He has always shown determination in making sure he delivers what the team, product, and business need. Most of the products he developed are now being used. He shines especially when working on AI-powered applications, and many of our users have enjoyed and appreciated them. I also appreciate how he recognizes the contributions of other team members, which is something I value most about him. Regs is the master of AI. If you have questions about coding or AI, I would definitely recommend Regs as someone who can help. One of his strengths is how he shares his ideas and plans. It is rare to meet someone who can explain work-related ideas in a way that makes sense to everyone. He communicates his thoughts clearly and makes sure others understand what he means. ### Isaac Manubag *Lead Fullstack Developer* > I remember a time when there were many back-and-forth meetings, and at times the objectives were not entirely clear. Despite the challenges, Regs demonstrated strong leadership by taking control of the situation and driving the discussions forward. What I particularly admired was how he went beyond his technical expertise and showcased exceptional people and leadership skills. He was able to navigate complex stakeholder discussions, build alignment, and provide direction when it was needed most. It was a great example of how his strengths extend far beyond the technical domain and into effective leadership and collaboration. I would describe him as someone who is highly dependable and trustworthy. If a new colleague asked me who they could confidently rely on for guidance or important decision-making, he would be one of the first people I'd recommend. ### Owen Banan *Senior Fullstack Developer* > I was amazed at how Regs wrote the ground rules and docs from scratch. Everything on the dev side felt seamless because the backbone of the project was already set up. He did the unglamorous groundwork that made the rest of us faster without realizing it. I also appreciated how he kept things clean and intentional: the commit conventions, the scope rules, the way the repo was organized. It's easy to take that for granted until you work on a project that doesn't have it. > > If I'm describing Regs to someone new, I'd say he's the person you go to when you're stuck. Not in a "he'll fix it for you" way, in a "he'll actually listen and help you think through it" way. You can open up to him about blockers, concerns, things you're unsure about, and he won't make you feel like you should've figured it out already. He's the kind of teammate where you can drop a "hey, I'm not sure about this" and walk away with both an answer and a bit more confidence. He's also just genuinely reliable. When he says he'll handle something, it gets handled, and handled well, not rushed. You don't have to follow up or double-check. That kind of consistency builds trust fast, and after a while you just stop worrying about the pieces he owns because you know they're in good hands. And it's not just about the work. He genuinely looks out for the people around him. He'll do his best within his power to help, and when something needs to go higher up, he's not afraid to bring it up. He's the kind of colleague who remembers that we're people first, not just contributors. That's rare, and it matters more than people admit. > > The thing that highlights him the most for me is how eager he is to discover new things, and that matters more right now than it ever has. We're in the AI era where something new drops almost every week. A lot of people get overwhelmed by that pace and stick to what they know. He doesn't. He runs toward it. ### Grace Unson *Product Owner* > We only worked together for a relatively short period, but what stood out to me was how quickly Regs could move from a single sync-up discussion to delivering results. I remember being impressed by how efficiently he worked through tasks and how confidently he navigated complex technical topics. It was clear why so many people looked to him as a subject matter expert and trusted his judgment. I would describe him as one of the most knowledgeable and dependable engineering leaders I've worked with. He's highly respected by both leadership and peers, not only because of his technical expertise but also because of how approachable and humble he is. He has a rare ability to explain complex concepts in a way that is easy to understand while still maintaining the necessary technical depth. His greatest strength is his ability to combine deep technical expertise with excellent people skills. Many experts are technically strong, but far fewer are also kind, respectful, and generous with their knowledge. He consistently earns people's trust through both his competence and his character, which is why so many teammates look up to him. ### Kyren Mearr Cabellon *Solutions Architect & Everythinger | Building Orbis in Public* > Regs is an emerging leader in our team — he excels not only technically but also in communication and leadership. A very great team player and has a passion for process improvement. Always willing to go above and beyond, and that makes him outstanding. --- # Certifications > Credentials held by Rodrigo N. Isabelo Jr. - [Growing Relationships as a Manager](https://www.linkedin.com/learning/certificates/d59f16f2071bde7a2a9a01170108ee2740a8ab72a40f2b580e75fb3c37df46e3) — LinkedIn Learning · 2025 - [Leadership Foundations](https://www.linkedin.com/learning/certificates/2dfe66a599f0c48396b87386d5b8b222e4a75b0d6b09d8211215eb775b53b7ce) — LinkedIn Learning · 2025 - [CSS Certificate](https://www.hackerrank.com/certificates/33954eebc287) — HackerRank · 2021 - [Rest API (Intermediate)](https://www.hackerrank.com/certificates/293eff21796d) — HackerRank · 2021 - [Problem Solving (Basic)](https://www.hackerrank.com/certificates/c786a7ed0702) — HackerRank · 2021 --- # Blog > Short, opinionated notes on building software that ships. ### [Every REST convention already has a file in Laravel](https://regsisabelo.com/blog/every-rest-convention-already-has-a-file-in-laravel.md) *2026-08-15* Route, middleware, Form Request, controller method, Resource. I keep finding all five rebuilt inside one method, and Laravel already named the file. ### [I write the spec before I open the coding model](https://regsisabelo.com/blog/i-write-the-spec-before-i-open-the-coding-model.md) *2026-08-15* I plan with the best model I have, then hand a fast one a short spec with no code in it. Three studies say the same thing I feel every week: the agent isn't the expensive part. The re-explaining is. --- # Every REST convention already has a file in Laravel *2026-08-15* > Route, middleware, Form Request, controller method, Resource. I keep finding all five rebuilt inside one method, and Laravel already named the file. Most Laravel APIs I review aren't wrong about REST. They're wrong about where REST lives. The developer knows the endpoint should be a noun, knows input needs validating, knows the response shouldn't leak a password hash. Then they do all three inside one controller method. Laravel already has a file for each of those. A request travels a fixed path from the route to the JSON, and every REST convention I care about belongs to exactly one stop on that path. The mistake isn't ignorance of REST. It's putting REST in the wrong place. That's the pipeline: 1. `Route::apiResource` maps the HTTP verb to a controller method 2. middleware decides whether the caller gets in at all 3. a Form Request authorizes the action and validates the payload 4. the controller method does the work 5. an API Resource decides what the client is allowed to see Five stops. If you can say which stop a rule belongs to, you can find it three months later. ## The route declares the contract, not the controller One line replaces five route definitions and, more importantly, five naming decisions: ```php Route::apiResource('posts', PostController::class); ``` | Verb | Path | Method | | --- | --- | --- | | `GET` | `/posts` | `index` | | `POST` | `/posts` | `store` | | `GET` | `/posts/{post}` | `show` | | `PUT`, `PATCH` | `/posts/{post}` | `update` | | `DELETE` | `/posts/{post}` | `destroy` | The verb carries the operation, so the path stays a noun. `GET /getPosts` and `POST /updatePostStatus` are the same mistake twice: an operation smuggled into the URL because the verb wasn't trusted to carry it. Route model binding comes free. `{post}` resolves to a `Post` instance before your method runs, and a bad ID is a 404 you didn't write. When a resource genuinely doesn't need all five, say so in the route rather than leaving a dead method behind: ```php Route::apiResource('posts', PostController::class)->only(['index', 'show']); ``` `php artisan route:list` is the cheapest review I know. If the output has a verb in a path, or two routes that do the same thing, that's the review comment. Nobody has to read a controller first. ## Middleware is the door, not the guard This is the stop people skip when they describe the path, and it matters that it comes *before* validation. Authentication, throttling, and anything that applies to a whole group of routes happen here: ```php Route::middleware(['auth:sanctum', 'throttle:api'])->group(function () { Route::apiResource('posts', PostController::class); }); ``` Custom middleware is rare, and it should stay rare. It's the right place for a check that has nothing to do with a specific record: an inactive subscription, a tenant the caller doesn't belong to, an API version that's gone. It's the wrong place for "can this user edit this post," because middleware runs on the route, not on the model. That's the test I use: if the rule needs to load the record to answer, it isn't middleware. It's a policy, one stop down. ## One Form Request per operation Not one per resource, and never one class with a `switch` on the HTTP method. `StorePostRequest` and `UpdatePostRequest` are different contracts. Create requires a title; update usually doesn't. Collapsing them is how a required field quietly becomes optional. The rules should read like documentation, because they are the only documentation that can't go stale: ```php public function rules(): array { return [ 'title' => ['required', 'string', 'max:255'], 'body' => ['required', 'string'], 'category_id' => ['required', 'integer', 'exists:categories,id'], 'published_at' => ['nullable', 'date', 'after_or_equal:today'], ]; } ``` Be specific. `'title' => 'required'` accepts an array, an integer, and a 60,000-character essay. Every field gets a type, and a bound if the column has one. Then write the messages. This is the part that gets skipped, and it's the part that pays for itself: ```php public function messages(): array { return [ 'category_id.exists' => 'The selected category no longer exists.', 'published_at.after_or_equal' => 'A post cannot be scheduled in the past.', ]; } ``` A 422 is not a failure of the API. It's the contract working. But "The selected category id is invalid" sends someone into the debugger, while "The selected category no longer exists" ends the conversation in Slack. The error message is where you decide how long the next bug takes to resolve. Authorization sits in the same class, at `authorize()`, and it runs before the rules do: ```php public function authorize(): bool { return $this->user()->can('update', $this->route('post')); } ``` Inline is fine when the rule is genuinely one line and lives in one place: `return $this->user()->is_admin;`. The moment the same condition appears in a second request class, it belongs in a policy. A policy is a named, testable, reusable object. An `if ($user->id === $post->user_id)` copied into three actions is three places to forget. What `authorize()` must never be is `return true` "for now." Valid input is not permission, and "for now" is how it ships. ## Stick to the five methods The controller gets `index`, `store`, `show`, `update`, `destroy`, and nothing else. Type-hint the Form Request so validation and authorization are already done by the time the body runs: ```php public function store(StorePostRequest $request): JsonResponse { $post = Post::query()->create($request->validated()); return PostResource::make($post) ->response() ->setStatusCode(201); } ``` `$request->validated()`. Not `all()`, not `input()`. If a field isn't in the rules, it doesn't reach the model. That plus an explicit `$fillable` is the whole defense against a payload that sets `is_admin`. When you want a sixth method, you usually want a sixth resource. "Publish a post" isn't a verb on `PostController`; it's `POST /posts/{post}/publication`, or a `PostPublicationController` with a `store`. Naming it as a resource keeps the route a noun and gives the new operation its own Form Request and its own policy check, which is what you actually wanted. Keep the body thin. Authorize and validate at the edge, do the work, return a Resource. When the query grows past a line or two (filters, search, joins), it moves to a repository the controller injects, so the query is testable without an HTTP request. That's a reuse decision, not a REST one. A repository is not what makes an API RESTful. ## The Resource decides what leaks `return $post` is the most common accidental disclosure I find. The model is a persistence object. It carries every column in the table, every relation someone eager-loaded for an unrelated reason, and whatever `$hidden` protected until the day someone edited that array. The client then depends on all of it, including the fields you never meant to publish. A Resource makes the payload an explicit list of keys: ```php public function toArray(Request $request): array { return [ 'id' => $this->id, 'title' => $this->title, 'body' => $this->body, 'published_at' => $this->published_at, 'author' => UserResource::make($this->whenLoaded('author')), ]; } ``` Two rules I hold to here. Keep the key names the same as the columns unless there's a real reason to differ. A rename feels tidy on day one and becomes a translation layer nobody maintains. And order the payload the way the data is shaped: own attributes first, then loaded relationships. The rule that matters most is harder. A Resource transforms data. It does not fetch data. `$this->author->name` inside `toArray()` is an N+1 waiting for a list endpoint: one query per row, invisible in a single-record test, fatal at a thousand. That's what `whenLoaded` is for: the relation appears if the controller eager-loaded it, and is omitted if not. Collections go through the Resource too, so pagination keeps one envelope across the whole API: ```php public function index(): AnonymousResourceCollection { return PostResource::collection( Post::query()->with('author')->latest()->paginate() ); } ``` `with('author')` in the controller, `whenLoaded('author')` in the Resource. The controller owns what gets loaded; the Resource owns what gets shown. ## Test the failures first Write the failing case before the happy path. A test that has never failed hasn't been shown to work, and a happy-path test tells you nothing about the two things that actually break in production: bad input and the wrong caller. ```php it('rejects a post without a title', function () { actingAs(User::factory()->create()) ->postJson('/api/posts', ['body' => 'no title']) ->assertStatus(422) ->assertJsonValidationErrors('title'); }); it("forbids editing another user's post", function () { $post = Post::factory()->create(); actingAs(User::factory()->create()) ->putJson("/api/posts/{$post->id}", ['title' => 'hijacked']) ->assertStatus(403); }); ``` Assert the status code, then the shape. 422 for invalid input, 403 when an authenticated caller isn't allowed, 404 only when revealing that the record exists would itself be the leak. Those three numbers are the contract as much as the JSON is. ## What I don't want to see - `$request->all()` passed into `create()` or `update()` - `return $post` or `return $post->toArray()` from a controller - a verb in a route path - one Form Request handling both create and update - `authorize()` returning `true` with a comment - a relationship accessed inside `toArray()` that nothing eager-loaded - a controller method that isn't one of the five, doing what a new resource should do None of that is a REST failure in the abstract. Each one is a rule put at the wrong stop: validation in the controller, authorization in the middleware or nowhere, the response shape decided by whatever Eloquent happened to hydrate. Laravel already named the file for each of them. Using the right one every time, and not only when the endpoint feels important, is the entire discipline. --- # I write the spec before I open the coding model *2026-08-15* > I plan with the best model I have, then hand a fast one a short spec with no code in it. Three studies say the same thing I feel every week: the agent isn't the expensive part. The re-explaining is. By the fourth prompt I'm not building anything. I'm repeating myself. The same validation rule. The same repository. The same five controller methods, said to an agent that invented a sixth one while I was typing. That repeating is the bill. The code is cheap. So I stopped opening the coding model first. I write a short spec, using the best model I have that day. Then a fast model builds it. 1. the best model I have writes the spec 2. the spec holds the flow and the rules this repo already follows. Never code. 3. a fast coding model builds it, preferably one that still reasons 4. the file goes to the next person, so the standard isn't stuck in my chat history ## Planning gets the best model I have This is the one thing I won't downgrade. Bugfix, new feature, a folder that doesn't exist yet. Same rule. Whatever the strongest reasoning model I have access to that day is the one that writes `spec.md`. It's the right place to spend the money because planning is judgment, not typing. What's in scope. What the service layer already covers. Where the flow branches. What "done" means when the ticket is one paragraph long. A cheaper model will still hand me a document. It just hands me one with all the ambiguity left in it, and I pay for that ambiguity later, during the build, when it's expensive. The planning session ends when the spec reads clean. I don't let that model write the feature. ## The coding model only has to be fast and obedient Building is volume. Lots of files, lots of small edits, lots of test runs. I want something quick enough to stay in the loop with me that still thinks for a second before it edits. A reasoning coding model. When the budget is tight, a non-reasoning model like Composer is a genuinely good deal. It's fast and it follows a tight spec closely. It falls apart on a vague one. That's the whole trade, and the spec is what makes the cheap side of it safe. Either way, neither one opens before `spec.md` exists. ## The spec holds the flow, never the code I don't put code in a spec. The moment I do, the agent copies it word for word, and now I'm maintaining two versions of the same class that drift apart by Thursday. What goes in instead is the business path (a flowchart or plain pseudocode) plus the patterns this project already chose. Repository, service layer, one validation step per operation, the formatter that's already running. I name the pattern. I don't rebuild it in Markdown. ```text # Cancel an order ## Flow customer taps cancel on an order → order already shipped? reject, with a reason → not their order? reject, forbidden → cancel through the order service, refund through the existing gateway call → notify the warehouse, return the updated order ## Keep - one validation step per operation - queries live in the repository, not the controller - money changes go through the service, never a controller - the formatter and lint rules this repo already runs, unchanged ## Done - a shipped order cannot be cancelled - another customer's order returns forbidden - a partial refund does not double-refund - the response doesn't leak the internal warehouse status ``` Greenfield or a ten-year-old app, same shape. On a new project I write the patterns I want invented once. On an existing one I point at what's already in the tree. For a Laravel API, that's the [five stops a request already travels](/blog/every-rest-convention-already-has-a-file-in-laravel). Either way the file describes the shape. The code is the output. A clear PRD and a real UAT make the spec sharper, and they aren't a requirement. A thin ticket still gets a spec. A thin ticket is exactly when I need one. ## What this looks like on a Laravel ticket Here's the whole loop, on a normal ticket: *customers should be able to cancel an order before it ships.* 1. I open the planning model first and point it at the parts it needs: `routes/api.php`, the `Order` model, the `OrderService` that already exists. I ask for a spec, not code. Flow, rules, done list. 2. I read it. This is the part that pays. Reading the flow out loud is where I notice nobody said what happens to an order the warehouse already picked but hasn't shipped, and that a partly refunded order would hit the gateway twice. Fixing that in the spec is one sentence. Fixing it after the build is a pull request, a review, and a second round of testing. 3. Once it reads clean I open the fast coding model and say implement `spec.md`. It writes the `CancelOrderRequest`, the policy check, the service method, the button on the order page, and the Pest tests for the two rejections. I review a diff instead of a conversation. 4. When it gets something wrong, and it does, I fix the spec and run implement again. I don't patch it in the chat. Patching the chat means the fix lives in a thread that closes tonight. Patching the file means the next ticket, and the next person, get it too. A conversation also guesses early and sticks. That's my sixth controller method. Decided in prompt one, then four more prompts arguing with a decision I never made. That's where the prompt count drops. I'm not explaining the repository pattern every session. I'm not listing which controller methods exist. And two engineers on the same team now ship the same shape, because the standard is a file in the repo instead of whatever each of us happened to type. ## Twenty tickets, and nine that buy nothing Someone measured the part I was only feeling. A [preregistered benchmark of 24 coding tasks](https://arxiv.org/abs/2608.01347) ran the same fixes twice: once with the scope, the acceptance criteria and a stop rule written down, once with just the wish: *something in here is producing wrong results, improve it.* Leave the scope vague and the model thinks 44% harder to land the same fix. It also lands it less often: 83% of the time, against a near-perfect record when the scope was written down. Forty-four percent is nothing on one ticket. Line up a month of them, say twenty, and it stops being nothing. Same twenty tickets, same models, same people. Nine tickets' worth of spend that bought no feature and no test. Just an agent working out decisions that had already been made, and getting them wrong more often while it did. The honest limit: those were small tasks, at most four files, and the only thing that changed was the prompt. Nobody has measured a real month, so the nine is one ratio stretched across twenty, not my invoice. I use it as a direction. ## The model gets lost in the chat These papers are why the spec is a file, not a thread. Same models. What they changed is how the work was handed over. **A file is the whole brief in one go. Chat is the same brief, one piece at a time.** Microsoft Research and Salesforce ran the same jobs two ways, across 15 models ([Laban, Hayashi, Zhou, and Neville, 2025](https://arxiv.org/abs/2505.06120)). Hand over everything in the first message and it does the job. Drip the same facts across a conversation and the score falls 39%. The answers swing around more than twice as much. Then they pasted those pieces into one ugly bullet list, no polish, and the score came back, about 95%. So it isn't the writing. It's handing everything over at once. That's `spec.md`, and it's why mine look like that cancel-order list. The model also guesses on turn one and doesn't climb back out. That's the sixth controller method, measured. **Gaps cost more than long prompts.** The same benchmark as the 44% found the other half. Splitting one task across two turns cost 31% more thinking. Restating the same requirements at length (a much longer prompt, no new information) cost nothing, about 1.0×. Length isn't what the model charges for. Undecided things are. I close those in the spec, not in prompt five. **I can't feel which way a session went.** METR ran a real randomized trial ([Becker, Rush, Barnes, and Rein, 2025](https://arxiv.org/abs/2507.09089)): 16 experienced developers, 246 real tasks, in repositories they'd worked in for years. With AI tools they were 19% *slower*. They finished believing they'd been 20% faster. A file is something I can check tomorrow. My sense of how fast today felt isn't. ## What I don't want to see - the coding model opened before `spec.md` exists - a spec that pastes a controller, a validation class, or a migration - the expensive model writing every line of the feature - a cheap model handed a vague ticket and told to just build it - the repository pattern explained again in prompt five - a fix that lives in the chat instead of the file - a different standard per teammate, because the rules lived in someone's history None of that is the model's fault. It's starting in the wrong session, or putting code in the file that was supposed to constrain it. I write the spec first. Then I open the coding model.