8.8 KiB
8.8 KiB
Selection API Lossiness Audit + Execution Plan
Goal: close data-loss gaps between KiCad protobuf payloads and public kicad-ipc-rs selection APIs.
Scope
GetSelectionfamily:get_selection_rawget_selectionget_selection_detailsget_selection_summaryadd/remove/clear_selectiontyped wrappersget_selection_as_string
Source Anchors (do not re-discover)
- Proto commands:
kicad/api/proto/common/commands/editor_commands.proto:338(GetSelection)kicad/api/proto/common/commands/editor_commands.proto:349(SelectionResponse)kicad/api/proto/common/commands/editor_commands.proto:355(AddToSelection)kicad/api/proto/common/commands/editor_commands.proto:364(RemoveFromSelection)kicad/api/proto/common/commands/editor_commands.proto:373(ClearSelection)kicad/api/proto/common/commands/editor_commands.proto:424(SavedSelectionResponse)
- Client flow:
src/client/selection.rs(get_selection_raw,get_selection_details,get_selection,get_selection_summary,add_to_selection,clear_selection,remove_from_selection,get_selection_as_string,summarize_selection,summarize_item_details)src/client/decode.rs(decode_pcb_item)
- Public model bottleneck:
src/model/board.rs:389onward (Pcb*structs +PcbItem)src/model/common.rs:194(SelectionSummary)src/model/common.rs:203(SelectionItemDetail)
- Relevant proto item schemas:
src/proto/generated/kiapi.board.types.rs:19(Track)src/proto/generated/kiapi.board.types.rs:39(Arc)src/proto/generated/kiapi.board.types.rs:227(Via)src/proto/generated/kiapi.board.types.rs:305(Pad)src/proto/generated/kiapi.board.types.rs:420(Zone)src/proto/generated/kiapi.board.types.rs:520(Dimension)src/proto/generated/kiapi.board.types.rs:580(Group)src/proto/generated/kiapi.board.types.rs:705(FootprintInstance)src/proto/generated/kiapi.common.types.rs:541(Text)src/proto/generated/kiapi.common.types.rs:554(TextBox)src/proto/generated/kiapi.common.types.rs:634(GraphicShape)
Current State: What Is Lossy vs Not
Not lossy
get_selection_rawreturnsSelectionResponse.itemsdirectly (Vec<Any>). No internal field drop.*_selection_rawvariants for add/remove/clear preserve raw payload when server returnsSelectionResponse.
Lossy API layers
get_selection_summary: compresses all item payloads into counts bytype_url.get_selection_details: flattens into human/debug string + byte length; no structured fields.get_selection: decodes into reducedPcbItemmodels with many fields omitted.add_to_selection/remove_from_selection/clear_selection: typed wrappers return summary only.get_selection_as_string: dropsSavedSelectionResponse.ids; returnscontentsonly.GetSelection.typesfilter exists in proto, but no public method exposes it (always empty in current code).
Loss Inventory by Item Type (proto -> public typed)
Track: dropslocked.Arc: dropslocked.Via: dropslocked; keeps only shallowpad_stackinfo (layer span + drill start/end), drops drill geometry and advanced padstack settings.Pad: dropslocked, fullpad_stack, clearance override, die length/delay, symbol pin metadata.FootprintInstance: keeps id/ref/pos/orientation/layer/pad_count; drops definition internals, fields (value,datasheet,description), attributes/overrides, symbol linkage metadata.BoardGraphicShape: keeps geometry kind as string only; drops structured geometry + graphic attributes.BoardText/BoardTextBox: keep body text only; drop position/box, style attributes, hyperlink, lock/knockout.Zone: keeps coarse stats (type/counts/filled); drops outline, settings, border, layer properties, priority.Dimension: keeps text/layer/style string only; drops detailed unit/precision/style geometry and overrides.Group: keepsitem_count; drops actual item id list.
Extra Coverage Gaps
decode_pcb_itemsupports 12 board item payload types only. Other PCB object types can appear asUnknownin typed API.protomodule is crate-private. Consumers getAnybytes, not generated proto structs from this crate.
Implementation Plan (follow in order)
Phase 1: additive APIs, zero breakage
- Add richer selection-return models in
src/model/common.rs:SelectionStringDump { ids: Vec<String>, contents: String }SelectionMutationResult { items: Vec<Any>, summary: SelectionSummary }or equivalent typed struct without reducing to summary-only.
- Add new
KiCadClientmethods insrc/client/selection.rs:get_selection_with_types(type_codes: Vec<i32>) -> Vec<PcbItem>and raw/details variants.get_selection_string_dump() -> SelectionStringDump(keep existingget_selection_as_stringas convenience).- Rich mutation variants for add/remove/clear that expose returned items, not summary only.
- Export new models via
src/lib.rs. - Add blocking mirror methods in
src/blocking.rs.
Phase 2: reduce typed-model loss
- Expand
Pcb*structs insrc/model/board.rswith additive optional fields (no removals). - Update
decode_pcb_itemmapping insrc/client/decode.rsto fill new fields. - Prefer structured enums over stringified debug fields where possible:
- graphic geometry
- dimension style
- Preserve backward compatibility:
- existing fields remain
- new fields optional/defaultable
Phase 3: unhandled item kinds
- Add typed support for additional PCB object payload types if proto types exist in generated files.
- If unavailable in proto snapshot, keep
Unknownfallback; includetype_url+raw_len.
Phase 4: docs/tests/regression
- Unit tests in
src/client/tests.rs:- new selection filter path
- new response models keep previously dropped fields
- backward compatibility on old methods
- Update docs:
README.mdAPI tabledocs/PCB_SELECTION_DEEP_DUMP.mdsequence updates
- Validation commands:
cargo fmt --allcargo testcargo test --features blocking
Decision Log Needed Before Coding
- Whether to expose proto-level structs publicly (
pub mod proto) vs keep custom models only. - Whether
get_selectionshould stay “compact model” and new methods be “full model” (recommended). - Naming:
- keep existing methods untouched
- add explicit
*_full/*_richAPIs for clarity.
Acceptance Criteria
- No breaking changes in existing method signatures.
- New selection APIs expose:
- selection type filtering
SavedSelectionResponse.ids- non-summary mutation payload access
- materially more per-item structured data than current
PcbItem.
- Existing examples still compile; add one new example showcasing rich selection extraction.