We shipped a rule engine that had never once fired
TLDR
We developed and shipped an electrical rule engine (ERC) designed to detect short circuits, unconnected pins, and bus contentions. The engine passed CI build checks and ran without throwing errors. However, an audit revealed it had produced zero findings on invalid circuits during an entire release cycle. It turned out to be a casing mismatch. Our spec lookup tables keyed everything with uppercase pin IDs likeOUT, but the SVG nodes in the DOM were using lowercase out. Re-keying specs and adding negative assertion tests restored detection.
| Audit Phase | Spec Key Casing | Runtime Pin Casing | Detection Result |
|---|---|---|---|
| Initial Release | IN1 / OUT (Uppercase) | in1 / out (Lowercase) | 0 Findings (Inert Rules) |
| Postmortem Fix | in1 / out (Matched) | in1 / out (Lowercase) | 100% Correct Short Detection |
Problem statement: the silent linter defect
Our editor included an Electrical Rule Checker (ERC) designed to flag shorted output pins, un-driven nets, and missing power connections.
The engine was integrated into the editor toolbar, ran on document edits, and consistently returned clean reports (0 Issues Found).
During manual testing, a engineer intentionally wired two gate outputs directly together to verify the short circuit warning.
The linter returned zero errors, failing to report the short circuit.
Technical failure mode: un-matched join keys
The rule engine joined runtime SVG DOM pin attributes against a static component spec table:
// DEPRECATED: Uppercase Spec Keys
const SPECS = {
andGate: { pins: { IN1: { role: 'input' }, OUT: { role: 'output' } } }
};
However, the SVG symbol kit rendered pin elements with lowercase IDs: <circle data-pin="out" />.
When checkShortCircuits(net) ran:
SPECS['andGate'].pins['out']returnedundefined.- The rule evaluated pin roles as
[]. - The checker concluded no outputs were present, suppressing the short circuit error.
The fix & architecture: runtime key synchronization & CI negative tests
Step 1: re-key spec tables to match runtime SVG attributes
We inspected the symbol kit DOM outputs and re-keyed spec tables to match exact runtime attributes:// REFACTORED: Synchronized Spec Table Keys
const SPECS = {
andGate: { pins: { in1: { role: 'input' }, out: { role: 'output' } } },
nandGate: { pins: { in1: { role: 'input' }, in2: { role: 'input' }, out: { role: 'output' } } }
};
Step 2: automated negative test case suite
We added CI test cases that pass invalid diagrams and assert that findings are generated:// REFACTORED: Mandatory Negative Assertion Test
test('ERC Engine flags shorted logic gate outputs', () => {
const shortedDiagram = buildShortedGatesDiagram();
const report = runERCSuite(shortedDiagram);
expect(report.errors.length).toBeGreaterThan(0); expect(report.errors[0].ruleId).toBe('bus-contention'); });
Rule of thumb: A linter's validity is proven by negative test cases. Always assert that known-invalid inputs generate expected findings in CI.