← Commit history

0.2.0: verbs from any bridge (tools/proposed.json, agreement gate, Altium measured too); batch 1: 21 schematic verbs from the KiCad bridge, agreed by altium-lane. Coverage: Altium 182, KiCad 113, Fusion 78 of 203

Colby Knox ·fc16144cb6 ·14d ago ·parent 1fba2ff
11 files changed +3671−461
README.md+42−11
@@ -5,14 +5,17 @@ Electronics or the next tool someone writes a bridge for: the same verbs, the sa page is where that is defined and kept in sync.  The **reference is the Altium bridge** ([adom/altium-bridge](https://wiki.adom.inc/adom/altium-bridge)), the most-complete one: its 201 verbs, sorted into tiers, are the standard; its board model is the model. The KiCad-([adom/kicad-bridge](https://wiki.adom.inc/adom/kicad-bridge)) and Fusion 360-([adom/fusion-bridge](https://wiki.adom.inc/adom/fusion-bridge)) bridges are measured against it below.+complete one: its board model is the model, its conventions are the conventions, and its Rust is the checks+implementation. Its 201 verbs, sorted into tiers, are the base of the verb list, and **any bridge can propose more**:+a job that Altium lacks but KiCad or Fusion does joins the standard once another bridge's thread agrees to it (see+*Proposing a verb* below). Every bridge, Altium included, is measured against the whole list below:+[adom/kicad-bridge](https://wiki.adom.inc/adom/kicad-bridge), [adom/fusion-bridge](https://wiki.adom.inc/adom/fusion-bridge).  ## What is in the standard -1. **The verbs** (`verbs/standard.json`): every reference verb with its inputs, outputs, hint, pitfalls and an-   example, generated from the Altium bridge's own `altium_describe`, each in a tier:+1. **The verbs** (`verbs/standard.json`): every standard verb with its inputs, outputs, hint, pitfalls and an+   example, each in a tier. The Altium bridge's own `altium_describe` gives most of them (`source: "altium"`); the+   others come from agreed proposals (`source: "proposed"`, with `proposedBy` and `agreedBy`):     | Tier | What it is |    |---|---|@@ -42,12 +45,12 @@ verb by verb: [docs/coverage.md](docs/coverage.md). <!-- coverage:start (tools/generate.py writes this) --> | Tier | Verbs | Altium | KiCad | Fusion 360 | |---|---|---|---|---|-| **core** | 60 | 60 | 38 | 26 |-| **native** | 34 | 34 | 23 | 16 |+| **core** | 79 | 60 | 57 | 26 |+| **native** | 36 | 34 | 25 | 16 | | **checks** | 32 | 32 | 7 | 3 | | **app** | 56 | 56 | 24 | 33 | | **platform** | 19 | 19 | 0 | 0 |-| standard (all but platform) | 182 | 182 | 92 | 78 |+| standard (all but platform) | 203 | 182 | 113 | 78 | <!-- coverage:end -->  The **checks** tier is where the other bridges are furthest behind, and it is the cheapest to close: those verbs are@@ -75,13 +78,41 @@ adom-bridge altium_describe '{}' > reference/altium-<version>.json python3 tools/generate.py ``` -`tools/tiers.json` puts each reference verb in a tier; `tools/equivalents.json` records verbs the other bridges have-under another name. An equivalent counts only when every verb it names is in that bridge's newest `reference/` file+`tools/tiers.json` puts each reference verb in a tier; `tools/equivalents.json` records verbs a bridge has under+another name (Altium included, for proposed verbs it already does). An equivalent counts only when every verb it names is in that bridge's newest `reference/` file (`generate.py` warns and leaves it out otherwise), so add the bridge's catalog before crediting its new verbs. When the reference bridge gains a verb, give it a tier and regenerate. +Clone the page's head right before running `generate.py` and push straight after: a stale clone overwrites another+bridge's newer reference or equivalents.++## Proposing a verb++A job the standard lacks can come from any bridge. Add it to `tools/proposed.json` with the same fields as a+`verbs/standard.json` row (`name`, `tier`, `summary`, `input`, `output`, `hint`, and `pitfalls`, `related`, `example`+where you can), in the standard's terms (mm, y up, KiCad layer names, `Ref.Pin`, no tool vocabulary), plus:++| Field | Meaning |+|---|---|+| `proposedBy` | the thread that proposed it (`kicad-lane`) |+| `since` | the standard version it joined in |+| `agreedBy` | the threads that agreed to the name and shape |++`generate.py` refuses the file unless every entry's `agreedBy` names a thread other than its proposer, and refuses a+name the Altium bridge already has (credit the verb in `tools/equivalents.json` instead). Naming:++- Board verbs take no prefix; a placed part is a *part* (`move_parts`, `remove_parts`).+- Schematic sheet verbs start with `sch_`.+- `*_symbol` and `*_footprint` are library verbs: they act on library files, not on the design.+- Verb first, plural when the verb takes a list. Edit verbs take a list and land as one undo step, so there are no+  separate batch verbs.+- Checks-tier proposals belong in the shared checks engine; a bridge may ship its own first if it answers in the+  proposed output shape.+ ## Status -Version 0.1.2: the verbs, the board model and the conventions, with Altium bridge 0.2.75 as the reference. 0.1.1+Version 0.2.0: verbs can come from any bridge. The first batch, 21 schematic verbs from the KiCad bridge+(`sch_connect_pins`, `sch_bus`, `sch_items`, `sch_pins`, `sch_trace_point`, `render_schematic` ...), was agreed by the+Altium bridge's thread; Altium now shows those as gaps. Earlier: version 0.1.2: the verbs, the board model and the conventions, with Altium bridge 0.2.75 as the reference. 0.1.1 settles the questions the KiCad and Fusion bridges raised as they adopted the board model (the y-down frame, pour islands, fractured fills, custom pads, reply units): the answers are in [docs/board-model.md](docs/board-model.md#settled-questions). 
SKILL.md+7−5
@@ -5,7 +5,7 @@ description: >-   The standard every Adom EDA bridge follows so one AI can drive Altium, KiCad, Fusion 360 and any future PCB tool the   same way: the shared verb names in tiers (core, native, checks, app, platform), the board model JSON every   <prefix>_routing_state returns (mm, KiCad copper layer names, revision guard), the reply and refusal conventions, and-  how far each bridge covers it. Altium bridge is the reference. Use when building or extending an EDA bridge, adding a+  how far each bridge covers it. Altium bridge is the reference; any bridge can propose verbs (tools/proposed.json). Use when building or extending an EDA bridge, adding a   verb to kicad/fusion/altium bridges, porting a check between bridges, comparing what each bridge can do, or reading a   board model from any bridge. Trigger words: eda bridge standard, bridge parity, same verbs every eda tool, board model   json, routing_state schema, port altium verb to kicad, what can the kicad bridge not do, standard verb names.@@ -13,8 +13,8 @@ description: >-  # eda-bridge-standard -The standard for Adom EDA bridges. The Altium bridge is the reference: its verbs are the standard and its board model-is the model.+The standard for Adom EDA bridges. The Altium bridge is the reference: its board model is the model and its verbs are+the base of the verb list. Other bridges add verbs through `tools/proposed.json` once another bridge's thread agrees.  ## Read first @@ -30,11 +30,13 @@ is the model. ## When you add a verb to a bridge  1. Look the job up in `verbs/standard.json` and use that name with your prefix (`kicad_return_path`), its inputs and-   its output keys. If the standard does not have it, add it to the reference bridge first, or propose it on this page.+   its output keys. If the standard does not have it, propose it in `tools/proposed.json` (README, *Proposing a+   verb*): neutral name and shape, and `agreedBy` from another bridge's thread before it lands. 2. If your tool does the job under its own verb already, keep it and add the standard name as an alias. 3. Reply with `success`, `errorCode` and `error` on refusal, and a `_hint` that says the next step. Take    `expectedRevision` on edits; offer `dryRun` where a plan can be wrong.-4. Add the bridge's verb list to `reference/` and run `python3 tools/generate.py`: `docs/coverage.md` moves.+4. Add the bridge's verb list to `reference/` and run `python3 tools/generate.py` on a fresh clone of the page's+   head, then push at once: `docs/coverage.md` moves.  ## When you port a check (the checks tier) 
docs/conventions.md+7−1
@@ -11,6 +11,9 @@ the same way, and lets the shared checks run on any of them. - A verb a tool cannot do at all is not faked. Leave it out, or answer `success:false` with   `errorCode: "not_supported"` and an `error` that says why. - Tool-only verbs (Altium 365, OutJobs) keep their own names under the `platform` tier and stay out of the standard.+- A job the standard lacks is proposed in `tools/proposed.json` and joins once another bridge's thread agrees (README,+  *Proposing a verb*). Board verbs have no prefix and call a placed part a part; sheet verbs start with `sch_`;+  `*_symbol` and `*_footprint` act on library files.  ## Units, layers, frames @@ -21,6 +24,8 @@ the same way, and lets the shared checks run on any of them. - A reply field that carries its unit in its name says mm: `xMm`, `widthMm`, `areaMm2`. Some of the reference bridge's   older verbs still answer in mils (`xMil`, marked `unitsNote` in `verbs/standard.json`); that is the reference's debt,   not the standard. A new bridge answers those verbs in mm under `Mm` names.+- Schematic sheets follow the same rule: millimetres, the tool's sheet origin, y up. A pin is named `Ref.Pin`+  (`U1.3`), and an item (a wire, a label, a junction) by the tool's own stable `id`, as `sch_items` lists it. - Copper layers carry KiCad's names on every tool: `F.Cu`, `In1.Cu` to `In30.Cu`, `B.Cu`, and `*.Cu` for a pad on every   copper layer. A layer argument also takes the tool's own id. - Nets are named as the design names them; matching is case-insensitive.@@ -91,4 +96,5 @@ The common ones. A bridge adds its own for its tool's states, in the same snake_ ## Every verb documents itself  `<prefix>_describe` returns every verb with `summary`, `input`, `output`, `hint`, `pitfalls`, `related`, `example` and-`timeoutSeconds`. `verbs/standard.json` is generated from the reference bridge's `describe`.+`timeoutSeconds`. `verbs/standard.json` is generated from the reference bridge's `describe` and the agreed proposals in+`tools/proposed.json`.
docs/coverage.md+236−215
@@ -1,250 +1,271 @@ # Coverage: every standard verb on each bridge -Reference: Altium bridge 0.2.75. Compared: KiCad bridge 1.0.62, Fusion 360 bridge 1.12.1.+Altium bridge 0.2.75 (the reference), KiCad bridge 1.0.62, Fusion 360 bridge 1.12.1. 21 verbs came from other bridges' proposals (tools/proposed.json); they are marked *proposed*. `exact` is the same job under the same or an equivalent name; `partial` does part of it or does it differently; blank is missing. Generated by `tools/generate.py` from `verbs/coverage.json`; do not edit by hand.  | Tier | Verbs | Altium | KiCad | Fusion 360 | |---|---|---|---|---|-| **core** | 60 | 60 | 38 | 26 |-| **native** | 34 | 34 | 23 | 16 |+| **core** | 79 | 60 | 57 | 26 |+| **native** | 36 | 34 | 25 | 16 | | **checks** | 32 | 32 | 7 | 3 | | **app** | 56 | 56 | 24 | 33 | | **platform** | 19 | 19 | 0 | 0 |-| standard (all but platform) | 182 | 182 | 92 | 78 |+| standard (all but platform) | 203 | 182 | 113 | 78 |  ## core  Read and edit the design. Every bridge provides these: they are how an AI sees and changes a board. -| Verb | What it does | KiCad | Fusion 360 |-|---|---|---|---|-| `add_body` | Put a 3D body on a footprint of a PcbLib: a STEP model, or an extruded box when no step is given. It REPLACES the footprint's existing 3D bodies (a... |  |  |-| `add_models` | Attach one or more PCBLIB footprint models, parameters, comment and description to a SchLib component (Altium's several-footprints-per-symbol mechanism). |  |  |-| `add_symbol_art` | Draw the chip-outline artwork (the chip-thumbnailer polylines adom-symbol baked into the KiCad symbol) into a SchLib component, fitted to its body... |  |  |-| `apply_silkscreen` | Land a silkscreen plan in one undo step: designators and comments moved, sized and turned (or hidden), free overlay texts and lines added (bottom texts... | `kicad_silk_fields_batch / kicad_silk_text_batch / kicad_silk_graphics_batch` | `fusion_apply_silkscreen` |-| `board_outline` | Draw the board shape as tracks and arcs on a mechanical layer: the outline a fab house reads from the Gerbers. A board built by script has its shape but... | `kicad_board_outline` | `fusion_board_outline` |-| `board_shape` | Redefine the CURRENT board's outline as a wMm x hMm rectangle at (x0Mm, y0Mm) by rewriting the board outline's segments. | `kicad_board_outline` | `fusion_board_shape` |-| `board_summary` | One-screen summary of the current board, shaped from one read_board round trip: component counts by side, nets, copper layers actually in use, rule counts. | `kicad_board_summary` | `fusion_board_summary` |-| `clone_symbol` | Copy a symbol inside the current SchLib under a new name, all display modes included. |  |  |-| `component_data` | Placement data for one board component, or for all of them: footprint pattern, comment, layer/side, position, rotation, size, pad count and the nets on its... | `kicad_component_data` | `fusion_component_data` |-| `component_pins` | Every pad of one board component with its net, position, layer, size and hole. | `kicad_component_pins` | `fusion_component_pins` |-| `copper_layers` | Every copper layer Altium can address on the current board (top, mid 1-30, planes 1-16, bottom) with names and visibility. | `kicad_copper_layers` | `fusion_copper_layers` |-| `copy_footprint` | Duplicate a footprint inside the current PcbLib under a new name (every primitive replicated). |  |  |-| `create_footprint` | Create one footprint from a pad list in a PcbLib (the library is created and saved if the path does not exist) and return a proof frame. | `kicad_create_footprint` |  |-| `create_symbol` | Create one rectangular symbol from a pin list in a SchLib (the library is created and saved if the path does not exist) and return a proof frame. | `kicad_create_symbol` |  |-| `doc_params` | Read or set a sheet's document parameters: the title block (Title, DocumentNumber, Revision, DrawnBy, Author, CompanyName, ...). |  |  |-| `find_symbol` | Find symbols (or footprints with kind:'footprint') by part of their name across libraries: the given ones, or every installed .SchLib/.PcbLib. | `kicad_find_symbol` |  |-| `footprint_primitives` | Geometry dump of one PLACED component: its tracks, arcs, pads (with solder and paste mask expansion in um) and texts in mils with layer ids; other primitive... | `kicad_fp_info` (partial) |  |-| `layer_stack` | The CURRENT board's stack-up: copper layers in order with copper thickness and the dielectric under each (height, constant, material), and the total... | `kicad_layer_stack` | `fusion_layer_stack` |-| `layers` | The current board's layer set with ids, names, kind and whether each is displayed. |  | `fusion_layers` |-| `layers_in_use` | Which layers of the current board actually carry primitives: copper layers with copper (densest first) and every layer with anything on it. | `kicad_layers_in_use` | `fusion_layers_in_use` |-| `list_designators` | Every component designator on the current board. | `kicad_list_designators` | `fusion_list_designators` |-| `list_library` | Names of every component in a .SchLib or every footprint in a .PcbLib (kind taken from the extension). Opens the library; no screenshot. | `kicad_list_footprints / kicad_list_symbols` (partial) |  |-| `list_nets` | Every net on the current board with its pad count. | `kicad_list_nets` | `fusion_list_nets` |-| `move_parts` | Move and rotate placed components; each part is read back to 0.001 mm and the exact rotation. One undo step. | `kicad_move_footprint` | `fusion_move_parts` |-| `net_connections` | Every pad on the board with its net and owner (Designator.Pad), plus a bounding span and the airline length (minimum spanning tree over its pads, airlineMm)... | `kicad_trace_net / kicad_find_connections` (partial) | `fusion_net_connections` |-| `normalize_bodies` | Move every 3D body of a PcbLib's footprints (or one footprint) onto its pad cluster. A body added through the canvas lands 50000 mil from the pads in the... |  |  |-| `part_parameters` | The parameter names a project's parts carry (with how many parts carry each), or with name, that parameter's value on every part. |  |  |-| `place_on_pcb` | Place ONE footprint from a PcbLib on a new board and return a proof frame. The single-part predecessor of altium_test_board. | `kicad_place_footprint` |  |-| `place_on_sch` | Place one symbol, or a ';' list of symbols, from the open SchLib on ONE new sheet (sheet sized FROM the measured parts: 500 mil gaps, 600 mil margins, A4... |  |  |-| `place_vias` | Place vias (through, top to bottom). One undo step, read back. | `kicad_add_via` | `fusion_place_vias` |-| `plate_vias` | Make every drilled pad in a PcbLib a plated MULTI-LAYER pad (all footprints, or footprintName). adom-lbr writes heatsink vias as pads with a hole; Altium... |  |  |-| `read_board` | ONE round trip: components, nets, layers, copper, rules, occupancy, outline. | `kicad_board_summary` (partial) | `fusion_board_info / fusion_get_design_info` (partial) |-| `read_rules` | Every design rule on the current board, flat, disabled ones included: name, kind ordinal, enabled, priority, both scope expressions, comment, and Altium's... | `kicad_list_design_rules` | `fusion_read_rules` |-| `read_schematic` | Components on the CURRENT schematic sheet (designator, library reference, comment, position, parameters) in one agent round trip. | `kicad_sch_components` (partial) | `fusion_schematic` (partial) |-| `read_symbol` | Read a SchLib component back: description, display-mode count, the pins of mode 0 (designator, name, electrical type), every parameter with its hidden flag,... | `kicad_read_symbol` |  |-| `remove_footprint` | Delete one footprint from the current PcbLib. |  |  |-| `remove_items` | Delete specific free tracks and vias, given exactly as altium_routing_state returned them. One undo step. | `kicad_remove_route` (partial) | `fusion_remove_items` |-| `remove_symbol` | Delete one component from the current SchLib. | `kicad_remove_symbol` |  |-| `rename_footprint` | Rename a footprint in the current PcbLib. |  |  |-| `rename_symbol` | Rename a component (LibReference) in the current SchLib. |  |  |-| `ripup_nets` | Delete every free track, arc and via on each named net. One undo step. |  | `fusion_ripup_nets` |-| `route_net` | Route one net as tracks, segment by segment; a waypoint on another layer drops a via there. One undo step, read back. | `kicad_route_net` | `fusion_route_net` |-| `routing_state` | The WHOLE current board as data, in mm: tracks, arcs, vias, pads (with owner and net), components (ref, x, y, rotation, side), polygon pours, the outline,... | `kicad_routing_state` | `fusion_routing_state` |-| `rules_by_kind` | The current board's ENABLED design rules grouped by rule kind (Clearance, Width, RoutingVias, ...), each group sorted by priority. Shaped from one... | `kicad_board_rules` (partial) | `fusion_rules_by_kind` |-| `sch_connect` | Connect pins of placed parts: a wire stub from each pin's outer end plus a net label (kind label), a power port (kind power: GND-like nets get a ground... | `kicad_sch_wire / kicad_sch_label` (partial) |  |-| `sch_edit` | Change placed parts on a sheet: move (to x,y mil), moveBy (dx,dy), rotate (degrees), rename (designator), re-comment (comment), delete. One undo step. | `kicad_sch_set_property / kicad_sch_move / kicad_sch_delete` (partial) |  |-| `sch_place_part` | Place a component from a .SchLib onto an EXISTING sheet at a position, with its library parameters (MPN, Manufacturer, distributor numbers) and its... | `kicad_sch_place_symbol` |  |-| `sch_sheet_symbol` | Make a design hierarchical: a sheet symbol on the parent sheet for a child sheet, its entries joined to the parent's nets, and matching ports on the child.... | `kicad_sch_sheet_symbol` |  |-| `sch_swap_part` | Replace a placed part with another library part (a different value, package or symbol) at the same place, designator and rotation, keeping its connections:... | `kicad_sch_replace_symbol` (partial) |  |-| `schematic_data` | Components on a schematic sheet (filePath, else the CURRENT sheet) with their pins (number, name, electrical type), position and orientation. designator... | `kicad_sch_components` (partial) |  |-| `set_models` | Replace every footprint model on a SchLib component with ONE PCBLIB model (set_params footprint and add_models APPEND, which is how a symbol ends up with two). |  |  |-| `set_outline` | Reshape the current board's outline (a rectangle with rounded corners, or a polygon). One undo step. | `kicad_board_outline` | `fusion_set_outline` |-| `set_params` | Set parameters on a SchLib component, optionally its comment, and optionally link a footprint by name. |  |  |-| `set_track_width` | Set the width of the EXISTING tracks and arcs on nets or a net class (rules only steer new routing). Widen power nets after routing, or thin a net that... | `kicad_modify_track` (partial) | `fusion_set_track_width` |-| `set_visibility` | Show or hide one named parameter on a SchLib component. |  |  |-| `sheet_params` | Write parameters onto PLACED parts on the schematic sheets (the BOM write-back): MPN, Manufacturer, Mouser/DigiKey/LCSC numbers, anything. A missing... |  |  |-| `silk_state` | The silkscreen as it stands: every part's body box, its designator and comment (text, location, size, rotation, shown, Altium's measured box), and the free... |  | `fusion_silk_state` |-| `swap_footprint` | Replace the FIRST component on the current board with a footprint from a PcbLib at the same position, re-assigning nets by pad designator. Tracks are... | `kicad_update_footprints_from_library` (partial) |  |-| `symbol_prims` | Read a SchLib component's drawing: primitive counts by kind, body rectangle, polyline bounding box, display mode and the footprint models. Read-only, use it... |  |  |-| `xcopy_footprint` | Copy a footprint ACROSS libraries: from fromLib into toLib (opened and made current), optionally under a new name. |  |  |+| Verb | What it does | Altium | KiCad | Fusion 360 |+|---|---|---|---|---|+| `add_body` | Put a 3D body on a footprint of a PcbLib: a STEP model, or an extruded box when no step is given. It REPLACES the footprint's existing 3D bodies (a... | `altium_add_body` |  |  |+| `add_models` | Attach one or more PCBLIB footprint models, parameters, comment and description to a SchLib component (Altium's several-footprints-per-symbol mechanism). | `altium_add_models` |  |  |+| `add_symbol_art` | Draw the chip-outline artwork (the chip-thumbnailer polylines adom-symbol baked into the KiCad symbol) into a SchLib component, fitted to its body... | `altium_add_symbol_art` |  |  |+| `apply_silkscreen` | Land a silkscreen plan in one undo step: designators and comments moved, sized and turned (or hidden), free overlay texts and lines added (bottom texts... | `altium_apply_silkscreen` | `kicad_silk_fields_batch / kicad_silk_text_batch / kicad_silk_graphics_batch` | `fusion_apply_silkscreen` |+| `board_outline` | Draw the board shape as tracks and arcs on a mechanical layer: the outline a fab house reads from the Gerbers. A board built by script has its shape but... | `altium_board_outline` | `kicad_board_outline` | `fusion_board_outline` |+| `board_shape` | Redefine the CURRENT board's outline as a wMm x hMm rectangle at (x0Mm, y0Mm) by rewriting the board outline's segments. | `altium_board_shape` | `kicad_board_outline` | `fusion_board_shape` |+| `board_summary` | One-screen summary of the current board, shaped from one read_board round trip: component counts by side, nets, copper layers actually in use, rule counts. | `altium_board_summary` | `kicad_board_summary` | `fusion_board_summary` |+| `clone_symbol` | Copy a symbol inside the current SchLib under a new name, all display modes included. | `altium_clone_symbol` |  |  |+| `component_data` | Placement data for one board component, or for all of them: footprint pattern, comment, layer/side, position, rotation, size, pad count and the nets on its... | `altium_component_data` | `kicad_component_data` | `fusion_component_data` |+| `component_pins` | Every pad of one board component with its net, position, layer, size and hole. | `altium_component_pins` | `kicad_component_pins` | `fusion_component_pins` |+| `copper_layers` | Every copper layer Altium can address on the current board (top, mid 1-30, planes 1-16, bottom) with names and visibility. | `altium_copper_layers` | `kicad_copper_layers` | `fusion_copper_layers` |+| `copy_footprint` | Duplicate a footprint inside the current PcbLib under a new name (every primitive replicated). | `altium_copy_footprint` |  |  |+| `create_footprint` | Create one footprint from a pad list in a PcbLib (the library is created and saved if the path does not exist) and return a proof frame. | `altium_create_footprint` | `kicad_create_footprint` |  |+| `create_symbol` | Create one rectangular symbol from a pin list in a SchLib (the library is created and saved if the path does not exist) and return a proof frame. | `altium_create_symbol` | `kicad_create_symbol` |  |+| `doc_params` | Read or set a sheet's document parameters: the title block (Title, DocumentNumber, Revision, DrawnBy, Author, CompanyName, ...). | `altium_doc_params` |  |  |+| `find_symbol` | Find symbols (or footprints with kind:'footprint') by part of their name across libraries: the given ones, or every installed .SchLib/.PcbLib. | `altium_find_symbol` | `kicad_find_symbol` |  |+| `footprint_primitives` | Geometry dump of one PLACED component: its tracks, arcs, pads (with solder and paste mask expansion in um) and texts in mils with layer ids; other primitive... | `altium_footprint_primitives` | `kicad_fp_info` (partial) |  |+| `layer_stack` | The CURRENT board's stack-up: copper layers in order with copper thickness and the dielectric under each (height, constant, material), and the total... | `altium_layer_stack` | `kicad_layer_stack` | `fusion_layer_stack` |+| `layers` | The current board's layer set with ids, names, kind and whether each is displayed. | `altium_layers` |  | `fusion_layers` |+| `layers_in_use` | Which layers of the current board actually carry primitives: copper layers with copper (densest first) and every layer with anything on it. | `altium_layers_in_use` | `kicad_layers_in_use` | `fusion_layers_in_use` |+| `list_designators` | Every component designator on the current board. | `altium_list_designators` | `kicad_list_designators` | `fusion_list_designators` |+| `list_library` | Names of every component in a .SchLib or every footprint in a .PcbLib (kind taken from the extension). Opens the library; no screenshot. | `altium_list_library` | `kicad_list_footprints / kicad_list_symbols` (partial) |  |+| `list_nets` | Every net on the current board with its pad count. | `altium_list_nets` | `kicad_list_nets` | `fusion_list_nets` |+| `move_parts` | Move and rotate placed components; each part is read back to 0.001 mm and the exact rotation. One undo step. | `altium_move_parts` | `kicad_move_footprint` | `fusion_move_parts` |+| `net_connections` | Every pad on the board with its net and owner (Designator.Pad), plus a bounding span and the airline length (minimum spanning tree over its pads, airlineMm)... | `altium_net_connections` | `kicad_trace_net / kicad_find_connections` (partial) | `fusion_net_connections` |+| `normalize_bodies` | Move every 3D body of a PcbLib's footprints (or one footprint) onto its pad cluster. A body added through the canvas lands 50000 mil from the pads in the... | `altium_normalize_bodies` |  |  |+| `part_parameters` | The parameter names a project's parts carry (with how many parts carry each), or with name, that parameter's value on every part. | `altium_part_parameters` |  |  |+| `place_on_pcb` | Place ONE footprint from a PcbLib on a new board and return a proof frame. The single-part predecessor of altium_test_board. | `altium_place_on_pcb` | `kicad_place_footprint` |  |+| `place_on_sch` | Place one symbol, or a ';' list of symbols, from the open SchLib on ONE new sheet (sheet sized FROM the measured parts: 500 mil gaps, 600 mil margins, A4... | `altium_place_on_sch` |  |  |+| `place_vias` | Place vias (through, top to bottom). One undo step, read back. | `altium_place_vias` | `kicad_add_via` | `fusion_place_vias` |+| `plate_vias` | Make every drilled pad in a PcbLib a plated MULTI-LAYER pad (all footprints, or footprintName). adom-lbr writes heatsink vias as pads with a hole; Altium... | `altium_plate_vias` |  |  |+| `read_board` | ONE round trip: components, nets, layers, copper, rules, occupancy, outline. | `altium_read_board` | `kicad_board_summary` (partial) | `fusion_board_info / fusion_get_design_info` (partial) |+| `read_rules` | Every design rule on the current board, flat, disabled ones included: name, kind ordinal, enabled, priority, both scope expressions, comment, and Altium's... | `altium_read_rules` | `kicad_list_design_rules` | `fusion_read_rules` |+| `read_schematic` | Components on the CURRENT schematic sheet (designator, library reference, comment, position, parameters) in one agent round trip. | `altium_read_schematic` | `kicad_sch_components` (partial) | `fusion_schematic` (partial) |+| `read_symbol` | Read a SchLib component back: description, display-mode count, the pins of mode 0 (designator, name, electrical type), every parameter with its hidden flag,... | `altium_read_symbol` | `kicad_read_symbol` |  |+| `remove_footprint` | Delete one footprint from the current PcbLib. | `altium_remove_footprint` |  |  |+| `remove_items` | Delete specific free tracks and vias, given exactly as altium_routing_state returned them. One undo step. | `altium_remove_items` | `kicad_remove_route` (partial) | `fusion_remove_items` |+| `remove_symbol` | Delete one component from the current SchLib. | `altium_remove_symbol` | `kicad_remove_symbol` |  |+| `rename_footprint` | Rename a footprint in the current PcbLib. | `altium_rename_footprint` |  |  |+| `rename_symbol` | Rename a component (LibReference) in the current SchLib. | `altium_rename_symbol` |  |  |+| `ripup_nets` | Delete every free track, arc and via on each named net. One undo step. | `altium_ripup_nets` |  | `fusion_ripup_nets` |+| `route_net` | Route one net as tracks, segment by segment; a waypoint on another layer drops a via there. One undo step, read back. | `altium_route_net` | `kicad_route_net` | `fusion_route_net` |+| `routing_state` | The WHOLE current board as data, in mm: tracks, arcs, vias, pads (with owner and net), components (ref, x, y, rotation, side), polygon pours, the outline,... | `altium_routing_state` | `kicad_routing_state` | `fusion_routing_state` |+| `rules_by_kind` | The current board's ENABLED design rules grouped by rule kind (Clearance, Width, RoutingVias, ...), each group sorted by priority. Shaped from one... | `altium_rules_by_kind` | `kicad_board_rules` (partial) | `fusion_rules_by_kind` |+| `sch_bus` *proposed* | Draw a bus as a polyline (one bus segment per pair of points), optionally with a bus label such as D[0..7] or a group {SDA SCL} at its first point. One undo... |  | `kicad_sch_bus` |  |+| `sch_bus_entry` *proposed* | Add 45-degree bus entries: the short diagonal that joins a member wire's end to a bus. One undo step. |  | `kicad_sch_bus_entry` |  |+| `sch_connect` | Connect pins of placed parts: a wire stub from each pin's outer end plus a net label (kind label), a power port (kind power: GND-like nets get a ground... | `altium_sch_connect` | `kicad_sch_connect_to_net / kicad_sch_no_connect / kicad_sch_wire / kicad_sch_label` |  |+| `sch_connect_pins` *proposed* | Wire pins to pins on a sheet by Ref.Pin: an L-shaped route (one horizontal and one vertical leg) for each pair, with a junction dot wherever a route meets... |  | `kicad_sch_connect_pins` |  |+| `sch_connect_to_bus` *proposed* | Fan pins onto a bus: for each pin a wire running to the bus, a 45-degree bus entry onto it and a member label (D0, D1 ...) on the wire. One undo step. |  | `kicad_sch_connect_to_bus` |  |+| `sch_create` *proposed* | Create an empty schematic sheet with a paper size and title block; optionally add it to a project as a child sheet of the root. It places no parts or nets... |  | `kicad_sch_create` |  |+| `sch_delete_wire` *proposed* | Delete wires or bus segments by id, by their two ends, or every wire through a point, and remove junction dots that no longer join three or more items. One... |  | `kicad_sch_delete_wire` |  |+| `sch_edit` | Change placed parts on a sheet: move (to x,y mil), moveBy (dx,dy), rotate (degrees), rename (designator), re-comment (comment), delete. One undo step. | `altium_sch_edit` | `kicad_sch_set_property / kicad_sch_move / kicad_sch_delete / kicad_sch_rotate` (partial) |  |+| `sch_edit_label` *proposed* | Edit net labels: rotate, move to a point or by a delta, rename, or move every label of a net at once. One undo step. |  | `kicad_sch_edit_label` |  |+| `sch_fix_connectivity` *proposed* | Snap near-miss wire ends onto the pin, label, sheet pin or wire end they almost touch, within a tolerance. dryRun (the default) lists the moves;... |  | `kicad_sch_fix_connectivity` |  |+| `sch_hierarchy` *proposed* | The sheet tree of a design, recursively: each sheet's name, file, id, instance path, page number, position, size and pins. renumber:true renumbers pages... |  | `kicad_sch_hierarchy` |  |+| `sch_items` *proposed* | List a sheet's wiring items with ids and coordinates: wires, buses, bus entries, net labels (local, global, hierarchical), power ports, junctions,... |  | `kicad_sch_items` |  |+| `sch_junction` *proposed* | Add junction dots at points, or remove dots by id or point. One undo step. |  | `kicad_sch_junction` |  |+| `sch_move_region` *proposed* | Move everything inside a box by (dx, dy): parts, wire ends inside the box (wires crossing its edge stretch), labels, junctions, no-connect markers, texts,... |  | `kicad_sch_move_region` |  |+| `sch_page` *proposed* | Read or set a sheet's page: paper size, orientation and title block (title, date, revision, company, comment lines). |  | `kicad_sch_page` |  |+| `sch_pins` *proposed* | Every pin of the named parts on a sheet: its absolute position (rotation and mirror applied), number, name, electrical type, the side it leaves the body,... |  | `kicad_sch_pins` |  |+| `sch_place_part` | Place a component from a .SchLib onto an EXISTING sheet at a position, with its library parameters (MPN, Manufacturer, distributor numbers) and its... | `altium_sch_place_part` | `kicad_sch_place_symbol` |  |+| `sch_reset_fields` *proposed* | Put parts' designator and value text (or the named fields) back where the library symbol places them, through each part's rotation and mirror. One undo step. |  | `kicad_sch_reset_fields` |  |+| `sch_sheet_pins` *proposed* | A sheet symbol's pins: list, add, edit (rename, kind, move along an edge) or delete. import:true adds a pin for every hierarchical port inside the child... |  | `kicad_sch_sheet_pins` |  |+| `sch_sheet_symbol` | Make a design hierarchical: a sheet symbol on the parent sheet for a child sheet, its entries joined to the parent's nets, and matching ports on the child.... | `altium_sch_sheet_symbol` | `kicad_sch_sheet_symbol` |  |+| `sch_split_wire` *proposed* | Split the wire through a point into two wires there, with a junction dot at the cut, so a new branch can end on a wire end. One undo step. |  | `kicad_sch_split_wire` |  |+| `sch_swap_part` | Replace a placed part with another library part (a different value, package or symbol) at the same place, designator and rotation, keeping its connections:... | `altium_sch_swap_part` | `kicad_sch_replace_symbol` (partial) |  |+| `sch_text` *proposed* | Add free text to a sheet (a note, a title, a design comment) with size, angle, justification, bold and italic. Text has no electrical meaning. One undo step. |  | `kicad_sch_text` |  |+| `sch_trace_point` *proposed* | Everything electrically connected at a point on a sheet: the wires, labels, pins, junctions, sheet pins and no-connect markers there, and for each net they... |  | `kicad_sch_trace_point` |  |+| `schematic_data` | Components on a schematic sheet (filePath, else the CURRENT sheet) with their pins (number, name, electrical type), position and orientation. designator... | `altium_schematic_data` | `kicad_sch_components` (partial) |  |+| `set_models` | Replace every footprint model on a SchLib component with ONE PCBLIB model (set_params footprint and add_models APPEND, which is how a symbol ends up with two). | `altium_set_models` |  |  |+| `set_outline` | Reshape the current board's outline (a rectangle with rounded corners, or a polygon). One undo step. | `altium_set_outline` | `kicad_board_outline` | `fusion_set_outline` |+| `set_params` | Set parameters on a SchLib component, optionally its comment, and optionally link a footprint by name. | `altium_set_params` |  |  |+| `set_track_width` | Set the width of the EXISTING tracks and arcs on nets or a net class (rules only steer new routing). Widen power nets after routing, or thin a net that... | `altium_set_track_width` | `kicad_modify_track` (partial) | `fusion_set_track_width` |+| `set_visibility` | Show or hide one named parameter on a SchLib component. | `altium_set_visibility` |  |  |+| `sheet_params` | Write parameters onto PLACED parts on the schematic sheets (the BOM write-back): MPN, Manufacturer, Mouser/DigiKey/LCSC numbers, anything. A missing... | `altium_sheet_params` |  |  |+| `silk_state` | The silkscreen as it stands: every part's body box, its designator and comment (text, location, size, rotation, shown, Altium's measured box), and the free... | `altium_silk_state` |  | `fusion_silk_state` |+| `swap_footprint` | Replace the FIRST component on the current board with a footprint from a PcbLib at the same position, re-assigning nets by pad designator. Tracks are... | `altium_swap_footprint` | `kicad_update_footprints_from_library` (partial) |  |+| `symbol_prims` | Read a SchLib component's drawing: primitive counts by kind, body rectangle, polyline bounding box, display mode and the footprint models. Read-only, use it... | `altium_symbol_prims` |  |  |+| `xcopy_footprint` | Copy a footprint ACROSS libraries: from fromLib into toLib (opened and made current), optionally under a new name. | `altium_xcopy_footprint` |  |  |  ## native  Wraps the EDA tool's own feature (its DRC, ERC, Gerbers, pours, Update PCB). Every tool has one; the bridge exposes it under this name. -| Verb | What it does | KiCad | Fusion 360 |-|---|---|---|---|-| `add_rule` | Add one SCOPED design rule that set_design_rules' board-wide values cannot express: a net's or class's clearance or width, a length limit, a matched-length... | `kicad_add_rule` |  |-| `annotate` | Number every '?' designator (R?, C?, U?) across the project's sheets: the lowest free number per prefix, top-left first on each sheet. dryRun shows the plan. | `kicad_annotate` |  |-| `apply_pours` | Add solid polygon pours from outlines and pour them, each with its own connect style (solid joints or thermal spokes), plus pour keepouts (polygon cutouts);... | `kicad_add_zone / kicad_apply_zone_plan` | `fusion_apply_pours` |-| `autoroute` | Altium's own autorouter (Situs) on the current board: picks a strategy, keeps existing routing locked by default, routes, and answers the unconnected count... | `kicad_autoroute` | `fusion_autoroute` |-| `build_symbol_modes` | Build ONE SchLib component with N display modes (Normal + Alternate 1..N-1) from a symbol_modes spec file on this machine, and return a proof frame. |  |  |-| `cleanup_libs` | Remove the factory-default stray every fresh library carries: Component_1 from the current SchLib and an empty (no pads) PCBComponent_1 from the current PcbLib. |  |  |-| `compile` | Compile a project and return Altium's Messages panel (ERC + connectivity) with counts by class. With no path it compiles Altium's bundled example project. |  |  |-| `component_classes` | List, make or remove component classes on the board, each optionally with a room: a placement area that keeps its parts together (fitted around the parts or... |  |  |-| `diff_pairs` | Differential pairs on the current board: list them, define one from two nets (replacing a pair of that name), or remove one. Altium's differential-pair... |  |  |-| `export_bom` | Bill of materials export: altium_run_outjob with the assembly OutJob and the 'Folder Structure' medium as defaults. | `kicad_export_bom_csv` (partial) | `fusion_export_bom` |-| `export_gerber` | Gerber/drill export: altium_run_outjob with the fabrication OutJob and the 'Folder Structure' medium as defaults. | `kicad_export_gerber` | `fusion_export_gerber` |-| `export_manufacturing` | A project's manufacturing set in one call: Gerbers, NC drill, pick and place (CSV, mm) and the BOM, from an OutJob the bridge writes beside the project... | `kicad_export_manufacturing` | `fusion_export_gerbers / fusion_export_cpl / fusion_export_bom` (partial) |-| `export_pdf` | Every sheet of a project as one PDF, plus on request the board's composite print, Altium's assembly drawings (top and bottom, designators on the parts) and... | `kicad_export_pdf` |  |-| `export_step` | Headless STEP export of a board. Default lane 'outjob': Altium's own ExportSTEP output run from a throwaway project in %TEMP% that points at the board - no... | `kicad_export_step` | `fusion_export_step` |-| `install_library` | Register a library file in Altium's Installed Libraries (IntegratedLibraryManager.InstallLibrary) so its parts appear in the Components panel. | `kicad_install_library` |  |-| `install_library_bundle` | One-click install of a wiki library bundle (zip of .SchLib/.PcbLib): unpack, register, open the library, prove it with a frame. | `kicad_install_library_bundle` | `fusion_install_library_bundle` |-| `list_installed_libraries` | Every library in Altium's Installed Libraries list (read-only). |  |  |-| `net_classes` | Net classes on the current board: list them with their nets, or make one (replacing a class of that name) with an optional width and clearance rule scoped... | `kicad_net_classes` | `fusion_net_classes` |-| `netlist` | The compiled netlist of a project: every net with its pins (Designator.Pin) across every sheet, the hierarchy resolved; or one net; or compare with the nets... | `kicad_netlist` | `fusion_netlist` |-| `panelize` | Step and repeat a board into a manufacturing panel: a new .PcbDoc holding Altium's own embedded board array of the board (rows x cols), with rails, the... |  |  |-| `pcb_report` | Numbers instead of pixels: for a PcbLib, every footprint's pads, pad bounding box, primitive census and 3D bodies; for a board, outline, components with... | `kicad_errors` (partial) |  |-| `pour_state` | Every polygon pour with the copper it actually poured: filled area per pour and per layer, and the pours that poured nothing. | `kicad_pour_state` | `fusion_pour_state` |-| `remove_pours` | Delete polygon pours by net (and layer), or all of them, and the pour keepouts (cutouts) apply_pours made. Tracks and vias are untouched. | `kicad_remove_zone` | `fusion_remove_pours` |-| `replicate_layout` | Copy one channel's placement to matching channels: each target keeps its anchor part where it is and every other part takes the source's offset and rotation... |  |  |-| `repour` | Repour every polygon on the board (Altium's Repour All) and answer the copper after. Runs outside the script engine so scoped rules apply. | `kicad_repour` | `fusion_repour` |-| `routing_drc` | Design-rule violations on the current board WITH locations, plus the unrouted (ratsnest) count, as one clean/not-clean answer. | `kicad_routing_validate` (partial) | `fusion_routing_drc` |-| `run_drc` | Run the design rule check on a board and read the violation markers back. PCB:DesignRuleCheck opens a MODAL; the bridge clicks 'Run Design Rule Check'... | `kicad_run_drc` | `fusion_run_drc` |-| `run_erc` | Electrical rules check. Same handler as altium_compile: in Altium, compiling the project IS the ERC. | `kicad_run_erc` | `fusion_run_erc` |-| `set_design_rules` | Write a fab's design rules into the current board: clearance, track width, routing via style, hole size, annular ring, hole-to-hole and board-edge clearance... | `kicad_set_design_rules` | `fusion_set_design_rules` |-| `silkscreen_prep` | Clean the silkscreen off the copper with Altium's own Tools > Silkscreen Preparation: silk clipped clear of every mask opening (pad) by the board's silk... |  |  |-| `symbol_mode` | Show one display mode (0 = Normal, 1.. = alternates) of the CURRENT SchLib component in the editor and capture a frame. Drives the editor's own mode toggle,... |  |  |-| `teardrops` | Add (or remove) teardrops with Altium's own Tools > Teardrops: on vias and through-hole pads, SMD pads, track width changes and T-junctions, for the whole... |  |  |-| `uninstall_library` | Remove libraries from Altium's Installed Libraries: the inverse of install_library / install_library_bundle. Library files are never touched. | `kicad_uninstall_library` |  |-| `update_pcb` | Design > Update PCB Document from the schematic (the engineering change order): parts added, removed or renamed, nets and footprints updated on the board.... | `kicad_update_pcb` |  |+| Verb | What it does | Altium | KiCad | Fusion 360 |+|---|---|---|---|---|+| `add_rule` | Add one SCOPED design rule that set_design_rules' board-wide values cannot express: a net's or class's clearance or width, a length limit, a matched-length... | `altium_add_rule` | `kicad_add_rule` |  |+| `annotate` | Number every '?' designator (R?, C?, U?) across the project's sheets: the lowest free number per prefix, top-left first on each sheet. dryRun shows the plan. | `altium_annotate` | `kicad_annotate` |  |+| `apply_pours` | Add solid polygon pours from outlines and pour them, each with its own connect style (solid joints or thermal spokes), plus pour keepouts (polygon cutouts);... | `altium_apply_pours` | `kicad_add_zone / kicad_apply_zone_plan` | `fusion_apply_pours` |+| `autoroute` | Altium's own autorouter (Situs) on the current board: picks a strategy, keeps existing routing locked by default, routes, and answers the unconnected count... | `altium_autoroute` | `kicad_autoroute` | `fusion_autoroute` |+| `build_symbol_modes` | Build ONE SchLib component with N display modes (Normal + Alternate 1..N-1) from a symbol_modes spec file on this machine, and return a proof frame. | `altium_build_symbol_modes` |  |  |+| `cleanup_libs` | Remove the factory-default stray every fresh library carries: Component_1 from the current SchLib and an empty (no pads) PCBComponent_1 from the current PcbLib. | `altium_cleanup_libs` |  |  |+| `compile` | Compile a project and return Altium's Messages panel (ERC + connectivity) with counts by class. With no path it compiles Altium's bundled example project. | `altium_compile` |  |  |+| `component_classes` | List, make or remove component classes on the board, each optionally with a room: a placement area that keeps its parts together (fitted around the parts or... | `altium_component_classes` |  |  |+| `diff_pairs` | Differential pairs on the current board: list them, define one from two nets (replacing a pair of that name), or remove one. Altium's differential-pair... | `altium_diff_pairs` |  |  |+| `export_bom` | Bill of materials export: altium_run_outjob with the assembly OutJob and the 'Folder Structure' medium as defaults. | `altium_export_bom` | `kicad_export_bom_csv` (partial) | `fusion_export_bom` |+| `export_gerber` | Gerber/drill export: altium_run_outjob with the fabrication OutJob and the 'Folder Structure' medium as defaults. | `altium_export_gerber` | `kicad_export_gerber` | `fusion_export_gerber` |+| `export_manufacturing` | A project's manufacturing set in one call: Gerbers, NC drill, pick and place (CSV, mm) and the BOM, from an OutJob the bridge writes beside the project... | `altium_export_manufacturing` | `kicad_export_manufacturing` | `fusion_export_gerbers / fusion_export_cpl / fusion_export_bom` (partial) |+| `export_pdf` | Every sheet of a project as one PDF, plus on request the board's composite print, Altium's assembly drawings (top and bottom, designators on the parts) and... | `altium_export_pdf` | `kicad_export_pdf` |  |+| `export_step` | Headless STEP export of a board. Default lane 'outjob': Altium's own ExportSTEP output run from a throwaway project in %TEMP% that points at the board - no... | `altium_export_step` | `kicad_export_step` | `fusion_export_step` |+| `install_library` | Register a library file in Altium's Installed Libraries (IntegratedLibraryManager.InstallLibrary) so its parts appear in the Components panel. | `altium_install_library` | `kicad_install_library` |  |+| `install_library_bundle` | One-click install of a wiki library bundle (zip of .SchLib/.PcbLib): unpack, register, open the library, prove it with a frame. | `altium_install_library_bundle` | `kicad_install_library_bundle` | `fusion_install_library_bundle` |+| `list_installed_libraries` | Every library in Altium's Installed Libraries list (read-only). | `altium_list_installed_libraries` |  |  |+| `net_classes` | Net classes on the current board: list them with their nets, or make one (replacing a class of that name) with an optional width and clearance rule scoped... | `altium_net_classes` | `kicad_net_classes` | `fusion_net_classes` |+| `netlist` | The compiled netlist of a project: every net with its pins (Designator.Pin) across every sheet, the hierarchy resolved; or one net; or compare with the nets... | `altium_netlist` | `kicad_netlist` | `fusion_netlist` |+| `panelize` | Step and repeat a board into a manufacturing panel: a new .PcbDoc holding Altium's own embedded board array of the board (rows x cols), with rails, the... | `altium_panelize` |  |  |+| `pcb_report` | Numbers instead of pixels: for a PcbLib, every footprint's pads, pad bounding box, primitive census and 3D bodies; for a board, outline, components with... | `altium_pcb_report` | `kicad_errors` (partial) |  |+| `pour_state` | Every polygon pour with the copper it actually poured: filled area per pour and per layer, and the pours that poured nothing. | `altium_pour_state` | `kicad_pour_state` | `fusion_pour_state` |+| `remove_pours` | Delete polygon pours by net (and layer), or all of them, and the pour keepouts (cutouts) apply_pours made. Tracks and vias are untouched. | `altium_remove_pours` | `kicad_remove_zone` | `fusion_remove_pours` |+| `render_schematic` *proposed* | Render a sheet to an image without opening a window, through the tool's own plotter, and keep visual baselines: baseline set stores the image, baseline... |  | `kicad_render_schematic` |  |+| `replicate_layout` | Copy one channel's placement to matching channels: each target keeps its anchor part where it is and every other part takes the source's offset and rotation... | `altium_replicate_layout` |  |  |+| `repour` | Repour every polygon on the board (Altium's Repour All) and answer the copper after. Runs outside the script engine so scoped rules apply. | `altium_repour` | `kicad_repour` | `fusion_repour` |+| `routing_drc` | Design-rule violations on the current board WITH locations, plus the unrouted (ratsnest) count, as one clean/not-clean answer. | `altium_routing_drc` | `kicad_routing_validate` (partial) | `fusion_routing_drc` |+| `run_drc` | Run the design rule check on a board and read the violation markers back. PCB:DesignRuleCheck opens a MODAL; the bridge clicks 'Run Design Rule Check'... | `altium_run_drc` | `kicad_run_drc` | `fusion_run_drc` |+| `run_erc` | Electrical rules check. Same handler as altium_compile: in Altium, compiling the project IS the ERC. | `altium_run_erc` | `kicad_run_erc` | `fusion_run_erc` |+| `sch_update_from_library` *proposed* | Update the placed symbols on a sheet from their libraries (all, or the listed ones) and report which changed, which already matched and which no library has. |  | `kicad_sch_update_from_library` |  |+| `set_design_rules` | Write a fab's design rules into the current board: clearance, track width, routing via style, hole size, annular ring, hole-to-hole and board-edge clearance... | `altium_set_design_rules` | `kicad_set_design_rules` | `fusion_set_design_rules` |+| `silkscreen_prep` | Clean the silkscreen off the copper with Altium's own Tools > Silkscreen Preparation: silk clipped clear of every mask opening (pad) by the board's silk... | `altium_silkscreen_prep` |  |  |+| `symbol_mode` | Show one display mode (0 = Normal, 1.. = alternates) of the CURRENT SchLib component in the editor and capture a frame. Drives the editor's own mode toggle,... | `altium_symbol_mode` |  |  |+| `teardrops` | Add (or remove) teardrops with Altium's own Tools > Teardrops: on vias and through-hole pads, SMD pads, track width changes and T-junctions, for the whole... | `altium_teardrops` |  |  |+| `uninstall_library` | Remove libraries from Altium's Installed Libraries: the inverse of install_library / install_library_bundle. Library files are never touched. | `altium_uninstall_library` | `kicad_uninstall_library` |  |+| `update_pcb` | Design > Update PCB Document from the schematic (the engineering change order): parts added, removed or renamed, nets and footprints updated on the board.... | `altium_update_pcb` | `kicad_update_pcb` |  |  ## checks  Engineering computed from the board model, not by the tool: one shared engine, so every bridge that serves the model gets them all. -| Verb | What it does | KiCad | Fusion 360 |-|---|---|---|---|-| `assembly_check` | Ready for JLCPCB assembly? The board against both JLCPCB PCBA tiers as published (Economic and Standard): board or panel size, thickness and layers, parts... |  |  |-| `auto_classes` | Net classes from the nets' own names: GND, Power (VCC, VDD, 3V3, VBAT...), Clock, HighSpeed (USB, Ethernet, HDMI, PCIe, DDR, MIPI, LVDS, SATA...) and the... |  |  |-| `board_features` | Add the furniture every real board needs in one undo step: mounting holes (at points or the four corners), fiducials, keepout areas, and a stitching-via... | `kicad_add_mounting_hole` (partial) |  |-| `board_report` | One shareable page per board: every check run against the live board and its project (Altium's DRC, JLCPCB fab limits and assembly tiers, the schematic... |  |  |-| `bom` | The project's bill of materials read straight from Altium: every schematic sheet the .PrjPcb lists (placed parts and their parameters) merged with the board... |  | `fusion_board_bom` (partial) |-| `build_board` | Build a NEW board from a parts list and a netlist: outline (rounded corners allowed), every footprint from one PcbLib placed by its own origin, pad nets... |  |  |-| `build_footprint` | Build a complete footprint (pads, silkscreen, courtyard, arcs) in a PcbLib from a kicad2altium spec file on this machine, and return a proof frame. |  |  |-| `build_schematic` | Draw a design's schematic from its netlist with the project library's symbols, inside a new project (.PrjPcb with the board and libraries), compile it, and... |  | `fusion_schematic_plan / fusion_schematic_run` (partial) |-| `check_orientation` | Advisory: 2-pad parts whose rotation could be better. Each orthogonal rotation is scored in place by airline length (a routable net's MST with the pad... |  |  |-| `copper_balance` | How much of each copper layer is copper (tracks, pads, vias and what Altium actually poured, inside the outline; a plane counts full), and how far apart... |  |  |-| `cross_check` | Compare one schematic sheet's designators with a board's. Altium holds ONE current document, so the verb activates the board, reads it, then activates the... | `kicad_analyze_connections` (partial) |  |-| `current_capacity` | Will this trace carry the current? For each power net and its current: the narrowest track on every layer it is routed on against the width IPC-2221 needs... |  |  |-| `fab_check` | Before ordering: the board's fab-relevant minimums measured from the live board (narrowest track, smallest via drill, diameter and annular ring, smallest... | `kicad_fab_check` |  |-| `find_space` | Free spots on the board for a part near another (clear of every other part on that side, of that side's tracks and vias, and inside the outline), nearest... |  |  |-| `footprint_from_land_pattern` | Build a complete footprint from the land pattern a datasheet prints: pads numbered the standard way (chip, dual SOIC/TSSOP/DFN, SOT, quad QFP/QFN, BGA), an... |  |  |-| `height_check` | Will it fit the enclosure? Each part's height from its 3D bodies (top and bottom side), the parts over a height limit board-wide or under a lid feature in a... |  |  |-| `impedance` | Controlled impedance from the board's own stack-up: the track width each copper layer needs for a single-ended target (50 ohm default) and the width and gap... |  |  |-| `import_part` | One call imports a whole part: footprint spec + STEP + symbol modes + models + params + save. |  |  |-| `jlcpcb_order` | A JLCPCB order in one call: the board checked against JLCPCB's fab limits, the Gerbers and drill zipped the way JLCPCB's order page takes them, the JLCPCB... |  |  |-| `length_tune` | Lengthen a routed net to a target length, or to match another net (a pair's skew, a DDR byte lane): a serpentine in its longest straight track that has room... |  |  |-| `net_lengths` | Routed length of every net (or the ones named) on the live board, by layer with its vias; the skew inside each differential pair; and the spread of... |  |  |-| `pin_pad_check` | Do the footprints fit their symbols? Part by part, the symbol's pin numbers (from the sheet files) against the footprint's pad names (from the board): pins... |  |  |-| `placement_check` | Review the placement before routing: parts whose courtyards (pads and body, grown by a margin) overlap on the same side, parts off the board or over its... | `kicad_placement_validate` (partial) |  |-| `read_sheet_file` | Read a schematic sheet straight from its .SchDoc file, without Altium (it need not be installed or running): every part with its designator, library... |  | `fusion_read_sheet_file` |-| `return_path` | Where signal tracks lose their reference: for every signal net, the length of track on each layer that runs over no pour or plane copper on either... |  |  |-| `review_board` | Design-review checks (14) over one board read; schematic checks with includeSchematic. | `kicad_lint_board` (partial) |  |-| `route_pair` | Route a differential pair as a pair: one centreline from the source pads' midpoint through waypoints to the destination pads' midpoint, each net offset to... | `kicad_route_pair` |  |-| `schematic_review` | Review the schematic before Update PCB: every placed pin (read from the sheet files, with its electrical type) against Altium's compiled netlist. Errors:... | `kicad_sch_check / kicad_design_review / kicad_lint_schematic` (partial) |  |-| `silk_designators` | Place every reference designator the way assembly houses want: one size, upright, beside its own part, clear of every pad (JLCPCB: 0.15 mm), every other... |  |  |-| `test_board` | Place one footprint, or a ';' list, from the open PcbLib on ONE board: a NEW board (wMm x hMm outline) when pcbPath is new or omitted, APPENDED to the... |  |  |-| `thermal_vias` | A thermal via grid in a part's exposed pad (the ground or thermal pad under a QFN, DFN, PowerPAD or regulator): centred, inset from the pad's edge, sized by... |  |  |-| `via_fence` | A via fence for EMC: a row of ground vias on both sides of RF or fast nets' tracks, and/or round the board edge, at a pitch from the frequency (lambda/20)... |  |  |+| Verb | What it does | Altium | KiCad | Fusion 360 |+|---|---|---|---|---|+| `assembly_check` | Ready for JLCPCB assembly? The board against both JLCPCB PCBA tiers as published (Economic and Standard): board or panel size, thickness and layers, parts... | `altium_assembly_check` |  |  |+| `auto_classes` | Net classes from the nets' own names: GND, Power (VCC, VDD, 3V3, VBAT...), Clock, HighSpeed (USB, Ethernet, HDMI, PCIe, DDR, MIPI, LVDS, SATA...) and the... | `altium_auto_classes` |  |  |+| `board_features` | Add the furniture every real board needs in one undo step: mounting holes (at points or the four corners), fiducials, keepout areas, and a stitching-via... | `altium_board_features` | `kicad_add_mounting_hole` (partial) |  |+| `board_report` | One shareable page per board: every check run against the live board and its project (Altium's DRC, JLCPCB fab limits and assembly tiers, the schematic... | `altium_board_report` |  |  |+| `bom` | The project's bill of materials read straight from Altium: every schematic sheet the .PrjPcb lists (placed parts and their parameters) merged with the board... | `altium_bom` |  | `fusion_board_bom` (partial) |+| `build_board` | Build a NEW board from a parts list and a netlist: outline (rounded corners allowed), every footprint from one PcbLib placed by its own origin, pad nets... | `altium_build_board` |  |  |+| `build_footprint` | Build a complete footprint (pads, silkscreen, courtyard, arcs) in a PcbLib from a kicad2altium spec file on this machine, and return a proof frame. | `altium_build_footprint` |  |  |+| `build_schematic` | Draw a design's schematic from its netlist with the project library's symbols, inside a new project (.PrjPcb with the board and libraries), compile it, and... | `altium_build_schematic` |  | `fusion_schematic_plan / fusion_schematic_run` (partial) |+| `check_orientation` | Advisory: 2-pad parts whose rotation could be better. Each orthogonal rotation is scored in place by airline length (a routable net's MST with the pad... | `altium_check_orientation` |  |  |+| `copper_balance` | How much of each copper layer is copper (tracks, pads, vias and what Altium actually poured, inside the outline; a plane counts full), and how far apart... | `altium_copper_balance` |  |  |+| `cross_check` | Compare one schematic sheet's designators with a board's. Altium holds ONE current document, so the verb activates the board, reads it, then activates the... | `altium_cross_check` | `kicad_analyze_connections` (partial) |  |+| `current_capacity` | Will this trace carry the current? For each power net and its current: the narrowest track on every layer it is routed on against the width IPC-2221 needs... | `altium_current_capacity` |  |  |+| `fab_check` | Before ordering: the board's fab-relevant minimums measured from the live board (narrowest track, smallest via drill, diameter and annular ring, smallest... | `altium_fab_check` | `kicad_fab_check` |  |+| `find_space` | Free spots on the board for a part near another (clear of every other part on that side, of that side's tracks and vias, and inside the outline), nearest... | `altium_find_space` |  |  |+| `footprint_from_land_pattern` | Build a complete footprint from the land pattern a datasheet prints: pads numbered the standard way (chip, dual SOIC/TSSOP/DFN, SOT, quad QFP/QFN, BGA), an... | `altium_footprint_from_land_pattern` |  |  |+| `height_check` | Will it fit the enclosure? Each part's height from its 3D bodies (top and bottom side), the parts over a height limit board-wide or under a lid feature in a... | `altium_height_check` |  |  |+| `impedance` | Controlled impedance from the board's own stack-up: the track width each copper layer needs for a single-ended target (50 ohm default) and the width and gap... | `altium_impedance` |  |  |+| `import_part` | One call imports a whole part: footprint spec + STEP + symbol modes + models + params + save. | `altium_import_part` |  |  |+| `jlcpcb_order` | A JLCPCB order in one call: the board checked against JLCPCB's fab limits, the Gerbers and drill zipped the way JLCPCB's order page takes them, the JLCPCB... | `altium_jlcpcb_order` |  |  |+| `length_tune` | Lengthen a routed net to a target length, or to match another net (a pair's skew, a DDR byte lane): a serpentine in its longest straight track that has room... | `altium_length_tune` |  |  |+| `net_lengths` | Routed length of every net (or the ones named) on the live board, by layer with its vias; the skew inside each differential pair; and the spread of... | `altium_net_lengths` |  |  |+| `pin_pad_check` | Do the footprints fit their symbols? Part by part, the symbol's pin numbers (from the sheet files) against the footprint's pad names (from the board): pins... | `altium_pin_pad_check` |  |  |+| `placement_check` | Review the placement before routing: parts whose courtyards (pads and body, grown by a margin) overlap on the same side, parts off the board or over its... | `altium_placement_check` | `kicad_placement_validate` (partial) |  |+| `read_sheet_file` | Read a schematic sheet straight from its .SchDoc file, without Altium (it need not be installed or running): every part with its designator, library... | `altium_read_sheet_file` |  | `fusion_read_sheet_file` |+| `return_path` | Where signal tracks lose their reference: for every signal net, the length of track on each layer that runs over no pour or plane copper on either... | `altium_return_path` |  |  |+| `review_board` | Design-review checks (14) over one board read; schematic checks with includeSchematic. | `altium_review_board` | `kicad_lint_board` (partial) |  |+| `route_pair` | Route a differential pair as a pair: one centreline from the source pads' midpoint through waypoints to the destination pads' midpoint, each net offset to... | `altium_route_pair` | `kicad_route_pair` |  |+| `schematic_review` | Review the schematic before Update PCB: every placed pin (read from the sheet files, with its electrical type) against Altium's compiled netlist. Errors:... | `altium_schematic_review` | `kicad_sch_check / kicad_design_review / kicad_lint_schematic` (partial) |  |+| `silk_designators` | Place every reference designator the way assembly houses want: one size, upright, beside its own part, clear of every pad (JLCPCB: 0.15 mm), every other... | `altium_silk_designators` |  |  |+| `test_board` | Place one footprint, or a ';' list, from the open PcbLib on ONE board: a NEW board (wMm x hMm outline) when pcbPath is new or omitted, APPENDED to the... | `altium_test_board` |  |  |+| `thermal_vias` | A thermal via grid in a part's exposed pad (the ground or thermal pad under a QFN, DFN, PowerPAD or regulator): centred, inset from the pad's edge, sized by... | `altium_thermal_vias` |  |  |+| `via_fence` | A via fence for EMC: a row of ground vias on both sides of RF or fast nets' tracks, and/or round the board edge, at a pitch from the frequency (lambda/20)... | `altium_via_fence` |  |  |  ## app  Driving the application itself (launch, licence, dialogs, windows, views). Each bridge has its own; the names are shared where the job is. -| Verb | What it does | KiCad | Fusion 360 |-|---|---|---|---|-| `activate_document` | Make a document current - the quiet lane (one in-process agent call, no cursor, no OS foreground). Board and schematic read verbs act on the CURRENT document. |  | `fusion_activate_document` |-| `agent_recover` | Un-halt the script engine: clear the PCB transaction, press OK on open Altium dialogs, send EditScript:Stop, reap the busy notice and delete stale request... |  |  |-| `agent_start` | Bootstrap the resident DelphiScript agent inside Altium (renders the script, runs it through the -R lane, waits for the heartbeat). Optional: every... |  |  |-| `agent_status` | Is the agent loop alive and responsive, in which workspace, and is any loop resident anywhere? Read-only; never starts the agent. |  |  |-| `agent_stop` | Stop the selected instance's resident agent loop (drops a stop file and waits up to 12 s for the heartbeat to go stale). |  |  |-| `animate_view` | Camera/zoom choreography on the current document - native Altium camera commands, animated by Altium itself. |  |  |-| `check_dialogs` | List every Altium dialog currently open, classified, each with a screenshot (the only way to READ one: Altium paints its dialog text). |  | `fusion_check_dialogs` |-| `close` | Polite close (releases the licence seat). Frees a script engine parked on a breakpoint first (Altium refuses to close over one). discardChanges:true answers... | `kicad_close` | `fusion_stop` |-| `close_document` | Close ONE open document by path through its document handle. Never saves. |  | `fusion_close_document` |-| `connect_workspace` | Open Altium's workspace picker (the 'Not Connected' menu) and return a screenshot with a coordMap. The list is a custom control with no UIA children, so the... |  |  |-| `demo` | The tour. Default: one background beat per call with a screenshot. live:true = the narrated FOREGROUND show: ab caption + document + in-bridge camera... | `kicad_demo` | `fusion_demo` |-| `describe` | This list - the bridge's verbs and schemas for ab's Verbs tab. | `kicad_describe` | `fusion_describe` |-| `diagnostics` | Bridge-side facts for a bug report: environment variables, every Altium install found, Altium's windows, the agent status block and the cache directory. | `kicad_diagnostics` |  |-| `dialog_log` | What the standing dialog reaper (and the bridge's own recoveries) pressed, newest last: nuisance boxes, script-error boxes, discarded save prompts, silent... |  | `fusion_dialog_log` |-| `dismiss_dialogs` | Press one named button (default OK) on the detected Altium dialogs through UIA - no cursor, no focus steal. titles narrows it to dialogs whose title... | `kicad_dismiss_dialogs` | `fusion_dismiss_dialogs` |-| `ensure_licensed` | One call to get a usable Altium: launch if needed, then claim a seat (Use License via UIA). Optional escalations: sign out to force a seat release, or start... |  |  |-| `eval` | Run a DelphiScript snippet inside Altium (optional Var block, then Begin ... End;) on the CURRENT document, or on filePath opened first. |  |  |-| `extension_ping` | Does the AdomBridge .NET extension answer? Sends AdomBridge:Ping through the -R lane and waits up to 30 s for its result file. |  |  |-| `foreground` | Bring Altium in front of the user - the sanctioned exception to the never-foreground rule. |  |  |-| `install` | Install Altium Designer on this machine, STAGED, with the rules in the verb (from 0.2.29). stage: preflight / get_installer / launch / wait / license, or... |  | `fusion_install` |-| `install_extension` | Install, update or remove the AdomBridge .NET extension (the PowerShell installer shipped beside the bridge). Altium must be CLOSED. |  |  |-| `install_receipt` | The last bundle install's full receipt (proof frame included), for a client whose install call outlived ab's budget. |  |  |-| `instances` | Every running Altium (Designer + Designer Develop can run together). |  |  |-| `launch` | Start Altium (the newest numbered install, or the one install names) and wait for its main window, then hand the user's own window back. Answers... | `kicad_launch` | `fusion_launch` |-| `license` | Drive the License Management page (UIA first - no cursor, no foreground). |  |  |-| `license_status` | Plain-language answer to 'what Altium licence am I on?': the state from the window title plus a capture of the License Management page. |  | `fusion_license_status` |-| `list_commands` | Search Altium's process-launcher catalog (about 1,100 Server:Command entries parsed from the install's System/*.rcs files) by text and/or server. |  | `fusion_list_commands` |-| `open_document` | Open a document or project by path through the agent and show it without focusing it. An already-open document is activated, not reloaded. | `kicad_open_board / kicad_open_schematic` (partial) | `fusion_open_document` |-| `open_project` | Open a project (.PrjPcb / .PrjScr / .PrjMbd / .PrjHar / .LibPkg) by path. Same handler as altium_open_document. |  |  |-| `panel` | Activate a docked panel TAB (SCH Library, PCB Library, Components, Projects, Properties) in the BACKGROUND - the 'ganged-up view' needs the right panels in... |  |  |-| `progress` | The bridge's timing book: phases in flight right now (percent/ETA blocks ab paints on the taskbar), measured phase history and per-verb run statistics. | `kicad_progress` |  |-| `readiness` | The one-call gate: is Altium installed, running, licensed, and is the resident agent alive? Answers with Altium closed and never touches the script engine. | `kicad_readiness` | `fusion_readiness` |-| `run_command` | Run an Altium process (Server:Command) through the agent, on the CURRENT document or on filePath opened first. |  | `fusion_run_command` |-| `run_script` | One shot: run a procedure of YOUR OWN .PrjScr through Altium's -R command line. Only for when the agent is NOT resident. |  | `fusion_run_script` |-| `save` | Save the focused document, or open filePath first and save that (WorkspaceManager:SaveObject on the focused document). | `kicad_save` | `fusion_save` |-| `sch_zoom` | Find parts on a sheet: select them (everything else deselected), frame the view on them and return a proof frame. The schematic half of cross-probing (the... |  |  |-| `select_net` | Select one net as a whole on the current board (tracks, arcs, vias, pads, pours) and nothing else, optionally framing it; no net clears the selection. | `kicad_select_net` | `fusion_select_net` |-| `selection` | What the user has selected in the current board (components with position mm, rotation, side, footprint, size) or sheet (components with location mils and... | `kicad_selection` |  |-| `selftest_script_error` | Regression test for the script-error safety net (from 0.2.23): makes the agent raise a REAL DelphiScript runtime error on purpose and checks that the bridge... |  |  |-| `set_layer_visibility` | Show or hide one layer of the current board (by layer id) and refresh the view and the layer tabs. |  | `fusion_set_layer_visibility` |-| `setup_trial` | Onboarding state machine: from nothing to a working trial. Each call reports the stage it found (install / launch / signin / done) and the ONE next action;... |  |  |-| `show_2d_board` | Open a .PcbDoc, switch to 2D, zoom to fit, and return a proof frame. With no filePath it opens the bundled Bluetooth Sentinel board. | `kicad_show_2d_board` | `fusion_show_2d_board` |-| `show_3d_board` | Open a .PcbDoc, switch to 3D, zoom to fit, and return a proof frame. With no filePath it opens the bundled Bluetooth Sentinel board. | `kicad_show_3d_board` | `fusion_show_3d_board` |-| `show_3d_chip` | Open a PcbLib member in the footprint editor in 3D, zoom to fit, and capture a proof frame of the part's 3D body. | `kicad_show_3d_chip` | `fusion_show_3d_chip` |-| `show_footprint` | Open a PcbLib member in the footprint editor in 2D, zoom to fit, and capture a proof frame. | `kicad_show_footprint` | `fusion_show_footprint` |-| `show_library` | Open a .SchLib or .PcbLib (kind taken from the extension), select its first component, return a proof frame and the component names. | `kicad_show_library` | `fusion_show_library` |-| `show_project` | Open a project (.PrjPcb) through the agent and return a proof frame of Altium's main window. With no filePath it opens Altium's bundled example project... | `kicad_show_project` | `fusion_show_project` |-| `show_schematic` | Open a .SchDoc, zoom to fit, and return a proof frame. With no filePath it opens the bundled Bluetooth Sentinel top sheet. | `kicad_show_schematic` | `fusion_show_schematic` |-| `show_symbol` | Open a SchLib member in the Symbol editor and capture a background proof. | `kicad_show_symbol` | `fusion_show_symbol` |-| `signin` | Report-only alias of altium_signin_status: it does NOT sign anyone in. Signing in to Altium is a browser flow only the human can complete. |  | `fusion_signin` |-| `signin_status` | Account and Altium 365 workspace connection as Altium's own UI reports it: licence state from the title, and whether the workspace menu reads 'Not Connected'. |  | `fusion_signin_status` |-| `state` | The whole picture in one call: licence state, windows, dialogs, a screenshot of every main/dialog window, and the agent's logical state (focused document,... | `kicad_state` | `fusion_state` |-| `status` | Is Altium running, licensed, and is the resident agent alive? | `kicad_status` | `fusion_status` |-| `uninstall` | Remove the bridge's own cache directory (agent workspaces, rendered agent scripts, the Altium 365 token file). Altium Designer and the user's designs are... | `kicad_uninstall` | `fusion_uninstall` |-| `window_info` | Altium's top-level windows plus any open dialogs, without screenshots. The cheap way to ask 'is a modal blocking the engine?'. | `kicad_window_info` |  |-| `zoom_to` | Frame the PCB view on a rectangle, a part (or several) or a whole net, with a margin. |  | `fusion_zoom_to` |+| Verb | What it does | Altium | KiCad | Fusion 360 |+|---|---|---|---|---|+| `activate_document` | Make a document current - the quiet lane (one in-process agent call, no cursor, no OS foreground). Board and schematic read verbs act on the CURRENT document. | `altium_activate_document` |  | `fusion_activate_document` |+| `agent_recover` | Un-halt the script engine: clear the PCB transaction, press OK on open Altium dialogs, send EditScript:Stop, reap the busy notice and delete stale request... | `altium_agent_recover` |  |  |+| `agent_start` | Bootstrap the resident DelphiScript agent inside Altium (renders the script, runs it through the -R lane, waits for the heartbeat). Optional: every... | `altium_agent_start` |  |  |+| `agent_status` | Is the agent loop alive and responsive, in which workspace, and is any loop resident anywhere? Read-only; never starts the agent. | `altium_agent_status` |  |  |+| `agent_stop` | Stop the selected instance's resident agent loop (drops a stop file and waits up to 12 s for the heartbeat to go stale). | `altium_agent_stop` |  |  |+| `animate_view` | Camera/zoom choreography on the current document - native Altium camera commands, animated by Altium itself. | `altium_animate_view` |  |  |+| `check_dialogs` | List every Altium dialog currently open, classified, each with a screenshot (the only way to READ one: Altium paints its dialog text). | `altium_check_dialogs` |  | `fusion_check_dialogs` |+| `close` | Polite close (releases the licence seat). Frees a script engine parked on a breakpoint first (Altium refuses to close over one). discardChanges:true answers... | `altium_close` | `kicad_close` | `fusion_stop` |+| `close_document` | Close ONE open document by path through its document handle. Never saves. | `altium_close_document` |  | `fusion_close_document` |+| `connect_workspace` | Open Altium's workspace picker (the 'Not Connected' menu) and return a screenshot with a coordMap. The list is a custom control with no UIA children, so the... | `altium_connect_workspace` |  |  |+| `demo` | The tour. Default: one background beat per call with a screenshot. live:true = the narrated FOREGROUND show: ab caption + document + in-bridge camera... | `altium_demo` | `kicad_demo` | `fusion_demo` |+| `describe` | This list - the bridge's verbs and schemas for ab's Verbs tab. | `altium_describe` | `kicad_describe` | `fusion_describe` |+| `diagnostics` | Bridge-side facts for a bug report: environment variables, every Altium install found, Altium's windows, the agent status block and the cache directory. | `altium_diagnostics` | `kicad_diagnostics` |  |+| `dialog_log` | What the standing dialog reaper (and the bridge's own recoveries) pressed, newest last: nuisance boxes, script-error boxes, discarded save prompts, silent... | `altium_dialog_log` |  | `fusion_dialog_log` |+| `dismiss_dialogs` | Press one named button (default OK) on the detected Altium dialogs through UIA - no cursor, no focus steal. titles narrows it to dialogs whose title... | `altium_dismiss_dialogs` | `kicad_dismiss_dialogs` | `fusion_dismiss_dialogs` |+| `ensure_licensed` | One call to get a usable Altium: launch if needed, then claim a seat (Use License via UIA). Optional escalations: sign out to force a seat release, or start... | `altium_ensure_licensed` |  |  |+| `eval` | Run a DelphiScript snippet inside Altium (optional Var block, then Begin ... End;) on the CURRENT document, or on filePath opened first. | `altium_eval` |  |  |+| `extension_ping` | Does the AdomBridge .NET extension answer? Sends AdomBridge:Ping through the -R lane and waits up to 30 s for its result file. | `altium_extension_ping` |  |  |+| `foreground` | Bring Altium in front of the user - the sanctioned exception to the never-foreground rule. | `altium_foreground` |  |  |+| `install` | Install Altium Designer on this machine, STAGED, with the rules in the verb (from 0.2.29). stage: preflight / get_installer / launch / wait / license, or... | `altium_install` |  | `fusion_install` |+| `install_extension` | Install, update or remove the AdomBridge .NET extension (the PowerShell installer shipped beside the bridge). Altium must be CLOSED. | `altium_install_extension` |  |  |+| `install_receipt` | The last bundle install's full receipt (proof frame included), for a client whose install call outlived ab's budget. | `altium_install_receipt` |  |  |+| `instances` | Every running Altium (Designer + Designer Develop can run together). | `altium_instances` |  |  |+| `launch` | Start Altium (the newest numbered install, or the one install names) and wait for its main window, then hand the user's own window back. Answers... | `altium_launch` | `kicad_launch` | `fusion_launch` |+| `license` | Drive the License Management page (UIA first - no cursor, no foreground). | `altium_license` |  |  |+| `license_status` | Plain-language answer to 'what Altium licence am I on?': the state from the window title plus a capture of the License Management page. | `altium_license_status` |  | `fusion_license_status` |+| `list_commands` | Search Altium's process-launcher catalog (about 1,100 Server:Command entries parsed from the install's System/*.rcs files) by text and/or server. | `altium_list_commands` |  | `fusion_list_commands` |+| `open_document` | Open a document or project by path through the agent and show it without focusing it. An already-open document is activated, not reloaded. | `altium_open_document` | `kicad_open_board / kicad_open_schematic` (partial) | `fusion_open_document` |+| `open_project` | Open a project (.PrjPcb / .PrjScr / .PrjMbd / .PrjHar / .LibPkg) by path. Same handler as altium_open_document. | `altium_open_project` |  |  |+| `panel` | Activate a docked panel TAB (SCH Library, PCB Library, Components, Projects, Properties) in the BACKGROUND - the 'ganged-up view' needs the right panels in... | `altium_panel` |  |  |+| `progress` | The bridge's timing book: phases in flight right now (percent/ETA blocks ab paints on the taskbar), measured phase history and per-verb run statistics. | `altium_progress` | `kicad_progress` |  |+| `readiness` | The one-call gate: is Altium installed, running, licensed, and is the resident agent alive? Answers with Altium closed and never touches the script engine. | `altium_readiness` | `kicad_readiness` | `fusion_readiness` |+| `run_command` | Run an Altium process (Server:Command) through the agent, on the CURRENT document or on filePath opened first. | `altium_run_command` |  | `fusion_run_command` |+| `run_script` | One shot: run a procedure of YOUR OWN .PrjScr through Altium's -R command line. Only for when the agent is NOT resident. | `altium_run_script` |  | `fusion_run_script` |+| `save` | Save the focused document, or open filePath first and save that (WorkspaceManager:SaveObject on the focused document). | `altium_save` | `kicad_save` | `fusion_save` |+| `sch_zoom` | Find parts on a sheet: select them (everything else deselected), frame the view on them and return a proof frame. The schematic half of cross-probing (the... | `altium_sch_zoom` |  |  |+| `select_net` | Select one net as a whole on the current board (tracks, arcs, vias, pads, pours) and nothing else, optionally framing it; no net clears the selection. | `altium_select_net` | `kicad_select_net` | `fusion_select_net` |+| `selection` | What the user has selected in the current board (components with position mm, rotation, side, footprint, size) or sheet (components with location mils and... | `altium_selection` | `kicad_selection` |  |+| `selftest_script_error` | Regression test for the script-error safety net (from 0.2.23): makes the agent raise a REAL DelphiScript runtime error on purpose and checks that the bridge... | `altium_selftest_script_error` |  |  |+| `set_layer_visibility` | Show or hide one layer of the current board (by layer id) and refresh the view and the layer tabs. | `altium_set_layer_visibility` |  | `fusion_set_layer_visibility` |+| `setup_trial` | Onboarding state machine: from nothing to a working trial. Each call reports the stage it found (install / launch / signin / done) and the ONE next action;... | `altium_setup_trial` |  |  |+| `show_2d_board` | Open a .PcbDoc, switch to 2D, zoom to fit, and return a proof frame. With no filePath it opens the bundled Bluetooth Sentinel board. | `altium_show_2d_board` | `kicad_show_2d_board` | `fusion_show_2d_board` |+| `show_3d_board` | Open a .PcbDoc, switch to 3D, zoom to fit, and return a proof frame. With no filePath it opens the bundled Bluetooth Sentinel board. | `altium_show_3d_board` | `kicad_show_3d_board` | `fusion_show_3d_board` |+| `show_3d_chip` | Open a PcbLib member in the footprint editor in 3D, zoom to fit, and capture a proof frame of the part's 3D body. | `altium_show_3d_chip` | `kicad_show_3d_chip` | `fusion_show_3d_chip` |+| `show_footprint` | Open a PcbLib member in the footprint editor in 2D, zoom to fit, and capture a proof frame. | `altium_show_footprint` | `kicad_show_footprint` | `fusion_show_footprint` |+| `show_library` | Open a .SchLib or .PcbLib (kind taken from the extension), select its first component, return a proof frame and the component names. | `altium_show_library` | `kicad_show_library` | `fusion_show_library` |+| `show_project` | Open a project (.PrjPcb) through the agent and return a proof frame of Altium's main window. With no filePath it opens Altium's bundled example project... | `altium_show_project` | `kicad_show_project` | `fusion_show_project` |+| `show_schematic` | Open a .SchDoc, zoom to fit, and return a proof frame. With no filePath it opens the bundled Bluetooth Sentinel top sheet. | `altium_show_schematic` | `kicad_show_schematic` | `fusion_show_schematic` |+| `show_symbol` | Open a SchLib member in the Symbol editor and capture a background proof. | `altium_show_symbol` | `kicad_show_symbol` | `fusion_show_symbol` |+| `signin` | Report-only alias of altium_signin_status: it does NOT sign anyone in. Signing in to Altium is a browser flow only the human can complete. | `altium_signin` |  | `fusion_signin` |+| `signin_status` | Account and Altium 365 workspace connection as Altium's own UI reports it: licence state from the title, and whether the workspace menu reads 'Not Connected'. | `altium_signin_status` |  | `fusion_signin_status` |+| `state` | The whole picture in one call: licence state, windows, dialogs, a screenshot of every main/dialog window, and the agent's logical state (focused document,... | `altium_state` | `kicad_state` | `fusion_state` |+| `status` | Is Altium running, licensed, and is the resident agent alive? | `altium_status` | `kicad_status` | `fusion_status` |+| `uninstall` | Remove the bridge's own cache directory (agent workspaces, rendered agent scripts, the Altium 365 token file). Altium Designer and the user's designs are... | `altium_uninstall` | `kicad_uninstall` | `fusion_uninstall` |+| `window_info` | Altium's top-level windows plus any open dialogs, without screenshots. The cheap way to ask 'is a modal blocking the engine?'. | `altium_window_info` | `kicad_window_info` |  |+| `zoom_to` | Frame the PCB view on a rectangle, a part (or several) or a whole net, with a margin. | `altium_zoom_to` |  | `fusion_zoom_to` |  ## platform  Specific to one tool's platform (Altium 365, OutJobs, integrated libraries). Not part of the standard; listed so nothing is lost. -| Verb | What it does | KiCad | Fusion 360 |-|---|---|---|---|-| `a365_configure` | Store the Altium 365 workspace domain and, optionally, a Bearer token created by hand in the workspace web UI (Admin - Developer). Local-only; tokens never... |  |  |-| `a365_files_upload` | Upload one local file to the workspace's Files Service and get a temporary opaque file id to pass to a library mutation. |  |  |-| `a365_library_overview` | One fixed read-only query: the workspace library's name, description, update time, component ids/names and footprint/symbol totals. |  |  |-| `a365_library_schema` | Read-only schema map: the GraphQL queries and mutations whose names mention lib, component, symbol, footprint, part or datasheet, with mutation argument types. |  |  |-| `a365_logout` | Revoke the refresh grant at Altium and remove every cached OAuth token. Workspace and client id stay configured. |  |  |-| `a365_oauth_begin` | Start the Altium 365 OAuth (PKCE + ActionWait) sign-in: the bridge starts listening FIRST, then returns the authorize URL for the user's browser. Works with... |  |  |-| `a365_oauth_cancel` | Cancel a waiting OAuth flow. |  |  |-| `a365_oauth_status` | State of the OAuth flow started by altium_a365_oauth_begin: idle / waiting / authorized / cancelled / error. |  |  |-| `a365_query` | Run one GraphQL query or mutation against the workspace's GraphQL gateway (https://<workspace>/svc/napi/gateway/graphql/) with the stored token. |  |  |-| `a365_refresh` | Exchange the stored refresh token for a new access token (and store a rotated refresh token if one comes back). |  |  |-| `a365_status` | Is the Altium 365 lane configured, is there a token, and is it LIVE (probed with a one-row GraphQL query)? |  |  |-| `compile_intlib` | Compile a .LibPkg into an integrated library (.IntLib). |  |  |-| `extract_intlib` | Extract the editable .SchLib/.PcbLib sources from a compiled .IntLib (Altium writes them next to the IntLib and opens them). |  |  |-| `import_kicad` | Import a KiCad file with Altium's own KiCad importer, driven through the AdomBridge .NET extension. |  |  |-| `outjob_info` | An OutJob's containers (output media), the outputs in each, and their key settings (units, decimals, plotted layer count), read from the .OutJob file:... |  |  |-| `run_outjob` | Run one output medium of an .OutJob (gerbers, drill, BOM, PDFs...) and list what it wrote under 'Project Outputs for <project>'. |  |  |-| `variants` | Assembly variants of a project (which parts are fitted on which build): list them, make or change one with not-fitted parts (or put parts back), or remove... |  |  |-| `workspace_place` | Put a part from the Altium 365 workspace on a sheet: search, pick a result, place it (Altium's own placement, so the part keeps its workspace link,... |  |  |-| `workspace_search` | Search the Altium 365 workspace's components (the shared cloud library Altium is signed in to) through Altium's own Components panel: name, description and... |  |  |+| Verb | What it does | Altium | KiCad | Fusion 360 |+|---|---|---|---|---|+| `a365_configure` | Store the Altium 365 workspace domain and, optionally, a Bearer token created by hand in the workspace web UI (Admin - Developer). Local-only; tokens never... | `altium_a365_configure` |  |  |+| `a365_files_upload` | Upload one local file to the workspace's Files Service and get a temporary opaque file id to pass to a library mutation. | `altium_a365_files_upload` |  |  |+| `a365_library_overview` | One fixed read-only query: the workspace library's name, description, update time, component ids/names and footprint/symbol totals. | `altium_a365_library_overview` |  |  |+| `a365_library_schema` | Read-only schema map: the GraphQL queries and mutations whose names mention lib, component, symbol, footprint, part or datasheet, with mutation argument types. | `altium_a365_library_schema` |  |  |+| `a365_logout` | Revoke the refresh grant at Altium and remove every cached OAuth token. Workspace and client id stay configured. | `altium_a365_logout` |  |  |+| `a365_oauth_begin` | Start the Altium 365 OAuth (PKCE + ActionWait) sign-in: the bridge starts listening FIRST, then returns the authorize URL for the user's browser. Works with... | `altium_a365_oauth_begin` |  |  |+| `a365_oauth_cancel` | Cancel a waiting OAuth flow. | `altium_a365_oauth_cancel` |  |  |+| `a365_oauth_status` | State of the OAuth flow started by altium_a365_oauth_begin: idle / waiting / authorized / cancelled / error. | `altium_a365_oauth_status` |  |  |+| `a365_query` | Run one GraphQL query or mutation against the workspace's GraphQL gateway (https://<workspace>/svc/napi/gateway/graphql/) with the stored token. | `altium_a365_query` |  |  |+| `a365_refresh` | Exchange the stored refresh token for a new access token (and store a rotated refresh token if one comes back). | `altium_a365_refresh` |  |  |+| `a365_status` | Is the Altium 365 lane configured, is there a token, and is it LIVE (probed with a one-row GraphQL query)? | `altium_a365_status` |  |  |+| `compile_intlib` | Compile a .LibPkg into an integrated library (.IntLib). | `altium_compile_intlib` |  |  |+| `extract_intlib` | Extract the editable .SchLib/.PcbLib sources from a compiled .IntLib (Altium writes them next to the IntLib and opens them). | `altium_extract_intlib` |  |  |+| `import_kicad` | Import a KiCad file with Altium's own KiCad importer, driven through the AdomBridge .NET extension. | `altium_import_kicad` |  |  |+| `outjob_info` | An OutJob's containers (output media), the outputs in each, and their key settings (units, decimals, plotted layer count), read from the .OutJob file:... | `altium_outjob_info` |  |  |+| `run_outjob` | Run one output medium of an .OutJob (gerbers, drill, BOM, PDFs...) and list what it wrote under 'Project Outputs for <project>'. | `altium_run_outjob` |  |  |+| `variants` | Assembly variants of a project (which parts are fitted on which build): list them, make or change one with not-fitted parts (or put parts back), or remove... | `altium_variants` |  |  |+| `workspace_place` | Put a part from the Altium 365 workspace on a sheet: search, pick a result, place it (Altium's own placement, so the part keeps its workspace link,... | `altium_workspace_place` |  |  |+| `workspace_search` | Search the Altium 365 workspace's components (the shared cloud library Altium is signed in to) through Altium's own Components panel: name, description and... | `altium_workspace_search` |  |  |
package.json+2−1
@@ -1,6 +1,6 @@ {   "slug": "eda-bridge-standard",-  "version": "0.1.2",+  "version": "0.2.0",   "type": "skill",   "title": "EDA Bridge Standard: one way for an AI to drive every PCB tool",   "description": "The standard every Adom EDA bridge follows so one AI can drive Altium, KiCad, Fusion 360 and any future PCB tool the same way: shared verb names in tiers, the board model JSON, reply and refusal conventions, and a coverage table of each bridge against the Altium reference.",@@ -29,6 +29,7 @@     "tools/generate.py",     "tools/tiers.json",     "tools/equivalents.json",+    "tools/proposed.json",     "install.sh",     "uninstall.sh",     "reference/"
page.json+1−1
@@ -4,7 +4,7 @@   "type": "skill",   "title": "EDA Bridge Standard: one way for an AI to drive every PCB tool",   "brief": "The standard every Adom EDA bridge follows so one AI can drive Altium, KiCad, Fusion 360 and any future PCB tool the same way: shared verb names in tiers, the board model JSON, reply and refusal conventions, and a coverage table of each bridge against the Altium reference.",-  "version": "0.1.2",+  "version": "0.2.0",   "hero": {     "type": "billboard",     "headline": "One standard for every EDA bridge",
tools/equivalents.json+4−3
@@ -1,4 +1,5 @@ {+ "altium": {},  "fusion360": {   "apply_pours": [    "change_pours",@@ -147,11 +148,11 @@    "partial"   ],   "sch_connect": [-   "sch_wire / sch_label",-   "partial"+   "sch_connect_to_net / sch_no_connect / sch_wire / sch_label",+   "exact"   ],   "sch_edit": [-   "sch_set_property / sch_move / sch_delete",+   "sch_set_property / sch_move / sch_delete / sch_rotate",    "partial"   ],   "sch_place_part": [
tools/generate.py+63−20
@@ -1,9 +1,10 @@ #!/usr/bin/env python3-"""Generate the standard's verb files from the reference bridge's own catalog.+"""Generate the standard's verb files from the reference bridge's catalog and the agreed proposals. -The reference is the Altium bridge (the most complete): reference/altium-<version>.json is its `altium_describe`-reply. Every verb gets a tier (tools/tiers.json); KiCad and Fusion coverage comes from their verb lists-(reference/<bridge>-<version>.json) and the hand-made map of verbs that mean the same under another name+The Altium bridge's verbs are the base: reference/altium-<version>.json is its `altium_describe` reply, and each verb+gets a tier (tools/tiers.json). Verbs proposed by any other bridge are added from tools/proposed.json once a thread+other than the proposer's has agreed to them (agreedBy). Each bridge's coverage, Altium's included, comes from its verb+list (reference/<bridge>-<version>.json) and the hand-made map of verbs that do the same job under another name (tools/equivalents.json).  Writes verbs/standard.json, verbs/coverage.json, docs/coverage.md and the coverage block in README.md.@@ -43,19 +44,50 @@ def strip(name, prefix):     return name[len(prefix):] if name.startswith(prefix) else name  +PROPOSAL_FIELDS = ["name", "tier", "summary", "input", "output", "hint", "proposedBy", "since", "agreedBy"]+++def proposals(altium_names):+    """tools/proposed.json, checked. A proposal lands only when a thread other than its proposer agreed to it."""+    path = os.path.join(ROOT, "tools", "proposed.json")+    if not os.path.exists(path):+        return []+    entries, problems, seen = load("tools/proposed.json"), [], set()+    for i, p in enumerate(entries):+        name = p.get("name") or f"entry {i}"+        missing = [k for k in PROPOSAL_FIELDS if k not in p]+        if missing:+            problems.append(f"{name}: missing {', '.join(missing)}")+            continue+        if p["tier"] not in ORDER or p["tier"] == "platform":+            problems.append(f"{name}: tier {p['tier']!r} is not one of core, native, checks, app")+        if not [t for t in p["agreedBy"] if t != p["proposedBy"]]:+            problems.append(f"{name}: agreedBy names no thread other than its proposer ({p['proposedBy']})")+        if name in altium_names:+            problems.append(f"{name}: already a reference verb; credit the proposer's verb in tools/equivalents.json instead")+        if name in seen:+            problems.append(f"{name}: proposed twice")+        seen.add(name)+    if problems:+        raise SystemExit("tools/proposed.json refused:\n  " + "\n  ".join(problems))+    return entries++ def main():     ref = latest("altium")     tiers = load("tools/tiers.json")     eq = load("tools/equivalents.json")-    others = {b: latest(b) for b in ("kicad", "fusion360")}-    prefixes = {"kicad": "kicad_", "fusion360": "fusion_"}-    have = {b: {strip(v, prefixes[b]) for v in o["verbs"]} for b, o in others.items()}+    bridges = {b: latest(b) for b in ("altium", "kicad", "fusion360")}+    others = {b: o for b, o in bridges.items() if b != "altium"}+    prefixes = {"altium": "altium_", "kicad": "kicad_", "fusion360": "fusion_"}+    have = {b: {strip(v if isinstance(v, str) else v["name"], prefixes[b]) for v in o["verbs"]} for b, o in bridges.items()}+    proposed = proposals(have["altium"])      standard = []-    for v in sorted(ref["verbs"], key=lambda v: (ORDER.index(tiers[strip(v["name"], "altium_")]), v["name"])):+    for v in ref["verbs"]:         name = strip(v["name"], "altium_")         standard.append({-            "name": name, "tier": tiers[name], "summary": v.get("summary", ""),+            "name": name, "tier": tiers[name], "source": "altium", "summary": v.get("summary", ""),             "input": v.get("input", {}), "output": v.get("output", {}), "hint": v.get("hint", ""),             "pitfalls": v.get("pitfalls", []), "related": [strip(r, "altium_") for r in v.get("related", [])],             "example": v.get("example", {}), "longRunning": v.get("longRunning", False), "timeoutSeconds": v.get("timeoutSeconds"),@@ -63,11 +95,19 @@ def main():         # the reference still answers some verbs in mils; the standard is mm (docs/conventions.md)         if re.search(r"Mils?\b", json.dumps([v.get("input", {}), v.get("output", {})])):             standard[-1]["unitsNote"] = "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."+    for p in proposed:+        standard.append({+            "name": p["name"], "tier": p["tier"], "source": "proposed", "summary": p["summary"],+            "input": p["input"], "output": p["output"], "hint": p["hint"], "pitfalls": p.get("pitfalls", []),+            "related": p.get("related", []), "example": p.get("example", {}), "longRunning": p.get("longRunning", False),+            "timeoutSeconds": p.get("timeoutSeconds"), "proposedBy": p["proposedBy"], "since": p["since"], "agreedBy": p["agreedBy"],+        })+    standard.sort(key=lambda s: (ORDER.index(s["tier"]), s["name"]))      coverage = []     for s in standard:-        row = {"name": s["name"], "tier": s["tier"], "altium": "altium_" + s["name"]}-        for b in others:+        row = {"name": s["name"], "tier": s["tier"], "source": s["source"]}+        for b in bridges:             if s["name"] in have[b]:                 row[b] = {"verb": prefixes[b] + s["name"], "match": "exact"}             elif s["name"] in eq.get(b, {}):@@ -76,7 +116,7 @@ def main():                 # an equivalent counts only when its verbs are in that bridge's reference catalog                 absent = [p for p in parts if p not in have[b]]                 if absent:-                    print(f"warning: {b} {s['name']}: {', '.join(absent)} not in reference/{b}-{others[b]['version']}.json, not counted")+                    print(f"warning: {b} {s['name']}: {', '.join(absent)} not in reference/{b}-{bridges[b]['version']}.json, not counted")                     row[b] = None                 else:                     row[b] = {"verb": " / ".join(prefixes[b] + p for p in parts), "match": match}@@ -84,7 +124,7 @@ def main():                 row[b] = None         coverage.append(row) -    meta = {"reference": {"bridge": "altium", "version": ref["version"]},+    meta = {"reference": {"bridge": "altium", "version": ref["version"]}, "proposed": len(proposed),             "compared": {b: o["version"] for b, o in others.items()}, "tiers": TIERS}     os.makedirs(os.path.join(ROOT, "verbs"), exist_ok=True)     with open(os.path.join(ROOT, "verbs", "standard.json"), "w") as f:@@ -101,21 +141,22 @@ def main():     tot = {"altium": 0, "kicad": 0, "fusion360": 0, "all": 0}     for t in ORDER:         n = sum(1 for r in coverage if r["tier"] == t)-        k, fu = count("kicad", t), count("fusion360", t)-        lines.append(f"| **{t}** | {n} | {n} | {k} | {fu} |")+        a, k, fu = count("altium", t), count("kicad", t), count("fusion360", t)+        lines.append(f"| **{t}** | {n} | {a} | {k} | {fu} |")         if t != "platform":-            tot["all"] += n; tot["altium"] += n; tot["kicad"] += k; tot["fusion360"] += fu+            tot["all"] += n; tot["altium"] += a; tot["kicad"] += k; tot["fusion360"] += fu     lines.append(f"| standard (all but platform) | {tot['all']} | {tot['altium']} | {tot['kicad']} | {tot['fusion360']} |")     summary = "\n".join(lines)      # docs/coverage.md: the full table     md = [f"# Coverage: every standard verb on each bridge",           "",-          f"Reference: Altium bridge {ref['version']}. Compared: KiCad bridge {others['kicad']['version']}, Fusion 360 bridge {others['fusion360']['version']}.",+          f"Altium bridge {ref['version']} (the reference), KiCad bridge {others['kicad']['version']}, Fusion 360 bridge {others['fusion360']['version']}. "+          f"{len(proposed)} verbs came from other bridges' proposals (tools/proposed.json); they are marked *proposed*.",           "`exact` is the same job under the same or an equivalent name; `partial` does part of it or does it differently; blank is missing.",           "Generated by `tools/generate.py` from `verbs/coverage.json`; do not edit by hand.", "", summary, ""]     for t in ORDER:-        md += [f"## {t}", "", TIERS[t], "", "| Verb | What it does | KiCad | Fusion 360 |", "|---|---|---|---|"]+        md += [f"## {t}", "", TIERS[t], "", "| Verb | What it does | Altium | KiCad | Fusion 360 |", "|---|---|---|---|---|"]         for r, s in zip(coverage, standard):             if r["tier"] != t:                 continue@@ -123,7 +164,8 @@ def main():             summ = s["summary"].replace("|", "/").replace("\n", " ")             if len(summ) > 160:                 summ = summ[:157].rsplit(" ", 1)[0] + "..."-            md.append(f"| `{r['name']}` | {summ} | {cell(r.get('kicad'))} | {cell(r.get('fusion360'))} |")+            mark = " *proposed*" if r["source"] == "proposed" else ""+            md.append(f"| `{r['name']}`{mark} | {summ} | {cell(r.get('altium'))} | {cell(r.get('kicad'))} | {cell(r.get('fusion360'))} |")         md.append("")     with open(os.path.join(ROOT, "docs", "coverage.md"), "w") as f:         f.write("\n".join(md))@@ -135,7 +177,8 @@ def main():         block = f"<!-- coverage:start (tools/generate.py writes this) -->\n{summary}\n<!-- coverage:end -->"         text = re.sub(r"<!-- coverage:start.*?<!-- coverage:end -->", lambda _: block, text, flags=re.S)         open(readme, "w").write(text)-    print(f"standard: {len(standard)} verbs ({tot['all']} in the standard); kicad covers {tot['kicad']}, fusion {tot['fusion360']}")+    print(f"standard: {len(standard)} verbs ({tot['all']} in the standard, {len(proposed)} proposed); "+          f"altium covers {tot['altium']}, kicad {tot['kicad']}, fusion {tot['fusion360']}")   if __name__ == "__main__":
tools/proposed.jsonadded+924
@@ -0,0 +1,924 @@+[+ {+  "name": "sch_connect_pins",+  "tier": "core",+  "summary": "Wire pins to pins on a sheet by Ref.Pin: an L-shaped route (one horizontal and one vertical leg) for each pair, with a junction dot wherever a route meets an existing wire in a T. One undo step.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "pairs": "[{from: \"U1.1\", to: \"R5.2\", first?: h|v (the leg to draw first; default along the axis the from pin points), via?: [[x, y], ...] mm waypoints}] (required)",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "wired": "int",+   "routes": "[{from, to, points: [[x, y]], ids: [wire id]}]",+   "junctionsAdded": "[[x, y]]",+   "failed": "[{from, to, error}]",+   "saved": "bool"+  },+  "hint": "Pins are matched by number, then by name. Aligned pins get one straight wire; otherwise the route turns once. Check the result with sch_pins (connectedPins) or run_erc.",+  "pitfalls": [+   "The route does not avoid part bodies or other wires: a leg running along another wire merges the two nets. Steer with first or via, and check with sch_pins."+  ],+  "related": [+   "sch_pins",+   "sch_connect",+   "sch_delete_wire",+   "run_erc"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "pairs": [+    {+     "from": "U1.1",+     "to": "R2.1"+    },+    {+     "from": "U1.2",+     "to": "C3.1",+     "first": "v"+    }+   ]+  },+  "longRunning": true,+  "timeoutSeconds": 120,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_connect_to_bus",+  "tier": "core",+  "summary": "Fan pins onto a bus: for each pin a wire running to the bus, a 45-degree bus entry onto it and a member label (D0, D1 ...) on the wire. One undo step.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "pins": "[\"U1.1\", \"U1.2\"] Ref.Pin, in member order (required)",+   "bus": "id of the bus segment (default the only bus on the sheet)",+   "members": "[\"D0\", \"D1\"]: the member names in pin order",+   "prefix": "\"D\": or name members prefix + number",+   "start": "int, default 0: the first number with prefix",+   "entry": "up|down (a vertical bus) or left|right (a horizontal bus): the way the entries lean",+   "busLabel": "\"D[0..7]\": also label the bus",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "connected": "[{pin, member, wireId, entryId}]",+   "busLabel": "string or null",+   "failed": "[{pin, error}]",+   "saved": "bool"+  },+  "hint": "Members name the nets: members lists them in pin order, or prefix plus start counts up. Refused with entry_off_bus when an entry would miss the bus: extend the bus with sch_bus first.",+  "pitfalls": [+   "Pins should face the bus; a pin facing away gets a wire across its own part.",+   "Two pins at the same height on a vertical bus share an entry point and collide: offset them or lean the entries differently."+  ],+  "related": [+   "sch_bus",+   "sch_bus_entry",+   "sch_pins"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "pins": [+    "U1.1",+    "U1.7"+   ],+   "prefix": "D",+   "busLabel": "D[0..1]"+  },+  "longRunning": true,+  "timeoutSeconds": 120,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_junction",+  "tier": "core",+  "summary": "Add junction dots at points, or remove dots by id or point. One undo step.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "points": "[[x, y], ...] mm: where to add dots",+   "remove": "[id or [x, y], ...]: dots to remove",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "added": "[{id, at}]",+   "removed": "[id]",+   "skipped": "[[x, y]]: points that already had a dot",+   "notNeeded": "[[x, y]]: added dots where fewer than three items meet (legal, but they join nothing extra)",+   "saved": "bool"+  },+  "hint": "The wiring verbs add the dots they need on their own; use this for a T made by hand, or to clean up.",+  "pitfalls": [+   "Items join only where their coordinates match exactly: use pin ends from sch_pins, or points on the sheet's grid."+  ],+  "related": [+   "sch_items",+   "sch_split_wire",+   "sch_delete_wire"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "points": [+    [+     110.49,+     60.96+    ]+   ]+  },+  "longRunning": true,+  "timeoutSeconds": 120,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_bus",+  "tier": "core",+  "summary": "Draw a bus as a polyline (one bus segment per pair of points), optionally with a bus label such as D[0..7] or a group {SDA SCL} at its first point. One undo step.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "points": "[[x, y], [x, y], ...] mm (required)",+   "label": "\"D[0..7]\" or \"{SDA SCL}\": the nets the bus carries",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "ids": "[bus segment id]",+   "label": "{id, text} or null",+   "saved": "bool"+  },+  "hint": "A bus carries the nets its label names, and each member wire needs its own label. sch_connect_to_bus does the member wires, entries and labels for a set of pins.",+  "pitfalls": [+   "A bus with no label carries nothing: ERC reports its members as unconnected."+  ],+  "related": [+   "sch_bus_entry",+   "sch_connect_to_bus",+   "sch_delete_wire",+   "sch_items"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "points": [+    [+     203.2,+     50.8+    ],+    [+     203.2,+     101.6+    ]+   ],+   "label": "D[0..7]"+  },+  "longRunning": true,+  "timeoutSeconds": 120,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_bus_entry",+  "tier": "core",+  "summary": "Add 45-degree bus entries: the short diagonal that joins a member wire's end to a bus. One undo step.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "entries": "[{at: [x, y] mm (the wire end), direction: up-right|down-right|up-left|down-left as seen (default down-right)}] (required)",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "added": "[{id, at, end: [x, y] (the bus side), onBus: bool}]",+   "saved": "bool"+  },+  "hint": "end is the bus side of each entry; onBus says whether it lands on a bus segment.",+  "pitfalls": [+   "The bus side must touch a bus and the other end a wire end, exactly, or ERC reports the entry as unconnected."+  ],+  "related": [+   "sch_bus",+   "sch_connect_to_bus",+   "sch_items"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "entries": [+    {+     "at": [+      200.66,+      63.5+     ],+     "direction": "up-right"+    }+   ]+  },+  "longRunning": true,+  "timeoutSeconds": 120,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_split_wire",+  "tier": "core",+  "summary": "Split the wire through a point into two wires there, with a junction dot at the cut, so a new branch can end on a wire end. One undo step.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "at": "[x, y] mm on the sheet (the tool's sheet origin, y up) (required)",+   "id": "the wire's id, when several wires pass through the point",+   "junction": "bool, default true",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "ids": "[first half (keeps the wire's id), second half (new id)]",+   "junction": "{id, at} or null",+   "saved": "bool"+  },+  "hint": "Split a wire where a new branch should join it, then wire to the cut.",+  "pitfalls": [+   "The point must lie on the wire and not at either end (not_on_wire otherwise)."+  ],+  "related": [+   "sch_delete_wire",+   "sch_junction",+   "sch_items"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "at": [+    110.49,+    60.96+   ]+  },+  "longRunning": true,+  "timeoutSeconds": 120,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_delete_wire",+  "tier": "core",+  "summary": "Delete wires or bus segments by id, by their two ends, or every wire through a point, and remove junction dots that no longer join three or more items. One undo step.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "ids": "[wire id, ...]",+   "from": "[x, y] mm, with to: the wire with exactly these ends (either order)",+   "to": "[x, y] mm",+   "at": "[x, y] mm: every wire passing through the point",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "deleted": "[{id, from, to}]",+   "junctionsRemoved": "[[x, y]]",+   "saved": "bool"+  },+  "hint": "Read ids with sch_items. from/to matches one segment, not a whole route.",+  "pitfalls": [+   "A polyline drawn in the editor is several wires sharing ends: from/to names one segment of it."+  ],+  "related": [+   "sch_items",+   "sch_split_wire",+   "sch_junction",+   "sch_connect_pins"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "from": [+    100.33,+    60.96+   ],+   "to": [+    120.65,+    60.96+   ]+  },+  "longRunning": true,+  "timeoutSeconds": 120,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_edit_label",+  "tier": "core",+  "summary": "Edit net labels: rotate, move to a point or by a delta, rename, or move every label of a net at once. One undo step.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "edits": "[{id | text (with at?: [x, y] to pick one) | net (every label of the net), rotation?: 0|90|180|270, to?: [x, y] mm (one label only), by?: [dx, dy] mm, rename?: string}] (required)",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "edited": "[{id, text, at, rotation}]",+   "failed": "[{edit, error}]",+   "saved": "bool"+  },+  "hint": "text picks every label with that text (or the one at at); net picks every label of the net. Read ids with sch_items.",+  "pitfalls": [+   "A label joins a net only where it sits on a wire or a pin end: moving it off disconnects it.",+   "rename changes only the labels picked: other labels with the old name stay on the old net."+  ],+  "related": [+   "sch_items",+   "sch_connect",+   "sch_edit"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "edits": [+    {+     "net": "VOUT",+     "by": [+      0,+      2.54+     ]+    }+   ]+  },+  "longRunning": true,+  "timeoutSeconds": 120,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_move_region",+  "tier": "core",+  "summary": "Move everything inside a box by (dx, dy): parts, wire ends inside the box (wires crossing its edge stretch), labels, junctions, no-connect markers, texts, bus entries and sheet symbols. One undo step.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "box": "[x1, y1, x2, y2] mm (required)",+   "by": "[dx, dy] mm (required)",+   "wires": "bool, default true: move wires, buses and bus entries",+   "labels": "bool, default true: move labels and texts",+   "junctions": "bool, default true: move junctions and no-connect markers",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "moved": "{parts, wires, buses, busEntries, labels, texts, junctions, noConnects, sheets: [id]}",+   "saved": "bool"+  },+  "hint": "Parts move by their anchor point. Move by a pure dx or a pure dy to keep stretched wires straight.",+  "pitfalls": [+   "A wire with one end in the box stretches diagonally when dx and dy are both non-zero.",+   "Keep the move on the sheet's grid, or pins and wires stop meeting.",+   "A multi-part component whose parts sit on both sides of the edge splits up."+  ],+  "related": [+   "sch_edit",+   "sch_items"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "box": [+    90,+    40,+    160,+    120+   ],+   "by": [+    25.4,+    0+   ]+  },+  "longRunning": true,+  "timeoutSeconds": 120,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_text",+  "tier": "core",+  "summary": "Add free text to a sheet (a note, a title, a design comment) with size, angle, justification, bold and italic. Text has no electrical meaning. One undo step.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "texts": "[{text, at: [x, y] mm, rotation?: 0|90|180|270, sizeMm?: 1.27, justify?: \"left bottom\", bold?: false, italic?: false}] (required)",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "added": "[{id, text, at}]",+   "saved": "bool"+  },+  "hint": "Net names are labels, not text: use sch_connect for them. Newlines in text become line breaks.",+  "pitfalls": [],+  "related": [+   "sch_items",+   "sch_edit_label"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "texts": [+    {+     "text": "USB input stage",+     "at": [+      50.8,+      30.48+     ],+     "sizeMm": 2.54,+     "bold": true+    }+   ]+  },+  "longRunning": true,+  "timeoutSeconds": 120,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_page",+  "tier": "core",+  "summary": "Read or set a sheet's page: paper size, orientation and title block (title, date, revision, company, comment lines).",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "paper": "A5 to A0, A to E, USLetter, USLegal, USLedger or custom",+   "orientation": "portrait|landscape",+   "widthMm": "number (custom paper)",+   "heightMm": "number (custom paper)",+   "title": "string",+   "date": "string",+   "rev": "string",+   "company": "string",+   "comments": "[string]: comment lines in order",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "paper": "string",+   "widthMm": "number",+   "heightMm": "number",+   "orientation": "string",+   "titleBlock": "{title, date, rev, company, comments}",+   "changed": "bool",+   "saved": "bool"+  },+  "hint": "With no change arguments it only reads. An empty string removes a title-block field. Each sheet of a hierarchy has its own page.",+  "pitfalls": [+   "Shrinking the paper moves nothing: items outside the new frame stay where they are (render_schematic shows it)."+  ],+  "related": [+   "sch_create",+   "render_schematic"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "paper": "A3",+   "title": "Main board",+   "rev": "B"+  },+  "longRunning": false,+  "timeoutSeconds": 30,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_items",+  "tier": "core",+  "summary": "List a sheet's wiring items with ids and coordinates: wires, buses, bus entries, net labels (local, global, hierarchical), power ports, junctions, no-connect markers, texts and sheet symbols. Read only.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "kinds": "[wires, buses, busEntries, labels, powerPorts, junctions, noConnects, texts, sheets] (default all)"+  },+  "output": {+   "wires": "[{id, from, to}]",+   "buses": "[{id, from, to}]",+   "busEntries": "[{id, at, end}]",+   "labels": "[{id, text, kind: local|global|hierarchical, at, rotation}]",+   "powerPorts": "[{id, net, at}]",+   "junctions": "[{id, at}]",+   "noConnects": "[{id, at}]",+   "texts": "[{id, text, at}]",+   "sheets": "[{id, name, file, at, sizeMm}]",+   "counts": "{kind: int}"+  },+  "hint": "The ids feed sch_delete_wire, sch_edit_label, sch_junction and sch_edit. Parts are in schematic_data.",+  "pitfalls": [+   "A wire is one straight segment: a polyline drawn in the editor is several wires sharing ends."+  ],+  "related": [+   "schematic_data",+   "sch_pins",+   "sch_delete_wire",+   "sch_edit_label"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "kinds": [+    "wires",+    "labels"+   ]+  },+  "longRunning": false,+  "timeoutSeconds": 30,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_pins",+  "tier": "core",+  "summary": "Every pin of the named parts on a sheet: its absolute position (rotation and mirror applied), number, name, electrical type, the side it leaves the body, and the wires, labels and nets touching it. Read only.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "references": "[\"U1\", \"R5\"] (default every part)",+   "connections": "bool, default true: add what touches each pin"+  },+  "output": {+   "pins": "[{ref, number, name, type, at: [x, y], direction: right|left|up|down as seen, hidden, touching: [{kind, id}], nets: [string], connectedPins: [Ref.Pin]}]"+  },+  "hint": "at is where a wire or label must land on the pin. connectedPins lists the other pins on the same copper on this sheet.",+  "pitfalls": [+   "Nets here come from this sheet's wires and labels only: netlist gives the project-wide nets.",+   "Hidden power pins (hidden:true) connect by name, not by wire."+  ],+  "related": [+   "sch_connect_pins",+   "sch_connect",+   "schematic_data",+   "netlist"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "references": [+    "U1",+    "R5"+   ]+  },+  "longRunning": false,+  "timeoutSeconds": 30,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_trace_point",+  "tier": "core",+  "summary": "Everything electrically connected at a point on a sheet: the wires, labels, pins, junctions, sheet pins and no-connect markers there, and for each net they belong to the whole net with its name. Read only.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "at": "[x, y] mm on the sheet (the tool's sheet origin, y up) (required)",+   "toleranceMm": "number, default 0.05"+  },+  "output": {+   "items": "[{kind, id, at}]",+   "nets": "[{name, pins: [Ref.Pin], labels, powerPorts, wires, leavesSheet: bool}]",+   "crossingWithoutJunction": "bool: two wires cross here without connecting",+   "nearest": "[x, y]: the nearest connectable point, when nothing is within tolerance"+  },+  "hint": "Read with the tool's own rules: wire ends join wires and wire middles (a T), labels and junction dots join a wire anywhere along it, pins join wire ends.",+  "pitfalls": [+   "One sheet only: a net that leaves through a global, hierarchical or power label (leavesSheet:true) continues on other sheets. netlist gives the compiled net."+  ],+  "related": [+   "sch_pins",+   "net_connections",+   "netlist"+  ],+  "example": {+   "sheet": "C:/proj/Power.SchDoc",+   "at": [+    109.22,+    73.66+   ]+  },+  "longRunning": false,+  "timeoutSeconds": 30,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_hierarchy",+  "tier": "core",+  "summary": "The sheet tree of a design, recursively: each sheet's name, file, id, instance path, page number, position, size and pins. renumber:true renumbers pages depth-first from the root.",+  "input": {+   "sheet": "path to the root sheet",+   "project": "path to the project (instead of sheet)",+   "renumber": "bool, default false",+   "dryRun": "bool, default false: answer the plan and change nothing"+  },+  "output": {+   "tree": "[{name, file, id, path, page, at, sizeMm, pins: [{name, kind}], children: [...]}]",+   "problems": "[{sheet, problem: missing|unreadable|recursive}]",+   "duplicatePages": "[int]",+   "renumbered": "[{sheet, from, to}]"+  },+  "hint": "Pass the root sheet or the project. renumber writes only the numbers that change.",+  "pitfalls": [+   "A sheet file used by two sheet symbols appears twice in the tree (one instance each) but is one file."+  ],+  "related": [+   "sch_sheet_pins",+   "sch_sheet_symbol",+   "sch_create"+  ],+  "example": {+   "project": "C:/proj/Board.PrjPcb",+   "renumber": true+  },+  "longRunning": false,+  "timeoutSeconds": 30,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_sheet_pins",+  "tier": "core",+  "summary": "A sheet symbol's pins: list, add, edit (rename, kind, move along an edge) or delete. import:true adds a pin for every hierarchical port inside the child sheet that the symbol lacks; validate:true reports ports without pins, pins without ports and kind mismatches.",+  "input": {+   "sheet": "path to the parent sheet (required)",+   "sheetSymbol": "the sheet symbol's name or id (default: validate checks every one)",+   "action": "list|add|edit|delete, default list",+   "name": "string: the pin",+   "kind": "input|output|bidirectional|tri_state|passive",+   "side": "left|right|top|bottom",+   "at": "[x, y] mm: snapped to the nearest edge point",+   "newName": "string (edit)",+   "import": "bool",+   "validate": "bool",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "pins": "[{id, name, kind, side, at}]",+   "added": "[name]",+   "problems": "[{sheetSymbol, pin, problem: no_port|no_pin|kind_mismatch}]",+   "saved": "bool"+  },+  "hint": "Inputs go on the left edge and outputs on the right by default, in the first free slot. A pin joins the child's hierarchical port of the same name; wire it on the parent side at its at.",+  "pitfalls": [+   "Renaming a pin does not rename the port inside the child sheet: validate afterwards.",+   "A pin moved or deleted leaves its parent-side wire dangling."+  ],+  "related": [+   "sch_sheet_symbol",+   "sch_hierarchy",+   "sch_connect"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "sheetSymbol": "Power",+   "import": true+  },+  "longRunning": false,+  "timeoutSeconds": 30,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_reset_fields",+  "tier": "core",+  "summary": "Put parts' designator and value text (or the named fields) back where the library symbol places them, through each part's rotation and mirror. One undo step.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "references": "[\"R5\", \"C3\"]",+   "all": "bool: every part on the sheet",+   "fields": "[designator, value] by default; other field names as the tool names them",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "reset": "[{ref, field}]",+   "saved": "bool"+  },+  "hint": "Font and visibility stay as they are; only position, angle and justification move.",+  "pitfalls": [+   "The library's offsets are what the symbol's author drew; the tool's automatic field placement may put them elsewhere."+  ],+  "related": [+   "sch_edit",+   "schematic_data"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "references": [+    "R5",+    "C3"+   ]+  },+  "longRunning": true,+  "timeoutSeconds": 120,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_update_from_library",+  "tier": "native",+  "summary": "Update the placed symbols on a sheet from their libraries (all, or the listed ones) and report which changed, which already matched and which no library has.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "symbols": "[library symbol name or id, ...] (default all)",+   "library": "path to one library to take them all from (with symbols)",+   "force": "bool, default false: update even when a placed pin would be dropped",+   "dryRun": "bool, default false: answer the plan and change nothing",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "changed": "[{symbol, pinsAdded, pinsRemoved}]",+   "unchanged": "[symbol]",+   "notFound": "[symbol]",+   "refused": "[{symbol, droppedPins}]",+   "saved": "bool"+  },+  "hint": "Run with dryRun first. A symbol whose new version drops a placed pin is refused unless force:true. Check the sheet afterwards with run_erc.",+  "pitfalls": [+   "A pin that moved in the library moves off its wire: check with sch_pins or run_erc after an update that reports changes."+  ],+  "related": [+   "sch_swap_part",+   "schematic_data",+   "run_erc"+  ],+  "example": {+   "sheet": "C:/proj/Main.SchDoc",+   "dryRun": true+  },+  "longRunning": true,+  "timeoutSeconds": 180,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_fix_connectivity",+  "tier": "core",+  "summary": "Snap near-miss wire ends onto the pin, label, sheet pin or wire end they almost touch, within a tolerance. dryRun (the default) lists the moves; dryRun:false makes them.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "toleranceMm": "number, default 0.5",+   "dryRun": "bool, default TRUE",+   "save": "bool, default true: save the sheet after the edit"+  },+  "output": {+   "moves": "[{wireId, from, to, onto: {kind, id}, diagonal: bool}]",+   "unresolved": "[[x, y]]: dangling ends with nothing close",+   "saved": "bool"+  },+  "hint": "Only dangling wire ends move. Read the moves before applying them: diagonal:true means the snapped wire is no longer horizontal or vertical. Check with run_erc after.",+  "pitfalls": [+   "dryRun defaults to true: nothing changes until dryRun:false.",+   "A wide tolerance can snap onto the wrong pin: keep it under half the sheet's grid."+  ],+  "related": [+   "sch_trace_point",+   "run_erc"+  ],+  "example": {+   "sheet": "C:/proj/Power.SchDoc",+   "toleranceMm": 0.5,+   "dryRun": false+  },+  "longRunning": false,+  "timeoutSeconds": 60,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "render_schematic",+  "tier": "native",+  "summary": "Render a sheet to an image without opening a window, through the tool's own plotter, and keep visual baselines: baseline set stores the image, baseline compare reports the pixel drift, the changed region and a diff image.",+  "input": {+   "sheet": "path to the schematic sheet file (required)",+   "width": "int px, default 2000",+   "outputDir": "folder for the image (default beside the project)",+   "baseline": "set|compare",+   "threshold": "percent of pixels, default 0.5 (compare)",+   "drawingSheet": "bool, default true: include the frame and title block"+  },+  "output": {+   "png": "path",+   "width": "int",+   "height": "int",+   "driftPercent": "number (compare)",+   "pass": "bool (compare)",+   "changedRegionMm": "[x1, y1, x2, y2] (compare)",+   "diffPng": "path: the changed pixels in red (compare)",+   "rendererChanged": "bool: the tool's plotter changed since the baseline"+  },+  "hint": "A sub-sheet renders with its real designators. compare renders at the baseline's width and passes when driftPercent <= threshold. show_* verbs open a window; this one does not.",+  "pitfalls": [+   "Anti-aliasing differs between tool versions: rendererChanged:true means drift may not be a design change.",+   "A baseline is per sheet and per width; a paper size change reads as 100 percent drift."+  ],+  "related": [+   "sch_page",+   "export_pdf"+  ],+  "example": {+   "sheet": "C:/proj/Power.SchDoc",+   "baseline": "compare"+  },+  "longRunning": true,+  "timeoutSeconds": 300,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ },+ {+  "name": "sch_create",+  "tier": "core",+  "summary": "Create an empty schematic sheet with a paper size and title block; optionally add it to a project as a child sheet of the root. It places no parts or nets (build_schematic does).",+  "input": {+   "sheet": "path of the sheet to create (required)",+   "paper": "A4, A3 ... USLetter or custom",+   "orientation": "portrait|landscape",+   "widthMm": "number (custom)",+   "heightMm": "number (custom)",+   "title": "string",+   "date": "string",+   "rev": "string",+   "company": "string",+   "comments": "[string]",+   "project": "path: add the sheet to this project under its root sheet",+   "sheetName": "string: the sheet symbol's name in the root",+   "at": "[x, y] mm: where the sheet symbol goes on the root",+   "dryRun": "bool, default false: answer the plan and change nothing"+  },+  "output": {+   "sheet": "path",+   "page": "int",+   "sheetSymbol": "{id, name, at} or null",+   "created": "bool"+  },+  "hint": "Without project the sheet stands alone. With project it is linked from the root sheet as a child sheet with the next page number.",+  "pitfalls": [+   "Never overwrites: an existing file is refused.",+   "A new child sheet has no pins on its symbol: add hierarchical ports inside, then sch_sheet_pins {import:true}."+  ],+  "related": [+   "sch_page",+   "sch_hierarchy",+   "sch_sheet_pins",+   "sch_place_part"+  ],+  "example": {+   "sheet": "C:/proj/Power.SchDoc",+   "project": "C:/proj/Board.PrjPcb",+   "sheetName": "Power",+   "title": "Power"+  },+  "longRunning": false,+  "timeoutSeconds": 30,+  "proposedBy": "kicad-lane",+  "since": "0.2.0",+  "agreedBy": [+   "altium-lane"+  ]+ }+]
verbs/coverage.json+1240−204
@@ -3,6 +3,7 @@   "bridge": "altium",   "version": "0.2.75"  },+ "proposed": 21,  "compared": {   "kicad": "1.0.62",   "fusion360": "1.12.1"@@ -18,28 +19,44 @@   {    "name": "add_body",    "tier": "core",-   "altium": "altium_add_body",+   "source": "altium",+   "altium": {+    "verb": "altium_add_body",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "add_models",    "tier": "core",-   "altium": "altium_add_models",+   "source": "altium",+   "altium": {+    "verb": "altium_add_models",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "add_symbol_art",    "tier": "core",-   "altium": "altium_add_symbol_art",+   "source": "altium",+   "altium": {+    "verb": "altium_add_symbol_art",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "apply_silkscreen",    "tier": "core",-   "altium": "altium_apply_silkscreen",+   "source": "altium",+   "altium": {+    "verb": "altium_apply_silkscreen",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_silk_fields_batch / kicad_silk_text_batch / kicad_silk_graphics_batch",     "match": "exact"@@ -52,7 +69,11 @@   {    "name": "board_outline",    "tier": "core",-   "altium": "altium_board_outline",+   "source": "altium",+   "altium": {+    "verb": "altium_board_outline",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_board_outline",     "match": "exact"@@ -65,7 +86,11 @@   {    "name": "board_shape",    "tier": "core",-   "altium": "altium_board_shape",+   "source": "altium",+   "altium": {+    "verb": "altium_board_shape",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_board_outline",     "match": "exact"@@ -78,7 +103,11 @@   {    "name": "board_summary",    "tier": "core",-   "altium": "altium_board_summary",+   "source": "altium",+   "altium": {+    "verb": "altium_board_summary",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_board_summary",     "match": "exact"@@ -91,14 +120,22 @@   {    "name": "clone_symbol",    "tier": "core",-   "altium": "altium_clone_symbol",+   "source": "altium",+   "altium": {+    "verb": "altium_clone_symbol",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "component_data",    "tier": "core",-   "altium": "altium_component_data",+   "source": "altium",+   "altium": {+    "verb": "altium_component_data",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_component_data",     "match": "exact"@@ -111,7 +148,11 @@   {    "name": "component_pins",    "tier": "core",-   "altium": "altium_component_pins",+   "source": "altium",+   "altium": {+    "verb": "altium_component_pins",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_component_pins",     "match": "exact"@@ -124,7 +165,11 @@   {    "name": "copper_layers",    "tier": "core",-   "altium": "altium_copper_layers",+   "source": "altium",+   "altium": {+    "verb": "altium_copper_layers",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_copper_layers",     "match": "exact"@@ -137,14 +182,22 @@   {    "name": "copy_footprint",    "tier": "core",-   "altium": "altium_copy_footprint",+   "source": "altium",+   "altium": {+    "verb": "altium_copy_footprint",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "create_footprint",    "tier": "core",-   "altium": "altium_create_footprint",+   "source": "altium",+   "altium": {+    "verb": "altium_create_footprint",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_create_footprint",     "match": "exact"@@ -154,7 +207,11 @@   {    "name": "create_symbol",    "tier": "core",-   "altium": "altium_create_symbol",+   "source": "altium",+   "altium": {+    "verb": "altium_create_symbol",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_create_symbol",     "match": "exact"@@ -164,14 +221,22 @@   {    "name": "doc_params",    "tier": "core",-   "altium": "altium_doc_params",+   "source": "altium",+   "altium": {+    "verb": "altium_doc_params",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "find_symbol",    "tier": "core",-   "altium": "altium_find_symbol",+   "source": "altium",+   "altium": {+    "verb": "altium_find_symbol",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_find_symbol",     "match": "exact"@@ -181,7 +246,11 @@   {    "name": "footprint_primitives",    "tier": "core",-   "altium": "altium_footprint_primitives",+   "source": "altium",+   "altium": {+    "verb": "altium_footprint_primitives",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_fp_info",     "match": "partial"@@ -191,7 +260,11 @@   {    "name": "layer_stack",    "tier": "core",-   "altium": "altium_layer_stack",+   "source": "altium",+   "altium": {+    "verb": "altium_layer_stack",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_layer_stack",     "match": "exact"@@ -204,7 +277,11 @@   {    "name": "layers",    "tier": "core",-   "altium": "altium_layers",+   "source": "altium",+   "altium": {+    "verb": "altium_layers",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_layers",@@ -214,7 +291,11 @@   {    "name": "layers_in_use",    "tier": "core",-   "altium": "altium_layers_in_use",+   "source": "altium",+   "altium": {+    "verb": "altium_layers_in_use",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_layers_in_use",     "match": "exact"@@ -227,7 +308,11 @@   {    "name": "list_designators",    "tier": "core",-   "altium": "altium_list_designators",+   "source": "altium",+   "altium": {+    "verb": "altium_list_designators",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_list_designators",     "match": "exact"@@ -240,7 +325,11 @@   {    "name": "list_library",    "tier": "core",-   "altium": "altium_list_library",+   "source": "altium",+   "altium": {+    "verb": "altium_list_library",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_list_footprints / kicad_list_symbols",     "match": "partial"@@ -250,7 +339,11 @@   {    "name": "list_nets",    "tier": "core",-   "altium": "altium_list_nets",+   "source": "altium",+   "altium": {+    "verb": "altium_list_nets",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_list_nets",     "match": "exact"@@ -263,7 +356,11 @@   {    "name": "move_parts",    "tier": "core",-   "altium": "altium_move_parts",+   "source": "altium",+   "altium": {+    "verb": "altium_move_parts",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_move_footprint",     "match": "exact"@@ -276,7 +373,11 @@   {    "name": "net_connections",    "tier": "core",-   "altium": "altium_net_connections",+   "source": "altium",+   "altium": {+    "verb": "altium_net_connections",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_trace_net / kicad_find_connections",     "match": "partial"@@ -289,21 +390,33 @@   {    "name": "normalize_bodies",    "tier": "core",-   "altium": "altium_normalize_bodies",+   "source": "altium",+   "altium": {+    "verb": "altium_normalize_bodies",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "part_parameters",    "tier": "core",-   "altium": "altium_part_parameters",+   "source": "altium",+   "altium": {+    "verb": "altium_part_parameters",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "place_on_pcb",    "tier": "core",-   "altium": "altium_place_on_pcb",+   "source": "altium",+   "altium": {+    "verb": "altium_place_on_pcb",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_place_footprint",     "match": "exact"@@ -313,14 +426,22 @@   {    "name": "place_on_sch",    "tier": "core",-   "altium": "altium_place_on_sch",+   "source": "altium",+   "altium": {+    "verb": "altium_place_on_sch",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "place_vias",    "tier": "core",-   "altium": "altium_place_vias",+   "source": "altium",+   "altium": {+    "verb": "altium_place_vias",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_add_via",     "match": "exact"@@ -333,14 +454,22 @@   {    "name": "plate_vias",    "tier": "core",-   "altium": "altium_plate_vias",+   "source": "altium",+   "altium": {+    "verb": "altium_plate_vias",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "read_board",    "tier": "core",-   "altium": "altium_read_board",+   "source": "altium",+   "altium": {+    "verb": "altium_read_board",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_board_summary",     "match": "partial"@@ -353,7 +482,11 @@   {    "name": "read_rules",    "tier": "core",-   "altium": "altium_read_rules",+   "source": "altium",+   "altium": {+    "verb": "altium_read_rules",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_list_design_rules",     "match": "exact"@@ -366,7 +499,11 @@   {    "name": "read_schematic",    "tier": "core",-   "altium": "altium_read_schematic",+   "source": "altium",+   "altium": {+    "verb": "altium_read_schematic",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_sch_components",     "match": "partial"@@ -379,7 +516,11 @@   {    "name": "read_symbol",    "tier": "core",-   "altium": "altium_read_symbol",+   "source": "altium",+   "altium": {+    "verb": "altium_read_symbol",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_read_symbol",     "match": "exact"@@ -389,14 +530,22 @@   {    "name": "remove_footprint",    "tier": "core",-   "altium": "altium_remove_footprint",+   "source": "altium",+   "altium": {+    "verb": "altium_remove_footprint",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "remove_items",    "tier": "core",-   "altium": "altium_remove_items",+   "source": "altium",+   "altium": {+    "verb": "altium_remove_items",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_remove_route",     "match": "partial"@@ -409,7 +558,11 @@   {    "name": "remove_symbol",    "tier": "core",-   "altium": "altium_remove_symbol",+   "source": "altium",+   "altium": {+    "verb": "altium_remove_symbol",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_remove_symbol",     "match": "exact"@@ -419,21 +572,33 @@   {    "name": "rename_footprint",    "tier": "core",-   "altium": "altium_rename_footprint",+   "source": "altium",+   "altium": {+    "verb": "altium_rename_footprint",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "rename_symbol",    "tier": "core",-   "altium": "altium_rename_symbol",+   "source": "altium",+   "altium": {+    "verb": "altium_rename_symbol",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "ripup_nets",    "tier": "core",-   "altium": "altium_ripup_nets",+   "source": "altium",+   "altium": {+    "verb": "altium_ripup_nets",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_ripup_nets",@@ -443,7 +608,11 @@   {    "name": "route_net",    "tier": "core",-   "altium": "altium_route_net",+   "source": "altium",+   "altium": {+    "verb": "altium_route_net",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_route_net",     "match": "exact"@@ -456,7 +625,11 @@   {    "name": "routing_state",    "tier": "core",-   "altium": "altium_routing_state",+   "source": "altium",+   "altium": {+    "verb": "altium_routing_state",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_routing_state",     "match": "exact"@@ -469,7 +642,11 @@   {    "name": "rules_by_kind",    "tier": "core",-   "altium": "altium_rules_by_kind",+   "source": "altium",+   "altium": {+    "verb": "altium_rules_by_kind",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_board_rules",     "match": "partial"@@ -479,60 +656,293 @@     "match": "exact"    }   },+  {+   "name": "sch_bus",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_bus",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_bus_entry",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_bus_entry",+    "match": "exact"+   },+   "fusion360": null+  },   {    "name": "sch_connect",    "tier": "core",-   "altium": "altium_sch_connect",+   "source": "altium",+   "altium": {+    "verb": "altium_sch_connect",+    "match": "exact"+   },    "kicad": {-    "verb": "kicad_sch_wire / kicad_sch_label",-    "match": "partial"+    "verb": "kicad_sch_connect_to_net / kicad_sch_no_connect / kicad_sch_wire / kicad_sch_label",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_connect_pins",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_connect_pins",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_connect_to_bus",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_connect_to_bus",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_create",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_create",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_delete_wire",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_delete_wire",+    "match": "exact"    },    "fusion360": null   },   {    "name": "sch_edit",    "tier": "core",-   "altium": "altium_sch_edit",+   "source": "altium",+   "altium": {+    "verb": "altium_sch_edit",+    "match": "exact"+   },    "kicad": {-    "verb": "kicad_sch_set_property / kicad_sch_move / kicad_sch_delete",+    "verb": "kicad_sch_set_property / kicad_sch_move / kicad_sch_delete / kicad_sch_rotate",     "match": "partial"    },    "fusion360": null   },+  {+   "name": "sch_edit_label",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_edit_label",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_fix_connectivity",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_fix_connectivity",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_hierarchy",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_hierarchy",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_items",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_items",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_junction",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_junction",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_move_region",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_move_region",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_page",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_page",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_pins",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_pins",+    "match": "exact"+   },+   "fusion360": null+  },   {    "name": "sch_place_part",    "tier": "core",-   "altium": "altium_sch_place_part",+   "source": "altium",+   "altium": {+    "verb": "altium_sch_place_part",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_sch_place_symbol",     "match": "exact"    },    "fusion360": null   },+  {+   "name": "sch_reset_fields",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_reset_fields",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_sheet_pins",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_sheet_pins",+    "match": "exact"+   },+   "fusion360": null+  },   {    "name": "sch_sheet_symbol",    "tier": "core",-   "altium": "altium_sch_sheet_symbol",+   "source": "altium",+   "altium": {+    "verb": "altium_sch_sheet_symbol",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_sch_sheet_symbol",     "match": "exact"    },    "fusion360": null   },+  {+   "name": "sch_split_wire",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_split_wire",+    "match": "exact"+   },+   "fusion360": null+  },   {    "name": "sch_swap_part",    "tier": "core",-   "altium": "altium_sch_swap_part",+   "source": "altium",+   "altium": {+    "verb": "altium_sch_swap_part",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_sch_replace_symbol",     "match": "partial"    },    "fusion360": null   },+  {+   "name": "sch_text",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_text",+    "match": "exact"+   },+   "fusion360": null+  },+  {+   "name": "sch_trace_point",+   "tier": "core",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_trace_point",+    "match": "exact"+   },+   "fusion360": null+  },   {    "name": "schematic_data",    "tier": "core",-   "altium": "altium_schematic_data",+   "source": "altium",+   "altium": {+    "verb": "altium_schematic_data",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_sch_components",     "match": "partial"@@ -542,14 +952,22 @@   {    "name": "set_models",    "tier": "core",-   "altium": "altium_set_models",+   "source": "altium",+   "altium": {+    "verb": "altium_set_models",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "set_outline",    "tier": "core",-   "altium": "altium_set_outline",+   "source": "altium",+   "altium": {+    "verb": "altium_set_outline",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_board_outline",     "match": "exact"@@ -562,14 +980,22 @@   {    "name": "set_params",    "tier": "core",-   "altium": "altium_set_params",+   "source": "altium",+   "altium": {+    "verb": "altium_set_params",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "set_track_width",    "tier": "core",-   "altium": "altium_set_track_width",+   "source": "altium",+   "altium": {+    "verb": "altium_set_track_width",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_modify_track",     "match": "partial"@@ -582,21 +1008,33 @@   {    "name": "set_visibility",    "tier": "core",-   "altium": "altium_set_visibility",+   "source": "altium",+   "altium": {+    "verb": "altium_set_visibility",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "sheet_params",    "tier": "core",-   "altium": "altium_sheet_params",+   "source": "altium",+   "altium": {+    "verb": "altium_sheet_params",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "silk_state",    "tier": "core",-   "altium": "altium_silk_state",+   "source": "altium",+   "altium": {+    "verb": "altium_silk_state",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_silk_state",@@ -606,7 +1044,11 @@   {    "name": "swap_footprint",    "tier": "core",-   "altium": "altium_swap_footprint",+   "source": "altium",+   "altium": {+    "verb": "altium_swap_footprint",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_update_footprints_from_library",     "match": "partial"@@ -616,21 +1058,33 @@   {    "name": "symbol_prims",    "tier": "core",-   "altium": "altium_symbol_prims",+   "source": "altium",+   "altium": {+    "verb": "altium_symbol_prims",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "xcopy_footprint",    "tier": "core",-   "altium": "altium_xcopy_footprint",+   "source": "altium",+   "altium": {+    "verb": "altium_xcopy_footprint",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "add_rule",    "tier": "native",-   "altium": "altium_add_rule",+   "source": "altium",+   "altium": {+    "verb": "altium_add_rule",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_add_rule",     "match": "exact"@@ -640,7 +1094,11 @@   {    "name": "annotate",    "tier": "native",-   "altium": "altium_annotate",+   "source": "altium",+   "altium": {+    "verb": "altium_annotate",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_annotate",     "match": "exact"@@ -650,7 +1108,11 @@   {    "name": "apply_pours",    "tier": "native",-   "altium": "altium_apply_pours",+   "source": "altium",+   "altium": {+    "verb": "altium_apply_pours",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_add_zone / kicad_apply_zone_plan",     "match": "exact"@@ -663,7 +1125,11 @@   {    "name": "autoroute",    "tier": "native",-   "altium": "altium_autoroute",+   "source": "altium",+   "altium": {+    "verb": "altium_autoroute",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_autoroute",     "match": "exact"@@ -676,42 +1142,66 @@   {    "name": "build_symbol_modes",    "tier": "native",-   "altium": "altium_build_symbol_modes",+   "source": "altium",+   "altium": {+    "verb": "altium_build_symbol_modes",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "cleanup_libs",    "tier": "native",-   "altium": "altium_cleanup_libs",+   "source": "altium",+   "altium": {+    "verb": "altium_cleanup_libs",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "compile",    "tier": "native",-   "altium": "altium_compile",+   "source": "altium",+   "altium": {+    "verb": "altium_compile",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "component_classes",    "tier": "native",-   "altium": "altium_component_classes",+   "source": "altium",+   "altium": {+    "verb": "altium_component_classes",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "diff_pairs",    "tier": "native",-   "altium": "altium_diff_pairs",+   "source": "altium",+   "altium": {+    "verb": "altium_diff_pairs",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "export_bom",    "tier": "native",-   "altium": "altium_export_bom",+   "source": "altium",+   "altium": {+    "verb": "altium_export_bom",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_export_bom_csv",     "match": "partial"@@ -724,7 +1214,11 @@   {    "name": "export_gerber",    "tier": "native",-   "altium": "altium_export_gerber",+   "source": "altium",+   "altium": {+    "verb": "altium_export_gerber",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_export_gerber",     "match": "exact"@@ -737,7 +1231,11 @@   {    "name": "export_manufacturing",    "tier": "native",-   "altium": "altium_export_manufacturing",+   "source": "altium",+   "altium": {+    "verb": "altium_export_manufacturing",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_export_manufacturing",     "match": "exact"@@ -750,7 +1248,11 @@   {    "name": "export_pdf",    "tier": "native",-   "altium": "altium_export_pdf",+   "source": "altium",+   "altium": {+    "verb": "altium_export_pdf",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_export_pdf",     "match": "exact"@@ -760,7 +1262,11 @@   {    "name": "export_step",    "tier": "native",-   "altium": "altium_export_step",+   "source": "altium",+   "altium": {+    "verb": "altium_export_step",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_export_step",     "match": "exact"@@ -773,7 +1279,11 @@   {    "name": "install_library",    "tier": "native",-   "altium": "altium_install_library",+   "source": "altium",+   "altium": {+    "verb": "altium_install_library",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_install_library",     "match": "exact"@@ -783,7 +1293,11 @@   {    "name": "install_library_bundle",    "tier": "native",-   "altium": "altium_install_library_bundle",+   "source": "altium",+   "altium": {+    "verb": "altium_install_library_bundle",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_install_library_bundle",     "match": "exact"@@ -796,14 +1310,22 @@   {    "name": "list_installed_libraries",    "tier": "native",-   "altium": "altium_list_installed_libraries",+   "source": "altium",+   "altium": {+    "verb": "altium_list_installed_libraries",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "net_classes",    "tier": "native",-   "altium": "altium_net_classes",+   "source": "altium",+   "altium": {+    "verb": "altium_net_classes",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_net_classes",     "match": "exact"@@ -816,7 +1338,11 @@   {    "name": "netlist",    "tier": "native",-   "altium": "altium_netlist",+   "source": "altium",+   "altium": {+    "verb": "altium_netlist",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_netlist",     "match": "exact"@@ -829,14 +1355,22 @@   {    "name": "panelize",    "tier": "native",-   "altium": "altium_panelize",+   "source": "altium",+   "altium": {+    "verb": "altium_panelize",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "pcb_report",    "tier": "native",-   "altium": "altium_pcb_report",+   "source": "altium",+   "altium": {+    "verb": "altium_pcb_report",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_errors",     "match": "partial"@@ -846,7 +1380,11 @@   {    "name": "pour_state",    "tier": "native",-   "altium": "altium_pour_state",+   "source": "altium",+   "altium": {+    "verb": "altium_pour_state",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_pour_state",     "match": "exact"@@ -859,7 +1397,11 @@   {    "name": "remove_pours",    "tier": "native",-   "altium": "altium_remove_pours",+   "source": "altium",+   "altium": {+    "verb": "altium_remove_pours",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_remove_zone",     "match": "exact"@@ -869,17 +1411,36 @@     "match": "exact"    }   },+  {+   "name": "render_schematic",+   "tier": "native",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_render_schematic",+    "match": "exact"+   },+   "fusion360": null+  },   {    "name": "replicate_layout",    "tier": "native",-   "altium": "altium_replicate_layout",+   "source": "altium",+   "altium": {+    "verb": "altium_replicate_layout",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "repour",    "tier": "native",-   "altium": "altium_repour",+   "source": "altium",+   "altium": {+    "verb": "altium_repour",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_repour",     "match": "exact"@@ -892,7 +1453,11 @@   {    "name": "routing_drc",    "tier": "native",-   "altium": "altium_routing_drc",+   "source": "altium",+   "altium": {+    "verb": "altium_routing_drc",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_routing_validate",     "match": "partial"@@ -905,7 +1470,11 @@   {    "name": "run_drc",    "tier": "native",-   "altium": "altium_run_drc",+   "source": "altium",+   "altium": {+    "verb": "altium_run_drc",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_run_drc",     "match": "exact"@@ -918,7 +1487,11 @@   {    "name": "run_erc",    "tier": "native",-   "altium": "altium_run_erc",+   "source": "altium",+   "altium": {+    "verb": "altium_run_erc",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_run_erc",     "match": "exact"@@ -928,10 +1501,25 @@     "match": "exact"    }   },+  {+   "name": "sch_update_from_library",+   "tier": "native",+   "source": "proposed",+   "altium": null,+   "kicad": {+    "verb": "kicad_sch_update_from_library",+    "match": "exact"+   },+   "fusion360": null+  },   {    "name": "set_design_rules",    "tier": "native",-   "altium": "altium_set_design_rules",+   "source": "altium",+   "altium": {+    "verb": "altium_set_design_rules",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_set_design_rules",     "match": "exact"@@ -944,28 +1532,44 @@   {    "name": "silkscreen_prep",    "tier": "native",-   "altium": "altium_silkscreen_prep",+   "source": "altium",+   "altium": {+    "verb": "altium_silkscreen_prep",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "symbol_mode",    "tier": "native",-   "altium": "altium_symbol_mode",+   "source": "altium",+   "altium": {+    "verb": "altium_symbol_mode",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "teardrops",    "tier": "native",-   "altium": "altium_teardrops",+   "source": "altium",+   "altium": {+    "verb": "altium_teardrops",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "uninstall_library",    "tier": "native",-   "altium": "altium_uninstall_library",+   "source": "altium",+   "altium": {+    "verb": "altium_uninstall_library",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_uninstall_library",     "match": "exact"@@ -975,7 +1579,11 @@   {    "name": "update_pcb",    "tier": "native",-   "altium": "altium_update_pcb",+   "source": "altium",+   "altium": {+    "verb": "altium_update_pcb",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_update_pcb",     "match": "exact"@@ -985,21 +1593,33 @@   {    "name": "assembly_check",    "tier": "checks",-   "altium": "altium_assembly_check",+   "source": "altium",+   "altium": {+    "verb": "altium_assembly_check",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "auto_classes",    "tier": "checks",-   "altium": "altium_auto_classes",+   "source": "altium",+   "altium": {+    "verb": "altium_auto_classes",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "board_features",    "tier": "checks",-   "altium": "altium_board_features",+   "source": "altium",+   "altium": {+    "verb": "altium_board_features",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_add_mounting_hole",     "match": "partial"@@ -1009,14 +1629,22 @@   {    "name": "board_report",    "tier": "checks",-   "altium": "altium_board_report",+   "source": "altium",+   "altium": {+    "verb": "altium_board_report",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "bom",    "tier": "checks",-   "altium": "altium_bom",+   "source": "altium",+   "altium": {+    "verb": "altium_bom",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_board_bom",@@ -1026,21 +1654,33 @@   {    "name": "build_board",    "tier": "checks",-   "altium": "altium_build_board",+   "source": "altium",+   "altium": {+    "verb": "altium_build_board",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "build_footprint",    "tier": "checks",-   "altium": "altium_build_footprint",+   "source": "altium",+   "altium": {+    "verb": "altium_build_footprint",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "build_schematic",    "tier": "checks",-   "altium": "altium_build_schematic",+   "source": "altium",+   "altium": {+    "verb": "altium_build_schematic",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_schematic_plan / fusion_schematic_run",@@ -1050,21 +1690,33 @@   {    "name": "check_orientation",    "tier": "checks",-   "altium": "altium_check_orientation",+   "source": "altium",+   "altium": {+    "verb": "altium_check_orientation",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "copper_balance",    "tier": "checks",-   "altium": "altium_copper_balance",+   "source": "altium",+   "altium": {+    "verb": "altium_copper_balance",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "cross_check",    "tier": "checks",-   "altium": "altium_cross_check",+   "source": "altium",+   "altium": {+    "verb": "altium_cross_check",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_analyze_connections",     "match": "partial"@@ -1074,14 +1726,22 @@   {    "name": "current_capacity",    "tier": "checks",-   "altium": "altium_current_capacity",+   "source": "altium",+   "altium": {+    "verb": "altium_current_capacity",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "fab_check",    "tier": "checks",-   "altium": "altium_fab_check",+   "source": "altium",+   "altium": {+    "verb": "altium_fab_check",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_fab_check",     "match": "exact"@@ -1091,70 +1751,110 @@   {    "name": "find_space",    "tier": "checks",-   "altium": "altium_find_space",+   "source": "altium",+   "altium": {+    "verb": "altium_find_space",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "footprint_from_land_pattern",    "tier": "checks",-   "altium": "altium_footprint_from_land_pattern",+   "source": "altium",+   "altium": {+    "verb": "altium_footprint_from_land_pattern",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "height_check",    "tier": "checks",-   "altium": "altium_height_check",+   "source": "altium",+   "altium": {+    "verb": "altium_height_check",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "impedance",    "tier": "checks",-   "altium": "altium_impedance",+   "source": "altium",+   "altium": {+    "verb": "altium_impedance",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "import_part",    "tier": "checks",-   "altium": "altium_import_part",+   "source": "altium",+   "altium": {+    "verb": "altium_import_part",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "jlcpcb_order",    "tier": "checks",-   "altium": "altium_jlcpcb_order",+   "source": "altium",+   "altium": {+    "verb": "altium_jlcpcb_order",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "length_tune",    "tier": "checks",-   "altium": "altium_length_tune",+   "source": "altium",+   "altium": {+    "verb": "altium_length_tune",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "net_lengths",    "tier": "checks",-   "altium": "altium_net_lengths",+   "source": "altium",+   "altium": {+    "verb": "altium_net_lengths",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "pin_pad_check",    "tier": "checks",-   "altium": "altium_pin_pad_check",+   "source": "altium",+   "altium": {+    "verb": "altium_pin_pad_check",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "placement_check",    "tier": "checks",-   "altium": "altium_placement_check",+   "source": "altium",+   "altium": {+    "verb": "altium_placement_check",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_placement_validate",     "match": "partial"@@ -1164,7 +1864,11 @@   {    "name": "read_sheet_file",    "tier": "checks",-   "altium": "altium_read_sheet_file",+   "source": "altium",+   "altium": {+    "verb": "altium_read_sheet_file",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_read_sheet_file",@@ -1174,14 +1878,22 @@   {    "name": "return_path",    "tier": "checks",-   "altium": "altium_return_path",+   "source": "altium",+   "altium": {+    "verb": "altium_return_path",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "review_board",    "tier": "checks",-   "altium": "altium_review_board",+   "source": "altium",+   "altium": {+    "verb": "altium_review_board",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_lint_board",     "match": "partial"@@ -1191,7 +1903,11 @@   {    "name": "route_pair",    "tier": "checks",-   "altium": "altium_route_pair",+   "source": "altium",+   "altium": {+    "verb": "altium_route_pair",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_route_pair",     "match": "exact"@@ -1201,7 +1917,11 @@   {    "name": "schematic_review",    "tier": "checks",-   "altium": "altium_schematic_review",+   "source": "altium",+   "altium": {+    "verb": "altium_schematic_review",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_sch_check / kicad_design_review / kicad_lint_schematic",     "match": "partial"@@ -1211,35 +1931,55 @@   {    "name": "silk_designators",    "tier": "checks",-   "altium": "altium_silk_designators",+   "source": "altium",+   "altium": {+    "verb": "altium_silk_designators",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "test_board",    "tier": "checks",-   "altium": "altium_test_board",+   "source": "altium",+   "altium": {+    "verb": "altium_test_board",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "thermal_vias",    "tier": "checks",-   "altium": "altium_thermal_vias",+   "source": "altium",+   "altium": {+    "verb": "altium_thermal_vias",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "via_fence",    "tier": "checks",-   "altium": "altium_via_fence",+   "source": "altium",+   "altium": {+    "verb": "altium_via_fence",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "activate_document",    "tier": "app",-   "altium": "altium_activate_document",+   "source": "altium",+   "altium": {+    "verb": "altium_activate_document",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_activate_document",@@ -1249,42 +1989,66 @@   {    "name": "agent_recover",    "tier": "app",-   "altium": "altium_agent_recover",+   "source": "altium",+   "altium": {+    "verb": "altium_agent_recover",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "agent_start",    "tier": "app",-   "altium": "altium_agent_start",+   "source": "altium",+   "altium": {+    "verb": "altium_agent_start",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "agent_status",    "tier": "app",-   "altium": "altium_agent_status",+   "source": "altium",+   "altium": {+    "verb": "altium_agent_status",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "agent_stop",    "tier": "app",-   "altium": "altium_agent_stop",+   "source": "altium",+   "altium": {+    "verb": "altium_agent_stop",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "animate_view",    "tier": "app",-   "altium": "altium_animate_view",+   "source": "altium",+   "altium": {+    "verb": "altium_animate_view",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "check_dialogs",    "tier": "app",-   "altium": "altium_check_dialogs",+   "source": "altium",+   "altium": {+    "verb": "altium_check_dialogs",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_check_dialogs",@@ -1294,7 +2058,11 @@   {    "name": "close",    "tier": "app",-   "altium": "altium_close",+   "source": "altium",+   "altium": {+    "verb": "altium_close",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_close",     "match": "exact"@@ -1307,7 +2075,11 @@   {    "name": "close_document",    "tier": "app",-   "altium": "altium_close_document",+   "source": "altium",+   "altium": {+    "verb": "altium_close_document",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_close_document",@@ -1317,14 +2089,22 @@   {    "name": "connect_workspace",    "tier": "app",-   "altium": "altium_connect_workspace",+   "source": "altium",+   "altium": {+    "verb": "altium_connect_workspace",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "demo",    "tier": "app",-   "altium": "altium_demo",+   "source": "altium",+   "altium": {+    "verb": "altium_demo",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_demo",     "match": "exact"@@ -1337,7 +2117,11 @@   {    "name": "describe",    "tier": "app",-   "altium": "altium_describe",+   "source": "altium",+   "altium": {+    "verb": "altium_describe",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_describe",     "match": "exact"@@ -1350,7 +2134,11 @@   {    "name": "diagnostics",    "tier": "app",-   "altium": "altium_diagnostics",+   "source": "altium",+   "altium": {+    "verb": "altium_diagnostics",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_diagnostics",     "match": "exact"@@ -1360,7 +2148,11 @@   {    "name": "dialog_log",    "tier": "app",-   "altium": "altium_dialog_log",+   "source": "altium",+   "altium": {+    "verb": "altium_dialog_log",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_dialog_log",@@ -1370,7 +2162,11 @@   {    "name": "dismiss_dialogs",    "tier": "app",-   "altium": "altium_dismiss_dialogs",+   "source": "altium",+   "altium": {+    "verb": "altium_dismiss_dialogs",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_dismiss_dialogs",     "match": "exact"@@ -1383,35 +2179,55 @@   {    "name": "ensure_licensed",    "tier": "app",-   "altium": "altium_ensure_licensed",+   "source": "altium",+   "altium": {+    "verb": "altium_ensure_licensed",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "eval",    "tier": "app",-   "altium": "altium_eval",+   "source": "altium",+   "altium": {+    "verb": "altium_eval",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "extension_ping",    "tier": "app",-   "altium": "altium_extension_ping",+   "source": "altium",+   "altium": {+    "verb": "altium_extension_ping",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "foreground",    "tier": "app",-   "altium": "altium_foreground",+   "source": "altium",+   "altium": {+    "verb": "altium_foreground",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "install",    "tier": "app",-   "altium": "altium_install",+   "source": "altium",+   "altium": {+    "verb": "altium_install",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_install",@@ -1421,28 +2237,44 @@   {    "name": "install_extension",    "tier": "app",-   "altium": "altium_install_extension",+   "source": "altium",+   "altium": {+    "verb": "altium_install_extension",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "install_receipt",    "tier": "app",-   "altium": "altium_install_receipt",+   "source": "altium",+   "altium": {+    "verb": "altium_install_receipt",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "instances",    "tier": "app",-   "altium": "altium_instances",+   "source": "altium",+   "altium": {+    "verb": "altium_instances",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "launch",    "tier": "app",-   "altium": "altium_launch",+   "source": "altium",+   "altium": {+    "verb": "altium_launch",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_launch",     "match": "exact"@@ -1455,14 +2287,22 @@   {    "name": "license",    "tier": "app",-   "altium": "altium_license",+   "source": "altium",+   "altium": {+    "verb": "altium_license",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "license_status",    "tier": "app",-   "altium": "altium_license_status",+   "source": "altium",+   "altium": {+    "verb": "altium_license_status",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_license_status",@@ -1472,7 +2312,11 @@   {    "name": "list_commands",    "tier": "app",-   "altium": "altium_list_commands",+   "source": "altium",+   "altium": {+    "verb": "altium_list_commands",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_list_commands",@@ -1482,7 +2326,11 @@   {    "name": "open_document",    "tier": "app",-   "altium": "altium_open_document",+   "source": "altium",+   "altium": {+    "verb": "altium_open_document",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_open_board / kicad_open_schematic",     "match": "partial"@@ -1495,21 +2343,33 @@   {    "name": "open_project",    "tier": "app",-   "altium": "altium_open_project",+   "source": "altium",+   "altium": {+    "verb": "altium_open_project",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "panel",    "tier": "app",-   "altium": "altium_panel",+   "source": "altium",+   "altium": {+    "verb": "altium_panel",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "progress",    "tier": "app",-   "altium": "altium_progress",+   "source": "altium",+   "altium": {+    "verb": "altium_progress",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_progress",     "match": "exact"@@ -1519,7 +2379,11 @@   {    "name": "readiness",    "tier": "app",-   "altium": "altium_readiness",+   "source": "altium",+   "altium": {+    "verb": "altium_readiness",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_readiness",     "match": "exact"@@ -1532,7 +2396,11 @@   {    "name": "run_command",    "tier": "app",-   "altium": "altium_run_command",+   "source": "altium",+   "altium": {+    "verb": "altium_run_command",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_run_command",@@ -1542,7 +2410,11 @@   {    "name": "run_script",    "tier": "app",-   "altium": "altium_run_script",+   "source": "altium",+   "altium": {+    "verb": "altium_run_script",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_run_script",@@ -1552,7 +2424,11 @@   {    "name": "save",    "tier": "app",-   "altium": "altium_save",+   "source": "altium",+   "altium": {+    "verb": "altium_save",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_save",     "match": "exact"@@ -1565,14 +2441,22 @@   {    "name": "sch_zoom",    "tier": "app",-   "altium": "altium_sch_zoom",+   "source": "altium",+   "altium": {+    "verb": "altium_sch_zoom",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "select_net",    "tier": "app",-   "altium": "altium_select_net",+   "source": "altium",+   "altium": {+    "verb": "altium_select_net",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_select_net",     "match": "exact"@@ -1585,7 +2469,11 @@   {    "name": "selection",    "tier": "app",-   "altium": "altium_selection",+   "source": "altium",+   "altium": {+    "verb": "altium_selection",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_selection",     "match": "exact"@@ -1595,14 +2483,22 @@   {    "name": "selftest_script_error",    "tier": "app",-   "altium": "altium_selftest_script_error",+   "source": "altium",+   "altium": {+    "verb": "altium_selftest_script_error",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "set_layer_visibility",    "tier": "app",-   "altium": "altium_set_layer_visibility",+   "source": "altium",+   "altium": {+    "verb": "altium_set_layer_visibility",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_set_layer_visibility",@@ -1612,14 +2508,22 @@   {    "name": "setup_trial",    "tier": "app",-   "altium": "altium_setup_trial",+   "source": "altium",+   "altium": {+    "verb": "altium_setup_trial",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "show_2d_board",    "tier": "app",-   "altium": "altium_show_2d_board",+   "source": "altium",+   "altium": {+    "verb": "altium_show_2d_board",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_show_2d_board",     "match": "exact"@@ -1632,7 +2536,11 @@   {    "name": "show_3d_board",    "tier": "app",-   "altium": "altium_show_3d_board",+   "source": "altium",+   "altium": {+    "verb": "altium_show_3d_board",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_show_3d_board",     "match": "exact"@@ -1645,7 +2553,11 @@   {    "name": "show_3d_chip",    "tier": "app",-   "altium": "altium_show_3d_chip",+   "source": "altium",+   "altium": {+    "verb": "altium_show_3d_chip",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_show_3d_chip",     "match": "exact"@@ -1658,7 +2570,11 @@   {    "name": "show_footprint",    "tier": "app",-   "altium": "altium_show_footprint",+   "source": "altium",+   "altium": {+    "verb": "altium_show_footprint",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_show_footprint",     "match": "exact"@@ -1671,7 +2587,11 @@   {    "name": "show_library",    "tier": "app",-   "altium": "altium_show_library",+   "source": "altium",+   "altium": {+    "verb": "altium_show_library",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_show_library",     "match": "exact"@@ -1684,7 +2604,11 @@   {    "name": "show_project",    "tier": "app",-   "altium": "altium_show_project",+   "source": "altium",+   "altium": {+    "verb": "altium_show_project",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_show_project",     "match": "exact"@@ -1697,7 +2621,11 @@   {    "name": "show_schematic",    "tier": "app",-   "altium": "altium_show_schematic",+   "source": "altium",+   "altium": {+    "verb": "altium_show_schematic",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_show_schematic",     "match": "exact"@@ -1710,7 +2638,11 @@   {    "name": "show_symbol",    "tier": "app",-   "altium": "altium_show_symbol",+   "source": "altium",+   "altium": {+    "verb": "altium_show_symbol",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_show_symbol",     "match": "exact"@@ -1723,7 +2655,11 @@   {    "name": "signin",    "tier": "app",-   "altium": "altium_signin",+   "source": "altium",+   "altium": {+    "verb": "altium_signin",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_signin",@@ -1733,7 +2669,11 @@   {    "name": "signin_status",    "tier": "app",-   "altium": "altium_signin_status",+   "source": "altium",+   "altium": {+    "verb": "altium_signin_status",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_signin_status",@@ -1743,7 +2683,11 @@   {    "name": "state",    "tier": "app",-   "altium": "altium_state",+   "source": "altium",+   "altium": {+    "verb": "altium_state",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_state",     "match": "exact"@@ -1756,7 +2700,11 @@   {    "name": "status",    "tier": "app",-   "altium": "altium_status",+   "source": "altium",+   "altium": {+    "verb": "altium_status",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_status",     "match": "exact"@@ -1769,7 +2717,11 @@   {    "name": "uninstall",    "tier": "app",-   "altium": "altium_uninstall",+   "source": "altium",+   "altium": {+    "verb": "altium_uninstall",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_uninstall",     "match": "exact"@@ -1782,7 +2734,11 @@   {    "name": "window_info",    "tier": "app",-   "altium": "altium_window_info",+   "source": "altium",+   "altium": {+    "verb": "altium_window_info",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_window_info",     "match": "exact"@@ -1792,7 +2748,11 @@   {    "name": "zoom_to",    "tier": "app",-   "altium": "altium_zoom_to",+   "source": "altium",+   "altium": {+    "verb": "altium_zoom_to",+    "match": "exact"+   },    "kicad": null,    "fusion360": {     "verb": "fusion_zoom_to",@@ -1802,133 +2762,209 @@   {    "name": "a365_configure",    "tier": "platform",-   "altium": "altium_a365_configure",+   "source": "altium",+   "altium": {+    "verb": "altium_a365_configure",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "a365_files_upload",    "tier": "platform",-   "altium": "altium_a365_files_upload",+   "source": "altium",+   "altium": {+    "verb": "altium_a365_files_upload",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "a365_library_overview",    "tier": "platform",-   "altium": "altium_a365_library_overview",+   "source": "altium",+   "altium": {+    "verb": "altium_a365_library_overview",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "a365_library_schema",    "tier": "platform",-   "altium": "altium_a365_library_schema",+   "source": "altium",+   "altium": {+    "verb": "altium_a365_library_schema",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "a365_logout",    "tier": "platform",-   "altium": "altium_a365_logout",+   "source": "altium",+   "altium": {+    "verb": "altium_a365_logout",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "a365_oauth_begin",    "tier": "platform",-   "altium": "altium_a365_oauth_begin",+   "source": "altium",+   "altium": {+    "verb": "altium_a365_oauth_begin",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "a365_oauth_cancel",    "tier": "platform",-   "altium": "altium_a365_oauth_cancel",+   "source": "altium",+   "altium": {+    "verb": "altium_a365_oauth_cancel",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "a365_oauth_status",    "tier": "platform",-   "altium": "altium_a365_oauth_status",+   "source": "altium",+   "altium": {+    "verb": "altium_a365_oauth_status",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "a365_query",    "tier": "platform",-   "altium": "altium_a365_query",+   "source": "altium",+   "altium": {+    "verb": "altium_a365_query",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "a365_refresh",    "tier": "platform",-   "altium": "altium_a365_refresh",+   "source": "altium",+   "altium": {+    "verb": "altium_a365_refresh",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "a365_status",    "tier": "platform",-   "altium": "altium_a365_status",+   "source": "altium",+   "altium": {+    "verb": "altium_a365_status",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "compile_intlib",    "tier": "platform",-   "altium": "altium_compile_intlib",+   "source": "altium",+   "altium": {+    "verb": "altium_compile_intlib",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "extract_intlib",    "tier": "platform",-   "altium": "altium_extract_intlib",+   "source": "altium",+   "altium": {+    "verb": "altium_extract_intlib",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "import_kicad",    "tier": "platform",-   "altium": "altium_import_kicad",+   "source": "altium",+   "altium": {+    "verb": "altium_import_kicad",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "outjob_info",    "tier": "platform",-   "altium": "altium_outjob_info",+   "source": "altium",+   "altium": {+    "verb": "altium_outjob_info",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "run_outjob",    "tier": "platform",-   "altium": "altium_run_outjob",+   "source": "altium",+   "altium": {+    "verb": "altium_run_outjob",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "variants",    "tier": "platform",-   "altium": "altium_variants",+   "source": "altium",+   "altium": {+    "verb": "altium_variants",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "workspace_place",    "tier": "platform",-   "altium": "altium_workspace_place",+   "source": "altium",+   "altium": {+    "verb": "altium_workspace_place",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   },   {    "name": "workspace_search",    "tier": "platform",-   "altium": "altium_workspace_search",+   "source": "altium",+   "altium": {+    "verb": "altium_workspace_search",+    "match": "exact"+   },    "kicad": null,    "fusion360": null   }
verbs/standard.json+1145
@@ -3,6 +3,7 @@   "bridge": "altium",   "version": "0.2.75"  },+ "proposed": 21,  "compared": {   "kicad": "1.0.62",   "fusion360": "1.12.1"@@ -18,6 +19,7 @@   {    "name": "add_body",    "tier": "core",+   "source": "altium",    "summary": "Put a 3D body on a footprint of a PcbLib: a STEP model, or an extruded box when no step is given. It REPLACES the footprint's existing 3D bodies (a re-import never stacks a second model) unless keepExisting:true. The bridge then re-aligns bodies onto the pads (normalize_bodies) and returns a frame.",    "input": {     "bhMil": "int, default 100 - box depth",@@ -64,6 +66,7 @@   {    "name": "add_models",    "tier": "core",+   "source": "altium",    "summary": "Attach one or more PCBLIB footprint models, parameters, comment and description to a SchLib component (Altium's several-footprints-per-symbol mechanism).",    "input": {     "comment": "string",@@ -110,6 +113,7 @@   {    "name": "add_symbol_art",    "tier": "core",+   "source": "altium",    "summary": "Draw the chip-outline artwork (the chip-thumbnailer polylines adom-symbol baked into the KiCad symbol) into a SchLib component, fitted to its body rectangle, so the Altium symbol shows the same chip as KiCad and Fusion.",    "input": {     "clear": "bool, default true: remove the component's existing polylines/lines first",@@ -145,6 +149,7 @@   {    "name": "apply_silkscreen",    "tier": "core",+   "source": "altium",    "summary": "Land a silkscreen plan in one undo step: designators and comments moved, sized and turned (or hidden), free overlay texts and lines added (bottom texts mirrored), earlier ones removed; answers silk_state after.",    "input": {     "comments": "[same] - the value",@@ -192,6 +197,7 @@   {    "name": "board_outline",    "tier": "core",+   "source": "altium",    "summary": "Draw the board shape as tracks and arcs on a mechanical layer: the outline a fab house reads from the Gerbers. A board built by script has its shape but nothing on an outline layer, so its GM1/GKO Gerbers are empty.",    "input": {     "filePath": "path to the .PcbDoc - optional",@@ -223,6 +229,7 @@   {    "name": "board_shape",    "tier": "core",+   "source": "altium",    "summary": "Redefine the CURRENT board's outline as a wMm x hMm rectangle at (x0Mm, y0Mm) by rewriting the board outline's segments.",    "input": {     "hMm": "number, default 15",@@ -262,6 +269,7 @@   {    "name": "board_summary",    "tier": "core",+   "source": "altium",    "summary": "One-screen summary of the current board, shaped from one read_board round trip: component counts by side, nets, copper layers actually in use, rule counts.",    "input": {     "limit": "int, default 2000",@@ -290,6 +298,7 @@   {    "name": "clone_symbol",    "tier": "core",+   "source": "altium",    "summary": "Copy a symbol inside the current SchLib under a new name, all display modes included.",    "input": {     "from": "string - existing LibReference",@@ -323,6 +332,7 @@   {    "name": "component_data",    "tier": "core",+   "source": "altium",    "summary": "Placement data for one board component, or for all of them: footprint pattern, comment, layer/side, position, rotation, size, pad count and the nets on its pads.",    "input": {     "designator": "string - optional; omit for every component",@@ -352,6 +362,7 @@   {    "name": "component_pins",    "tier": "core",+   "source": "altium",    "summary": "Every pad of one board component with its net, position, layer, size and hole.",    "input": {     "designator": "string (required), e.g. U1"@@ -380,6 +391,7 @@   {    "name": "copper_layers",    "tier": "core",+   "source": "altium",    "summary": "Every copper layer Altium can address on the current board (top, mid 1-30, planes 1-16, bottom) with names and visibility.",    "input": {},    "output": {@@ -402,6 +414,7 @@   {    "name": "copy_footprint",    "tier": "core",+   "source": "altium",    "summary": "Duplicate a footprint inside the current PcbLib under a new name (every primitive replicated).",    "input": {     "from": "string",@@ -433,6 +446,7 @@   {    "name": "create_footprint",    "tier": "core",+   "source": "altium",    "summary": "Create one footprint from a pad list in a PcbLib (the library is created and saved if the path does not exist) and return a proof frame.",    "input": {     "description": "string",@@ -470,6 +484,7 @@   {    "name": "create_symbol",    "tier": "core",+   "source": "altium",    "summary": "Create one rectangular symbol from a pin list in a SchLib (the library is created and saved if the path does not exist) and return a proof frame.",    "input": {     "bodyHeightMil": "int, default 600",@@ -510,6 +525,7 @@   {    "name": "doc_params",    "tier": "core",+   "source": "altium",    "summary": "Read or set a sheet's document parameters: the title block (Title, DocumentNumber, Revision, DrawnBy, Author, CompanyName, ...).",    "input": {     "save": "bool, default true",@@ -540,6 +556,7 @@   {    "name": "find_symbol",    "tier": "core",+   "source": "altium",    "summary": "Find symbols (or footprints with kind:'footprint') by part of their name across libraries: the given ones, or every installed .SchLib/.PcbLib.",    "input": {     "kind": "symbol (default) | footprint",@@ -569,6 +586,7 @@   {    "name": "footprint_primitives",    "tier": "core",+   "source": "altium",    "summary": "Geometry dump of one PLACED component: its tracks, arcs, pads (with solder and paste mask expansion in um) and texts in mils with layer ids; other primitive kinds are counted.",    "input": {     "designator": "string (required) - a component on the current board, e.g. U1"@@ -597,6 +615,7 @@   {    "name": "layer_stack",    "tier": "core",+   "source": "altium",    "summary": "The CURRENT board's stack-up: copper layers in order with copper thickness and the dielectric under each (height, constant, material), and the total thickness. For impedance, current capacity and fab quotes.",    "input": {},    "output": {@@ -618,6 +637,7 @@   {    "name": "layers",    "tier": "core",+   "source": "altium",    "summary": "The current board's layer set with ids, names, kind and whether each is displayed.",    "input": {},    "output": {@@ -641,6 +661,7 @@   {    "name": "layers_in_use",    "tier": "core",+   "source": "altium",    "summary": "Which layers of the current board actually carry primitives: copper layers with copper (densest first) and every layer with anything on it.",    "input": {     "limit": "int, default 2000",@@ -670,6 +691,7 @@   {    "name": "list_designators",    "tier": "core",+   "source": "altium",    "summary": "Every component designator on the current board.",    "input": {},    "output": {@@ -692,6 +714,7 @@   {    "name": "list_library",    "tier": "core",+   "source": "altium",    "summary": "Names of every component in a .SchLib or every footprint in a .PcbLib (kind taken from the extension). Opens the library; no screenshot.",    "input": {     "libraryPath": "path to a .SchLib/.PcbLib (alias: filePath) - default: the bundled SpiritLevel SchLib",@@ -722,6 +745,7 @@   {    "name": "list_nets",    "tier": "core",+   "source": "altium",    "summary": "Every net on the current board with its pad count.",    "input": {},    "output": {@@ -744,6 +768,7 @@   {    "name": "move_parts",    "tier": "core",+   "source": "altium",    "summary": "Move and rotate placed components; each part is read back to 0.001 mm and the exact rotation. One undo step.",    "input": {     "boardId": "string (optional) - refused with board_mismatch unless this is the current board",@@ -780,6 +805,7 @@   {    "name": "net_connections",    "tier": "core",+   "source": "altium",    "summary": "Every pad on the board with its net and owner (Designator.Pad), plus a bounding span and the airline length (minimum spanning tree over its pads, airlineMm) per net. net filters to one net.",    "input": {     "limit": "int, default 4000 - caps pads",@@ -808,6 +834,7 @@   {    "name": "normalize_bodies",    "tier": "core",+   "source": "altium",    "summary": "Move every 3D body of a PcbLib's footprints (or one footprint) onto its pad cluster. A body added through the canvas lands 50000 mil from the pads in the stored frame, which makes Zoom All frame 50 inches of nothing.",    "input": {     "footprintName": "string - optional filter",@@ -838,6 +865,7 @@   {    "name": "part_parameters",    "tier": "core",+   "source": "altium",    "summary": "The parameter names a project's parts carry (with how many parts carry each), or with name, that parameter's value on every part.",    "input": {     "name": "a parameter name - optional",@@ -864,6 +892,7 @@   {    "name": "place_on_pcb",    "tier": "core",+   "source": "altium",    "summary": "Place ONE footprint from a PcbLib on a new board and return a proof frame. The single-part predecessor of altium_test_board.",    "input": {     "footprintName": "string",@@ -897,6 +926,7 @@   {    "name": "place_on_sch",    "tier": "core",+   "source": "altium",    "summary": "Place one symbol, or a ';' list of symbols, from the open SchLib on ONE new sheet (sheet sized FROM the measured parts: 500 mil gaps, 600 mil margins, A4 minimum; parts inside the frame as U1..Un with the part number as Comment); fills the title block from title/number/revision/drawnBy and places description as a text frame; saves to schPath when given. When schPath names an EXISTING .SchDoc the symbols are APPENDED to it (right of the current ones, designators continuing; sheet size and title block untouched, issue 11).",    "input": {     "description": "string (what the sheet shows, 2-3 sentences)",@@ -936,6 +966,7 @@   {    "name": "place_vias",    "tier": "core",+   "source": "altium",    "summary": "Place vias (through, top to bottom). One undo step, read back.",    "input": {     "boardId": "string (optional) - refused with board_mismatch unless this is the current board",@@ -971,6 +1002,7 @@   {    "name": "plate_vias",    "tier": "core",+   "source": "altium",    "summary": "Make every drilled pad in a PcbLib a plated MULTI-LAYER pad (all footprints, or footprintName). adom-lbr writes heatsink vias as pads with a hole; Altium loaded them on the Top Layer, so a thermal pad's vias were not through-holes until this ran.",    "input": {     "footprintName": "string (optional filter)",@@ -999,6 +1031,7 @@   {    "name": "read_board",    "tier": "core",+   "source": "altium",    "summary": "ONE round trip: components, nets, layers, copper, rules, occupancy, outline.",    "input": {     "limit": "int",@@ -1024,6 +1057,7 @@   {    "name": "read_rules",    "tier": "core",+   "source": "altium",    "summary": "Every design rule on the current board, flat, disabled ones included: name, kind ordinal, enabled, priority, both scope expressions, comment, and Altium's descriptor with the rule's VALUES (e.g. 'Clearance Constraint (Gap=6mil) (All),(All)').",    "input": {},    "output": {@@ -1046,6 +1080,7 @@   {    "name": "read_schematic",    "tier": "core",+   "source": "altium",    "summary": "Components on the CURRENT schematic sheet (designator, library reference, comment, position, parameters) in one agent round trip.",    "input": {     "limit": "int, default 500",@@ -1077,6 +1112,7 @@   {    "name": "read_symbol",    "tier": "core",+   "source": "altium",    "summary": "Read a SchLib component back: description, display-mode count, the pins of mode 0 (designator, name, electrical type), every parameter with its hidden flag, and its model links (footprints, 3D, sim).",    "input": {     "libraryPath": "path to a .SchLib - optional; opened first",@@ -1108,6 +1144,7 @@   {    "name": "remove_footprint",    "tier": "core",+   "source": "altium",    "summary": "Delete one footprint from the current PcbLib.",    "input": {     "footprintName": "string",@@ -1138,6 +1175,7 @@   {    "name": "remove_items",    "tier": "core",+   "source": "altium",    "summary": "Delete specific free tracks and vias, given exactly as altium_routing_state returned them. One undo step.",    "input": {     "boardId": "string (optional) - refused with board_mismatch unless this is the current board",@@ -1172,6 +1210,7 @@   {    "name": "remove_symbol",    "tier": "core",+   "source": "altium",    "summary": "Delete one component from the current SchLib.",    "input": {     "libraryPath": "path to a .SchLib - optional; opened first",@@ -1202,6 +1241,7 @@   {    "name": "rename_footprint",    "tier": "core",+   "source": "altium",    "summary": "Rename a footprint in the current PcbLib.",    "input": {     "from": "string",@@ -1235,6 +1275,7 @@   {    "name": "rename_symbol",    "tier": "core",+   "source": "altium",    "summary": "Rename a component (LibReference) in the current SchLib.",    "input": {     "from": "string",@@ -1267,6 +1308,7 @@   {    "name": "ripup_nets",    "tier": "core",+   "source": "altium",    "summary": "Delete every free track, arc and via on each named net. One undo step.",    "input": {     "boardId": "string (optional) - refused with board_mismatch unless this is the current board",@@ -1296,6 +1338,7 @@   {    "name": "route_net",    "tier": "core",+   "source": "altium",    "summary": "Route one net as tracks, segment by segment; a waypoint on another layer drops a via there. One undo step, read back.",    "input": {     "boardId": "string (optional) - refused with board_mismatch unless this is the current board",@@ -1352,6 +1395,7 @@   {    "name": "routing_state",    "tier": "core",+   "source": "altium",    "summary": "The WHOLE current board as data, in mm: tracks, arcs, vias, pads (with owner and net), components (ref, x, y, rotation, side), polygon pours, the outline, the unrouted (ratsnest) count, and a revision hash.",    "input": {     "expectPath": "string (optional) - refuse with wrong_board unless this .PcbDoc is the current board"@@ -1388,6 +1432,7 @@   {    "name": "rules_by_kind",    "tier": "core",+   "source": "altium",    "summary": "The current board's ENABLED design rules grouped by rule kind (Clearance, Width, RoutingVias, ...), each group sorted by priority. Shaped from one read_board round trip.",    "input": {     "limit": "int, default 2000",@@ -1412,9 +1457,103 @@    "longRunning": false,    "timeoutSeconds": 120   },+  {+   "name": "sch_bus",+   "tier": "core",+   "source": "proposed",+   "summary": "Draw a bus as a polyline (one bus segment per pair of points), optionally with a bus label such as D[0..7] or a group {SDA SCL} at its first point. One undo step.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "points": "[[x, y], [x, y], ...] mm (required)",+    "label": "\"D[0..7]\" or \"{SDA SCL}\": the nets the bus carries",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "ids": "[bus segment id]",+    "label": "{id, text} or null",+    "saved": "bool"+   },+   "hint": "A bus carries the nets its label names, and each member wire needs its own label. sch_connect_to_bus does the member wires, entries and labels for a set of pins.",+   "pitfalls": [+    "A bus with no label carries nothing: ERC reports its members as unconnected."+   ],+   "related": [+    "sch_bus_entry",+    "sch_connect_to_bus",+    "sch_delete_wire",+    "sch_items"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "points": [+     [+      203.2,+      50.8+     ],+     [+      203.2,+      101.6+     ]+    ],+    "label": "D[0..7]"+   },+   "longRunning": true,+   "timeoutSeconds": 120,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_bus_entry",+   "tier": "core",+   "source": "proposed",+   "summary": "Add 45-degree bus entries: the short diagonal that joins a member wire's end to a bus. One undo step.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "entries": "[{at: [x, y] mm (the wire end), direction: up-right|down-right|up-left|down-left as seen (default down-right)}] (required)",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "added": "[{id, at, end: [x, y] (the bus side), onBus: bool}]",+    "saved": "bool"+   },+   "hint": "end is the bus side of each entry; onBus says whether it lands on a bus segment.",+   "pitfalls": [+    "The bus side must touch a bus and the other end a wire end, exactly, or ERC reports the entry as unconnected."+   ],+   "related": [+    "sch_bus",+    "sch_connect_to_bus",+    "sch_items"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "entries": [+     {+      "at": [+       200.66,+       63.5+      ],+      "direction": "up-right"+     }+    ]+   },+   "longRunning": true,+   "timeoutSeconds": 120,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },   {    "name": "sch_connect",    "tier": "core",+   "source": "altium",    "summary": "Connect pins of placed parts: a wire stub from each pin's outer end plus a net label (kind label), a power port (kind power: GND-like nets get a ground symbol) or the stub alone (kind wire); or mark a pin left open on purpose with a No ERC marker (kind noerc, no net). One undo step.",    "input": {     "connections": "[{designator, pin (number or name), net, kind: label|power|wire|noerc|port (default label), io?: input|output|bidirectional (port), stubMil (default 200)}] (required)",@@ -1457,9 +1596,210 @@    "timeoutSeconds": 90,    "unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."   },+  {+   "name": "sch_connect_pins",+   "tier": "core",+   "source": "proposed",+   "summary": "Wire pins to pins on a sheet by Ref.Pin: an L-shaped route (one horizontal and one vertical leg) for each pair, with a junction dot wherever a route meets an existing wire in a T. One undo step.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "pairs": "[{from: \"U1.1\", to: \"R5.2\", first?: h|v (the leg to draw first; default along the axis the from pin points), via?: [[x, y], ...] mm waypoints}] (required)",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "wired": "int",+    "routes": "[{from, to, points: [[x, y]], ids: [wire id]}]",+    "junctionsAdded": "[[x, y]]",+    "failed": "[{from, to, error}]",+    "saved": "bool"+   },+   "hint": "Pins are matched by number, then by name. Aligned pins get one straight wire; otherwise the route turns once. Check the result with sch_pins (connectedPins) or run_erc.",+   "pitfalls": [+    "The route does not avoid part bodies or other wires: a leg running along another wire merges the two nets. Steer with first or via, and check with sch_pins."+   ],+   "related": [+    "sch_pins",+    "sch_connect",+    "sch_delete_wire",+    "run_erc"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "pairs": [+     {+      "from": "U1.1",+      "to": "R2.1"+     },+     {+      "from": "U1.2",+      "to": "C3.1",+      "first": "v"+     }+    ]+   },+   "longRunning": true,+   "timeoutSeconds": 120,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_connect_to_bus",+   "tier": "core",+   "source": "proposed",+   "summary": "Fan pins onto a bus: for each pin a wire running to the bus, a 45-degree bus entry onto it and a member label (D0, D1 ...) on the wire. One undo step.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "pins": "[\"U1.1\", \"U1.2\"] Ref.Pin, in member order (required)",+    "bus": "id of the bus segment (default the only bus on the sheet)",+    "members": "[\"D0\", \"D1\"]: the member names in pin order",+    "prefix": "\"D\": or name members prefix + number",+    "start": "int, default 0: the first number with prefix",+    "entry": "up|down (a vertical bus) or left|right (a horizontal bus): the way the entries lean",+    "busLabel": "\"D[0..7]\": also label the bus",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "connected": "[{pin, member, wireId, entryId}]",+    "busLabel": "string or null",+    "failed": "[{pin, error}]",+    "saved": "bool"+   },+   "hint": "Members name the nets: members lists them in pin order, or prefix plus start counts up. Refused with entry_off_bus when an entry would miss the bus: extend the bus with sch_bus first.",+   "pitfalls": [+    "Pins should face the bus; a pin facing away gets a wire across its own part.",+    "Two pins at the same height on a vertical bus share an entry point and collide: offset them or lean the entries differently."+   ],+   "related": [+    "sch_bus",+    "sch_bus_entry",+    "sch_pins"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "pins": [+     "U1.1",+     "U1.7"+    ],+    "prefix": "D",+    "busLabel": "D[0..1]"+   },+   "longRunning": true,+   "timeoutSeconds": 120,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_create",+   "tier": "core",+   "source": "proposed",+   "summary": "Create an empty schematic sheet with a paper size and title block; optionally add it to a project as a child sheet of the root. It places no parts or nets (build_schematic does).",+   "input": {+    "sheet": "path of the sheet to create (required)",+    "paper": "A4, A3 ... USLetter or custom",+    "orientation": "portrait|landscape",+    "widthMm": "number (custom)",+    "heightMm": "number (custom)",+    "title": "string",+    "date": "string",+    "rev": "string",+    "company": "string",+    "comments": "[string]",+    "project": "path: add the sheet to this project under its root sheet",+    "sheetName": "string: the sheet symbol's name in the root",+    "at": "[x, y] mm: where the sheet symbol goes on the root",+    "dryRun": "bool, default false: answer the plan and change nothing"+   },+   "output": {+    "sheet": "path",+    "page": "int",+    "sheetSymbol": "{id, name, at} or null",+    "created": "bool"+   },+   "hint": "Without project the sheet stands alone. With project it is linked from the root sheet as a child sheet with the next page number.",+   "pitfalls": [+    "Never overwrites: an existing file is refused.",+    "A new child sheet has no pins on its symbol: add hierarchical ports inside, then sch_sheet_pins {import:true}."+   ],+   "related": [+    "sch_page",+    "sch_hierarchy",+    "sch_sheet_pins",+    "sch_place_part"+   ],+   "example": {+    "sheet": "C:/proj/Power.SchDoc",+    "project": "C:/proj/Board.PrjPcb",+    "sheetName": "Power",+    "title": "Power"+   },+   "longRunning": false,+   "timeoutSeconds": 30,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_delete_wire",+   "tier": "core",+   "source": "proposed",+   "summary": "Delete wires or bus segments by id, by their two ends, or every wire through a point, and remove junction dots that no longer join three or more items. One undo step.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "ids": "[wire id, ...]",+    "from": "[x, y] mm, with to: the wire with exactly these ends (either order)",+    "to": "[x, y] mm",+    "at": "[x, y] mm: every wire passing through the point",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "deleted": "[{id, from, to}]",+    "junctionsRemoved": "[[x, y]]",+    "saved": "bool"+   },+   "hint": "Read ids with sch_items. from/to matches one segment, not a whole route.",+   "pitfalls": [+    "A polyline drawn in the editor is several wires sharing ends: from/to names one segment of it."+   ],+   "related": [+    "sch_items",+    "sch_split_wire",+    "sch_junction",+    "sch_connect_pins"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "from": [+     100.33,+     60.96+    ],+    "to": [+     120.65,+     60.96+    ]+   },+   "longRunning": true,+   "timeoutSeconds": 120,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },   {    "name": "sch_edit",    "tier": "core",+   "source": "altium",    "summary": "Change placed parts on a sheet: move (to x,y mil), moveBy (dx,dy), rotate (degrees), rename (designator), re-comment (comment), delete. One undo step.",    "input": {     "edits": "[{designator, action: move|moveBy|rotate|designator|comment|delete, x,y | dx,dy | degrees | to | text}] (required)",@@ -1498,9 +1838,362 @@    "longRunning": false,    "timeoutSeconds": 90   },+  {+   "name": "sch_edit_label",+   "tier": "core",+   "source": "proposed",+   "summary": "Edit net labels: rotate, move to a point or by a delta, rename, or move every label of a net at once. One undo step.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "edits": "[{id | text (with at?: [x, y] to pick one) | net (every label of the net), rotation?: 0|90|180|270, to?: [x, y] mm (one label only), by?: [dx, dy] mm, rename?: string}] (required)",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "edited": "[{id, text, at, rotation}]",+    "failed": "[{edit, error}]",+    "saved": "bool"+   },+   "hint": "text picks every label with that text (or the one at at); net picks every label of the net. Read ids with sch_items.",+   "pitfalls": [+    "A label joins a net only where it sits on a wire or a pin end: moving it off disconnects it.",+    "rename changes only the labels picked: other labels with the old name stay on the old net."+   ],+   "related": [+    "sch_items",+    "sch_connect",+    "sch_edit"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "edits": [+     {+      "net": "VOUT",+      "by": [+       0,+       2.54+      ]+     }+    ]+   },+   "longRunning": true,+   "timeoutSeconds": 120,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_fix_connectivity",+   "tier": "core",+   "source": "proposed",+   "summary": "Snap near-miss wire ends onto the pin, label, sheet pin or wire end they almost touch, within a tolerance. dryRun (the default) lists the moves; dryRun:false makes them.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "toleranceMm": "number, default 0.5",+    "dryRun": "bool, default TRUE",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "moves": "[{wireId, from, to, onto: {kind, id}, diagonal: bool}]",+    "unresolved": "[[x, y]]: dangling ends with nothing close",+    "saved": "bool"+   },+   "hint": "Only dangling wire ends move. Read the moves before applying them: diagonal:true means the snapped wire is no longer horizontal or vertical. Check with run_erc after.",+   "pitfalls": [+    "dryRun defaults to true: nothing changes until dryRun:false.",+    "A wide tolerance can snap onto the wrong pin: keep it under half the sheet's grid."+   ],+   "related": [+    "sch_trace_point",+    "run_erc"+   ],+   "example": {+    "sheet": "C:/proj/Power.SchDoc",+    "toleranceMm": 0.5,+    "dryRun": false+   },+   "longRunning": false,+   "timeoutSeconds": 60,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_hierarchy",+   "tier": "core",+   "source": "proposed",+   "summary": "The sheet tree of a design, recursively: each sheet's name, file, id, instance path, page number, position, size and pins. renumber:true renumbers pages depth-first from the root.",+   "input": {+    "sheet": "path to the root sheet",+    "project": "path to the project (instead of sheet)",+    "renumber": "bool, default false",+    "dryRun": "bool, default false: answer the plan and change nothing"+   },+   "output": {+    "tree": "[{name, file, id, path, page, at, sizeMm, pins: [{name, kind}], children: [...]}]",+    "problems": "[{sheet, problem: missing|unreadable|recursive}]",+    "duplicatePages": "[int]",+    "renumbered": "[{sheet, from, to}]"+   },+   "hint": "Pass the root sheet or the project. renumber writes only the numbers that change.",+   "pitfalls": [+    "A sheet file used by two sheet symbols appears twice in the tree (one instance each) but is one file."+   ],+   "related": [+    "sch_sheet_pins",+    "sch_sheet_symbol",+    "sch_create"+   ],+   "example": {+    "project": "C:/proj/Board.PrjPcb",+    "renumber": true+   },+   "longRunning": false,+   "timeoutSeconds": 30,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_items",+   "tier": "core",+   "source": "proposed",+   "summary": "List a sheet's wiring items with ids and coordinates: wires, buses, bus entries, net labels (local, global, hierarchical), power ports, junctions, no-connect markers, texts and sheet symbols. Read only.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "kinds": "[wires, buses, busEntries, labels, powerPorts, junctions, noConnects, texts, sheets] (default all)"+   },+   "output": {+    "wires": "[{id, from, to}]",+    "buses": "[{id, from, to}]",+    "busEntries": "[{id, at, end}]",+    "labels": "[{id, text, kind: local|global|hierarchical, at, rotation}]",+    "powerPorts": "[{id, net, at}]",+    "junctions": "[{id, at}]",+    "noConnects": "[{id, at}]",+    "texts": "[{id, text, at}]",+    "sheets": "[{id, name, file, at, sizeMm}]",+    "counts": "{kind: int}"+   },+   "hint": "The ids feed sch_delete_wire, sch_edit_label, sch_junction and sch_edit. Parts are in schematic_data.",+   "pitfalls": [+    "A wire is one straight segment: a polyline drawn in the editor is several wires sharing ends."+   ],+   "related": [+    "schematic_data",+    "sch_pins",+    "sch_delete_wire",+    "sch_edit_label"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "kinds": [+     "wires",+     "labels"+    ]+   },+   "longRunning": false,+   "timeoutSeconds": 30,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_junction",+   "tier": "core",+   "source": "proposed",+   "summary": "Add junction dots at points, or remove dots by id or point. One undo step.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "points": "[[x, y], ...] mm: where to add dots",+    "remove": "[id or [x, y], ...]: dots to remove",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "added": "[{id, at}]",+    "removed": "[id]",+    "skipped": "[[x, y]]: points that already had a dot",+    "notNeeded": "[[x, y]]: added dots where fewer than three items meet (legal, but they join nothing extra)",+    "saved": "bool"+   },+   "hint": "The wiring verbs add the dots they need on their own; use this for a T made by hand, or to clean up.",+   "pitfalls": [+    "Items join only where their coordinates match exactly: use pin ends from sch_pins, or points on the sheet's grid."+   ],+   "related": [+    "sch_items",+    "sch_split_wire",+    "sch_delete_wire"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "points": [+     [+      110.49,+      60.96+     ]+    ]+   },+   "longRunning": true,+   "timeoutSeconds": 120,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_move_region",+   "tier": "core",+   "source": "proposed",+   "summary": "Move everything inside a box by (dx, dy): parts, wire ends inside the box (wires crossing its edge stretch), labels, junctions, no-connect markers, texts, bus entries and sheet symbols. One undo step.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "box": "[x1, y1, x2, y2] mm (required)",+    "by": "[dx, dy] mm (required)",+    "wires": "bool, default true: move wires, buses and bus entries",+    "labels": "bool, default true: move labels and texts",+    "junctions": "bool, default true: move junctions and no-connect markers",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "moved": "{parts, wires, buses, busEntries, labels, texts, junctions, noConnects, sheets: [id]}",+    "saved": "bool"+   },+   "hint": "Parts move by their anchor point. Move by a pure dx or a pure dy to keep stretched wires straight.",+   "pitfalls": [+    "A wire with one end in the box stretches diagonally when dx and dy are both non-zero.",+    "Keep the move on the sheet's grid, or pins and wires stop meeting.",+    "A multi-part component whose parts sit on both sides of the edge splits up."+   ],+   "related": [+    "sch_edit",+    "sch_items"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "box": [+     90,+     40,+     160,+     120+    ],+    "by": [+     25.4,+     0+    ]+   },+   "longRunning": true,+   "timeoutSeconds": 120,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_page",+   "tier": "core",+   "source": "proposed",+   "summary": "Read or set a sheet's page: paper size, orientation and title block (title, date, revision, company, comment lines).",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "paper": "A5 to A0, A to E, USLetter, USLegal, USLedger or custom",+    "orientation": "portrait|landscape",+    "widthMm": "number (custom paper)",+    "heightMm": "number (custom paper)",+    "title": "string",+    "date": "string",+    "rev": "string",+    "company": "string",+    "comments": "[string]: comment lines in order",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "paper": "string",+    "widthMm": "number",+    "heightMm": "number",+    "orientation": "string",+    "titleBlock": "{title, date, rev, company, comments}",+    "changed": "bool",+    "saved": "bool"+   },+   "hint": "With no change arguments it only reads. An empty string removes a title-block field. Each sheet of a hierarchy has its own page.",+   "pitfalls": [+    "Shrinking the paper moves nothing: items outside the new frame stay where they are (render_schematic shows it)."+   ],+   "related": [+    "sch_create",+    "render_schematic"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "paper": "A3",+    "title": "Main board",+    "rev": "B"+   },+   "longRunning": false,+   "timeoutSeconds": 30,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_pins",+   "tier": "core",+   "source": "proposed",+   "summary": "Every pin of the named parts on a sheet: its absolute position (rotation and mirror applied), number, name, electrical type, the side it leaves the body, and the wires, labels and nets touching it. Read only.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "references": "[\"U1\", \"R5\"] (default every part)",+    "connections": "bool, default true: add what touches each pin"+   },+   "output": {+    "pins": "[{ref, number, name, type, at: [x, y], direction: right|left|up|down as seen, hidden, touching: [{kind, id}], nets: [string], connectedPins: [Ref.Pin]}]"+   },+   "hint": "at is where a wire or label must land on the pin. connectedPins lists the other pins on the same copper on this sheet.",+   "pitfalls": [+    "Nets here come from this sheet's wires and labels only: netlist gives the project-wide nets.",+    "Hidden power pins (hidden:true) connect by name, not by wire."+   ],+   "related": [+    "sch_connect_pins",+    "sch_connect",+    "schematic_data",+    "netlist"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "references": [+     "U1",+     "R5"+    ]+   },+   "longRunning": false,+   "timeoutSeconds": 30,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },   {    "name": "sch_place_part",    "tier": "core",+   "source": "altium",    "summary": "Place a component from a .SchLib onto an EXISTING sheet at a position, with its library parameters (MPN, Manufacturer, distributor numbers) and its footprint link.",    "input": {     "comment": "string, default the library's",@@ -1547,9 +2240,98 @@    "timeoutSeconds": 120,    "unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."   },+  {+   "name": "sch_reset_fields",+   "tier": "core",+   "source": "proposed",+   "summary": "Put parts' designator and value text (or the named fields) back where the library symbol places them, through each part's rotation and mirror. One undo step.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "references": "[\"R5\", \"C3\"]",+    "all": "bool: every part on the sheet",+    "fields": "[designator, value] by default; other field names as the tool names them",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "reset": "[{ref, field}]",+    "saved": "bool"+   },+   "hint": "Font and visibility stay as they are; only position, angle and justification move.",+   "pitfalls": [+    "The library's offsets are what the symbol's author drew; the tool's automatic field placement may put them elsewhere."+   ],+   "related": [+    "sch_edit",+    "schematic_data"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "references": [+     "R5",+     "C3"+    ]+   },+   "longRunning": true,+   "timeoutSeconds": 120,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_sheet_pins",+   "tier": "core",+   "source": "proposed",+   "summary": "A sheet symbol's pins: list, add, edit (rename, kind, move along an edge) or delete. import:true adds a pin for every hierarchical port inside the child sheet that the symbol lacks; validate:true reports ports without pins, pins without ports and kind mismatches.",+   "input": {+    "sheet": "path to the parent sheet (required)",+    "sheetSymbol": "the sheet symbol's name or id (default: validate checks every one)",+    "action": "list|add|edit|delete, default list",+    "name": "string: the pin",+    "kind": "input|output|bidirectional|tri_state|passive",+    "side": "left|right|top|bottom",+    "at": "[x, y] mm: snapped to the nearest edge point",+    "newName": "string (edit)",+    "import": "bool",+    "validate": "bool",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "pins": "[{id, name, kind, side, at}]",+    "added": "[name]",+    "problems": "[{sheetSymbol, pin, problem: no_port|no_pin|kind_mismatch}]",+    "saved": "bool"+   },+   "hint": "Inputs go on the left edge and outputs on the right by default, in the first free slot. A pin joins the child's hierarchical port of the same name; wire it on the parent side at its at.",+   "pitfalls": [+    "Renaming a pin does not rename the port inside the child sheet: validate afterwards.",+    "A pin moved or deleted leaves its parent-side wire dangling."+   ],+   "related": [+    "sch_sheet_symbol",+    "sch_hierarchy",+    "sch_connect"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "sheetSymbol": "Power",+    "import": true+   },+   "longRunning": false,+   "timeoutSeconds": 30,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },   {    "name": "sch_sheet_symbol",    "tier": "core",+   "source": "altium",    "summary": "Make a design hierarchical: a sheet symbol on the parent sheet for a child sheet, its entries joined to the parent's nets, and matching ports on the child. A child that does not exist yet is made from Altium's sheet template and added to the project.",    "input": {     "child": "the child .SchDoc (required; a name alone sits beside the parent)",@@ -1607,9 +2389,52 @@    "timeoutSeconds": 240,    "unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."   },+  {+   "name": "sch_split_wire",+   "tier": "core",+   "source": "proposed",+   "summary": "Split the wire through a point into two wires there, with a junction dot at the cut, so a new branch can end on a wire end. One undo step.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "at": "[x, y] mm on the sheet (the tool's sheet origin, y up) (required)",+    "id": "the wire's id, when several wires pass through the point",+    "junction": "bool, default true",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "ids": "[first half (keeps the wire's id), second half (new id)]",+    "junction": "{id, at} or null",+    "saved": "bool"+   },+   "hint": "Split a wire where a new branch should join it, then wire to the cut.",+   "pitfalls": [+    "The point must lie on the wire and not at either end (not_on_wire otherwise)."+   ],+   "related": [+    "sch_delete_wire",+    "sch_junction",+    "sch_items"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "at": [+     110.49,+     60.96+    ]+   },+   "longRunning": true,+   "timeoutSeconds": 120,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },   {    "name": "sch_swap_part",    "tier": "core",+   "source": "altium",    "summary": "Replace a placed part with another library part (a different value, package or symbol) at the same place, designator and rotation, keeping its connections: where a new pin ends elsewhere, a wire joins it to where the old pin ended.",    "input": {     "designator": "the part to replace (required)",@@ -1647,9 +2472,93 @@    "longRunning": false,    "timeoutSeconds": 120   },+  {+   "name": "sch_text",+   "tier": "core",+   "source": "proposed",+   "summary": "Add free text to a sheet (a note, a title, a design comment) with size, angle, justification, bold and italic. Text has no electrical meaning. One undo step.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "texts": "[{text, at: [x, y] mm, rotation?: 0|90|180|270, sizeMm?: 1.27, justify?: \"left bottom\", bold?: false, italic?: false}] (required)",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "added": "[{id, text, at}]",+    "saved": "bool"+   },+   "hint": "Net names are labels, not text: use sch_connect for them. Newlines in text become line breaks.",+   "pitfalls": [],+   "related": [+    "sch_items",+    "sch_edit_label"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "texts": [+     {+      "text": "USB input stage",+      "at": [+       50.8,+       30.48+      ],+      "sizeMm": 2.54,+      "bold": true+     }+    ]+   },+   "longRunning": true,+   "timeoutSeconds": 120,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },+  {+   "name": "sch_trace_point",+   "tier": "core",+   "source": "proposed",+   "summary": "Everything electrically connected at a point on a sheet: the wires, labels, pins, junctions, sheet pins and no-connect markers there, and for each net they belong to the whole net with its name. Read only.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "at": "[x, y] mm on the sheet (the tool's sheet origin, y up) (required)",+    "toleranceMm": "number, default 0.05"+   },+   "output": {+    "items": "[{kind, id, at}]",+    "nets": "[{name, pins: [Ref.Pin], labels, powerPorts, wires, leavesSheet: bool}]",+    "crossingWithoutJunction": "bool: two wires cross here without connecting",+    "nearest": "[x, y]: the nearest connectable point, when nothing is within tolerance"+   },+   "hint": "Read with the tool's own rules: wire ends join wires and wire middles (a T), labels and junction dots join a wire anywhere along it, pins join wire ends.",+   "pitfalls": [+    "One sheet only: a net that leaves through a global, hierarchical or power label (leavesSheet:true) continues on other sheets. netlist gives the compiled net."+   ],+   "related": [+    "sch_pins",+    "net_connections",+    "netlist"+   ],+   "example": {+    "sheet": "C:/proj/Power.SchDoc",+    "at": [+     109.22,+     73.66+    ]+   },+   "longRunning": false,+   "timeoutSeconds": 30,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },   {    "name": "schematic_data",    "tier": "core",+   "source": "altium",    "summary": "Components on a schematic sheet (filePath, else the CURRENT sheet) with their pins (number, name, electrical type), position and orientation. designator filters to one part.",    "input": {     "designator": "string - optional filter",@@ -1683,6 +2592,7 @@   {    "name": "set_models",    "tier": "core",+   "source": "altium",    "summary": "Replace every footprint model on a SchLib component with ONE PCBLIB model (set_params footprint and add_models APPEND, which is how a symbol ends up with two).",    "input": {     "footprint": "string (PcbLib footprint name)",@@ -1709,6 +2619,7 @@   {    "name": "set_outline",    "tier": "core",+   "source": "altium",    "summary": "Reshape the current board's outline (a rectangle with rounded corners, or a polygon). One undo step.",    "input": {     "expectedRevision": "string (optional) - refused with stale_board if the board changed",@@ -1745,6 +2656,7 @@   {    "name": "set_params",    "tier": "core",+   "source": "altium",    "summary": "Set parameters on a SchLib component, optionally its comment, and optionally link a footprint by name.",    "input": {     "comment": "string",@@ -1785,6 +2697,7 @@   {    "name": "set_track_width",    "tier": "core",+   "source": "altium",    "summary": "Set the width of the EXISTING tracks and arcs on nets or a net class (rules only steer new routing). Widen power nets after routing, or thin a net that fails clearance.",    "input": {     "filePath": "path to the .PcbDoc - optional",@@ -1818,6 +2731,7 @@   {    "name": "set_visibility",    "tier": "core",+   "source": "altium",    "summary": "Show or hide one named parameter on a SchLib component.",    "input": {     "libraryPath": "path to a .SchLib - optional; opened first",@@ -1852,6 +2766,7 @@   {    "name": "sheet_params",    "tier": "core",+   "source": "altium",    "summary": "Write parameters onto PLACED parts on the schematic sheets (the BOM write-back): MPN, Manufacturer, Mouser/DigiKey/LCSC numbers, anything. A missing parameter is added hidden; one undo step per sheet; each touched sheet is saved.",    "input": {     "designators": "[string] or 'R1,R2' (required; every part of a multi-part component)",@@ -1893,6 +2808,7 @@   {    "name": "silk_state",    "tier": "core",+   "source": "altium",    "summary": "The silkscreen as it stands: every part's body box, its designator and comment (text, location, size, rotation, shown, Altium's measured box), and the free overlay texts and lines on both faces.",    "input": {},    "output": {@@ -1916,6 +2832,7 @@   {    "name": "swap_footprint",    "tier": "core",+   "source": "altium",    "summary": "Replace the FIRST component on the current board with a footprint from a PcbLib at the same position, re-assigning nets by pad designator. Tracks are untouched, so the wiring survives.",    "input": {     "assigns": "'padDes=NET;...'",@@ -1950,6 +2867,7 @@   {    "name": "symbol_prims",    "tier": "core",+   "source": "altium",    "summary": "Read a SchLib component's drawing: primitive counts by kind, body rectangle, polyline bounding box, display mode and the footprint models. Read-only, use it to verify add_symbol_art / set_models.",    "input": {     "libraryPath": "path (.SchLib)",@@ -1980,6 +2898,7 @@   {    "name": "xcopy_footprint",    "tier": "core",+   "source": "altium",    "summary": "Copy a footprint ACROSS libraries: from fromLib into toLib (opened and made current), optionally under a new name.",    "input": {     "from": "string - footprint name in the source",@@ -2014,6 +2933,7 @@   {    "name": "add_rule",    "tier": "native",+   "source": "altium",    "summary": "Add one SCOPED design rule that set_design_rules' board-wide values cannot express: a net's or class's clearance or width, a length limit, a matched-length group, a differential pair's width and gap, a routing via style, or how a net's pads join a pour (direct, relief, none).",    "input": {     "comment": "optional",@@ -2070,6 +2990,7 @@   {    "name": "annotate",    "tier": "native",+   "source": "altium",    "summary": "Number every '?' designator (R?, C?, U?) across the project's sheets: the lowest free number per prefix, top-left first on each sheet. dryRun shows the plan.",    "input": {     "dryRun": "bool, default false",@@ -2099,6 +3020,7 @@   {    "name": "apply_pours",    "tier": "native",+   "source": "altium",    "summary": "Add solid polygon pours from outlines and pour them, each with its own connect style (solid joints or thermal spokes), plus pour keepouts (polygon cutouts); answers each pour's real poured copper area. One undo step.",    "input": {     "cutouts": "(optional) [{layer, points:[[x,y]...] mm, name?}] - areas every pour on that layer stays out of (KiCad's pour keepout); landed before the pours",@@ -2208,6 +3130,7 @@   {    "name": "autoroute",    "tier": "native",+   "source": "altium",    "summary": "Altium's own autorouter (Situs) on the current board: picks a strategy, keeps existing routing locked by default, routes, and answers the unconnected count and DRC errors before and after. Not saved unless save:true.",    "input": {     "filePath": "path to the .PcbDoc - optional, else the current board",@@ -2244,6 +3167,7 @@   {    "name": "build_symbol_modes",    "tier": "native",+   "source": "altium",    "summary": "Build ONE SchLib component with N display modes (Normal + Alternate 1..N-1) from a symbol_modes spec file on this machine, and return a proof frame.",    "input": {     "libraryPath": "path to a .SchLib (required; created if missing)",@@ -2277,6 +3201,7 @@   {    "name": "cleanup_libs",    "tier": "native",+   "source": "altium",    "summary": "Remove the factory-default stray every fresh library carries: Component_1 from the current SchLib and an empty (no pads) PCBComponent_1 from the current PcbLib.",    "input": {     "libraryPath": "path to a .SchLib/.PcbLib - optional; opened first",@@ -2306,6 +3231,7 @@   {    "name": "compile",    "tier": "native",+   "source": "altium",    "summary": "Compile a project and return Altium's Messages panel (ERC + connectivity) with counts by class. With no path it compiles Altium's bundled example project.",    "input": {     "limit": "int, default 200 messages",@@ -2341,6 +3267,7 @@   {    "name": "component_classes",    "tier": "native",+   "source": "altium",    "summary": "List, make or remove component classes on the board, each optionally with a room: a placement area that keeps its parts together (fitted around the parts or a rectangle). The classes scope rules and group a channel for replicate_layout.",    "input": {     "filePath": "the .PcbDoc (opened first)",@@ -2382,6 +3309,7 @@   {    "name": "diff_pairs",    "tier": "native",+   "source": "altium",    "summary": "Differential pairs on the current board: list them, define one from two nets (replacing a pair of that name), or remove one. Altium's differential-pair router and rules work on these.",    "input": {     "filePath": "path to the .PcbDoc - optional",@@ -2415,6 +3343,7 @@   {    "name": "export_bom",    "tier": "native",+   "source": "altium",    "summary": "Bill of materials export: altium_run_outjob with the assembly OutJob and the 'Folder Structure' medium as defaults.",    "input": {     "medium": "string, default 'Folder Structure'",@@ -2450,6 +3379,7 @@   {    "name": "export_gerber",    "tier": "native",+   "source": "altium",    "summary": "Gerber/drill export: altium_run_outjob with the fabrication OutJob and the 'Folder Structure' medium as defaults.",    "input": {     "medium": "string, default 'Folder Structure'",@@ -2486,6 +3416,7 @@   {    "name": "export_manufacturing",    "tier": "native",+   "source": "altium",    "summary": "A project's manufacturing set in one call: Gerbers, NC drill, pick and place (CSV, mm) and the BOM, from an OutJob the bridge writes beside the project (composed from this Altium's own OutJob templates, every output on one medium that opens nothing).",    "input": {     "bomColumns": "(optional) [column or parameter name] - default Comment, Description, Designator, Footprint, Quantity, MPN, Manufacturer, Mouser/DigiKey/LCSC Part #",@@ -2524,6 +3455,7 @@   {    "name": "export_pdf",    "tier": "native",+   "source": "altium",    "summary": "Every sheet of a project as one PDF, plus on request the board's composite print, Altium's assembly drawings (top and bottom, designators on the parts) and its fabrication print, from an OutJob in a throwaway project; the user's project is not touched.",    "input": {     "assembly": "bool, default false - Altium's Assembly Drawings output (needs a board in the project)",@@ -2556,6 +3488,7 @@   {    "name": "export_step",    "tier": "native",+   "source": "altium",    "summary": "Headless STEP export of a board. Default lane 'outjob': Altium's own ExportSTEP output run from a throwaway project in %TEMP% that points at the board - no dialog, no click (measured on AD 26.9.1). lane:'extension' is the older AdomBridge .NET extension path.",    "input": {     "componentsOption": "int, Altium ExportComponentOptions, default 0 (all)",@@ -2603,6 +3536,7 @@   {    "name": "install_library",    "tier": "native",+   "source": "altium",    "summary": "Register a library file in Altium's Installed Libraries (IntegratedLibraryManager.InstallLibrary) so its parts appear in the Components panel.",    "input": {     "libraryPath": "path to a .IntLib/.SchLib/.PcbLib/.DbLib (required)",@@ -2631,6 +3565,7 @@   {    "name": "install_library_bundle",    "tier": "native",+   "source": "altium",    "summary": "One-click install of a wiki library bundle (zip of .SchLib/.PcbLib): unpack, register, open the library, prove it with a frame.",    "input": {     "capture": "bool",@@ -2671,6 +3606,7 @@   {    "name": "list_installed_libraries",    "tier": "native",+   "source": "altium",    "summary": "Every library in Altium's Installed Libraries list (read-only).",    "input": {},    "output": {@@ -2693,6 +3629,7 @@   {    "name": "net_classes",    "tier": "native",+   "source": "altium",    "summary": "Net classes on the current board: list them with their nets, or make one (replacing a class of that name) with an optional width and clearance rule scoped to it, or remove one with its rules. Power nets wider, a high-voltage class with more clearance.",    "input": {     "clearance": "mm - optional rule 'Adom <name> clearance' (class to All)",@@ -2738,6 +3675,7 @@   {    "name": "netlist",    "tier": "native",+   "source": "altium",    "summary": "The compiled netlist of a project: every net with its pins (Designator.Pin) across every sheet, the hierarchy resolved; or one net; or compare with the nets you expect.",    "input": {     "expect": "optional {net: [\"U1.3\", ...]}: compare pin by pin",@@ -2781,6 +3719,7 @@   {    "name": "panelize",    "tier": "native",+   "source": "altium",    "summary": "Step and repeat a board into a manufacturing panel: a new .PcbDoc holding Altium's own embedded board array of the board (rows x cols), with rails, the panel frame on the outline layer, three tooling holes and three fiducials; boards separated by JLCPCB-style V-score lines or mouse-bite tabs, with JLCPCB's rules checked. The array stays linked to the board.",    "input": {     "cols": "default 2",@@ -2833,6 +3772,7 @@   {    "name": "pcb_report",    "tier": "native",+   "source": "altium",    "summary": "Numbers instead of pixels: for a PcbLib, every footprint's pads, pad bounding box, primitive census and 3D bodies; for a board, outline, components with nets and bodies, census and tracks.",    "input": {     "name": "string - footprint name filter (library form)",@@ -2866,6 +3806,7 @@   {    "name": "pour_state",    "tier": "native",+   "source": "altium",    "summary": "Every polygon pour with the copper it actually poured: filled area per pour and per layer, and the pours that poured nothing.",    "input": {},    "output": {@@ -2889,6 +3830,7 @@   {    "name": "remove_pours",    "tier": "native",+   "source": "altium",    "summary": "Delete polygon pours by net (and layer), or all of them, and the pour keepouts (cutouts) apply_pours made. Tracks and vias are untouched.",    "input": {     "cutouts": "(optional) \"all\" or [{layer}] - only the cutouts apply_pours landed (named Adom...)",@@ -2917,9 +3859,54 @@    "longRunning": false,    "timeoutSeconds": 300   },+  {+   "name": "render_schematic",+   "tier": "native",+   "source": "proposed",+   "summary": "Render a sheet to an image without opening a window, through the tool's own plotter, and keep visual baselines: baseline set stores the image, baseline compare reports the pixel drift, the changed region and a diff image.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "width": "int px, default 2000",+    "outputDir": "folder for the image (default beside the project)",+    "baseline": "set|compare",+    "threshold": "percent of pixels, default 0.5 (compare)",+    "drawingSheet": "bool, default true: include the frame and title block"+   },+   "output": {+    "png": "path",+    "width": "int",+    "height": "int",+    "driftPercent": "number (compare)",+    "pass": "bool (compare)",+    "changedRegionMm": "[x1, y1, x2, y2] (compare)",+    "diffPng": "path: the changed pixels in red (compare)",+    "rendererChanged": "bool: the tool's plotter changed since the baseline"+   },+   "hint": "A sub-sheet renders with its real designators. compare renders at the baseline's width and passes when driftPercent <= threshold. show_* verbs open a window; this one does not.",+   "pitfalls": [+    "Anti-aliasing differs between tool versions: rendererChanged:true means drift may not be a design change.",+    "A baseline is per sheet and per width; a paper size change reads as 100 percent drift."+   ],+   "related": [+    "sch_page",+    "export_pdf"+   ],+   "example": {+    "sheet": "C:/proj/Power.SchDoc",+    "baseline": "compare"+   },+   "longRunning": true,+   "timeoutSeconds": 300,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },   {    "name": "replicate_layout",    "tier": "native",+   "source": "altium",    "summary": "Copy one channel's placement to matching channels: each target keeps its anchor part where it is and every other part takes the source's offset and rotation from the anchor (turned by the anchors' rotation difference).",    "input": {     "anchor": "optional ref from source (default the first)",@@ -2966,6 +3953,7 @@   {    "name": "repour",    "tier": "native",+   "source": "altium",    "summary": "Repour every polygon on the board (Altium's Repour All) and answer the copper after. Runs outside the script engine so scoped rules apply.",    "input": {     "inScript": "bool (default false) - repour from inside the agent instead (scoped rules then match nothing)"@@ -2992,6 +3980,7 @@   {    "name": "routing_drc",    "tier": "native",+   "source": "altium",    "summary": "Design-rule violations on the current board WITH locations, plus the unrouted (ratsnest) count, as one clean/not-clean answer.",    "input": {     "full": "bool (default false) - run Altium's batch DRC on this board first"@@ -3020,6 +4009,7 @@   {    "name": "run_drc",    "tier": "native",+   "source": "altium",    "summary": "Run the design rule check on a board and read the violation markers back. PCB:DesignRuleCheck opens a MODAL; the bridge clicks 'Run Design Rule Check' through UIA in the background, waits for the agent, re-activates the board and reads the violations.",    "input": {     "filePath": "path to a .PcbDoc - default: the bundled Bluetooth Sentinel board",@@ -3056,6 +4046,7 @@   {    "name": "run_erc",    "tier": "native",+   "source": "altium",    "summary": "Electrical rules check. Same handler as altium_compile: in Altium, compiling the project IS the ERC.",    "input": {     "limit": "int, default 200 messages",@@ -3087,9 +4078,51 @@    "longRunning": false,    "timeoutSeconds": 180   },+  {+   "name": "sch_update_from_library",+   "tier": "native",+   "source": "proposed",+   "summary": "Update the placed symbols on a sheet from their libraries (all, or the listed ones) and report which changed, which already matched and which no library has.",+   "input": {+    "sheet": "path to the schematic sheet file (required)",+    "symbols": "[library symbol name or id, ...] (default all)",+    "library": "path to one library to take them all from (with symbols)",+    "force": "bool, default false: update even when a placed pin would be dropped",+    "dryRun": "bool, default false: answer the plan and change nothing",+    "save": "bool, default true: save the sheet after the edit"+   },+   "output": {+    "changed": "[{symbol, pinsAdded, pinsRemoved}]",+    "unchanged": "[symbol]",+    "notFound": "[symbol]",+    "refused": "[{symbol, droppedPins}]",+    "saved": "bool"+   },+   "hint": "Run with dryRun first. A symbol whose new version drops a placed pin is refused unless force:true. Check the sheet afterwards with run_erc.",+   "pitfalls": [+    "A pin that moved in the library moves off its wire: check with sch_pins or run_erc after an update that reports changes."+   ],+   "related": [+    "sch_swap_part",+    "schematic_data",+    "run_erc"+   ],+   "example": {+    "sheet": "C:/proj/Main.SchDoc",+    "dryRun": true+   },+   "longRunning": true,+   "timeoutSeconds": 180,+   "proposedBy": "kicad-lane",+   "since": "0.2.0",+   "agreedBy": [+    "altium-lane"+   ]+  },   {    "name": "set_design_rules",    "tier": "native",+   "source": "altium",    "summary": "Write a fab's design rules into the current board: clearance, track width, routing via style, hole size, annular ring, hole-to-hole and board-edge clearance (mm).",    "input": {     "annularRing": "mm",@@ -3142,6 +4175,7 @@   {    "name": "silkscreen_prep",    "tier": "native",+   "source": "altium",    "summary": "Clean the silkscreen off the copper with Altium's own Tools > Silkscreen Preparation: silk clipped clear of every mask opening (pad) by the board's silk rule, designators moved off pads where they fit, silk outside the board deleted; the silkscreen DRC hits counted before and after.",    "input": {     "check": "bool, default true: DRC before and after",@@ -3181,6 +4215,7 @@   {    "name": "symbol_mode",    "tier": "native",+   "source": "altium",    "summary": "Show one display mode (0 = Normal, 1.. = alternates) of the CURRENT SchLib component in the editor and capture a frame. Drives the editor's own mode toggle, because setting DisplayMode alone does not repaint.",    "input": {     "libraryPath": "path to a .SchLib - optional; opened first",@@ -3212,6 +4247,7 @@   {    "name": "teardrops",    "tier": "native",+   "source": "altium",    "summary": "Add (or remove) teardrops with Altium's own Tools > Teardrops: on vias and through-hole pads, SMD pads, track width changes and T-junctions, for the whole board or the selection; teardrops counted before and after.",    "input": {     "filePath": "the .PcbDoc (opened first)",@@ -3250,6 +4286,7 @@   {    "name": "uninstall_library",    "tier": "native",+   "source": "altium",    "summary": "Remove libraries from Altium's Installed Libraries: the inverse of install_library / install_library_bundle. Library files are never touched.",    "input": {     "dryRun": "bool",@@ -3281,6 +4318,7 @@   {    "name": "update_pcb",    "tier": "native",+   "source": "altium",    "summary": "Design > Update PCB Document from the schematic (the engineering change order): parts added, removed or renamed, nets and footprints updated on the board. Previews by default; execute:true runs it (Execute Changes, Close), refusing to delete board parts unless allowRemovals:true.",    "input": {     "allowRemovals": "bool, default false - let the change order delete board parts that are on no sheet",@@ -3317,6 +4355,7 @@   {    "name": "assembly_check",    "tier": "checks",+   "source": "altium",    "summary": "Ready for JLCPCB assembly? The board against both JLCPCB PCBA tiers as published (Economic and Standard): board or panel size, thickness and layers, parts on one or both sides, the smallest package and the finest pin pitch, fiducials, and the parts with no LCSC number; answers the cheapest tier every rule allows.",    "input": {     "filePath": "the .PcbDoc (opened first; else the current board)",@@ -3352,6 +4391,7 @@   {    "name": "auto_classes",    "tier": "checks",+   "source": "altium",    "summary": "Net classes from the nets' own names: GND, Power (VCC, VDD, 3V3, VBAT...), Clock, HighSpeed (USB, Ethernet, HDMI, PCIe, DDR, MIPI, LVDS, SATA...) and the differential pairs their _P/_N, +/-, DP/DN names spell; a proposal first, written as Altium net classes (Power with a width rule) and pairs with apply.",    "input": {     "apply": "bool - write the classes and pairs (default: propose only)",@@ -3384,6 +4424,7 @@   {    "name": "board_features",    "tier": "checks",+   "source": "altium",    "summary": "Add the furniture every real board needs in one undo step: mounting holes (at points or the four corners), fiducials, keepout areas, and a stitching-via grid on a net that keeps clear of every other net's copper, every pad and the board edge.",    "input": {     "dryRun": "bool - plan only",@@ -3440,6 +4481,7 @@   {    "name": "board_report",    "tier": "checks",+   "source": "altium",    "summary": "One shareable page per board: every check run against the live board and its project (Altium's DRC, JLCPCB fab limits and assembly tiers, the schematic review, symbols against footprints, impedance widths, return paths, copper balance, 3D heights) with a picture of the board, written as a single HTML file.",    "input": {     "out": "the .html to write (default '<board> report.html' beside the project)",@@ -3479,6 +4521,7 @@   {    "name": "bom",    "tier": "checks",+   "source": "altium",    "summary": "The project's bill of materials read straight from Altium: every schematic sheet the .PrjPcb lists (placed parts and their parameters) merged with the board (footprint, position, side), a variant applied, grouped one line per manufacturer part number, checked for what an order needs, and written as bom.csv, bom-jlcpcb.csv + cpl-jlcpcb.csv, bom-mouser.csv and bom-digikey.csv (+ bom.json).",    "input": {     "boards": "int, default 1 - multiplies the quantities in the Mouser/DigiKey files",@@ -3521,6 +4564,7 @@   {    "name": "build_board",    "tier": "checks",+   "source": "altium",    "summary": "Build a NEW board from a parts list and a netlist: outline (rounded corners allowed), every footprint from one PcbLib placed by its own origin, pad nets assigned, saved; then read back pin by pin.",    "input": {     "libraryPath": "string (required) - the .PcbLib holding every footprint",@@ -3581,6 +4625,7 @@   {    "name": "build_footprint",    "tier": "checks",+   "source": "altium",    "summary": "Build a complete footprint (pads, silkscreen, courtyard, arcs) in a PcbLib from a kicad2altium spec file on this machine, and return a proof frame.",    "input": {     "libraryPath": "path to a .PcbLib (required; created if missing)",@@ -3614,6 +4659,7 @@   {    "name": "build_schematic",    "tier": "checks",+   "source": "altium",    "summary": "Draw a design's schematic from its netlist with the project library's symbols, inside a new project (.PrjPcb with the board and libraries), compile it, and check its netlist pin by pin.",    "input": {     "drawnBy": "optional",@@ -3671,6 +4717,7 @@   {    "name": "check_orientation",    "tier": "checks",+   "source": "altium",    "summary": "Advisory: 2-pad parts whose rotation could be better. Each orthogonal rotation is scored in place by airline length (a routable net's MST with the pad there; a plane-like net's distance to its nearest pad); parts whose best rotation saves minImprovementMm are listed. Nothing is moved.",    "input": {     "filePath": "optional .PcbDoc",@@ -3700,6 +4747,7 @@   {    "name": "copper_balance",    "tier": "checks",+   "source": "altium",    "summary": "How much of each copper layer is copper (tracks, pads, vias and what Altium actually poured, inside the outline; a plane counts full), and how far apart each mirrored pair of layers is: the copper balance a fab asks about because an unbalanced stack bows and twists in reflow.",    "input": {     "filePath": "the .PcbDoc (opened first; else the current board)",@@ -3730,6 +4778,7 @@   {    "name": "cross_check",    "tier": "checks",+   "source": "altium",    "summary": "Compare one schematic sheet's designators with a board's. Altium holds ONE current document, so the verb activates the board, reads it, then activates the sheet and reads that.",    "input": {     "board": "path to the .PcbDoc - optional, else the current board",@@ -3767,6 +4816,7 @@   {    "name": "current_capacity",    "tier": "checks",+   "source": "altium",    "summary": "Will this trace carry the current? For each power net and its current: the narrowest track on every layer it is routed on against the width IPC-2221 needs for the allowed temperature rise (with each layer's real copper weight), and what one of its vias carries.",    "input": {     "filePath": "the .PcbDoc (opened first; else the current board)",@@ -3805,6 +4855,7 @@   {    "name": "fab_check",    "tier": "checks",+   "source": "altium",    "summary": "Before ordering: the board's fab-relevant minimums measured from the live board (narrowest track, smallest via drill, diameter and annular ring, smallest pad hole and ring, smallest SMD pad, clearance rule, copper layers, board size), each with where it is; with a fab's limits, which ones fall short.",    "input": {     "copperOz": "outer copper weight for the preset (default: read from the stack)",@@ -3840,6 +4891,7 @@   {    "name": "find_space",    "tier": "checks",+   "source": "altium",    "summary": "Free spots on the board for a part near another (clear of every other part on that side, of that side's tracks and vias, and inside the outline), nearest first; or check:true lists parts that already overlap or leave the outline.",    "input": {     "check": "bool - report overlaps instead",@@ -3879,6 +4931,7 @@   {    "name": "footprint_from_land_pattern",    "tier": "checks",+   "source": "altium",    "summary": "Build a complete footprint from the land pattern a datasheet prints: pads numbered the standard way (chip, dual SOIC/TSSOP/DFN, SOT, quad QFP/QFN, BGA), an exposed pad, the courtyard, silkscreen kept clear of the copper with a pin-1 dot, a fab outline with a pin-1 chamfer, and an extruded 3D body when the height is given.",    "input": {     "ballPad": "bga pad diameter mm",@@ -3948,6 +5001,7 @@   {    "name": "height_check",    "tier": "checks",+   "source": "altium",    "summary": "Will it fit the enclosure? Each part's height from its 3D bodies (top and bottom side), the parts over a height limit board-wide or under a lid feature in a region, and part bodies that collide or come closer than a gap.",    "input": {     "filePath": "the .PcbDoc (opened first; else the current board)",@@ -4002,6 +5056,7 @@   {    "name": "impedance",    "tier": "checks",+   "source": "altium",    "summary": "Controlled impedance from the board's own stack-up: the track width each copper layer needs for a single-ended target (50 ohm default) and the width and gap for a differential pair (90 ohm USB, 100 ohm Ethernet/LVDS), microstrip outside and stripline inside; optionally written as width or diff-pair rules per layer.",    "input": {     "apply": "{scope: Altium query e.g. InNetClass('RF') or InDifferentialPair('USB'), name?} - one rule per layer at +/-10%",@@ -4040,6 +5095,7 @@   {    "name": "import_part",    "tier": "checks",+   "source": "altium",    "summary": "One call imports a whole part: footprint spec + STEP + symbol modes + models + params + save.",    "input": {     "comment": "string",@@ -4073,6 +5129,7 @@   {    "name": "jlcpcb_order",    "tier": "checks",+   "source": "altium",    "summary": "A JLCPCB order in one call: the board checked against JLCPCB's fab limits, the Gerbers and drill zipped the way JLCPCB's order page takes them, the JLCPCB BOM and pick-and-place (CPL), the assembly-tier check, and the order-form values, in one folder with every issue in one list.",    "input": {     "outputDir": "the order folder (default 'JLCPCB order <board>' beside the project; emptied first)",@@ -4111,6 +5168,7 @@   {    "name": "length_tune",    "tier": "checks",+   "source": "altium",    "summary": "Lengthen a routed net to a target length, or to match another net (a pair's skew, a DDR byte lane): a serpentine in its longest straight track that has room beside it, the bumps sized to add exactly the length missing, every bump clear of other copper and inside the board.",    "input": {     "clearance": "to other copper, default 0.2",@@ -4152,6 +5210,7 @@   {    "name": "net_lengths",    "tier": "checks",+   "source": "altium",    "summary": "Routed length of every net (or the ones named) on the live board, by layer with its vias; the skew inside each differential pair; and the spread of matched-length groups against a tolerance.",    "input": {     "filePath": "the .PcbDoc (opened first)",@@ -4195,6 +5254,7 @@   {    "name": "pin_pad_check",    "tier": "checks",+   "source": "altium",    "summary": "Do the footprints fit their symbols? Part by part, the symbol's pin numbers (from the sheet files) against the footprint's pad names (from the board): pins with no pad, pads with no pin, and parts on only the sheets or only the board.",    "input": {     "pcbPath": "its .PcbDoc",@@ -4227,6 +5287,7 @@   {    "name": "placement_check",    "tier": "checks",+   "source": "altium",    "summary": "Review the placement before routing: parts whose courtyards (pads and body, grown by a margin) overlap on the same side, parts off the board or over its edge, pads too close to the edge for assembly and depanelling, and parts on a mounting hole.",    "input": {     "edgeMm": "pad to board edge, default 0.5",@@ -4260,6 +5321,7 @@   {    "name": "read_sheet_file",    "tier": "checks",+   "source": "altium",    "summary": "Read a schematic sheet straight from its .SchDoc file, without Altium (it need not be installed or running): every part with its designator, library reference, comment, UniqueID, part number, position, parameters and pins, in milliseconds.",    "input": {     "params": "bool, default false - every parameter with its value",@@ -4294,6 +5356,7 @@   {    "name": "return_path",    "tier": "checks",+   "source": "altium",    "summary": "Where signal tracks lose their reference: for every signal net, the length of track on each layer that runs over no pour or plane copper on either neighbouring layer (a split, a gap, a void), with where the first gap starts. The return current detours around those gaps: loop area, emissions, crosstalk.",    "input": {     "filePath": "the .PcbDoc (opened first; else the current board)",@@ -4332,6 +5395,7 @@   {    "name": "review_board",    "tier": "checks",+   "source": "altium",    "summary": "Design-review checks (14) over one board read; schematic checks with includeSchematic.",    "input": {     "board": "path - optional",@@ -4362,6 +5426,7 @@   {    "name": "route_pair",    "tier": "checks",+   "source": "altium",    "summary": "Route a differential pair as a pair: one centreline from the source pads' midpoint through waypoints to the destination pads' midpoint, each net offset to its own side at width + gap with mitred corners and a short fan-out from each pad; width and gap given or solved from the stack-up for a target impedance; both lengths and the skew answered.",    "input": {     "clearance": "to other nets' pads when checking the plan, default 0.15",@@ -4427,6 +5492,7 @@   {    "name": "schematic_review",    "tier": "checks",+   "source": "altium",    "summary": "Review the schematic before Update PCB: every placed pin (read from the sheet files, with its electrical type) against Altium's compiled netlist. Errors: power pins on no net, outputs driving each other. Warnings: pins on no net, one-pin nets, inputs nothing drives, IC supplies with no decoupling capacitor to ground.",    "input": {     "projectPath": "the .PrjPcb (its sheets are read from file; the netlist is Altium's compile)"@@ -4461,6 +5527,7 @@   {    "name": "silk_designators",    "tier": "checks",+   "source": "altium",    "summary": "Place every reference designator the way assembly houses want: one size, upright, beside its own part, clear of every pad (JLCPCB: 0.15 mm), every other part's body and the other designators, inside the board; read back from Altium's own text boxes. Parts with no clear spot are reported, not forced onto pads.",    "input": {     "dryRun": "bool - plan only",@@ -4498,6 +5565,7 @@   {    "name": "test_board",    "tier": "checks",+   "source": "altium",    "summary": "Place one footprint, or a ';' list, from the open PcbLib on ONE board: a NEW board (wMm x hMm outline) when pcbPath is new or omitted, APPENDED to the existing board when pcbPath already exists (issue 11).",    "input": {     "assigns": "des=NET;...",@@ -4544,6 +5612,7 @@   {    "name": "thermal_vias",    "tier": "checks",+   "source": "altium",    "summary": "A thermal via grid in a part's exposed pad (the ground or thermal pad under a QFN, DFN, PowerPAD or regulator): centred, inset from the pad's edge, sized by the board's Routing Via rule, on the pad's net.",    "input": {     "drill": "mm (default the board's via rule)",@@ -4581,6 +5650,7 @@   {    "name": "via_fence",    "tier": "checks",+   "source": "altium",    "summary": "A via fence for EMC: a row of ground vias on both sides of RF or fast nets' tracks, and/or round the board edge, at a pitch from the frequency (lambda/20) or given; each via clear of other copper and pads, the same net's vias and the edge.",    "input": {     "clearance": "to other copper, mm, default 0.2",@@ -4628,6 +5698,7 @@   {    "name": "activate_document",    "tier": "app",+   "source": "altium",    "summary": "Make a document current - the quiet lane (one in-process agent call, no cursor, no OS foreground). Board and schematic read verbs act on the CURRENT document.",    "input": {     "path": "full path of the document (aliases: document, name)",@@ -4659,6 +5730,7 @@   {    "name": "agent_recover",    "tier": "app",+   "source": "altium",    "summary": "Un-halt the script engine: clear the PCB transaction, press OK on open Altium dialogs, send EditScript:Stop, reap the busy notice and delete stale request files.",    "input": {     "reason": "string - optional, recorded in steps"@@ -4687,6 +5759,7 @@   {    "name": "agent_start",    "tier": "app",+   "source": "altium",    "summary": "Bootstrap the resident DelphiScript agent inside Altium (renders the script, runs it through the -R lane, waits for the heartbeat). Optional: every agent-backed verb does this on demand.",    "input": {     "waitSec": "int, default 45 - how long to wait for the first heartbeat"@@ -4717,6 +5790,7 @@   {    "name": "agent_status",    "tier": "app",+   "source": "altium",    "summary": "Is the agent loop alive and responsive, in which workspace, and is any loop resident anywhere? Read-only; never starts the agent.",    "input": {},    "output": {@@ -4743,6 +5817,7 @@   {    "name": "agent_stop",    "tier": "app",+   "source": "altium",    "summary": "Stop the selected instance's resident agent loop (drops a stop file and waits up to 12 s for the heartbeat to go stale).",    "input": {},    "output": {@@ -4767,6 +5842,7 @@   {    "name": "animate_view",    "tier": "app",+   "source": "altium",    "summary": "Camera/zoom choreography on the current document - native Altium camera commands, animated by Altium itself.",    "input": {     "lane": "pcb (default) | sch",@@ -4797,6 +5873,7 @@   {    "name": "check_dialogs",    "tier": "app",+   "source": "altium",    "summary": "List every Altium dialog currently open, classified, each with a screenshot (the only way to READ one: Altium paints its dialog text).",    "input": {     "screenshots": "bool, default true"@@ -4823,6 +5900,7 @@   {    "name": "close",    "tier": "app",+   "source": "altium",    "summary": "Polite close (releases the licence seat). Frees a script engine parked on a breakpoint first (Altium refuses to close over one). discardChanges:true answers Altium's save prompts with Save None for callers whose modified documents are ALL their own; force needs acceptSeatLoss.",    "input": {     "acceptSeatLoss": "bool",@@ -4853,6 +5931,7 @@   {    "name": "close_document",    "tier": "app",+   "source": "altium",    "summary": "Close ONE open document by path through its document handle. Never saves.",    "input": {     "path": "absolute path of the open document (required)"@@ -4880,6 +5959,7 @@   {    "name": "connect_workspace",    "tier": "app",+   "source": "altium",    "summary": "Open Altium's workspace picker (the 'Not Connected' menu) and return a screenshot with a coordMap. The list is a custom control with no UIA children, so the caller clicks the row.",    "input": {},    "output": {@@ -4905,6 +5985,7 @@   {    "name": "demo",    "tier": "app",+   "source": "altium",    "summary": "The tour. Default: one background beat per call with a screenshot. live:true = the narrated FOREGROUND show: ab caption + document + in-bridge camera choreography per stop, returning the narration text for YOUR TTS.",    "input": {     "live": "bool",@@ -4936,6 +6017,7 @@   {    "name": "describe",    "tier": "app",+   "source": "altium",    "summary": "This list - the bridge's verbs and schemas for ab's Verbs tab.",    "input": {},    "output": {@@ -4953,6 +6035,7 @@   {    "name": "diagnostics",    "tier": "app",+   "source": "altium",    "summary": "Bridge-side facts for a bug report: environment variables, every Altium install found, Altium's windows, the agent status block and the cache directory.",    "input": {},    "output": {@@ -4978,6 +6061,7 @@   {    "name": "dialog_log",    "tier": "app",+   "source": "altium",    "summary": "What the standing dialog reaper (and the bridge's own recoveries) pressed, newest last: nuisance boxes, script-error boxes, discarded save prompts, silent engine halts cleared.",    "input": {     "limit": "int, default 25"@@ -5005,6 +6089,7 @@   {    "name": "dismiss_dialogs",    "tier": "app",+   "source": "altium",    "summary": "Press one named button (default OK) on the detected Altium dialogs through UIA - no cursor, no focus steal. titles narrows it to dialogs whose title contains one of the strings.",    "input": {     "button": "string, default 'OK' - the button's accessible name",@@ -5037,6 +6122,7 @@   {    "name": "ensure_licensed",    "tier": "app",+   "source": "altium",    "summary": "One call to get a usable Altium: launch if needed, then claim a seat (Use License via UIA). Optional escalations: sign out to force a seat release, or start the free-trial flow.",    "input": {     "allowSignInReset": "bool - if no seat is free, Sign Out (the human must sign back in)",@@ -5072,6 +6158,7 @@   {    "name": "eval",    "tier": "app",+   "source": "altium",    "summary": "Run a DelphiScript snippet inside Altium (optional Var block, then Begin ... End;) on the CURRENT document, or on filePath opened first.",    "input": {     "filePath": "optional: the document to make current first (a .PcbDoc for PCBServer.GetCurrentPCBBoard)",@@ -5100,6 +6187,7 @@   {    "name": "extension_ping",    "tier": "app",+   "source": "altium",    "summary": "Does the AdomBridge .NET extension answer? Sends AdomBridge:Ping through the -R lane and waits up to 30 s for its result file.",    "input": {},    "output": {@@ -5123,6 +6211,7 @@   {    "name": "foreground",    "tier": "app",+   "source": "altium",    "summary": "Bring Altium in front of the user - the sanctioned exception to the never-foreground rule.",    "input": {     "reason": "string >=10 chars, written for the HUMAN (required)"@@ -5147,6 +6236,7 @@   {    "name": "install",    "tier": "app",+   "source": "altium",    "summary": "Install Altium Designer on this machine, STAGED, with the rules in the verb (from 0.2.29). stage: preflight | get_installer | launch | wait | license, or omit it and 'auto' picks the stage from the machine's state. The verb looks before it asks, verifies the installer's Authenticode signature (Valid, CN=Altium LLC) before anything runs, refuses to launch into an empty room, toasts the human itself and says truthfully whether the toast displayed, and does the licensing clicks (Refresh / Use License) ITSELF.",    "input": {     "humanIsPresent": "bool, REQUIRED true for stage launch: the UAC prompt auto-denies in ~2 minutes",@@ -5184,6 +6274,7 @@   {    "name": "install_extension",    "tier": "app",+   "source": "altium",    "summary": "Install, update or remove the AdomBridge .NET extension (the PowerShell installer shipped beside the bridge). Altium must be CLOSED.",    "input": {     "remove": "bool, default false - uninstall instead"@@ -5212,6 +6303,7 @@   {    "name": "install_receipt",    "tier": "app",+   "source": "altium",    "summary": "The last bundle install's full receipt (proof frame included), for a client whose install call outlived ab's budget.",    "input": {},    "output": {@@ -5230,6 +6322,7 @@   {    "name": "instances",    "tier": "app",+   "source": "altium",    "summary": "Every running Altium (Designer + Designer Develop can run together).",    "input": {},    "output": {@@ -5250,6 +6343,7 @@   {    "name": "launch",    "tier": "app",+   "source": "altium",    "summary": "Start Altium (the newest numbered install, or the one install names) and wait for its main window, then hand the user's own window back. Answers alreadyRunning when one is up.",    "input": {     "background": "bool, default TRUE: remember the user's foreground window and restore it once Altium is up. Pass false only when the user asked to SEE Altium come up.",@@ -5282,6 +6376,7 @@   {    "name": "license",    "tier": "app",+   "source": "altium",    "summary": "Drive the License Management page (UIA first - no cursor, no foreground).",    "input": {     "action": "show|refresh|use_license|start_trial|sign_out"@@ -5309,6 +6404,7 @@   {    "name": "license_status",    "tier": "app",+   "source": "altium",    "summary": "Plain-language answer to 'what Altium licence am I on?': the state from the window title plus a capture of the License Management page.",    "input": {},    "output": {@@ -5336,6 +6432,7 @@   {    "name": "list_commands",    "tier": "app",+   "source": "altium",    "summary": "Search Altium's process-launcher catalog (about 1,100 Server:Command entries parsed from the install's System/*.rcs files) by text and/or server.",    "input": {     "limit": "int, default 50",@@ -5367,6 +6464,7 @@   {    "name": "open_document",    "tier": "app",+   "source": "altium",    "summary": "Open a document or project by path through the agent and show it without focusing it. An already-open document is activated, not reloaded.",    "input": {     "filePath": "absolute Windows path (alias: path)",@@ -5398,6 +6496,7 @@   {    "name": "open_project",    "tier": "app",+   "source": "altium",    "summary": "Open a project (.PrjPcb / .PrjScr / .PrjMbd / .PrjHar / .LibPkg) by path. Same handler as altium_open_document.",    "input": {     "filePath": "absolute Windows path (alias: path)",@@ -5427,6 +6526,7 @@   {    "name": "panel",    "tier": "app",+   "source": "altium",    "summary": "Activate a docked panel TAB (SCH Library, PCB Library, Components, Projects, Properties) in the BACKGROUND - the 'ganged-up view' needs the right panels in front, and no Altium server process switches a tab.",    "input": {     "ensureId": "string optional - panel ID for Client:CustomizeResources (e.g. TSchLibPanel) when the panel may not exist yet",@@ -5459,6 +6559,7 @@   {    "name": "progress",    "tier": "app",+   "source": "altium",    "summary": "The bridge's timing book: phases in flight right now (percent/ETA blocks ab paints on the taskbar), measured phase history and per-verb run statistics.",    "input": {},    "output": {@@ -5479,6 +6580,7 @@   {    "name": "readiness",    "tier": "app",+   "source": "altium",    "summary": "The one-call gate: is Altium installed, running, licensed, and is the resident agent alive? Answers with Altium closed and never touches the script engine.",    "input": {},    "output": {@@ -5510,6 +6612,7 @@   {    "name": "run_command",    "tier": "app",+   "source": "altium",    "summary": "Run an Altium process (Server:Command) through the agent, on the CURRENT document or on filePath opened first.",    "input": {     "command": "string - e.g. PCB:Zoom",@@ -5539,6 +6642,7 @@   {    "name": "run_script",    "tier": "app",+   "source": "altium",    "summary": "One shot: run a procedure of YOUR OWN .PrjScr through Altium's -R command line. Only for when the agent is NOT resident.",    "input": {     "prjscr": "absolute path to a .PrjScr on this machine (required)",@@ -5571,6 +6675,7 @@   {    "name": "save",    "tier": "app",+   "source": "altium",    "summary": "Save the focused document, or open filePath first and save that (WorkspaceManager:SaveObject on the focused document).",    "input": {     "filePath": "path - optional; opened and made current before the save"@@ -5598,6 +6703,7 @@   {    "name": "sch_zoom",    "tier": "app",+   "source": "altium",    "summary": "Find parts on a sheet: select them (everything else deselected), frame the view on them and return a proof frame. The schematic half of cross-probing (the board half: altium_zoom_to).",    "input": {     "designators": "[string] or 'R1,U2' (required)",@@ -5630,6 +6736,7 @@   {    "name": "select_net",    "tier": "app",+   "source": "altium",    "summary": "Select one net as a whole on the current board (tracks, arcs, vias, pads, pours) and nothing else, optionally framing it; no net clears the selection.",    "input": {     "margin": "mm, default 1",@@ -5662,6 +6769,7 @@   {    "name": "selection",    "tier": "app",+   "source": "altium",    "summary": "What the user has selected in the current board (components with position mm, rotation, side, footprint, size) or sheet (components with location mils and orientation).",    "input": {     "filePath": "optional: the document to make current first",@@ -5688,6 +6796,7 @@   {    "name": "selftest_script_error",    "tier": "app",+   "source": "altium",    "summary": "Regression test for the script-error safety net (from 0.2.23): makes the agent raise a REAL DelphiScript runtime error on purpose and checks that the bridge photographs Altium's Error box, stops the halted script itself and leaves no dialog behind. Flashes one error box for under a second. Run it after any change to agent.rs / dialogs.rs and once on every new Altium build.",    "input": {},    "output": {@@ -5714,6 +6823,7 @@   {    "name": "set_layer_visibility",    "tier": "app",+   "source": "altium",    "summary": "Show or hide one layer of the current board (by layer id) and refresh the view and the layer tabs.",    "input": {     "displayed": "bool, default true",@@ -5743,6 +6853,7 @@   {    "name": "setup_trial",    "tier": "app",+   "source": "altium",    "summary": "Onboarding state machine: from nothing to a working trial. Each call reports the stage it found (install | launch | signin | done) and the ONE next action; human steps are named, not faked.",    "input": {},    "output": {@@ -5770,6 +6881,7 @@   {    "name": "show_2d_board",    "tier": "app",+   "source": "altium",    "summary": "Open a .PcbDoc, switch to 2D, zoom to fit, and return a proof frame. With no filePath it opens the bundled Bluetooth Sentinel board.",    "input": {     "filePath": "path to a .PcbDoc - default: the bundled example board",@@ -5807,6 +6919,7 @@   {    "name": "show_3d_board",    "tier": "app",+   "source": "altium",    "summary": "Open a .PcbDoc, switch to 3D, zoom to fit, and return a proof frame. With no filePath it opens the bundled Bluetooth Sentinel board.",    "input": {     "filePath": "path to a .PcbDoc - default: the bundled example board",@@ -5845,6 +6958,7 @@   {    "name": "show_3d_chip",    "tier": "app",+   "source": "altium",    "summary": "Open a PcbLib member in the footprint editor in 3D, zoom to fit, and capture a proof frame of the part's 3D body.",    "input": {     "footprintName": "string (alias: name) - default: the first footprint of YOUR library, SO-G3 in the demo library",@@ -5882,6 +6996,7 @@   {    "name": "show_footprint",    "tier": "app",+   "source": "altium",    "summary": "Open a PcbLib member in the footprint editor in 2D, zoom to fit, and capture a proof frame.",    "input": {     "footprintName": "string (alias: name) - default: the first footprint of YOUR library, SO-G3 in the demo library",@@ -5920,6 +7035,7 @@   {    "name": "show_library",    "tier": "app",+   "source": "altium",    "summary": "Open a .SchLib or .PcbLib (kind taken from the extension), select its first component, return a proof frame and the component names.",    "input": {     "libraryPath": "path to a .SchLib/.PcbLib (alias: filePath) - default: the bundled SpiritLevel SchLib",@@ -5957,6 +7073,7 @@   {    "name": "show_project",    "tier": "app",+   "source": "altium",    "summary": "Open a project (.PrjPcb) through the agent and return a proof frame of Altium's main window. With no filePath it opens Altium's bundled example project (Bluetooth Sentinel).",    "input": {     "filePath": "path to a .PrjPcb - default: the bundled Bluetooth Sentinel example",@@ -5995,6 +7112,7 @@   {    "name": "show_schematic",    "tier": "app",+   "source": "altium",    "summary": "Open a .SchDoc, zoom to fit, and return a proof frame. With no filePath it opens the bundled Bluetooth Sentinel top sheet.",    "input": {     "filePath": "path to a .SchDoc - default: the bundled example sheet",@@ -6033,6 +7151,7 @@   {    "name": "show_symbol",    "tier": "app",+   "source": "altium",    "summary": "Open a SchLib member in the Symbol editor and capture a background proof.",    "input": {     "libraryPath": "path",@@ -6059,6 +7178,7 @@   {    "name": "signin",    "tier": "app",+   "source": "altium",    "summary": "Report-only alias of altium_signin_status: it does NOT sign anyone in. Signing in to Altium is a browser flow only the human can complete.",    "input": {},    "output": {@@ -6087,6 +7207,7 @@   {    "name": "signin_status",    "tier": "app",+   "source": "altium",    "summary": "Account and Altium 365 workspace connection as Altium's own UI reports it: licence state from the title, and whether the workspace menu reads 'Not Connected'.",    "input": {},    "output": {@@ -6114,6 +7235,7 @@   {    "name": "state",    "tier": "app",+   "source": "altium",    "summary": "The whole picture in one call: licence state, windows, dialogs, a screenshot of every main/dialog window, and the agent's logical state (focused document, focused project, open documents).",    "input": {     "screenshots": "bool, default true"@@ -6149,6 +7271,7 @@   {    "name": "status",    "tier": "app",+   "source": "altium",    "summary": "Is Altium running, licensed, and is the resident agent alive?",    "input": {},    "output": {@@ -6173,6 +7296,7 @@   {    "name": "uninstall",    "tier": "app",+   "source": "altium",    "summary": "Remove the bridge's own cache directory (agent workspaces, rendered agent scripts, the Altium 365 token file). Altium Designer and the user's designs are never touched.",    "input": {     "dryRun": "bool - report only, delete nothing"@@ -6199,6 +7323,7 @@   {    "name": "window_info",    "tier": "app",+   "source": "altium",    "summary": "Altium's top-level windows plus any open dialogs, without screenshots. The cheap way to ask 'is a modal blocking the engine?'.",    "input": {},    "output": {@@ -6222,6 +7347,7 @@   {    "name": "zoom_to",    "tier": "app",+   "source": "altium",    "summary": "Frame the PCB view on a rectangle, a part (or several) or a whole net, with a margin.",    "input": {     "margin": "mm (default 1)",@@ -6253,6 +7379,7 @@   {    "name": "a365_configure",    "tier": "platform",+   "source": "altium",    "summary": "Store the Altium 365 workspace domain and, optionally, a Bearer token created by hand in the workspace web UI (Admin - Developer). Local-only; tokens never appear in replies.",    "input": {     "token": "string - optional developer token",@@ -6281,6 +7408,7 @@   {    "name": "a365_files_upload",    "tier": "platform",+   "source": "altium",    "summary": "Upload one local file to the workspace's Files Service and get a temporary opaque file id to pass to a library mutation.",    "input": {     "filePath": "path on THIS machine (required)",@@ -6309,6 +7437,7 @@   {    "name": "a365_library_overview",    "tier": "platform",+   "source": "altium",    "summary": "One fixed read-only query: the workspace library's name, description, update time, component ids/names and footprint/symbol totals.",    "input": {},    "output": {@@ -6331,6 +7460,7 @@   {    "name": "a365_library_schema",    "tier": "platform",+   "source": "altium",    "summary": "Read-only schema map: the GraphQL queries and mutations whose names mention lib, component, symbol, footprint, part or datasheet, with mutation argument types.",    "input": {     "timeout": "int seconds, default 60"@@ -6355,6 +7485,7 @@   {    "name": "a365_logout",    "tier": "platform",+   "source": "altium",    "summary": "Revoke the refresh grant at Altium and remove every cached OAuth token. Workspace and client id stay configured.",    "input": {},    "output": {@@ -6378,6 +7509,7 @@   {    "name": "a365_oauth_begin",    "tier": "platform",+   "source": "altium",    "summary": "Start the Altium 365 OAuth (PKCE + ActionWait) sign-in: the bridge starts listening FIRST, then returns the authorize URL for the user's browser. Works with Altium closed.",    "input": {     "clientId": "string - an Altium-issued public OAuth client id (or the stored one)",@@ -6411,6 +7543,7 @@   {    "name": "a365_oauth_cancel",    "tier": "platform",+   "source": "altium",    "summary": "Cancel a waiting OAuth flow.",    "input": {},    "output": {@@ -6432,6 +7565,7 @@   {    "name": "a365_oauth_status",    "tier": "platform",+   "source": "altium",    "summary": "State of the OAuth flow started by altium_a365_oauth_begin: idle | waiting | authorized | cancelled | error.",    "input": {},    "output": {@@ -6458,6 +7592,7 @@   {    "name": "a365_query",    "tier": "platform",+   "source": "altium",    "summary": "Run one GraphQL query or mutation against the workspace's GraphQL gateway (https://<workspace>/svc/napi/gateway/graphql/) with the stored token.",    "input": {     "query": "string - GraphQL (required)",@@ -6489,6 +7624,7 @@   {    "name": "a365_refresh",    "tier": "platform",+   "source": "altium",    "summary": "Exchange the stored refresh token for a new access token (and store a rotated refresh token if one comes back).",    "input": {},    "output": {@@ -6512,6 +7648,7 @@   {    "name": "a365_status",    "tier": "platform",+   "source": "altium",    "summary": "Is the Altium 365 lane configured, is there a token, and is it LIVE (probed with a one-row GraphQL query)?",    "input": {},    "output": {@@ -6541,6 +7678,7 @@   {    "name": "compile_intlib",    "tier": "platform",+   "source": "altium",    "summary": "Compile a .LibPkg into an integrated library (.IntLib).",    "input": {     "libpkgPath": "path to a .LibPkg (required)",@@ -6570,6 +7708,7 @@   {    "name": "extract_intlib",    "tier": "platform",+   "source": "altium",    "summary": "Extract the editable .SchLib/.PcbLib sources from a compiled .IntLib (Altium writes them next to the IntLib and opens them).",    "input": {     "intlibPath": "path to an .IntLib (required)",@@ -6597,6 +7736,7 @@   {    "name": "import_kicad",    "tier": "platform",+   "source": "altium",    "summary": "Import a KiCad file with Altium's own KiCad importer, driven through the AdomBridge .NET extension.",    "input": {     "filePath": "path to a .kicad_sym / .kicad_sch / .kicad_pcb (required)",@@ -6627,6 +7767,7 @@   {    "name": "outjob_info",    "tier": "platform",+   "source": "altium",    "summary": "An OutJob's containers (output media), the outputs in each, and their key settings (units, decimals, plotted layer count), read from the .OutJob file: Altium need not be running.",    "input": {     "outjobPath": "path to the .OutJob (required)"@@ -6651,6 +7792,7 @@   {    "name": "run_outjob",    "tier": "platform",+   "source": "altium",    "summary": "Run one output medium of an .OutJob (gerbers, drill, BOM, PDFs...) and list what it wrote under 'Project Outputs for <project>'.",    "input": {     "medium": "string, default 'Folder Structure' - the OutputMedium name inside the OutJob",@@ -6692,6 +7834,7 @@   {    "name": "variants",    "tier": "platform",+   "source": "altium",    "summary": "Assembly variants of a project (which parts are fitted on which build): list them, make or change one with not-fitted parts (or put parts back), or remove one. Altium's script API cannot create variants, so the bridge writes them into the .PrjPcb, reloads the project and reads back what Altium holds.",    "input": {     "fitted": "[designators] to put back (their variation is dropped)",@@ -6730,6 +7873,7 @@   {    "name": "workspace_place",    "tier": "platform",+   "source": "altium",    "summary": "Put a part from the Altium 365 workspace on a sheet: search, pick a result, place it (Altium's own placement, so the part keeps its workspace link, parameters and footprint), move it to x,y and name it.",    "input": {     "designator": "optional, else Altium's ('C?')",@@ -6769,6 +7913,7 @@   {    "name": "workspace_search",    "tier": "platform",+   "source": "altium",    "summary": "Search the Altium 365 workspace's components (the shared cloud library Altium is signed in to) through Altium's own Components panel: name, description and footprint per result.",    "input": {     "limit": "int, default 25",