Skip to content

Senior Engineering Interview Handbook / Chapter 159

Coding Readiness Gates

A coding-readiness chapter built around observable attempts, narrow repair, adjacent retesting, and a defensible decision about when to schedule interviews.

A solved problem can still be a failed gate

At minute 36, the candidate has working code. It is readable, it runs, and it passes the sample. The approach is appropriately efficient. If the only question is whether the problem was solved, the session looks successful.

But the first test the candidate invented arrived at minute 33, after an interviewer asked what should happen when two intervals touch. The code had silently treated touching half-open intervals as overlapping, despite a clarification made near the start. The candidate repaired the comparison, retested, and explained the complexity correctly. Recovery was good. Testing was late.

Should this candidate schedule a coding loop?

One attempt cannot answer. A lucky prompt can conceal a weak process; an awkward prompt can make a sound process look worse than it is. Readiness is a claim about repeated behavior under representative conditions. The useful question is not “Did I solve it?” but “Which parts of a complete coding round can I now produce reliably, and which still depend on the prompt or the interviewer?”

A readiness gate turns that claim into a scheduling decision. It does not measure engineering worth, and it does not require flawless sessions. It asks whether the remaining variation is tolerable for the loop you are about to enter—or whether the evidence points to one more repair.

Read a round in the order it happens

The seven behaviors form one sequence. A later strength can reveal or repair an earlier failure, but it cannot make the failure disappear.

  1. Clarify. Settle the input, output, constraints, examples, and any ambiguity that would change the algorithm. Good clarification is brief because its questions have consequences.
  2. Choose an approach. Name a viable baseline, the pressure imposed by the constraints, the state or invariant that keeps the solution correct, and the expected cost. A pattern name without its invariant is weak evidence.
  3. Implement. Produce code whose state can be followed and repaired. Ordinary fluency with the chosen language matters more here than clever abstraction.
  4. Test. Try to disprove the code with a sample, a minimal input, a boundary, a repeated value or state, and a case aimed at the invariant’s weakest point. The exact cases depend on the problem; the habit of seeking a counterexample does not.
  5. Explain complexity. Derive time and space from the code that actually exists: the sort, loop, heap, recursion tree, graph traversal, or retained state. Do not recite the cost of the pattern you intended to write.
  6. Recover. Make a failure inspectable: name the symptom, reconnect it to the invariant, localize the cause, make the smallest repair, and rerun the failed case plus a neighboring case. A hint changes the evidence for independent correctness, but it also creates evidence about recovery.
  7. Finish. Leave a coherent answer inside the round: completed code, tests performed, final complexity, and any honest caveat. Code without a close forces the interviewer to reconstruct the result.

This order makes diagnosis possible. If clarification was sound and the approach had the right invariant, a boundary bug may be an implementation or testing failure. If the invariant was never stated, patching the comparison may produce correct code without demonstrating a reusable method. “Almost there” is too vague to guide practice; the sequence identifies where the round first became unstable.

Build a gate from evidence, not confidence

A gate needs more than one good afternoon. Gather recent attempts close enough together that they describe current performance, and choose prompt families that resemble the target loop. Arrays, intervals, maps, trees, graphs, heaps, recursion, backtracking, or dynamic programming are not a universal syllabus. A frontend platform role, an infrastructure role, and a generalist product role may sample different families. The gate should match the likely work without waiving correctness, tests, recovery, or a controlled finish.

Preserve the lightest artifacts that can settle a disagreement with memory: the prompt family, code, tests, a few time marks, any hint, the failure that changed the result, and the final decision. A lifetime problem count cannot show whether testing has become automatic. “Felt good” cannot show whether a hint supplied the missing invariant.

Use the target round’s language, editor, execution policy, and time box when they are known. Otherwise, choose a plausible format and label it as a practice assumption. A 35-to-45-minute session can be a useful default for a coding gate, but it is not a fact about every employer. The clock should reproduce the decision pressure of the intended round, not create theater.

Before the attempt, write the decision it will support:

Target loop and round shape:
Prompt family and why it is representative:
Known risk, if any:
Time box and tool rules:
Hint policy:
Artifacts to keep:
Decision after the attempt: ready | repair | retest | explicit narrow risk

The four decisions have different meanings. Ready means no behavior is a repeated blocker in representative recent work. Repair means the evidence has isolated a behavior that should be practiced directly. Retest means a correction has been learned but has not yet transferred to an adjacent problem. An explicit narrow risk is a weakness the target loop is unlikely to sample and that the candidate has consciously chosen not to repair now.

The boundary bug

Consider the opening attempt as a modeled gate run. The prompt asks the candidate to merge reservation windows. Windows are half-open: [start, end). Two windows that touch, such as [1, 3) and [3, 5), must remain separate. The input may be unsorted.

The candidate’s sparse record reads:

02:10  asks whether touching windows merge; interviewer says no
04:30  chooses sort-by-start, then a linear merge
06:20  states current output contains all earlier windows, already merged
18:40  finishes the main loop
22:10  traces the sample successfully
27:30  handles empty input and one window
31:50  interviewer asks for the touching-window case
33:00  discovers that the merge condition uses <=
34:10  changes <= to < and reruns touching, nested, and sample cases
36:00  gives O(n log n) time for sorting and O(n) output space
37:10  summarizes the rule and closes

The defect is one character:

if next.start <= current.end:   # wrong for half-open touching windows
    merge(next)

The important observation is not that the candidate made a boundary mistake. Interview code will sometimes contain bugs. The record shows how the whole round behaved around it.

Clarification was strong: the candidate asked the exact semantic question that later mattered. Approach selection was sound: sorting dominates at O(n log n), the linear scan is O(n), and the output invariant gives the loop a clear purpose. Implementation was readable enough that the defect could be localized. Recovery was also strong: the candidate connected the failing case to the half-open boundary, changed the responsible comparison, and retested adjacent cases. The finish was complete.

Testing is the unsettled gate. The candidate knew the boundary at minute two but did not turn it into a test until prompted nearly thirty minutes later. That is not the same failure as misunderstanding half-open intervals. It is a failure to carry an earlier decision forward into the test plan.

Now place the attempt beside three recent records:

Intervals       correct after prompted boundary test; recovery clear
Tree recursion  sample passes; missing base case found after hint
Graph BFS       cycle test begins only after interviewer asks
Map counts      duplicate and empty cases tested without prompting

The pattern matters more than any numeric average. Three attempts show late or prompted tests across different state shapes. The candidate has enough algorithm knowledge to finish these problems, but systematic testing is not yet reliable under time. The decision is repair, not “do thirty more problems,” and not “coding is weak.”

Repair the smallest unstable behavior

A useful repair is narrower and cheaper than another full mock. For this candidate, the correction rule is:

Every consequential clarification becomes a test before coding begins; add one minimal case and one case designed to break the invariant.

The candidate can rehearse that rule without repeatedly spending forty minutes on complete solutions. Take several fresh prompts and stop after writing the interpretation, invariant, and tests. An interval prompt should produce a touching boundary. A graph prompt should produce a cycle or a disconnected component when relevant. A recursive search should produce a branch that must restore state. Then run one complete attempt and see whether the tests appear without rescue.

Other failed gates call for different repairs:

  • If clarification sprawls, practice openings that ask only questions capable of changing the implementation, then commit to a reading of the prompt.
  • If approach selection is brittle, write the brute-force baseline, constraint pressure, state or invariant, and chosen structure before touching code.
  • If implementation consumes the round, use small timed exercises for the exact state shape that breaks: two pointers, heap maintenance, visited sets, recursion parameters, or backtracking restoration.
  • If complexity is memorized rather than derived, annotate the operations in completed code and account for each one.
  • If recovery becomes silent, debug intentionally broken solutions aloud: symptom, invariant, cause, patch, retest.
  • If the finish disappears, reserve the last few minutes and practice closing incomplete as well as complete answers honestly.

Repeat the original prompt once if that is the fastest way to learn the correction. It cannot prove transfer because the counterexample is now known. The readiness evidence must come from an adjacent prompt that requires the same behavior without reproducing the same solution.

Decide without fake precision

A score can help two reviewers use the same vocabulary, but arithmetic does not create readiness. If you use numbers, anchor them in behavior: low means the behavior was missing or disruptive; middle means it appeared inconsistently or after material prompting; high means it remained clear under the round’s pressure. Preserve the evidence beside the score.

Then apply three rules:

  1. Do not average away a repeated blocker. Strong clarification does not compensate for code that repeatedly remains untested.
  2. Count a hinted finish as recovery evidence, not an independent pass on the behavior the hint supplied.
  3. Require transfer. A familiar prompt can maintain fluency; it cannot alone establish readiness.

Read the recent attempts as a set. Can the candidate efficiently settle the problem? Can they state why the approach fits and what keeps it correct? Is the code executable and inspectable? Do tests try to falsify it before the interviewer requests them? Does the complexity statement match the actual implementation? When something breaks, does the candidate recover visibly? Does the round end with a defensible answer inside the target format?

A single imperfect answer need not delay scheduling. A repeated failure in one of those behaviors should. Repair it, retest it on an adjacent problem, and return to an integrated mock. If several behaviors remain unstable, coding is still in deliberate-practice mode rather than final-campaign mode.

Keep one record that changes the plan

Complete the record immediately after the attempt, before reading a solution or turning the session into a story about confidence:

Prompt family:
Target time box:
Clarification evidence:
Approach and invariant:
Implementation evidence:
Tests attempted without prompting:
Complexity from the written code:
Bug or hint and recovery:
Finish:
Repeated blocker across recent attempts:
Correction rule:
Adjacent retest:
Decision: ready | repair | retest | explicit narrow risk

The record is deliberately compact. Its job is to protect the next decision, not to archive every keystroke. When the same seven behaviors hold across fresh, representative attempts, stop buying confidence with volume. Protect the process that produced the evidence and schedule.

Coding readiness proves that one performance can travel across prompt families. The next gate asks the analogous but broader question of system design: whether architectural judgment travels when the product shape, authority boundary, and production pressure change.