How I built a structured AI-assisted development workflow as a tech lead, where the real work happens before a line of code is written.
You open a chat, describe what you want, iterate over the output, and send something that more or less works. It feels fast. The features technically work. but nobody, including meCompletely understood what’s there. No one had thought about handling edge cases, architectures that made sense at that moment but didn’t survive the transition to the next feature. There is a growing feeling that I am creating rapidly and understanding less.
The problem I struggled with was this: How do you get the speed benefits of AI assistance without losing the clarity and intent that makes software maintainable? The short answer is that the real work happens before the coding begins.
Basic idea: thinking in writing, not in code
What is AI really good at? execution. What’s really bad about it? Figuring out what you really want, catching assumptions you forgot to clarify, and letting you know when your mental model of the problem is wrong.
That’s your job. This will always be your job.
The most valuable change I made was to treat each feature as a thinking problem first and an implementation problem second. The workflow is designed to apply that thinking before any code is written, and the AI is used to stress-test it, not abandon it.
This workflow has been adapted from Mark Pocock’s skills working with me.
workflow
Step 1: Free-Form Planning
Everything starts with a document that I write myself, in simple language, without any necessary structure. I describe the problem, my initial thinking about the solution, the constraints I know about, and the things I’m unsure about. It’s not distributable, no one reads it except me. Its sole purpose is to get the thinking out of my head and into a form I can examine.
The quality of everything downstream completely depends on the quality of this step. A vague plan creates ambiguity PRDWhich creates obscure problems, which produces code that technically runs but doesn’t do what you wanted.
Step 2: Through PRD write-a-prd
The free-form plan becomes the input for a structured interview process. Skill explores the codebase to understand the current state of things, then continuously interviews me about every aspect of the plan, walking through each branch of the design tree, resolving dependencies between decisions one by one. This is the step where bad thoughts take hold. Not because the AI is smarter than me, but because being forced to answer specific questions about your own plan reveals places where you were hand-waving. “How does it behave when the user is not authenticated?” “What if this operation partially fails?” “You said it changes an existing feature, what will happen to users who rely on the current behavior?”
The output is a structured PRD The file contains a problem statement, a solution description, a detailed list of user stories, implementation decisions (modules, interfaces, schema changes, API contracts), module designs, testing decisions, and obvious out-of-scope items. everything is outspoken. User stories are the backbone of everything that comes next. They need to be specific enough so that acceptance criteria can be clearly derived downstream, not at this stage, but when the scope is defined at the issue level.
Step 3: Sort through the issues prd-to-issues
PRD creates a bunch of issues using vertical piecesTracer bullets that slice each integration layer from beginning to end, rather than horizontal slices of a single layer. A slice that only touches the database, or only touches the UI, is not a valid slice. Each issue should provide a narrow but complete path that is demonstrable or verifiable in itself. Each issue is classified as either AFK (AI can apply and merge changes without human interaction) or hital (Requires human judgment at some point during implementation). Preferring AFK over HITL wherever possible keeps the work moving forward without hindering my focus.
Before writing anything, Kaushal presents the proposed split and asks: does the granularity feel right, are the dependency relationships correct, should anything be merged or split? The issues are written in dependency order so that cross-references between them use real numbers.
Each issue contains a brief description of end-to-end behavior, a “How to Verify” section explaining how to verify slice completion, acceptance criteria in a given/when/then format including error cases, a list of blockers, and references to user stories that address this. Everything remains in files. I work on different platforms, sometimes GitHub, sometimes GitLab, and keeping the workflow file-based means it’s not dependent on any particular tool.
Step 4: Through the tasks issues-to-tasks
Each issue is broken down into concrete, sequential tasks, one task per focused AI session. The constraint is intentional: if a task cannot be completed in a single session, it is too large. The skill explores specific parts of the codebase affected by the problem, identifies existing patterns to follow, and creates a task list with types (WRITE, TEST, MIGRATE, CONFIG, REVIEW), clear outputs, and dependency order. Schema before logic, logic before API, API before UI, tests interleaved instead of batched at the end.
Key design decisions in task descriptions: They are written as instructions for the AI that will execute them, not as notes for a human developer. Each task specifies which files to touch, which existing patterns to follow, and what the output looks like when completed. No code snippet, only intention, not implementation.
Step 5: Handoff for Code
Each job description is a self-contained prompt. When I’m ready to implement a task, I open a new session and paste the task description with the original issue for reference. The task description was written for this purpose, specifying the scope, referencing the correct files and patterns, and defining what the job looks like. The refresh reference per task is intentional. Long sessions with accumulated context go astray: the model begins to make decisions based on what it has already done rather than what the task requires. Starting cleanly with a good scoped task consistently gives better output than continuing a long session. For review tasks that are marked as requiring human judgment, I stop, make a decision, update the task file with the results, and continue. These are the moments where workflow takes hold: decisions are made deliberately, in context, not buried in long generations.
Step 6: Through Code Review code-review
Each PR undergoes a structured six-pass review before being merged. Passes include logic errors, operation ordering, bad practices, security, magical strings, and value and pattern correction.
Operation ordering deserves special attention in AI-generated code. Models produce code that does the right thing but sometimes in the wrong order: sending a notification before committing a transaction, writing an audit log after the action it should record, changing state before validating inputs. It’s easy to miss these bugs in review because the code looks perfect at a glance.
The review runs on a single file or issue, not the entire feature. The scope is deliberately narrow, catching issues at the PR level is far cheaper than discovering them later.
Step 7: Through the final audit final-audit
At the end of a feature, a cross-cutting audit looks at things that can only be evaluated across the entire implementation. Not individual bugs, they should have been caught according to the PR, but systemic issues: inconsistencies between modules, patterns that were introduced early and replicated incorrectly everywhere, security assumptions that live in isolation but are broken across the entire surface area.
Audit reads the full implementation before flagging anything, which is the point. It groups findings by severity, gives a clear overall decision on whether it is safe to leave the feature in production, and asks for approval before making any changes. Unsupervised improvements to previously merged code are riskier than improvements made during development.
What is this workflow not?
It is not fast to install. planning and PRD The steps take real time, and the temptation to skip them in favor of going straight to the code is constant. The workflow is only profitable if you truly believe that time to think before coding is cheaper than spending time debugging later.
It is also not a replacement for engineering judgment. The AI will suggest appropriate things at every step that are wrong for your specific situation. The review phase, where you evaluate breakdowns before anything is built, exists precisely because the AI’s output needs to be validated against knowledge it doesn’t have: your team’s conventions, the actual behavior of your users, parts of the codebase that contain hidden complexity.
underlying principles
Each step in this workflow has the same structure: AI generates something, you review it with full context, then it gets built. AI speeds up production. review is always yours.
The workflow is designed to make that review as effective as possible, by ensuring that when you are evaluating an issue, you have a PRD To check against; When you are evaluating a task, you have a problem to examine; And when you’re reviewing code, you have acceptance criteria to check it.
Skill
Now if you read this article till the end then you are at least eligible to connect with my skills. Check out my GitHub repo.
Read further
<a href