Where you are. Your skills refuse when their preconditions fail, measure their own postconditions, and report failure as a description of the world. Your planner reads those reports and decides what to do next. This lesson is about the question that sits between those two sentences and usually gets skipped.
Three nights, and one of them is unfixable
Run the desk task three nights running.
Night one. pick("pen") comes back as a failure: gripper closed to 2 mm, which is empty, pen still detected in the same place. Your loop retries. It fails again. The third attempt works and the task finishes forty seconds late. Annoying, and honest.
Night two. Every call returns success. The log is clean from top to bottom and ends with “desk clear.” There is a mug on the desk. The mug was behind the monitor in the single frame the plan was built from, so it was never in the plan at all.
Night three. Every call returns success. The log is identical to night two’s, line for line, modulo timestamps. There is a pen on the floor. The arm’s elbow swept it off the edge during step two, while carrying the mug. No skill did anything wrong. Nothing was looking at the pen.
Three failures. Three different repairs: a better grasp, a second camera angle before planning, and something nobody has built for you at all. And two of the three produced logs you cannot tell apart.
The idea in one paragraph
A failed run has three possible authors, and they are the three things that can be wrong independently of each other. The skill can break its contract: its precondition held and its postcondition did not. The plan can be wrong: every skill did exactly what it promised, and the goal is still not satisfied. The world model can be wrong: the fact the plan was built on stopped being true, either because the world moved or because the planner’s picture of it drifted. Retrying fixes the first, does nothing for the second, and actively makes the third worse. So the first job when a run fails is not recovery. It is attribution: deciding which of the three broke, using evidence that comes from somewhere other than the component under suspicion.
Wider than the screen; scroll it sideways.
Each class has its own signature, and the signature is what you check.
| Class | Precondition | Postcondition | Goal | What sees it | Cheapest correct response |
|---|---|---|---|---|---|
| Skill failed | held | broke | not reached | the skill’s own measurement | retry, or a different skill |
| Plan wrong | held every time | held every time | false | a goal check the planner did not write | observe, then replan |
| World model wrong | no longer true, or true but meaningless | may be fine | false | a fresh observation compared against the belief | re-ground the scene first |
Class one: the skill broke its contract
This is the class you have already built for, and it is the easy one for a reason worth naming. The failing component is the one holding the measuring instrument. A grasp that closed on air is detectable by the gripper that closed, in about a millisecond, with no judgement involved.
That locality is what makes it cheap. It is caught immediately, it is caught before anything downstream is planned against it, and the failure report can say what is still true, so a retry is a decision rather than a reflex.
Class two: the plan was wrong
Now the harder half. Every precondition held, every postcondition was measured and held, every report was honest, and the desk is not clear.
Nothing inside the execution path can see this. Each skill checked its own promise and its own promise was kept. Only a check written against the goal catches it, which is why your planner loop already carries an independently authored goal predicate.
Here that predicate takes on a second job. A failed goal check with every postcondition intact is what puts you in class two or class three, and a fresh observation then splits those two. Used that way it is a diagnostic instrument rather than a finish line, and it is worth knowing what its readings look like.
Class three: the world model was wrong
The third class is the one that breaks the loop everything else is built on.
The plan-execute-replan pattern assumes that when the world stops matching the plan, a precondition will fail and announce it. Sometimes that happens: someone puts a coffee cup where the tray was, place re-checks its precondition against fresh state, refuses, and the planner gets a clean signal. That is the well-behaved version, and it is well-behaved precisely because the mismatch is loud enough to trip a check somebody wrote.
The badly-behaved version is the one from night three. The skill executed. Its precondition held. Its postcondition held. It also did something nobody wrote down, and that something changed the world in a way no check was watching.
Wider than the screen; scroll it sideways.
Read that figure with an eye on where the damage happens versus where it shows up. The world changed at step two. Every check between step two and step four passes, correctly, because each one is asking about its own step. The task fails at step four, and if you debug at step four you will conclude the plan was wrong.
There is a second source of world-model error that has nothing to do with the world moving: the planner’s own memory. Over a long task the agent forgets which objects it has already binned, or records a step as done that it never ran. The world did not change; the belief decayed. The remedy is the same one, which is why they belong in the same class. Do not ask the transcript what is true. Look.
Attribution is the expensive half
Notice what the three classes cost to detect. Class one is a millisecond and a threshold. Class two costs one fresh observation and one judgement call against a predicate. Class three costs a comparison between the whole belief and the whole scene, which is the most expensive thing in this stack and the one nobody runs often enough.
That ordering is a budget, not an excuse. It says: check the cheap thing after every skill, the middle thing after every plan, and the expensive thing before anything irreversible.
And be honest about the ceiling. Detectors trained specifically to spot robot failures are noticeably better at seeing that a gripper missed than at seeing that a plan was wrong; the evaluation lesson has the numbers. As of August 2026 no shipped system cleanly separates these three classes. What ships is a vision-language model looking at a frame and judging whether the current step is done, which is a class-one and class-two detector with no class-three coverage at all. The separation exists in benchmarks and in your own code, and nowhere else.
Review
Three authors, and only one is fixed by retrying
A failed run has three possible authors, and they can be wrong independently of each other. The skill can break its contract: its precondition held and its postcondition did not. The plan can be wrong: every skill did exactly what it promised and the goal is still not satisfied. The world model can be wrong: the fact the plan was built on stopped being true, either because the world moved or because the planner’s picture of it drifted. Retrying fixes the first, does nothing for the second, and actively makes the third worse. So the first job when a run fails is not recovery, it is attribution: deciding which of the three broke, using evidence that comes from somewhere other than the component under suspicion. Something went wrong is not a diagnosis.
The three questions that give you a diagnosis
Each class has its own signature, and the signature is what you check. Did any step break its promise? That is the skill’s own measurement, and it costs a millisecond and a threshold. Is the goal actually satisfied? That needs a goal check the planner did not write, and it costs one fresh observation and one judgement against a predicate. Does what I can see right now still match what I believed? That is a comparison between the whole belief and the whole scene, the most expensive thing in the stack and the one nobody runs often enough. The ordering is a budget rather than an excuse: check the cheap thing after every skill, the middle thing after every plan, and the expensive thing before anything irreversible.
What ships, and what does not
Be honest about the ceiling. Detectors trained specifically to spot robot failures are noticeably better at seeing that a gripper missed than at seeing that a plan was wrong. As of August twenty twenty-six no shipped system cleanly separates these three classes. What ships is a vision-language model looking at a frame and judging whether the current step is done, which is a class-one and class-two detector with no class-three coverage at all. The separation exists in benchmarks and in your own code, and nowhere else, which means the attribution step is something you build rather than something you install.
Check yourself
1. Nights two and three produced identical logs. What single piece of evidence tells them apart, and why can it not come from the log?
A fresh observation of the scene, compared against the planner’s belief. On night two the belief and the world agree; the mug was simply never in the belief, so the plan was wrong given what the planner knew. On night three the belief and the world disagree; the pen moved and nobody recorded it. The log cannot distinguish them because in both cases every skill kept its contract and reported honestly, so the log is identical by construction. The distinguishing evidence lives outside the execution path.
2. Why can a planner not be asked to write its own goal check?
Because the plan and the completion judgement would come from the same component and be wrong together. A planner that omitted the mug from the plan has a world model with no mug in it, and will evaluate “is the desk clear” against that same model and answer yes. The check has to be derived from the instruction rather than from the plan, and evaluated on a fresh observation by something that never saw the step list.
3. A run fails. Every step reported success. Your recovery replans and the new plan fails in the same place. What does that tell you?
That the failure is a world-model failure and the replan inherited the broken belief. A wrong plan built on a correct world model usually produces a visibly different second plan, because the model is reasoning over accurate state. A plan that fails identically twice is a strong signal that the input to the planning step, not the planning step, is the problem. Re-ground the scene and plan again from what you actually see.
4. Give a latent failure that no precondition and no postcondition would catch, and say why.
Placing the mug nudges the tray two centimetres. place promised the gripper would end empty and the mug would be on the shelf, and both are true, so its postcondition holds. The next skill’s precondition asks whether the tray is detected and reachable, and it is. Nothing in either contract mentions the tray’s exact position, because nobody wrote down that a placing motion can move a neighbouring object. The contracts bound what each skill promised, never what it also happened to do.
5. Which class does retry help, which does it waste time on, and which does it make worse?
Retry helps class one, where the failure was stochastic and the world is unchanged. It wastes time on class two: the skill will succeed again and the goal will still be unmet, so you burn actions confirming something already known. It makes class three worse, because each attempt is a fresh physical action taken against a world you have misunderstood, and physical actions do not roll back. Retrying a place into a tray that has moved does not miss once, it misses three times.
6. You can only afford one expensive check per task. Where do you put it?
Immediately before the first irreversible action, not at the end. A class-three failure detected after the task cannot be undone, and a goal check at the end tells you only that something went wrong somewhere. Re-grounding the scene before anything unrecoverable happens converts the most expensive class of failure into a refusal, which is the cheapest outcome available.
Do this
About an hour, standard library only. Extend the fake skills from lesson 5.
1. Build a world with two copies. A truth dict holding real object positions, and a belief dict the planner reads. Planning copies truth into belief once, at the start. Nothing updates belief afterwards unless you explicitly re-perceive.
2. Add three injectable faults, one per class.
slip:pickfails its postcondition 30% of the time.blind: one object is omitted from the observation that buildsbelief, and only that one.nudge:placesilently shifts the tray intruthby 2 cm, and reports success. Later places aimed at the believed position miss.
3. Write the classifier. It gets three inputs and nothing else: per-step postcondition results, a goal_check(truth) you wrote before the planner existed, and one fresh observation.
def attribute(step_results, goal_ok, belief, fresh_observation):
if any(not r["postcondition_held"] for r in step_results):
return "skill_failed"
if goal_ok:
return "success"
return "plan_wrong" if belief == fresh_observation else "world_model_wrong"
4. Run thirty episodes, ten per fault, and build a three-by-three confusion table of predicted class against the fault you injected. Print it. Do not tidy the result.
5. Read the table honestly. The blind episodes will mostly come back as plan_wrong, and that is not a bug in your classifier. The plan really was wrong, given the belief; the root cause sits one layer further upstream in perception, which is why grounding gets its own lesson. Write one sentence on what a fourth label would have to measure to catch it.
6. Delete the fresh observation and re-run. With belief compared against itself, every non-skill failure collapses into plan_wrong. That is the state most agentic systems ship in, and now you know what it costs.
What you can now do
You can take a failed run and name which of the three layers broke: the skill, the plan, or the world model. You can explain why the last two produce identical logs and what single piece of evidence separates them, why a goal check has to be authored outside the planner, and why replanning without re-observing reproduces the same failure with more confidence. You can recognise a latent failure as an action that keeps every promise it made and still corrupts the state, and you know where to spend your one expensive check.