Question 01Fully unlocked sample
A strong answer sounds like a loop the candidate actually runs, with a check they can name at every single step
What an AI-prepared candidate might say
I use it pretty much all day, honestly. Mostly for the routine stuff, so boilerplate, test scaffolding, refactoring, explaining code I haven't seen before. Everything it gives me I treat as a first draft and review before it goes anywhere. For bigger tasks I break the work into steps and prompt it one step at a time, and I paste in the relevant bits of our codebase so the suggestions fit our patterns. I make a point of understanding the code before I commit it. It's good for learning new APIs faster too, not just writing code. Basically it handles the repetitive work so I can spend my time on design and the harder problems. The assistant suggests, and I stay in control of what actually ships.
Senior
Honestly it's a loop with checkpoints, and the checkpoints are where the real work happens. Decomposition comes first, and I don't hand that part off. Before I prompt anything I split the task into slices small enough that I can read each resulting diff completely, usually one function, one module boundary, or one behavior change. And the prompt for each slice reads like a little spec. Inputs, outputs, the edge cases that have to hold, the error behavior I expect. Because an underspecified prompt just returns the model's statistical default, and the default is usually the happy path.
Then after every accepted slice, something runs. Might be the unit test for that slice, might be the type checker, might be a probe in the REPL. That one rule does most of the work for me. And I never stack a second generation on top of an unverified first one, I got burned on that early, two unverified layers cost more to bisect than they ever saved to produce.
When I read a diff I look hardest at the places generated code fails most often. Swallowed errors. Cleanup that's missing on an early return. An API that looks plausible but belongs to the wrong runtime version. The fluent happy path gets less of my attention, since that's the part the model gets right anyway. I also know when to stop. If the model has looped twice on the same correction I abandon it and write that slice by hand. The assistant compresses typing and recall. The decomposition, the spec, the read, the run, those stay mine. And I can point to each of those checkpoints in the last change I shipped, not just describe them in the abstract.
Staff
Once you zoom out to the team, the interesting effects are economic. Assistants raise the volume of plausible code per engineer-hour while review capacity stays flat, so the default failure mode is quiet. Reviewers start skimming these big fluent diffs, approval latency stays constant while review depth collapses, and the standard for what reviewed means erodes without anyone ever deciding to lower it.
So I watch for that with numbers, not impressions. Revert rate per module. Escaped-defect rate traced back to the introducing PR. Review time per changed line, which you can pull from PR metadata. And time-to-diagnose during incidents in the modules where generation was heaviest. That last number is the one I care about most, because a team that accepted code faster than it built understanding pays for it when the pager goes off.
The norms I set are structural. You merge a diff, you own it, exactly as if you'd typed it, and postmortems never get to accept the assistant as an explanation. CI gates are identical for generated and hand-written code. Diff-size norms cap how much fluent output can land in one review. And juniors get an explicit rule. Generation is available for anything they can verify, and it stays off the table where they can't yet tell right from plausible.
The tradeoff I defend is deliberate lost throughput. Slice caps and mandatory per-slice execution cost raw speed, sure. In return I get a bounded review burden and a team that can still explain its own codebase. Verification discipline is what decides whether the assistant's extra output becomes working software or review debt.
Follow-up chain
- What's the biggest chunk of work you'd hand the assistant in one go?
- And what starts going wrong when you go bigger than that?
- How do you know when a generated change is actually done?
- Has the assistant changed which parts of the work you keep for yourself these days?
Question 02First answer included
A strong answer gives you a real cadence for when generated code first runs, with the checks lined up from cheapest to most expensive
What an AI-prepared candidate might say
I try to verify as I go, I don't save it all up for one big pass at the end. Every slice the assistant generates gets a read before I move on, and I run the tests pretty often so problems show up early. If something looks wrong I'll ask the assistant to explain what it did, or just tell it to fix it. Before I call a change done I make sure the whole suite passes and I read the final diff one more time. The type checker and the linter are running the whole time anyway, so they catch the mechanical mistakes for me. My main rule is basically that unverified code shouldn't pile up. The assistant is fast, it's easy to just keep generating, so I try to keep my checking pace matched to the accept.
Senior
The cadence that holds up in practice, read first, then typecheck, then a focused test, then a runtime probe, plus the one rule about stacking generations that keeps bisection cheap.
Staff
Verification debt you can actually measure, the first-execution failure rate, where to sample it, and how to tune a team's cadence off that number.
Follow-up chain
- What's the cheapest check you run, and when is it enough all on its own?
- Okay, so where does just reading it let you down?
- Does that rhythm change when you're in a codebase you don't know well?
- And what if the language or the framework is new to you too?
Question 03First answer included
A strong answer has an actual rule for when generation is off the table, and the rule comes down to what verification costs.
What an AI-prepared candidate might say
I keep it away from anything where a mistake would be expensive. So core business logic, security-sensitive code, anything touching authentication or payments, I write that myself, because those need careful human judgment. Architecture decisions too, since they depend on context about our systems and our team that the model just doesn't have. Where it does well is the routine work. Boilerplate, tests, small utilities, documentation, explaining code, all of that fits. So I lean on it when the task is well-defined and low-risk, and I do the high-stakes thinking myself. It's a tool with limits, and I think the job is knowing where it's strong and using it there. When I'm not sure which side a task falls on, I default to writing it myself and only reach for the assistant once the shape is clear.
Senior
The one rule the whole keep-away list falls out of, and the four kinds of work where it tells you to write the code yourself.
Staff
Setting generation boundaries for a whole team, why the line has to move with seniority, and what shows up in the incident channel when a boundary sits in the wrong place.
Follow-up chain
- Why hold onto debugging yourself when the assistant is pretty good at suggesting fixes?
- You ruled out security-sensitive code, but the assistant has seen more security patterns than most engineers ever will. Defend that one.
- So does the assistant get any role at all in that code?
Question 04First answer included
A strong answer knows why reviewing generated code is different, the bugs land in new places and the author's intent is no longer in the text
What an AI-prepared candidate might say
I hold it to the same standard as anything else, honestly. It has to be correct, readable, tested, consistent with our patterns. The difference is I read it more carefully, because AI code can look right while being subtly wrong. So I check that it actually solves the problem, that the edge cases are handled, that the tests mean something. I also watch for code that reads like it came out of a generic tutorial instead of being fitted to our codebase, and for unnecessary complexity, since the models sometimes over-engineer things. If an API looks unfamiliar I'll verify it's real. But the author is still responsible for what they submit, so I treat the human as the author no matter what tool produced the text.
Senior
Why fluency stops being a quality signal, where the plausible-but-wrong bugs actually cluster, and what you ask instead of 'why did you do it this way' when the author is a model.
Staff
How review survives when diff volume doubles, the provenance norms, where the depth should go, and the PR metadata that catches rubber-stamping before an incident has to.
Follow-up chain
- Say the author tells you they already went through the generated code themselves. Do you ease up?
- If you could ask the human behind an AI-heavy PR just one question, what would it be?
- And what if they can't answer it?
Question 05First answer included
A strong answer splits hallucinations into the ones that crash and the ones that quietly no-op, and knows which check catches each kind
What an AI-prepared candidate might say
My main defense is just never trusting code I haven't run. Hallucinated APIs usually fail the first time they execute, so running the code or its tests catches most of them right away. For anything unfamiliar I'll check the official docs, make sure the method actually exists and takes the arguments the model says it does. Type checking helps here too, TypeScript will flag a method that doesn't exist on a type. I'm extra careful with the less common libraries, that's where the model invents things more often, and with anything version-specific. And when it suggests a package to install, I confirm the package actually exists and is maintained, not something the model made up. Between running the code, the types, and a quick docs check, I think very little gets through.
Senior
The loud hallucinations and the silent ones, why Node ignoring unknown options makes the silent kind genuinely dangerous, and the cheap check that catches each.
Staff
The gates that make hallucinations unshippable by construction, from type coverage to executed-path tests to the dependency check for packages that never existed.
Follow-up chain
- Why does the model make up an API instead of just telling you it doesn't know?
- TypeScript would catch most of this stuff, right? So does adopting it close the problem?
- What still slips through even on a fully typed codebase?
Question 06First answer included
A strong answer treats the prompt like an engineering spec with acceptance criteria, written down before the model generates a single line
What an AI-prepared candidate might say
I give it as much context as I can. What the code should do, the language and framework, our conventions, and I paste in relevant snippets from the codebase so the output actually fits in. I try to be specific about requirements, and I break big asks into smaller steps. If the first answer misses, I refine the prompt and run it again until it converges. I usually ask for tests along with the implementation too, and sometimes I'll have the model explain its approach first so I can course-correct before it writes any code. Treating it like a very fast junior developer works pretty well for me. Clear instructions go in, decent code comes out. The quality of what you get back tracks the quality of what you asked for, basically.
Senior
Writing the prompt as a spec, inputs, outputs, invariants, error behavior, non-goals, and why an underspecified prompt hands you the training data's median implementation.
Staff
Why spec quality moves a team more than anything else downstream, prompts and plans living as PR artifacts, and what the drift between stated spec and shipped diff tells you in review.
Follow-up chain
- Honestly, writing that much spec sounds slower than just writing the code. When does it pay off?
- So the model keeps blowing past one of your stated constraints. What do you do about it?
- And when do you give up on re-prompting?
Question 07First answer included
A strong answer gets correlated blind spots, that the generator can't be the only author of its own verification, and builds the tests around independence
What an AI-prepared candidate might say
I always ask for tests along with the implementation, and then I review both. The tests need to cover the main functionality, the edge cases, the error handling. I add whatever cases the model missed, especially around boundaries. Everything runs locally before it goes into a PR, and then CI runs the full suite again anyway. One thing I do check is whether the tests assert meaningful behavior, because generated tests sometimes only check that a function returns something. Coverage tools help me confirm the new code is actually exercised. The bar is the same as for human code, really. If the tests wouldn't catch a regression they're just decoration, so I make sure they genuinely pin down the behavior.
Senior
The independence rule, assertions that come from the spec instead of the implementation, and the sixty-second break-the-code trick that outs a vacuous suite.
Staff
Keeping a test suite honest once generation scales up, why coverage inflates, what mutation-style sampling actually tells you, and where property-based testing earns its complexity.
Follow-up chain
- Generated tests have to be good for something, though. What do you actually keep them around for?
- How would you even know your suite would go red if the code broke?
- That's basically mutation testing, right? Would you put it in CI?
Question 08First answer included
A strong answer reviews generated code against the vulnerability classes models actually reproduce, and treats every new dependency as attack surface
What an AI-prepared candidate might say
I apply the same security fundamentals I'd apply to any code. Validate inputs, parameterize queries, never build shell commands from user data, keep secrets out of source, least privilege everywhere. Generated code just gets extra scrutiny, because the model doesn't know our threat model or which inputs are attacker-controlled. So I check the authentication and authorization paths carefully, I look at how errors are handled so we're not leaking internals, and I make sure any crypto uses standard libraries rather than something homemade. On dependencies I stick to well-known packages and run the usual audit tooling. The model produces plausible code, and security is kind of where plausible gets dangerous, so a human review is always required. That's the rule I'd hold no matter what.
Senior
The vulnerabilities generation actually produces, interpreter boundaries, weak randomness, example secrets that turn real, and the boundary-walking checklist that catches them.
Staff
The security gates a generating team needs, secret scanning, SAST tuned to generated patterns, deny-by-default dependencies, and how slopsquatting turns package names into an attack.
Follow-up chain
- Give me a real example, a vulnerability a model wrote that a human probably wouldn't have.
- Why do model-suggested dependencies count as a security problem and not just a quality problem?
- So walk me through it, what does your policy actually require before a new package lands?
Question 09First answer included
A strong answer has real practices for keeping a mental model of code the assistant wrote, plus a way to notice when that model has slipped
What an AI-prepared candidate might say
My rule is pretty simple, I never merge code I don't understand. I read everything the assistant produces, and if something's unclear I ask it to explain until I could have written the code myself. I try to stay the architect too. The assistant fills in implementations, but I decide the structure, so the overall design stays in my head. Regular code review keeps the team familiar with each other's changes, and decent documentation captures the intent behind the code. When I feel some distance from a module, I'll spend an afternoon reading it or stepping through it in the debugger. Understanding is something you keep up on purpose, I think. The tool tempts you to go faster than your comprehension, and you kind of have to refuse, because you're the one who'll maintain the result.
Senior
What actually causes ownership decay, the boundaries-by-hand rule, and the predict-before-grep test that tells you whether the system still lives in your head.
Staff
Ownership decay as an operational risk, the symptoms that surface at incident time, the MTTR pattern by module, and the structures that keep humans holding the architecture.
Follow-up chain
- Come on, reading every accepted diff carefully, does that really survive a deadline?
- When this happens to a team, what does it actually look like?
- And once nobody understands a module anymore, how do you get it back?
Question 10First answer included
A strong answer designs real policy, ownership, gates, and disclosure, and can defend it against a ban on one side and a free-for-all on the other
What an AI-prepared candidate might say
The policy I'd write is basically, assistants are allowed and honestly encouraged, but the engineer is fully responsible for anything they submit. The AI wrote it is never an excuse. All code goes through the same review process regardless of where it came from, though reviewers should know when a change is heavily AI-generated so they can review accordingly. Nothing sensitive goes into prompts, so no secrets, no customer data, and only approved tools with the right data-handling agreements in place. Tests and CI checks apply to everything equally. And for the genuinely sensitive areas like security and payments, a senior engineer stays closely involved rather than leaving the work to generation. It mostly boils down to one idea, I think. Use the productivity, and keep the accountability with humans.
Senior
The four clauses that do all the work, merge ownership, identical gates, disclosure that actually changes reviewer behavior, and the named paths that demand a human author.
Staff
Policy run as a control system, measuring outcomes instead of usage, watching the exception budget for a misfitted rule, and keeping postmortem language pointed at humans.
Follow-up chain
- Why not keep it simple, ban assistants on the riskiest repos and allow everything else?
- Do you want commits recording that an assistant wrote the code?
- Okay, but what stops disclosure from turning into a stigma that people dodge by hiding their usage?
Question 11First answer included
A strong answer drives the assistant live, narrating intent, reading each diff before accepting it, and running code on a cadence stated out loud
What an AI-prepared candidate might say
First I'd make sure I understand the problem myself before involving the tool at all. So restate the requirements, sketch an approach. Then I'd use the assistant to speed up the implementation, have it generate boilerplate, write helpers, draft tests, that kind of thing. I'd review each suggestion before accepting it rather than trusting it blindly, and I'd keep you in the loop by explaining what I'm asking for and why. I'd test as I go instead of hoping it all works at the end. The division is basically that I direct and the assistant accelerates. The design decisions are mine, the typing is shared, and everything gets verified before I build on it. And I'd say when I disagree with a suggestion, since that shows judgment rather than dependence, I think.
Senior
The three moves of the live protocol, say the plan before you touch the tool, read every diff out loud before accepting, and put a run between each accept and the next prompt.
Staff
What the interviewer is really scoring, direction, verification cadence, and recovery when the model gets it wrong, and why a wrong generation is your best chance to gain ground.
Follow-up chain
- The assistant hands you a big diff that mostly works, and the clock's running down. What do you do?
- What do you do when the assistant is confidently wrong right in front of the interviewer?
- And if you honestly can't tell whether it's wrong?
Question 12First answer included
A strong answer treats the accept as taking ownership, reads the diff in a fixed order, and can name the things that get a diff rejected on sight
What an AI-prepared candidate might say
Before I accept anything I read the whole diff and make sure I understand what it's doing. If I can't explain it, I don't accept it, simple as that. I check that it handles errors and edge cases, that it matches our codebase conventions, and that any APIs it calls are real and used correctly. Then I run the tests, or write a quick one if nothing covers the change, and I only build on the code once it passes. If a piece is unclear I'll ask the model to explain it or simplify it. My rule is basically to assume nothing about generated code and verify everything that matters. The speed of generation should never push code through faster than I can actually evaluate it.
Senior
Why the accept is an ownership transfer, the fixed reading order that keeps your attention off the happy path, and the diffs that get thrown out before the read even finishes.
Staff
What happens to the protocol under incident pressure, which checks compress, which ones never go away, and how skipped depth gets written down instead of forgotten.
Follow-up chain
- Sixty seconds an accept, dozens of accepts a day, does that math actually work out?
- What is it in a diff that makes you slow down and blow the sixty-second budget?
- And what makes you just reject it without even finishing the read?