The problem
You are building a review bot. Every time someone pushes, it reads the diff (the lines that changed) and decides whether a team rule was broken. You wired it up with one number: above 0.5, block the merge.
The first author to meet it got fourteen blocking comments in a single review. Twelve of them were wrong. He merged anyway, switched the bot off for his repo, and told everyone else not to bother installing it.
You try the obvious fix and raise the line to 0.9. The noise stops, and so does everything else: the two changes that really did break a rule came back at 0.62, and now the bot says nothing about them either. One line can be loud or it can be silent; it cannot be careful.
The real trouble is that your bot can do three things — rewrite the code, leave a comment for a person, stay quiet — and a single line only ever picks between two of them.
The solution
The traffic light pattern says: count your actions first, then give each one its own line, heaviest at the top. Write the list down plainly — rewrite it, mention it, say nothing — because that list, not the model, is the shape of the decision.
The action that is hardest to undo gets the highest line. This illustrative policy uses 0.8 for rewriting and 0.5 for a comment; neither value establishes an acceptable error rate. Choose the lines on labeled tuning data, then check them on separate validation cases for your task and model version. Anything under the lowest line falls through to doing nothing, which is a decision too and deserves to be counted like one.
Keep the lines together in one place instead of scattering them through the code. The day someone says the bot is too loud, you want to move one number and know exactly what moved with it.
Ask · Answer · Act
- AskPut the changed lines and one team rule in front of Jev and ask whether this change breaks this rule.
- Answer0.83.
- ActThat clears the top line, so the bot rewrites the code itself. Had it come back 0.62 it would only have left a comment; at 0.30 it says nothing at all.
Where the name comes from
A junction with a single lamp has two states, and drivers can only floor it or slam the brakes. Amber exists for the case in between: slow down and look. Your middle tier is the amber lamp — and like a real amber lamp, it only works if somebody is actually looking.
Use it when
You really do have three or more actions whose cost of being wrong differs: fix it automatically, hand it to a person, let it go.
Not when
You only have two actions. Do not invent a middle one for the sake of having tiers: a flag with nobody assigned to read it quietly becomes the same thing as doing nothing, and you will not find out for months.
Projects that do this
- abide — Enforce project rules on coding agents with Jev.
- jev-axi — CLI for TypeSafe's Jev: fast calibrated judgments from the shell.
- jev-review — Staged code-review workflow with a local dashboard, gated by Jev.
Read this code
- abide
packages/cli/src/lib/band.ts:48-49Two lines, 0.8 and 0.5, turn one probability into three fates: fix it, flag it for a person, leave it alone.
- jev-axi
src/safety.ts:238-261A guard standing in front of shell commands: deny at 0.8, ask at 0.45, allow below — and the milder kind of problem only escalates if the damage would be big enough.
- jev-review
src/domain/config.ts:5-17Three numbers in one small config file — 0.7, 1.5, 2 — decide whether a finding is dropped, sent to a person, or blocks the merge.
Show me the code
const TIERS = [[0.8, "fix"], [0.5, "comment"]]; // illustrative; validate locally before use
function route(p) {
for (const [line, action] of TIERS) if (p >= line) return action;
return "quiet";
}
switch (route(answers.violation.p)) {
case "fix": return rewrite(edit); // nobody is asked
case "comment": return mention(edit); // a person takes ten seconds
default: return count("quiet"); // doing nothing is a decision; count it
}How jevbooks recognises it
How do we know a project does this? We put one question about its README to Jev and it returns a percentage; the higher, the more it looks like it. If you copy the question, copy one thing: ask whether the text mentions this one concrete thing, never whether the project is good.
{
"tiered-thresholds": {
"type": "noul",
"instructions": {
"what": "Does the text describe two or more probability cut-offs mapping to different actions, such as act / flag / clear or deny / ask / allow?",
"not_for": "A single yes-or-no threshold at 0.5."
},
"criteria": {
"true": "The text explicitly describes this. One sentence is enough; other content does not cancel it.",
"false": "The text does not describe this."
}
}
}