The Hint Ladder
Hint one: the conceptual direction. Hint two: the relevant abstraction. Hint three: pseudocode. Hint four: a partial implementation. Then the reference. Each rung gives less than the next, and the rung you stop at is the measure of what you still own.
The situation, the reflex, and why it stalls
Every lesson starts where being stuck starts: someone has a problem, and the first move that comes to mind feels like progress.
You are stuck after an honest attempt, and you want help that unblocks you without taking the problem away. What are the rungs of help, how do you ask for one at a time, and how do you tell that you took one too many?
Your checkout attempt charges twice on a retry, and you have stared at it for an hour. You could ask for the fix and have it in a minute. You could also ask for something smaller, but you do not know what "smaller" would be, and an hour of being stuck makes the whole solution feel like the only thing that would help.
Ask for the fix. Being stuck is unproductive; the fix ends it; you will understand the fix when you see it. Asking for less feels like asking to stay stuck longer.
The fix arrives with the concept inside it — an idempotency key — and the concept is never named, so you have a fix and not an idea. The next problem that needs the same idea in a different shape, say a webhook that arrives twice, looks like a new problem.
- The fix arrives with the concept inside it — an idempotency key — and the concept is never named, so you have a fix and not an idea. The next problem that needs the same idea in a different shape, say a webhook that arrives twice, looks like a new problem.
- The fix ends the being-stuck and with it the search, which was the part that was learning. An hour of staring was not productive, but the minute before the fix, when you almost saw it, was — and the fix arrived in that minute.
- "You will understand the fix when you see it" is recognition again. You can read it and agree; asked a week later what it does and why the key is per attempt and not per customer, nothing is there.
- There is no record of how much help was needed, so there is no way to notice that the same kind of gap keeps needing the same kind of help — which is the signal that says what to study.
The move
Precisely enough to apply it to a problem you have never seen — not a slogan.
- Ask for help in rungs, each giving less than the next, and stop at the first that unblocks you. Rung one: the conceptual direction — "the problem is that nothing identifies an attempt". Rung two: the relevant abstraction — "an idempotency key, sent with the request and stored with the result". Rung three: pseudocode — where the key is generated, checked and stored. Rung four: a partial implementation — the key check, with the rest left to you. Then, last, the reference (The Problem-Solving Loop).
- After every rung, attempt again before asking for the next. The rung is a hint, not an instalment; its whole value is in what you do with it between rungs, and a ladder climbed without attempts in between is the reference delivered slowly.
- Record the rung you stopped at. It is a measurement: rung one means the concept was the gap; rung four means most of the solution was. Over problems of one kind, a falling rung is learning and a flat one is the concept to study directly (The Engineering Notebook).
- Be honest about the direction of the ladder. The rungs give more help as they go, which means the lower ones require more from you — and being stuck longer at a low rung is not a failure of the ladder; it is where the learning is priced.
The rungs, and what each one leaves you
The pipeline is the ladder from the helper's side: what each rung supplies, and the way each is faked — a rung that supplies the next one's content while wearing this one's name. The last column is worth reading against real help you have received; most "conceptual hints" are rung three in disguise.
- 1Rung 1 — conceptual direction
Names the kind of thing missing: "nothing identifies an attempt". Leaves you the abstraction, the design and the code.
fails by Naming the abstraction too — "you need an idempotency key" — which is rung two.
- 2Rung 2 — relevant abstraction
Names the abstraction and its shape: a key per attempt, sent and stored. Leaves you the design and the code.
fails by Describing where the key is generated, checked and stored, which is rung three.
- 3Rung 3 — pseudocode
The logic of the piece: generate, look up, return stored or charge and store. Leaves you the code and its integration.
fails by Pseudocode so complete that translation is the only work left.
- 4Rung 4 — partial implementation
The hard part in code — the key check — with the rest left. Leaves you the integration and the understanding of why it works.
fails by A "partial" implementation that is the whole thing minus a variable name.
- 5Reference
The complete solution, shown last, to compare with your post-ladder attempt.
fails by Shown first, or shown without an attempt to compare it against.
Every rung is followed by an attempt. A ladder with no attempts between rungs delivers the reference in five instalments.
Which rung to ask for
The choice of rung is a decision with named options, and the criteria are the gap and the attempt so far, not how long you have been stuck. The options below are the ones the double-charge learner faced; the costs are what each rung takes away from the attempt.
After an honest attempt, which rung do you ask for?
when The attempt runs and fails in a way you can describe, and you suspect the gap is a concept you would recognise if named.
cost You may be stuck a while longer; the concept may not be one you can get from a direction alone.
when You have the concept — attempts must be identified — and not the standard shape for it.
cost The design of the piece is now largely given; what remains is where it lives and how it is stored.
when You have the abstraction and cannot see the sequence of operations that makes it safe under a retry in flight.
cost The logic is given; the learning left is translating it and seeing why each line is there.
when The logic is clear and the code for the check keeps being wrong in a way the tests show and you cannot see.
cost Most of the solution is now supplied; the tally records four, and the concept should be studied afterwards.
Rung three, as it was given
This is the pseudocode rung for the double charge, written to leave the code and the integration to the learner. Notice what it does not contain: no language, no library, no storage choice, nothing about the provider's own deduplication. Those are the learner's, and the reference will show one way of doing them.
1checkout(cart, customer, attempt_key): -- client generates attempt_key once per attempt2 existing = lookup_payment(attempt_key)3 if existing: return existing.result -- the retry gets the first answer, no second charge4 order = create_order(cart, status = "pending")5 result = provider.charge(order.total, customer.payment_method)6 store_payment(attempt_key, order.id, result)7 if result.ok: mark_paid(order)8 return resultThe retry in flight — two requests with the same key arriving before either has stored — is deliberately not solved here; it is the next gap, and the learner who notices it has climbed past rung three on their own.
How to do it
Most important first.
- Before asking, name the gap in one sentence: "my attempt charges twice on a retry and I do not see what would stop it". A named gap can be answered at rung one; an unnamed one only at the reference.
- Ask for the rung by name: "give me only the conceptual direction — what kind of thing am I missing?" Most tools and most colleagues honour the request if it is explicit.
- Set a minimum between rungs: a real attempt, however short. If the attempt makes no progress, the next rung; if it does, no next rung.
- When you reach the reference, do the comparison from No AI on the First Attempt: where did my attempt after the last rung differ, and what does that say about which rung I actually needed?
- Keep a tally per kind of problem — concurrency, external systems, state — of the rung you stopped at. The tally is your syllabus.
Worked on a concrete problem
The move has to produce something. This is what it produced.
- The double charge, up the ladder. Rung one: "nothing in your design identifies a single attempt; two requests look like two attempts". Attempt: you add a check on "has this cart been charged?" — better, and still wrong when the first charge is in flight. Rung two: "an idempotency key: the client generates one per checkout attempt, sends it, and the server refuses a second charge with the same key". Attempt: you generate the key, store it with the payment, check before charging. Test: one charge on retry. Stopped at rung two. The reference, compared afterwards, also passes the key to the provider so the provider dedupes too — a difference you can now name.
- The same gap for someone else. A learner for whom rung two does not land — "what does the server store, and when?" — asks for rung three and gets pseudocode: generate key; look up key; if found return stored result; else charge, store key with result, return. Attempt succeeds. Stopped at rung three; the tally says "external-system idempotency: three", and it says it twice more over the next month before it says two.
- The chat app, read state on two devices. Rung one: "read is not a property of a message; it is a relationship between a user and a message". That sentence reorganises the whole attempt, and the learner stops there. Rung one is the cheapest help there is and it is only available to someone who has an attempt for it to reorganise.
- The rung taken too far. A learner asks for rung four — the key check implemented — before attempting after rung two. The implementation works; the tally records four; and the next external-system problem needs four again. The ladder was climbed, and nothing was carried up it.
How you know it worked
What now exists that did not before, and what question you can now ask.
- Each request for help names a rung and a gap, and the response fits the rung asked for.
- There is a real attempt between every rung, and the attempt after the last rung is what shipped.
- A tally of stopping rungs exists per kind of problem, and on at least one kind it is falling.
- The reference, when reached, differs from your post-ladder attempt in ways you can list rather than in every line.
The questions you can now ask
The field this whole domain exists for. After this lesson, these are the questions to put to an unfamiliar problem.
- ?What is the gap, in one sentence, that a hint could be aimed at?
- ?Which rung am I asking for, and have I attempted since the last one?
- ?At which rung did I stop, and what does that say about whether the gap was a concept, an abstraction, or the code?
- ?On problems of this kind, is my stopping rung falling — and if not, what is the concept underneath that I should study directly?
What can go wrong
- Rung one asked for on a gap that has not been named. "I am stuck on checkout — give me a conceptual hint" has no gap to aim at, and the hint that comes back is either useless or the solution wearing a disguise.
- The ladder climbed for pride. Hours at rung one on a gap that is genuinely a missing concept nobody discovers unaided. The rungs exist to be climbed; the rule is an attempt between them, not a vow to stay low.
- Rung confusion. A pseudocode hint is asked for and a partial implementation supplied, or a "conceptual direction" arrives as three paragraphs that describe the whole solution. Name the rung, and push back when the response is a higher one.
- The tally kept and never read. It exists to say what to study; a flat line at rung four on concurrency problems is a syllabus item, and ignoring it is choosing to need rung four forever.
- Rungs are slower than the reference, always. On a problem you will solve once and never again, the reference is the right rung.
- Asking for a specific rung requires a helper — human or tool — willing to give less than they could, and some are not; a colleague who answers rung one with the solution has to be asked again, which costs goodwill.
- The tally is bookkeeping, and bookkeeping on a solo project is the first thing dropped when time is short.
- "Lower rungs are better." Lower rungs demand more and teach more when they work; the right rung is the lowest one that unblocks you after an honest attempt, and for a genuinely missing concept that may be rung three.
- "The reference is failure." The reference is the fifth rung, reached after four attempts; arriving there with four attempts behind you and a comparison ahead is the ladder working. Arriving there first is the reflex.
- "The ladder is only for AI." It is how good mentors have always helped: the question before the answer. The tool is simply the helper most willing to be asked for a rung by name.
Where this applies
Problem-solving advice is stated as universal far more often than it is. These labels say what each method is specific to — and where CONTESTED appears, the note gives the strongest form of the opposing view.
- GENERALConcept, abstraction, pseudocode, partial implementation, reference — the rungs are the same for any problem a learner is stuck on, in any domain; what changes is which rung a given gap needs.
- TEAM-SPECIFICA solo learner asks the tool for rungs and keeps the tally; a senior helping a junior gives rungs deliberately and watches where they stop; a team under deadline sends the stuck engineer straight to the reference and writes the concept down as a debt to revisit. All three are the ladder; only the last skips the attempts, and it knows it is doing so.
- ILLUSTRATIVEThe hour of staring, the four-rung learner and the month-long tally are invented to show the rungs in use; no real learner or tool is described.
Where the depth lives
This domain asks the question and hands the answer off by name.
- — The manifesto's ladders at /manifesto/without-ai are the origin of these rungs; the lab at /thinking/without-ai hands them out one at a time on a project.
- — The manifesto's /manifesto/review is what happens at the reference rung: the comparison is a review, and it needs your attempt to review against.