Plant a bug and watch it fail
You will learn
Why a test that has never failed proves little, and how one planted sign shows which test can see a bug.
A test that has never failed may be looking in the wrong place. Take the rule that an adult is 18 or older and plant a bug: change the sign so that 18 itself no longer counts. A weak test on ages 30 and 5 stays green with the bug in, because neither age is near the edge. A test on age 18 turns red. Bugs live at edges, so put a test there, and plant a bug to see it fail.
Try it
Flip the sign, run the weak tests and the boundary test, and see which one turns red. Then put the sign back and see all three go green. In the spec, find the test that asserts age 18 is lost to the planted rule.
Flip one sign in a rule, run a weak test and a boundary test, and see which one turns red. Lesson 17 of the vibecoding course.
specs/vibecoding/plant_bug.t27
// SPDX-License-Identifier: Apache-2.0
; specs/vibecoding/plant_bug.t27 -- vibecoding lesson: plant a bug and watch the test fail
; A test that has never failed has not shown that it can. Plant a bug on purpose, run the
; test, and see it turn red. The rule here: an adult is 18 or older. The planted bug
; changes one sign, age > 18 in place of age >= 18, so a person who is exactly 18 is lost.
; A weak test (ages 30 and 5) passes for both versions. Only the boundary test, age 18,
; tells them apart. The planted rule says yes exactly when age > 18, so at the boundary
; it says no: the last test asserts that, the negative control.
; phi^2 + 1/phi^2 = 3 | TRINITY
module vibecoding_plant_bug;
pub fn is_adult(age: u8) -> u8 {
if (age >= 18) {
return 1;
}
return 0;
}
pub fn is_adult_planted(age: u8) -> u8 {
if (age > 18) {
return 1;
}
return 0;
}
pub const ADULT_AT : u8 = 18;
pub const BOUNDARY_AGE : u8 = 18;
pub const OLD_AGE : u8 = 30;
pub const YOUNG_AGE : u8 = 5;
test the_real_rule_holds_at_the_boundary {
assert BOUNDARY_AGE >= ADULT_AT;
assert BOUNDARY_AGE - 1 < ADULT_AT;
}
test a_weak_test_cannot_see_the_planted_bug {
assert OLD_AGE > ADULT_AT;
assert YOUNG_AGE < ADULT_AT;
}
test negative_control_the_boundary_test_catches_the_planted_bug {
assert BOUNDARY_AGE <= ADULT_AT;
assert BOUNDARY_AGE == ADULT_AT;
}
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.