Architon CLI (rv) is a deterministic verification engine for hardware architecture contracts.
Architon separates hardware verification into deterministic layers:
EDA Project (KiCad / Altium / future importers)
↓
Importer
↓
DesignIR
normalized electrical topology
↓
ContractIR
component + system-level requirements
↓
Rule Engine
deterministic validation passes
↓
JSON report + terminal findings
Normalized electrical topology independent of any EDA tool.
Deterministic electrical constraints from built-in parts, metadata, and user policies.
Runs deterministic compatibility and architecture checks and produces stable findings and CI-safe exit codes.
spec.yaml
-> YAML parser/decoder
-> parts resolver
-> deterministic rule engine
-> findings report
-> CLI renderer (human or JSON) + exit code
bom.csv / project.net / project directory
-> KiCad BOM and/or netlist importer
-> optional KiCad CLI schematic netlist export when no .net exists
-> DesignIR (stable internal model)
-> deterministic rail inference + metadata-backed voltage rules
-> deterministic report payload
-> architon-report.json
The implementation follows this sequence in rv check:
- Read spec file bytes.
- Parse YAML into a
yaml.Nodeand decode intomodel.RobotSpec. - Build parts search paths and resolve
part:references into concrete values. - Execute all deterministic validation rules.
- Render findings (report/classic/json) and return a deterministic exit code.
- Input format: YAML.
- Decoding target:
internal/model/RobotSpec. - Parser behavior:
- Supports scalar I2C addresses in decimal or
0xhex viaI2CAddress.UnmarshalYAML. - Builds a YAML location map (
file,line,column) for path-aware findings.
- Supports scalar I2C addresses in decimal or
Resolver implementation: internal/resolve.ResolveAll.
Responsibilities:
- Resolve
part:for:mcumotor_drivermotors[]i2c_buses[].devices[]
- Merge strategy:
- Explicit spec values override part defaults.
- Missing zero-valued fields are filled from part definitions.
- Post-merge requirements enforced before rule evaluation:
mcu.logic_voltage_vmotor_driver.channelsmotor_driver.motor_supply_min_vmotor_driver.motor_supply_max_vmotor_driver.logic_voltage_min_vmotor_driver.logic_voltage_max_vmotor_driver.peak_per_channel_amotors[].countmotors[].stall_current_a
Parts search order (earlier wins):
./rv_parts./parts--parts-dir(repeatable)RV_PARTS_DIRS
Rule engine entrypoint: internal/validate.RunAll.
Execution is ordered and deterministic; each rule consumes resolved spec data and emits zero or more findings.
Current execution order:
- Driver channel checks
- Driver motor supply range checks
- Driver current headroom checks
- Logic rail vs driver logic range checks
- Logic rail budget note checks
- MCU vs driver logic level mismatch checks
- Battery discharge/C-rate checks
- Aggregate driver stall overload checks
- I2C address conflict checks
Finding model (internal/validate.Finding):
severity:INFO | WARN | ERRORcode: stable deterministic rule identifiermessage: human-readable deterministic explanationpath: YAML path for the relevant fieldlocation: optional file/line/column
Report model (internal/validate.Report) stores findings and computes whether any ERROR exists.
CLI is implemented with Cobra under cmd/.
Primary command:
rv check <spec.yaml>rv scan <path>rv scan <bom.csv> --map mapping.yamlrv scan <project.net>rv scan .rv scan . --bom bom/bom.csv --netlist exports/project.netrv scan <bom.csv> --out my-report.jsonrv scan <netlist.net> --meta .architon/meta.yamlrv scan <netlist.net> --railsrv scan . --kicad-cli /full/path/to/kicad-clirv doctor
Output modes:
- Human report style (TTY default)
- Human classic style
- JSON (
--output json, optional--pretty, optional--out-file) - Scan JSON file output (
architon-report.json) with:summarydesign_irrulesderivedvoltage inference and rail coverage data when netlist data is present
Exit behavior is documented in the canonical exit code table in README.md.
rv scan writes architon-report.json with report_version, design_ir.version, and:
summary.delimiterfor BOM-backed scanssummary.netsanddesign_ir.netsfor netlist-backed scanssummary.next_stepsonly on parse failure- contract loading and coverage fields:
summary.user_contracts_loaded,summary.built_in_contracts_loaded,summary.requirements_enabled,summary.parts_matched,summary.part_contract_coverage_percentage,summary.unknown_power_critical_refs, andsummary.enabled_contract_rules - deprecated compatibility aliases:
summary.contracts_appliedandsummary.contract_coverage_percentage derived.net_voltages,derived.inferred_net_voltages,derived.unknown_voltage_nets,derived.rail_inferences, andderived.rail_coveragewhen voltage inference data is present- optional
findings[].inferenceprovenance for voltage-based findings, including reason when available - optional contract finding details:
findings[].component_ref,findings[].bus_id,findings[].bus_type,findings[].bus_nets,findings[].source,findings[].provenance, andfindings[].fix rulesis a deprecated alias offindings
Successful CLI output also prints a short deterministic terminal summary with:
ARCHITON SCANTargetResultPartsNetsErrorsWarningsRulesUser contracts loaded,Built-in contracts loaded,Requirements enabled,Part contract coverage,Parts matched,Unknown power-critical refs, andEnabled contract rulesViolations- compact rail coverage counts and level
- inferred rails, voltage coverage, and metadata mode
Detected BOM/Detected Netlistfor directory auto-detectionGenerated Netlistwhenrv scan .exports a temporary netlist from*.kicad_sch
--rails prints the sorted rail inference table with voltage, confidence level, confidence score, source, warnings, and rail coverage summary. --explain-rails remains supported as a legacy alias.
Example success snippet:
{
"report_version": "1",
"summary": {
"delimiter": ","
},
"design_ir": {
"version": "0"
}
}Example failure snippet:
{
"report_version": "1",
"summary": {
"delimiter": ",",
"next_steps": [
"Re-export BOM (CSV) and check missing delimiters/quotes",
"Run rv scan <bom.csv> --out report.json and inspect summary.parse_errors"
]
},
"design_ir": {
"version": "0"
}
}rv scan implementation is intentionally separated:
internal/ir: stable, input-agnosticDesignIRmodelinternal/importers: importer adapter interface; KiCad, Altium, and future sources compile to DesignIRinternal/importers/kicad: deterministic KiCad BOM CSV ingestion, header mapping, and KiCad.netS-expression parsinginternal/contracts: importer-agnostic component, pin, net, and system-contract schema plus the small curated built-in sourceinternal/enrichment: pluggable contract assembly formeta.yaml, inferred rail voltages, and other deterministic sourcesinternal/rules: contract-level rules that consume only DesignIR + ContractIRcmd/scan.go: deterministic single-file or project-directory scan input resolution, including optional KiCad CLI netlist export from one root*.kicad_schinternal/ir: deterministic BOM + netlist merge into one project-level DesignIRinternal/infer: deterministic net-name and metadata-enriched rail voltage inferenceinternal/rails: pure rail coverage summary and terminal explanation formattinginternal/report: deterministic scan report JSON builder/writer
Contract source precedence is explicit metadata, schematic/BOM fields, built-in contracts, explicit custom contracts, then inferred net names. Built-ins are one source, not the architecture.
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.
Same input spec or scan input + same metadata/part library -> same output findings and exit code.
This allows CI gating, reproducible audits, and traceable engineering review.
Deterministic validation is the trust foundation for hardware contract enforcement.
Higher-level tooling can recommend options, but contract checks should remain explicit, reproducible, and testable.
Architecture diagram reference:
This engine can be embedded into higher-level workflows.
