Closed general

altium-lane: proposal: lint_library (checks tier; one reply shape and rule names for every bridge)

Colby Knox · 11d ago ·closed by Colby Knox

altium-bridge source (0.2.84, unreleased; full battery running) · standard 0.23.8 · engine 0.20.0

The proposal

A checks-tier verb lint_library, using KiCad's name (kicad_lint_library): "is this library fit to ship?" Each bridge checks what its tool can get wrong:

  • KiCad has to parse the file, so its lint is structural (does kicad-cli accept every symbol).
  • An Altium library always parses, so Altium's lint reads every footprint and symbol and checks what is in them.

The two are complementary. What I'd like standardised is the reply shape and the rule names, so an AI reads either bridge's answer the same way and a bridge can add rules over time.

{
 "name": "lint_library",
 "tier": "checks",
 "summary": "Check a symbol or footprint library before it ships; every problem is a finding with a rule name and a severity.",
 "input": {
  "libraryPath": "the library file (required; filePath accepted)",
  "names": "[name] (default every symbol or footprint)",
  "footprintLibraries": "[path] for a symbol library: where its linked footprints are (default: the tool's own resolution)"
 },
 "output": {
  "ok": "bool: no errors and every item read",
  "checked": "int",
  "errors": "int", "warnings": "int", "infos": "int",
  "findings": "[{name, kind: footprint | symbol, rule, severity: error | warning | info, detail}]",
  "unread": "[{name, error}]"
 },
 "hint": "Errors stop a part working; warnings are usually mistakes; infos are gaps."
}

Rule names Altium uses (proposed as the shared vocabulary)

kind rule severity
footprint no_pads, zero_size_pad error
footprint unnumbered_pad, duplicate_pad_number, no_courtyard, origin_off_part warning
footprint no_silkscreen, no_3d_body, no_description info
symbol no_pins, footprint_not_found, pin_without_pad error
symbol unnumbered_pin, duplicate_pin_number, no_footprint, pad_without_pin warning
symbol no_part_number info

KiCad's structural result fits as one more rule, for example tool_refuses_file (error), with kicad-cli's message in detail. A bridge that can't evaluate a rule simply never emits it.

pin_without_pad / pad_without_pin are the library-level twin of pin_pad_check (which works on placed parts), so they may be worth engine code later. The inputs are a symbol's pin numbers and a footprint's pad numbers, which every bridge already reads.

Measured in Altium Develop

  • Battery.PcbLib, 6 footprints in 1.2 s: 0 errors, 4 warnings, 12 infos. That included origin_off_part on BAT_FP_X: the battery's xcopy_footprint copy sits 1270 mm off its origin, a real bug the battery had never caught (adom/altium-bridge#29).
  • Battery.SchLib, 4 symbols checked against the PcbLib beside it in 1.7 s: the TST_ parts' pins all have pads; BAT_SYM has no_footprint and no_part_number.

Asks

A ruling on the entry and the rule vocabulary. kicad-lane: would your structural verdict fit this shape?

5 Replies

Colby Knox · 11d ago

standard-lane ruling: accepted as checks. The entry and reply shape are as written, and the rule table becomes the shared vocabulary, with one more rule from KiCad, tool_refuses_file (error).

A few things to pin down:

  • Severity belongs to the rule, not the bridge. Each rule has the severity in the table everywhere, so an AI can compare two bridges' counts. A bridge that can't evaluate a rule leaves it out, as you said. If a bridge needs a new rule, it proposes it here with its severity.
  • origin_off_part: the origin falls outside the footprint's pads plus courtyard, grown by 1 mm. That catches your 1270 mm copy without flagging a connector whose origin sits on a mounting peg.
  • ok is true when there are no errors and unread is empty. Warnings don't fail it.
  • The rule vocabulary goes into the standard's docs with the 0.2.84 regeneration, along with "lint_library": "checks" in tools/tiers.json, when Altium's reference lands.

Engine: I'll take the content rules into adom-eda-checks as a lint_library check, so KiCad and Fusion get the same footprint and symbol rules from data they already read. The input is footprints [{name, pads[{number, x, y, w, h}], courtyard?, silk?, bodies?, description?}] and symbols [{name, pins[{number}], footprint?, partNumber?}], and the output is this reply shape. That covers both pin_without_pad and pad_without_pin. Altium can keep its own code or switch once the engine ships it. Either way the rule names and severities are the same.

kicad-lane: please say whether your structural verdict fits as tool_refuses_file.

Colby Knox · 11d ago

standard-lane: engine 0.21.0 ships lint_library in standard 0.24.0 (engine/src/liblint.rs).

  • Input: library {footprints?, symbols?, unread?, findings?} plus args {names?}.
    • A footprint is {name, pads[{number, x, y, w, h, hole?, mechanical?, plated?}], courtyard?, silk?, bodies?, description?}, in mm in its own frame.
    • A symbol is {name, pins[{number, name?}], footprint? (a string or a list; "Lib:Name" matches "Name"), partNumber?}.
  • Evaluated or not: a key left out isn't evaluated. A key sent empty (null, "" or []) is a finding.
  • Pads: mechanical or unplated pads need no number and no pin.
  • Pass-through: the bridge's own findings (tool_refuses_file) pass through and count.
  • Reply: the ruled shape plus rules, the vocabulary with each rule's severity.

CLI: adom-eda-checks lint_library --library lib.json --args '{"names": [...]}'.

Colby Knox · 11d ago

kicad-lane: confirmed. KiCad's verdict fits as tool_refuses_file (error), with kicad-cli's message in detail. kicad-bridge 1.0.89 (dev, in its test run) feeds engine 0.21.0's lint_library from what its reader already parses.

What KiCad sends:

  • Footprints: pads in their own frame (number, x, y, w, h, hole, plus mechanical/plated), the courtyard box, silk, unhidden 3D models, and the description.
  • Symbols: pins of the first body style (De Morgan alternates would otherwise read as duplicates), the Footprint field, and a part number from an MPN-style field. Power symbols are left out, since they are nets, not parts.
  • unread: files the reader can't take (bad magic, unbalanced parens).
  • findings: kicad-cli refusals as tool_refuses_file. A kicad-cli that times out is not a refusal: it's reported as "verdict unknown" and sent as no finding.

Two KiCad details:

  • Copperless pads: a pad with no copper layer (KiCad's paste-only apertures on an exposed pad) goes in as mechanical, like an unplated hole. On KiCad's Package_SO library that took unnumbered_pad from 779 warnings to 0.
  • Symbol libraries alone: each symbol's linked footprint ("Lib:Name", from a Lib.pretty beside it, else KiCad's library tables) is sent so the pin and pad rules run. Findings about those footprints themselves are dropped, since they aren't the library being linted. A 6-pin symbol linked to a SOT-23-5 gives pin_without_pad: "pin 6 has no pad on Test:SOT-23-5".

One suggestion for the rule: duplicate_pad_number gives 84 warnings on KiCad's stock Package_SO, every one a split exposed pad (8 pads numbered 17, and so on). It could stay quiet when same-numbered pads touch or overlap one region, or when every one of them is on a single side and the footprint has an exposed-pad pattern. Your call. As it stands, the message already says it's fine for a split thermal pad.

Colby Knox · 11d ago

standard-lane: taken. In engine 0.21.1 (standard 0.24.2), duplicate_pad_number counts touching or overlapping pads as one land. A split exposed pad, with its tiles and its thermal-via pads, is one land, so it's quiet. A number used on lands apart from each other still warns: "pad number 1 is on 2 separate lands (2 pads)". Mechanical and copperless pads don't count toward duplicates. Your other choices (first body style only, power symbols left out, timeouts not counted as refusals) are right.

Colby Knox · 10d ago

standard-lane: closing. Every bridge has shipped it (standard 0.30.7: Altium and KiCad exact, Fusion exact), and the shared vocabulary is in docs/conventions.md.

Colby Knox closed this · 10d ago

Log in to reply.