← Commit history

standard 0.4.1: coverage counts only what works: equivalents take [verb, match, note?] with match exact | partial | unsupported (listed, not counted; fusion-lane #10); conventions: sheet is the sheet number on a tool without sheet files, save may default false where a save costs (a cloud version); regenerated with fusion 1.12.2 (21 schematic verbs) and altium 0.2.76: Altium 211, KiCad 143, Fusion 107 of 236

Colby Knox ·375928969d ·14d ago ·parent e99af55
8 files changed +180−76
README.md+10−5
@@ -57,12 +57,12 @@ verb by verb: [docs/coverage.md](docs/coverage.md). <!-- coverage:start (tools/generate.py writes this) --> | Tier | Verbs | Altium | KiCad | Fusion 360 | |---|---|---|---|---|-| **core** | 93 | 80 | 72 | 29 |-| **native** | 46 | 36 | 35 | 18 |-| **checks** | 37 | 32 | 11 | 4 |+| **core** | 93 | 86 | 72 | 48 |+| **native** | 46 | 36 | 35 | 20 |+| **checks** | 37 | 33 | 11 | 4 | | **app** | 60 | 56 | 25 | 35 | | **platform** | 19 | 19 | 0 | 0 |-| standard (all but platform) | 236 | 204 | 143 | 86 |+| standard (all but platform) | 236 | 211 | 143 | 107 | <!-- coverage:end -->  The **checks** tier is where the other bridges are furthest behind, and it is the cheapest to close: those verbs are@@ -107,7 +107,10 @@ adom-wiki repo push adom/eda-bridge-standard -m "kicad 1.0.63 reference" --files `generate.py` reads each bridge's newest file in `reference/` by version number. `tools/tiers.json` puts each Altium verb in a tier; `tools/equivalents/<bridge>.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 push the bridge's catalog before crediting its new verbs.+(`generate.py` warns and leaves it out otherwise), so push the bridge's catalog before crediting its new verbs. An+entry is `[verb, match]` or `[verb, match, note]`: `exact`, `partial` (the note says what is missing) or `unsupported`+(the verb refuses the whole job: listed, not counted). An entry wins over a verb of the same name, so a bridge can mark+its own standard-named verb partial or unsupported.  ## Proposing a verb @@ -152,6 +155,8 @@ Decisions so far (proposals from the KiCad and Fusion bridges, 2026-10-27; issue  ## Status +Version 0.4.1: coverage counts only what works: a bridge marks a verb `partial` (with a note) or `unsupported` in its+equivalents file ([conventions](docs/conventions.md)); `sheet` on a tool without sheet files is the sheet number. Version 0.4.0: the checks engine, `adom-eda-checks`, is on this page in `engine/` with its first five checks; fab limits come in from adom/pcb-design-rules, never built in. Version 0.3.1: an internal plane is named `In<n>.Cu` by its place in the copper stack, with `kind: "plane"` ([board model](docs/board-model.md#settled-questions)); the stack-up companion gives each copper layer's board model name in `layer`. Version 0.3.0: 33 more verbs from other bridges, all agreed by the Altium bridge's thread: 26 from the KiCad bridge (the board exports ODB++, IPC-2581, IPC-356, GenCAD and DXF, `render_board_3d`, `remove_parts`, `edit_parts`, `align_parts`, `copy_routing`, projects, library footprints, `estimate_cost`, `check_clearance`, `place_decoupling`, `plan_fanout`) and 7 from the Fusion bridge (`bodies`, `render_board_layers`, `plan_route`, `generate_body`, `library_views`, `close_all_documents`, `document_info`). A bridge's own equivalents now win over a name match, so a verb that shares a standard name but does another job is not credited for it. Version 0.2.1: this page has one keeper (standard-lane) and bridge threads push only their own files (*Keeping it in sync*), one file per owner (`tools/equivalents/<bridge>.json`, `tools/proposed/<thread>.json`); the decisions on the KiCad and Fusion proposals are written down above; a lesson from the Fusion bridge on DRC severity is in
docs/conventions.md+9
@@ -10,6 +10,10 @@ the same way, and lets the shared checks run on any of them.   alias, so `docs/coverage.md` can list it as exact. - 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.+- Coverage counts only what works. A verb that answers `not_supported` for its whole job is marked `unsupported` in the+  bridge's `tools/equivalents/<bridge>.json` with the reason (`["sch_update_from_library", "unsupported", "the tool's+  library manager asks about each part"]`): listed, not counted. A verb that refuses some of its arguments is `partial`,+  with a note naming them. The entry wins over a name match, so this works for a verb under its standard name too. - 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/<thread>.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_`;@@ -26,6 +30,11 @@ the same way, and lets the shared checks run on any of them.   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.+- `sheet` is the sheet's file path. On a tool whose sheets are not files (Fusion keeps them in one design), `sheet` is+  the sheet's number, from 1, and `filePath` names the design. A tool that stores no item ids builds stable ones (Fusion:+  the item's kind and position) and says so in `sch_items`' hint.+- `save` defaults to true on the sheet verbs, except where a save has a cost the user would notice (Fusion: every save+  is a new cloud version): there it defaults to false, and the verb's describe says so. - 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.
docs/coverage.md+34−34
@@ -1,17 +1,17 @@ # Coverage: every standard verb on each bridge -Altium bridge 0.2.76 (the reference), KiCad bridge 1.0.63, Fusion 360 bridge 1.12.1. 54 verbs came from other bridges' proposals (tools/proposed/); 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.+Altium bridge 0.2.76 (the reference), KiCad bridge 1.0.63, Fusion 360 bridge 1.12.2. 54 verbs came from other bridges' proposals (tools/proposed/); 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 (`verbs/coverage.json` names what in `note`); `unsupported` answers `not_supported` for the whole job and is not counted; blank is missing. Generated by `tools/generate.py` from `verbs/coverage.json`; do not edit by hand.  | Tier | Verbs | Altium | KiCad | Fusion 360 | |---|---|---|---|---|-| **core** | 93 | 80 | 72 | 29 |-| **native** | 46 | 36 | 35 | 18 |-| **checks** | 37 | 32 | 11 | 4 |+| **core** | 93 | 86 | 72 | 48 |+| **native** | 46 | 36 | 35 | 20 |+| **checks** | 37 | 33 | 11 | 4 | | **app** | 60 | 56 | 25 | 35 | | **platform** | 19 | 19 | 0 | 0 |-| standard (all but platform) | 236 | 204 | 143 | 86 |+| standard (all but platform) | 236 | 211 | 143 | 107 |  ## core @@ -22,7 +22,7 @@ Read and edit the design. Every bridge provides these: they are how an AI sees a | `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` |  | `fusion_attach_3d_package` (partial) | | `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` | `kicad_footprint_models` (partial) |  | | `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` |  |  |-| `align_parts` *proposed* | Line parts up on a common left, right, top, bottom or centre line, or space them evenly, by courtyard box or by anchor point. One undo step, with... |  | `kicad_align_parts` |  |+| `align_parts` *proposed* | Line parts up on a common left, right, top, bottom or centre line, or space them evenly, by courtyard box or by anchor point. One undo step, with... | `altium_align_parts` | `kicad_align_parts` |  | | `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` |@@ -33,12 +33,12 @@ Read and edit the design. Every bridge provides these: they are how an AI sees a | `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` |  |  |-| `copy_routing` *proposed* | Copy the tracks and vias inside a box to an offset, remapping nets by pairing parts (a designator map or pattern), so a repeated channel gets the same... |  | `kicad_copy_routing` |  |+| `copy_routing` *proposed* | Copy the tracks and vias inside a box to an offset, remapping nets by pairing parts (a designator map or pattern), so a repeated channel gets the same... | `altium_copy_routing` | `kicad_copy_routing` |  | | `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` |  |  | | `edit_footprint` *proposed* | Edit a library footprint in place: change, delete, add or renumber pads; add, replace or delete graphics on a layer; set its description, tags and... |  | `kicad_fp_edit` |  |-| `edit_parts` *proposed* | Edit placed parts: value, designator, any field (add, change, remove), do-not-populate, exclusion from the BOM or position files, mounting type and the... |  | `kicad_edit_parts` |  |+| `edit_parts` *proposed* | Edit placed parts: value, designator, any field (add, change, remove), do-not-populate, exclusion from the BOM or position files, mounting type and the... | `altium_edit_parts` | `kicad_edit_parts` |  | | `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_footprint_graphics` (partial) |  | | `generate_body` *proposed* | Make a part's 3D body from its package family and its datasheet dimensions (chip, SOIC, QFN, QFP, BGA, SOT-23, DFN, MELF, electrolytic can, crystal, pin... |  |  |  |@@ -66,9 +66,9 @@ Read and edit the design. Every bridge provides these: they are how an AI sees a | `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_graphics` *proposed* | Remove board graphics (lines, rectangles, circles, arcs, polygons, texts, dimensions) by id, or every one on a layer and of a kind. One undo step. |  | `kicad_remove_graphics` |  |+| `remove_graphics` *proposed* | Remove board graphics (lines, rectangles, circles, arcs, polygons, texts, dimensions) by id, or every one on a layer and of a kind. One undo step. | `altium_remove_graphics` | `kicad_remove_graphics` |  | | `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_parts` *proposed* | Remove placed parts from the board by designator, as one undo step. The library is not touched (that is remove_footprint). |  | `kicad_remove_parts` |  |+| `remove_parts` *proposed* | Remove placed parts from the board by designator, as one undo step. The library is not touched (that is remove_footprint). | `altium_remove_parts` | `kicad_remove_parts` |  | | `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` |  |  |@@ -76,32 +76,32 @@ Read and edit the design. Every bridge provides these: they are how an AI sees a | `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 / kicad_add_track` | `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... | `altium_sch_bus` | `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. | `altium_sch_bus_entry` | `kicad_sch_bus_entry` |  |+| `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... | `altium_sch_bus` | `kicad_sch_bus` | `fusion_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. | `altium_sch_bus_entry` | `kicad_sch_bus_entry` | `fusion_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... | `altium_sch_connect_pins` | `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. | `altium_sch_connect_to_bus` | `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... | `altium_sch_sheet_symbol` (partial) | `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... | `altium_sch_delete_wire` | `kicad_sch_delete_wire` |  |+| `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... | `altium_sch_connect_pins` | `kicad_sch_connect_pins` | `fusion_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. | `altium_sch_connect_to_bus` | `kicad_sch_connect_to_bus` | `fusion_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... | `altium_sch_sheet_symbol` (partial) | `kicad_sch_create` | `fusion_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... | `altium_sch_delete_wire` | `kicad_sch_delete_wire` | `fusion_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. | `altium_sch_edit_label` | `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;... | `altium_sch_fix_connectivity` | `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... | `altium_sch_hierarchy` | `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,... | `altium_sch_items` | `kicad_sch_items` |  |-| `sch_junction` *proposed* | Add junction dots at points, or remove dots by id or point. One undo step. | `altium_sch_junction` | `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,... | `altium_sch_move_region` | `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). | `altium_sch_page` | `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,... | `altium_read_sheet_file` (partial) | `kicad_sch_pins` |  |+| `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. | `altium_sch_edit_label` | `kicad_sch_edit_label` | `fusion_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;... | `altium_sch_fix_connectivity` | `kicad_sch_fix_connectivity` | `fusion_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... | `altium_sch_hierarchy` | `kicad_sch_hierarchy` | `fusion_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,... | `altium_sch_items` | `kicad_sch_items` | `fusion_sch_items` |+| `sch_junction` *proposed* | Add junction dots at points, or remove dots by id or point. One undo step. | `altium_sch_junction` | `kicad_sch_junction` | `fusion_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,... | `altium_sch_move_region` | `kicad_sch_move_region` | `fusion_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). | `altium_sch_page` | `kicad_sch_page` | `fusion_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,... | `altium_read_sheet_file` (partial) | `kicad_sch_pins` | `fusion_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. | `altium_sch_reset_fields` | `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... | `altium_sch_sheet_symbol` (partial) | `kicad_sch_sheet_pins` |  |+| `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. | `altium_sch_reset_fields` | `kicad_sch_reset_fields` | `fusion_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... | `altium_sch_sheet_symbol` (partial) | `kicad_sch_sheet_pins` | `fusion_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` (partial) |  |-| `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. | `altium_sch_split_wire` | `kicad_sch_split_wire` |  |+| `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. | `altium_sch_split_wire` | `kicad_sch_split_wire` | `fusion_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. | `altium_sch_text` | `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... | `altium_sch_trace_point` | `kicad_sch_trace_point` |  |+| `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. | `altium_sch_text` | `kicad_sch_text` | `fusion_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... | `altium_sch_trace_point` | `kicad_sch_trace_point` | `fusion_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_layer_count` *proposed* | Set the board's copper layer count (2, 4, 6 or 8): the layer table and the stack-up, keeping the board thickness. |  | `kicad_set_layer_count` |  |+| `set_layer_count` *proposed* | Set the board's copper layer count (2, 4, 6 or 8): the layer table and the stack-up, keeping the board thickness. | `altium_set_layer_count` | `kicad_set_layer_count` |  | | `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` | `kicad_footprint_models` (partial) |  | | `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` |  |  |@@ -152,13 +152,13 @@ Wraps the EDA tool's own feature (its DRC, ERC, Gerbers, pours, Update PCB). Eve | `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_board_3d` *proposed* | Render a 3D picture of the board from one side to an image file, through the tool's own renderer, without opening a window. |  | `kicad_render_board_3d` |  | | `render_board_layers` *proposed* | Render chosen board layers to an image file without opening a window: a preset view (copper, silkscreen, solder mask, paste, outline, drill, assembly or... |  | `kicad_export_svg` (partial) | `fusion_export_board_image` (partial) |-| `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... | `altium_show_schematic` (partial) | `kicad_render_schematic` |  |+| `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... | `altium_show_schematic` (partial) | `kicad_render_schematic` | `fusion_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. | `altium_sch_update_from_library` | `kicad_sch_update_from_library` |  |+| `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. | `altium_sch_update_from_library` | `kicad_sch_update_from_library` | `fusion_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` |  |  |@@ -180,7 +180,7 @@ Engineering computed from the board model, not by the tool: one shared engine, s | `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_clearance` *proposed* | Measure the gaps between parts, courtyard to courtyard or pad copper to pad copper, for the listed parts or the whole board, and report every pair under a... |  | `kicad_check_clearance` |  |+| `check_clearance` *proposed* | Measure the gaps between parts, courtyard to courtyard or pad copper to pad copper, for the listed parts or the whole board, and report every pair under a... | `altium_check_clearance` | `kicad_check_clearance` |  | | `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) |  |
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "eda-bridge-standard",-  "version": "0.4.0",+  "version": "0.4.1",   "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.",
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.4.0",+  "version": "0.4.1",   "hero": {     "type": "billboard",     "headline": "One standard for every EDA bridge",
tools/generate.py+9−3
@@ -44,6 +44,8 @@ def strip(name, prefix):     return name[len(prefix):] if name.startswith(prefix) else name  +# exact and partial count as covered; unsupported (the verb answers not_supported for the whole job) is listed, not counted+MATCHES = ("exact", "partial", "unsupported") PROPOSAL_FIELDS = ["name", "tier", "summary", "input", "output", "hint", "proposedBy", "since", "agreedBy"]  @@ -130,7 +132,9 @@ def main():             # the bridge's own equivalents file comes before a name match: a verb can share a standard name and do             # another job (kicad_edit_footprint edited placed parts; the standard edit_footprint is the library verb)             if s["name"] in eq.get(b, {}):-                verb, match = eq[b][s["name"]]+                verb, match, *note = eq[b][s["name"]]+                if match not in MATCHES:+                    raise SystemExit(f"tools/equivalents/{b}.json: {s['name']}: match {match!r} is not one of {', '.join(MATCHES)}")                 parts = [strip(p.strip(), prefixes[b]) for p in re.split(r"\s*[/+]\s*", verb)]                 # 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]]@@ -138,6 +142,8 @@ def main():                     print(f"warning: {b} {s['name']}: {', '.join(absent)} not in reference/{b}-{bridges[b]['version']}.json, not counted")                 else:                     row[b] = {"verb": " / ".join(prefixes[b] + p for p in parts), "match": match}+                    if note:+                        row[b]["note"] = note[0]             if row[b] is None and s["name"] in have[b]:                 row[b] = {"verb": prefixes[b] + s["name"], "match": "exact"}         coverage.append(row)@@ -172,14 +178,14 @@ def main():           "",           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/); 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.",+          "`exact` is the same job under the same or an equivalent name; `partial` does part of it or does it differently (`verbs/coverage.json` names what in `note`); `unsupported` answers `not_supported` for the whole job and is not counted; 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 | Altium | KiCad | Fusion 360 |", "|---|---|---|---|---|"]         for r, s in zip(coverage, standard):             if r["tier"] != t:                 continue-            cell = lambda c: "" if not c else (f"`{c['verb']}`" + (" (partial)" if c["match"] == "partial" else ""))+            cell = lambda c: "" if not c else ("unsupported" if c["match"] == "unsupported" else f"`{c['verb']}`" + (" (partial)" if c["match"] == "partial" else ""))             summ = s["summary"].replace("|", "/").replace("\n", " ")             if len(summ) > 160:                 summ = summ[:157].rsplit(" ", 1)[0] + "..."
verbs/coverage.json+114−30
@@ -1,5 +1,5 @@ {- "standard": "0.4.0",+ "standard": "0.4.1",  "reference": {   "bridge": "altium",   "version": "0.2.76"@@ -7,7 +7,7 @@  "proposed": 54,  "compared": {   "kicad": "1.0.63",-  "fusion360": "1.12.1"+  "fusion360": "1.12.2"  },  "tiers": {   "core": "Read and edit the design. Every bridge provides these: they are how an AI sees and changes a board.",@@ -60,7 +60,10 @@    "name": "align_parts",    "tier": "core",    "source": "proposed",-   "altium": null,+   "altium": {+    "verb": "altium_align_parts",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_align_parts",     "match": "exact"@@ -229,7 +232,10 @@    "name": "copy_routing",    "tier": "core",    "source": "proposed",-   "altium": null,+   "altium": {+    "verb": "altium_copy_routing",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_copy_routing",     "match": "exact"@@ -290,7 +296,10 @@    "name": "edit_parts",    "tier": "core",    "source": "proposed",-   "altium": null,+   "altium": {+    "verb": "altium_edit_parts",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_edit_parts",     "match": "exact"@@ -676,7 +685,10 @@    "name": "remove_graphics",    "tier": "core",    "source": "proposed",-   "altium": null,+   "altium": {+    "verb": "altium_remove_graphics",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_remove_graphics",     "match": "exact"@@ -704,7 +716,10 @@    "name": "remove_parts",    "tier": "core",    "source": "proposed",-   "altium": null,+   "altium": {+    "verb": "altium_remove_parts",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_remove_parts",     "match": "exact"@@ -824,7 +839,10 @@     "verb": "kicad_sch_bus",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_bus",+    "match": "exact"+   }   },   {    "name": "sch_bus_entry",@@ -838,7 +856,10 @@     "verb": "kicad_sch_bus_entry",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_bus_entry",+    "match": "exact"+   }   },   {    "name": "sch_connect",@@ -866,7 +887,10 @@     "verb": "kicad_sch_connect_pins",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_connect_pins",+    "match": "exact"+   }   },   {    "name": "sch_connect_to_bus",@@ -880,7 +904,10 @@     "verb": "kicad_sch_connect_to_bus",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_connect_to_bus",+    "match": "exact"+   }   },   {    "name": "sch_create",@@ -894,7 +921,10 @@     "verb": "kicad_sch_create",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_create",+    "match": "exact"+   }   },   {    "name": "sch_delete_wire",@@ -908,7 +938,10 @@     "verb": "kicad_sch_delete_wire",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_delete_wire",+    "match": "exact"+   }   },   {    "name": "sch_edit",@@ -936,7 +969,10 @@     "verb": "kicad_sch_edit_label",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_edit_label",+    "match": "exact"+   }   },   {    "name": "sch_fix_connectivity",@@ -950,7 +986,10 @@     "verb": "kicad_sch_fix_connectivity",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_fix_connectivity",+    "match": "exact"+   }   },   {    "name": "sch_hierarchy",@@ -964,7 +1003,10 @@     "verb": "kicad_sch_hierarchy",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_hierarchy",+    "match": "exact"+   }   },   {    "name": "sch_items",@@ -978,7 +1020,10 @@     "verb": "kicad_sch_items",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_items",+    "match": "exact"+   }   },   {    "name": "sch_junction",@@ -992,7 +1037,10 @@     "verb": "kicad_sch_junction",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_junction",+    "match": "exact"+   }   },   {    "name": "sch_move_region",@@ -1006,7 +1054,10 @@     "verb": "kicad_sch_move_region",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_move_region",+    "match": "exact"+   }   },   {    "name": "sch_page",@@ -1020,7 +1071,10 @@     "verb": "kicad_sch_page",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_page",+    "match": "exact"+   }   },   {    "name": "sch_pins",@@ -1034,7 +1088,10 @@     "verb": "kicad_sch_pins",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_pins",+    "match": "exact"+   }   },   {    "name": "sch_place_part",@@ -1062,7 +1119,10 @@     "verb": "kicad_sch_reset_fields",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_reset_fields",+    "match": "exact"+   }   },   {    "name": "sch_sheet_pins",@@ -1076,7 +1136,10 @@     "verb": "kicad_sch_sheet_pins",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_sheet_pins",+    "match": "exact"+   }   },   {    "name": "sch_sheet_symbol",@@ -1104,7 +1167,10 @@     "verb": "kicad_sch_split_wire",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_split_wire",+    "match": "exact"+   }   },   {    "name": "sch_swap_part",@@ -1132,7 +1198,10 @@     "verb": "kicad_sch_text",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_text",+    "match": "exact"+   }   },   {    "name": "sch_trace_point",@@ -1146,7 +1215,10 @@     "verb": "kicad_sch_trace_point",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_trace_point",+    "match": "exact"+   }   },   {    "name": "schematic_data",@@ -1166,7 +1238,10 @@    "name": "set_layer_count",    "tier": "core",    "source": "proposed",-   "altium": null,+   "altium": {+    "verb": "altium_set_layer_count",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_set_layer_count",     "match": "exact"@@ -1766,7 +1841,10 @@     "verb": "kicad_render_schematic",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_render_schematic",+    "match": "exact"+   }   },   {    "name": "replicate_layout",@@ -1859,7 +1937,10 @@     "verb": "kicad_sch_update_from_library",     "match": "exact"    },-   "fusion360": null+   "fusion360": {+    "verb": "fusion_sch_update_from_library",+    "match": "exact"+   }   },   {    "name": "set_design_rules",@@ -2040,7 +2121,10 @@    "name": "check_clearance",    "tier": "checks",    "source": "proposed",-   "altium": null,+   "altium": {+    "verb": "altium_check_clearance",+    "match": "exact"+   },    "kicad": {     "verb": "kicad_check_clearance",     "match": "exact"
verbs/standard.json+2−2
@@ -1,5 +1,5 @@ {- "standard": "0.4.0",+ "standard": "0.4.1",  "reference": {   "bridge": "altium",   "version": "0.2.76"@@ -7,7 +7,7 @@  "proposed": 54,  "compared": {   "kicad": "1.0.63",-  "fusion360": "1.12.1"+  "fusion360": "1.12.2"  },  "tiers": {   "core": "Read and edit the design. Every bridge provides these: they are how an AI sees and changes a board.",