12. Reconcile with the tools you already run
Bring your existing DRC or ERC report into the same model, and see where the two tools agree, differ, and cannot see each other's work.
You already run a design-rule check. Your CAD tool ships one, you have tuned it, and it gates your release. The question to ask of anything new is “what does it add to what I already have, and where do the two disagree”.
You could answer it by reading two reports side by side, but that does not scale and nobody does it twice. So bring the other tool’s report into the same model and ask directly.
Import the other tool’s report ¶
Run your existing check and keep the JSON. The project keeps KiCad’s own report for this board in
reports/kicad-drc.json, so you can follow along without KiCad installed. It came from:
kicad-cli pcb drc --format json -o kicad-drc.json designs/jetson/jetson-agx-thor-baseboard.kicad_pcb
KiCad 10.0.6 found 578 violations. Import them:
$ agni import-results reports/kicad-drc.json --design designs/jetson -o kicad.results.json
kicad-cli pcb drc 10.0.6 — 957 finding(s) from designs/jetson
attached to an entity: 946 of 957
1 not attached — an entity the description names but the loaded design does not contain
e.g. Footprint REF**
10 not attached — board outline geometry, which belongs to no component or net
e.g. Segment on Edge.Cuts
This document carries no coverage axis: a vendor report lists violations and says
nothing about what it did not check, so its silence must not be read as a pass.
Read the summary slowly. In it the import tells you how far to trust what follows.
946 of 957 attached to an entity. A vendor report names things in prose, so importing it means resolving each name to an entity in your design. “Track [/CSI/CAM0.CSI2_CLK+] on In2.Cu”, or a curved one written “Track (arc) […]”, resolves to your design’s net of that name. “NPTH pad of J12” is an unplated hole with no pin or net, and it resolves to its part. The resolution works only because agni names a KiCad schematic’s nets exactly as KiCad does, including the sheet path on a bus member drawn on a sub-sheet. There are more findings than violations because a clearance violation names two items, and each becomes a finding.
The rest are named, with a reason. Ten are board outline geometry, which belongs to no component
or net. One names a footprint, REF**, that is on the board and in no schematic. Nothing is
dropped quietly. That matters, because a silently discarded finding is worse than one that was never
imported.
The document carries no coverage axis. This is the same idea as rung 9, applied to somebody else’s tool. A vendor report is a flat list of violations. It does not say which checks ran, so it cannot distinguish “checked and fine” from “never checked”. The import records that limitation rather than papering over it, and every reader of the document inherits the caveat.
Compare the two runs ¶
Now produce your own run over the same design and compare them:
$ agni check designs/jetson --results-out agni.results.json > /dev/null
$ agni results agni.results.json --compare kicad.results.json
comparing:
ours: agni <version> — 87 finding(s) over mount://jetson/designs/jetson
theirs: kicad-cli pcb drc 10.0.6 — 957 finding(s) over designs/jetson [no coverage axis: its silence is not a pass]
entities flagged:
both 1
ours only 85
theirs only 259
ours only:
net /CSI/CSIA_3V3
net /CSI/CSIA_5V
net /CSI/CSIA_I2C_VCC
net /CSI/CSIB_3V3
net /CSI/CSIB_5V
net /CSI/CSIB_I2C_VCC
net /CSI/I2C_MUX_SCL
net /CSI/I2C_MUX_SDA
net /CSI/I2C_{CAM}.SCL
net /CSI/I2C_{CAM}.SDA
net /CSI/MUX_I2C_4_SCL
net /CSI/MUX_I2C_4_SDA
net /CSI/MUX_I2C_5_SCL
net /CSI/MUX_I2C_5_SDA
net /CSI/MUX_I2C_6_SCL
net /CSI/MUX_I2C_6_SDA
net /CSI/MUX_I2C_7_SCL
net /CSI/MUX_I2C_7_SDA
net /DCDC/12V_OUT
net /DCDC/12V_VDD
net /DCDC/16V_OUT
net /DCDC/16V_VDD
net /DCDC/1V15_OUT
net /DCDC/1V8_OUT
net /DCDC/20V_OUT
net /DCDC/20V_VDD
net /DCDC/3V3_OUT
net /DCDC/3V3_VDD
net /DCDC/5V_OUT
net /DCDC/5V_VDD
net /DCDC/5V_{AON}_OUT
net /DCDC/5V_{AON}_VDD
net /DCDC/VIN_PWR_ON
net /Expansion connector/+12V_FMC
net /Expansion connector/+3V3_AUX
net /Expansion connector/+3V3_FMC
net /Expansion connector/+5V_FMC
net /Expansion connector/+VCC_FMC
net /Expansion connector/+V_{ADJ}
net /Expansion connector/I2C7.SCL
net /Expansion connector/I2C7.SDA
net /Expansion connector/I2C8.SCL
net /Expansion connector/I2C8.SDA
net /I2C_{SYS}.SCL
net /I2C_{SYS}.SDA
net /Peripherals/FAN_VDD
net /Power/3V3_LDO
net /SFP/SFI_CONN_RX_N
net /SFP/SFI_CONN_RX_P
net /SFP/SFI_CONN_TX_N
net /SFP/SFI_CONN_TX_P
net /SFP/SH
net /SoM_IO/I2C0_SCL_1V8
net /SoM_IO/I2C0_SDA_1V8
net /SoM_IO/I2C1_SCL_1V8
net /SoM_IO/I2C1_SDA_1V8
net /SoM_IO/I2C2_SCL_1V8
net /SoM_IO/I2C2_SDA_1V8
net /SoM_IO/I2C3_SCL_1V8
net /SoM_IO/I2C3_SDA_1V8
net /SoM_IO/I2C5_SCL_1V8
net /SoM_IO/I2C5_SDA_1V8
net /SoM_IO2/TC_VCC
net /USB DP Alt mode/USBC1_DPEQ0
net /USB DP Alt mode/USBC1_EQ0
net /USB DP Alt mode/USBC1_SSEQ0
net /USB Debug, PD/DEBUG_SCL
net /USB Debug, PD/DEBUG_SDA
net /USB Debug, PD/FTDI_3V3
net /USB Debug, PD/PDC_I2C1_IRQn
net /USB Debug, PD/PDC_I2C2_IRQn
net /USB Debug, PD/PDC_I2C3_SCL
net /USB Debug, PD/PDC_I2C3_SDA
net /USB Debug, PD/PDC_LDO_1V8
net /USB Debug, PD/PDC_LDO_3V3
net FLASH_PWR
net Net-(D1-C)
net Net-(J12-RS0)
net Net-(J12-RS1)
net Net-(J12-RX_{LOS})
net Net-(J12-TX_{DISABLE})
net Net-(J12-TX_{FAULT})
net VCC_IN
net unconnected-(J18-PadB24)
net unconnected-(J18-PadB25)
theirs only:
component C102
component C107
component C111
component C117
component C121
component C127
component C130
component C131
component C132
component C138
component C139
component C142
component C144
component C145
component C156
component C194
component C195
component C196
component C197
component C202
component C234
component C236
component C242
component C243
component C245
component C246
component C247
component C249
component C251
component C252
component C253
component C255
component C257
component C26
component C260
component C268
component C269
component C270
component C271
component C273
component C274
component C276
component C280
component C286
component C287
component C293
component C295
component C298
component C299
component C300
component C301
component C302
component C305
component C307
component C309
component C310
component C311
component C314
component C318
component C335
component C338
component C343
component C348
component C349
component C35
component C350
component C354
component C355
component C370
component C371
component C372
component C373
component C375
component C378
component C384
component C387
component C39
component C43
component C47
component C5
component C52
component C55
component C59
component C6
component C70
component C75
component C79
component C81
component C86
component C9
component C90
component C93
component C94
component D10
component D12
component D14
component D19
component D24
component D30
component D31
component D39
component D42
component D51
component D61
component D7
component D9
component H4
component H5
component J1
component J10
component J11
component J12
component J14
component J15
component J18
component J19
component J2
component J7
component L4
component L5
component Q10
component Q18
component Q38
component Q40
component R119
component R123
component R14
component R156
component R16
component R162
component R166
component R172
component R18
component R19
component R193
component R195
component R196
component R201
component R202
component R205
component R218
component R225
component R228
component R231
component R234
component R260
component R261
component R284
component R288
component R29
component R298
component R301
component R306
component R326
component R344
component R346
component R347
component R348
component R351
component R352
component R354
component R356
component R357
component R360
component R361
component R362
component R366
component R370
component R374
component R375
component R376
component R377
component R387
component R49
component R52
component R54
component R59
component R60
component R65
component R69
component R71
component R74
component R76
component R87
component R9
component R90
component R91
component R92
component TP11
component TP12
component TP21
component TP24
component TP3
component TP4
component TP5
component TP63
component TP73
component TP77
component U1
component U17
component U19
component U26
component U28
component U31
component U33
component U57
component U60
component U69
component U71
component U78
component U8
component Y2
net +3V3
net +5V_SOM
net /CSI/CAM0.CSI2_CLK+
net /CSI/CAM0.CSI2_CLK-
net /CSI/CAM0.CSI2_D0+
net /CSI/CAM0.CSI2_D0-
net /CSI/CAM0.CSI2_D1+
net /CSI/CAM0.CSI2_D1-
net /CSI/CAM0.CSI3_D0+
net /CSI/CAM0.CSI3_D0-
net /CSI/CAM0.CSI3_D1+
net /CSI/CAM0.CSI3_D1-
net /CSI/CAM1.CSI0_CLK+
net /CSI/CAM1.CSI0_D0+
net /CSI/CAM1.CSI0_D0-
net /CSI/CAM1.CSI0_D1+
net /CSI/CAM1.CSI0_D1-
net /CSI/CAM1.CSI1_D0+
net /CSI/CAM1.CSI1_D0-
net /CSI/CAM1.CSI1_D1+
net /CSI/CAM1.CSI1_D1-
net /CSI/CAM3.CSI6_CLK+
net /CSI/CAM3.CSI6_CLK-
net /CSI/CAM3.CSI6_D0+
net /CSI/CAM3.CSI6_D0-
net /CSI/CAM3.CSI6_D1+
net /CSI/CAM3.CSI6_D1-
net /CSI/CAM3.CSI7_D0+
net /CSI/CAM3.CSI7_D0-
net /Expansion connector/DP2.AUX-
net /Expansion connector/PCIe_{C2x1}.CLK-
net /Expansion connector/PCIe_{C2x1}.TX0+
net /M.2/PCIe_{C1x1}.CLK-
net /M.2/PCIe_{C1x1}.~{CLKREQ}
net /M.2/PCIe_{C5x4}.TX1+
net /M.2/PCIe_{C5x4}.TX1-
net /Power/USBPD1_HV
net /SFP/SFI.RX+
net /SoM_IO2/DP0.HPD
net /SoM_IO2/DP0.TX0+
net /SoM_IO2/DP0.TX0_C+
net /SoM_IO2/DP2.AUX_C+
net /SoM_IO2/DP2.AUX_C-
net /SoM_IO2/PCIe_{C2x1}R_CLK-
net GND
net SYS_VIN_HV
net VCC
rules seen on the same entity (an observation about these two documents,
not a claim that the rules ask the same question):
ours theirs entities
test-point-coverage kicad-drc/clearance 1
not comparable (a finding naming no component or net): ours 0, theirs 11
Reading the split ¶
The instinct is to compare 91 against 957 and conclude something about which tool is better. That reading is wrong, and the three-way split is there to stop you making it.
Theirs only is mostly components. Nearly all of them are KiCad’s lib_footprint_issues, where a
footprint differs from the library copy KiCad has installed, and courtyard and silkscreen checks add
to them. Agni has no
opinion about most of that and should not pretend to. Your existing DRC is not being replaced.
The nets in that column are KiCad’s clearance findings, and the two tools genuinely disagree about
them. KiCad reports 357 clearance violations, and agni, checking the same copper against the board’s
declared 0.1 mm minimum, reports none. The board also carries a .kicad_dru file of custom rules,
wider gaps for differential pairs and keep-outs between high-speed pairs and copper pours, and agni
does not read it. So KiCad is checking against rules unknown to agni, and the split tells you which
tool to believe for that question.
Ours only is nets, and each is a statement about what the circuit means: an I2C bus with no pull-up, a rail with no test point, a supply entering through a connector with no reverse protection, a net named against house style. A board DRC structurally cannot reach any of them. It is checking copper against fabrication limits, and it has no model in which “this bus needs a pull-up” is expressible.
Both is two rails, and the line under the list says what that overlap is worth. Agni flags them for reverse protection and test points, KiCad for clearance. That is the same entity under two unrelated questions, so the tool calls it an observation about two documents rather than agreement.
The useful answer to “what does this add” is a different axis, not a bigger number.
About this board’s copper ¶
The numbers above are a real board’s. It was laid out by people, passes its own manufacturer’s review, and still collects hundreds of DRC findings. Most of them are library bookkeeping, or rules that were never given to the second tool. That is normal, so the comparison reads the columns rather than the totals. The columns are complementary, because the two tools are answering different questions, and no amount of careful layout gives a copper checker access to the fact that an I2C bus has no pull-up.
Using it as a gate ¶
agni import-results writes an ordinary check-result document, so everything from rung
11 applies: archive it, re-render it later, diff it against next month’s
run. A vendor report that was a terminal scroll becomes an artifact in the same format as your own.
The comparison is the more useful gate. Suppose a finding appears in “theirs only” and is still there months later. That is a check you are not doing. And if a finding moves from “both” into “theirs only”, one of your two tools stopped seeing something it used to.
Next ¶
Drive it in the browser, the last rung.