{
 "format": 1,
 "severities": [
  "error",
  "warning",
  "at-verified",
  "mixed",
  "mixed-at-verified"
 ],
 "rules": [
  {
   "code": "L0",
   "scope": "any yaml",
   "rule": "the file parses as YAML",
   "why": "A file that does not parse cannot be drawn, exported or checked at all, so the fault is reported at its own line rather than as an unexplained failure further on.",
   "fix": "fix the syntax the message points at; a `#` after a space inside an unquoted string starts a comment",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L1",
   "scope": "any yaml",
   "rule": "the file validates against its schema",
   "why": "The renderer, the exports and every later check read the shape the schema describes, so a misspelt key or a value of the wrong type would otherwise be ignored or misread without a word.",
   "fix": "the path in the message names the key; the schema's description for it says what is accepted",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L2",
   "scope": "any id",
   "rule": "every id and segment matches ^[a-z0-9]+(-[a-z0-9]+)*$ with no double hyphen",
   "why": "Every id becomes a segment of the element ids and data paths in each drawing, so a capital, a space or a double hyphen would break the addresses that selectors, the explorer tree and the exports rely on.",
   "fix": "rename the id; it becomes a DOM id segment in every SVG",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L3",
   "scope": "component",
   "rule": "every contracted element id exists in every declared skin",
   "why": "A skin without an element the contract promises draws that variant without the node the explorer, the lamp states and the 3D relief address, so the element silently vanishes when that skin is chosen.",
   "fix": "add the element to the skin, or remove it from `elements:`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L4",
   "scope": "component",
   "rule": "each skin's viewBox matches the contract size",
   "why": "A skin drawn to a different size from its contract is stretched or shifted when it is placed in millimetres, so every opening and lamp in it lands in the wrong place on the faceplate.",
   "fix": "set `viewBox=\"0 0 <w> <h>\"` and mm width/height from `size`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L5",
   "scope": "device",
   "rule": "placement refs resolve in the library, and instance ids are unique per view; no placement ref, and no bay's `accepts` or `default`, is a `kind: kit`, which a device names only from `chassis.kits`",
   "why": "A placement that resolves to nothing, or two parts sharing one id in a view, leave a missing part or an ambiguous address in the drawing, and a rail kit placed like a module draws something no build contains.",
   "fix": "fix the `ref` (namespace/name@major) or the duplicate id; list a rail kit under `chassis.kits` and place its parts, if anything, by their own refs",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L6",
   "scope": "device",
   "rule": "a bay's default appears in its accepts list",
   "why": "A bay whose default it does not accept draws a module the vendor says does not fit there, and a bay nothing ever fills draws as an empty frame in every drawing of the device.",
   "fix": "add the default to `accepts`, or change the default",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L7",
   "scope": "device",
   "rule": "region members reference existing instance ids",
   "why": "A region framing an id that is not in its view frames nothing, so a reader sees a labelled block whose members the drawing cannot find.",
   "fix": "name ids that exist in the same view",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L8",
   "scope": "device",
   "rule": "a configuration seats only what its bays accept, and only in bays that exist in it",
   "why": "A configuration that seats a module its bay does not accept, or fills a bay its build does not have, shows a fit-out nobody can order, or silently drops the module.",
   "fix": "add the occupant to the bay's `accepts`, or seat something the bay takes; for a bay `only-in` scopes out, add the configuration to it or drop the key",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L9",
   "scope": "component",
   "rule": "a conforms-declared size matches spec/schemas/standards.yaml",
   "why": "A part that claims a published standard but is drawn to another size passes a wrong aperture to every device that places it, with the standard's name vouching for it.",
   "fix": "take the size from the registry, or drop `conforms` if the part is not the standard aperture",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L10",
   "scope": "component",
   "rule": "composed parts resolve, ids are unique, composition does not cycle (depth <= 4), and neither a part nor a bay's `default` or `accepts` is a `kind: kit`",
   "why": "A composition that names a missing part, repeats an id or loops back on itself cannot be drawn, and a kit composed as a part offers something no configuration can hold.",
   "fix": "fix the `parts:` refs; a part must not compose itself; a kit is named from a device's `chassis.kits`, never composed or seated",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L11",
   "scope": "component",
   "rule": "interface/mates declarations carry a `mate` connection point, and a wrapper keeps the interface of what it composes",
   "why": "A receptacle or plug with no mate point has nothing to align to, so it cannot be seated, and a wrapper that changes its interface lets parts pass the fit check against something they do not really mate.",
   "fix": "add `connection-points.mate`; do not change the interface in a wrapper",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L12",
   "scope": "device",
   "rule": "mate-to resolves to a receptacle whose interface the occupant mates; a seated part's `rate` is at or below its cage's media",
   "why": "A drawing could otherwise seat a part where it cannot go, such as a QSFP transceiver in an SFP cage or a 10G cable in a 1G cage, while still looking right.",
   "fix": "point `mate-to` at the receptacle id; check `interface` and `mates` agree; seat a part the cage offers",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L13",
   "scope": "device",
   "rule": "two placed components do not occupy the same faceplate area",
   "why": "Two parts on one patch of faceplate are almost always a sizing mistake, hidden in the flat drawing where one paints over the other and plain in 3D as a lamp hanging over a port.",
   "fix": "move one, or declare `for:`/`under:` when one deliberately sits on the other",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L14",
   "scope": "device",
   "rule": "a silkscreen `for:` target exists and is nearby",
   "why": "A legend or lamp bound to a part that does not exist, or to one across the panel, tells a reader and every tool that follows the binding something false about what it annotates.",
   "fix": "name the placement or bay the mark annotates, and anchor the mark at it",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L15",
   "scope": "device",
   "rule": "a device at `modelled` or above has a provenance block good enough for the level",
   "why": "A device that claims to be modelled or verified could otherwise carry figures with no source, so nobody could tell a measured dimension from a guess.",
   "fix": "add provenance for every figure, or lower `maturity`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L16",
   "scope": "device",
   "rule": "keys inside a view read in manufacturing order",
   "why": "Anyone building a device follows the file stage by stage, so a view written out of manufacturing order teaches the wrong procedure and is harder to compare with its neighbours.",
   "fix": "reorder: empty, size, open-frame, panel, silkscreen, components, regions",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L17",
   "scope": "component, device",
   "rule": "a placement's or part's group is declared under `groups:`, and a component that declares groups puts every port part in one",
   "why": "A group used but never declared carries no vendor term, role or numbering origin, and on a card, ports half inside and half outside groups read as two kinds of port where there is one.",
   "fix": "declare the group with term, role and index-origin; join the loose port to a group",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L18",
   "scope": "device",
   "rule": "a port inherits media from its group rather than restating it",
   "why": "A port that takes its media from a cage covering a whole family shows only the family, so an SFP28 port reads as SFP and the model looks complete when it is not.",
   "fix": "drop the per-port media, or fix the group's `attrs.media`",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L19",
   "scope": "device",
   "rule": "an indicator declares `for:` the thing it indicates - a lamp, button or display placement, and a bay in a group whose role is `indicator`",
   "why": "A lamp, button or display with no stated subject leaves its meaning to a naming convention a reader can guess and no tool can read.",
   "fix": "add `for:` to the lamp placement or the bay; a panel that reports on the whole box is `for: chassis`",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L20",
   "scope": "component, device",
   "rule": "state names are tokens and each `behavior` is well-formed, on a contract's states, an element's, or a placement's",
   "why": "A state written as prose cannot become the class and the chip the viewer builds from it, and a malformed behaviour cannot be animated, so the lamp's real meaning reaches no one.",
   "fix": "a state name is a token like `link`; prose goes in `description`; `behavior` is solid, blinking, alternating or sequence, with `behavior.color` for the second colour",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L21",
   "scope": "device",
   "rule": "chassis silkscreen does not sit under a bay where the module covers it",
   "why": "A legend printed where a module sits is painted over by it and cannot be read in the drawing.",
   "fix": "move the mark, or put it in the module's own skin if the module carries it",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L22",
   "scope": "component, device",
   "rule": "a group's declared media/speed matches the ports it holds",
   "why": "A group's attributes are copied onto every member, so a group whose media or speed contradicts a member would quietly relabel that port, for example an RJ45 jack drawn as SFP28.",
   "fix": "fix the group's `attrs`, or move the odd port to its own group",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L23",
   "scope": "component, device",
   "rule": "a port group is one family, or says in `mixed:` why it is not",
   "why": "A group mixing connector families cannot carry shared attributes, and an unexplained mix cannot be told from ports nobody has sorted yet.",
   "fix": "split the group by family, or add `mixed:` naming the job they share",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L24",
   "scope": "device",
   "rule": "`attrs.other` is counted so the long tail cannot go quiet",
   "why": "Keys left in the catch-all section are counted on every run, so the catch-all cannot quietly become the place anything awkward is put.",
   "fix": "file each key under its section where one fits; otherwise leave it and accept the count",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L25",
   "scope": "device",
   "rule": "one attr key is claimed by one section",
   "why": "Attribute sections flatten into one set of data attributes on the drawing, so two sections claiming one key would let one fact silently overwrite the other.",
   "fix": "rename one of the two; keys flatten to data-<key>",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L26",
   "scope": "component",
   "rule": "every `class: cutout` element is backed by a conforming contract or a part that resolves to one",
   "why": "An opening with no standard part behind it has a size nothing checks, and the count keeps every such opening visible until a standard or a drawing is found for it.",
   "fix": "add `conforms`, or compose the std/ part that owns the aperture",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L27",
   "scope": "component",
   "rule": "a power-bearing module states its power figure or records that no document holds it",
   "why": "A power-bearing module with neither a figure nor a recorded absence leaves power totals short, with no record of which figures are missing.",
   "fix": "add `power-output-w` or `power-draw-max-w` from the guide's appendix, or leave the warning as the record",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L28",
   "scope": "component",
   "rule": "a power figure says which way it points and its min/typical/max are ordered",
   "why": "A bare watts figure cannot say whether a part supplies or draws power, and a minimum above its maximum is a transcription slip, so either would corrupt any power budget built from the library.",
   "fix": "use `power-output-w` for supplies and `power-draw-*-w` for consumers; never `watts`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L29",
   "scope": "device",
   "rule": "a chassis says how many of the modules it accepts have no figure",
   "why": "A chassis whose modules lack figures would total to a small, confident, wrong power draw, so the count of modules with no figure travels with the total and marks it as a floor.",
   "fix": "walk the list; each is either in a document you missed or stays as the record",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L30",
   "scope": "device",
   "rule": "a card whose figure covers its paired module does not sit beside a module that also states its own",
   "why": "When a card's figure already includes its paired module and that module states its own, a sum over the bays counts the pair twice and gives a plausible over-count.",
   "fix": "decide which figure carries the pair and say so",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L31",
   "scope": "device",
   "rule": "a region's label matches the group or id it frames",
   "why": "A region label that disagrees with what the drawing puts there tells a reader a part is somewhere it is not.",
   "fix": "fix the label text or the region's members",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L32",
   "scope": "any yaml",
   "rule": "no mapping declares the same key twice",
   "why": "YAML keeps the last of two identical keys without a word, so whatever the first one said is lost before any rule or reader sees the file.",
   "fix": "remove the duplicate; YAML keeps the last silently",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L33",
   "scope": "device",
   "rule": "a bay reserves room for every module it accepts",
   "why": "A module larger than the bay that accepts it is either a part that cannot fit or a figure measuring something else, and either misleads someone planning a fit-out.",
   "fix": "size the bay to the largest `insert`/`size` it accepts, or remove the module from `accepts`",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L34",
   "scope": "device",
   "rule": "front and rear occupants sharing a slot column, in every configuration, fit around the midplane",
   "why": "Front and rear modules in one slot column can each look plausible yet together be deeper than the chassis, giving the 3D view and anyone planning a fit-out depths that cannot both be true.",
   "fix": "check the two depths against chassis depth; one of them is wrong, or the two cannot be seated together",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L35",
   "scope": "component",
   "rule": "a relief magnitude says where it came from",
   "why": "A relief depth with no stated source looks exactly like a measured one, so neither a reader of the 3D model nor the next contributor can tell a guess from a fact.",
   "fix": "add `confidence` and `source` to each `relief.features` entry",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L36",
   "scope": "component",
   "rule": "a `borrowed` relief magnitude names an origin that actually measured it",
   "why": "A borrowed depth claims another part measured it, so a borrowed guess, or a chain of them, would otherwise pass for a measurement in the 3D model.",
   "fix": "name a part whose own figure is `measured` or `photo-measured`, or use `estimated`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L37",
   "scope": "component, device",
   "rule": "a group says what it is for and has members",
   "why": "Without a role nothing reading the drawing can tell the bays the box exists for from the ones that keep it running, and a group with no members promises parts that are not there.",
   "fix": "add `role`; delete a group nothing joins",
   "severity": "at-verified",
   "fails": false,
   "warns": true,
   "fails-at-verified": true
  },
  {
   "code": "L38",
   "scope": "component",
   "rule": "printed text in a skin sits in `<g id=\"silkscreen\">` unless the part is applied over the panel",
   "why": "Printing grouped as silkscreen is a layer of its own, so a drawing without the printing drops every legend and keeps the metal without relying on a sweep for loose text, and anything reading the skin can tell what is printed from what is cut.",
   "fix": "wrap the text nodes in the silkscreen group",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L39",
   "scope": "device",
   "rule": "the panel's holes agree with what goes in them: no overlap, standard sizes, no legend on a hole, every port has one where cutouts are declared",
   "why": "A hole that disagrees with its part draws metal the hardware does not have, misleading anyone checking the drawing against the real panel.",
   "fix": "fix the cutout size/position, or the placement; one wrong `ref` shows as many overlaps",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L40",
   "scope": "device",
   "rule": "a pluggable cage says which optics run in it, and optics prose names a group that exists",
   "why": "A cage's shape says which optics fit, not which ones work, so someone fitting an optic to a port would have nothing to go on.",
   "fix": "add the group's optics attrs, or fix the group name in the prose",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L41",
   "scope": "device",
   "rule": "a bay or placement scoped to configurations names ones that exist, not all, not none",
   "why": "A typo in `only-in` drops a bay or part from the configuration it was meant for, and scoping to every configuration leaves the part out of one added later.",
   "fix": "fix `only-in`",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L42",
   "scope": "device",
   "rule": "a silkscreen mark says what it annotates, or `chassis` for printing about the whole unit",
   "why": "A legend with no owner cannot be checked for sitting beside its part or hidden by the module that covers it, and nothing reading the drawing can say what is printed next to a given port.",
   "fix": "add `for:`",
   "severity": "at-verified",
   "fails": false,
   "warns": true,
   "fails-at-verified": true
  },
  {
   "code": "L43",
   "scope": "device",
   "rule": "a front or rear view as wide as the rack face still has its ears in it, unless the device is a `rack-face` part, which is its ears, states `chassis.ears: behind` (or `ears: {behind: true}`), whose face is the part, or has a body as wide as the rack (a blanking plate, whose ears are built into the face)",
   "why": "The library draws the metal between the ear folds, and the ears are added from the chassis, so a face measured across the ears puts every port off by an ear's width and gives the rack a body wider than the opening it fits.",
   "fix": "model the body between the ear folds; record the ear extent in provenance",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L44",
   "scope": "device",
   "rule": "panel decor agrees with the face: a patterned field is not buried under parts, printing does not run off the edge, no decor lies wholly off the face",
   "why": "Decor that is buried under parts, runs off the face, or lies wholly off it shows vents or printing the real panel does not have, and usually means something was mismeasured.",
   "fix": "move or trim the decor",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L45",
   "scope": "device",
   "rule": "a view at `modelled` draws something or declares itself empty",
   "why": "A face that only declares a size is not drawn, so the device would claim more than it shows unless the author records why the face stays empty.",
   "fix": "add content, or an `empty:` sentence of 40+ characters saying where you looked",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L46",
   "scope": "component",
   "rule": "composed parts do not collide inside the part",
   "why": "Two parts composed into the same place render as doubled or buried detail, such as one cage stacked over another, which a reader would take for real hardware.",
   "fix": "move a part, or say in provenance that the layering is deliberate",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L47",
   "scope": "component",
   "rule": "a state nothing draws is not declared",
   "why": "The viewer would offer a lamp state, such as fault, that changes nothing when chosen, because no drawn lamp takes the state's colour.",
   "fix": "draw a lamp element for the state, or remove the state",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L48",
   "scope": "component",
   "rule": "a bay the contract declares is drawn by a skin",
   "why": "With no drawn element for the bay a seated module has nothing to nest under, so the explorer hangs it off the chassis rather than inside the part that holds it.",
   "fix": "draw the bay opening in every skin, or remove the bay",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L49",
   "scope": "device",
   "rule": "members of one group, cut to one size, sit on one pitch",
   "why": "Uneven spacing among same-size members of one group is nearly always a misreading, and drawn as found it puts modules where the hardware does not.",
   "fix": "re-measure; an uneven pitch is usually a mis-read, not a finding",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L50",
   "scope": "component",
   "rule": "printing inside a skin is legible at the size it is set",
   "why": "Printing that runs off the edge of the part, or is covered by something drawn after it, is printing the reader cannot see while the drawing claims it is there.",
   "fix": "raise the font size or drop the text",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L51",
   "scope": "component",
   "rule": "a class has a power role in spec/schemas/power-roles.yaml",
   "why": "A class with no power role is never asked for a figure, so a power total quietly counts an unknown part as zero and presents a lower bound as the total.",
   "fix": "add the class under `draw`, `supply` or `passive` in power-roles.yaml",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L52",
   "scope": "component",
   "rule": "a stated power figure says where it was read from",
   "why": "Vendor power figures vary with conditions, so a number with no source cannot be rechecked or tied to the row it came from.",
   "fix": "add the provenance key the message names",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L53",
   "scope": "device",
   "rule": "content changed without the version bump the change requires (see devicelock)",
   "why": "Without it, a drawing someone has cached or imported goes stale without notice: a moved slot breaks a saved coordinate just as a renamed id breaks a saved reference.",
   "fix": "bump `version`: patch for wording, minor for additions, major for geometry or ids",
   "severity": "at-verified",
   "fails": false,
   "warns": true,
   "fails-at-verified": true
  },
  {
   "code": "L54",
   "scope": "device",
   "rule": "a gap's scope names a group, view, configuration, id or attribute the device has",
   "why": "A gap scoped to something renamed or never declared would be read as applying to a part of the device that does not exist.",
   "fix": "fix the `scope`, or drop it",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L55",
   "scope": "library",
   "rule": "every vendor namespace is in spec/schemas/vendors.yaml",
   "why": "A namespace missing from the registry breaks the link from the name on the metal to the company that owns it now, so a search under the current name finds nothing.",
   "fix": "add the vendor to the registry with display, role and source",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L56",
   "scope": "listing",
   "rule": "a listing sits under a software vendor in spec/schemas/vendors.yaml and lists a device that exists - every configuration it overrides, port it names and component it maps is the hardware's",
   "why": "A listing that names a port, configuration or part the hardware lacks would export interfaces and modules to a DCIM that no box has.",
   "fix": "register the NOS vendor with role software, point `hardware` at a device's <namespace>/<directory>, and name only configurations and ids that device declares",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L57",
   "scope": "device",
   "rule": "exactly one configuration is `kind: base`, and each says whether it is orderable",
   "why": "Without a kind on each configuration the DCIM export can name a device type after an illustration rather than an orderable chassis, and the drawing can open on something nobody can buy.",
   "fix": "set `kind` on every configuration",
   "severity": "mixed-at-verified",
   "fails": true,
   "warns": true,
   "fails-at-verified": true
  },
  {
   "code": "L58",
   "scope": "component",
   "rule": "a cage's own connection point agrees with the aperture inside it",
   "why": "When the two points disagree, a cable drawn to the declared point and a module seated on the aperture's point end up in different places.",
   "fix": "move the connection point to the composed aperture's",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L59",
   "scope": "device",
   "rule": "SKUs live on configurations, not at the top level",
   "why": "The DCIM export reads part numbers per configuration, so it never sees SKUs left at the top level: one already on a configuration is a second copy that can go stale, and one on none is an orderable build missing from the export.",
   "fix": "move `part-numbers` into the configuration they belong to",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L60",
   "scope": "device",
   "rule": "a face that declares itself empty is actually bare",
   "why": "A face declared empty counts as finished without drawing anything, so a stale claim would contradict the drawing and pass the face on false grounds.",
   "fix": "remove the `empty:` or the content; not both",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L61",
   "scope": "device",
   "rule": "a legend is centred on the thing it names, or plainly not trying to be",
   "why": "A legend a fraction of a millimetre off the part it labels looks wrong to anyone who zooms in.",
   "fix": "centre it, or move it clear",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L62",
   "scope": "device",
   "rule": "an id names the connector the way the rest of the library does",
   "why": "An id that names the connector rather than its job becomes false when the part changes, and two correct models of one device end up with different names for the same port, so references and exported interface names drift.",
   "fix": "use the convention the message quotes (e.g. `port-N`, `led-port-N`)",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L63",
   "scope": "device",
   "rule": "a configuration binds each face to a view that draws that face; a hole is derived from its part, not drawn around it",
   "why": "A face bound to a missing view, or to another face's view, makes an impossible front and rear pairing look declared, and a hole drawn around its part is a second record of the opening that can disagree with the first.",
   "fix": "fix the `views` binding, or derive the cutout from the placement",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L64",
   "scope": "device",
   "rule": "nothing is bolted to, or printed on, an air hole",
   "why": "A vent field is open air, so a legend placed on it is printed on nothing and a jack is mounted to nothing.",
   "fix": "move the part or the mark off the vent field",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L65",
   "scope": "component",
   "rule": "a DC power part with nothing seated states what it can pass",
   "why": "On a DC chassis a power entry module is the only way power gets in, so if it states no rating nothing says how much power the chassis can take.",
   "fix": "add `power-output-w` for the PEM/terminal",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L66",
   "scope": "device",
   "rule": "a power group with more than one bay states its redundancy",
   "why": "Two supplies mean either double the capacity or one plus a spare, so someone adding up the bays could provision for twice what the box can rely on.",
   "fix": "add `attrs.redundancy` (e.g. `1+1`) and a `redundancy-note` citing the guide",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L67",
   "scope": "device",
   "rule": "a control-plane or fabric group with more than one bay states its redundancy",
   "why": "Someone counting control or fabric cards would take a standby spare for working capacity and overstate the headroom.",
   "fix": "as L66, for the RE/RP/fabric group",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L68",
   "scope": "library",
   "rule": "a measurement keeps one attr name and one section across the library",
   "why": "A comparison that cannot find one spelling shows a blank or a wrong figure with nothing to warn the reader, and a key filed under different sections cannot be found by section.",
   "fix": "use the name the message quotes",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L69",
   "scope": "device",
   "rule": "a cooling group with more than one bay says how many fans it can lose",
   "why": "Without a stated figure nobody comparing devices or planning cooling can tell how many fans the box can lose and keep running.",
   "fix": "add `attrs.redundancy` (e.g. `n+1`) and a note",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L70",
   "scope": "device",
   "rule": "a `fact:` gap names a real fact and does not contradict the device",
   "why": "A gap scoped to a misspelt fact leaves the comparison showing a bare blank although the search was done, and a device that states a figure while calling the vendor silent on it shows a number and a retraction at once.",
   "fix": "fix the gap's scope or remove it",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L71",
   "scope": "component",
   "rule": "a body box reaches no further than the part says it is deep; a round one states its axis (a ring its wall) and is square across it; one that `shows` a drawing is a box of a part declaring that face",
   "why": "A body box deeper than the part gives the wrong bay hole, pull distance and fit checks, and a round piece with no axis or a non-square section builds as an oval in 3D.",
   "fix": "shrink the body box or raise `body.depth`; state `axis`/`wall` or square the envelope; declare the face or drop `shows`",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L72",
   "scope": "device",
   "rule": "a bay's `plan:` or `rear:` lands in a view that exists, inside the chassis",
   "why": "A bay projected into a view or neighbour that does not exist draws nothing and raises nothing, so the plan or rear view silently loses the part.",
   "fix": "fix the plan view name or the coordinates",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L73",
   "scope": "component",
   "rule": "a field prints somewhere, and what prints is a field; a node a field paints states no relief `color`, so its 3D sides follow the field",
   "why": "A form would offer a field that changes nothing on the drawing, or the drawing would paint from a value no form can set, and a fixed relief colour leaves a field-painted part's 3D sides the wrong colour.",
   "fix": "add a `data-from` text node for each field, or remove the field; drop a relief feature's `color` on a field-painted node",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L74",
   "scope": "component",
   "rule": "a lamp that declares states is painted from the lamp-colour variable",
   "why": "A lamp painted in a literal colour ignores every state its contract declares, so in 2D and 3D it can never light the way the viewer says it does.",
   "fix": "fill or stroke the lamp node with `var(--led-color, <off colour>)`, not a literal colour",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L75",
   "scope": "component",
   "rule": "a slot's structured facts agree with its prose, and lanes fit the connector",
   "why": "A slot's prose and its structured facts would drift apart, so a reader and the card-fit check would see different slots, and a lane count wider than the connector is a typo, not a slot.",
   "fix": "fix `lanes`/`connector` or the description",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L76",
   "scope": "device",
   "rule": "the RJ45 census: every Ethernet jack says whether it has lamps",
   "why": "Every Ethernet jack has to answer whether it has link lamps the same way, or a drawing can leave out lamps the hardware has, or add them to a console jack, and the viewer cannot light them consistently.",
   "fix": "use std/rj45@2 with the lamp parts, or say in provenance the jack is bare",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L77",
   "scope": "component",
   "rule": "a `sink` sits in a cavity, because that is what it measures from",
   "why": "A sink with no cavity above it has no floor to measure from, so the recess is declared but never built in 3D, and nothing reports it.",
   "fix": "use `pocket` for a recess in an otherwise solid face",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L78",
   "scope": "component",
   "rule": "an optical endpoint names a composed connector and a position it has; a front order that names a part's positions names each once, together; a trunk entry names a connector on this face and a position it has",
   "why": "An optical endpoint, front order or trunk entry that names a missing part or position describes a fibre that does not exist, so ports are left unnumbered or numbered twice.",
   "fix": "fix the part id or the position number; list every position of the part, or name it bare",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L79",
   "scope": "component",
   "rule": "no fibre position is claimed twice, and a split's ratios sum to 100; a source starts one path, unless every path it starts but one carries a `band` (an add/drop filter)",
   "why": "Two paths into one bore describe something no ferrule allows, and ratios that do not add to 100 describe a split that cannot exist.",
   "fix": "remove the duplicate path, or fix the ratios; write a split as one path with a ratio list",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L80",
   "scope": "component",
   "rule": "every fibre position is reached by a path or declared unused with a reason",
   "why": "A fibre position nothing reaches cannot otherwise be told from a deliberate dead end, so a missed path would pass as a design choice.",
   "fix": "route it, or add an `optical.unused` entry saying why it terminates nothing",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L81",
   "scope": "component",
   "rule": "a composed pitch respects the standard the part conforms to - equal for a target, no narrower for a floor",
   "why": "Connectors set closer than their standard allows, or off its fixed pitch, draw a port array a mating plug or neighbouring module would not line up with.",
   "fix": "move a target onto the standard's pitch, widen a floor to at least it, or say in provenance why this part differs. Where the placements share an x, make their `rotate` agree so a rotated column can be told from a stacked pair",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L82",
   "scope": "component",
   "rule": "a part names its plan drawing one way or the other, never both",
   "why": "Two copies of one plan reference agree only until someone edits one and misses the other, and then every reader has to guess which copy counts.",
   "fix": "keep `plan:` or `faces.plan`, not both - they mean the same thing",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L83",
   "scope": "component",
   "rule": "a declared face names a real component, is not the part itself, and that component has no face of the same direction",
   "why": "A face ref with a typo draws nothing while the contract still lints, and a face that names its own part, or a direction the named part already has, means the wrong part is drawn.",
   "fix": "fix the ref, or drop the face it names if the chain has no meaning",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L84",
   "scope": "component",
   "rule": "a face-qualified optical endpoint names a face the part declares",
   "why": "An endpoint qualified with a face the part does not declare resolves to nothing, and its fibre drops out of the map.",
   "fix": "add the face to `faces:`, or fix the prefix on the endpoint",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L85",
   "scope": "component",
   "rule": "only a face that is another side of the module draws fibres of its own",
   "why": "A connector drawn on a face that is only another view of the same module is not counted, so it is either the front's port drawn twice or a real port missing from the fibre map, and nothing says which.",
   "fix": "move the connector onto the face that really carries it, or extend `faces.OPTICAL_FACES` if this direction genuinely is another side",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L86",
   "scope": "component",
   "rule": "a module composing a connector the enum spells two ways states its polish",
   "why": "Without a stated polish a module of LC or similar adapters has no port type a DCIM import can take, because the type is spelled UPC or APC.",
   "fix": "add `optical.polish: upc` or `apc`, and say in provenance where it came from",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L87",
   "scope": "component",
   "rule": "a module naming what its rear IS has a rear face to name",
   "why": "A rear kind on a module with no rear face describes a drawing that does not exist, so the export writes nothing for that side and nothing says so.",
   "fix": "add `faces.rear`, or drop `optical.rear-kind`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L88",
   "scope": "component",
   "rule": "a fibre face with more than one row of connectors states its own front numbering",
   "why": "On a face with more than one row of connectors, numbering by position alone guesses the vendor's printed order, so DCIM front ports could be numbered differently from the silkscreen.",
   "fix": "add `optical.front-order` listing the fibre part ids in the vendor's printed order",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L89",
   "scope": "library",
   "rule": "every component major is reachable from a device, or says why it is not",
   "why": "A part nothing seats would look in the catalogue exactly like one in use, so a reader could choose a part no drawing has ever shown in place.",
   "fix": "seat it in a device or in a seated part's bay, or add `unplaced:` saying what would seat it and what is missing",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L90",
   "scope": "device",
   "rule": "a manifest's top-level keys read in the canonical order",
   "why": "Keys in one order across every manifest let a reviewer compare two devices line by line, and a contributor copying a neighbour copies the canonical layout rather than an accident.",
   "fix": "reorder them; the message prints the order, and docs/device-template.yaml is written in it",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L91",
   "scope": "device",
   "rule": "airflow is stated once - on the chassis, and on a configuration only where it differs",
   "why": "Airflow stated in two places drifts, so a change to the chassis could be masked by stale copies, and a reader cannot tell a real difference between builds from repetition.",
   "fix": "move it to `chassis.airflow`, or drop the configuration's copy",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L92",
   "scope": "component",
   "rule": "a part's size says where it came from",
   "why": "Cutouts, bay sizes and pitches are derived from a part's size, so an unsourced size spreads unchecked into everything built on it.",
   "fix": "add a `size:` provenance note; the key for a size is `size`, not a sentence about it",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L93",
   "scope": "device",
   "rule": "a provenance entry says how the figure is known, not only where it was read",
   "why": "Without a confidence word nobody can ask which figures are estimated and which were measured, so an estimate reads like a measurement.",
   "fix": "add `confidence:` beside the note, from the eight words in the confidence enum",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L94",
   "scope": "device",
   "rule": "a `component-attrs` key names a component the device seats, or a placement or bay it declares",
   "why": "A key that matches nothing renders exactly as if the line were missing, so a typo silently drops a setting someone meant to make.",
   "fix": "fix the key; one that matches neither sets nothing and is silently ignored",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L95",
   "scope": "component",
   "rule": "a power supply says where power enters it",
   "why": "A supply that does not say where power enters it exports no power port, so a DCIM shows supplies with nothing to cable.",
   "fix": "compose an inlet part, or add `attrs.inlet` from the enum - `none` if the chassis carries it",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L96",
   "scope": "component",
   "rule": "a module composing a pluggable cage says what rate it runs at",
   "why": "A card that does not state its cages' rate is exported with a default, so a DCIM can show 10G interfaces on a card that is 1G, with nothing to tell a right default from a wrong one.",
   "fix": "add the media attr for that family - `sfp`, `sfp-plus`, `qsfp`, `qsfp28`, `qsfp-dd`, `xfp-10g` - with the port count; a cage carrying a proprietary link no rate names takes `proprietary-link: <label>` on its placement instead",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L97",
   "scope": "component",
   "rule": "a part that states a size says where each dimension came from",
   "why": "A dimension with no confidence reads exactly like a measured one to anything that has only the number, so an estimated size passes for a measured one.",
   "fix": "add `size-confidence: {w: ..., h: ...}` from the confidence vocabulary, and `size-notes` where it needs a sentence",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L98",
   "scope": "component",
   "rule": "a character display says how wide it is, and every reading fits",
   "why": "A display with no character width cannot have its readings checked, so a reading too long for the display survives as a silent transcription error.",
   "fix": "add `characters:` to the `class: display` element, and keep each `messages[].text` inside it",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L99",
   "scope": "component",
   "rule": "a generic stays generic - no rate, reach, wavelength or wattage under generic/",
   "why": "A generic part stands for every module of its kind, so a rate, reach or wattage on it would make one product's figure look like a property of the whole family.",
   "fix": "move the figure to the vendor wrapper's attrs; a generic/ part stands for every module of its kind",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L100",
   "scope": "component, device",
   "rule": "no key in an `attrs:` map has a null value",
   "why": "A null attr carries nothing into the drawing or the export, and is almost always a missing colon that would otherwise fail far away, looking like a fault in the tools.",
   "fix": "add the missing colon and a value; in flow style `{a: 1, b}` is TWO keys, the second null",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L101",
   "scope": "component",
   "rule": "a `superseded-by` names a component major that exists and is not the part itself, and a kit's successor is a kit and a component's is not",
   "why": "A successor that dangles, points back at the part, or crosses between kit and component sends anyone following it to nothing, round a loop, or to something that cannot replace what it supersedes.",
   "fix": "fix the ref, or add the successor if it has not landed yet",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L102",
   "scope": "component, device",
   "rule": "a device's pluggable media, and a part's `rate` attr, each name a rate spec/schemas/pluggables.yaml actually carries; a part states its rung as `rate`, never as `media`",
   "why": "A media no pluggables family carries leaves its cage offering every optic of its shape with no rate limit, and a rate written as media offers the optic in every cage of its family, so a 10G cable appears in a 1G cage.",
   "fix": "fix the media/rate, move a rung from media to rate, or add the missing rate to the family in pluggables.yaml",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L103",
   "scope": "library",
   "rule": "a pluggable family's `interface` matches at least one component's `interface`",
   "why": "A pluggable family no component presents is vocabulary with no hardware behind it, so the registry and the library would drift apart unnoticed.",
   "fix": "model the cage, or leave the family as-is if the vocabulary needs it ahead of the metal (sfp-dd today)",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L104",
   "scope": "device",
   "rule": "a port's declared media and its cage's presented interface name the same pluggable family",
   "why": "A port whose declared media and drawn cage disagree would be offered optics of one family through an aperture shaped for another.",
   "fix": "the declared media governs the accept list render.py's cages[] builds - check the source and fix whichever of the drawing's aperture or the declared media is wrong",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L105",
   "scope": "component, device",
   "rule": "a placement's or part's `interfaces:` are held by a port the export files as a switch interface, named once in the view or component, and never the id of a placement, part, element or bay",
   "why": "A DCIM import would otherwise list one interface twice or give two real connectors the same name, and interfaces declared on a lamp, filler, console or timing jack are dropped from the export without a word.",
   "fix": "rename the colliding placement or interface - both are real and a DCIM needs a name for each - or move `interfaces:` onto the cage that presents them",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L106",
   "scope": "component",
   "rule": "`interface-at` names a declared connection point, and a connection point's `on:` names a `relief.features[]` node that carries an `out`, or a `cyl` whose far end (`lift + cyl`) is its rear; a numeric `seat-out` is a number at or above 0, never beside `on:`, and only on the presented point (`interface-at`, default `mate`)",
   "why": "A seat point that names nothing falls back silently, so a plug or boot is drawn standing at the wrong depth, often inside the part it wraps, and nothing reports it.",
   "fix": "fix the name, or give the feature the `out` (or `cyl`) a part seated on it stands off by; a point on the part's own face needs no `on:`; move a `seat-out` to the presented point; quote the key (`'on':`) - a bare `on` is YAML boolean true",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L107",
   "scope": "component, device",
   "rule": "no quoted run in a contract or manifest is longer than 25 words - a vendor's facts are transcribed, its prose is not reproduced",
   "why": "A vendor's facts are written down in the library's own words, so the drawings can be shared without reproducing anyone's text.",
   "fix": "paraphrase and cite the section (\"the ASR 9903 guide, Power Supply LEDs, says a flashing green lamp means...\"); a state table becomes `state = meaning` pairs, not a quotation",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L108",
   "scope": "component, device",
   "rule": "a stacked cage pair faces the library's way - an SFP/QSFP/QSFP-DD pair belly-to-belly, upper 0 over lower 180, or left 270 beside right 90 on a card drawn on its side, so both bails face outward; an OSFP pair the same way up, turned alike - 0 over 0, or 180 over 180 for a cage under the board, or both 90 or both 270 on its side - because a stacked OSFP cage is one connector and the OSFP MSA rev 5.22 draws both its modules heat sink up (section 7.1, Table 7-1, Figures 7-1 and 7-2)",
   "why": "A stack turned the other way seats its optics with their bails facing into the gap between the rows, where no thumb can reach them, and every rendering of the stack shows the wrong hardware.",
   "fix": "turn the pair; where a recorded reading says the stack is built otherwise, name the pair in `stack-exceptions:` with that reading as its `reason`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L109",
   "scope": "component",
   "rule": "a declared `optical.polarity` is what the paths actually wire - A straight, AF pair-flipped (and its rows exchanged at 24 fibres), universal - judged at the trunk connector's own width, and only at a width a held source draws (a warning otherwise)",
   "why": "A polarity label the fibre paths do not match tells someone patching a link the wrong pair order, which is how a link ends up with transmit facing transmit.",
   "fix": "fix the paths or the polarity; the paths are the evidence, `polarity` is only the claim. For a width no source draws, add it to POLARITY_WIDTHS with the figure that draws it",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L110",
   "scope": "component, device",
   "rule": "a port's `speed` is one of the closed set in spec/schemas/speeds.yaml - the highest native rate the port runs at, and nothing else",
   "why": "A speed spelled more than one way breaks a filter such as every 1G port, and leaves the DCIM export unable to type the port, so it exports nothing for it.",
   "fix": "spell the rate from the set (a 10/100/1000 jack is `1g`); media goes in `media`, a USB generation in `usb`, a PON flavour in `pon`, a caveat in the placement's `description`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L111",
   "scope": "library",
   "rule": "an alias names one box - no two devices claim the same `aliases[].name` (case-insensitive) unless every claimant marks it `shared: true`, and no alias repeats its own or another device's `model`",
   "why": "A model number looked up from a compatibility list could land on whichever of two drawings is read first, or mistake a nickname for a real model.",
   "fix": "drop or rename the alias; if an OEM name really maps to either of a pair, set `shared: true` on it in EVERY claimant and say why in its `note`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L112",
   "scope": "component",
   "rule": "a connector draws a node 1..N for each of its optical.positions, and a cassette's rear face reuses no front id",
   "why": "Every fibre a module's paths name has to be a node someone can point at, or the explorer and other tools cannot find it, and two connectors could end up sharing one address.",
   "fix": "compose a bore with the position's number as its id, or declare an element of class fibre; rename a clashing rear id",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L113",
   "scope": "device",
   "rule": "a device port whose effective media carries a network interface (a pluggable cage, or `rj45`) has a `speed` and a group with a `role` - warning at `modelled`, error at `verified`",
   "why": "A network port with no rate is missing from speed filters, and the DCIM export has to guess its type, which can file a 10G port as 25G.",
   "fix": "add the rate the source states, on the port or its group; a console, timing or alarm jack takes the media that says so (`rj45-serial`, `rj45-tod`, `rj48`) instead of a speed; where no document states a rate, leave it and record the search in `gaps:`",
   "severity": "at-verified",
   "fails": false,
   "warns": true,
   "fails-at-verified": true
  },
  {
   "code": "L114",
   "scope": "component",
   "rule": "a `default:` - on a `parts:` entry or at a component's top level - sits on a slot (a part presenting a pluggables family or a registered connector interface) and names a part that slot accepts",
   "why": "The shipped default is drawn in every configuration that does not override it, so a default on a part that is not a slot, or one the slot cannot accept, puts the wrong part in every drawing.",
   "fix": "name a ref the slot's `accepts` lists (components.json `cages`), or remove the `default:` from a part that presents no slot; `\"\"` ships a slot empty",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L115",
   "scope": "component, device",
   "rule": "a slot that SPANS others (an LC duplex adapter over its two bores) and the slots it spans are never both filled - by a configuration, or by what the parts ship",
   "why": "One duplex connector fills both bores, so filling the adapter and its bores at once describes hardware that cannot exist, and the build refuses to draw it.",
   "fix": "empty the level you do not want: an empty string on the bores to seat a duplex connector, or one on the adapter's own slot to seat a simplex part in a bore",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L116",
   "scope": "component",
   "rule": "a component presenting a spanning connector interface really hosts what it spans - the number of bores the registry says, at the standard's pitch, with its own `mate` at their midpoint, its bores at the depth that point presents, and the axis it derives putting a duplex connector's latches on its bores' keyway side - and a component MATING one is drawn on the canonical axis, the pair running across from its own `mate`",
   "why": "An adapter whose bores are off the standard pitch, at the wrong depth or the wrong way round would accept a duplex connector it cannot hold, seating it floating, sunk, or with its latches away from the keyway.",
   "fix": "place the bores at the interface pitch spec/schemas/standards.yaml records, put `mate` on their midpoint, and give each bore the `lift` the feature that point sits `on:` stands at - or drop the `interface:`, because an adapter off the pitch presents no duplex connector; compose the bores in the order whose derived axis carries the latch into the keyway, all at one `rotate`; draw a duplex connector itself with its pair ACROSS and its latches up, because the host's own axis arrives with the seat",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L117",
   "scope": "component",
   "rule": "a part `on` a facet names a relief feature that declares `facet`, whose node is a declared element, and its projected box lies within that element; a facet does not also declare `out`, `profile` or `profile-y`; a facet sunk below the plate (`lift < 0`) lies inside the box of a `pocket` element at least `-lift` deep",
   "why": "A tilted part needs a real slope to stand on: otherwise the 3D view floats it in the air, buries its wedge in a solid face, or takes the slope from two places that disagree.",
   "fix": "name the facet feature's node in `on`, declare the node in `elements`, move the part onto the facet, or drop the hand-written slope - the renderer derives it; for a sunk facet, declare the recess it stands in as a `pocket` around it, or deepen the pocket to the facet's lift",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L118",
   "scope": "device",
   "rule": "power is stated once - on the chassis where the box has one feed, and on a configuration only where it differs",
   "why": "Power written on both the chassis and its configurations gives two answers that can drift apart, and a reader cannot tell which one is meant.",
   "fix": "move it to `chassis.power`, or drop the configuration's copy",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L119",
   "scope": "device",
   "rule": "a device with supplies says what feeds each build - `power` on the chassis or on every orderable configuration",
   "why": "A device with supplies that does not say its feed cannot be filtered as AC or DC, so its builds can only be told apart by name.",
   "fix": "state `chassis.power` (one feed) or `power` on each configuration (`ac`, `dc`, `hvdc`) from the supplies it seats and the datasheet's input rows",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L120",
   "scope": "device",
   "rule": "a configuration's `power` agrees with the supplies it seats - `dc` over an `-ac` supply is a contradiction - warning at `modelled`, error at `verified`",
   "why": "A configuration that contradicts its own supplies, such as an AC inlet under a label that says -48 V, misleads anyone choosing or cabling the build.",
   "fix": "correct `power`, or seat the supply the build actually ships with",
   "severity": "at-verified",
   "fails": false,
   "warns": true,
   "fails-at-verified": true
  },
  {
   "code": "L121",
   "scope": "component",
   "rule": "a pluggable that conforms to a module envelope declares its `head:` - the box it occupies outside the cage - and the head fits the MSA's outside envelope, or lists each dimension it exceeds with a source; no relief feature of its own that starts inside the head stands past it (one lifted to the head's rear or beyond is the cable's, not the head's), and the head's node draws it",
   "why": "A pluggable whose part outside the cage is unchecked can be drawn bigger or smaller than the real module, with a pull tab standing anywhere, and nobody can tell whether the size is real.",
   "fix": "add `head:` from the part's drawing, list a real overhang under `head.exceeds` with the document that shows it, drop a waiver that no longer applies, or shorten the feature that stands past the head",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L122",
   "scope": "component, device",
   "rule": "a `cable-od` value is a diameter in millimetres from 2 to 15 - on a field's default, a composing part's attrs, and a device placement's attrs - written as plain ASCII digits and a point, the only number the build and the kit draw",
   "why": "A wrong unit or a typo in a cable's diameter draws a cable stub as big as a fan, in the build and in the kit.",
   "fix": "give the cable's outside diameter in mm as a number, from the product's own document",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L123",
   "scope": "library",
   "rule": "one module, one bay size - every bay that accepts a module, in any device or carrier, reserves the same size for it, to within a millimetre",
   "why": "A module is the same metal in every chassis, so two bays reserving different sizes for it show the card not fitting its slot in one of them.",
   "fix": "reserve one figure everywhere - the module's own `insert` or `size`; a difference that is real stays in the baseline, with the reason in the provenance of the chassis that reserves more (the warning is filed on the module, so a chassis `lint.waive` cannot clear it)",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L124",
   "scope": "library",
   "rule": "under one NOS vendor, no two listings export the same DCIM model, and no alias is claimed by two listings unless each marks it `shared`",
   "why": "Two listings exporting the same DCIM model would write one device type file twice, which stops the export, and a shared name sends a lookup to an arbitrary box.",
   "fix": "give one listing a configuration `model` or its own SKU; drop the duplicate alias, or mark it `shared: true` in every claimant with a `note`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L125",
   "scope": "device",
   "rule": "a device says how it is installed - a rack device (the default `mount`), a `rack-face` part or a `rack-side` part states `ru` (warning), and a device whose `chassis.mount` is `din-rail`, `wall` or `desktop` states none (error); `chassis.full-depth`, `chassis.overhang`, `chassis.ears` and `chassis.kits` appear only on a rack device (error)",
   "why": "Without a stated mount, a wall-mounted or desktop box exports as a 1U rack device, and someone planning a rack makes room for equipment that never goes in it.",
   "fix": "give a rack device its `ru` from the datasheet; for a box that is not racked, state `chassis.mount` and drop `ru`, so its DCIM export says `u_height: 0` rather than an invented rack unit",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L126",
   "scope": "device",
   "rule": "a bevelled chassis is a solid the box can have - every edge named by two faces that meet, none bevelled twice, no face cut away and no bevel swallowed by its neighbours - its face drawings are the chassis's own size, and every part, bay and cutout on a face lies on the flat face rather than on a bevel",
   "why": "A bevel that is not a real edge, or that eats a face, makes an impossible solid, and a port left where a bevel cuts is drawn on an angled strip where no port can be fitted.",
   "fix": "name edges as two adjacent faces (`front-left`), shrink a bevel that cuts too much, drop a view `size` that differs from the chassis on a bevelled face, or move the part onto the flat face - spec/tools/portrayal/bevel.py says where it is",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L127",
   "scope": "device",
   "rule": "a `shell: sheet` body states `chassis.thickness`, between 0 and 10 mm, and a box states none (error)",
   "why": "A sheet body with no gauge describes only half of the metal, and a thickness on a solid box states a fact that describes nothing.",
   "fix": "give a sheet body the gauge its datasheet states; on a box, drop `thickness`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L128",
   "scope": "device, listing",
   "rule": "a part-number key has no stray whitespace - none leading or trailing, none but the plain ASCII space (an error), and none splitting a run of capitals and digits between two hyphens (`-A C-`, a warning)",
   "why": "A part number is the DCIM model, its slug and the export file name, so one stray space exports the build under a model nobody can order, and can change which name the device type is exported under.",
   "fix": "retype the SKU as the vendor prints it; a space the vendor really prints inside a hyphenated token is waived with the document that shows it",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L129",
   "scope": "component",
   "rule": "`optical.trunk` is for a single-faced module - not one whose rear face carries fibre - and a position it names by number is not also declared `unused`",
   "why": "Saying where the trunk is in two ways, or listing a dead position as part of it, gives the fibre export two conflicting answers about where the common end is.",
   "fix": "drop `trunk` where the rear face already is the trunk; name a part bare when it carries a dead position, or route the position",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L130",
   "scope": "component",
   "rule": "every leg of a module whose glass is projected runs between the front and the trunk (a rear-face connector or an `optical.trunk` position)",
   "why": "A fibre leg that does not run between the front and the trunk has no row in the fibre map, so the export would drop it without a word.",
   "fix": "fix the path, or the trunk; a front-to-front or trunk-to-trunk leg has no row in the fibre map and would be dropped",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L131",
   "scope": "component",
   "rule": "a module with `optical.paths` has a trunk - a rear face carrying its common end, or `optical.trunk` (error)",
   "why": "Without a trunk the export has nowhere to put the common end, so it drops the module's whole fibre map and no DCIM sees how the glass is wired.",
   "fix": "add `optical.trunk` naming the common, network-side positions, from the vendor's own port roles, and say in provenance where they were read",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L132",
   "scope": "device",
   "rule": "a placement's `fed-by` names a placement on this device, in any view, whose part exports a power port (`dcim_export.PART_POWER`), and it stands on a part that exports a power outlet (`dcim_export.PART_OUTLET`) - an error, because both DCIMs refuse an outlet whose `power_port` names nothing",
   "why": "Both NetBox and Nautobot refuse an outlet whose power port names nothing, so a broken feed reference fails the device's import.",
   "fix": "name the input this output hands on, by its placement id; drop a `fed-by` on a part that is not an outlet",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L133",
   "scope": "device",
   "rule": "a placement's `through` names a bay on this device, in any view - the breaker or fuse position the circuit runs through - or a placement of a part of class `breaker`, a breaker fixed to the unit (an error)",
   "why": "An outlet's breaker or fuse reference that points at nothing leaves nobody able to tell which position protects the circuit.",
   "fix": "name the bay or the breaker placement by its id, as the face spells it",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L134",
   "scope": "device",
   "rule": "every placement of a part in `dcim_export.PART_OUTLET` states `fed-by` - a warning at `draft` and `modelled`, an error at `verified`: an outlet with no feed imports, and names no power port",
   "why": "An outlet with no feed still imports but names no power port, so someone tracing power in the DCIM cannot see which input supplies it.",
   "fix": "state `fed-by: <input id>` on each output, read from the panel's own wiring or datasheet",
   "severity": "at-verified",
   "fails": false,
   "warns": true,
   "fails-at-verified": true
  },
  {
   "code": "L135",
   "scope": "device",
   "rule": "one position, one circuit - no two placements name the same `through` bay (a warning); a fixed breaker placement feeds many outlets by design and is not counted",
   "why": "Two outlets claiming one breaker position usually means one of them names the wrong position, which misleads anyone tracing which breaker cuts which circuit.",
   "fix": "correct the `through` that names the wrong position; if two outputs really are paralleled behind one breaker, waive with the document that says so",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L136",
   "scope": "device",
   "rule": "a declared pass-through (`passes:`) lies inside its face and overlaps no component - except a well that holds it whole, the plate it is cut through - and no two in a view share an id",
   "why": "A cable cannot pass through a port or a ring, so a pass-through that sits off its face or over a part would send cable routing through solid hardware.",
   "fix": "move the pass-through off the part, or onto the face; a window punched in a part's floor is declared over that well",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L137",
   "scope": "device",
   "rule": "a pass-through whose `cover` is `brush` has a `pattern: brush` decor drawn over the whole of it, and a brush drawn over a pass-through belongs to one whose cover is `brush`",
   "why": "The picture and the data have to agree: a pass-through declared as brushed shows a brush, and a brush drawn on the face really is a pass-through's cover.",
   "fix": "draw the brush over the opening, or change `cover` to say what the picture shows",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L138",
   "scope": "component, device",
   "rule": "a guide fits what declares it - a ring's opening inside the part, seen along its run (its size, and its relief or `size.d` out of the face), and a duct inside its view, with a finger gap less than the finger pitch",
   "why": "Cable routing reads a guide's opening, so an opening bigger than its loop or a duct off its face would route cables through space that does not exist, and fingers with no width describe a duct that cannot be built.",
   "fix": "measure the clear opening, not the outside of the loop; give the part the relief that holds the opening; move the duct onto its face, or re-read the pitch and the gap off the drawing",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L139",
   "scope": "lab",
   "rule": "every placement's `ref` is a library device (and its `cfg` one of that device's configurations), every placement id is unique, and every `on` names another placement in the lab (error)",
   "why": "A lab that names a device or configuration the library does not have, reuses an id, or hangs a part on a placement that is not there cannot be resolved into a rack, so it cannot be drawn or published at all.",
   "fix": "name the device by its `name`, e.g. `fhd-1ufce`; give each placement its own id; point `on` at the id of the placement the part sits on",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L140",
   "scope": "lab",
   "rule": "`on` and `unit` appear only on a device whose `chassis.mount` is `rack-face`, and `face` only on a `rack-face` or `rack-side` part; a rack-face device is placed by `on` or by `ru`, not both, and a rack device by `ru` (error)",
   "why": "A rack-face part with no host and no rack unit, or a rack device with no rack unit, has no position to draw, and one given both a host and a rack unit, or host keys on the wrong kind of mount, could be drawn in either place.",
   "fix": "drop the key from a rack device; give a rack-face part either `on` (and `unit`) or `ru`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L141",
   "scope": "lab",
   "rule": "a rack-face part's host is a `rack` device, and `unit` is within the host's height, 1 to its `chassis.ru` (error)",
   "why": "A cable manager or lacer bar hung on something that is not a rack device, or on a unit its host does not have, would be drawn floating where nothing holds it.",
   "fix": "put the part `on` the rack device behind it; count `unit` from 1 at the host's bottom unit",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L142",
   "scope": "lab",
   "rule": "every placement fits inside the rack's `height-ru`, no two rack devices share a rack unit, and no two rack-face parts claim one rack unit on one face and side - a part narrower than the rack opening placed at a `side` claims that side, any other claims both (error)",
   "why": "Two pieces of equipment drawn in one rack unit, or a device past the top of the rack, would show someone building the rack a layout that cannot be built.",
   "fix": "move one of the two, or put one rack-face part on the other face",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L143",
   "scope": "lab",
   "rule": "a rack-face part placed by `ru` over a rack device is reported with that host (warning)",
   "why": "A rack-face part pinned to a rack unit rather than to the device behind it stays put when that device moves, and ends up over the wrong equipment.",
   "fix": "place it `on` the host with its `unit` so it moves with the host, or leave it by `ru` if it belongs to the rack rather than the device",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L144",
   "scope": "device",
   "rule": "members of one group that one configuration draws on one face hold one `rel-pos` each; alternatives (variant views, `only-in` builds) may share one (warning)",
   "why": "Two members of a group at one position leave its numbering ambiguous, so the tree and an ENTITY-MIB walk cannot tell which member comes first.",
   "fix": "give each member its own position, or move the unlike members - ESD jacks among earthing studs, lane lamps among port lamps - to a group of their own",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L145",
   "scope": "device",
   "rule": "a group is not named only for the class of its members - `ports` names no port family (warning)",
   "why": "A group named only `ports` says nothing about which port family it holds, so a reader cannot tell what kind of ports are in it.",
   "fix": "name the group for the family it holds (`sfp28`, `rj45-1g`), or a mixed block for the job it does and say so in `mixed:`",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L146",
   "scope": "device",
   "rule": "an occupant's `turn` is one its host allows - the host's interface `turns` in connectors.yaml, narrowed by its presented point's own (an error; the build refuses it too)",
   "why": "A plug or lug seated at a turn its socket does not allow would be drawn in an orientation the hardware cannot take, and the build refuses to seat it.",
   "fix": "choose one of the listed turns, or drop `turn:` to take the default the build computes; a barrier block's terminal screw allows 0 alone",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L147",
   "scope": "component",
   "rule": "a connection point's `turns` is a subset of the turns its part's interface allows in connectors.yaml, and only the presented point states one (an error)",
   "why": "A connection point cannot allow a turn its interface does not, since no mating part is drawn for that turn, and `turns` on a point nothing reads would look like a setting that works when it does nothing.",
   "fix": "list only turns the interface allows - a point narrows the list, it cannot widen it; move `turns` to the point the interface is presented at, or drop it",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L148",
   "scope": "component",
   "rule": "a node a field moves or shows names a `choice` field the contract declares, and every option its `data-move` or `data-show` lists is one of that field's options; every option of a field with SHOW nodes shows at least one node, or is listed in the field's `drawn-by-absence` (an error)",
   "why": "A switch or selector position drawn for an option nobody can set, or an option with nothing drawn for it, would look correct while the drawing never changes when that option is chosen.",
   "fix": "declare the field as a choice, or name only its options in the table; spell a move `option: dx dy [deg]`; show a node for the option, or list it in `drawn-by-absence`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L149",
   "scope": "component",
   "rule": "a node a position moves stays inside its part under every move: its box, translated and turned, lies within `size` (an error)",
   "why": "An actuator moved off its own part would be drawn on the chassis beside it, and extruded there in the 3D view.",
   "fix": "shorten the move, or move the node in the skin so its travel stays on the part",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L150",
   "scope": "device",
   "rule": "a placement, bay or cutout whose box lies outside its view's face (beyond 0.5 mm) is covered by that side's `chassis.overhang` - across the width only, the rear and underside mirrored; one beyond the face in height or along a side view is always reported. `optional` placements are exempt, and decor is not checked, since it is clipped and never drawn outside the face (error)",
   "why": "A part drawn outside the device's face with no stated overhang reads as a stray coordinate, so the drawing and the rack builder would show hardware sticking out with no source for its reach.",
   "fix": "state `chassis.overhang: {left, right}` with the reach and its source, or move the part onto the face",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L151",
   "scope": "device",
   "rule": "a side of `chassis.overhang` is reached by some part to within 0.5 mm (warning)",
   "why": "An overhang figure that no part reaches is stale or overstated, so the device would claim more room beside the rack than it uses.",
   "fix": "lower the figure to what the parts reach, or drop it when nothing reaches past the face",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L152",
   "scope": "device",
   "rule": "a `rack-side` part's front view is taller than it is wide - it is drawn as it stands beside the rack (warning)",
   "why": "A vertical cable manager drawn landscape has its width and height swapped, so it would be drawn lying down beside the rack instead of standing.",
   "fix": "draw it standing: the front's `w` is the width across the rack's face direction and `h` the height it runs; swap them if the spec line printed them the other way",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L153",
   "scope": "lab",
   "rule": "`side` appears only on a `rack-side` part, which states it as an attachment point (`left`, `right`, `left-front`, `left-rear`, `right-front`, `right-rear`), and on a `rack-face` part narrower than the rack opening, as `left` or `right`; a rack-side part takes no `on` or `unit` (error)",
   "why": "A side position on a part that does not attach at the side, or a rack-side part given a host, has no meaning in the rack, so the part could not be placed where it really goes.",
   "fix": "give a rack-side part its `side` and place it by `ru`; drop `side` from a full-width part; a rack-face part's side is a rail, left or right",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L154",
   "scope": "lab",
   "rule": "a rack-side part fits the rack's `height-ru`; no two rack-side parts at one attachment point overlap in height; and one side of the rack does not mix the two-post name (`left`) with a four-post name (`left-front`, `left-rear`) (error)",
   "why": "Two vertical managers drawn in one place beside the rack, or one taller than the rack, would be a layout nobody can build, and mixing two-post and four-post names on one side describes two different racks, so an overlap cannot be judged.",
   "fix": "move one of the two up, or stand it at another attachment point; name every part on a side with the same rack's points",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L155",
   "scope": "kit",
   "rule": "every part `ref` of a `kind: kit` resolves to a component in the library that is not itself a kit, and no two parts share an `id` (error)",
   "why": "A kit part that points at nothing has no geometry to draw, and two parts under one id leave a configuration that names that id ambiguous.",
   "fix": "fix the ref (namespace/name@major) or write the part's contract; a kit lists ordinary rails, brackets and ears, never another kit",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L156",
   "scope": "kit",
   "rule": "every configuration of a kit has its own `id`, and names in `parts` only ids of the kit's own `parts` (error)",
   "why": "A kit configuration that names parts the kit does not have, or shares an id with another, cannot be assembled, and a device's depth override that names it could point at the wrong one.",
   "fix": "list the part ids the configuration uses, as the kit's `parts` spell them; give each configuration an id of its own",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L157",
   "scope": "kit",
   "rule": "every depth range of a kit configuration, one `[min, max]` or one per hole type, has min below max (error)",
   "why": "A depth range whose minimum is not below its maximum fits no rack, so a person building a rack would be told the kit fits a depth it cannot.",
   "fix": "write the range as `[min, max]` in mm, from the source; a single figure is a `preset`, not a range",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L158",
   "scope": "kit",
   "rule": "`travel` appears only on a kit whose `motion` is `sliding` (error)",
   "why": "Travel on fixed rails would claim the equipment slides out for service when it does not.",
   "fix": "drop `travel`, or set `motion: sliding` if the rails really slide out for service",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L159",
   "scope": "kit",
   "rule": "every accessory `ref` of a kit resolves to a component in the library that is not a kit (error)",
   "why": "An accessory ref that points at nothing, or at another kit, leaves a cable arm or bar the kit promises and cannot draw.",
   "fix": "fix the ref (namespace/name@major), or write the arm's or the bar's contract",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L160",
   "scope": "device",
   "rule": "at most one of a device's `chassis.ears.positions` is the `default` (error)",
   "why": "A device ships in one ear position and the drawing sets the ears at the default, taking the first one it finds, so a second default is silently ignored.",
   "fix": "keep `default: true` on the position the device ships in, from the installation guide, and drop it from the rest",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L161",
   "scope": "device",
   "rule": "every `chassis.kits[].ref` resolves to a `kind: kit` in the library, and no kit is listed twice (error)",
   "why": "A mounting kit that points at nothing, or at a part that is not a kit, cannot be offered, and a kit listed twice makes an ear position that names it ambiguous.",
   "fix": "fix the ref (namespace/name@major), or write the kit's contract; a component that is not a kit is placed, not listed here",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L162",
   "scope": "device",
   "rule": "an ear position's `part: {kit, part}` names a kit the device lists under `chassis.kits` and the `id` of one of that kit's parts (error)",
   "why": "An ear position whose part names a kit the device does not list, or a part the kit does not have, points at nothing, so the rack builder could not show the ear it describes.",
   "fix": "list the kit under `chassis.kits`, or name the part by the id the kit's `parts` give it",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L163",
   "scope": "device",
   "rule": "a `chassis.kits[].depth` override names a configuration `id` of that kit, and its `range` has the configuration's shape - one `[min, max]`, or the same hole types - with min below max (error)",
   "why": "A depth override replaces its kit configuration's depth whole, so one that names no configuration, has a different shape or an impossible range would tell someone building a rack the wrong depths.",
   "fix": "name a configuration the kit has, and write the range as the kit writes that configuration's `depth`",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L164",
   "scope": "device",
   "rule": "the span `chassis.ears` states fits the chassis: `y + h` is not above its top (warning)",
   "why": "Ears are drawn from this span, so a figure past the top of the chassis draws an ear hanging off it.",
   "fix": "measure the ears again against the chassis height; leave `h` and `y` out when the ears span the whole chassis, which is what is drawn without them",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L165",
   "scope": "device",
   "rule": "no two of a device's `chassis.ears.positions` are the same position - the same `name` with the same `label`, or no label on either (warning)",
   "why": "Two identical ear positions are one position written twice, and anything offering the positions would offer it twice.",
   "fix": "give each a `label` in the vendor's own words (\"chassis flush\", \"transponder flush\"), or drop the duplicate",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L166",
   "scope": "device",
   "rule": "a rack PDU states `attrs.management.metering-scope` and `outlet-switching` together (error); with `outlet-switching: true` every power outlet declares the `[on, off]` states (warning), and without it none declares any (error)",
   "why": "A PDU's class is derived from its metering and switching together, so stating only one publishes no class at all, and on/off states on an unswitched PDU offer a switch the hardware does not have.",
   "fix": "state both keys, from the vendor's topology table; declare `states: [on, off]` on the outlets group of a switched PDU, and none on an unswitched one",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L167",
   "scope": "device",
   "rule": "a rack PDU's `attrs.power.input-plug` is the `dcim_export.PART_POWER` slug of the input its outlets are `fed-by`, and `input-wiring` is stated exactly when `input-phase` is `three` (error)",
   "why": "An input plug that differs from the power port the outlets are fed by gives the device two answers for its plug, and a three-phase input without its wye or delta wiring leaves each outlet's feed leg unknown.",
   "fix": "write the plug as the slug the input part exports, with the cord in `input-cord` and the provenance; state `wye` or `delta` on a three-phase input only",
   "severity": "error",
   "fails": true,
   "warns": false,
   "fails-at-verified": false
  },
  {
   "code": "L168",
   "scope": "device",
   "rule": "a device of the `power` profile that states `input-voltage-v` does not also state `input-voltage` (warning)",
   "why": "Stating the voltage in two keys writes one fact twice, and the two copies can disagree.",
   "fix": "move the voltage prose into `input-ac` and keep the number in `input-voltage-v`",
   "severity": "warning",
   "fails": false,
   "warns": true,
   "fails-at-verified": false
  },
  {
   "code": "L169",
   "scope": "device",
   "rule": "`lines` stands on a placement of class `breaker` or on a power outlet (error), and on a three-phase input every outlet's lines resolve, on itself or on the breaker it runs `through` (warning)",
   "why": "Lines on a part that protects no circuit say nothing true, and on a three-phase PDU an outlet with no lines exports no feed leg to the DCIM.",
   "fix": "state `lines` once, on the breaker that protects the circuit, and `through: <breaker>` on each outlet it feeds",
   "severity": "mixed",
   "fails": true,
   "warns": true,
   "fails-at-verified": false
  }
 ],
 "retired": []
}
