# Selection API Lossiness Audit + Execution Plan Goal: close data-loss gaps between KiCad protobuf payloads and public `kicad-ipc-rs` selection APIs. ## Scope - `GetSelection` family: - `get_selection_raw` - `get_selection` - `get_selection_details` - `get_selection_summary` - `add/remove/clear_selection` typed wrappers - `get_selection_as_string` ## Source Anchors (do not re-discover) - Proto commands: - [`kicad/api/proto/common/commands/editor_commands.proto:338`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/kicad/api/proto/common/commands/editor_commands.proto:338) (`GetSelection`) - [`kicad/api/proto/common/commands/editor_commands.proto:349`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/kicad/api/proto/common/commands/editor_commands.proto:349) (`SelectionResponse`) - [`kicad/api/proto/common/commands/editor_commands.proto:355`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/kicad/api/proto/common/commands/editor_commands.proto:355) (`AddToSelection`) - [`kicad/api/proto/common/commands/editor_commands.proto:364`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/kicad/api/proto/common/commands/editor_commands.proto:364) (`RemoveFromSelection`) - [`kicad/api/proto/common/commands/editor_commands.proto:373`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/kicad/api/proto/common/commands/editor_commands.proto:373) (`ClearSelection`) - [`kicad/api/proto/common/commands/editor_commands.proto:424`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/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:389`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/model/board.rs:389) onward (`Pcb*` structs + `PcbItem`) - [`src/model/common.rs:194`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/model/common.rs:194) (`SelectionSummary`) - [`src/model/common.rs:203`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/model/common.rs:203) (`SelectionItemDetail`) - Relevant proto item schemas: - [`src/proto/generated/kiapi.board.types.rs:19`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/proto/generated/kiapi.board.types.rs:19) (`Track`) - [`src/proto/generated/kiapi.board.types.rs:39`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/proto/generated/kiapi.board.types.rs:39) (`Arc`) - [`src/proto/generated/kiapi.board.types.rs:227`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/proto/generated/kiapi.board.types.rs:227) (`Via`) - [`src/proto/generated/kiapi.board.types.rs:305`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/proto/generated/kiapi.board.types.rs:305) (`Pad`) - [`src/proto/generated/kiapi.board.types.rs:420`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/proto/generated/kiapi.board.types.rs:420) (`Zone`) - [`src/proto/generated/kiapi.board.types.rs:520`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/proto/generated/kiapi.board.types.rs:520) (`Dimension`) - [`src/proto/generated/kiapi.board.types.rs:580`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/proto/generated/kiapi.board.types.rs:580) (`Group`) - [`src/proto/generated/kiapi.board.types.rs:705`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/proto/generated/kiapi.board.types.rs:705) (`FootprintInstance`) - [`src/proto/generated/kiapi.common.types.rs:541`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/proto/generated/kiapi.common.types.rs:541) (`Text`) - [`src/proto/generated/kiapi.common.types.rs:554`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/proto/generated/kiapi.common.types.rs:554) (`TextBox`) - [`src/proto/generated/kiapi.common.types.rs:634`](/Users/milindsharma/Developer/kicad-oss/kicad-ipc-rs/src/proto/generated/kiapi.common.types.rs:634) (`GraphicShape`) ## Current State: What Is Lossy vs Not ### Not lossy - `get_selection_raw` returns `SelectionResponse.items` directly (`Vec`). No internal field drop. - `*_selection_raw` variants for add/remove/clear preserve raw payload when server returns `SelectionResponse`. ### Lossy API layers - `get_selection_summary`: compresses all item payloads into counts by `type_url`. - `get_selection_details`: flattens into human/debug string + byte length; no structured fields. - `get_selection`: decodes into reduced `PcbItem` models with many fields omitted. - `add_to_selection` / `remove_from_selection` / `clear_selection`: typed wrappers return summary only. - `get_selection_as_string`: drops `SavedSelectionResponse.ids`; returns `contents` only. - `GetSelection.types` filter exists in proto, but no public method exposes it (always empty in current code). ## Loss Inventory by Item Type (proto -> public typed) - `Track`: drops `locked`. - `Arc`: drops `locked`. - `Via`: drops `locked`; keeps only shallow `pad_stack` info (layer span + drill start/end), drops drill geometry and advanced padstack settings. - `Pad`: drops `locked`, full `pad_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`: keeps `item_count`; drops actual item id list. ## Extra Coverage Gaps - `decode_pcb_item` supports 12 board item payload types only. Other PCB object types can appear as `Unknown` in typed API. - `proto` module is crate-private. Consumers get `Any` bytes, not generated proto structs from this crate. ## Implementation Plan (follow in order) ### Phase 1: additive APIs, zero breakage 1. Add richer selection-return models in `src/model/common.rs`: - `SelectionStringDump { ids: Vec, contents: String }` - `SelectionMutationResult { items: Vec, summary: SelectionSummary }` or equivalent typed struct without reducing to summary-only. 2. Add new `KiCadClient` methods in `src/client/selection.rs`: - `get_selection_with_types(type_codes: Vec) -> Vec` and raw/details variants. - `get_selection_string_dump() -> SelectionStringDump` (keep existing `get_selection_as_string` as convenience). - Rich mutation variants for add/remove/clear that expose returned items, not summary only. 3. Export new models via `src/lib.rs`. 4. Add blocking mirror methods in `src/blocking.rs`. ### Phase 2: reduce typed-model loss 1. Expand `Pcb*` structs in `src/model/board.rs` with additive optional fields (no removals). 2. Update `decode_pcb_item` mapping in `src/client/decode.rs` to fill new fields. 3. Prefer structured enums over stringified debug fields where possible: - graphic geometry - dimension style 4. Preserve backward compatibility: - existing fields remain - new fields optional/defaultable ### Phase 3: unhandled item kinds 1. Add typed support for additional PCB object payload types if proto types exist in generated files. 2. If unavailable in proto snapshot, keep `Unknown` fallback; include `type_url` + `raw_len`. ### Phase 4: docs/tests/regression 1. Unit tests in `src/client/tests.rs`: - new selection filter path - new response models keep previously dropped fields - backward compatibility on old methods 2. Update docs: - `README.md` API table - `docs/PCB_SELECTION_DEEP_DUMP.md` sequence updates 3. Validation commands: - `cargo fmt --all` - `cargo test` - `cargo 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_selection` should stay “compact model” and new methods be “full model” (recommended). - Naming: - keep existing methods untouched - add explicit `*_full`/`*_rich` APIs 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.