Your approved-base-image rule has grown a dozen special-case clauses and still blocks legitimate builds — what do you change?
answer
- Carve-outs are a transcript of past arguments
- The predicate reads what, disputes are why
- Split by decidable versus judgement
- Match opens a review, not a failure
- Routing is tuned for attention, not verdicts
basics
~20 sStop encoding judgement in the predicate. Split the rule: keep a hard block for the part that is mechanically decidable, and demote the rest to a signal that routes the build to a human review instead of failing it.
solid answer
~50 sA rule that keeps growing carve-outs is telling you something: it is being asked to decide necessity, and necessity is not in the document it reads. Each new clause encodes one past argument, so the rule becomes a log of exceptions that is unreadable, untestable, and always one novel case behind. The fix is to split it by decidability. Keep hard-blocking the part that genuinely is a fact — for example, a base outside the organisation's own registries at all. For the rest, demote the rule from an enforcement point to a routing signal: it still evaluates on every build, but a match opens a review with the requester rather than failing the pipeline. You lose nothing in visibility, you stop shipping false blocks, and the judgement moves to the control that can actually make it. The clauses you delete become review context, not policy.
go deeper
Recognise the smell: a rule full of team names and repository names is encoding decisions people made, and those clauses will never stop multiplying.
Be able to sort conditions into the ones fully decided by the artifact and the ones that depend on a reason, and explain why only the first kind should hard-block.
Show that you would change the outcome rather than the predicate, and that you would name the accountable reviewer before demoting anything to a signal.
Own the standard that enforcement mode is a design decision per condition, and that a guardrail's success is measured by the attention it directs, not only by what it stops.
## Reading the symptom A guardrail that accumulates named carve-outs — this repository, that team, this base for the GPU workload, that one until the migration finishes — is not a badly written rule. It is a correctly written rule being asked the wrong question. Every clause was added because someone made a judgement about necessity and the only place to record it was the predicate. The predicate has become a transcript of past arguments. The reason this never converges is structural. The rule reads a document that records *what* was built. The disputes are always about *why*. Adding clauses moves the boundary of which images fail; it never gives the rule access to the information the disputes turn on. So the next unanticipated but legitimate case fails the same way, and the clause count grows monotonically. The costs compound quickly: - **Unreadable.** Nobody can say what the rule now enforces without reading all of it, so nobody can say what it does not enforce either. - **Untestable.** Clauses added for a specific past case have no test that says when they should be removed. They outlive their reason silently. - **Over-broad by accident.** A carve-out written for one team is usually a pattern, and patterns match more than the case that motivated them. The rule quietly stops enforcing for images nobody meant to exempt. - **Corrosive.** Every false block teaches the team that the gate is an obstacle rather than a control, and that is the sentiment that produces the next request to turn it off entirely. ## Splitting by decidability The useful cut is not "strict versus lenient" but **decidable versus judgement**. Go through what the rule currently blocks and sort each condition into one of two piles: **Pile one — facts.** Conditions that are fully determined by the artifact and that nobody has ever legitimately argued about. A base image pulled from outside the organisation's registries at all; a base with no recorded identity whatsoever. These stay a hard block. There is no reasonable case on the other side, so blocking costs nothing and the failure message is unambiguous. **Pile two — judgements.** Everything whose correctness depends on why: an unapproved-but-internal base, a vendor image required by a driver, a legacy runtime kept alive for a migration. These cannot be settled by the predicate, no matter how it is written. ## Demoting the second pile to a routing signal The second pile keeps the rule but changes its **outcome**. The rule still evaluates on every build — you keep full visibility, and the set of deviating images stays complete. What changes is what happens on a match: instead of failing the pipeline, the match opens a review, attaches the offending image and the field that matched, and asks the requester the question the rule cannot: *why this base?* This is deliberate non-enforcement, and it is a design choice rather than a retreat. What you gain: - The block disappears for cases the rule was never able to judge, so legitimate work stops being stopped by a machine that cannot hear the reason. - A person answers the question that was always a person's question, with the artifact and the matching field already in front of them. - The rule stops being edited every time a new legitimate case appears. New cases are review input, not new clauses. - The signal has a job it can actually do well: **narrowing**. Its value is now measured by how small and how relevant the review queue is, not by whether it got every verdict right. What you must be honest about: a routing signal enforces nothing on its own. If reviews are not staffed, or the review is a rubber stamp, you have removed a block and replaced it with a queue. The demotion is only sound if the review is a real control with someone accountable for answering. ## The tuning that follows Once the rule routes rather than blocks, tuning changes character. A rule that blocks must be tuned for correctness — every false positive is an outage for someone. A rule that routes is tuned for **precision of attention**: too many matches and reviewers stop reading; too few and deviations pass unseen. That is a much more forgiving target, and it is the reason demotion often makes a guardrail more useful rather than less. ## The sentence to be ready with "We block what is unambiguous and route what requires a reason." If you cannot say which pile a given condition is in, that condition is the one to look at first.
- What do you actually delete when you make this change, and what happens to those clauses?The named carve-outs go. Each one existed to record a judgement someone already made, so it becomes review context rather than rule logic — the reviewer sees that this team's deviation was accepted before and why. The rule keeps only conditions that are true facts about the artifact. That is usually a rule an order of magnitude shorter, and one you can explain to a new engineer in a sentence.
- How do you avoid the demotion becoming a queue nobody reads?Name an accountable reviewer before you demote, and keep the match set small enough that reading it is realistic. A routing signal enforces nothing by itself; its whole value is that a specific person answers a specific question about a specific image. If nobody owns the queue, you have not moved the judgement anywhere — you have removed a control and told yourself otherwise.
- Is there a case where you keep the hard block despite the false positives?Yes — when the failure it prevents is severe and irreversible, and the false-positive cost is a delayed build rather than a stopped incident response. Blocking is right when being wrong is cheap for the requester and expensive for everyone if you let it through. It stops being right when the requester routinely has a good answer and no way to give it.
saying these in an interview costs you the question
- Adding another clause for each new legitimate case
- Treating growing carve-outs as normal rule maintenance
- Demoting to a signal with nobody reading the queue
- Claiming a stricter predicate can capture necessity
- Removing the check entirely instead of changing its outcome