FUI9008: Rule override outranks a record's authored severity
moderateA govern.rules entry enforces a different severity than the policy record next to it authored.
Details
{
"code": "FUI9008",
"ruleId": "config/overridden-record-severity",
"category": "System",
"defaultSeverity": "moderate",
"lifecycle": "experimental",
"fixAvailable": false,
"evidenceRequired": false
}Guidance
What it means
You authored a severity on a governance record — govern.styles[] or govern.jsx[] — and a
govern.rules entry in the same policy enforces a different one. The rule entry wins, so the
severity you can read on the record is not the severity that gates CI.
This usually comes from a broad rule id. tokens/hardcoded-values is a family: it stands
for styles/no-raw-color, styles/no-raw-spacing, styles/no-raw-typography,
tokens/require-dual-fallback and theme/no-theme-coupled-literal at once. Setting a severity
on the family sets it on every one of those rules, including the one your record just authored
at a different level.
You will not see this for a preset. A preset's family entry is a default — it says what the family looks like when nobody has an opinion — so your record's severity wins and nothing is reported. FUI9008 fires where that distinction cannot be made: a Cloud-served policy arrives whole, with no way to tell which of its entries came from a preset and which someone typed.
The diagnostic is verdict-neutral: it warns on stderr and never fails a run on its own. Turn it
into a gate with govern.ci.failOnInert.
How to resolve it
Pick one place to say it. Either drop the rule override and let the record speak:
govern: {
styles: [
{
kind: "style.rawColors.forbid",
except: ["transparent"],
prefer: "token",
severity: "error",
},
],
// rules: { "tokens/hardcoded-values": { severity: "warn" } }, ← removed
}
…or keep the override and author the record at the severity you actually want enforced. If the
override is deliberate for one rule but not the whole family, name the concrete rule id
(styles/no-raw-color) instead of the family — a narrower key changes less.
Verify the change
Run npx @usefragments/cli check --format json and read the finding's severity and level:
they should now match what the record says. check --ci gates on level, so this is the field
worth confirming. Set govern.ci.failOnInert: true to keep the config honest from then on.
Intentional exception? Use a narrow, reasoned directive from the in-source suppression reference.