Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| // Preserve typed part metadata emitted from `Component(part=...)`. | ||
| // Legacy `properties["part"]` must not overwrite the structured JSON payload. | ||
| if key == crate::attrs::PART { | ||
| continue; |
There was a problem hiding this comment.
Unconditional skip drops legacy properties["part"] values
Medium Severity
The properties["part"] key is unconditionally skipped in the properties loop, but the typed part attribute is only emitted earlier when component.part() returns Some. When a component has no typed part= kwarg but does have a legacy properties = {"part": "some-value"}, that property is silently dropped from the output — the typed path doesn't emit anything, and the properties loop skips it. The guard needs to be conditional on component.part().is_some().
There was a problem hiding this comment.
this is intentional
| // Legacy `properties["part"]` must not overwrite the structured JSON payload. | ||
| if key == crate::attrs::PART { | ||
| continue; |
There was a problem hiding this comment.
🔴 Unconditional skip of properties["part"] drops the property when no typed part is set
When converting a component to schematic attributes, properties["part"] is unconditionally skipped at line 630, even when component.part() returns None. This means a user who writes Component(..., properties={"part": "some-legacy-value"}) without a typed part=... kwarg will have their "part" property silently dropped from the schematic output.
Root Cause
The guard at crates/pcb-zen-core/src/convert.rs:630 checks if key == crate::attrs::PART { continue; } without first verifying that a typed part attribute was actually emitted. Meanwhile, remove_consolidated_component_properties at crates/pcb-zen-core/src/lang/component.rs:391-410 does not remove "part" from the properties map, so the value survives into component.properties() but gets unconditionally skipped during serialization.
The two relevant code paths:
- Typed part emitted (lines 601-606):
if let Some(part) = component.part() { comp_inst.add_attribute("part", ...) } - Properties loop (lines 627-634): unconditionally skips
key == "part"
When component.part() is None, path (1) emits nothing and path (2) skips the legacy property → "part" disappears entirely from the schematic attributes.
Impact: Silent data loss for any existing project that stores metadata in properties["part"] without using the new typed part=... kwarg.
| // Legacy `properties["part"]` must not overwrite the structured JSON payload. | |
| if key == crate::attrs::PART { | |
| continue; | |
| // Preserve typed part metadata emitted from `Component(part=...)`. | |
| // Legacy `properties["part"]` must not overwrite the structured JSON payload. | |
| if key == crate::attrs::PART && component.part().is_some() { |
Was this helpful? React with 👍 or 👎 to provide feedback.
crates/pcb-zen-core/tests/part.rs
Outdated
| @@ -0,0 +1,553 @@ | |||
| use std::sync::Arc; | |||
There was a problem hiding this comment.
any reason not to do the snapshot_eval! here?
There was a problem hiding this comment.
mainly because it doesn't snapshot netlist / post-conversion state. I can add snapshot_netlist_eval!. other option is to use the netlist snapshot test stuff in pcb-zen instead of pcb-zen-core
Build Performance
Measured with hyperfine. Times show median ±stddev. |


Note
Medium Risk
Touches core
Componentconstruction/mutation and schematic/netlist attribute serialization, so regressions could affect BOM/netlist outputs despite added tests and compatibility guards.Overview
Adds a new typed
Partvalue (builtin.Part(...)) and aComponent(part=...)kwarg to carry structured sourcing metadata (MPN, manufacturer, qualifications) while keeping the existing scalarmpn/manufacturerfields.Updates schematic/netlist conversion to serialize
partas a JSON attribute, supportlist[Part]inproperties["alternatives"], and prevent legacyproperties["part"]from overwriting the structured payload; component modifiers can also mutatepart/alternativeswithpartkept in sync when scalar fields change. Includes new unit/integration tests, docs/spec updates, and example/workspace board updates demonstrating the new API.Written by Cursor Bugbot for commit 8773310. This will update automatically on new commits. Configure here.