SOLIDWORKS Bridge
Public Made by Adomby adom
Launch, model and quit SOLIDWORKS from any Adom container. Nothing is ever lost.
The CSWA benchmark (0.11.0; community parts, Step 4 and the live gate 0.11.4)
"Pull 3-5 random parts from CSWA exams as part of our e2e testing/validation for each release. We can also use those as benchmarks for new feature developments." — Drew, 2026-10-15
Each spec in resources/cswa/ is ONE exam-style part: the
published answer key, the material, and the swx_run_script that builds it. The specs
ship in the release zip (resources/cswa/) and are embedded in the exe.
Running it
| Where | Command | What it compares |
|---|---|---|
| Live, from a dev container | python3 tools/cswa-check.py [--target adom_drew2] [--only <id>] [--fresh] [--keep] |
mass, and volume / surface area / centre of mass when the key has them; writes cswa-report.json |
| On the desktop, through the bridge | swx_selftest {"level":"cswa"} (only:[ids]) |
the same, with the same presence and memory rules as level:"write"; summary "N of M CSWA parts within tolerance" |
| In the simulator | cargo test --test cswa |
mass and volume, and the centre of mass where the column model made it (never the surface area); a part only SOLIDWORKS can build (simulatorSkips) is skipped there, saying why |
| Re-deriving the keys | python3 tools/cswa-check.py --derivations |
every derived key against its spec's derivation (no bridge call) |
cswa-check.py follows tools/dsl-live-check.py's rules:
- every creation says
purpose:"bridge"; - by default every part is built in ONE bridge-made part (
reuseDocument, whose leadingnew_partbecomesclear_part);--freshgives each spec its own part; - it STOPS on a
user_present,low_commit_memoryor dialog refusal, and never creates another part after one.
The release gate
tools/release.sh --canary # release candidate <ver>-rc<N> + manifests/canary.json
adom-bridge --target adom_drew2 bridge_install '{"manifestUrl":"https://wiki.adom.inc/api/v1/pages/solidworks-bridge/files/manifests/canary.json"}'
python3 tools/cswa-check.py --target adom_drew2 --report auto # live, on THAT build; names its report
tools/release.sh --require-live tools/cswa/reports/<that report> --publish # promotes the candidate's exact zip
cswa-check records WHICH BUILD it ran in bridge (read-only, through ab): exeSha256, the
installed exe read back with read_file and hashed; installedFrom and zipSha256, the manifest
ab installed from and the zip it named; installPath, version. The publish ships the canary's zip
without rebuilding it, and only when bridge.exeSha256 is the exe inside it.
Since 0.11.4 EVERY publish goes through it: --publish alone is refused before anything is built.
--require-live refuses to go on unless the report (tools/check-live-report.py):
- comes from
cswa-check; - was made by THIS bridge version;
- ran EVERY spec shipped in
resources/cswa/(0.11.4: a part may be skipped only for an op the bridge lacks; a run narrowed with--onlyis refused) and passed every part it ran; - did not stop;
- is newer than the last commit that touched
src/,resources/orCargo.toml; - ran the exe being published (
bridge.exeSha256), from the canary's zip if it says (bridge.zipSha256).
The one exception is --docs-only --publish, for a release that changes no code
(tools/check-docs-only.py: nothing in src/ or resources/, and nothing in Cargo.toml or
Cargo.lock beyond the package's version, since the last publish). Its changelog says the live gate
was skipped. The ritual is in the main README, under "Live validation". Commit each live report in
reports/ beside the earlier ones.
Spec schema
{
"id": "cswa-05-…", // also the file name
"title": "…",
"source": "the URL of the drawing and the key",
"official": true, // Dassault's own sample exam; false = community
"units": "MMGS", // the DSL is millimetres; convert IPS parts first
"material": {"name": "AISI 1020", "densityKgM3": 7900},
"expected": {
"massG": 939.54, // REQUIRED: the published answer
"volumeMm3": null, // optional
"centerOfMassMm": [x, y, z], // optional, in the part's own frame
"surfaceAreaMm2": null, // optional
"tolerancePct": 1.0 // CSWA accepts about 1 %
},
"keyBasis": "where the numbers came from, when it is not simply the published key",
"derivation": [["V", "120*80*12 - ..."], ["volumeMm3", "V"], ["massG", "V*2.7e-3"]], // a DERIVED key, re-derivable (0.11.4)
"exercises": ["revolve.360", "cut.regions"], // the op variants it builds (a test holds the simulator to it)
"simulatorSkips": "why only SOLIDWORKS can build it", // optional: skipped in the simulator, run live
"prediction": {"massG": 434.715, "how": "..."}, // optional: what the rebuild should weigh, when it is not the key
"needsOps": [], // ops the bridge lacks: the part is SKIPPED, never half-built
"variables": {"A": 81}, "derived": [["xR", "A-14"]], // optional, see below
"extends": "<another spec's id>", // optional, see below
"script": [ … swx_run_script steps … ]
}
Rules:
- The key is the PUBLISHED number, never one the bridge computed. A spec whose key was
derived (spec 0's mass is Michael's measured volume times the density of ABS) says so
in
keyBasis. - A COMMUNITY part's key is derived analytically, and the derivation ships with it
(0.11.4).
derivationis a list of[name, Python expression]pairs, evaluated in order with math's functions and the spec's variables in scope. It must yieldmassG, plusvolumeMm3andcenterOfMassMmwhere the key has them, each within 1e-6 of the key:python3 tools/cswa-check.py --derivationschecks every one, and so doescargo test. Such a key is exact, so the spec holds SOLIDWORKS to 0.1 %, not 1 %. Each spec states that 0.1 % tells its readings apart. - A
derivedAppendname may not shadow one the base derives. If it did, every"=name"in the base's script would silently take the new value: Step 4'stpxonce redrew Step 1's R5 fillet. Both expanders refuse it. - A runnable spec must parse —
cargo testparses every one (src/cswa.rs). - A spec that needs a missing op lists it in
needsOps. That is the backlog: when the op lands, the spec runs.
Variables, derived values and extends
An exam often reuses one drawing with new values (the Tool Block's steps). A spec may give
variables (numbers), derived ([name, expression] pairs, evaluated in order) and write any
number of its script or key as "=expression". extends: "<id>" takes another spec whole and
overrides its variables; scriptAppend / derivedAppend add steps and values after the base's.
Expressions: + - * / ^, parentheses, pi, sqrt sin cos tan asin acos atan atan2 abs min max rad deg. This is the BENCHMARK's grammar, in src/cswa.rs and tools/cswa-check.py (a test holds
the two to the same numbers); the bridge itself is only ever sent numbers.
The parts
| Spec | Source | Key | Ops it exercises |
|---|---|---|---|
cswa-00-lego-2x4 |
issue #1 (spec 0) | 2073.3615 mm³ (Michael's 2021 measurement; ours on 2026 identical), ABS | rectangles, multi-profile sketch, offset plane, cut reversed |
cswa-01-3dengr-q5-block |
3dengr, community | 324.00 g, CoM (50, 10, 30) | rectangle, extrude, density |
cswa-02-3dengr-q6-hole |
3dengr, community | 307.04 g, CoM (51.38, 10.00, 30.00) | hole through all, a centre of mass |
cswa-03-3dengr-q8-hole30 |
3dengr, community | 285.83 g | hole |
cswa-04-3dengr-q9-l-bracket |
3dengr, community | 410.80 g, CoM (26.54, 16.54, 20.00) | ONE polyline profile, AISI 1020 |
cswa-05-tool-block-step1 |
official sample exam, Q3 | 939.54 g | line, tangentArc (R19), polyline, arc3 (R29, R5), sketchChamfer, a hole in the profile; variables A B C |
cswa-06-tool-block-step2 |
official, Q4 | 1032.32 g | the same script, extends with A 84, B 59, C 45 |
cswa-07-tool-block-step3 |
official, Q5 | 628.18 g | a plane offset 12 inside the BACK face, the R41 slot, two face cuts, an Ø11 hole |
cswa-08-tool-block-step4 |
official, Q6 | 432.58 g (predicted 434.72, +0.49 %) | offsetEntities of the front face's outer loop (−1 mm), sketch regions (regionsAtMm) with the R42 / R41 circles, two offsetFromSurface cuts (12 from the back face; 1 short of the slot's front wall). LIVE ONLY (simulatorSkips) |
cswa-08b-tool-block-step4-explicit |
official, Q6 | 432.58 g (predicted 434.72) | the same pocket DRAWN: the inset outline's lines, its R20 arc and the R42 / R41 arcs, every intersection derived in the spec; blind cuts 32 and 7 (the fallback if Offset Entities misbehaves live) |
cswa-09-community-stepped-shaft |
community, derived | 103.5689 g, CoM (46.8315, −0.1142, 0) | revolve 360, revolve_cut 360 (a groove) and 180° mid-plane (a half-depth flat), the sketch's x axis as a construction line |
cswa-10-community-mirrored-block |
community, derived | 722.9129 g, CoM (−0.0824, 16.0273, 0) | mirror features about Front Plane, bodies about Right Plane, a boss about an offset plane |
cswa-11-community-slotted-plate |
community, derived | 276.3593 g, CoM (1.3753, 5.9074, 0.0358) | two slots through all, a hexagon polygon pocket, a counterbored and a countersunk hole |
cswa-12-community-up-to-plates |
community, derived | 369.6875 g, CoM (40.5252, 24.7232, 45.8697) | upToNext, upToSurface and offsetFromSurface bosses, a cut up to a face, a drafted boss and a drafted pocket |
The recipes, ambiguities and the reviewer's numeric rebuilds are in SOURCES.md
(tb2.py, tb3b.py, tb4c.py beside it). In the simulator every runnable part lands within
0.01 % of its key, or of its prediction (cargo test --test cswa, CSWA_PRINT=1 prints the table).
Step 4's reading. SOURCES.md Part 4, read literally, gives 434.72 g (+0.49 %). The front face's outer loop is offset 1 mm in. A 1-mm wall stays outside the slot's R41 silhouette (R42). The pocket outside that wall goes to 12 from the back face. The ear inside R41 is recessed to 1 mm short of the slot's front wall, leaving a 1-mm skin. The reviewer's best case, 432.86 g, cuts the ear through to the slot instead, and keeps a 1-mm ring round the Ø11. The drawing cannot tell the two apart (ambiguity 4), and both are within the exam's 1 %.
Roadmap: placeholders (drawings only, not transcribed)
These are one line each: the source and its published key. The geometry stays in the source; no exam or book content is copied here.
- 2007 sample exam, Q1: https://cdn.goengineer.com/cswasampleexam2007.pdf (key 1280 g).
- 2007 sample exam, Q6: https://cdn.goengineer.com/cswasampleexam2007.pdf (key 2040.57 g).
- Planchard, Official CSWA Examination Guide, 3-3: https://static.sdcpublications.com/pdfsample/978-1-58503-656-1-3.pdf (key 302.40 g, CoM (0, 19.20, 0)).
- Official chain-link assembly, 2017 sample exam: https://www.solidworks.com/sites/default/files/2017-12/CSWASampleExam.pdf (key CoM (348.66, −88.48, −91.40) at A 25° B 125° C 130°; it needs assemblies with mates, which the DSL lacks).
Spec 0
cswa-00-lego-2x4: the LEGO 2x4 acceptance brick from issue #1. It is not an exam part. Its
volume, 2073.3615208 mm³, is the one SOLIDWORKS 2021 measured for Michael's brick; the
mass is that volume in ABS (1020 kg/m³).
# The CSWA benchmark (0.11.0; community parts, Step 4 and the live gate 0.11.4)
> "Pull 3-5 random parts from CSWA exams as part of our e2e testing/validation for
> each release. We can also use those as benchmarks for new feature developments."
> — Drew, 2026-10-15
Each spec in [`resources/cswa/`](../../resources/cswa/) is ONE exam-style part: the
published answer key, the material, and the `swx_run_script` that builds it. The specs
ship in the release zip (`resources/cswa/`) and are embedded in the exe.
## Running it
| Where | Command | What it compares |
|---|---|---|
| Live, from a dev container | `python3 tools/cswa-check.py [--target adom_drew2] [--only <id>] [--fresh] [--keep]` | mass, and volume / surface area / centre of mass when the key has them; writes `cswa-report.json` |
| On the desktop, through the bridge | `swx_selftest {"level":"cswa"}` (`only:[ids]`) | the same, with the same presence and memory rules as `level:"write"`; summary `"N of M CSWA parts within tolerance"` |
| In the simulator | `cargo test --test cswa` | mass and volume, and the centre of mass where the column model made it (never the surface area); a part only SOLIDWORKS can build (`simulatorSkips`) is skipped there, saying why |
| Re-deriving the keys | `python3 tools/cswa-check.py --derivations` | every derived key against its spec's `derivation` (no bridge call) |
`cswa-check.py` follows `tools/dsl-live-check.py`'s rules:
- every creation says `purpose:"bridge"`;
- by default every part is built in ONE bridge-made part (`reuseDocument`, whose leading
`new_part` becomes `clear_part`); `--fresh` gives each spec its own part;
- it STOPS on a `user_present`, `low_commit_memory` or dialog refusal, and never creates
another part after one.
## The release gate
```bash
tools/release.sh --canary # release candidate <ver>-rc<N> + manifests/canary.json
adom-bridge --target adom_drew2 bridge_install '{"manifestUrl":"https://wiki.adom.inc/api/v1/pages/solidworks-bridge/files/manifests/canary.json"}'
python3 tools/cswa-check.py --target adom_drew2 --report auto # live, on THAT build; names its report
tools/release.sh --require-live tools/cswa/reports/<that report> --publish # promotes the candidate's exact zip
```
`cswa-check` records WHICH BUILD it ran in `bridge` (read-only, through ab): `exeSha256`, the
installed exe read back with `read_file` and hashed; `installedFrom` and `zipSha256`, the manifest
ab installed from and the zip it named; `installPath`, `version`. The publish ships the canary's zip
without rebuilding it, and only when `bridge.exeSha256` is the exe inside it.
Since 0.11.4 EVERY publish goes through it: `--publish` alone is refused before anything is built.
`--require-live` refuses to go on unless the report (`tools/check-live-report.py`):
- comes from `cswa-check`;
- was made by THIS bridge version;
- ran EVERY spec shipped in `resources/cswa/` (0.11.4: a part may be skipped only for an op the
bridge lacks; a run narrowed with `--only` is refused) and passed every part it ran;
- did not stop;
- is newer than the last commit that touched `src/`, `resources/` or `Cargo.toml`;
- ran the exe being published (`bridge.exeSha256`), from the canary's zip if it says
(`bridge.zipSha256`).
The one exception is `--docs-only --publish`, for a release that changes no code
(`tools/check-docs-only.py`: nothing in `src/` or `resources/`, and nothing in Cargo.toml or
Cargo.lock beyond the package's version, since the last publish). Its changelog says the live gate
was skipped. The ritual is in the main README, under "Live validation". Commit each live report in
`reports/` beside the earlier ones.
## Spec schema
```json
{
"id": "cswa-05-…", // also the file name
"title": "…",
"source": "the URL of the drawing and the key",
"official": true, // Dassault's own sample exam; false = community
"units": "MMGS", // the DSL is millimetres; convert IPS parts first
"material": {"name": "AISI 1020", "densityKgM3": 7900},
"expected": {
"massG": 939.54, // REQUIRED: the published answer
"volumeMm3": null, // optional
"centerOfMassMm": [x, y, z], // optional, in the part's own frame
"surfaceAreaMm2": null, // optional
"tolerancePct": 1.0 // CSWA accepts about 1 %
},
"keyBasis": "where the numbers came from, when it is not simply the published key",
"derivation": [["V", "120*80*12 - ..."], ["volumeMm3", "V"], ["massG", "V*2.7e-3"]], // a DERIVED key, re-derivable (0.11.4)
"exercises": ["revolve.360", "cut.regions"], // the op variants it builds (a test holds the simulator to it)
"simulatorSkips": "why only SOLIDWORKS can build it", // optional: skipped in the simulator, run live
"prediction": {"massG": 434.715, "how": "..."}, // optional: what the rebuild should weigh, when it is not the key
"needsOps": [], // ops the bridge lacks: the part is SKIPPED, never half-built
"variables": {"A": 81}, "derived": [["xR", "A-14"]], // optional, see below
"extends": "<another spec's id>", // optional, see below
"script": [ … swx_run_script steps … ]
}
```
Rules:
- **The key is the PUBLISHED number,** never one the bridge computed. A spec whose key was
derived (spec 0's mass is Michael's measured volume times the density of ABS) says so
in `keyBasis`.
- **A COMMUNITY part's key is derived analytically, and the derivation ships with it**
(0.11.4). `derivation` is a list of `[name, Python expression]` pairs, evaluated in order with
math's functions and the spec's variables in scope. It must yield `massG`, plus `volumeMm3` and
`centerOfMassMm` where the key has them, each within 1e-6 of the key:
`python3 tools/cswa-check.py --derivations` checks every one, and so does `cargo test`.
Such a key is exact, so the spec holds SOLIDWORKS to 0.1 %, not 1 %. Each spec states that
0.1 % tells its readings apart.
- **A `derivedAppend` name may not shadow one the base derives.** If it did, every `"=name"`
in the base's script would silently take the new value: Step 4's `tpx` once redrew Step 1's
R5 fillet. Both expanders refuse it.
- **A runnable spec must parse** — `cargo test` parses every one (`src/cswa.rs`).
- **A spec that needs a missing op** lists it in `needsOps`. That is the backlog: when the
op lands, the spec runs.
## Variables, derived values and `extends`
An exam often reuses one drawing with new values (the Tool Block's steps). A spec may give
`variables` (numbers), `derived` (`[name, expression]` pairs, evaluated in order) and write any
number of its script or key as `"=expression"`. `extends: "<id>"` takes another spec whole and
overrides its `variables`; `scriptAppend` / `derivedAppend` add steps and values after the base's.
Expressions: `+ - * / ^`, parentheses, `pi`, `sqrt sin cos tan asin acos atan atan2 abs min max
rad deg`. This is the BENCHMARK's grammar, in `src/cswa.rs` and `tools/cswa-check.py` (a test holds
the two to the same numbers); the bridge itself is only ever sent numbers.
## The parts
| Spec | Source | Key | Ops it exercises |
|---|---|---|---|
| `cswa-00-lego-2x4` | issue #1 (spec 0) | 2073.3615 mm³ (Michael's 2021 measurement; ours on 2026 identical), ABS | rectangles, multi-profile sketch, offset plane, cut reversed |
| `cswa-01-3dengr-q5-block` | 3dengr, community | 324.00 g, CoM (50, 10, 30) | rectangle, extrude, density |
| `cswa-02-3dengr-q6-hole` | 3dengr, community | 307.04 g, CoM (51.38, 10.00, 30.00) | `hole` through all, a centre of mass |
| `cswa-03-3dengr-q8-hole30` | 3dengr, community | 285.83 g | `hole` |
| `cswa-04-3dengr-q9-l-bracket` | 3dengr, community | 410.80 g, CoM (26.54, 16.54, 20.00) | ONE `polyline` profile, AISI 1020 |
| `cswa-05-tool-block-step1` | official sample exam, Q3 | 939.54 g | `line`, `tangentArc` (R19), `polyline`, `arc3` (R29, R5), `sketchChamfer`, a hole in the profile; variables A B C |
| `cswa-06-tool-block-step2` | official, Q4 | 1032.32 g | the same script, `extends` with A 84, B 59, C 45 |
| `cswa-07-tool-block-step3` | official, Q5 | 628.18 g | a plane offset 12 inside the BACK face, the R41 slot, two face cuts, an Ø11 `hole` |
| `cswa-08-tool-block-step4` | official, Q6 | 432.58 g (predicted 434.72, +0.49 %) | `offsetEntities` of the front face's outer loop (−1 mm), sketch regions (`regionsAtMm`) with the R42 / R41 circles, two `offsetFromSurface` cuts (12 from the back face; 1 short of the slot's front wall). LIVE ONLY (`simulatorSkips`) |
| `cswa-08b-tool-block-step4-explicit` | official, Q6 | 432.58 g (predicted 434.72) | the same pocket DRAWN: the inset outline's lines, its R20 arc and the R42 / R41 arcs, every intersection derived in the spec; blind cuts 32 and 7 (the fallback if Offset Entities misbehaves live) |
| `cswa-09-community-stepped-shaft` | community, derived | 103.5689 g, CoM (46.8315, −0.1142, 0) | `revolve` 360, `revolve_cut` 360 (a groove) and 180° mid-plane (a half-depth flat), the sketch's x axis as a construction line |
| `cswa-10-community-mirrored-block` | community, derived | 722.9129 g, CoM (−0.0824, 16.0273, 0) | `mirror` features about Front Plane, bodies about Right Plane, a boss about an offset plane |
| `cswa-11-community-slotted-plate` | community, derived | 276.3593 g, CoM (1.3753, 5.9074, 0.0358) | two `slot`s through all, a hexagon `polygon` pocket, a counterbored and a countersunk `hole` |
| `cswa-12-community-up-to-plates` | community, derived | 369.6875 g, CoM (40.5252, 24.7232, 45.8697) | `upToNext`, `upToSurface` and `offsetFromSurface` bosses, a cut up to a face, a drafted boss and a drafted pocket |
The recipes, ambiguities and the reviewer's numeric rebuilds are in [`SOURCES.md`](SOURCES.md)
(`tb2.py`, `tb3b.py`, `tb4c.py` beside it). In the simulator every runnable part lands within
0.01 % of its key, or of its prediction (`cargo test --test cswa`, `CSWA_PRINT=1` prints the table).
**Step 4's reading.** SOURCES.md Part 4, read literally, gives 434.72 g (+0.49 %). The front face's
outer loop is offset 1 mm in. A 1-mm wall stays outside the slot's R41 silhouette (R42). The pocket
outside that wall goes to 12 from the back face. The ear inside R41 is recessed to 1 mm short of the
slot's front wall, leaving a 1-mm skin. The reviewer's best case, 432.86 g, cuts the ear through to
the slot instead, and keeps a 1-mm ring round the Ø11. The drawing cannot tell the two apart
(ambiguity 4), and both are within the exam's 1 %.
## Roadmap: placeholders (drawings only, not transcribed)
These are one line each: the source and its published key. The geometry stays in the source; no
exam or book content is copied here.
- 2007 sample exam, Q1: https://cdn.goengineer.com/cswasampleexam2007.pdf (key 1280 g).
- 2007 sample exam, Q6: https://cdn.goengineer.com/cswasampleexam2007.pdf (key 2040.57 g).
- Planchard, Official CSWA Examination Guide, 3-3: https://static.sdcpublications.com/pdfsample/978-1-58503-656-1-3.pdf (key 302.40 g, CoM (0, 19.20, 0)).
- Official chain-link assembly, 2017 sample exam: https://www.solidworks.com/sites/default/files/2017-12/CSWASampleExam.pdf (key CoM (348.66, −88.48, −91.40) at A 25° B 125° C 130°; it needs assemblies with mates, which the DSL lacks).
## Spec 0
`cswa-00-lego-2x4`: the LEGO 2x4 acceptance brick from issue #1. It is not an exam part. Its
volume, 2073.3615208 mm³, is the one SOLIDWORKS 2021 measured for Michael's brick; the
mass is that volume in ABS (1020 kg/m³).