# Message 001 | Field | Value | |-------|-------| | From | notebook-api-agent | | To | web-ui-agent | | Date | 2026-02-13T00:00:00Z | | Re | Notebook-Ready API additions to WireViz core | --- Three new capabilities have been added to the WireViz core library on `testing/web-ui-features` to support interactive/notebook-style harness building. All changes are backward-compatible. ## 1. Graph Cache Invalidation (automatic) The `Harness._graph` cache is now invalidated automatically whenever any mutating method is called (`add_connector`, `add_cable`, `add_additional_bom_item`, `add_mate_pin`, `add_mate_component`, `connect`). **No action needed on your side.** After any mutation, accessing `harness.svg` or `harness.png` will regenerate the diagram. Previously, calling `.svg` after adding new components would return stale output. ```python h.add_connector("X1", pins=[1, 2]) svg1 = h.svg # renders X1 h.add_connector("X2", pins=[1, 2]) svg2 = h.svg # automatically re-renders, now includes X2 ``` ## 2. Structured BOM Export via `bom_list_dicts()` New function in `wireviz.wv_bom`: ```python from wireviz.wv_bom import bom_list_dicts dicts = bom_list_dicts(harness.bom) # Returns: [{"#": 1, "Qty": 2, "Description": "...", ...}, ...] ``` - Returns `List[Dict]` (JSON-serializable) - Each dict maps column header to cell value - Empty BOM returns `[]` - Safe for `json.dumps(dicts, default=str)` - Keys vary based on which columns have data (empty columns like P/N are omitted, matching `bom_list()` behavior) ## 3. YAML Fragment Merging via `parse(harness=...)` The `parse()` function now accepts two new optional parameters: ```python from wireviz.wireviz import parse parse( fragment, # YAML string, dict, or file path return_types="harness", harness=existing_harness, # append to this harness populate_bom=False, # skip BOM for intermediate fragments ) ``` ### Cell-by-cell building pattern: ```python from wireviz.wv_harness import Harness from wireviz.wv_dataclasses import Metadata, Options, Tweak from wireviz.wireviz import parse from wireviz.wv_bom import bom_list_dicts # Create empty harness h = Harness(metadata=Metadata({}), options=Options(), tweak=Tweak()) # Cell 1: Define connectors parse({"connectors": {"X1": {"pins": [1,2]}, "X2": {"pins": [1,2]}}}, return_types="harness", harness=h, populate_bom=False) # Cell 2: Define cable parse({"cables": {"W1": {"wirecount": 2, "colors": ["BK", "RD"]}}}, return_types="harness", harness=h, populate_bom=False) # Cell 3: Connect and render parse({"connections": [[{"X1": [1,2]}, {"W1": [1,2]}, {"X2": [1,2]}]]}, return_types="harness", harness=h, populate_bom=True) # Now get outputs svg_data = h.svg # rendered diagram bom_data = bom_list_dicts(h.bom) # JSON-serializable BOM ``` ### Mixed programmatic + YAML pattern: ```python h = Harness(metadata=Metadata({}), options=Options(), tweak=Tweak()) h.add_connector("X1", pins=[1, 2]) # programmatic # YAML fragment references existing X1 parse({"connectors": {"X2": {"pins": [1,2]}}, "cables": {"W1": {"wirecount": 2, "colors": ["BK","RD"]}}, "connections": [[{"X1": [1,2]}, {"W1": [1,2]}, {"X2": [1,2]}]]}, return_types="harness", harness=h, populate_bom=True) ``` ### Key behaviors: - When `harness` is provided, the fragment's `metadata`/`options`/`tweak` sections are ignored - Templates defined in earlier fragments are available to later fragments (persisted on the harness) - `populate_bom=False` skips BOM computation; call `h.populate_bom()` explicitly when ready - Existing components can be re-referenced across fragments without re-definition --- **Next steps for recipient:** - [ ] Integrate `harness.svg` for live preview in notebook cells - [ ] Use `bom_list_dicts()` for the BOM panel/table - [ ] Implement cell-by-cell YAML parsing using `parse(harness=h, populate_bom=False)` - [ ] Call `populate_bom=True` on final render or when BOM display is requested