Architon CLI (rv) uses deterministic rule engines for YAML specs and KiCad scan data. rv check rules live in internal/validate/rules.go; scan voltage rules live under internal/rules.
Rules evaluate only resolved local input data and emit findings with explicit IDs.
- Rules are deterministic.
- Rules never guess.
- Rules never infer missing hidden data.
- Rules operate only on provided and resolved values.
- Rules may skip when required inputs are unknown (
0or unset), unless the rule explicitly validates that field.
Rule engine entrypoint: validate.RunAll(spec, locs).
Rules execute in a fixed order:
ruleDriverChannelsruleMotorSupplyVoltageruleDriverCurrentHeadroomruleLogicVoltageCompatruleRailCurrentBudgetruleLogicLevelMisMatchruleBatteryCRateruleDriverStallOverloadruleI2CAddressConflict
This order is stable and produces reproducible findings for identical input.
INFO: context and non-blocking notesWARN: elevated risk or low marginERROR: deterministic contract violation
Exit behavior is documented in README.md.
The catalog below covers rv check.
DRV_CHANNELS_INVALID(ERROR):motor_driver.channels <= 0DRV_CHANNELS_INSUFFICIENT(ERROR): total motor count exceeds channel count
When channels are sufficient, this rule emits no finding.
BAT_V_INVALID(ERROR): negative battery voltage;0means unset and the rule skipsDRV_SUPPLY_RANGE(ERROR): battery voltage outside driver motor supply range
DRV_PEAK_LT_STALL(ERROR): driver peak per channel below motor stall currentDRV_CONT_LOW_MARGIN(WARN): driver continuous per channel below recommended1.25 * nominal_current
RAIL_V_INVALID(ERROR): negative logic rail voltage;0means unset and the rule skipsLOGIC_V_DRIVER_MISMATCH(ERROR): logic rail outside driver logic rangeLOGIC_V_MCU_MISMATCH(WARN): MCU logic voltage differs from logic rail by more than0.25V
RAIL_I_UNKNOWN(WARN):power.logic_rail.max_current_amissing or<= 0
When power.logic_rail.max_current_a > 0, this rule emits no finding.
MCU_LOGIC_V_INVALID(ERROR): negative MCU logic voltage;0means unset and the rule skipsDRV_LOGIC_MIN_V_INVALID(ERROR): negative driver logic min voltage;0means unset and the rule skipsDRV_LOGIC_MAX_V_INVALID(ERROR): negative driver logic max voltage;0means unset and the rule skipsDRV_LOGIC_RANGE_INVALID(ERROR): driver logic min > maxLOGIC_LEVEL_MISMATCH(ERROR): MCU logic outside driver logic window
Battery max current source precedence:
power.battery.max_discharge_apower.battery.capacity_ah * power.battery.c_ratingpower.battery.max_current_a
Rules:
BATT_PEAK_OVER_C(ERROR): total motor stall current exceeds battery max derived from precedenceBATT_PEAK_MARGIN_LOW(WARN): total motor stall current is>= 80%of battery max
DRV_PEAK_OVERLOAD(ERROR): total motor stall current exceedsdriver_peak_per_channel * channelsDRV_PEAK_MARGIN_LOW(WARN): total motor stall current is>= 80%of driver total peak
I2C_ADDR_CONFLICT(ERROR): duplicate non-zero I2C address on the same bus
address_hex accepts decimal or 0x-prefixed hex values.
Netlist-backed scans can run deterministic contract rules when rail voltages are inferred from net names and/or supplied by .architon/meta.yaml / --meta. Project scans can generate a temporary KiCad netlist from one root *.kicad_sch when no .net file exists.
RULE_SUPPLY_CONTRACT(ERROR): provider voltage on a net is outside a consumer pin's contracted voltage rangeRULE_LOGIC_LEVEL_CONTRACT(ERROR): output logic voltage exceeds an input pin's contracted toleranceRULE_BUS_ROLE_CONTRACT(WARNING/ERROR): obvious I2C role/direction conflicts without guessing when data is missingRULE_VOLTAGE_CONFLICT(ERROR): metadata, inferred, or propagated voltage evidence conflicts on a netsupply_abs_max(ERROR): powered supply pin exceeds a matched part's absolute maximum supply voltagesupply_recommended_range(WARNING): powered supply pin is outside the recommended operating range but within absolute maximumgpio_abs_max(ERROR): GPIO-like pin is on a net above its absolute maximum voltagemotor_driver_vm_range(ERROR): motor-driver VM pin is outside the supported motor-supply voltage rangeregulator_output_current(ERROR): known downstream load current exceeds a regulator output-current contract
Voltage-based findings include inference provenance when available: net name, source, confidence score, confidence level, and reason.
Contract source precedence is deterministic: explicit .architon/meta.yaml, then schematic/BOM contract fields, then the curated built-in contract source, then explicit custom contracts from .architon/contracts.yaml or --contracts, then inferred net names. Built-ins are intentionally small and local; there is no network lookup, datasheet scraping, or generic parts database.
Custom contracts are deterministic explicit YAML. rv contracts validate validates schema only; use rv scan --contracts <path> to enforce a contract file against a design.
pullup_ohms is resistance-only in v0.4.0. I2C capacitance and rise-time validation require physical bus data and are future work.
Given the same:
- Spec file content, or scan input netlist/BOM and metadata
- Part files resolved by search order
- CLI options
the engine returns the same findings and exit code.
Architon performs deterministic analysis. Rail voltage inference is deterministic and transparent. Each inference includes source, confidence score, reason, evidence, and warnings. No probabilistic models or network calls are used.
To add a new rule safely:
- Add a pure rule function in
internal/validate/rules.gothat readsmodel.RobotSpecand returns[]Finding. - Register it in
RunAllin a deterministic position. - Assign a stable, descriptive rule code.
- Add tests in
internal/validate/rules_test.gofor pass/fail and edge cases. - Keep rule logic side-effect free and independent of external state.