Repository navigation
Conversation
create_netclass takes diff_pair_width, diff_pair_gap and diff_pair_via_gap, each optional and greater than zero, and get_netclasses reports them beside the four settings it already did. Both read the one field mapping. An update changes only the values named. A new named class without them leaves them out of the project file, so its width and gap keep resolving from the Default; the four older settings keep their creation defaults. The Default is still written complete and repaired without touching values already set. The bound is checked before the guard against a board KiCad holds, as every argument error is. The reply reports the class as stored. get_netclasses reports each setting resolved, naming in inherits those taken from the Default, except diff_pair_via_gap: KiCad 10.0.6 never fills a named class's from the Default, so a named class without its own reports null. The fixture is a project KiCad 10.0.6 saved after reading the classes create_netclass wrote, so its bytes are KiCad's. Closes mixelpixx#777 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
KiCad keeps a differential-pair width, gap and via gap on every netclass, and Konnect's complete Default already writes all three. But
create_netclasscould not set them, andget_netclassesdid not report them.create_netclassnow takesdiff_pair_width,diff_pair_gapanddiff_pair_via_gap, and both tools report them under the contract the four existing settings follow.Closes #777.
One reading for you to confirm. The issue lists a differential field in
inherits"when supplied by Default".addMissingDefaultsfills in the width and gap the class omits, taking them from the Default (common/project/net_settings.cpp:1094-1106).:1108-1114).null. It is in neitherinheritsnormissing_fields, sincemissing_fieldsis carried only by the Default and names only what the Default lacks.If you would rather report the Default's via gap there, I'll change it in this PR: one condition (
NOT_INHERITED), the two tests that assertnull, and the sentences that say so.Approach
FIELDSand the module'sNETCLASS_FIELDSmapped the same KiCad keys to the same argument names, one for writing and one for reading. They are now one table,NETCLASS_FIELDS, with the creation default as a third column, so the two tools cannot disagree on which settings exist. The schema, the handler's bound and the reply still name the three new settings separately, and tests cover each.numberwithexclusiveMinimum: 0.opt_positive_f64. It checks this before the guard against a board KiCad holds, as it checks every argument error.net_settings.cpp:44-51).net_settings.cpp:116-123). So its width and gap keep resolving from the Default. The four older settings keep their creation defaults.kicad_default_class(), which already carried KiCad's 0.2 / 0.25 / 0.25 (common/netclass.cpp:46-48). An incomplete one is still repaired without touching values already set.nullwhere it sets none.get_netclassesreports each value resolved, naming ininheritsthose taken from the Default. The via gap is the exception above.pcbnew/router/pns_kicad_iface.cpp:1222,:1258-1262).pcbnew/board_design_settings.cpp:1587-1604).pcbnew/drc/drc_engine.cpp:313-364).common/dialogs/panel_setup_netclasses.cpp:464-531).route_differential_pairis untouched.KiCad line numbers are at tag 10.0.6.
Architectural fit
This extends the two netclass tools and the field mapping they now share. It adds no tool, no IPC command and no dependency, and it touches no board file.
The scope is #777's acceptance. Explicit exclusions:
opt_f64, and their schema has no minimum. So zero or a negative is still accepted for them, throughtools/calland on a direct call alike.net_settingson read.get_netclassesstill reads anet_settingsthat is not an object as no classes.create_netclassrefuses it.null, and an omitted argument leaves the value. The four older settings are the same. Hand-edit the project file, or delete the class in Board Setup and create it again.opt_f64still reads a wrong-typed value for them as omitted, as before.Branch and dependencies
mainat9488e5f.77fdd7a. It owns Expose differential-pair settings in netclass create and readback #777's acceptance criteria.crates/konnect-core/src/tools/pcb_routing.rswith fix(pcb): refuse project-file writes while KiCad holds the project #817. The hunks are apart from fix(pcb): refuse project-file writes while KiCad holds the project #817's, and a localgit merge-fileof that file takes both without a conflict.docs/API_MIGRATIONS.mdgains an entry at the top, like nearly every open PR, so it conflicts there with fix(pcb): refuse project-file writes while KiCad holds the project #817, fix(pcb): mirror inner copper layers when a footprint changes sides #864, fix(pcb): refuse sync updates that would drop footprint children #865 (mine) and the others. Whichever lands second restacks its entry. That file is all it shares with fix(pcb): refuse sync updates that would drop footprint children #865.crates/konnect/assets/skills/kicad-pcb/SKILL.mdwith fix(pcb): mirror inner copper layers when a footprint changes sides #864, about 280 lines apart.Compatibility and safety
create_netclass's reply and each classget_netclassesreports gain the three fields. Migration entry: "create_netclassandget_netclassescarry the differential-pair settings" (minor release, since a response changes shape)..kicad_prois written, atomically, and not at all when nothing changes. A new named class gets no differential-pair key unless one is named. The board is never touched.docs/KICAD_NETCLASS_DEFAULTS.mdsaidaddMissingDefaultsfills any field a class omits. It now names the two of its twelve fields that function does not fill, the via gap andline_style, and its two line references to the function point at 10.0.6.kicad-pcb/SKILL.mdnow names the three arguments.Validation
Acceptance (issue body)
exclusiveMinimum: 0, andopt_positive_f64in the handler. JSON carries no non-finite number.create_netclass_updates_one_differential_pair_setting_alonecreate_netclass_leaves_a_named_class_sparseDefaultcomplete, repair keptcreate_netclass_writes_the_default_class_complete,create_netclass_backfills_an_incomplete_default_without_touching_set_valuesinherits, missing fieldsget_netclasses_reports_differential_pair_settings_as_kicad_resolves_them,an_unresolved_differential_pair_setting_is_named_missing_not_invented. The via gap is as in the Summary.create_netclass_updates_one_differential_pair_setting_alone).route_differential_pairseparatenetclass_diff_pair_kicad10.*and its README, below.a_kicad_written_project_reads_explicit_and_inherited_differential_pair_settingsreadsUSBas explicit andPoweras inherited.differential_pair_settings_out_of_bounds_are_refused_by_namesends 0, -0.1,"0.2"andnullfor each of the three fields, to the compiled validator and throughtools/call.updating_a_kicad_written_project_changes_only_the_value_named, on the KiCad-written fixture.every_setting_create_netclass_writes_reads_back_as_its_ownwrites all seven settings and reads each back as the class's own.Changed tool behavior
null(create_netclass_leaves_a_named_class_sparse). The four older creation defaults are unchanged (a_new_class_is_still_created_with_the_documented_defaults). Values given are written as given (create_netclass_writes_the_differential_pair_settings_it_is_given), on the Default too (create_netclass_lets_the_caller_override_the_default_class).nullare refused by the compiled schema. Throughtools/calleach is refused asinvalid_argumentnaming the field, and nothing is written. A direct call with zero gets the same refusal from the handler, even while a mock KiCad holds the board (differential_pair_settings_out_of_bounds_are_refused_by_name)..kicad_pro. A missing file is refused (create_netclass_without_a_project_file_refuses_and_writes_nothing). A malformed one is refused and left as it was: invalid JSON by both tools, and anet_settingsthat is not an object bycreate_netclass(a_malformed_project_file_is_refused_and_left_alone).create_netclass_updates_one_differential_pair_setting_alone). On a project KiCad wrote, changing one value leaves every other setting, class and pattern as KiCad left it, and the board byte-identical (updating_a_kicad_written_project_changes_only_the_value_named). A call that changes nothing writes nothing (a_call_that_changes_nothing_leaves_the_project_file_untouched). The Default's repair fills only what is absent (create_netclass_backfills_an_incomplete_default_without_touching_set_values).Commands, on Linux with Rust 1.96.0 from
rust-toolchain.toml, on the tree of this head:cargo fmt --all -- --check: clean.cargo test --workspace --locked --lib --tests: 2,398 passed, 0 failed, 45 ignored.cargo test --workspace --locked --doc: 9 passed, 2 ignored.cargo clippy --workspace --locked --all-targets -- -D warnings: clean.Real KiCad. KiCad 10.0.6 on Linux, standalone
pcbnewunder Xvfb with the API enabled.Setup:
create_projectlaid out a fresh project, and pcbnew saved it through the API'sSaveDocument, which writes the board and the project file (pcbnew/api/api_handler_pcb.cpp:185-198,pcbnew/files.cpp:376-382,:999-1002).create_netclasswroteUSBwith all three differential-pair values andPowerwith only a clearance, andassign_net_to_classadded a pattern.Results:
pcb_color,schematic_colorandtuning_profile, which it always writes (net_settings.cpp:76-80).USB's values unchanged, the via gap included. A differential-pair key is written only when the class holds one (:116-123), so that is what KiCad had read.Powercame back with no differential-pair key.netclass_patternsand every other key were identical, and the board was saved byte-identical.get_netclasseson KiCad's file gives:USB: 0.18 / 0.15 / 0.3, nothing inherited;Power: the Default's 0.2 / 0.25, both ininherits, and anullvia gap.74449740d24dbd3b02b6df536327447088197856ab049ad29f883f68431c6ac3before KiCad's resave), andget_netclasseson KiCad's file returns the same classes.Not run:
The fixture.
netclass_diff_pair_kicad10.kicad_proand.kicad_pcbare the files of that run as KiCad saved them the second time, with nothing edited. The README beside them has the recipe and the SHA-256s. This branch wrote the classes before KiCad read and resaved them, which is whyUSBcan carry a via gap: Board Setup cannot author one on a named class.Tests. 9 new and 5 extended in
netclass_tests. The acceptance and behavior tables above name them.Negative controls. A baseline run of the 43 tests
cargo test -p konnect-core --lib netclassselects passed. Then each guard was neutered on its own, those tests were run, and the file was restored. 13 of 13 were caught, none by a build break:diff_pair_gapremoved from the shared mapping, the array's length adjusted (the issue's control)every_setting_create_netclass_writes_reads_back_as_its_own,create_netclass_writes_the_differential_pair_settings_it_is_given,create_netclass_updates_one_differential_pair_setting_alone,create_netclass_lets_the_caller_override_the_default_class,get_netclasses_reports_differential_pair_settings_as_kicad_resolves_them,an_unresolved_differential_pair_setting_is_named_missing_not_invented,a_kicad_written_project_reads_explicit_and_inherited_differential_pair_settings,updating_a_kicad_written_project_changes_only_the_value_nameddiff_pair_widthremoved from the shared mapping, the array's length adjustedevery_setting_create_netclass_writes_reads_back_as_its_ownanda_kicad_written_project_reads_explicit_and_inherited_differential_pair_settingsget_netclasses_reports_differential_pair_settings_as_kicad_resolves_them,a_kicad_written_project_reads_explicit_and_inherited_differential_pair_settingscreate_netclass_leaves_a_named_class_sparsenullwhere unsetcreate_netclass_leaves_a_named_class_sparsedifferential_pair_settings_out_of_bounds_are_refused_by_namedifferential_pair_settings_out_of_bounds_are_refused_by_nameexclusiveMinimumremoved from one propertydifferential_pair_settings_out_of_bounds_are_refused_by_namedifferential_pair_settings_out_of_bounds_are_refused_by_namedifferential_pair_settings_out_of_bounds_are_refused_by_name,updating_a_kicad_written_project_changes_only_the_value_named,a_malformed_project_file_is_refused_and_left_alonecreate_netclass_writes_the_differential_pair_settings_it_is_given,create_netclass_updates_one_differential_pair_setting_alone,create_netclass_leaves_a_named_class_sparsecreate_netclass_writes_the_default_class_complete,create_netclass_backfills_an_incomplete_default_without_touching_set_valuesa_call_that_changes_nothing_leaves_the_project_file_untouchedReview checklist
upstream/main, has no merge conflicts, and CI passed on this exact head. (After CI runs on this head.)responsibility for the final current-main refresh.
upstream/main, not a release tag (unless this is an approved backport).has been reviewed on the new exact head. An unchanged unique diff may use a
focused refresh review; changed behavior received substantive re-review.
docs/NAMING_CONVENTIONS.md; public renames include compatibility handling.tool_count,tool-directory.md, DEV.md stats, README count). N/A: no tool added.Maintainer merge state
status:*workflow label.status:ready-to-mergeapplies to this exact head SHA.were cleared under the review-request workflow (manual requests remain open).
mainruleset.@mixelpixx/@neussePR, or explicit authorization names this exact head.gh pr merge N --merge.🤖 Generated with Claude Code