When you are stuck
You will learn
How to count the same error coming back, and how that count picks your next move: read it, ask smaller, go back to the save point, start fresh.
Getting stuck is normal; going round in a circle is the signal to change what you do. Count how many times in a row the same error came back. The opening time, read the error and say in your own words what it claims. The second time, ask for a smaller step. The third time, go back to the last save point, the commit that worked. After that, start a fresh conversation with a short summary and the one error. A different error resets the count, because it means you got past the last one. The spec holds this as a table of moves indexed by the count, and its 4 tests check each rung.
Try it
In the widget press the same error three times and name the move it picks. Then press a different error and see the count start again. In the spec change the move for a count of 3 from 2 to 1 and read which test goes red.
Press the same error again and again and watch the advice grow: read it, ask for a smaller step, go back to the save point, start a fresh conversation. A new error resets it.
specs/vibecoding/unstuck.t27
// SPDX-License-Identifier: Apache-2.0
; specs/vibecoding/unstuck.t27 -- vibecoding lesson: when you are stuck
; One idea: count how many times in a row the SAME error came back, and let the count pick the
; move. 0 read the error again, 1 ask for a smaller step, 2 go back to the last save point,
; 3 start a fresh conversation with a short summary. MOVE_FOR is indexed by that count, 0 to 4;
; a longer streak stays at the last move. A different error starts the count again at 1.
; Run it in the player, then change MOVE_FOR[3] from 2 to 1 (never going back to the save point)
; and read which test goes red.
; ASCII only, English only.
; phi^2 + 1/phi^2 = 3 | TRINITY
module vibecoding_unstuck;
pub const MOVE_READ : u8 = 0;
pub const MOVE_SMALLER : u8 = 1;
pub const MOVE_SAVE_POINT : u8 = 2;
pub const MOVE_FRESH : u8 = 3;
pub const MOVE_COUNT : u8 = 4;
pub const MOVE_FOR : [5]u8 = [0, 0, 1, 2, 3];
pub const COUNT_AFTER_NEW_ERROR : u8 = 1;
test the_first_time_you_read_the_error {
assert MOVE_FOR[0] == MOVE_READ;
assert MOVE_FOR[1] == MOVE_READ;
}
test each_repeat_escalates {
assert MOVE_FOR[2] == MOVE_SMALLER;
assert MOVE_FOR[3] == MOVE_SAVE_POINT;
assert MOVE_FOR[4] == MOVE_FRESH;
}
test the_last_move_is_a_fresh_start {
assert MOVE_FRESH + 1 == MOVE_COUNT;
assert MOVE_FOR[4] == MOVE_COUNT - 1;
}
test a_new_error_is_a_first_time {
assert MOVE_FOR[COUNT_AFTER_NEW_ERROR] == MOVE_READ;
}
All lessons
Module 1 · What vibecoding is
You describe, an agent writes, you run it and check. What a program is, and five myths put to a test.
Module 2 · Your desk
An editor with an agent beside it, ten terminal commands, and reading an error message.
Module 3 · Save points with git
A commit is a save point, a branch is a safe try, and a key is a pair of which one stays private.
Module 4 · Prompting
The parts of a prompt, an example in place of an adjective, and one small step at a time.
Module 5 · The working loop
Four phases from idea to ship, the loop of ask, run, read and fix, and what to do when it is stuck.
Module 6 · A test as the judge
A test says yes or no, a planted bug shows the test works, and a diff is read before it is accepted.
Module 7 · The parts of an agent
What an agent answers with, what it can do with tools, and what it keeps between messages.
Module 8 · A first bot
A bot is a message loop, a bot comes from a spec, and a secret stays out of the repository and the prompt.
Module 9 · Your own project
A spec for your own idea, one thing measured after it runs, and an honest plan for the next month.