A feature flag often represents a priority rule. A user override wins over an organization default, which wins over a global default, with a final fallback when none is set. Shortening that rule can change which value wins, even when the new expression looks familiar and the existing tests pass.
Review the behavior table before reviewing the expression’s length. The important questions are what counts as an absent value, whether explicit false values survive, and whether every fallback level remains in the same order.
Write the priority rule in plain language
Suppose the contract is:
- Use the user override when it is present.
- Otherwise use the organization default when present.
- Otherwise use the global default when present.
- Otherwise return false.
This example defines “absent” as null or undefined. Present values are booleans. An explicit false means the feature is disabled at that level; it does not mean “ask the next level.”
Make that definition visible in the task brief and review. If an existing system gives null a different meaning, resolve that contract before choosing an operator. A familiar language feature cannot decide the intended business rule.
Identify both regressions in the shortcut
Consider this proposed replacement:
return userOverride || orgDefault || false;
It has two independent problems. First, logical OR selects by truthiness. A false user override falls through to a true organization default. The feature becomes enabled even though the highest-priority present value disabled it.
Second, the expression omits the global default entirely. When the user and organization values are absent, a true global default is lost and the function returns false.
Changing the operators without restoring the missing level fixes only part of the regression. A review should name both defects and give a concrete input for each, so one partial repair cannot pass as complete.
Use a table that exposes missing cases
For the stated boolean-or-absent contract, useful cases include:
| User override | Organization default | Global default | Expected result |
|---|---|---|---|
| true | false | false | true |
| false | true | true | false |
| absent | true | false | true |
| absent | false | true | false |
| absent | absent | true | true |
| absent | absent | false | false |
| absent | absent | absent | false |
The second row exposes the explicit-false problem. The fifth exposes the missing global fallback. The fourth ensures that an organization-level false stops the chain before a global true.
Expand absent cases to cover null and undefined individually. Do not let one placeholder in a review table conceal two input representations that the implementation actually receives.
Choose an expression only after defining absence
With null and undefined defined as absent, nullish coalescing preserves false and retains all three levels:
function resolveFlag(
userOverride,
orgDefault,
globalDefault
) {
return (
userOverride ??
orgDefault ??
globalDefault ??
false
);
}
This is an illustrative helper for the contract above. Its shape is less important than the cases it must satisfy. A longer conditional implementation can be equally correct.
Nullish coalescing also preserves zero and an empty string. That language behavior does not make those values valid feature flags. Decide how invalid configuration is rejected or handled at the boundary; do not silently replace a boolean contract with “anything truthy enough.”
Preserve the contracts around the expression
Trace where the three values come from. An unknown flag may follow a different path from a known flag with no override. A disabled user may be rejected before evaluation. A stale configuration may have an established fallback or error policy.
Identify which of those behaviors belongs to this patch. A value-selection helper alone cannot demonstrate that access checks, configuration lookup, and error handling still behave correctly.
If retrieving a fallback has observable cost or side effects, inspect evaluation order too. Selecting false at the first level should not accidentally trigger work that the old control flow skipped. State that expectation separately from the table of resolved values.
Add characterization checks before changing behavior
When the old contract is poorly documented, capture representative client inputs and outputs before replacing the implementation. Include the explicit-false cases, every fallback level, unknown flags, and relevant stale-configuration behavior.
Investigate conflicts between observed behavior and the intended rule. Existing behavior can contain a defect, but correcting it requires an explicit decision about compatibility. A refactor should not smuggle that decision into an operator change.
Write assertions against the selected result or established error, rather than the presence of a particular operator. A test that merely expects a helper call can survive while the caller drops the global value. Exercise the path through which clients obtain the result.
Review the callers and the tests together
Check whether the patch changes input normalization, defaults, configuration caching, or the response shape alongside the expression. A correct helper can receive the wrong arguments or have its false result overwritten later.
Compare tests with the behavior table. Identify which case would fail for the original shortcut and which would fail for a partial repair that uses only two nullish levels. Retain both.
Keep outcomes and performance evidence separate. Faster evaluation is useful only after the required behavior is preserved. Compare performance using equivalent inputs and workloads; a shorter fallback path that skips required behavior is a different computation.
Make intentional behavior changes explicit
Sometimes the old priority rule should change. Describe the new rule, affected callers, migration expectations, and owner before accepting the patch. Include checks for the clients that depend on the contract and the edge cases they exercise.
A useful review finding is concrete: “An explicit false user override must beat the organization default. The proposed OR chain returns true for that case. It also drops a true global default when both higher levels are absent.”
The closing review should state which behavior is preserved, which checks are proposed or observed, and what remains unverified. Approve the simplification when its behavior matches the agreed contract, with every intentional deviation separately explained and owned.
The Agentic Developer Interview includes Behavior Regression Hunt and Interface Contract Brief cards covering explicit-false overrides, fallback order, and client-visible edge-case contracts.