← Commit history
BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.11.2+0.11.3
Cargo.lock+1−1
@@ -122,7 +122,7 @@ dependencies = [  [[package]] name = "swx-bridge"-version = "0.11.2"+version = "0.11.3" dependencies = [  "miniz_oxide",  "serde",
Cargo.toml+1−1
@@ -1,6 +1,6 @@ [package] name = "swx-bridge"-version = "0.11.2"+version = "0.11.3" edition = "2021" rust-version = "1.80" description = "Adom SOLIDWORKS bridge — swx_* verbs over the SOLIDWORKS COM API, as a single native binary"
README.md+35−1
@@ -506,7 +506,41 @@ not.  ## Roadmap -- v0.11.2 (this): **the File ▸ Open was the launch's own.** The laptop's+- v0.11.3 (this): **a quick restart is not ready; a reply is not an effect.**+  Two live findings.++  The good one: the HideFileExt fix is PROVEN on Drew's laptop with extensions+  hidden. Every verb passed by the title, by the stem and by stem + `.SLDPRT`+  (`titles.hiddenExtensions`).++  The bad one, from the ledger: a quit then an immediate start was called+  `ready` 4 s after attach. A `swx_new_document` 11 s after attach returned OK.+  SOLIDWORKS (pid 26316) died a second later.++  Now:+  - **A marker counts only if it is beyond the launch.** The performance log's+    state is recorded when no SOLIDWORKS is writing it (launch, quit, or a first+    sight of a log still holding the last session). A marker counts only beyond+    that recorded length, unless the file has been rewritten since (shorter, or+    different bytes where it ended).+  - **A fresh attach** (the bridge's own launch, or a young process) is ready+    only with StartupProcessCompleted TRUE, this session's marker, and+    `SWX_READY_SETTLE_SECS` (20 s) since attach.+    - `readiness.evidence` lists each signal with its age, and `readiness.why`+      says what holds it.+    - The transition is ledgered as `solidworks_ready`.+    - The ready latch stays keyed to (pid, creation time).+  - **Verify by effect.** After `swx_new_document`, `swx_open` and+    `swx_import`, the live session is read again: the same process, still+    running, a non-zero document count, and the document in the list. A fresh+    session is read again after 1.5 s. Failure is `host_app_died` (with the pid,+    the ledger line and the crash markers) or `document_not_created`, never ok.+  - **A start within 60 s of a quit waits** (up to 30 s) for that session's+    sldworks.exe and per-session children to be gone, never the platform+    daemons. It is ledgered as `launch_waited_for_previous_exit`.++  691 tests.+- v0.11.2: **the File ▸ Open was the launch's own.** The laptop's   ledger had the sequence:   - the 3DEXPERIENCE helper sign-in took 2 min 13 s;   - the supervisor called that a stall, killed the chain and invoked the shortcut
SKILL.md+4−1
@@ -99,7 +99,10 @@ BEFORE you do it:    dialog is the user's to answer. A launch retry never re-invokes over a    running SOLIDWORKS, and the 3DEXPERIENCE helper sign-in is never treated as a    stall (a second invoke at a starting SOLIDWORKS raised a File ▸ Open,-   measured 2026-10-15).+   measured 2026-10-15). After any (re)start, WAIT for `swx_status`+   `solidworks.ready` before a document verb — a fresh attach settles 20 s, and+   a document command sent sooner crashed SOLIDWORKS twice (2026-10-01,+   2026-10-15). A document verb that reports `host_app_died` created NOTHING. 9. **Never end a session the user is working in, and never pile windows on    them.** Every quit and sweep refuses `user_is_active` when SOLIDWORKS is in    front with recent input, or documents appeared that the bridge did not open;
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "solidworks",   "displayName": "SOLIDWORKS",-  "version": "0.11.2",+  "version": "0.11.3",   "description": "Bridge for SOLIDWORKS desktop CAD — create and open documents, a modeling DSL, file management (find/open/save/export/Pack and Go), custom properties, BOM generation, design analysis (mass properties, bodies, parameters, interference, rebuild health) and background window/dialog etiquette, over the SOLIDWORKS COM API. Single native binary: no interpreter, no PowerShell, ~10ms cold start.",   "author": "Adom Inc.",   "license": "MIT",
docs/LIVE-RESULTS.md+45
@@ -22,6 +22,51 @@ Built in 4 features, measured live: | Colour | [200, 0, 0] (set before the material, kept after it) | red requested | | Density / mass | 1020.0 kg/m^3 / 0.0021148 kg | ABS 1020 / 0.0021148 | +## HideFileExt, measured 2026-10-15 (bridge 0.11.2, SOLIDWORKS 2026)++On Drew's laptop, with Windows' "Hide extensions for known file types" turned+ON (HideFileExt=1, SOLIDWORKS restarted). This is Michael's 2021 condition,+reproduced on our machine to prove the 0.10.10 fix:++| Check | Result |+|---|---|+| `swx_new_document` title read back | `Part1-1792103965000`, with no extension. `swx_docs` lists it the same way |+| `swx_run_script` by path | ok, `bridgeCreatedDocument:true` |+| `swx_design_info`, `swx_get_parameters` | PASS by the reported title, by the stem, and by the stem + `.SLDPRT` |+| `swx_set_parameter`, `swx_export_step` (15,944 B), `swx_save`, `swx_close_doc` | PASS by the stem |+| Left open | nothing |++`compat::OP_FACTS` carries it as `titles.hiddenExtensions`.++### The restart that followed (the 0.11.3 finding)++The second phase restarted SOLIDWORKS with extensions shown. From the ledger:++| Time (Z) | Event |+|---|---|+| 22:40:01 | quit (processGone) |+| 22:40:02 | launch |+| 22:40:07 | `sldworksUp` |+| 22:40:39 | attached |+| 22:40:43 | `solidworks.ready` TRUE, 4 s after attach (the first phase's start took 22 s to ready) |+| 22:40:50 | `swx_new_document` OK, title `Part1-1792104049001.SLDPRT`, ledger `document_created` |+| 22:40:51 | `swx_docs`: `[]`; SOLIDWORKS pid 26316 had DIED |+| 22:40:58 | `swx_stop`: `host_app_not_running` |++This was the 2026-10-01 crash again: a document command sent while an add-in+was still initialising.++0.11.3 makes these changes:+- A performance-log marker counts only if it lies beyond the state the file was+  in when no SOLIDWORKS was writing it (launch, quit, or a first sight of a+  stale log), unless the file has been rewritten since.+- A fresh attach is ready only with StartupProcessCompleted TRUE, this session's+  own marker, and 20 s after attach.+- `swx_new_document`, `swx_open` and `swx_import` verify the effect on the live+  session: same process, still running, the document in the list. If the effect+  is missing they return `host_app_died` / `document_not_created`, never ok.+- A start within 60 s of a quit waits for that session's process tree to be gone.+ ## SOLIDWORKS 2021 (community)  Run 2026-10-15 by Michael (issue #1) with bridge **0.10.9** on **SOLIDWORKS 2021**
install.sh

  
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "solidworks-bridge",-  "version": "0.11.2",+  "version": "0.11.3",   "type": "app",   "description": "Skills for your container so your AI knows how to drive the SOLIDWORKS bridge (swx_* verbs). The bridge runtime itself is the release zip — a single native swx-bridge.exe; Adom Bridge loads that.",   "tags": [
src/comhost/mock.rs+29
@@ -1137,6 +1137,19 @@ impl Backend for MockBackend {                 let _ = std::fs::remove_file(&trigger);             }         }+        // SOLIDWORKS DIES SHORTLY AFTER A DOCUMENT COMMAND (0.11.3) — the+        // 2026-10-15 22:40 crash: `mock-dies-after-new-document` arms a countdown+        // of commands that still answer (default 1: the identity save); then the+        // process is gone, its documents with it.+        let countdown = crate::scratch::root().join("mock-death-countdown");+        if let Some(k) = std::fs::read_to_string(&countdown).ok().and_then(|t| t.trim().parse::<u64>().ok()) {+            if k == 0 {+                let _ = std::fs::remove_file(&countdown);+                self.finish_exit();+            } else {+                let _ = std::fs::write(&countdown, (k - 1).to_string());+            }+        }         let out = self.dispatch(cmd, args);         // The simulated APPLICATION's session outlives the com host, because a         // real one does. Written after every command so a respawn resumes from@@ -2676,6 +2689,22 @@ impl MockBackend {                 }                 let hidden = !doc.visible;                 self.docs.push(doc);+                if fault("mock-dies-after-new-document") {+                    let n = std::fs::read_to_string(crate::scratch::root().join("mock-dies-after-new-document"))+                        .ok()+                        .and_then(|t| t.trim().parse::<u64>().ok())+                        .unwrap_or(1);+                    let _ = std::fs::write(crate::scratch::root().join("mock-death-countdown"), n.to_string());+                    let _ = std::fs::remove_file(crate::scratch::root().join("mock-dies-after-new-document"));+                }+                // THE REPLY IS NOT THE EFFECT (0.11.3): `mock-newdoc-vanishes` —+                // the call reports a document that is not there.+                if fault("mock-newdoc-vanishes") {+                    let info = self.doc_info(&key);+                    self.docs.retain(|d| d.path != key);+                    self.active = None;+                    return Ok(json!({"created": info, "template": template, "type": kind}));+                }                 // A hidden document is not made the active one (UNMEASURED live;                 // modelled conservatively).                 if !hidden {
src/compat.rs+8
@@ -122,7 +122,14 @@ pub const LIVE_2026_10_14_C: Measurement = Measurement { year: 2026, major: 34, /// one bug (titles and HideFileExt, fixed in 0.10.10), in verbs, not ops. pub const LIVE_2021_10_15: Measurement = Measurement { year: 2021, major: 29, edition: "desktop", date: "2026-10-15", bridge: "0.10.9", by: "community" }; +/// 2026-10-15 22:38Z, bridge 0.11.2, SOLIDWORKS 2026, Drew's laptop with+/// Windows' "Hide extensions for known file types" ON (HideFileExt=1,+/// SOLIDWORKS restarted) — Michael's 2021 condition, reproduced: the 0.10.10+/// title fix, proven.+pub const LIVE_2026_10_15_HIDEEXT: Measurement = Measurement { year: 2026, major: 34, edition: "connected", date: "2026-10-15", bridge: "0.11.2", by: "adom" };+ const M2026_2021: &[Measurement] = &[LIVE_2026_10_14, LIVE_2021_10_15];+const M2026_HIDEEXT: &[Measurement] = &[LIVE_2026_10_15_HIDEEXT]; const M2026C_2021: &[Measurement] = &[LIVE_2026_10_14_C, LIVE_2021_10_15]; const M2026B: &[Measurement] = &[LIVE_2026_10_14_B]; const UNMEASURED: &[Measurement] = &[];@@ -226,6 +233,7 @@ pub const OP_FACTS: &[OpFact] = &[     OpFact { id: "hole.counterbore", what: "a counterbored hole (two cuts)", checks: "not run live (0.11.0)", measured: UNMEASURED },     OpFact { id: "hole.countersink", what: "a countersunk hole (a drafted cut, then the hole)", checks: "not run live (0.11.0)", measured: UNMEASURED },     OpFact { id: "set_material.density", what: "a density in kg/m³ (the document's own, or checked against the material's)", checks: "not run live (0.11.0)", measured: UNMEASURED },+    OpFact { id: "titles.hiddenExtensions", what: "documents addressed by title while Windows hides known extensions: swx_new_document reads back 'Part1-…' (no .SLDPRT); swx_design_info and swx_get_parameters by the reported title, the stem and stem+.SLDPRT; swx_set_parameter, swx_export_step, swx_save and swx_close_doc by the stem; nothing left open", checks: "the focused HideFileExt test, 2026-10-15 22:38-22:41Z", measured: M2026_HIDEEXT },     OpFact { id: "save_as", what: "save_as as a script step", checks: "not in the live battery (swx_save_as, the verb, is)", measured: UNMEASURED },     OpFact { id: "rebuild", what: "rebuild as a script step", checks: "not in the live battery", measured: UNMEASURED },     OpFact { id: "zoom_fit", what: "zoom_fit as a script step", checks: "not in the live battery", measured: UNMEASURED },
src/launch.rs+66
@@ -615,6 +615,66 @@ pub fn dialog_grace() -> Duration {     Duration::from_millis(secs_env("SWX_LAUNCH_DIALOG_GRACE_MS", 90_000)) } +/// A START RIGHT AFTER A QUIT (0.11.3). MEASURED 2026-10-15: a quit at+/// 22:40:01, a launch at 22:40:02 — and the new SOLIDWORKS died 11 s after+/// attach. A start within `SWX_START_AFTER_QUIT_SECS` (60) of a quit this bridge+/// made first waits, up to `SWX_START_AFTER_QUIT_WAIT_SECS` (30), for that+/// session's process tree to be gone: its sldworks.exe and the per-session+/// children (`quit::SESSION_CHILDREN`) — never the platform daemons, which+/// survive a quit by design.+pub fn previous_session_remaining(census: &[ProcInfo], prev_pid: u32, prev_created: Option<u64>, quit_at_secs: u64) -> Vec<ProcInfo> {+    census+        .iter()+        .filter(|p| {+            (p.is("SLDWORKS.exe") && p.pid == prev_pid && (prev_created.is_none() || p.created_at.is_none() || p.created_at == prev_created))+                || (crate::quit::SESSION_CHILDREN.iter().any(|c| p.is(c))+                    && (p.ppid == Some(prev_pid) || p.created_at.map(|c| c <= quit_at_secs).unwrap_or(true)))+        })+        .cloned()+        .collect()+}++/// Wait (bounded) for the last quit's process tree to be gone, ledgered.+/// `None` when no quit was recent.+pub fn wait_for_previous_exit(os: &dyn LaunchOs) -> Option<Value> {+    let q: Value = std::fs::read_to_string(crate::scratch::root().join("last-quit.json")).ok().and_then(|t| serde_json::from_str(&t).ok())?;+    let at_ms = q.get("atMs").and_then(|v| v.as_u64())?;+    let pid = q.get("pid").and_then(|v| v.as_u64())? as u32;+    let created = q.get("createdAt").and_then(|v| v.as_u64());+    let now_ms = crate::launchos::epoch_ms() as u64;+    if now_ms.saturating_sub(at_ms) > secs_env("SWX_START_AFTER_QUIT_SECS", 60) * 1000 {+        return None;+    }+    let started = std::time::Instant::now();+    let deadline = started + Duration::from_secs(secs_env("SWX_START_AFTER_QUIT_WAIT_SECS", 30));+    let mut remaining: Vec<ProcInfo>;+    let mut readable = true;+    loop {+        match os.processes() {+            Ok(c) => remaining = previous_session_remaining(&c, pid, created, at_ms / 1000),+            Err(_) => {+                readable = false;+                remaining = Vec::new();+            }+        }+        if remaining.is_empty() || std::time::Instant::now() >= deadline || !readable {+            break;+        }+        std::thread::sleep(Duration::from_millis(250));+    }+    let gone = readable && remaining.is_empty();+    let v = json!({+        "previous": {"pid": pid, "createdAt": created},+        "quitSecondsAgo": now_ms.saturating_sub(at_ms) / 1000,+        "waitedMs": started.elapsed().as_millis() as u64,+        "gone": gone,+        "censusReadable": readable,+        "remaining": remaining.iter().map(|p| json!({"pid": p.pid, "image": p.image})).collect::<Vec<_>>(),+    });+    crate::ledger::record("launch_waited_for_previous_exit", v.clone());+    Some(v)+}+ /// A SOLIDWORKS that this launch did not find running before it began: any /// sldworks.exe outside the FIRST route's baseline. While one exists, no route /// is invoked again — a second invoke reaches it as an "open" request.@@ -1629,6 +1689,12 @@ fn run_supervisor(channel: Channel, os: Box<dyn LaunchOs>) {     // WHAT RAN BEFORE THIS LAUNCH BEGAN — the FIRST route's baseline. Any     // sldworks.exe outside it is this launch's, whichever route started it.     let first_baseline: Vec<u32> = os.processes().map(|c| c.iter().map(|p| p.pid).collect()).unwrap_or_default();+    // THE PERFORMANCE LOG AS NO SOLIDWORKS IS WRITING IT (0.11.3): a marker the+    // session this launch starts writes must lie beyond this (or the file be+    // rewritten) — see perflog::Baseline.+    if os.processes().map(|c| !c.iter().any(|p| p.is("SLDWORKS.exe"))).unwrap_or(false) {+        crate::perflog::record_baseline("launch", None);+    }     for (index, route) in plan.iter().enumerate() {         // NEVER RE-INVOKE OVER A RUNNING SOLIDWORKS (0.11.2). Before a retry,         // watch a moment for a SOLIDWORKS the stalled route started anyway; if
src/launchos.rs+11−1
@@ -960,7 +960,17 @@ impl LaunchOs for FakeOs {                     continue;                 }                 let image = r.get("image").and_then(|i| i.as_str()).unwrap_or("").to_string();-                if reaped(&image) {+                // `reapedAfterQuitMs` (0.11.3): a per-session child that outlives+                // the quit by this long — what a start right after a quit must+                // wait out.+                let lingers = r.get("reapedAfterQuitMs").and_then(|x| x.as_u64()).map(|n| {+                    let first_quit = std::fs::read_to_string(self.dir.join("quit.jsonl")).unwrap_or_default().lines().filter_map(|l| {+                        let v: Value = serde_json::from_str(l).ok()?;+                        v.get("effectiveAtMs").or_else(|| v.get("atMs")).and_then(|x| x.as_u64())+                    }).min();+                    first_quit.map(|q| (epoch_ms() as u64) < q + n).unwrap_or(true)+                });+                if reaped(&image) && lingers != Some(true) {                     continue;                 }                 out.push(ProcInfo {
src/perflog.rs+161−11
@@ -56,6 +56,12 @@ pub fn path() -> Option<PathBuf> { }  fn tail() -> Option<String> {+    tail_bytes().map(|(b, _)| String::from_utf8_lossy(&b).to_string())+}++/// The tail as BYTES, with the file offset it starts at — positions compare+/// exactly only before a lossy UTF-8 conversion.+fn tail_bytes() -> Option<(Vec<u8>, u64)> {     use std::io::{Read, Seek, SeekFrom};     let mut f = std::fs::File::open(path()?).ok()?;     let len = f.metadata().ok()?.len();@@ -63,7 +69,98 @@ fn tail() -> Option<String> {     f.seek(SeekFrom::Start(start)).ok()?;     let mut buf = Vec::new();     f.read_to_end(&mut buf).ok()?;-    Some(String::from_utf8_lossy(&buf).to_string())+    Some((buf, start))+}++/// `n` bytes of the log ending at `end` (or fewer at the start of the file).+fn bytes_before(path: &std::path::Path, end: u64, n: u64) -> Option<Vec<u8>> {+    use std::io::{Read, Seek, SeekFrom};+    let mut f = std::fs::File::open(path).ok()?;+    let from = end.saturating_sub(n);+    f.seek(SeekFrom::Start(from)).ok()?;+    let mut buf = vec![0u8; (end - from) as usize];+    f.read_exact(&mut buf).ok()?;+    Some(buf)+}++// ── THE LAUNCH BASELINE (0.11.3) ────────────────────────────────────────────+// MEASURED 2026-10-15 22:40 (hosted 0.11.2): a quit at 22:40:01, a launch at+// 22:40:02, COM attached at 22:40:39 — and `ready` at 22:40:43. A document+// command at 22:40:50 "succeeded", and SOLIDWORKS died a second later: the+// 2026-10-01 crash, an add-in still initialising. The log is tied to a session+// by its modification time, which says nothing about WHICH lines are the new+// session's: a marker the PREVIOUS session wrote, still in the file when the new+// one touched it, read as this start completing. So the file's state is+// recorded when no SOLIDWORKS can be writing it — when a launch begins, when a+// quit has verifiably finished — and a marker counts for a session that started+// after that only if it lies BEYOND the recorded length, unless the file has+// been REWRITTEN since (shorter now, or different bytes where the recorded file+// ended).++/// The log's state at a moment no SOLIDWORKS session was writing it.+#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]+pub struct Baseline {+    /// The file's length then.+    pub len: u64,+    /// sha256 of the (up to) 256 bytes that ended the file then: still there+    /// unchanged means the file was APPENDED to; different, it was rewritten.+    pub end_fp: String,+    /// When it was taken (epoch seconds).+    pub at_secs: u64,+    /// Why (launch / quit / first sight of a session whose log was still the+    /// previous session's).+    pub why: String,+}++const END_FP_BYTES: u64 = 256;++/// The log's state now, if there is a log.+pub fn snapshot(why: &str) -> Option<Baseline> {+    let p = path()?;+    let len = std::fs::metadata(&p).ok()?.len();+    let end_fp = crate::sha256::hex_of(&bytes_before(&p, len, END_FP_BYTES)?);+    Some(Baseline { len, end_fp, at_secs: crate::launchos::epoch_secs(), why: why.to_string() })+}++fn baselines_path() -> PathBuf {+    crate::scratch::root().join("perflog-baselines.json")+}++pub fn baselines() -> Vec<Baseline> {+    std::fs::read_to_string(baselines_path()).ok().and_then(|t| serde_json::from_str(&t).ok()).unwrap_or_default()+}++/// Record the log's state now (keeps the last 8). `at_override`: the moment the+/// record speaks for (a session's creation time, for a first-sight record).+pub fn record_baseline(why: &str, at_override: Option<u64>) -> Option<Baseline> {+    let mut b = snapshot(why)?;+    if let Some(a) = at_override {+        b.at_secs = a;+    }+    let mut all = baselines();+    all.push(b.clone());+    let keep = all.len().saturating_sub(8);+    let all: Vec<Baseline> = all.into_iter().skip(keep).collect();+    let _ = std::fs::write(baselines_path(), serde_json::to_string(&all).unwrap_or_else(|_| "[]".into()));+    Some(b)+}++/// The latest record taken at or before a session started: everything the file+/// held then was written by earlier sessions.+pub fn baseline_for(session_start: u64) -> Option<Baseline> {+    baselines().into_iter().filter(|b| b.at_secs <= session_start).max_by_key(|b| b.at_secs)+}++/// Has the file been rewritten since `b` (shorter, or different bytes where it+/// ended)? `None` = could not tell.+pub fn rewritten_since(b: &Baseline) -> Option<bool> {+    let p = path()?;+    let len = std::fs::metadata(&p).ok()?.len();+    if len < b.len {+        return Some(true);+    }+    let now = bytes_before(&p, b.len, END_FP_BYTES)?;+    Some(crate::sha256::hex_of(&now) != b.end_fp) }  /// How long the log must have been QUIET before a `LOAD_ADDIN` after this@@ -197,10 +294,33 @@ fn mtime_secs(path: &std::path::Path) -> Option<u64> { /// start, so a log that cannot be tied to the session never lets COM decide /// alone, and a log still being written holds COM's `true`. pub fn startup_complete(session_start: Option<u64>) -> (LogVerdict, String) {+    let base = session_start.and_then(baseline_for);+    let (v, why, _) = startup_complete_since(session_start, base.as_ref());+    (v, why)+}++/// What the region read came from: the baseline used, whether the file was+/// rewritten since it, and where the region began (file offset).+#[derive(Clone, Debug, Default, PartialEq)]+pub struct Region {+    pub baseline: Option<Baseline>,+    pub rewritten: Option<bool>,+    pub from_offset: u64,+    /// The file offset of the marker that decided `Complete`, if one did.+    pub marker_offset: Option<u64>,+    pub marker: Option<String>,+}++/// `startup_complete`, reading only what a session that started after `base`+/// can have written (0.11.3): when the file was APPENDED to since `base`, the+/// region starts at `base.len`; when it was rewritten (or there is no+/// baseline), at the last start header, as before.+pub fn startup_complete_since(session_start: Option<u64>, base: Option<&Baseline>) -> (LogVerdict, String, Region) {+    let mut region = Region { baseline: base.cloned(), ..Default::default() };     let Some(path) = path() else {-        return (LogVerdict::Unavailable, "no SOLIDWORKS performance log to read".into());+        return (LogVerdict::Unavailable, "no SOLIDWORKS performance log to read".into(), region);     };-    let Some(t) = tail() else {+    let Some((raw, tail_start)) = tail_bytes() else {         // ABSENT AND UNREADABLE ARE DIFFERENT FACTS (adversary pass 45, V1). A         // log that exists — or a configured path that is missing — and cannot         // be read says the edition DOES write one and this bridge did not see@@ -212,17 +332,32 @@ pub fn startup_complete(session_start: Option<u64>) -> (LogVerdict, String) {             } else {                 format!("the configured performance log path is missing ({})", path.display())             },+            region,         );     };-    let t: &str = match t.rfind(LOG_HEADER) {-        Some(h) => &t[h..],-        None => &t,+    // WHERE THIS SESSION'S TEXT CAN BEGIN. Appended since the baseline: after+    // the recorded length — what lies before it is an earlier session's, its+    // markers included. Rewritten (or no baseline): the whole tail.+    let mut from_rel = 0usize;+    if let Some(b) = base {+        let rw = rewritten_since(b);+        region.rewritten = rw;+        if rw == Some(false) {+            from_rel = (b.len.saturating_sub(tail_start) as usize).min(raw.len());+        }+    }+    let scoped = String::from_utf8_lossy(&raw[from_rel..]).to_string();+    let (t, header_rel): (&str, usize) = match scoped.rfind(LOG_HEADER) {+        Some(h) => (&scoped[h..], h),+        None => (&scoped, 0),     };+    region.from_offset = tail_start + from_rel as u64 + header_rel as u64;     let mtime = mtime_secs(&path);     let Some(start) = session_start else {         return (             LogVerdict::NotThisSession,             "this SOLIDWORKS process's creation time is unknown, so the log cannot be tied to it".into(),+            region,         );     };     let mt = match mtime {@@ -235,9 +370,10 @@ pub fn startup_complete(session_start: Option<u64>) -> (LogVerdict, String) {                      an earlier session, not this one",                     start - mt                 ),+                region,             )         }-        None => return (LogVerdict::NotThisSession, "the log's modification time could not be read".into()),+        None => return (LogVerdict::NotThisSession, "the log's modification time could not be read".into(), region),     };     let is_platform = |l: &str| is_load_event(l) && l.to_ascii_lowercase().contains(PLATFORM_ADDIN_DLL);     // Every line with its byte offset, so positions compare exactly.@@ -266,10 +402,12 @@ pub fn startup_complete(session_start: Option<u64>) -> (LogVerdict, String) {                 LogVerdict::Loading,                 format!(                     "this session's startup lines changed {quiet}s ago ({addins} LOAD_ADDIN \-                     line(s)) and the log holds no 3DEXPERIENCE marker yet: a start in progress — \+                     line(s)) and the log holds no 3DEXPERIENCE marker {}yet: a start in progress — \                      held until the marker arrives or no startup line changes for {}s",+                    if from_rel > 0 { "written since the launch " } else { "" },                     quiet_window()                 ),+                region,             );         }         if platform {@@ -280,6 +418,7 @@ pub fn startup_complete(session_start: Option<u64>) -> (LogVerdict, String) {                      has not been written, and no startup line has changed for {quiet}s: the platform \                      load has not finished (a dialog, a sign-in?)"                 ),+                region,             );         }         return (@@ -290,10 +429,13 @@ pub fn startup_complete(session_start: Option<u64>) -> (LogVerdict, String) {                  {ON_DEMAND_QUIET_SECS}s): the add-in load phase is over — ready only if COM also \                  says the start completed"             ),+            region,         );     };     let last_addin = lines.iter().rev().find(|(_, l)| is_load_event(l)).map(|(o, _)| *o);-    match last_addin {+    region.marker = Some(name.to_string());+    region.marker_offset = Some(region.from_offset + m as u64);+    let verdict_and_why = match last_addin {         Some(a) if a > m => {             // A START loads the PLATFORM add-in — it is what writes the marker —             // so a LOAD_ADDIN for it after the last marker is a start in@@ -331,9 +473,17 @@ pub fn startup_complete(session_start: Option<u64>) -> (LogVerdict, String) {         }         _ => (             LogVerdict::Complete,-            format!("{name} written after the last LOAD_ADDIN line, in a log written since this process started"),+            format!(+                "{name} written after the last LOAD_ADDIN line, in a log written since this process started{}",+                match (&region.baseline, region.rewritten) {+                    (Some(b), Some(false)) => format!(", and beyond the {} bytes the file held before this launch ({})", b.len, b.why),+                    (Some(b), Some(true)) => format!(" (the file was rewritten since the {} record)", b.why),+                    _ => String::new(),+                }+            ),         ),-    }+    };+    (verdict_and_why.0, verdict_and_why.1, region) }  /// THE FILE'S SHAPE, for the record (adversary pass 44, F7): its length now and
src/readiness.rs+130−4
@@ -37,6 +37,15 @@ //! that does not become ready within `TIMEOUT_SECS` is `readinessTimedOut`, still //! starting. Once a session (by process id) is verified ready it stays ready. //!+//! A QUICK RESTART (0.11.3, measured 2026-10-15): `ready` came 4 s after attach+//! and a document command 11 s after attach killed SOLIDWORKS. So the log is+//! read only beyond its state when no SOLIDWORKS was writing it+//! (`perflog::Baseline`: a launch, a quit, or a first sight of a log still+//! holding the previous session), and a FRESH attach — the bridge's own launch,+//! or a process first seen young — needs StartupProcessCompleted TRUE and+//! `settle_secs()` since attach on top of the marker. `evidence` lists what was+//! used and how old it is; the ready transition is ledgered.+//! //! Every assessment also reads `GetDocumentCount` (in `startup_state`): a //! non-zero count at ANY poll records the session as having held a document //! (`session_history`).@@ -52,6 +61,33 @@ pub const RETRY_AFTER_SECS: u64 = 5;  /// The grace, overridable (`SWX_READINESS_GRACE_SECS`) so the suite need not /// wait a real minute. It only ever unlocks READ verbs.+/// THE SETTLE AFTER A FRESH ATTACH (0.11.3, `SWX_READY_SETTLE_SECS`). MEASURED+/// 2026-10-15 22:40 (hosted 0.11.2): a quick restart was called `ready` 4 s+/// after COM attached; a document command 11 s after attach "succeeded" and+/// SOLIDWORKS died a second later — the 2026-10-01 crash again (8 s after+/// attach, an add-in still initialising). A session this bridge has just seen+/// start is ready only with COM's StartupProcessCompleted TRUE, this session's+/// own marker, AND this long since it attached.+pub fn settle_secs() -> u64 {+    std::env::var("SWX_READY_SETTLE_SECS").ok().and_then(|v| v.trim().parse().ok()).unwrap_or(20)+}++/// When THIS session attached, as far as the bridge knows: the launch that+/// attached it (the attempt's attach time, when the attempt is about this+/// process or one created after the attempt began).+fn launch_attach_anchor(pid: i64, created: Option<u64>) -> Option<u64> {+    let a = crate::launch::attempt()?;+    if !a.finished || a.outcome.as_deref() != Some("attached") {+        return None;+    }+    let ours = match (a.attributed_sldworks, created) {+        (Some((p, c)), Some(cr)) if p as i64 == pid && c == cr => true,+        (_, Some(cr)) => cr + 5 >= a.started_at,+        _ => false,+    };+    ours.then_some(a.stage_at)+}+ fn grace_secs() -> u64 {     std::env::var("SWX_READINESS_GRACE_SECS")         .ok()@@ -61,6 +97,9 @@ fn grace_secs() -> u64 {  struct Seen {     first: Instant,+    /// The same moment, in epoch seconds — the settle's anchor for a session+    /// first seen young.+    first_epoch: u64,     ready: bool,     /// The performance log's length when this session was first seen (F7): a     /// rewrite at the next start shrinks it; an appended log only grows.@@ -103,16 +142,33 @@ pub fn assess(ctx: &crate::verbs::Ctx) -> Value {                 .and_then(|ps| ps.iter().find(|x| x.pid == p).and_then(|x| x.created_at))         })         .or_else(|| state.get("processCreatedAt").and_then(|v| v.as_u64()));-    let (log, log_why) = crate::perflog::startup_complete(created);+    // THE LOG, READ ONLY WHERE THIS SESSION CAN HAVE WRITTEN (0.11.3): beyond+    // the state the file was in when no SOLIDWORKS was writing it (a launch+    // began, a quit finished), unless it has been rewritten since. A session+    // first seen while the log is still the previous session's records that+    // state itself.+    if let Some(c) = created {+        let written = crate::perflog::path().and_then(|p| {+            std::fs::metadata(&p).and_then(|m| m.modified()).ok().and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok()).map(|d| d.as_secs())+        });+        if written.map(|w| w < c).unwrap_or(false) && crate::perflog::baseline_for(c).is_none() {+            crate::perflog::record_baseline("firstSightWhileTheLogWasStillTheLastSession's", Some(c));+        }+    }+    let base = created.and_then(crate::perflog::baseline_for);+    let (log, log_why, region) = crate::perflog::startup_complete_since(created, base.as_ref());     use crate::perflog::LogVerdict as L;     let mut guard = SESSIONS.lock().unwrap_or_else(|e| e.into_inner());     let map = guard.get_or_insert_with(HashMap::new);     let key = (pid.unwrap_or(-1), created);     let shape = crate::perflog::shape();     let len_now = shape.get("lengthNow").and_then(|v| v.as_u64());-    let seen = map-        .entry(key)-        .or_insert(Seen { first: Instant::now(), ready: false, log_len_at_first_sight: len_now });+    let seen = map.entry(key).or_insert(Seen {+        first: Instant::now(),+        first_epoch: crate::launchos::epoch_secs(),+        ready: false,+        log_len_at_first_sight: len_now,+    });     let len_first = seen.log_len_at_first_sight;     let age = seen.first.elapsed().as_secs();     let mut based_on: Vec<&str> = Vec::new();@@ -167,10 +223,64 @@ pub fn assess(ctx: &crate::verbs::Ctx) -> Value {             (L::NotThisSession, _) => None,         }     };+    // A FRESH ATTACH (0.11.3): a session the bridge saw start — attached by its+    // own launch, or first seen while the process was young — is ready only with+    // StartupProcessCompleted TRUE and `settle_secs()` since it attached.+    let now_secs = crate::launchos::epoch_secs();+    let launch_anchor = launch_attach_anchor(pid.unwrap_or(-1), created);+    let young_at_first_sight = created.map(|c| seen.first_epoch.saturating_sub(c) < long_running_secs()).unwrap_or(false);+    let anchor: Option<u64> = match (launch_anchor, young_at_first_sight) {+        (Some(a), _) => Some(a),+        (None, true) => Some(seen.first_epoch),+        (None, false) => None,+    };+    let fresh = anchor.is_some() && !seen.ready;+    let since_attach = anchor.map(|a| now_secs.saturating_sub(a));+    let mut held_by: Option<String> = None;+    let mut verdict = verdict;+    if verdict == Some(true) && fresh {+        if com != Some(true) {+            held_by = Some("a fresh start is ready only with StartupProcessCompleted TRUE, and COM has not said so".into());+            verdict = Some(false);+        } else if since_attach.map(|s| s < settle_secs()).unwrap_or(false) {+            held_by = Some(format!(+                "settling: attached {}s ago, and a fresh start is ready only {}s after attach (SWX_READY_SETTLE_SECS) — \+                 document commands 8 s and 11 s after attach crashed SOLIDWORKS (2026-10-01, 2026-10-15)",+                since_attach.unwrap_or(0),+                settle_secs()+            ));+            verdict = Some(false);+        }+    }+    if held_by.is_some() {+        based_on.push("settleAfterAttach");+    }     let ready = verdict == Some(true);+    // THE EVIDENCE, with its age — what the verdict was built from.+    let log_age = crate::perflog::path()+        .and_then(|p| std::fs::metadata(&p).and_then(|m| m.modified()).ok())+        .and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok())+        .map(|d| now_secs.saturating_sub(d.as_secs()));+    let evidence = json!([+        {"signal": "StartupProcessCompleted", "value": com},+        {"signal": "performanceLog", "verdict": log.name(), "marker": region.marker, "markerOffset": region.marker_offset,+         "readFromOffset": region.from_offset,+         "launchBaseline": region.baseline.as_ref().map(|b| json!({"length": b.len, "why": b.why, "ageSeconds": now_secs.saturating_sub(b.at_secs)})),+         "rewrittenSinceBaseline": region.rewritten,+         "logLastWrittenSecondsAgo": log_age},+        {"signal": "settleAfterAttach", "attachedSecondsAgo": since_attach, "required": settle_secs(),+         "anchor": if launch_anchor.is_some() { "launchAttach" } else if anchor.is_some() { "firstSeenYoung" } else { "notAFreshStart" },+         "satisfied": since_attach.map(|s| s >= settle_secs()).unwrap_or(true)},+    ]);     if ready && pid.is_some() {         if !seen.ready {             persist_ready(pid.unwrap_or(-1), created);+            // THE TRANSITION IS ON THE RECORD, with what decided it — so a+            // crash after it can be laid beside the evidence.+            crate::ledger::record(+                "solidworks_ready",+                json!({"processId": pid, "processCreatedAt": created, "basedOn": based_on, "evidence": evidence}),+            );         }         seen.ready = true;     }@@ -201,6 +311,8 @@ pub fn assess(ctx: &crate::verbs::Ctx) -> Value {         "processId": pid,         "processCreatedAt": created,         "basedOn": based_on,+        "evidence": evidence,+        "why": held_by.clone().unwrap_or_else(|| log_why.clone()),         "startupProcessCompleted": com,         "performanceLog": {             "verdict": log.name(),@@ -224,6 +336,20 @@ pub fn assess(ctx: &crate::verbs::Ctx) -> Value {     }) } +/// How long ago THIS session attached, as far as the bridge knows: its own+/// launch's attach, or its first sight if the process was young then. `None` =+/// not a session the bridge saw start.+pub fn attached_secs_ago(pid: i64, created: Option<u64>) -> Option<u64> {+    let now = crate::launchos::epoch_secs();+    if let Some(a) = launch_attach_anchor(pid, created) {+        return Some(now.saturating_sub(a));+    }+    let g = SESSIONS.lock().unwrap_or_else(|e| e.into_inner());+    let seen = g.as_ref()?.get(&(pid, created))?;+    let young = created.map(|c| seen.first_epoch.saturating_sub(c) < long_running_secs()).unwrap_or(false);+    young.then(|| now.saturating_sub(seen.first_epoch))+}+ /// A session is long-running past this many seconds (`SWX_LONG_RUNNING_SECS`). pub fn long_running_secs() -> u64 {     std::env::var("SWX_LONG_RUNNING_SECS").ok().and_then(|v| v.trim().parse().ok()).unwrap_or(600)
src/verbs.rs+33−2
@@ -810,7 +810,16 @@ fn swx_progress(ctx: &Ctx, _args: &Value) -> Value { /// with an empty name that a launch route provably raised is cancelled here /// too — ledgered — so a launch never leaves the session blocked. fn swx_start(ctx: &Ctx, args: &Value) -> Value {+    // A START RIGHT AFTER A QUIT waits for that session to be gone (0.11.3).+    let waited = if arg_str(args, "app").map(|a| a == "visualize").unwrap_or(false) {+        None+    } else {+        crate::launch::wait_for_previous_exit(crate::launchos::os().as_ref())+    };     let mut out = swx_start_inner(ctx, args);+    if let (Some(w), Value::Object(m)) = (waited, &mut out) {+        m.insert("waitedForPreviousExit".into(), w);+    }     let cancelled = crate::dialogs::cancel_launch_file_dialogs(crate::launchos::os().as_ref());     if !cancelled.is_empty() {         if let Value::Object(m) = &mut out {@@ -1810,6 +1819,14 @@ fn swx_stop(ctx: &Ctx, args: &Value) -> Value {             "solidworks_stopped",             json!({"rung": winning, "authorized": grant.user_write, "identity": id.to_json()}),         );+        // THE QUIT IS REMEMBERED (0.11.3): a start right after it waits for this+        // session's process tree to be gone, and the performance log's state now+        // — no SOLIDWORKS writing it — bounds what the NEXT session may claim.+        crate::perflog::record_baseline("quit", None);+        let _ = std::fs::write(+            crate::scratch::root().join("last-quit.json"),+            json!({"pid": id.pid, "createdAt": id.created_at, "atMs": crate::launchos::epoch_ms() as u64}).to_string(),+        );     }     let rungs_json: Vec<Value> = tries.iter().map(|t| t.to_json()).collect();     let census_json = |c: &Result<Vec<crate::launchos::ProcInfo>, String>| -> Value {@@ -2230,11 +2247,24 @@ fn swx_open(ctx: &Ctx, args: &Value) -> Value {         m.insert("launch".into(), Value::Bool(may));         m.insert("readOnly".into(), Value::Bool(read_only));     }+    let session_before = crate::verbs3::session_identity(ctx);     match ctx.call("open", call_args, 280) {         Err(e) => sidecar_error(e),-        Ok(r) => ok_merge(+        Ok(r) => {+            // THE EFFECT (0.11.3): the document is open in the SAME, LIVE session.+            // A SOLIDWORKS that was not running before the open (a classic+            // install the open launched) is read as the session now answering.+            let before = session_before.or_else(|| crate::verbs3::session_identity(ctx));+            let opened_path = r.pointer("/doc/path").and_then(|p| p.as_str()).filter(|p| !p.is_empty()).map(String::from).unwrap_or_else(|| path.clone());+            let opened_title = r.pointer("/doc/title").and_then(|t| t.as_str()).map(String::from);+            let effect = match crate::verbs3::verify_effect(ctx, "swx_open", before, opened_title.as_deref(), Some(&opened_path)) {+                Ok(v) => v,+                Err(e) => return e,+            };+            ok_merge(             r,             json!({+                "effect": effect,                 "windowEtiquette": "background",                 "progress": job.finished(),                 "_hint": "Open and active, READ-ONLY by default — so the bridge does not hold a \@@ -2247,7 +2277,8 @@ fn swx_open(ctx: &Ctx, args: &Value) -> Value {                           answers host_app_launch_blocked instead. On a classic desktop install \                           it will launch it, and the progress frame reports what that cost.",             }),-        ),+        )+        }     } } 
src/verbs3.rs+161−1
@@ -3928,6 +3928,142 @@ pub(crate) fn settle_document_visible(ctx: &Ctx, kind: &str, visibility: &Value)     v } +// ── VERIFY BY EFFECT (0.11.3) ───────────────────────────────────────────────+// MEASURED 2026-10-15 22:40:50 (hosted 0.11.2): swx_new_document returned OK,+// with a title and a ledger `document_created` — and swx_docs one second later+// said []: SOLIDWORKS (pid 26316) had died right after the document command, 11 s+// after attach. A reply is not an effect. After a document-creating verb the+// bridge reads, from the LIVE session: the process is still the same one and+// still in the process census, the document count is not zero, and the document+// is in the list. Fresh sessions are read again after a short pause, because+// that death came a second after the reply.++/// The running session's (pid, creation time), from the host and the census.+pub(crate) fn session_identity(ctx: &Ctx) -> Option<(i64, Option<u64>)> {+    let s = ctx.call("startup_state", json!({}), 20).ok()?;+    if s.get("running").and_then(|v| v.as_bool()) != Some(true) {+        return None;+    }+    let pid = s.get("processId").and_then(|v| v.as_i64())?;+    let created = u32::try_from(pid)+        .ok()+        .and_then(|p| crate::launchos::os().processes().ok().and_then(|ps| ps.iter().find(|x| x.pid == p).and_then(|x| x.created_at)))+        .or_else(|| s.get("processCreatedAt").and_then(|v| v.as_u64()));+    Some((pid, created))+}++fn effect_recheck_ms() -> u64 {+    std::env::var("SWX_EFFECT_RECHECK_MS").ok().and_then(|v| v.trim().parse().ok()).unwrap_or(1500)+}++/// One reading of the effect: Ok(evidence), or Err((died, why)).+fn read_effect(ctx: &Ctx, before: (i64, Option<u64>), title: Option<&str>, path: Option<&str>) -> Result<Value, (bool, String)> {+    let (pid, created) = before;+    let census = crate::launchos::os().processes().ok();+    let in_census = census.as_ref().map(|ps| ps.iter().any(|p| p.pid as i64 == pid && (created.is_none() || p.created_at.is_none() || p.created_at == created)));+    // THE LIVE SESSION ANSWERS FIRST; the process census decides only when it+    // cannot (a dead SOLIDWORKS takes its COM server with it).+    let state = match ctx.call("startup_state", json!({}), 20) {+        Ok(s) => s,+        Err(e) => {+            if in_census == Some(false) {+                return Err((true, format!("the com host could not answer ({}) and SOLIDWORKS pid {pid} is gone from the process census", e.message)));+            }+            return Ok(json!({"verified": false, "processId": pid, "inProcessCensus": in_census,+                             "why": format!("the com host could not answer ({}); the process is {}", e.message,+                                            if in_census == Some(true) { "still running" } else { "of unknown state" })}));+        }+    };+    if state.get("running").and_then(|v| v.as_bool()) != Some(true) {+        return Err((true, format!("SOLIDWORKS (pid {pid}) is no longer running")));+    }+    let now_pid = state.get("processId").and_then(|v| v.as_i64());+    if now_pid != Some(pid) {+        return Err((true, format!("SOLIDWORKS pid {pid} is gone: the session now answering is pid {now_pid:?}")));+    }+    let count = state.get("documentCount").and_then(|v| v.as_u64());+    if count == Some(0) {+        return Err((false, "SOLIDWORKS reports ZERO open documents".into()));+    }+    let docs = ctx.call("docs", json!({}), 30).map_err(|e| (false, format!("the document list could not be read ({})", e.message)))?;+    // A list too long to enumerate (leaked import temps) cannot show the+    // document either way: the live count and the live process stand.+    if docs.get("truncated").and_then(|t| t.as_bool()) == Some(true) {+        return Ok(json!({"verified": true, "processId": pid, "processCreatedAt": created, "documentCount": count,+                         "inProcessCensus": in_census, "documentListTruncated": true}));+    }+    let list = docs.get("docs").and_then(|d| d.as_array()).cloned().unwrap_or_default();+    let found = list.iter().any(|d| {+        let dp = d.get("path").and_then(|p| p.as_str()).filter(|p| !p.is_empty());+        let dt = d.get("title").and_then(|t| t.as_str()).unwrap_or("");+        match (path, dp) {+            (Some(p), Some(q)) => crate::verbs::same_path(p, q),+            _ => title.map(|t| crate::verbs::same_title(t, dt)).unwrap_or(false),+        }+    });+    if !found && (title.is_some() || path.is_some()) {+        return Err((false, format!("the document ({}) is not in SOLIDWORKS' document list", path.or(title).unwrap_or("?"))));+    }+    Ok(json!({"verified": true, "processId": pid, "processCreatedAt": created, "documentCount": count, "inProcessCensus": in_census}))+}++/// THE EFFECT CHECK. `Ok(evidence)` to merge into the reply; `Err(reply)` —+/// `host_app_died` or `document_not_created` — never an ok.+pub(crate) fn verify_effect(ctx: &Ctx, verb: &str, before: Option<(i64, Option<u64>)>, title: Option<&str>, path: Option<&str>) -> Result<Value, Value> {+    let Some(before) = before else {+        return Ok(json!({"verified": false, "why": "the session's identity could not be read before the command"}));+    };+    let mut reads = 1;+    let mut r = read_effect(ctx, before, title, path);+    // A FRESH SESSION IS READ AGAIN: the 2026-10-15 death came a second after+    // the reply.+    let fresh = crate::readiness::attached_secs_ago(before.0, before.1).map(|s| s < 180).unwrap_or(false);+    if r.is_ok() && fresh && effect_recheck_ms() > 0 {+        std::thread::sleep(std::time::Duration::from_millis(effect_recheck_ms()));+        reads = 2;+        r = read_effect(ctx, before, title, path);+    }+    match r {+        Ok(mut v) => {+            v["reads"] = json!(reads);+            Ok(v)+        }+        Err((died, why)) => {+            let evidence = crate::perflog::crash_evidence();+            let code = if died { "host_app_died" } else { "document_not_created" };+            crate::ledger::record(+                code,+                json!({"verb": verb, "processId": before.0, "processCreatedAt": before.1, "documentReported": path.or(title),+                       "why": why, "crashEvidence": evidence}),+            );+            let mut out = err_code(+                code,+                if died {+                    format!("{verb} reported success, then SOLIDWORKS stopped: {why}. The document does not exist.")+                } else {+                    format!("{verb} reported success, but {why}: the document was NOT created")+                },+                if died {+                    "SOLIDWORKS died right after the command (measured 2026-10-15: 11 s after attach, a fresh start). \+                     Nothing was created. Quote `crashEvidence`; let the user restart it (swx_start), and wait for \+                     swx_status solidworks.ready before any document verb."+                } else {+                    "The command's reply is not the effect. swx_docs shows what is really open; retry once SOLIDWORKS \+                     is ready."+                },+            );+            if let Value::Object(m) = &mut out {+                m.insert("processId".into(), json!(before.0));+                m.insert("processCreatedAt".into(), json!(before.1));+                m.insert("documentReported".into(), json!(path.or(title)));+                m.insert("crashEvidence".into(), json!(evidence));+                m.insert("ledger".into(), json!(code));+            }+            Err(out)+        }+    }+}+ pub fn new_document(ctx: &Ctx, args: &Value) -> Value {     gate!(ctx);     let kind = arg_str(args, "type").unwrap_or("part").to_string();@@ -3957,6 +4093,7 @@ pub fn new_document(ctx: &Ctx, args: &Value) -> Value {         call_args["scratchPath"] = json!(path.to_string_lossy());     }     let started = std::time::Instant::now();+    let session_before = session_identity(ctx);     match ctx.call("new_document", call_args, 110) {         // A FAILED new_document IS THE EXHAUSTION SIGNAL. On 2026-09-03 both the         // part and the assembly template came back with no document at 17.4 GB@@ -4012,6 +4149,19 @@ pub fn new_document(ctx: &Ctx, args: &Value) -> Value {                     None => ctx.remember_scratch(&now_titled, session),                 }             }+            // THE EFFECT, before anything is recorded as created (0.11.3).+            let made_title = identity.get("title").and_then(|v| v.as_str()).map(String::from)+                .or_else(|| r.get("created").and_then(|c| c.get("title")).and_then(|t| t.as_str()).map(String::from));+            let made_path = identity.get("path").and_then(|p| p.as_str()).filter(|p| !p.is_empty()).map(String::from);+            let effect = match verify_effect(ctx, "swx_new_document", session_before, made_title.as_deref(), made_path.as_deref()) {+                Ok(v) => v,+                Err(e) => {+                    if let Some(t) = &made_title {+                        ctx.forget_scratch_doc(t, made_path.as_deref());+                    }+                    return e;+                }+            };             crate::ledger::record(                 "document_created",                 json!({@@ -4019,6 +4169,7 @@ pub fn new_document(ctx: &Ctx, args: &Value) -> Value {                     "type": kind,                     "template": r.get("template").cloned(),                     "visible": visible,+                    "effect": effect,                 }),             );             let mut r = r;@@ -4040,6 +4191,7 @@ pub fn new_document(ctx: &Ctx, args: &Value) -> Value {             let titled_only = identity.get("identity").and_then(|v| v.as_str()) == Some("titleOnly");             ok_merge(r, json!({                 "documentIdentity": identity,+                "effect": effect,                 "windowEtiquette": "background",                 "progress": job.finished(),                 "_hint": if !visible {@@ -4206,6 +4358,7 @@ pub fn import(ctx: &Ctx, args: &Value) -> Value {     let before_docs = ownership_context(ctx).1;     let before_titles: Vec<String> = before_docs.iter().map(doc_title).collect();     let before_count = Some(before_docs.len() as u64);+    let session_before = session_identity(ctx);     let mut host_args = json!({"filePath": path});     if args.get("dissolve").and_then(|v| v.as_bool()).unwrap_or(false) {         host_args["dissolve"] = json!(true);@@ -4301,9 +4454,16 @@ pub fn import(ctx: &Ctx, args: &Value) -> Value {                     None => ctx.remember_scratch(&now_titled, session),                 }             }+            let made_title = identity.get("title").and_then(|v| v.as_str()).map(String::from)+                .or_else(|| r.get("imported").and_then(|c| c.get("title")).and_then(|t| t.as_str()).map(String::from));+            let made_path = identity.get("path").and_then(|p| p.as_str()).filter(|p| !p.is_empty()).map(String::from);+            let effect = match verify_effect(ctx, "swx_import", session_before, made_title.as_deref(), made_path.as_deref()) {+                Ok(v) => v,+                Err(e) => return e,+            };             crate::ledger::record(                 "document_created",-                json!({"title": r.get("imported").and_then(|c| c.get("title")).cloned(), "via": "import"}),+                json!({"title": r.get("imported").and_then(|c| c.get("title")).cloned(), "via": "import", "effect": effect}),             );             let mut r = r;             if let Some(o) = r.as_object_mut() {
tests/common/mod.rs+5
@@ -158,6 +158,11 @@ impl Bridge {             .env("SWX_MOCK", "1")             .env("ADOM_BIND_HOST", "127.0.0.1")             .env("SWX_SCRATCH_DIR", scratch.path())+            // The fresh-attach settle (0.11.3) is 20 s in production; a test that+            // is ABOUT it sets its own.+            .env("SWX_READY_SETTLE_SECS", "0")+            // ...and so is the effect re-read of a fresh session (1.5 s).+            .env("SWX_EFFECT_RECHECK_MS", "0")             // ab injects these; absent here on purpose so the callback path is             // exercised in its "ab unreachable" shape.             .env_remove("ADOM_DIRECT_API_URL")
tests/e2e.rs+1−1
@@ -1646,7 +1646,7 @@ fn ownership_does_not_survive_a_solidworks_restart_or_a_close() {         b,         "a new SOLIDWORKS session REUSES the title Part1, exactly as the real one does",         after_restart == "Part1",-        after_restart.clone()+        format!("{after_restart} {}", s(&r))     );     let r = b.call("swx_reset_workspace", json!({"titles": ["nothing"]}));     let tracked = r["trackedScratchDocuments"].as_array().cloned().unwrap_or_default();
tests/restart.rsadded+323
@@ -0,0 +1,323 @@+//! A QUICK RESTART IS NOT READY (0.11.3) — from the laptop's ledger,+//! 2026-10-15, hosted 0.11.2, SOLIDWORKS 2026:+//!+//! | 22:40:01 | quit (processGone) |+//! | 22:40:02 | launch |+//! | 22:40:07 | sldworksUp |+//! | 22:40:39 | attached |+//! | 22:40:43 | `solidworks.ready` TRUE — 4 s after attach |+//! | 22:40:50 | swx_new_document OK, title `Part1-…SLDPRT`, ledger `document_created` |+//! | 22:40:51 | swx_docs: [] — SOLIDWORKS (pid 26316) had DIED |+//!+//! The 2026-10-01 crash again: a document command while an add-in was still+//! initialising. Everything here runs in the simulator.++mod common;++use common::{Bridge, TempDir};+use serde_json::{json, Value};+use std::time::{Duration, SystemTime};++fn s(v: &Value) -> String {+    serde_json::to_string_pretty(v).unwrap_or_default()+}++fn ledger(b: &Bridge) -> Vec<Value> {+    b.call("swx_action_ledger", json!({"limit": 500}))["actions"].as_array().cloned().unwrap_or_default()+}++fn now() -> u64 {+    SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs()+}++fn session(scratch: &TempDir) {+    std::fs::write(+        scratch.join("mock-solidworks-open-docs.json"),+        json!({"running": true, "untitled": 0, "active": Value::Null, "docs": [], "files": {}}).to_string(),+    )+    .unwrap();+}++/// A session the simulated machine started `age` seconds ago.+fn young_session(scratch: &TempDir, age: u64) {+    session(scratch);+    std::fs::write(scratch.join("mock-sldworks-created"), (now() - age).to_string()).unwrap();+}++fn set_mtime(p: &std::path::Path, secs_ago: u64) {+    std::fs::File::options()+        .write(true)+        .open(p)+        .unwrap()+        .set_modified(SystemTime::now() - Duration::from_secs(secs_ago))+        .unwrap();+}++/// The previous session's whole start, as its log holds it.+const PREVIOUS: &str = "; SolidWorks generated log file\n<AD2> \"LOAD_ADDIN\" \"SWK3DCompassAddin.dll\" \"3DEXPERIENCE for WORKS\"\n\+<3DXLOAD_TIME>24000</3DXLOAD_TIME>\n<PROCMEM> CMD:AppRunTime 1\n<PROCMEM> CMD:AppRunTime 2\n";++#[test]+fn a_marker_the_previous_session_wrote_never_makes_the_new_one_ready() {+    let scratch = TempDir::new("restart-stale");+    young_session(&scratch, 3);+    let log = scratch.join("SolidWorksPerformance.log");+    std::fs::write(&log, PREVIOUS).unwrap();+    // Last written 30 s ago: before this SOLIDWORKS started.+    set_mtime(&log, 30);+    let logp = log.to_string_lossy().to_string();+    let b = Bridge::start_in(TempDir::borrowed(&scratch.0), &[("SWX_PERF_LOG", &logp)]);+    b.call("swx_start", json!({}));+    let st = b.call("swx_status", json!({}));+    check!(+        b,+        "first sight: the log is still the previous session's — not ready, and its state is recorded as the baseline",+        st["solidworks"]["ready"] == false && scratch.join("perflog-baselines.json").exists(),+        s(&st["solidworks"]["readiness"])+    );+    // The NEW session touches the file — a line, no header, no add-in yet. The+    // old reading took the text after the last header: the previous session's+    // marker after its last LOAD_ADDIN — "complete".+    std::fs::write(&log, format!("{PREVIOUS}<PROCMEM> CMD:SessionStart\n")).unwrap();+    let r = b.call("swx_new_document", json!({"type": "part"}));+    let ev = r["readiness"].clone();+    check!(+        b,+        "a quick restart is NOT ready on the previous session's marker: host_app_starting",+        r["errorCode"] == "host_app_starting",+        s(&r)+    );+    let full = b.call("swx_status", json!({}));+    let pl = full["solidworks"]["readiness"]["evidence"][1].clone();+    check!(+        b,+        "...the evidence says the log was read from beyond the launch baseline, and holds no marker of this session",+        pl["launchBaseline"]["length"].as_u64() == Some(PREVIOUS.len() as u64)+            && pl["readFromOffset"].as_u64() == Some(PREVIOUS.len() as u64)+            && pl["marker"].is_null()+            && pl["rewrittenSinceBaseline"] == false,+        format!("{}\n{}", s(&full["solidworks"]["readiness"]), s(&ev))+    );+    // THIS session loads its add-ins and writes its own marker: ready.+    std::fs::write(+        &log,+        format!("{PREVIOUS}<PROCMEM> CMD:SessionStart\n<AD2> \"LOAD_ADDIN\" \"SWK3DCompassAddin.dll\" \"3DEXPERIENCE for WORKS\"\n<3DXLOAD_TIME>21000</3DXLOAD_TIME>\n"),+    )+    .unwrap();+    let r = b.call("swx_new_document", json!({"type": "part"}));+    check!(b, "this session's own marker, beyond the baseline: ready, the document is made", r["success"] == true, s(&r));+    let ready = ledger(&b).into_iter().find(|e| e["action"] == "solidworks_ready").unwrap_or(Value::Null);+    check!(+        b,+        "...and the transition is LEDGERED with the evidence that decided it",+        ready["detail"]["evidence"][1]["markerOffset"].as_u64().map(|o| o > PREVIOUS.len() as u64).unwrap_or(false),+        s(&ready)+    );+}++#[test]+fn a_rewritten_log_is_read_whole_and_its_marker_counts() {+    let scratch = TempDir::new("restart-rewritten");+    young_session(&scratch, 3);+    let log = scratch.join("SolidWorksPerformance.log");+    std::fs::write(&log, format!("{PREVIOUS}{}", "<PROCMEM> CMD:AppRunTime n\n".repeat(40))).unwrap();+    set_mtime(&log, 30);+    let logp = log.to_string_lossy().to_string();+    let b = Bridge::start_in(TempDir::borrowed(&scratch.0), &[("SWX_PERF_LOG", &logp)]);+    b.call("swx_start", json!({}));+    b.call("swx_status", json!({}));+    // REWRITTEN at the new start (measured 2026-10-01: one header, at the top).+    std::fs::write(&log, PREVIOUS).unwrap();+    let r = b.call("swx_new_document", json!({"type": "part"}));+    check!(b, "a log rewritten since the baseline is this session's: its marker counts", r["success"] == true, s(&r));+}++#[test]+fn a_log_rewritten_past_the_old_length_is_known_by_its_bytes_not_its_size() {+    let scratch = TempDir::new("restart-rewritten-long");+    young_session(&scratch, 3);+    let log = scratch.join("SolidWorksPerformance.log");+    std::fs::write(&log, PREVIOUS).unwrap();+    set_mtime(&log, 30);+    let logp = log.to_string_lossy().to_string();+    let b = Bridge::start_in(TempDir::borrowed(&scratch.0), &[("SWX_PERF_LOG", &logp)]);+    b.call("swx_start", json!({}));+    b.call("swx_status", json!({}));+    // Rewritten, this session's marker EARLY in it, and already LONGER than the+    // old file: only the bytes where the old file ended can tell.+    let mut fresh = String::from("; SolidWorks generated log file\n<AD2> \"LOAD_ADDIN\" \"SWK3DCompassAddin.dll\" \"3DEXPERIENCE for WORKS\"\n<3DXLOAD_TIME>19000</3DXLOAD_TIME>\n");+    while fresh.len() < PREVIOUS.len() * 3 {+        fresh.push_str("<PROCMEM> CMD:AppRunTime this-session\n");+    }+    std::fs::write(&log, fresh).unwrap();+    let r = b.call("swx_new_document", json!({"type": "part"}));+    check!(b, "rewritten (different bytes where the old file ended): its early marker counts", r["success"] == true, s(&r));+}++#[test]+fn the_ready_latch_belongs_to_one_process_identity() {+    let scratch = TempDir::new("restart-latch");+    session(&scratch);+    std::fs::write(scratch.join("mock-startup-incomplete"), "").unwrap();+    let b = Bridge::start_in(TempDir::borrowed(&scratch.0), &[("SWX_PERF_LOG", "")]);+    b.call("swx_start", json!({}));+    let st = b.call("swx_status", json!({}));+    let pid = st["solidworks"]["readiness"]["processId"].as_i64().unwrap();+    let created = st["solidworks"]["readiness"]["processCreatedAt"].as_u64().unwrap();+    // A latch for the SAME pid with ANOTHER creation time — the previous+    // session's — and one for another pid.+    std::fs::write(+        scratch.join("ready-sessions.json"),+        json!({format!("{pid}:{}", created - 7): {"readyAtMs": 1}, format!("{}:{created}", pid + 1): {"readyAtMs": 1}}).to_string(),+    )+    .unwrap();+    let st = b.call("swx_status", json!({}));+    check!(+        b,+        "a latch from another process identity never makes this session ready",+        st["solidworks"]["ready"] == false+            && !st["solidworks"]["readiness"]["basedOn"].as_array().map(|a| a.iter().any(|x| x == "readyBeforeThisBridgeRestarted")).unwrap_or(true),+        s(&st["solidworks"]["readiness"])+    );+    std::fs::write(scratch.join("ready-sessions.json"), json!({format!("{pid}:{created}"): {"readyAtMs": 1}}).to_string()).unwrap();+    let st = b.call("swx_status", json!({}));+    check!(b, "...THIS identity's latch does (a bridge restart keeps a verified session ready)", st["solidworks"]["ready"] == true, s(&st["solidworks"]["readiness"]));+}++#[test]+fn a_fresh_start_settles_after_attach_and_needs_com_to_say_it_completed() {+    let scratch = TempDir::new("restart-settle");+    young_session(&scratch, 2);+    let b = Bridge::start_in(TempDir::borrowed(&scratch.0), &[("SWX_PERF_LOG", ""), ("SWX_READY_SETTLE_SECS", "3")]);+    b.call("swx_start", json!({}));+    let r = b.call("swx_new_document", json!({"type": "part"}));+    check!(+        b,+        "attached a moment ago: host_app_starting — settling, with the evidence and its age",+        r["errorCode"] == "host_app_starting"+            && r["readiness"]["basedOn"].as_array().map(|a| a.iter().any(|x| x == "settleAfterAttach")).unwrap_or(false),+        s(&r)+    );+    let st = b.call("swx_status", json!({}));+    let settle = st["solidworks"]["readiness"]["evidence"][2].clone();+    check!(+        b,+        "...the settle evidence: required 3 s, not yet satisfied, anchored on the young session's first sight",+        settle["required"] == 3 && settle["satisfied"] == false && settle["anchor"] == "firstSeenYoung"+            && st["solidworks"]["readiness"]["why"].as_str().unwrap_or("").contains("settling"),+        s(&st["solidworks"]["readiness"])+    );+    std::thread::sleep(Duration::from_millis(3300));+    let r = b.call("swx_new_document", json!({"type": "part"}));+    check!(b, "after the settle: ready, the document is made", r["success"] == true, s(&r));++    // COM UNSURE on a fresh start: never ready on the log alone.+    let scratch2 = TempDir::new("restart-com");+    young_session(&scratch2, 2);+    std::fs::write(scratch2.join("mock-startup-unreadable"), "").unwrap();+    let log = scratch2.join("SolidWorksPerformance.log");+    std::fs::write(&log, PREVIOUS).unwrap();+    let logp = log.to_string_lossy().to_string();+    let b2 = Bridge::start_in(TempDir::borrowed(&scratch2.0), &[("SWX_PERF_LOG", &logp)]);+    b2.call("swx_start", json!({}));+    let st = b2.call("swx_status", json!({}));+    check!(+        b2,+        "a fresh start with a complete log but StartupProcessCompleted unknown is NOT ready",+        st["solidworks"]["ready"] == false+            && st["solidworks"]["readiness"]["why"].as_str().unwrap_or("").contains("StartupProcessCompleted"),+        s(&st["solidworks"]["readiness"])+    );+}++#[test]+fn a_document_solidworks_dies_right_after_is_never_reported_created() {+    let scratch = TempDir::new("restart-died");+    session(&scratch);+    let b = Bridge::start_in(TempDir::borrowed(&scratch.0), &[]);+    b.call("swx_start", json!({}));+    // The command answers, the identity save answers — then the process is gone.+    std::fs::write(scratch.join("mock-dies-after-new-document"), "1").unwrap();+    let r = b.call("swx_new_document", json!({"type": "part"}));+    check!(+        b,+        "swx_new_document: host_app_died, with the pid and the ledger line — never ok",+        r["success"] == false && r["errorCode"] == "host_app_died" && r["processId"].is_i64() && r["ledger"] == "host_app_died",+        s(&r)+    );+    let l = ledger(&b);+    check!(+        b,+        "...the ledger records the death, and NO document_created",+        l.iter().any(|e| e["action"] == "host_app_died" && e["detail"]["verb"] == "swx_new_document")+            && !l.iter().any(|e| e["action"] == "document_created"),+        s(&json!(l))+    );++    // A reply that names a document SOLIDWORKS does not have.+    let scratch2 = TempDir::new("restart-vanish");+    session(&scratch2);+    let b2 = Bridge::start_in(TempDir::borrowed(&scratch2.0), &[]);+    b2.call("swx_start", json!({}));+    // Another document is open, so the count alone cannot tell.+    let other = b2.call("swx_new_document", json!({"type": "part"}));+    check!(b2, "a first, real document", other["success"] == true, s(&other));+    std::fs::write(scratch2.join("mock-newdoc-vanishes"), "").unwrap();+    let r = b2.call("swx_new_document", json!({"type": "part", "keepUnsaved": true}));+    check!(+        b2,+        "a document missing from the live list: document_not_created, never ok",+        r["success"] == false && r["errorCode"] == "document_not_created",+        s(&r)+    );+    std::fs::remove_file(scratch2.join("mock-newdoc-vanishes")).unwrap();+    let ok = b2.call("swx_new_document", json!({"type": "part"}));+    check!(b2, "...and a real document reports the effect it verified", ok["success"] == true && ok["effect"]["verified"] == true, s(&ok));+}++#[test]+fn a_start_right_after_a_quit_waits_for_the_quit_sessions_process_tree() {+    let m = TempDir::new("restart-quit");+    std::fs::write(m.join("quit-script.json"), json!({"a": "exited"}).to_string()).unwrap();+    std::fs::write(m.join("windows.json"), "[]").unwrap();+    std::fs::write(m.join("sldworks.json"), json!({"responding": true, "hwnd": 6622700, "privateMB": 900, "handles": 4000}).to_string()).unwrap();+    // sldProcMon outlives the quit by 1.5 s; the platform daemons survive it+    // by design and must never be waited for.+    std::fs::write(+        m.join("preexisting.json"),+        json!([+            {"pid": 6076, "image": "3DEXPERIENCELauncher.exe", "ageSeconds": 30000},+            {"pid": 701, "image": "ENOPLMCSAClient.exe", "ageSeconds": 30000},+            {"pid": 800, "image": "sldProcMon.exe", "ageSeconds": 500, "reapedAfterQuitMs": 1500}+        ])+        .to_string(),+    )+    .unwrap();+    let b = Bridge::start_in(+        TempDir::new("restart-quit-scratch"),+        &[+            ("SWX_LAUNCH_FAKE_DIR", &m.path()),+            ("SWX_ALLOW_USER_WRITES", "1"),+            ("SWX_QUIT_SETTLE_MS", "80"),+            ("SWX_QUIT_EXIT_WAIT_SECS", "3"),+        ],+    );+    b.call("swx_start", json!({}));+    let st = b.call("swx_stop", json!({"userAuthorized": true, "confirm": true, "reason": "test: restart", "maxRung": "a"}));+    check!(b, "the quit goes through", st["stopped"] == true, s(&st));+    let r = b.call("swx_start", json!({}));+    let w = r["waitedForPreviousExit"].clone();+    check!(+        b,+        "the start right after it WAITED for the quit session's sldProcMon — not for the platform daemons",+        w["gone"] == true && w["waitedMs"].as_u64().unwrap_or(0) >= 700+            && !s(&w).contains("ENOPLMCSAClient") && !s(&w).contains("3DEXPERIENCELauncher"),+        s(&r)+    );+    check!(+        b,+        "...ledgered as launch_waited_for_previous_exit",+        ledger(&b).iter().any(|e| e["action"] == "launch_waited_for_previous_exit" && e["detail"]["gone"] == true),+        s(&json!(ledger(&b)))+    );+}
tools/cswa/reports/cswa-2026-10-15-sw2026-0.11.2.jsonadded+4571
@@ -0,0 +1,4571 @@+{+ "tool": "cswa-check",+ "when": "2026-10-15T23:04:22Z",+ "whenEpoch": 1792105462,+ "target": "adom_drew2",+ "bridgeVersion": "0.11.2",+ "solidworks": {+  "majorVersion": 34,+  "edition": "connected",+  "versionSupport": {+   "lacks": [],+   "majorVersion": 34,+   "revision": "34.3.0",+   "supported": true,+   "supportedFrom": 2021,+   "tested": true,+   "testedOn": [+    2026,+    2021+   ],+   "year": 2026+  }+ },+ "summary": "8 of 8 CSWA parts within tolerance",+ "passed": 8,+ "ran": 8,+ "skipped": 1,+ "stopped": null,+ "allPassed": true,+ "parts": [+  {+   "id": "cswa-00-lego-2x4",+   "title": "LEGO 2x4 brick (spec 0: the acceptance brick, not an exam part)",+   "official": false,+   "source": "adom/solidworks-bridge issue #1 (Michael, SOLIDWORKS 2021: volumeM3 2.0733615208e-6 from swx_mass_properties); examples/lego-2x4.json",+   "expected": {+    "massG": 2.114829,+    "volumeMm3": 2073.3615208,+    "tolerancePct": 1.0+   },+   "material": {+    "name": "ABS",+    "densityKgM3": 1020+   },+   "runScript": {+    "_hint": "Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.",+    "_timeoutHint": "ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "bridgeCreatedDocument": true,+    "created": null,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "documentName": "Part1-1792105365003.SLDPRT",+    "durationMs": 13690,+    "error": "",+    "ops": [+     "new_part",+     "new_assembly",+     "clear_part",+     "sketch",+     "sketch_rect",+     "sketch_circle",+     "extrude",+     "cut",+     "set_material",+     "set_appearance",+     "fillet",+     "chamfer",+     "shell",+     "revolve",+     "revolve_cut",+     "mirror",+     "hole",+     "linear_pattern",+     "circular_pattern",+     "set_prop",+     "save_as",+     "rebuild",+     "zoom_fit"+    ],+    "output": "{\"_hint\":\"Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.\",\"_timeoutHint\":\"ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"bridgeCreatedDocument\":true,\"created\":null,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"documentName\":\"Part1-1792105365003.SLDPRT\",\"ops\":[\"new_part\",\"new_assembly\",\"clear_part\",\"sketch\",\"sketch_rect\",\"sketch_circle\",\"extrude\",\"cut\",\"set_material\",\"set_appearance\",\"fillet\",\"chamfer\",\"shell\",\"revolve\",\"revolve_cut\",\"mirror\",\"hole\",\"linear_pattern\",\"circular_pattern\",\"set_prop\",\"save_as\",\"rebuild\",\"zoom_fit\"],\"progress\":{\"confidence\":\"estimate\",\"elapsedSec\":12.2,\"estimatedSec\":30,\"etaSec\":0,\"percent\":100,\"phase\":\"run_script\",\"startKind\":\"warm\",\"stepLabel\":\"Running 10 modeling step(s)\"},\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"solidworksRevision\":\"34.3.0\",\"statusVerb\":\"swx_status\",\"stepCount\":10,\"steps\":[{\"op\":\"clear_part\",\"result\":{\"bodiesLeft\":0,\"cleared\":\"Part1-1792105365003.SLDPRT\",\"deleted\":[],\"featuresDeleted\":0,\"passes\":0,\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.6\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"clear_part\"]},\"route\":\"DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty\"},\"step\":1},{\"op\":\"sketch_rect\",\"result\":{\"createdPlane\":null,\"entities\":[{\"rect\":{\"cornersMm\":[[-15.9,-7.9],[15.9,7.9]]}}],\"heightMm\":15.8,\"mapped\":false,\"plane\":\"Top Plane\",\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"sketch.plane.top\",\"sketch.rect\"]},\"resolvedPlane\":null,\"sketch\":\"Sketch1\",\"sketchNormal\":[0.0,1.0,0.0],\"sketchedOn\":\"Top Plane\",\"transformInverted\":false,\"widthMm\":31.8},\"step\":2},{\"op\":\"extrude\",\"result\":{\"depth2Mm\":null,\"depthMm\":9.6,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":null,\"sketchNormal\":[0.0,1.0,0.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Boss-Extrude1\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"extrude.one\"]},\"reverse\":false,\"sketch\":\"Sketch1\",\"throughAll\":false,\"upToFace\":null},\"step\":3},{\"op\":\"sketch_rect\",\"result\":{\"createdPlane\":null,\"entities\":[{\"rect\":{\"cornersMm\":[[-14.7,-6.7],[14.7,6.7]]}}],\"heightMm\":13.4,\"mapped\":false,\"plane\":\"Top Plane\",\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"sketch.plane.top\",\"sketch.rect\"]},\"resolvedPlane\":null,\"sketch\":\"Sketch2\",\"sketchNormal\":[0.0,1.0,0.0],\"sketchedOn\":\"Top Plane\",\"transformInverted\":false,\"widthMm\":29.4},\"step\":4},{\"op\":\"cut\",\"result\":{\"depth2Mm\":null,\"depthMm\":8.6,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":null,\"sketchNormal\":[0.0,1.0,0.0],\"value\":true},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Cut-Extrude1\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"cut.one.reversed\"]},\"reverse\":true,\"sketch\":\"Sketch2\",\"throughAll\":false,\"upToFace\":null},\"step\":5},{\"op\":\"sketch\",\"result\":{\"createdPlane\":null,\"entities\":[{\"circle\":{\"centerMm\":[-8.0,0.0],\"radiusMm\":3.255}},{\"circle\":{\"centerMm\":[-8.0,0.0],\"radiusMm\":2.4}},{\"circle\":{\"centerMm\":[0.0,0.0],\"radiusMm\":3.255}},{\"circle\":{\"centerMm\":[0.0,0.0],\"radiusMm\":2.4}},{\"circle\":{\"centerMm\":[8.0,0.0],\"radiusMm\":3.255}},{\"circle\":{\"centerMm\":[8.0,0.0],\"radiusMm\":2.4}}],\"mapped\":false,\"plane\":\"Top Plane\",\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"sketch.plane.top\",\"sketch.circle\",\"sketch.multiProfile\"]},\"resolvedPlane\":null,\"sketch\":\"Sketch3\",\"sketchNormal\":[0.0,1.0,0.0],\"sketchedOn\":\"Top Plane\",\"transformInverted\":false},\"step\":6},{\"op\":\"extrude\",\"result\":{\"depth2Mm\":null,\"depthMm\":8.6,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":null,\"sketchNormal\":[0.0,1.0,0.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Boss-Extrude2\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"extrude.one\"]},\"reverse\":false,\"sketch\":\"Sketch3\",\"throughAll\":false,\"upToFace\":null},\"step\":7},{\"op\":\"sketch\",\"result\":{\"createdPlane\":\"Plane1\",\"entities\":[{\"circle\":{\"centerMm\":[-12.0,-4.0],\"radiusMm\":2.4}},{\"circle\":{\"centerMm\":[-12.0,4.0],\"radiusMm\":2.4}},{\"circle\":{\"centerMm\":[-4.0,-4.0],\"radiusMm\":2.4}},{\"circle\":{\"centerMm\":[-4.0,4.0],\"radiusMm\":2.4}},{\"circle\":{\"centerMm\":[4.0,-4.0],\"radiusMm\":2.4}},{\"circle\":{\"centerMm\":[4.0,4.0],\"radiusMm\":2.4}},{\"circle\":{\"centerMm\":[12.0,-4.0],\"radiusMm\":2.4}},{\"circle\":{\"centerMm\":[12.0,4.0],\"radiusMm\":2.4}}],\"mapped\":true,\"plane\":{\"offsetFrom\":\"Top Plane\",\"offsetMm\":9.6},\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"sketch.offset.top.positive\",\"sketch.circle\",\"sketch.multiProfile\"]},\"resolvedPlane\":{\"offsetFrom\":\"Top Plane\",\"offsetMm\":9.6,\"plane\":\"Plane1\",\"verified\":true},\"sketch\":\"Sketch4\",\"sketchNormal\":[0.0,1.0,0.0],\"sketchedOn\":\"Plane1\",\"transformInverted\":false},\"step\":8},{\"op\":\"extrude\",\"result\":{\"depth2Mm\":null,\"depthMm\":1.7,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":[0.0,1.0,0.0],\"sketchNormal\":[0.0,1.0,0.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Boss-Extrude3\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"extrude.one\"]},\"reverse\":false,\"sketch\":\"Sketch4\",\"throughAll\":false,\"upToFace\":null},\"step\":9},{\"op\":\"set_material\",\"result\":{\"appearanceReapplied\":[],\"current\":{\"database\":\"SOLIDWORKS Materials\",\"name\":\"ABS\"},\"database\":\"SOLIDWORKS Materials.sldmat\",\"densityKgM3\":1020.0,\"densityRequested\":1020.0,\"material\":\"ABS\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"set_material.density\",\"what\":\"a density in kg/m\u00b3 (the document's own, or checked against the material's)\"}],\"variants\":[\"set_material\",\"set_material.density\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"}},\"step\":10}],\"success\":true,\"targetDocument\":\"Part1-1792105365003.SLDPRT\",\"timeoutSeconds\":420}",+    "progress": {+     "confidence": "estimate",+     "elapsedSec": 12.2,+     "estimatedSec": 30,+     "etaSec": 0,+     "percent": 100,+     "phase": "run_script",+     "startKind": "warm",+     "stepLabel": "Running 10 modeling step(s)"+    },+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "solidworksRevision": "34.3.0",+    "status": "ok",+    "statusVerb": "swx_status",+    "stepCount": 10,+    "steps": [+     {+      "op": "clear_part",+      "result": {+       "bodiesLeft": 0,+       "cleared": "Part1-1792105365003.SLDPRT",+       "deleted": [],+       "featuresDeleted": 0,+       "passes": 0,+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.6",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "clear_part"+        ]+       },+       "route": "DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty"+      },+      "step": 1+     },+     {+      "op": "sketch_rect",+      "result": {+       "createdPlane": null,+       "entities": [+        {+         "rect": {+          "cornersMm": [+           [+            -15.9,+            -7.9+           ],+           [+            15.9,+            7.9+           ]+          ]+         }+        }+       ],+       "heightMm": 15.8,+       "mapped": false,+       "plane": "Top Plane",+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "sketch.plane.top",+         "sketch.rect"+        ]+       },+       "resolvedPlane": null,+       "sketch": "Sketch1",+       "sketchNormal": [+        0.0,+        1.0,+        0.0+       ],+       "sketchedOn": "Top Plane",+       "transformInverted": false,+       "widthMm": 31.8+      },+      "step": 2+     },+     {+      "op": "extrude",+      "result": {+       "depth2Mm": null,+       "depthMm": 9.6,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": null,+        "sketchNormal": [+         0.0,+         1.0,+         0.0+        ],+        "value": false+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Boss-Extrude1",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "extrude.one"+        ]+       },+       "reverse": false,+       "sketch": "Sketch1",+       "throughAll": false,+       "upToFace": null+      },+      "step": 3+     },+     {+      "op": "sketch_rect",+      "result": {+       "createdPlane": null,+       "entities": [+        {+         "rect": {+          "cornersMm": [+           [+            -14.7,+            -6.7+           ],+           [+            14.7,+            6.7+           ]+          ]+         }+        }+       ],+       "heightMm": 13.4,+       "mapped": false,+       "plane": "Top Plane",+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "sketch.plane.top",+         "sketch.rect"+        ]+       },+       "resolvedPlane": null,+       "sketch": "Sketch2",+       "sketchNormal": [+        0.0,+        1.0,+        0.0+       ],+       "sketchedOn": "Top Plane",+       "transformInverted": false,+       "widthMm": 29.4+      },+      "step": 4+     },+     {+      "op": "cut",+      "result": {+       "depth2Mm": null,+       "depthMm": 8.6,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": null,+        "sketchNormal": [+         0.0,+         1.0,+         0.0+        ],+        "value": true+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Cut-Extrude1",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "cut.one.reversed"+        ]+       },+       "reverse": true,+       "sketch": "Sketch2",+       "throughAll": false,+       "upToFace": null+      },+      "step": 5+     },+     {+      "op": "sketch",+      "result": {+       "createdPlane": null,+       "entities": [+        {+         "circle": {+          "centerMm": [+           -8.0,+           0.0+          ],+          "radiusMm": 3.255+         }+        },+        {+         "circle": {+          "centerMm": [+           -8.0,+           0.0+          ],+          "radiusMm": 2.4+         }+        },+        {+         "circle": {+          "centerMm": [+           0.0,+           0.0+          ],+          "radiusMm": 3.255+         }+        },+        {+         "circle": {+          "centerMm": [+           0.0,+           0.0+          ],+          "radiusMm": 2.4+         }+        },+        {+         "circle": {+          "centerMm": [+           8.0,+           0.0+          ],+          "radiusMm": 3.255+         }+        },+        {+         "circle": {+          "centerMm": [+           8.0,+           0.0+          ],+          "radiusMm": 2.4+         }+        }+       ],+       "mapped": false,+       "plane": "Top Plane",+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "sketch.plane.top",+         "sketch.circle",+         "sketch.multiProfile"+        ]+       },+       "resolvedPlane": null,+       "sketch": "Sketch3",+       "sketchNormal": [+        0.0,+        1.0,+        0.0+       ],+       "sketchedOn": "Top Plane",+       "transformInverted": false+      },+      "step": 6+     },+     {+      "op": "extrude",+      "result": {+       "depth2Mm": null,+       "depthMm": 8.6,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": null,+        "sketchNormal": [+         0.0,+         1.0,+         0.0+        ],+        "value": false+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Boss-Extrude2",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "extrude.one"+        ]+       },+       "reverse": false,+       "sketch": "Sketch3",+       "throughAll": false,+       "upToFace": null+      },+      "step": 7+     },+     {+      "op": "sketch",+      "result": {+       "createdPlane": "Plane1",+       "entities": [+        {+         "circle": {+          "centerMm": [+           -12.0,+           -4.0+          ],+          "radiusMm": 2.4+         }+        },+        {+         "circle": {+          "centerMm": [+           -12.0,+           4.0+          ],+          "radiusMm": 2.4+         }+        },+        {+         "circle": {+          "centerMm": [+           -4.0,+           -4.0+          ],+          "radiusMm": 2.4+         }+        },+        {+         "circle": {+          "centerMm": [+           -4.0,+           4.0+          ],+          "radiusMm": 2.4+         }+        },+        {+         "circle": {+          "centerMm": [+           4.0,+           -4.0+          ],+          "radiusMm": 2.4+         }+        },+        {+         "circle": {+          "centerMm": [+           4.0,+           4.0+          ],+          "radiusMm": 2.4+         }+        },+        {+         "circle": {+          "centerMm": [+           12.0,+           -4.0+          ],+          "radiusMm": 2.4+         }+        },+        {+         "circle": {+          "centerMm": [+           12.0,+           4.0+          ],+          "radiusMm": 2.4+         }+        }+       ],+       "mapped": true,+       "plane": {+        "offsetFrom": "Top Plane",+        "offsetMm": 9.6+       },+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "sketch.offset.top.positive",+         "sketch.circle",+         "sketch.multiProfile"+        ]+       },+       "resolvedPlane": {+        "offsetFrom": "Top Plane",+        "offsetMm": 9.6,+        "plane": "Plane1",+        "verified": true+       },+       "sketch": "Sketch4",+       "sketchNormal": [+        0.0,+        1.0,+        0.0+       ],+       "sketchedOn": "Plane1",+       "transformInverted": false+      },+      "step": 8+     },+     {+      "op": "extrude",+      "result": {+       "depth2Mm": null,+       "depthMm": 1.7,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": [+         0.0,+         1.0,+         0.0+        ],+        "sketchNormal": [+         0.0,+         1.0,+         0.0+        ],+        "value": false+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Boss-Extrude3",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "extrude.one"+        ]+       },+       "reverse": false,+       "sketch": "Sketch4",+       "throughAll": false,+       "upToFace": null+      },+      "step": 9+     },+     {+      "op": "set_material",+      "result": {+       "appearanceReapplied": [],+       "current": {+        "database": "SOLIDWORKS Materials",+        "name": "ABS"+       },+       "database": "SOLIDWORKS Materials.sldmat",+       "densityKgM3": 1020.0,+       "densityRequested": 1020.0,+       "material": "ABS",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "set_material.density",+          "what": "a density in kg/m\u00b3 (the document's own, or checked against the material's)"+         }+        ],+        "variants": [+         "set_material",+         "set_material.density"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       }+      },+      "step": 10+     }+    ],+    "success": true,+    "targetDocument": "Part1-1792105365003.SLDPRT",+    "timeoutSeconds": 420+   },+   "massProperties": {+    "_hint": "SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.",+    "_timeoutHint": "ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "boundingBox": [+     -0.0159,+     0.0,+     -0.0079,+     0.0159,+     0.0113,+     0.0079+    ],+    "centerOfMass": [+     3.4214491115036863e-19,+     0.006193169977140961,+     -1.994781431613623e-19+    ],+    "centerOfMassMm": [+     0.0,+     6.19317,+     -0.0+    ],+    "density": 1020.0,+    "densityKgM3": 1020.0,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "durationMs": 1047,+    "error": "",+    "massG": 2.114828751242137,+    "massKg": 0.002114828751242137,+    "materialName": "ABS",+    "output": "{\"_hint\":\"SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.\",\"_timeoutHint\":\"ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"boundingBox\":[-0.0159,0.0,-0.0079,0.0159,0.0113,0.0079],\"centerOfMass\":[3.4214491115036863e-19,0.006193169977140961,-1.994781431613623e-19],\"centerOfMassMm\":[0.0,6.19317,-0.0],\"density\":1020.0,\"densityKgM3\":1020.0,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"massG\":2.114828751242137,\"massKg\":0.002114828751242137,\"materialName\":\"ABS\",\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"statusVerb\":\"swx_status\",\"success\":true,\"surfaceAreaM2\":0.003776753621558533,\"surfaceAreaMm2\":3776.753621558533,\"timeoutSeconds\":120,\"volumeM3\":2.0733615208256247e-6,\"volumeMm3\":2073.3615208256247}",+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "status": "ok",+    "statusVerb": "swx_status",+    "success": true,+    "surfaceAreaM2": 0.003776753621558533,+    "surfaceAreaMm2": 3776.753621558533,+    "timeoutSeconds": 120,+    "volumeM3": 2.0733615208256247e-06,+    "volumeMm3": 2073.3615208256247+   },+   "pass": true,+   "checks": [+    {+     "quantity": "massG",+     "expected": 2.114829,+     "measured": 2.114828751242137,+     "offPct": 1.1762552090642981e-05,+     "pass": true+    },+    {+     "quantity": "volumeMm3",+     "expected": 2073.3615208,+     "measured": 2073.3615208256247,+     "offPct": 1.2358943781890103e-09,+     "pass": true+    }+   ],+   "fails": [],+   "seconds": 14.7+  },+  {+   "id": "cswa-01-3dengr-q5-block",+   "title": "3dengr Q5: a 100 x 20 x 60 block in 6061",+   "official": false,+   "source": "https://www.3dengr.com/cswa-practice-questions.html",+   "expected": {+    "massG": 324.0,+    "volumeMm3": 120000.0,+    "centerOfMassMm": [+     50.0,+     10.0,+     30.0+    ],+    "tolerancePct": 1.0+   },+   "material": {+    "name": "6061 Alloy",+    "densityKgM3": 2700+   },+   "runScript": {+    "_hint": "Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.",+    "_timeoutHint": "ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "bridgeCreatedDocument": true,+    "created": null,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "documentName": "Part1-1792105365003.SLDPRT",+    "durationMs": 8044,+    "error": "",+    "ops": [+     "new_part",+     "new_assembly",+     "clear_part",+     "sketch",+     "sketch_rect",+     "sketch_circle",+     "extrude",+     "cut",+     "set_material",+     "set_appearance",+     "fillet",+     "chamfer",+     "shell",+     "revolve",+     "revolve_cut",+     "mirror",+     "hole",+     "linear_pattern",+     "circular_pattern",+     "set_prop",+     "save_as",+     "rebuild",+     "zoom_fit"+    ],+    "output": "{\"_hint\":\"Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.\",\"_timeoutHint\":\"ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"bridgeCreatedDocument\":true,\"created\":null,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"documentName\":\"Part1-1792105365003.SLDPRT\",\"ops\":[\"new_part\",\"new_assembly\",\"clear_part\",\"sketch\",\"sketch_rect\",\"sketch_circle\",\"extrude\",\"cut\",\"set_material\",\"set_appearance\",\"fillet\",\"chamfer\",\"shell\",\"revolve\",\"revolve_cut\",\"mirror\",\"hole\",\"linear_pattern\",\"circular_pattern\",\"set_prop\",\"save_as\",\"rebuild\",\"zoom_fit\"],\"progress\":{\"confidence\":\"estimate\",\"elapsedSec\":6.5,\"estimatedSec\":30,\"etaSec\":0,\"percent\":100,\"phase\":\"run_script\",\"startKind\":\"warm\",\"stepLabel\":\"Running 4 modeling step(s)\"},\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"solidworksRevision\":\"34.3.0\",\"statusVerb\":\"swx_status\",\"stepCount\":4,\"steps\":[{\"op\":\"clear_part\",\"result\":{\"bodiesLeft\":0,\"cleared\":\"Part1-1792105365003.SLDPRT\",\"deleted\":[\"Sketch1\",\"Boss-Extrude1\",\"Cut-Extrude1\",\"Boss-Extrude2\",\"Plane1\",\"Sketch4\",\"Boss-Extrude3\",\"Sketch2\",\"Sketch3\"],\"featuresDeleted\":9,\"passes\":2,\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.6\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"clear_part\"]},\"route\":\"DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty\"},\"step\":1},{\"op\":\"sketch_rect\",\"result\":{\"createdPlane\":null,\"entities\":[{\"rect\":{\"cornersMm\":[[0.0,0.0],[100.0,20.0]]}}],\"heightMm\":20.0,\"mapped\":false,\"plane\":\"Front Plane\",\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"sketch.plane.front\",\"sketch.rect\"]},\"resolvedPlane\":null,\"sketch\":\"Sketch5\",\"sketchNormal\":[0.0,0.0,1.0],\"sketchedOn\":\"Front Plane\",\"transformInverted\":false,\"widthMm\":100.0},\"step\":2},{\"op\":\"extrude\",\"result\":{\"depth2Mm\":null,\"depthMm\":60.0,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":null,\"sketchNormal\":[0.0,0.0,1.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Boss-Extrude4\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"extrude.one\"]},\"reverse\":false,\"sketch\":\"Sketch5\",\"throughAll\":false,\"upToFace\":null},\"step\":3},{\"op\":\"set_material\",\"result\":{\"appearanceReapplied\":[],\"current\":{\"database\":\"SOLIDWORKS Materials\",\"name\":\"6061 Alloy\"},\"database\":\"SOLIDWORKS Materials.sldmat\",\"densityKgM3\":2700.0,\"densityRequested\":2700.0,\"material\":\"6061 Alloy\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"set_material.density\",\"what\":\"a density in kg/m\u00b3 (the document's own, or checked against the material's)\"}],\"variants\":[\"set_material\",\"set_material.density\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"}},\"step\":4}],\"success\":true,\"targetDocument\":\"Part1-1792105365003.SLDPRT\",\"timeoutSeconds\":420}",+    "progress": {+     "confidence": "estimate",+     "elapsedSec": 6.5,+     "estimatedSec": 30,+     "etaSec": 0,+     "percent": 100,+     "phase": "run_script",+     "startKind": "warm",+     "stepLabel": "Running 4 modeling step(s)"+    },+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "solidworksRevision": "34.3.0",+    "status": "ok",+    "statusVerb": "swx_status",+    "stepCount": 4,+    "steps": [+     {+      "op": "clear_part",+      "result": {+       "bodiesLeft": 0,+       "cleared": "Part1-1792105365003.SLDPRT",+       "deleted": [+        "Sketch1",+        "Boss-Extrude1",+        "Cut-Extrude1",+        "Boss-Extrude2",+        "Plane1",+        "Sketch4",+        "Boss-Extrude3",+        "Sketch2",+        "Sketch3"+       ],+       "featuresDeleted": 9,+       "passes": 2,+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.6",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "clear_part"+        ]+       },+       "route": "DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty"+      },+      "step": 1+     },+     {+      "op": "sketch_rect",+      "result": {+       "createdPlane": null,+       "entities": [+        {+         "rect": {+          "cornersMm": [+           [+            0.0,+            0.0+           ],+           [+            100.0,+            20.0+           ]+          ]+         }+        }+       ],+       "heightMm": 20.0,+       "mapped": false,+       "plane": "Front Plane",+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "sketch.plane.front",+         "sketch.rect"+        ]+       },+       "resolvedPlane": null,+       "sketch": "Sketch5",+       "sketchNormal": [+        0.0,+        0.0,+        1.0+       ],+       "sketchedOn": "Front Plane",+       "transformInverted": false,+       "widthMm": 100.0+      },+      "step": 2+     },+     {+      "op": "extrude",+      "result": {+       "depth2Mm": null,+       "depthMm": 60.0,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": null,+        "sketchNormal": [+         0.0,+         0.0,+         1.0+        ],+        "value": false+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Boss-Extrude4",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "extrude.one"+        ]+       },+       "reverse": false,+       "sketch": "Sketch5",+       "throughAll": false,+       "upToFace": null+      },+      "step": 3+     },+     {+      "op": "set_material",+      "result": {+       "appearanceReapplied": [],+       "current": {+        "database": "SOLIDWORKS Materials",+        "name": "6061 Alloy"+       },+       "database": "SOLIDWORKS Materials.sldmat",+       "densityKgM3": 2700.0,+       "densityRequested": 2700.0,+       "material": "6061 Alloy",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "set_material.density",+          "what": "a density in kg/m\u00b3 (the document's own, or checked against the material's)"+         }+        ],+        "variants": [+         "set_material",+         "set_material.density"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       }+      },+      "step": 4+     }+    ],+    "success": true,+    "targetDocument": "Part1-1792105365003.SLDPRT",+    "timeoutSeconds": 420+   },+   "massProperties": {+    "_hint": "SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.",+    "_timeoutHint": "ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "boundingBox": [+     0.0,+     0.0,+     0.0,+     0.1,+     0.02,+     0.06+    ],+    "centerOfMass": [+     0.05,+     0.01,+     0.03+    ],+    "centerOfMassMm": [+     50.0,+     10.0,+     30.0+    ],+    "density": 2700.0,+    "densityKgM3": 2700.0,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "durationMs": 1377,+    "error": "",+    "massG": 323.99999999999994,+    "massKg": 0.32399999999999995,+    "materialName": "6061 Alloy",+    "output": "{\"_hint\":\"SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.\",\"_timeoutHint\":\"ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"boundingBox\":[0.0,0.0,0.0,0.1,0.02,0.06],\"centerOfMass\":[0.05,0.01,0.03],\"centerOfMassMm\":[50.0,10.0,30.0],\"density\":2700.0,\"densityKgM3\":2700.0,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"massG\":323.99999999999994,\"massKg\":0.32399999999999995,\"materialName\":\"6061 Alloy\",\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"statusVerb\":\"swx_status\",\"success\":true,\"surfaceAreaM2\":0.0184,\"surfaceAreaMm2\":18400.0,\"timeoutSeconds\":120,\"volumeM3\":0.00012,\"volumeMm3\":120000.0}",+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "status": "ok",+    "statusVerb": "swx_status",+    "success": true,+    "surfaceAreaM2": 0.0184,+    "surfaceAreaMm2": 18400.0,+    "timeoutSeconds": 120,+    "volumeM3": 0.00012,+    "volumeMm3": 120000.0+   },+   "pass": true,+   "checks": [+    {+     "quantity": "massG",+     "expected": 324.0,+     "measured": 323.99999999999994,+     "offPct": 1.75442650804963e-14,+     "pass": true+    },+    {+     "quantity": "volumeMm3",+     "expected": 120000.0,+     "measured": 120000.0,+     "offPct": 0.0,+     "pass": true+    },+    {+     "quantity": "centerOfMassMm",+     "expected": [+      50.0,+      10.0,+      30.0+     ],+     "measured": [+      50.0,+      10.0,+      30.0+     ],+     "pass": true+    }+   ],+   "fails": [],+   "seconds": 9.4+  },+  {+   "id": "cswa-02-3dengr-q6-hole",+   "title": "3dengr Q6/Q7: the block with a \u00d820 hole through it along Y at X 25, Z 30",+   "official": false,+   "source": "https://www.3dengr.com/cswa-practice-questions.html",+   "expected": {+    "massG": 307.04,+    "centerOfMassMm": [+     51.38,+     10.0,+     30.0+    ],+    "tolerancePct": 1.0+   },+   "material": {+    "name": "6061 Alloy",+    "densityKgM3": 2700+   },+   "runScript": {+    "_hint": "Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.",+    "_timeoutHint": "ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "bridgeCreatedDocument": true,+    "created": null,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "documentName": "Part1-1792105365003.SLDPRT",+    "durationMs": 10254,+    "error": "",+    "ops": [+     "new_part",+     "new_assembly",+     "clear_part",+     "sketch",+     "sketch_rect",+     "sketch_circle",+     "extrude",+     "cut",+     "set_material",+     "set_appearance",+     "fillet",+     "chamfer",+     "shell",+     "revolve",+     "revolve_cut",+     "mirror",+     "hole",+     "linear_pattern",+     "circular_pattern",+     "set_prop",+     "save_as",+     "rebuild",+     "zoom_fit"+    ],+    "output": "{\"_hint\":\"Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.\",\"_timeoutHint\":\"ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"bridgeCreatedDocument\":true,\"created\":null,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"documentName\":\"Part1-1792105365003.SLDPRT\",\"ops\":[\"new_part\",\"new_assembly\",\"clear_part\",\"sketch\",\"sketch_rect\",\"sketch_circle\",\"extrude\",\"cut\",\"set_material\",\"set_appearance\",\"fillet\",\"chamfer\",\"shell\",\"revolve\",\"revolve_cut\",\"mirror\",\"hole\",\"linear_pattern\",\"circular_pattern\",\"set_prop\",\"save_as\",\"rebuild\",\"zoom_fit\"],\"progress\":{\"confidence\":\"estimate\",\"elapsedSec\":8.2,\"estimatedSec\":30,\"etaSec\":0,\"percent\":100,\"phase\":\"run_script\",\"startKind\":\"warm\",\"stepLabel\":\"Running 5 modeling step(s)\"},\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"solidworksRevision\":\"34.3.0\",\"statusVerb\":\"swx_status\",\"stepCount\":5,\"steps\":[{\"op\":\"clear_part\",\"result\":{\"bodiesLeft\":0,\"cleared\":\"Part1-1792105365003.SLDPRT\",\"deleted\":[\"Sketch5\",\"Boss-Extrude4\"],\"featuresDeleted\":2,\"passes\":1,\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.6\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"clear_part\"]},\"route\":\"DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty\"},\"step\":1},{\"op\":\"sketch_rect\",\"result\":{\"createdPlane\":null,\"entities\":[{\"rect\":{\"cornersMm\":[[0.0,0.0],[100.0,20.0]]}}],\"heightMm\":20.0,\"mapped\":false,\"plane\":\"Front Plane\",\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"sketch.plane.front\",\"sketch.rect\"]},\"resolvedPlane\":null,\"sketch\":\"Sketch6\",\"sketchNormal\":[0.0,0.0,1.0],\"sketchedOn\":\"Front Plane\",\"transformInverted\":false,\"widthMm\":100.0},\"step\":2},{\"op\":\"extrude\",\"result\":{\"depth2Mm\":null,\"depthMm\":60.0,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":null,\"sketchNormal\":[0.0,0.0,1.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Boss-Extrude5\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"extrude.one\"]},\"reverse\":false,\"sketch\":\"Sketch6\",\"throughAll\":false,\"upToFace\":null},\"step\":3},{\"op\":\"hole\",\"result\":{\"depthMm\":null,\"diameterMm\":20.0,\"face\":{\"atPointMm\":[25.0,20.0,30.0],\"heightMm\":20.0,\"normal\":[-0.0,1.0,-0.0],\"pickedBy\":\"geometry\",\"plane\":\"Top Plane\"},\"feature\":\"Cut-Extrude2\",\"features\":[\"Cut-Extrude2\"],\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"hole.simple\",\"what\":\"a plain hole: a circle on the face's plane, cut blind or through all\"}],\"variants\":[\"hole.simple\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"},\"steps\":[{\"op\":\"sketch\",\"result\":{\"createdPlane\":\"Plane2\",\"entities\":[{\"circle\":{\"centerMm\":[25.0,-30.0],\"radiusMm\":10.0}}],\"mapped\":true,\"plane\":{\"offsetFrom\":\"Top Plane\",\"offsetMm\":20.0},\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"radiusMm\":10.0,\"resolvedPlane\":{\"offsetFrom\":\"Top Plane\",\"offsetMm\":20.0,\"plane\":\"Plane2\",\"verified\":true},\"sketch\":\"Sketch7\",\"sketchNormal\":[0.0,1.0,0.0],\"sketchedOn\":\"Plane2\",\"transformInverted\":false}},{\"op\":\"cut\",\"result\":{\"depth2Mm\":null,\"depthMm\":0.0,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":[0.0,1.0,0.0],\"sketchNormal\":[0.0,1.0,0.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":1,\"feature\":\"Cut-Extrude2\",\"reverse\":false,\"sketch\":\"Sketch7\",\"throughAll\":true,\"upToFace\":null}}],\"throughAll\":true},\"step\":4},{\"op\":\"set_material\",\"result\":{\"appearanceReapplied\":[],\"current\":{\"database\":\"SOLIDWORKS Materials\",\"name\":\"6061 Alloy\"},\"database\":\"SOLIDWORKS Materials.sldmat\",\"densityKgM3\":2700.0,\"densityRequested\":2700.0,\"material\":\"6061 Alloy\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"set_material.density\",\"what\":\"a density in kg/m\u00b3 (the document's own, or checked against the material's)\"}],\"variants\":[\"set_material\",\"set_material.density\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"}},\"step\":5}],\"success\":true,\"targetDocument\":\"Part1-1792105365003.SLDPRT\",\"timeoutSeconds\":420}",+    "progress": {+     "confidence": "estimate",+     "elapsedSec": 8.2,+     "estimatedSec": 30,+     "etaSec": 0,+     "percent": 100,+     "phase": "run_script",+     "startKind": "warm",+     "stepLabel": "Running 5 modeling step(s)"+    },+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "solidworksRevision": "34.3.0",+    "status": "ok",+    "statusVerb": "swx_status",+    "stepCount": 5,+    "steps": [+     {+      "op": "clear_part",+      "result": {+       "bodiesLeft": 0,+       "cleared": "Part1-1792105365003.SLDPRT",+       "deleted": [+        "Sketch5",+        "Boss-Extrude4"+       ],+       "featuresDeleted": 2,+       "passes": 1,+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.6",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "clear_part"+        ]+       },+       "route": "DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty"+      },+      "step": 1+     },+     {+      "op": "sketch_rect",+      "result": {+       "createdPlane": null,+       "entities": [+        {+         "rect": {+          "cornersMm": [+           [+            0.0,+            0.0+           ],+           [+            100.0,+            20.0+           ]+          ]+         }+        }+       ],+       "heightMm": 20.0,+       "mapped": false,+       "plane": "Front Plane",+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "sketch.plane.front",+         "sketch.rect"+        ]+       },+       "resolvedPlane": null,+       "sketch": "Sketch6",+       "sketchNormal": [+        0.0,+        0.0,+        1.0+       ],+       "sketchedOn": "Front Plane",+       "transformInverted": false,+       "widthMm": 100.0+      },+      "step": 2+     },+     {+      "op": "extrude",+      "result": {+       "depth2Mm": null,+       "depthMm": 60.0,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": null,+        "sketchNormal": [+         0.0,+         0.0,+         1.0+        ],+        "value": false+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Boss-Extrude5",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "extrude.one"+        ]+       },+       "reverse": false,+       "sketch": "Sketch6",+       "throughAll": false,+       "upToFace": null+      },+      "step": 3+     },+     {+      "op": "hole",+      "result": {+       "depthMm": null,+       "diameterMm": 20.0,+       "face": {+        "atPointMm": [+         25.0,+         20.0,+         30.0+        ],+        "heightMm": 20.0,+        "normal": [+         -0.0,+         1.0,+         -0.0+        ],+        "pickedBy": "geometry",+        "plane": "Top Plane"+       },+       "feature": "Cut-Extrude2",+       "features": [+        "Cut-Extrude2"+       ],+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "hole.simple",+          "what": "a plain hole: a circle on the face's plane, cut blind or through all"+         }+        ],+        "variants": [+         "hole.simple"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       },+       "steps": [+        {+         "op": "sketch",+         "result": {+          "createdPlane": "Plane2",+          "entities": [+           {+            "circle": {+             "centerMm": [+              25.0,+              -30.0+             ],+             "radiusMm": 10.0+            }+           }+          ],+          "mapped": true,+          "plane": {+           "offsetFrom": "Top Plane",+           "offsetMm": 20.0+          },+          "planeFrames": "plane transforms (they match the measured Front/Top axes)",+          "radiusMm": 10.0,+          "resolvedPlane": {+           "offsetFrom": "Top Plane",+           "offsetMm": 20.0,+           "plane": "Plane2",+           "verified": true+          },+          "sketch": "Sketch7",+          "sketchNormal": [+           0.0,+           1.0,+           0.0+          ],+          "sketchedOn": "Plane2",+          "transformInverted": false+         }+        },+        {+         "op": "cut",+         "result": {+          "depth2Mm": null,+          "depthMm": 0.0,+          "dir": {+           "flippedToFollowTheReference": false,+           "reference": [+            0.0,+            1.0,+            0.0+           ],+           "sketchNormal": [+            0.0,+            1.0,+            0.0+           ],+           "value": false+          },+          "direction": "one",+          "draftDeg": null,+          "draftInward": null,+          "endCondition": 1,+          "feature": "Cut-Extrude2",+          "reverse": false,+          "sketch": "Sketch7",+          "throughAll": true,+          "upToFace": null+         }+        }+       ],+       "throughAll": true+      },+      "step": 4+     },+     {+      "op": "set_material",+      "result": {+       "appearanceReapplied": [],+       "current": {+        "database": "SOLIDWORKS Materials",+        "name": "6061 Alloy"+       },+       "database": "SOLIDWORKS Materials.sldmat",+       "densityKgM3": 2700.0,+       "densityRequested": 2700.0,+       "material": "6061 Alloy",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "set_material.density",+          "what": "a density in kg/m\u00b3 (the document's own, or checked against the material's)"+         }+        ],+        "variants": [+         "set_material",+         "set_material.density"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       }+      },+      "step": 5+     }+    ],+    "success": true,+    "targetDocument": "Part1-1792105365003.SLDPRT",+    "timeoutSeconds": 420+   },+   "massProperties": {+    "_hint": "SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.",+    "_timeoutHint": "ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "boundingBox": [+     0.0,+     0.0,+     0.0,+     0.1,+     0.02,+     0.06+    ],+    "centerOfMass": [+     0.05138132283342444,+     0.009999999999999998,+     0.029999999999999995+    ],+    "centerOfMassMm": [+     51.381323,+     10.0,+     30.0+    ],+    "density": 2700.0,+    "densityKgM3": 2700.0,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "durationMs": 1759,+    "error": "",+    "massG": 307.0353996706151,+    "massKg": 0.3070353996706151,+    "materialName": "6061 Alloy",+    "output": "{\"_hint\":\"SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.\",\"_timeoutHint\":\"ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"boundingBox\":[0.0,0.0,0.0,0.1,0.02,0.06],\"centerOfMass\":[0.05138132283342444,0.009999999999999998,0.029999999999999995],\"centerOfMassMm\":[51.381323,10.0,30.0],\"density\":2700.0,\"densityKgM3\":2700.0,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"massG\":307.0353996706151,\"massKg\":0.3070353996706151,\"materialName\":\"6061 Alloy\",\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"statusVerb\":\"swx_status\",\"success\":true,\"surfaceAreaM2\":0.01902831853071796,\"surfaceAreaMm2\":19028.31853071796,\"timeoutSeconds\":120,\"volumeM3\":0.0001137168146928204,\"volumeMm3\":113716.8146928204}",+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "status": "ok",+    "statusVerb": "swx_status",+    "success": true,+    "surfaceAreaM2": 0.01902831853071796,+    "surfaceAreaMm2": 19028.31853071796,+    "timeoutSeconds": 120,+    "volumeM3": 0.0001137168146928204,+    "volumeMm3": 113716.8146928204+   },+   "pass": true,+   "checks": [+    {+     "quantity": "massG",+     "expected": 307.04,+     "measured": 307.0353996706151,+     "offPct": 0.0014982834109282007,+     "pass": true+    },+    {+     "quantity": "centerOfMassMm",+     "expected": [+      51.38,+      10.0,+      30.0+     ],+     "measured": [+      51.381323,+      10.0,+      30.0+     ],+     "pass": true+    }+   ],+   "fails": [],+   "seconds": 12.0+  },+  {+   "id": "cswa-03-3dengr-q8-hole30",+   "title": "3dengr Q8: the hole changed to \u00d830",+   "official": false,+   "source": "https://www.3dengr.com/cswa-practice-questions.html",+   "expected": {+    "massG": 285.83,+    "tolerancePct": 1.0+   },+   "material": {+    "name": "6061 Alloy",+    "densityKgM3": 2700+   },+   "runScript": {+    "_hint": "Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.",+    "_timeoutHint": "ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "bridgeCreatedDocument": true,+    "created": null,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "documentName": "Part1-1792105365003.SLDPRT",+    "durationMs": 10687,+    "error": "",+    "ops": [+     "new_part",+     "new_assembly",+     "clear_part",+     "sketch",+     "sketch_rect",+     "sketch_circle",+     "extrude",+     "cut",+     "set_material",+     "set_appearance",+     "fillet",+     "chamfer",+     "shell",+     "revolve",+     "revolve_cut",+     "mirror",+     "hole",+     "linear_pattern",+     "circular_pattern",+     "set_prop",+     "save_as",+     "rebuild",+     "zoom_fit"+    ],+    "output": "{\"_hint\":\"Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.\",\"_timeoutHint\":\"ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"bridgeCreatedDocument\":true,\"created\":null,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"documentName\":\"Part1-1792105365003.SLDPRT\",\"ops\":[\"new_part\",\"new_assembly\",\"clear_part\",\"sketch\",\"sketch_rect\",\"sketch_circle\",\"extrude\",\"cut\",\"set_material\",\"set_appearance\",\"fillet\",\"chamfer\",\"shell\",\"revolve\",\"revolve_cut\",\"mirror\",\"hole\",\"linear_pattern\",\"circular_pattern\",\"set_prop\",\"save_as\",\"rebuild\",\"zoom_fit\"],\"progress\":{\"confidence\":\"estimate\",\"elapsedSec\":8.5,\"estimatedSec\":30,\"etaSec\":0,\"percent\":100,\"phase\":\"run_script\",\"startKind\":\"warm\",\"stepLabel\":\"Running 5 modeling step(s)\"},\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"solidworksRevision\":\"34.3.0\",\"statusVerb\":\"swx_status\",\"stepCount\":5,\"steps\":[{\"op\":\"clear_part\",\"result\":{\"bodiesLeft\":0,\"cleared\":\"Part1-1792105365003.SLDPRT\",\"deleted\":[\"Sketch6\",\"Boss-Extrude5\",\"Plane2\",\"Sketch7\",\"Cut-Extrude2\"],\"featuresDeleted\":5,\"passes\":1,\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.6\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"clear_part\"]},\"route\":\"DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty\"},\"step\":1},{\"op\":\"sketch_rect\",\"result\":{\"createdPlane\":null,\"entities\":[{\"rect\":{\"cornersMm\":[[0.0,0.0],[100.0,20.0]]}}],\"heightMm\":20.0,\"mapped\":false,\"plane\":\"Front Plane\",\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"sketch.plane.front\",\"sketch.rect\"]},\"resolvedPlane\":null,\"sketch\":\"Sketch8\",\"sketchNormal\":[0.0,0.0,1.0],\"sketchedOn\":\"Front Plane\",\"transformInverted\":false,\"widthMm\":100.0},\"step\":2},{\"op\":\"extrude\",\"result\":{\"depth2Mm\":null,\"depthMm\":60.0,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":null,\"sketchNormal\":[0.0,0.0,1.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Boss-Extrude6\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"extrude.one\"]},\"reverse\":false,\"sketch\":\"Sketch8\",\"throughAll\":false,\"upToFace\":null},\"step\":3},{\"op\":\"hole\",\"result\":{\"depthMm\":null,\"diameterMm\":30.0,\"face\":{\"atPointMm\":[25.0,20.0,30.0],\"heightMm\":20.0,\"normal\":[-0.0,1.0,-0.0],\"pickedBy\":\"geometry\",\"plane\":\"Top Plane\"},\"feature\":\"Cut-Extrude3\",\"features\":[\"Cut-Extrude3\"],\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"hole.simple\",\"what\":\"a plain hole: a circle on the face's plane, cut blind or through all\"}],\"variants\":[\"hole.simple\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"},\"steps\":[{\"op\":\"sketch\",\"result\":{\"createdPlane\":\"Plane3\",\"entities\":[{\"circle\":{\"centerMm\":[25.0,-30.0],\"radiusMm\":15.0}}],\"mapped\":true,\"plane\":{\"offsetFrom\":\"Top Plane\",\"offsetMm\":20.0},\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"radiusMm\":15.0,\"resolvedPlane\":{\"offsetFrom\":\"Top Plane\",\"offsetMm\":20.0,\"plane\":\"Plane3\",\"verified\":true},\"sketch\":\"Sketch9\",\"sketchNormal\":[0.0,1.0,0.0],\"sketchedOn\":\"Plane3\",\"transformInverted\":false}},{\"op\":\"cut\",\"result\":{\"depth2Mm\":null,\"depthMm\":0.0,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":[0.0,1.0,0.0],\"sketchNormal\":[0.0,1.0,0.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":1,\"feature\":\"Cut-Extrude3\",\"reverse\":false,\"sketch\":\"Sketch9\",\"throughAll\":true,\"upToFace\":null}}],\"throughAll\":true},\"step\":4},{\"op\":\"set_material\",\"result\":{\"appearanceReapplied\":[],\"current\":{\"database\":\"SOLIDWORKS Materials\",\"name\":\"6061 Alloy\"},\"database\":\"SOLIDWORKS Materials.sldmat\",\"densityKgM3\":2700.0,\"densityRequested\":2700.0,\"material\":\"6061 Alloy\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"set_material.density\",\"what\":\"a density in kg/m\u00b3 (the document's own, or checked against the material's)\"}],\"variants\":[\"set_material\",\"set_material.density\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"}},\"step\":5}],\"success\":true,\"targetDocument\":\"Part1-1792105365003.SLDPRT\",\"timeoutSeconds\":420}",+    "progress": {+     "confidence": "estimate",+     "elapsedSec": 8.5,+     "estimatedSec": 30,+     "etaSec": 0,+     "percent": 100,+     "phase": "run_script",+     "startKind": "warm",+     "stepLabel": "Running 5 modeling step(s)"+    },+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "solidworksRevision": "34.3.0",+    "status": "ok",+    "statusVerb": "swx_status",+    "stepCount": 5,+    "steps": [+     {+      "op": "clear_part",+      "result": {+       "bodiesLeft": 0,+       "cleared": "Part1-1792105365003.SLDPRT",+       "deleted": [+        "Sketch6",+        "Boss-Extrude5",+        "Plane2",+        "Sketch7",+        "Cut-Extrude2"+       ],+       "featuresDeleted": 5,+       "passes": 1,+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.6",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "clear_part"+        ]+       },+       "route": "DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty"+      },+      "step": 1+     },+     {+      "op": "sketch_rect",+      "result": {+       "createdPlane": null,+       "entities": [+        {+         "rect": {+          "cornersMm": [+           [+            0.0,+            0.0+           ],+           [+            100.0,+            20.0+           ]+          ]+         }+        }+       ],+       "heightMm": 20.0,+       "mapped": false,+       "plane": "Front Plane",+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "sketch.plane.front",+         "sketch.rect"+        ]+       },+       "resolvedPlane": null,+       "sketch": "Sketch8",+       "sketchNormal": [+        0.0,+        0.0,+        1.0+       ],+       "sketchedOn": "Front Plane",+       "transformInverted": false,+       "widthMm": 100.0+      },+      "step": 2+     },+     {+      "op": "extrude",+      "result": {+       "depth2Mm": null,+       "depthMm": 60.0,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": null,+        "sketchNormal": [+         0.0,+         0.0,+         1.0+        ],+        "value": false+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Boss-Extrude6",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "extrude.one"+        ]+       },+       "reverse": false,+       "sketch": "Sketch8",+       "throughAll": false,+       "upToFace": null+      },+      "step": 3+     },+     {+      "op": "hole",+      "result": {+       "depthMm": null,+       "diameterMm": 30.0,+       "face": {+        "atPointMm": [+         25.0,+         20.0,+         30.0+        ],+        "heightMm": 20.0,+        "normal": [+         -0.0,+         1.0,+         -0.0+        ],+        "pickedBy": "geometry",+        "plane": "Top Plane"+       },+       "feature": "Cut-Extrude3",+       "features": [+        "Cut-Extrude3"+       ],+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "hole.simple",+          "what": "a plain hole: a circle on the face's plane, cut blind or through all"+         }+        ],+        "variants": [+         "hole.simple"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       },+       "steps": [+        {+         "op": "sketch",+         "result": {+          "createdPlane": "Plane3",+          "entities": [+           {+            "circle": {+             "centerMm": [+              25.0,+              -30.0+             ],+             "radiusMm": 15.0+            }+           }+          ],+          "mapped": true,+          "plane": {+           "offsetFrom": "Top Plane",+           "offsetMm": 20.0+          },+          "planeFrames": "plane transforms (they match the measured Front/Top axes)",+          "radiusMm": 15.0,+          "resolvedPlane": {+           "offsetFrom": "Top Plane",+           "offsetMm": 20.0,+           "plane": "Plane3",+           "verified": true+          },+          "sketch": "Sketch9",+          "sketchNormal": [+           0.0,+           1.0,+           0.0+          ],+          "sketchedOn": "Plane3",+          "transformInverted": false+         }+        },+        {+         "op": "cut",+         "result": {+          "depth2Mm": null,+          "depthMm": 0.0,+          "dir": {+           "flippedToFollowTheReference": false,+           "reference": [+            0.0,+            1.0,+            0.0+           ],+           "sketchNormal": [+            0.0,+            1.0,+            0.0+           ],+           "value": false+          },+          "direction": "one",+          "draftDeg": null,+          "draftInward": null,+          "endCondition": 1,+          "feature": "Cut-Extrude3",+          "reverse": false,+          "sketch": "Sketch9",+          "throughAll": true,+          "upToFace": null+         }+        }+       ],+       "throughAll": true+      },+      "step": 4+     },+     {+      "op": "set_material",+      "result": {+       "appearanceReapplied": [],+       "current": {+        "database": "SOLIDWORKS Materials",+        "name": "6061 Alloy"+       },+       "database": "SOLIDWORKS Materials.sldmat",+       "densityKgM3": 2700.0,+       "densityRequested": 2700.0,+       "material": "6061 Alloy",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "set_material.density",+          "what": "a density in kg/m\u00b3 (the document's own, or checked against the material's)"+         }+        ],+        "variants": [+         "set_material",+         "set_material.density"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       }+      },+      "step": 5+     }+    ],+    "success": true,+    "targetDocument": "Part1-1792105365003.SLDPRT",+    "timeoutSeconds": 420+   },+   "massProperties": {+    "_hint": "SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.",+    "_timeoutHint": "ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "boundingBox": [+     0.0,+     0.0,+     0.0,+     0.1,+     0.02,+     0.06+    ],+    "centerOfMass": [+     0.05333855767238339,+     0.009999999999999998,+     0.03+    ],+    "centerOfMassMm": [+     53.338558,+     10.0,+     30.0+    ],+    "density": 2700.0,+    "densityKgM3": 2700.0,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "durationMs": 1085,+    "error": "",+    "massG": 285.829649258884,+    "massKg": 0.285829649258884,+    "materialName": "6061 Alloy",+    "output": "{\"_hint\":\"SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.\",\"_timeoutHint\":\"ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"boundingBox\":[0.0,0.0,0.0,0.1,0.02,0.06],\"centerOfMass\":[0.05333855767238339,0.009999999999999998,0.03],\"centerOfMassMm\":[53.338558,10.0,30.0],\"density\":2700.0,\"densityKgM3\":2700.0,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"massG\":285.829649258884,\"massKg\":0.285829649258884,\"materialName\":\"6061 Alloy\",\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"statusVerb\":\"swx_status\",\"success\":true,\"surfaceAreaM2\":0.01887123889803847,\"surfaceAreaMm2\":18871.238898038468,\"timeoutSeconds\":120,\"volumeM3\":0.00010586283305884592,\"volumeMm3\":105862.83305884592}",+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "status": "ok",+    "statusVerb": "swx_status",+    "success": true,+    "surfaceAreaM2": 0.01887123889803847,+    "surfaceAreaMm2": 18871.238898038468,+    "timeoutSeconds": 120,+    "volumeM3": 0.00010586283305884592,+    "volumeMm3": 105862.83305884592+   },+   "pass": true,+   "checks": [+    {+     "quantity": "massG",+     "expected": 285.83,+     "measured": 285.829649258884,+     "offPct": 0.00012270969317231364,+     "pass": true+    }+   ],+   "fails": [],+   "seconds": 11.8+  },+  {+   "id": "cswa-04-3dengr-q9-l-bracket",+   "title": "3dengr Q9: an L-bracket in AISI 1020, ONE polyline sketch",+   "official": false,+   "source": "https://www.3dengr.com/cswa-practice-questions.html",+   "expected": {+    "massG": 410.8,+    "centerOfMassMm": [+     26.54,+     16.54,+     20.0+    ],+    "tolerancePct": 1.0+   },+   "material": {+    "name": "AISI 1020",+    "densityKgM3": 7900+   },+   "runScript": {+    "_hint": "Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.",+    "_timeoutHint": "ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "bridgeCreatedDocument": true,+    "created": null,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "documentName": "Part1-1792105365003.SLDPRT",+    "durationMs": 6099,+    "error": "",+    "ops": [+     "new_part",+     "new_assembly",+     "clear_part",+     "sketch",+     "sketch_rect",+     "sketch_circle",+     "extrude",+     "cut",+     "set_material",+     "set_appearance",+     "fillet",+     "chamfer",+     "shell",+     "revolve",+     "revolve_cut",+     "mirror",+     "hole",+     "linear_pattern",+     "circular_pattern",+     "set_prop",+     "save_as",+     "rebuild",+     "zoom_fit"+    ],+    "output": "{\"_hint\":\"Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.\",\"_timeoutHint\":\"ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"bridgeCreatedDocument\":true,\"created\":null,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"documentName\":\"Part1-1792105365003.SLDPRT\",\"ops\":[\"new_part\",\"new_assembly\",\"clear_part\",\"sketch\",\"sketch_rect\",\"sketch_circle\",\"extrude\",\"cut\",\"set_material\",\"set_appearance\",\"fillet\",\"chamfer\",\"shell\",\"revolve\",\"revolve_cut\",\"mirror\",\"hole\",\"linear_pattern\",\"circular_pattern\",\"set_prop\",\"save_as\",\"rebuild\",\"zoom_fit\"],\"progress\":{\"confidence\":\"estimate\",\"elapsedSec\":4.7,\"estimatedSec\":30,\"etaSec\":0,\"percent\":100,\"phase\":\"run_script\",\"startKind\":\"warm\",\"stepLabel\":\"Running 4 modeling step(s)\"},\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"solidworksRevision\":\"34.3.0\",\"statusVerb\":\"swx_status\",\"stepCount\":4,\"steps\":[{\"op\":\"clear_part\",\"result\":{\"bodiesLeft\":0,\"cleared\":\"Part1-1792105365003.SLDPRT\",\"deleted\":[\"Sketch8\",\"Boss-Extrude6\",\"Plane3\",\"Sketch9\",\"Cut-Extrude3\"],\"featuresDeleted\":5,\"passes\":1,\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.6\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"clear_part\"]},\"route\":\"DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty\"},\"step\":1},{\"op\":\"sketch\",\"result\":{\"createdPlane\":null,\"entities\":[{\"line\":{\"fromMm\":[0.0,0.0],\"toMm\":[80.0,0.0]}},{\"line\":{\"fromMm\":[80.0,0.0],\"toMm\":[80.0,10.0]}},{\"line\":{\"fromMm\":[80.0,10.0],\"toMm\":[10.0,10.0]}},{\"line\":{\"fromMm\":[10.0,10.0],\"toMm\":[10.0,60.0]}},{\"line\":{\"fromMm\":[10.0,60.0],\"toMm\":[0.0,60.0]}},{\"line\":{\"fromMm\":[0.0,60.0],\"toMm\":[0.0,0.0]}}],\"mapped\":false,\"plane\":\"Front Plane\",\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"sketch.line\",\"what\":\"lines of a closed contour (line, polyline, polygon, slot, rounded rect): ISketchManager::CreateLine\"}],\"variants\":[\"sketch.plane.front\",\"sketch.multiProfile\",\"sketch.line\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"},\"resolvedPlane\":null,\"sketch\":\"Sketch10\",\"sketchNormal\":[0.0,0.0,1.0],\"sketchedOn\":\"Front Plane\",\"transformInverted\":false},\"step\":2},{\"op\":\"extrude\",\"result\":{\"depth2Mm\":null,\"depthMm\":40.0,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":null,\"sketchNormal\":[0.0,0.0,1.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Boss-Extrude7\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"extrude.one\"]},\"reverse\":false,\"sketch\":\"Sketch10\",\"throughAll\":false,\"upToFace\":null},\"step\":3},{\"op\":\"set_material\",\"result\":{\"appearanceReapplied\":[],\"current\":{\"database\":\"SOLIDWORKS Materials\",\"name\":\"AISI 1020\"},\"database\":\"SOLIDWORKS Materials.sldmat\",\"densityKgM3\":7900.000000000001,\"densityRequested\":7900.0,\"material\":\"AISI 1020\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"set_material.density\",\"what\":\"a density in kg/m\u00b3 (the document's own, or checked against the material's)\"}],\"variants\":[\"set_material\",\"set_material.density\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"}},\"step\":4}],\"success\":true,\"targetDocument\":\"Part1-1792105365003.SLDPRT\",\"timeoutSeconds\":420}",+    "progress": {+     "confidence": "estimate",+     "elapsedSec": 4.7,+     "estimatedSec": 30,+     "etaSec": 0,+     "percent": 100,+     "phase": "run_script",+     "startKind": "warm",+     "stepLabel": "Running 4 modeling step(s)"+    },+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "solidworksRevision": "34.3.0",+    "status": "ok",+    "statusVerb": "swx_status",+    "stepCount": 4,+    "steps": [+     {+      "op": "clear_part",+      "result": {+       "bodiesLeft": 0,+       "cleared": "Part1-1792105365003.SLDPRT",+       "deleted": [+        "Sketch8",+        "Boss-Extrude6",+        "Plane3",+        "Sketch9",+        "Cut-Extrude3"+       ],+       "featuresDeleted": 5,+       "passes": 1,+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.6",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "clear_part"+        ]+       },+       "route": "DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty"+      },+      "step": 1+     },+     {+      "op": "sketch",+      "result": {+       "createdPlane": null,+       "entities": [+        {+         "line": {+          "fromMm": [+           0.0,+           0.0+          ],+          "toMm": [+           80.0,+           0.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           80.0,+           0.0+          ],+          "toMm": [+           80.0,+           10.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           80.0,+           10.0+          ],+          "toMm": [+           10.0,+           10.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           10.0,+           10.0+          ],+          "toMm": [+           10.0,+           60.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           10.0,+           60.0+          ],+          "toMm": [+           0.0,+           60.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           0.0,+           60.0+          ],+          "toMm": [+           0.0,+           0.0+          ]+         }+        }+       ],+       "mapped": false,+       "plane": "Front Plane",+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "sketch.line",+          "what": "lines of a closed contour (line, polyline, polygon, slot, rounded rect): ISketchManager::CreateLine"+         }+        ],+        "variants": [+         "sketch.plane.front",+         "sketch.multiProfile",+         "sketch.line"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       },+       "resolvedPlane": null,+       "sketch": "Sketch10",+       "sketchNormal": [+        0.0,+        0.0,+        1.0+       ],+       "sketchedOn": "Front Plane",+       "transformInverted": false+      },+      "step": 2+     },+     {+      "op": "extrude",+      "result": {+       "depth2Mm": null,+       "depthMm": 40.0,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": null,+        "sketchNormal": [+         0.0,+         0.0,+         1.0+        ],+        "value": false+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Boss-Extrude7",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "extrude.one"+        ]+       },+       "reverse": false,+       "sketch": "Sketch10",+       "throughAll": false,+       "upToFace": null+      },+      "step": 3+     },+     {+      "op": "set_material",+      "result": {+       "appearanceReapplied": [],+       "current": {+        "database": "SOLIDWORKS Materials",+        "name": "AISI 1020"+       },+       "database": "SOLIDWORKS Materials.sldmat",+       "densityKgM3": 7900.000000000001,+       "densityRequested": 7900.0,+       "material": "AISI 1020",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "set_material.density",+          "what": "a density in kg/m\u00b3 (the document's own, or checked against the material's)"+         }+        ],+        "variants": [+         "set_material",+         "set_material.density"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       }+      },+      "step": 4+     }+    ],+    "success": true,+    "targetDocument": "Part1-1792105365003.SLDPRT",+    "timeoutSeconds": 420+   },+   "massProperties": {+    "_hint": "SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.",+    "_timeoutHint": "ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "boundingBox": [+     0.0,+     0.0,+     0.0,+     0.08,+     0.06,+     0.04+    ],+    "centerOfMass": [+     0.026538461538461535,+     0.016538461538461537,+     0.019999999999999997+    ],+    "centerOfMassMm": [+     26.538462,+     16.538462,+     20.0+    ],+    "density": 7900.000000000001,+    "densityKgM3": 7900.000000000001,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "durationMs": 1230,+    "error": "",+    "massG": 410.80000000000007,+    "massKg": 0.41080000000000005,+    "materialName": "AISI 1020",+    "output": "{\"_hint\":\"SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.\",\"_timeoutHint\":\"ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"boundingBox\":[0.0,0.0,0.0,0.08,0.06,0.04],\"centerOfMass\":[0.026538461538461535,0.016538461538461537,0.019999999999999997],\"centerOfMassMm\":[26.538462,16.538462,20.0],\"density\":7900.000000000001,\"densityKgM3\":7900.000000000001,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"massG\":410.80000000000007,\"massKg\":0.41080000000000005,\"materialName\":\"AISI 1020\",\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"statusVerb\":\"swx_status\",\"success\":true,\"surfaceAreaM2\":0.0138,\"surfaceAreaMm2\":13800.0,\"timeoutSeconds\":120,\"volumeM3\":0.000052,\"volumeMm3\":52000.0}",+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "status": "ok",+    "statusVerb": "swx_status",+    "success": true,+    "surfaceAreaM2": 0.0138,+    "surfaceAreaMm2": 13800.0,+    "timeoutSeconds": 120,+    "volumeM3": 5.2e-05,+    "volumeMm3": 52000.0+   },+   "pass": true,+   "checks": [+    {+     "quantity": "massG",+     "expected": 410.8,+     "measured": 410.80000000000007,+     "offPct": 1.3837248992407013e-14,+     "pass": true+    },+    {+     "quantity": "centerOfMassMm",+     "expected": [+      26.54,+      16.54,+      20.0+     ],+     "measured": [+      26.538462,+      16.538462,+      20.0+     ],+     "pass": true+    }+   ],+   "fails": [],+   "seconds": 7.3+  },+  {+   "id": "cswa-05-tool-block-step1",+   "title": "Official Tool Block, Step 1 (Q3): A 81, B 57, C 43",+   "official": true,+   "source": "https://www.solidworks.com/sites/default/files/2017-12/CSWASampleExam.pdf (Dassault CSWA Sample Exam, 2017 edition; archive http://web.archive.org/web/20251230104817/https://www.solidworks.com/sites/default/files/2017-12/CSWASampleExam.pdf)",+   "expected": {+    "massG": 939.54,+    "tolerancePct": 1.0+   },+   "material": {+    "name": "AISI 1020",+    "densityKgM3": 7900+   },+   "runScript": {+    "_hint": "Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.",+    "_timeoutHint": "ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "bridgeCreatedDocument": true,+    "created": null,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "documentName": "Part1-1792105365003.SLDPRT",+    "durationMs": 6621,+    "error": "",+    "ops": [+     "new_part",+     "new_assembly",+     "clear_part",+     "sketch",+     "sketch_rect",+     "sketch_circle",+     "extrude",+     "cut",+     "set_material",+     "set_appearance",+     "fillet",+     "chamfer",+     "shell",+     "revolve",+     "revolve_cut",+     "mirror",+     "hole",+     "linear_pattern",+     "circular_pattern",+     "set_prop",+     "save_as",+     "rebuild",+     "zoom_fit"+    ],+    "output": "{\"_hint\":\"Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.\",\"_timeoutHint\":\"ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"bridgeCreatedDocument\":true,\"created\":null,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"documentName\":\"Part1-1792105365003.SLDPRT\",\"ops\":[\"new_part\",\"new_assembly\",\"clear_part\",\"sketch\",\"sketch_rect\",\"sketch_circle\",\"extrude\",\"cut\",\"set_material\",\"set_appearance\",\"fillet\",\"chamfer\",\"shell\",\"revolve\",\"revolve_cut\",\"mirror\",\"hole\",\"linear_pattern\",\"circular_pattern\",\"set_prop\",\"save_as\",\"rebuild\",\"zoom_fit\"],\"progress\":{\"confidence\":\"estimate\",\"elapsedSec\":4.9,\"estimatedSec\":30,\"etaSec\":0,\"percent\":100,\"phase\":\"run_script\",\"startKind\":\"warm\",\"stepLabel\":\"Running 4 modeling step(s)\"},\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"solidworksRevision\":\"34.3.0\",\"statusVerb\":\"swx_status\",\"stepCount\":4,\"steps\":[{\"op\":\"clear_part\",\"result\":{\"bodiesLeft\":0,\"cleared\":\"Part1-1792105365003.SLDPRT\",\"deleted\":[\"Sketch10\",\"Boss-Extrude7\"],\"featuresDeleted\":2,\"passes\":1,\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.6\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"clear_part\"]},\"route\":\"DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty\"},\"step\":1},{\"op\":\"sketch\",\"result\":{\"createdPlane\":null,\"entities\":[{\"line\":{\"fromMm\":[0.0,18.0],\"toMm\":[18.243084987875623,14.783251905279968]}},{\"arc\":{\"ccw\":true,\"centerMm\":[21.5424003635473,33.494599212511915],\"endMm\":[38.0,24.0],\"radiusMm\":19.0,\"startMm\":[18.243084987875623,14.783251905279968]}},{\"line\":{\"fromMm\":[38.0,24.0],\"toMm\":[62.00000000000001,24.0]}},{\"line\":{\"fromMm\":[67.0,19.0],\"toMm\":[67.0,0.0]}},{\"line\":{\"fromMm\":[67.0,0.0],\"toMm\":[38.0,-33.0]}},{\"line\":{\"fromMm\":[38.0,-33.0],\"toMm\":[32.788067396763054,-33.0]}},{\"arc\":{\"ccw\":false,\"centerMm\":[54.69696969696975,-13.999999999999972],\"endMm\":[26.012264996781063,-18.264705882352946],\"radiusMm\":29.000000000000053,\"startMm\":[32.788067396763054,-33.0]}},{\"arc\":{\"ccw\":true,\"centerMm\":[21.066626255369176,-18.999999999999964],\"endMm\":[21.06662625536923,-14.0],\"radiusMm\":5.000000000000048,\"startMm\":[26.012264996781063,-18.264705882352946]}},{\"line\":{\"fromMm\":[21.06662625536923,-14.0],\"toMm\":[-7.0,-14.0]}},{\"line\":{\"fromMm\":[-14.0,-7.0],\"toMm\":[-14.0,11.000000000000002]}},{\"line\":{\"fromMm\":[-7.0,18.0],\"toMm\":[0.0,18.0]}},{\"line\":{\"fromMm\":[-14.0,11.000000000000002],\"toMm\":[-7.0,18.0]}},{\"line\":{\"fromMm\":[-7.0,-14.0],\"toMm\":[-14.0,-7.0]}},{\"line\":{\"fromMm\":[62.00000000000001,24.0],\"toMm\":[67.0,19.0]}},{\"circle\":{\"centerMm\":[0.0,0.0],\"radiusMm\":7.0}}],\"mapped\":false,\"plane\":\"Front Plane\",\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"sketch.line\",\"what\":\"lines of a closed contour (line, polyline, polygon, slot, rounded rect): ISketchManager::CreateLine\"},{\"variant\":\"sketch.arc\",\"what\":\"arcs of a closed contour (arc, arc3, tangentArc, slot, rounded rect): ISketchManager::CreateArc\"}],\"variants\":[\"sketch.plane.front\",\"sketch.circle\",\"sketch.multiProfile\",\"sketch.line\",\"sketch.arc\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"},\"resolvedPlane\":null,\"sketch\":\"Sketch11\",\"sketchNormal\":[0.0,0.0,1.0],\"sketchedOn\":\"Front Plane\",\"transformInverted\":false},\"step\":2},{\"op\":\"extrude\",\"result\":{\"depth2Mm\":null,\"depthMm\":43.0,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":null,\"sketchNormal\":[0.0,0.0,1.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Boss-Extrude8\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"extrude.one\"]},\"reverse\":false,\"sketch\":\"Sketch11\",\"throughAll\":false,\"upToFace\":null},\"step\":3},{\"op\":\"set_material\",\"result\":{\"appearanceReapplied\":[],\"current\":{\"database\":\"SOLIDWORKS Materials\",\"name\":\"AISI 1020\"},\"database\":\"SOLIDWORKS Materials.sldmat\",\"densityKgM3\":7900.0,\"densityRequested\":7900.0,\"material\":\"AISI 1020\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"set_material.density\",\"what\":\"a density in kg/m\u00b3 (the document's own, or checked against the material's)\"}],\"variants\":[\"set_material\",\"set_material.density\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"}},\"step\":4}],\"success\":true,\"targetDocument\":\"Part1-1792105365003.SLDPRT\",\"timeoutSeconds\":420}",+    "progress": {+     "confidence": "estimate",+     "elapsedSec": 4.9,+     "estimatedSec": 30,+     "etaSec": 0,+     "percent": 100,+     "phase": "run_script",+     "startKind": "warm",+     "stepLabel": "Running 4 modeling step(s)"+    },+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "solidworksRevision": "34.3.0",+    "status": "ok",+    "statusVerb": "swx_status",+    "stepCount": 4,+    "steps": [+     {+      "op": "clear_part",+      "result": {+       "bodiesLeft": 0,+       "cleared": "Part1-1792105365003.SLDPRT",+       "deleted": [+        "Sketch10",+        "Boss-Extrude7"+       ],+       "featuresDeleted": 2,+       "passes": 1,+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.6",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "clear_part"+        ]+       },+       "route": "DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty"+      },+      "step": 1+     },+     {+      "op": "sketch",+      "result": {+       "createdPlane": null,+       "entities": [+        {+         "line": {+          "fromMm": [+           0.0,+           18.0+          ],+          "toMm": [+           18.243084987875623,+           14.783251905279968+          ]+         }+        },+        {+         "arc": {+          "ccw": true,+          "centerMm": [+           21.5424003635473,+           33.494599212511915+          ],+          "endMm": [+           38.0,+           24.0+          ],+          "radiusMm": 19.0,+          "startMm": [+           18.243084987875623,+           14.783251905279968+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           38.0,+           24.0+          ],+          "toMm": [+           62.00000000000001,+           24.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           67.0,+           19.0+          ],+          "toMm": [+           67.0,+           0.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           67.0,+           0.0+          ],+          "toMm": [+           38.0,+           -33.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           38.0,+           -33.0+          ],+          "toMm": [+           32.788067396763054,+           -33.0+          ]+         }+        },+        {+         "arc": {+          "ccw": false,+          "centerMm": [+           54.69696969696975,+           -13.999999999999972+          ],+          "endMm": [+           26.012264996781063,+           -18.264705882352946+          ],+          "radiusMm": 29.000000000000053,+          "startMm": [+           32.788067396763054,+           -33.0+          ]+         }+        },+        {+         "arc": {+          "ccw": true,+          "centerMm": [+           21.066626255369176,+           -18.999999999999964+          ],+          "endMm": [+           21.06662625536923,+           -14.0+          ],+          "radiusMm": 5.000000000000048,+          "startMm": [+           26.012264996781063,+           -18.264705882352946+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           21.06662625536923,+           -14.0+          ],+          "toMm": [+           -7.0,+           -14.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           -14.0,+           -7.0+          ],+          "toMm": [+           -14.0,+           11.000000000000002+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           -7.0,+           18.0+          ],+          "toMm": [+           0.0,+           18.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           -14.0,+           11.000000000000002+          ],+          "toMm": [+           -7.0,+           18.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           -7.0,+           -14.0+          ],+          "toMm": [+           -14.0,+           -7.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           62.00000000000001,+           24.0+          ],+          "toMm": [+           67.0,+           19.0+          ]+         }+        },+        {+         "circle": {+          "centerMm": [+           0.0,+           0.0+          ],+          "radiusMm": 7.0+         }+        }+       ],+       "mapped": false,+       "plane": "Front Plane",+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "sketch.line",+          "what": "lines of a closed contour (line, polyline, polygon, slot, rounded rect): ISketchManager::CreateLine"+         },+         {+          "variant": "sketch.arc",+          "what": "arcs of a closed contour (arc, arc3, tangentArc, slot, rounded rect): ISketchManager::CreateArc"+         }+        ],+        "variants": [+         "sketch.plane.front",+         "sketch.circle",+         "sketch.multiProfile",+         "sketch.line",+         "sketch.arc"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       },+       "resolvedPlane": null,+       "sketch": "Sketch11",+       "sketchNormal": [+        0.0,+        0.0,+        1.0+       ],+       "sketchedOn": "Front Plane",+       "transformInverted": false+      },+      "step": 2+     },+     {+      "op": "extrude",+      "result": {+       "depth2Mm": null,+       "depthMm": 43.0,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": null,+        "sketchNormal": [+         0.0,+         0.0,+         1.0+        ],+        "value": false+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Boss-Extrude8",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "extrude.one"+        ]+       },+       "reverse": false,+       "sketch": "Sketch11",+       "throughAll": false,+       "upToFace": null+      },+      "step": 3+     },+     {+      "op": "set_material",+      "result": {+       "appearanceReapplied": [],+       "current": {+        "database": "SOLIDWORKS Materials",+        "name": "AISI 1020"+       },+       "database": "SOLIDWORKS Materials.sldmat",+       "densityKgM3": 7900.0,+       "densityRequested": 7900.0,+       "material": "AISI 1020",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "set_material.density",+          "what": "a density in kg/m\u00b3 (the document's own, or checked against the material's)"+         }+        ],+        "variants": [+         "set_material",+         "set_material.density"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       }+      },+      "step": 4+     }+    ],+    "success": true,+    "targetDocument": "Part1-1792105365003.SLDPRT",+    "timeoutSeconds": 420+   },+   "massProperties": {+    "_hint": "SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.",+    "_timeoutHint": "ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "boundingBox": [+     -0.014,+     -0.033,+     0.0,+     0.067,+     0.024,+     0.043+    ],+    "centerOfMass": [+     0.03062236692252704,+     0.0003076468646468399,+     0.0215+    ],+    "centerOfMassMm": [+     30.622367,+     0.307647,+     21.5+    ],+    "density": 7900.0,+    "densityKgM3": 7900.0,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "durationMs": 1094,+    "error": "",+    "massG": 939.5395682014018,+    "massKg": 0.9395395682014018,+    "materialName": "AISI 1020",+    "output": "{\"_hint\":\"SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.\",\"_timeoutHint\":\"ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"boundingBox\":[-0.014,-0.033,0.0,0.067,0.024,0.043],\"centerOfMass\":[0.03062236692252704,0.0003076468646468399,0.0215],\"centerOfMassMm\":[30.622367,0.307647,21.5],\"density\":7900.0,\"densityKgM3\":7900.0,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"massG\":939.5395682014018,\"massKg\":0.9395395682014018,\"materialName\":\"AISI 1020\",\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"statusVerb\":\"swx_status\",\"success\":true,\"surfaceAreaM2\":0.01763006429786853,\"surfaceAreaMm2\":17630.06429786853,\"timeoutSeconds\":120,\"volumeM3\":0.00011892905926600024,\"volumeMm3\":118929.05926600024}",+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "status": "ok",+    "statusVerb": "swx_status",+    "success": true,+    "surfaceAreaM2": 0.01763006429786853,+    "surfaceAreaMm2": 17630.06429786853,+    "timeoutSeconds": 120,+    "volumeM3": 0.00011892905926600024,+    "volumeMm3": 118929.05926600024+   },+   "pass": true,+   "checks": [+    {+     "quantity": "massG",+     "expected": 939.54,+     "measured": 939.5395682014018,+     "offPct": 4.595851141290499e-05,+     "pass": true+    }+   ],+   "fails": [],+   "seconds": 7.7+  },+  {+   "id": "cswa-06-tool-block-step2",+   "title": "Official Tool Block, Step 2 (Q4): A 84, B 59, C 45, all other dimensions the same",+   "official": true,+   "source": "https://www.solidworks.com/sites/default/files/2017-12/CSWASampleExam.pdf (Dassault CSWA Sample Exam, 2017 edition; archive http://web.archive.org/web/20251230104817/https://www.solidworks.com/sites/default/files/2017-12/CSWASampleExam.pdf)",+   "expected": {+    "massG": 1032.32,+    "tolerancePct": 1.0+   },+   "material": {+    "name": "AISI 1020",+    "densityKgM3": 7900+   },+   "runScript": {+    "_hint": "Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.",+    "_timeoutHint": "ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "bridgeCreatedDocument": true,+    "created": null,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "documentName": "Part1-1792105365003.SLDPRT",+    "durationMs": 6408,+    "error": "",+    "ops": [+     "new_part",+     "new_assembly",+     "clear_part",+     "sketch",+     "sketch_rect",+     "sketch_circle",+     "extrude",+     "cut",+     "set_material",+     "set_appearance",+     "fillet",+     "chamfer",+     "shell",+     "revolve",+     "revolve_cut",+     "mirror",+     "hole",+     "linear_pattern",+     "circular_pattern",+     "set_prop",+     "save_as",+     "rebuild",+     "zoom_fit"+    ],+    "output": "{\"_hint\":\"Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.\",\"_timeoutHint\":\"ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"bridgeCreatedDocument\":true,\"created\":null,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"documentName\":\"Part1-1792105365003.SLDPRT\",\"ops\":[\"new_part\",\"new_assembly\",\"clear_part\",\"sketch\",\"sketch_rect\",\"sketch_circle\",\"extrude\",\"cut\",\"set_material\",\"set_appearance\",\"fillet\",\"chamfer\",\"shell\",\"revolve\",\"revolve_cut\",\"mirror\",\"hole\",\"linear_pattern\",\"circular_pattern\",\"set_prop\",\"save_as\",\"rebuild\",\"zoom_fit\"],\"progress\":{\"confidence\":\"estimate\",\"elapsedSec\":4.7,\"estimatedSec\":30,\"etaSec\":0,\"percent\":100,\"phase\":\"run_script\",\"startKind\":\"warm\",\"stepLabel\":\"Running 4 modeling step(s)\"},\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"solidworksRevision\":\"34.3.0\",\"statusVerb\":\"swx_status\",\"stepCount\":4,\"steps\":[{\"op\":\"clear_part\",\"result\":{\"bodiesLeft\":0,\"cleared\":\"Part1-1792105365003.SLDPRT\",\"deleted\":[\"Sketch11\",\"Boss-Extrude8\"],\"featuresDeleted\":2,\"passes\":1,\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.6\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"clear_part\"]},\"route\":\"DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty\"},\"step\":1},{\"op\":\"sketch\",\"result\":{\"createdPlane\":null,\"entities\":[{\"line\":{\"fromMm\":[0.0,18.0],\"toMm\":[20.10404235201319,14.455114912034407]}},{\"arc\":{\"ccw\":true,\"centerMm\":[23.40335772768487,33.166462219266364],\"endMm\":[41.0,26.0],\"radiusMm\":19.0,\"startMm\":[20.10404235201319,14.455114912034407]}},{\"line\":{\"fromMm\":[41.0,26.0],\"toMm\":[65.0,26.0]}},{\"line\":{\"fromMm\":[70.0,21.0],\"toMm\":[70.0,2.0]}},{\"line\":{\"fromMm\":[70.0,2.0],\"toMm\":[41.0,-33.0]}},{\"line\":{\"fromMm\":[41.0,-33.0],\"toMm\":[34.8339548426505,-33.0]}},{\"arc\":{\"ccw\":false,\"centerMm\":[56.74285714285731,-14.000000000000036],\"endMm\":[28.0581524426685,-18.264705882352946],\"radiusMm\":29.000000000000107,\"startMm\":[34.8339548426505,-33.0]}},{\"arc\":{\"ccw\":true,\"centerMm\":[23.112513701256617,-18.999999999999982],\"endMm\":[23.112513701256667,-14.0],\"radiusMm\":5.0000000000000515,\"startMm\":[28.0581524426685,-18.264705882352946]}},{\"line\":{\"fromMm\":[23.112513701256667,-14.0],\"toMm\":[-7.0,-14.0]}},{\"line\":{\"fromMm\":[-14.0,-7.0],\"toMm\":[-14.0,11.000000000000002]}},{\"line\":{\"fromMm\":[-7.0,18.0],\"toMm\":[0.0,18.0]}},{\"line\":{\"fromMm\":[-14.0,11.000000000000002],\"toMm\":[-7.0,18.0]}},{\"line\":{\"fromMm\":[-7.0,-14.0],\"toMm\":[-14.0,-7.0]}},{\"line\":{\"fromMm\":[65.0,26.0],\"toMm\":[70.0,21.0]}},{\"circle\":{\"centerMm\":[0.0,0.0],\"radiusMm\":7.0}}],\"mapped\":false,\"plane\":\"Front Plane\",\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"sketch.line\",\"what\":\"lines of a closed contour (line, polyline, polygon, slot, rounded rect): ISketchManager::CreateLine\"},{\"variant\":\"sketch.arc\",\"what\":\"arcs of a closed contour (arc, arc3, tangentArc, slot, rounded rect): ISketchManager::CreateArc\"}],\"variants\":[\"sketch.plane.front\",\"sketch.circle\",\"sketch.multiProfile\",\"sketch.line\",\"sketch.arc\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"},\"resolvedPlane\":null,\"sketch\":\"Sketch12\",\"sketchNormal\":[0.0,0.0,1.0],\"sketchedOn\":\"Front Plane\",\"transformInverted\":false},\"step\":2},{\"op\":\"extrude\",\"result\":{\"depth2Mm\":null,\"depthMm\":45.0,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":null,\"sketchNormal\":[0.0,0.0,1.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Boss-Extrude9\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"extrude.one\"]},\"reverse\":false,\"sketch\":\"Sketch12\",\"throughAll\":false,\"upToFace\":null},\"step\":3},{\"op\":\"set_material\",\"result\":{\"appearanceReapplied\":[],\"current\":{\"database\":\"SOLIDWORKS Materials\",\"name\":\"AISI 1020\"},\"database\":\"SOLIDWORKS Materials.sldmat\",\"densityKgM3\":7899.999999999999,\"densityRequested\":7900.0,\"material\":\"AISI 1020\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"set_material.density\",\"what\":\"a density in kg/m\u00b3 (the document's own, or checked against the material's)\"}],\"variants\":[\"set_material\",\"set_material.density\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"}},\"step\":4}],\"success\":true,\"targetDocument\":\"Part1-1792105365003.SLDPRT\",\"timeoutSeconds\":420}",+    "progress": {+     "confidence": "estimate",+     "elapsedSec": 4.7,+     "estimatedSec": 30,+     "etaSec": 0,+     "percent": 100,+     "phase": "run_script",+     "startKind": "warm",+     "stepLabel": "Running 4 modeling step(s)"+    },+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "solidworksRevision": "34.3.0",+    "status": "ok",+    "statusVerb": "swx_status",+    "stepCount": 4,+    "steps": [+     {+      "op": "clear_part",+      "result": {+       "bodiesLeft": 0,+       "cleared": "Part1-1792105365003.SLDPRT",+       "deleted": [+        "Sketch11",+        "Boss-Extrude8"+       ],+       "featuresDeleted": 2,+       "passes": 1,+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.6",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "clear_part"+        ]+       },+       "route": "DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty"+      },+      "step": 1+     },+     {+      "op": "sketch",+      "result": {+       "createdPlane": null,+       "entities": [+        {+         "line": {+          "fromMm": [+           0.0,+           18.0+          ],+          "toMm": [+           20.10404235201319,+           14.455114912034407+          ]+         }+        },+        {+         "arc": {+          "ccw": true,+          "centerMm": [+           23.40335772768487,+           33.166462219266364+          ],+          "endMm": [+           41.0,+           26.0+          ],+          "radiusMm": 19.0,+          "startMm": [+           20.10404235201319,+           14.455114912034407+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           41.0,+           26.0+          ],+          "toMm": [+           65.0,+           26.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           70.0,+           21.0+          ],+          "toMm": [+           70.0,+           2.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           70.0,+           2.0+          ],+          "toMm": [+           41.0,+           -33.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           41.0,+           -33.0+          ],+          "toMm": [+           34.8339548426505,+           -33.0+          ]+         }+        },+        {+         "arc": {+          "ccw": false,+          "centerMm": [+           56.74285714285731,+           -14.000000000000036+          ],+          "endMm": [+           28.0581524426685,+           -18.264705882352946+          ],+          "radiusMm": 29.000000000000107,+          "startMm": [+           34.8339548426505,+           -33.0+          ]+         }+        },+        {+         "arc": {+          "ccw": true,+          "centerMm": [+           23.112513701256617,+           -18.999999999999982+          ],+          "endMm": [+           23.112513701256667,+           -14.0+          ],+          "radiusMm": 5.0000000000000515,+          "startMm": [+           28.0581524426685,+           -18.264705882352946+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           23.112513701256667,+           -14.0+          ],+          "toMm": [+           -7.0,+           -14.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           -14.0,+           -7.0+          ],+          "toMm": [+           -14.0,+           11.000000000000002+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           -7.0,+           18.0+          ],+          "toMm": [+           0.0,+           18.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           -14.0,+           11.000000000000002+          ],+          "toMm": [+           -7.0,+           18.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           -7.0,+           -14.0+          ],+          "toMm": [+           -14.0,+           -7.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           65.0,+           26.0+          ],+          "toMm": [+           70.0,+           21.0+          ]+         }+        },+        {+         "circle": {+          "centerMm": [+           0.0,+           0.0+          ],+          "radiusMm": 7.0+         }+        }+       ],+       "mapped": false,+       "plane": "Front Plane",+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "sketch.line",+          "what": "lines of a closed contour (line, polyline, polygon, slot, rounded rect): ISketchManager::CreateLine"+         },+         {+          "variant": "sketch.arc",+          "what": "arcs of a closed contour (arc, arc3, tangentArc, slot, rounded rect): ISketchManager::CreateArc"+         }+        ],+        "variants": [+         "sketch.plane.front",+         "sketch.circle",+         "sketch.multiProfile",+         "sketch.line",+         "sketch.arc"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       },+       "resolvedPlane": null,+       "sketch": "Sketch12",+       "sketchNormal": [+        0.0,+        0.0,+        1.0+       ],+       "sketchedOn": "Front Plane",+       "transformInverted": false+      },+      "step": 2+     },+     {+      "op": "extrude",+      "result": {+       "depth2Mm": null,+       "depthMm": 45.0,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": null,+        "sketchNormal": [+         0.0,+         0.0,+         1.0+        ],+        "value": false+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Boss-Extrude9",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "extrude.one"+        ]+       },+       "reverse": false,+       "sketch": "Sketch12",+       "throughAll": false,+       "upToFace": null+      },+      "step": 3+     },+     {+      "op": "set_material",+      "result": {+       "appearanceReapplied": [],+       "current": {+        "database": "SOLIDWORKS Materials",+        "name": "AISI 1020"+       },+       "database": "SOLIDWORKS Materials.sldmat",+       "densityKgM3": 7899.999999999999,+       "densityRequested": 7900.0,+       "material": "AISI 1020",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "set_material.density",+          "what": "a density in kg/m\u00b3 (the document's own, or checked against the material's)"+         }+        ],+        "variants": [+         "set_material",+         "set_material.density"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       }+      },+      "step": 4+     }+    ],+    "success": true,+    "targetDocument": "Part1-1792105365003.SLDPRT",+    "timeoutSeconds": 420+   },+   "massProperties": {+    "_hint": "SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.",+    "_timeoutHint": "ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "boundingBox": [+     -0.014,+     -0.033,+     0.0,+     0.07,+     0.026,+     0.045+    ],+    "centerOfMass": [+     0.03255336787850931,+     0.0007907183444125464,+     0.0225+    ],+    "centerOfMassMm": [+     32.553368,+     0.790718,+     22.5+    ],+    "density": 7899.999999999999,+    "densityKgM3": 7899.999999999999,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "durationMs": 1037,+    "error": "",+    "massG": 1032.3206766712835,+    "massKg": 1.0323206766712836,+    "materialName": "AISI 1020",+    "output": "{\"_hint\":\"SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.\",\"_timeoutHint\":\"ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"boundingBox\":[-0.014,-0.033,0.0,0.07,0.026,0.045],\"centerOfMass\":[0.03255336787850931,0.0007907183444125464,0.0225],\"centerOfMassMm\":[32.553368,0.790718,22.5],\"density\":7899.999999999999,\"densityKgM3\":7899.999999999999,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"massG\":1032.3206766712835,\"massKg\":1.0323206766712836,\"materialName\":\"AISI 1020\",\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"statusVerb\":\"swx_status\",\"success\":true,\"surfaceAreaM2\":0.0188741376700506,\"surfaceAreaMm2\":18874.137670050597,\"timeoutSeconds\":120,\"volumeM3\":0.00013067350337611186,\"volumeMm3\":130673.50337611184}",+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "status": "ok",+    "statusVerb": "swx_status",+    "success": true,+    "surfaceAreaM2": 0.0188741376700506,+    "surfaceAreaMm2": 18874.137670050597,+    "timeoutSeconds": 120,+    "volumeM3": 0.00013067350337611186,+    "volumeMm3": 130673.50337611184+   },+   "pass": true,+   "checks": [+    {+     "quantity": "massG",+     "expected": 1032.32,+     "measured": 1032.3206766712835,+     "offPct": 6.55485976828616e-05,+     "pass": true+    }+   ],+   "fails": [],+   "seconds": 7.5+  },+  {+   "id": "cswa-07-tool-block-step3",+   "title": "Official Tool Block, Step 3 (Q5): A 86, B 58, C 44, then remove material",+   "official": true,+   "source": "https://www.solidworks.com/sites/default/files/2017-12/CSWASampleExam.pdf (Dassault CSWA Sample Exam, 2017 edition; archive http://web.archive.org/web/20251230104817/https://www.solidworks.com/sites/default/files/2017-12/CSWASampleExam.pdf)",+   "expected": {+    "massG": 628.18,+    "tolerancePct": 1.0+   },+   "material": {+    "name": "AISI 1020",+    "densityKgM3": 7900+   },+   "runScript": {+    "_hint": "Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.",+    "_timeoutHint": "ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "bridgeCreatedDocument": true,+    "created": null,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "documentName": "Part1-1792105365003.SLDPRT",+    "durationMs": 20797,+    "error": "",+    "ops": [+     "new_part",+     "new_assembly",+     "clear_part",+     "sketch",+     "sketch_rect",+     "sketch_circle",+     "extrude",+     "cut",+     "set_material",+     "set_appearance",+     "fillet",+     "chamfer",+     "shell",+     "revolve",+     "revolve_cut",+     "mirror",+     "hole",+     "linear_pattern",+     "circular_pattern",+     "set_prop",+     "save_as",+     "rebuild",+     "zoom_fit"+    ],+    "output": "{\"_hint\":\"Each step reports what it built. Verify with swx_inspect_bodies (the geometry) or swx_mass_properties (the mass) rather than trusting the step list. This document was created by the bridge, so swx_close_doc {save:false} discards the whole thing safely; swx_save_as puts it on disk. A step that fails stops the script and says which one, leaving what was already built in place.\",\"_timeoutHint\":\"ab waits up to 420s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"bridgeCreatedDocument\":true,\"created\":null,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"documentName\":\"Part1-1792105365003.SLDPRT\",\"ops\":[\"new_part\",\"new_assembly\",\"clear_part\",\"sketch\",\"sketch_rect\",\"sketch_circle\",\"extrude\",\"cut\",\"set_material\",\"set_appearance\",\"fillet\",\"chamfer\",\"shell\",\"revolve\",\"revolve_cut\",\"mirror\",\"hole\",\"linear_pattern\",\"circular_pattern\",\"set_prop\",\"save_as\",\"rebuild\",\"zoom_fit\"],\"progress\":{\"confidence\":\"estimate\",\"elapsedSec\":18.7,\"estimatedSec\":30,\"etaSec\":0,\"percent\":100,\"phase\":\"run_script\",\"startKind\":\"warm\",\"stepLabel\":\"Running 11 modeling step(s)\"},\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"solidworksRevision\":\"34.3.0\",\"statusVerb\":\"swx_status\",\"stepCount\":11,\"steps\":[{\"op\":\"clear_part\",\"result\":{\"bodiesLeft\":0,\"cleared\":\"Part1-1792105365003.SLDPRT\",\"deleted\":[\"Sketch12\",\"Boss-Extrude9\"],\"featuresDeleted\":2,\"passes\":1,\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.6\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"clear_part\"]},\"route\":\"DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty\"},\"step\":1},{\"op\":\"sketch\",\"result\":{\"createdPlane\":null,\"entities\":[{\"line\":{\"fromMm\":[0.0,18.0],\"toMm\":[22.3613808357771,14.057085232755291]}},{\"arc\":{\"ccw\":true,\"centerMm\":[25.66069621144878,32.768432539987224],\"endMm\":[43.0,25.0],\"radiusMm\":18.99999999999998,\"startMm\":[22.3613808357771,14.057085232755291]}},{\"line\":{\"fromMm\":[43.0,25.0],\"toMm\":[67.0,25.0]}},{\"line\":{\"fromMm\":[72.0,20.0],\"toMm\":[72.0,1.0]}},{\"line\":{\"fromMm\":[72.0,1.0],\"toMm\":[43.0,-33.0]}},{\"line\":{\"fromMm\":[43.0,-33.0],\"toMm\":[37.296980052734526,-33.0]}},{\"arc\":{\"ccw\":false,\"centerMm\":[59.20588235294099,-13.99999999999998],\"endMm\":[30.521177652752534,-18.264705882352946],\"radiusMm\":28.999999999999883,\"startMm\":[37.296980052734526,-33.0]}},{\"arc\":{\"ccw\":true,\"centerMm\":[25.575538911340765,-18.99999999999997],\"endMm\":[25.5755389113407,-14.0],\"radiusMm\":4.9999999999999325,\"startMm\":[30.521177652752534,-18.264705882352946]}},{\"line\":{\"fromMm\":[25.5755389113407,-14.0],\"toMm\":[-7.0,-14.0]}},{\"line\":{\"fromMm\":[-14.0,-7.0],\"toMm\":[-14.0,11.000000000000002]}},{\"line\":{\"fromMm\":[-7.0,18.0],\"toMm\":[0.0,18.0]}},{\"line\":{\"fromMm\":[-14.0,11.000000000000002],\"toMm\":[-7.0,18.0]}},{\"line\":{\"fromMm\":[-7.0,-14.0],\"toMm\":[-14.0,-7.0]}},{\"line\":{\"fromMm\":[67.0,25.0],\"toMm\":[72.0,20.0]}},{\"circle\":{\"centerMm\":[0.0,0.0],\"radiusMm\":7.0}}],\"mapped\":false,\"plane\":\"Front Plane\",\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"sketch.line\",\"what\":\"lines of a closed contour (line, polyline, polygon, slot, rounded rect): ISketchManager::CreateLine\"},{\"variant\":\"sketch.arc\",\"what\":\"arcs of a closed contour (arc, arc3, tangentArc, slot, rounded rect): ISketchManager::CreateArc\"}],\"variants\":[\"sketch.plane.front\",\"sketch.circle\",\"sketch.multiProfile\",\"sketch.line\",\"sketch.arc\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"},\"resolvedPlane\":null,\"sketch\":\"Sketch13\",\"sketchNormal\":[0.0,0.0,1.0],\"sketchedOn\":\"Front Plane\",\"transformInverted\":false},\"step\":2},{\"op\":\"extrude\",\"result\":{\"depth2Mm\":null,\"depthMm\":44.0,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":null,\"sketchNormal\":[0.0,0.0,1.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Boss-Extrude10\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"extrude.one\"]},\"reverse\":false,\"sketch\":\"Sketch13\",\"throughAll\":false,\"upToFace\":null},\"step\":3},{\"op\":\"set_material\",\"result\":{\"appearanceReapplied\":[],\"current\":{\"database\":\"SOLIDWORKS Materials\",\"name\":\"AISI 1020\"},\"database\":\"SOLIDWORKS Materials.sldmat\",\"densityKgM3\":7899.999999999999,\"densityRequested\":7900.0,\"material\":\"AISI 1020\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"set_material.density\",\"what\":\"a density in kg/m\u00b3 (the document's own, or checked against the material's)\"}],\"variants\":[\"set_material\",\"set_material.density\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"}},\"step\":4},{\"op\":\"sketch\",\"result\":{\"createdPlane\":\"Plane4\",\"entities\":[{\"circle\":{\"centerMm\":[72.0,28.70187343596344],\"radiusMm\":41.0}}],\"mapped\":true,\"plane\":{\"offsetFrom\":{\"face\":{\"atPointMm\":[-10.0,0.0,0.0]}},\"offsetMm\":-12.0},\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"sketch.faceOffset\",\"what\":\"a sketch on a plane offset from a picked face (along its outward normal)\"}],\"variants\":[\"sketch.faceOffset\",\"sketch.circle\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"},\"radiusMm\":41.0,\"resolvedPlane\":{\"faceNormal\":[-0.0,-0.0,-1.0],\"faceOffsetMm\":-12.0,\"fromFace\":true,\"offsetFrom\":\"Front Plane\",\"offsetMm\":12.0,\"pickedBy\":\"geometry\",\"plane\":\"Plane4\",\"verified\":true},\"sketch\":\"Sketch14\",\"sketchNormal\":[0.0,0.0,1.0],\"sketchedOn\":\"Plane4\",\"transformInverted\":false},\"step\":5},{\"op\":\"cut\",\"result\":{\"depth2Mm\":null,\"depthMm\":24.0,\"dir\":{\"flippedToFollowTheReference\":true,\"reference\":[-0.0,-0.0,-1.0],\"sketchNormal\":[0.0,0.0,1.0],\"value\":true},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Cut-Extrude4\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"cut.one.reversed\"]},\"reverse\":false,\"sketch\":\"Sketch14\",\"throughAll\":false,\"upToFace\":null},\"step\":6},{\"op\":\"sketch\",\"result\":{\"createdPlane\":null,\"entities\":[{\"rect\":{\"cornersMm\":[[-20.0,-40.0],[85.99999999999999,-13.999999999999998]]}}],\"heightMm\":26.0,\"mapped\":true,\"plane\":{\"face\":{\"atPointMm\":[-10.0,0.0,44.0]}},\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"sketch.face.front.positive\",\"what\":\"a sketch on a face facing +Z\"}],\"variants\":[\"sketch.face.front.positive\",\"sketch.rect\",\"select.multiSelectTyped\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"},\"resolvedPlane\":{\"faceNormal\":[0.0,0.0,1.0],\"offsetFrom\":\"Front Plane\",\"offsetMm\":44.0,\"pickedBy\":\"geometry\",\"selectedVia\":\"MultiSelect2(typed array)\",\"viewDependent\":false},\"sketch\":\"Sketch15\",\"sketchNormal\":[0.0,0.0,1.0],\"sketchedOn\":\"the picked face\",\"transformInverted\":false,\"widthMm\":106.0},\"step\":7},{\"op\":\"cut\",\"result\":{\"depth2Mm\":null,\"depthMm\":19.0,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":[0.0,0.0,1.0],\"sketchNormal\":[0.0,0.0,1.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Cut-Extrude5\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"cut.one\"]},\"reverse\":false,\"sketch\":\"Sketch15\",\"throughAll\":false,\"upToFace\":null},\"step\":8},{\"op\":\"sketch\",\"result\":{\"createdPlane\":null,\"entities\":[{\"rect\":{\"cornersMm\":[[-20.0,-40.0],[20.0,40.0]]}}],\"heightMm\":80.0,\"mapped\":true,\"plane\":{\"face\":{\"atPointMm\":[-10.0,0.0,44.0]}},\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"sketch.face.front.positive\",\"what\":\"a sketch on a face facing +Z\"}],\"variants\":[\"sketch.face.front.positive\",\"sketch.rect\",\"select.multiSelectTyped\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"},\"resolvedPlane\":{\"faceNormal\":[0.0,0.0,1.0],\"offsetFrom\":\"Front Plane\",\"offsetMm\":44.0,\"pickedBy\":\"geometry\",\"selectedVia\":\"MultiSelect2(typed array)\",\"viewDependent\":false},\"sketch\":\"Sketch16\",\"sketchNormal\":[0.0,0.0,1.0],\"sketchedOn\":\"the picked face\",\"transformInverted\":false,\"widthMm\":40.0},\"step\":9},{\"op\":\"cut\",\"result\":{\"depth2Mm\":null,\"depthMm\":19.0,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":[0.0,0.0,1.0],\"sketchNormal\":[0.0,0.0,1.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":0,\"feature\":\"Cut-Extrude6\",\"proven\":{\"live\":true,\"measuredOn\":[{\"bridge\":\"0.10.3\",\"by\":\"adom\",\"date\":\"2026-10-14\",\"edition\":\"connected\",\"major\":34,\"solidworks\":2026},{\"bridge\":\"0.10.9\",\"by\":\"community\",\"date\":\"2026-10-15\",\"edition\":\"desktop\",\"major\":29,\"solidworks\":2021}],\"variants\":[\"cut.one\"]},\"reverse\":false,\"sketch\":\"Sketch16\",\"throughAll\":false,\"upToFace\":null},\"step\":10},{\"op\":\"hole\",\"result\":{\"depthMm\":null,\"diameterMm\":11.0,\"face\":{\"atPointMm\":[58.0,11.0,44.0],\"heightMm\":44.0,\"normal\":[0.0,0.0,1.0],\"pickedBy\":\"geometry\",\"plane\":\"Front Plane\"},\"feature\":\"Cut-Extrude7\",\"features\":[\"Cut-Extrude7\"],\"proven\":{\"live\":false,\"measuredOn\":[],\"unmeasured\":[{\"variant\":\"hole.simple\",\"what\":\"a plain hole: a circle on the face's plane, cut blind or through all\"}],\"variants\":[\"hole.simple\"],\"why\":\"not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies\"},\"steps\":[{\"op\":\"sketch\",\"result\":{\"createdPlane\":\"Plane5\",\"entities\":[{\"circle\":{\"centerMm\":[58.0,11.0],\"radiusMm\":5.5}}],\"mapped\":true,\"plane\":{\"offsetFrom\":\"Front Plane\",\"offsetMm\":44.0},\"planeFrames\":\"plane transforms (they match the measured Front/Top axes)\",\"radiusMm\":5.5,\"resolvedPlane\":{\"offsetFrom\":\"Front Plane\",\"offsetMm\":44.0,\"plane\":\"Plane5\",\"verified\":true},\"sketch\":\"Sketch17\",\"sketchNormal\":[0.0,0.0,1.0],\"sketchedOn\":\"Plane5\",\"transformInverted\":false}},{\"op\":\"cut\",\"result\":{\"depth2Mm\":null,\"depthMm\":0.0,\"dir\":{\"flippedToFollowTheReference\":false,\"reference\":[0.0,0.0,1.0],\"sketchNormal\":[0.0,0.0,1.0],\"value\":false},\"direction\":\"one\",\"draftDeg\":null,\"draftInward\":null,\"endCondition\":1,\"feature\":\"Cut-Extrude7\",\"reverse\":false,\"sketch\":\"Sketch17\",\"throughAll\":true,\"upToFace\":null}}],\"throughAll\":true},\"step\":11}],\"success\":true,\"targetDocument\":\"Part1-1792105365003.SLDPRT\",\"timeoutSeconds\":420}",+    "progress": {+     "confidence": "estimate",+     "elapsedSec": 18.7,+     "estimatedSec": 30,+     "etaSec": 0,+     "percent": 100,+     "phase": "run_script",+     "startKind": "warm",+     "stepLabel": "Running 11 modeling step(s)"+    },+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "solidworksRevision": "34.3.0",+    "status": "ok",+    "statusVerb": "swx_status",+    "stepCount": 11,+    "steps": [+     {+      "op": "clear_part",+      "result": {+       "bodiesLeft": 0,+       "cleared": "Part1-1792105365003.SLDPRT",+       "deleted": [+        "Sketch12",+        "Boss-Extrude9"+       ],+       "featuresDeleted": 2,+       "passes": 1,+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.6",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "clear_part"+        ]+       },+       "route": "DeleteSelection2(swDelete_Children | swDelete_Absorbed), repeated until the tree is empty"+      },+      "step": 1+     },+     {+      "op": "sketch",+      "result": {+       "createdPlane": null,+       "entities": [+        {+         "line": {+          "fromMm": [+           0.0,+           18.0+          ],+          "toMm": [+           22.3613808357771,+           14.057085232755291+          ]+         }+        },+        {+         "arc": {+          "ccw": true,+          "centerMm": [+           25.66069621144878,+           32.768432539987224+          ],+          "endMm": [+           43.0,+           25.0+          ],+          "radiusMm": 18.99999999999998,+          "startMm": [+           22.3613808357771,+           14.057085232755291+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           43.0,+           25.0+          ],+          "toMm": [+           67.0,+           25.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           72.0,+           20.0+          ],+          "toMm": [+           72.0,+           1.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           72.0,+           1.0+          ],+          "toMm": [+           43.0,+           -33.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           43.0,+           -33.0+          ],+          "toMm": [+           37.296980052734526,+           -33.0+          ]+         }+        },+        {+         "arc": {+          "ccw": false,+          "centerMm": [+           59.20588235294099,+           -13.99999999999998+          ],+          "endMm": [+           30.521177652752534,+           -18.264705882352946+          ],+          "radiusMm": 28.999999999999883,+          "startMm": [+           37.296980052734526,+           -33.0+          ]+         }+        },+        {+         "arc": {+          "ccw": true,+          "centerMm": [+           25.575538911340765,+           -18.99999999999997+          ],+          "endMm": [+           25.5755389113407,+           -14.0+          ],+          "radiusMm": 4.9999999999999325,+          "startMm": [+           30.521177652752534,+           -18.264705882352946+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           25.5755389113407,+           -14.0+          ],+          "toMm": [+           -7.0,+           -14.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           -14.0,+           -7.0+          ],+          "toMm": [+           -14.0,+           11.000000000000002+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           -7.0,+           18.0+          ],+          "toMm": [+           0.0,+           18.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           -14.0,+           11.000000000000002+          ],+          "toMm": [+           -7.0,+           18.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           -7.0,+           -14.0+          ],+          "toMm": [+           -14.0,+           -7.0+          ]+         }+        },+        {+         "line": {+          "fromMm": [+           67.0,+           25.0+          ],+          "toMm": [+           72.0,+           20.0+          ]+         }+        },+        {+         "circle": {+          "centerMm": [+           0.0,+           0.0+          ],+          "radiusMm": 7.0+         }+        }+       ],+       "mapped": false,+       "plane": "Front Plane",+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "sketch.line",+          "what": "lines of a closed contour (line, polyline, polygon, slot, rounded rect): ISketchManager::CreateLine"+         },+         {+          "variant": "sketch.arc",+          "what": "arcs of a closed contour (arc, arc3, tangentArc, slot, rounded rect): ISketchManager::CreateArc"+         }+        ],+        "variants": [+         "sketch.plane.front",+         "sketch.circle",+         "sketch.multiProfile",+         "sketch.line",+         "sketch.arc"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       },+       "resolvedPlane": null,+       "sketch": "Sketch13",+       "sketchNormal": [+        0.0,+        0.0,+        1.0+       ],+       "sketchedOn": "Front Plane",+       "transformInverted": false+      },+      "step": 2+     },+     {+      "op": "extrude",+      "result": {+       "depth2Mm": null,+       "depthMm": 44.0,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": null,+        "sketchNormal": [+         0.0,+         0.0,+         1.0+        ],+        "value": false+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Boss-Extrude10",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "extrude.one"+        ]+       },+       "reverse": false,+       "sketch": "Sketch13",+       "throughAll": false,+       "upToFace": null+      },+      "step": 3+     },+     {+      "op": "set_material",+      "result": {+       "appearanceReapplied": [],+       "current": {+        "database": "SOLIDWORKS Materials",+        "name": "AISI 1020"+       },+       "database": "SOLIDWORKS Materials.sldmat",+       "densityKgM3": 7899.999999999999,+       "densityRequested": 7900.0,+       "material": "AISI 1020",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "set_material.density",+          "what": "a density in kg/m\u00b3 (the document's own, or checked against the material's)"+         }+        ],+        "variants": [+         "set_material",+         "set_material.density"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       }+      },+      "step": 4+     },+     {+      "op": "sketch",+      "result": {+       "createdPlane": "Plane4",+       "entities": [+        {+         "circle": {+          "centerMm": [+           72.0,+           28.70187343596344+          ],+          "radiusMm": 41.0+         }+        }+       ],+       "mapped": true,+       "plane": {+        "offsetFrom": {+         "face": {+          "atPointMm": [+           -10.0,+           0.0,+           0.0+          ]+         }+        },+        "offsetMm": -12.0+       },+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "sketch.faceOffset",+          "what": "a sketch on a plane offset from a picked face (along its outward normal)"+         }+        ],+        "variants": [+         "sketch.faceOffset",+         "sketch.circle"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       },+       "radiusMm": 41.0,+       "resolvedPlane": {+        "faceNormal": [+         -0.0,+         -0.0,+         -1.0+        ],+        "faceOffsetMm": -12.0,+        "fromFace": true,+        "offsetFrom": "Front Plane",+        "offsetMm": 12.0,+        "pickedBy": "geometry",+        "plane": "Plane4",+        "verified": true+       },+       "sketch": "Sketch14",+       "sketchNormal": [+        0.0,+        0.0,+        1.0+       ],+       "sketchedOn": "Plane4",+       "transformInverted": false+      },+      "step": 5+     },+     {+      "op": "cut",+      "result": {+       "depth2Mm": null,+       "depthMm": 24.0,+       "dir": {+        "flippedToFollowTheReference": true,+        "reference": [+         -0.0,+         -0.0,+         -1.0+        ],+        "sketchNormal": [+         0.0,+         0.0,+         1.0+        ],+        "value": true+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Cut-Extrude4",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "cut.one.reversed"+        ]+       },+       "reverse": false,+       "sketch": "Sketch14",+       "throughAll": false,+       "upToFace": null+      },+      "step": 6+     },+     {+      "op": "sketch",+      "result": {+       "createdPlane": null,+       "entities": [+        {+         "rect": {+          "cornersMm": [+           [+            -20.0,+            -40.0+           ],+           [+            85.99999999999999,+            -13.999999999999998+           ]+          ]+         }+        }+       ],+       "heightMm": 26.0,+       "mapped": true,+       "plane": {+        "face": {+         "atPointMm": [+          -10.0,+          0.0,+          44.0+         ]+        }+       },+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "sketch.face.front.positive",+          "what": "a sketch on a face facing +Z"+         }+        ],+        "variants": [+         "sketch.face.front.positive",+         "sketch.rect",+         "select.multiSelectTyped"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       },+       "resolvedPlane": {+        "faceNormal": [+         0.0,+         0.0,+         1.0+        ],+        "offsetFrom": "Front Plane",+        "offsetMm": 44.0,+        "pickedBy": "geometry",+        "selectedVia": "MultiSelect2(typed array)",+        "viewDependent": false+       },+       "sketch": "Sketch15",+       "sketchNormal": [+        0.0,+        0.0,+        1.0+       ],+       "sketchedOn": "the picked face",+       "transformInverted": false,+       "widthMm": 106.0+      },+      "step": 7+     },+     {+      "op": "cut",+      "result": {+       "depth2Mm": null,+       "depthMm": 19.0,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": [+         0.0,+         0.0,+         1.0+        ],+        "sketchNormal": [+         0.0,+         0.0,+         1.0+        ],+        "value": false+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Cut-Extrude5",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "cut.one"+        ]+       },+       "reverse": false,+       "sketch": "Sketch15",+       "throughAll": false,+       "upToFace": null+      },+      "step": 8+     },+     {+      "op": "sketch",+      "result": {+       "createdPlane": null,+       "entities": [+        {+         "rect": {+          "cornersMm": [+           [+            -20.0,+            -40.0+           ],+           [+            20.0,+            40.0+           ]+          ]+         }+        }+       ],+       "heightMm": 80.0,+       "mapped": true,+       "plane": {+        "face": {+         "atPointMm": [+          -10.0,+          0.0,+          44.0+         ]+        }+       },+       "planeFrames": "plane transforms (they match the measured Front/Top axes)",+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "sketch.face.front.positive",+          "what": "a sketch on a face facing +Z"+         }+        ],+        "variants": [+         "sketch.face.front.positive",+         "sketch.rect",+         "select.multiSelectTyped"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       },+       "resolvedPlane": {+        "faceNormal": [+         0.0,+         0.0,+         1.0+        ],+        "offsetFrom": "Front Plane",+        "offsetMm": 44.0,+        "pickedBy": "geometry",+        "selectedVia": "MultiSelect2(typed array)",+        "viewDependent": false+       },+       "sketch": "Sketch16",+       "sketchNormal": [+        0.0,+        0.0,+        1.0+       ],+       "sketchedOn": "the picked face",+       "transformInverted": false,+       "widthMm": 40.0+      },+      "step": 9+     },+     {+      "op": "cut",+      "result": {+       "depth2Mm": null,+       "depthMm": 19.0,+       "dir": {+        "flippedToFollowTheReference": false,+        "reference": [+         0.0,+         0.0,+         1.0+        ],+        "sketchNormal": [+         0.0,+         0.0,+         1.0+        ],+        "value": false+       },+       "direction": "one",+       "draftDeg": null,+       "draftInward": null,+       "endCondition": 0,+       "feature": "Cut-Extrude6",+       "proven": {+        "live": true,+        "measuredOn": [+         {+          "bridge": "0.10.3",+          "by": "adom",+          "date": "2026-10-14",+          "edition": "connected",+          "major": 34,+          "solidworks": 2026+         },+         {+          "bridge": "0.10.9",+          "by": "community",+          "date": "2026-10-15",+          "edition": "desktop",+          "major": 29,+          "solidworks": 2021+         }+        ],+        "variants": [+         "cut.one"+        ]+       },+       "reverse": false,+       "sketch": "Sketch16",+       "throughAll": false,+       "upToFace": null+      },+      "step": 10+     },+     {+      "op": "hole",+      "result": {+       "depthMm": null,+       "diameterMm": 11.0,+       "face": {+        "atPointMm": [+         58.0,+         11.0,+         44.0+        ],+        "heightMm": 44.0,+        "normal": [+         0.0,+         0.0,+         1.0+        ],+        "pickedBy": "geometry",+        "plane": "Front Plane"+       },+       "feature": "Cut-Extrude7",+       "features": [+        "Cut-Extrude7"+       ],+       "proven": {+        "live": false,+        "measuredOn": [],+        "unmeasured": [+         {+          "variant": "hole.simple",+          "what": "a plain hole: a circle on the face's plane, cut blind or through all"+         }+        ],+        "variants": [+         "hole.simple"+        ],+        "why": "not measured live: see `unmeasured` \u2014 verify this step's geometry with swx_inspect_bodies"+       },+       "steps": [+        {+         "op": "sketch",+         "result": {+          "createdPlane": "Plane5",+          "entities": [+           {+            "circle": {+             "centerMm": [+              58.0,+              11.0+             ],+             "radiusMm": 5.5+            }+           }+          ],+          "mapped": true,+          "plane": {+           "offsetFrom": "Front Plane",+           "offsetMm": 44.0+          },+          "planeFrames": "plane transforms (they match the measured Front/Top axes)",+          "radiusMm": 5.5,+          "resolvedPlane": {+           "offsetFrom": "Front Plane",+           "offsetMm": 44.0,+           "plane": "Plane5",+           "verified": true+          },+          "sketch": "Sketch17",+          "sketchNormal": [+           0.0,+           0.0,+           1.0+          ],+          "sketchedOn": "Plane5",+          "transformInverted": false+         }+        },+        {+         "op": "cut",+         "result": {+          "depth2Mm": null,+          "depthMm": 0.0,+          "dir": {+           "flippedToFollowTheReference": false,+           "reference": [+            0.0,+            0.0,+            1.0+           ],+           "sketchNormal": [+            0.0,+            0.0,+            1.0+           ],+           "value": false+          },+          "direction": "one",+          "draftDeg": null,+          "draftInward": null,+          "endCondition": 1,+          "feature": "Cut-Extrude7",+          "reverse": false,+          "sketch": "Sketch17",+          "throughAll": true,+          "upToFace": null+         }+        }+       ],+       "throughAll": true+      },+      "step": 11+     }+    ],+    "success": true,+    "targetDocument": "Part1-1792105365003.SLDPRT",+    "timeoutSeconds": 420+   },+   "massProperties": {+    "_hint": "SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.",+    "_timeoutHint": "ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.",+    "boundingBox": [+     -0.014,+     -0.033,+     0.0,+     0.07200000000000001,+     0.025,+     0.044+    ],+    "centerOfMass": [+     0.03174279639698831,+     -0.0008683174573996883,+     0.017834837095750275+    ],+    "centerOfMassMm": [+     31.742796,+     -0.868317,+     17.834837+    ],+    "density": 7900.0,+    "densityKgM3": 7900.0,+    "doc": {+     "config": "Default",+     "dirty": true,+     "path": "C:/Users/drew/AppData/Local/adom-solidworks-bridge/exports/scratch/Part1-1792105365003.SLDPRT",+     "title": "Part1-1792105365003.SLDPRT",+     "type": "part"+    },+    "durationMs": 2150,+    "error": "",+    "massG": 628.1833833399141,+    "massKg": 0.6281833833399142,+    "materialName": "AISI 1020",+    "output": "{\"_hint\":\"SI units: kg, m^3, m^2, m. Mass is only as good as the material assignment \u2014 a 0 or default density means no material is set on the model, so report the density alongside the mass.\",\"_timeoutHint\":\"ab waits up to 120s for this verb before the request times out. If it's a long operation (cloud open / download / export), DON'T treat a timeout as failure \u2014 the work usually keeps running on the bridge. Poll `swx_status` until it reports done.\",\"boundingBox\":[-0.014,-0.033,0.0,0.07200000000000001,0.025,0.044],\"centerOfMass\":[0.03174279639698831,-0.0008683174573996883,0.017834837095750275],\"centerOfMassMm\":[31.742796,-0.868317,17.834837],\"density\":7900.0,\"densityKgM3\":7900.0,\"doc\":{\"config\":\"Default\",\"dirty\":true,\"path\":\"C:\\\\Users\\\\drew\\\\AppData\\\\Local\\\\adom-solidworks-bridge\\\\exports\\\\scratch\\\\Part1-1792105365003.SLDPRT\",\"title\":\"Part1-1792105365003.SLDPRT\",\"type\":\"part\"},\"massG\":628.1833833399141,\"massKg\":0.6281833833399142,\"materialName\":\"AISI 1020\",\"readiness\":{\"basedOn\":[\"alreadyReadyThisSession\"],\"evaluatedAt\":\"gate\",\"readsAllowed\":true,\"ready\":true,\"running\":true,\"state\":\"ready\",\"why\":null},\"statusVerb\":\"swx_status\",\"success\":true,\"surfaceAreaM2\":0.01771252880409412,\"surfaceAreaMm2\":17712.52880409412,\"timeoutSeconds\":120,\"volumeM3\":0.00007951688396707775,\"volumeMm3\":79516.88396707775}",+    "readiness": {+     "basedOn": [+      "alreadyReadyThisSession"+     ],+     "evaluatedAt": "gate",+     "readsAllowed": true,+     "ready": true,+     "running": true,+     "state": "ready",+     "why": null+    },+    "schemaVersion": 1,+    "status": "ok",+    "statusVerb": "swx_status",+    "success": true,+    "surfaceAreaM2": 0.01771252880409412,+    "surfaceAreaMm2": 17712.52880409412,+    "timeoutSeconds": 120,+    "volumeM3": 7.951688396707775e-05,+    "volumeMm3": 79516.88396707775+   },+   "pass": true,+   "checks": [+    {+     "quantity": "massG",+     "expected": 628.18,+     "measured": 628.1833833399141,+     "offPct": 0.0005385940198978062,+     "pass": true+    }+   ],+   "fails": [],+   "seconds": 23.0+  },+  {+   "id": "cswa-08-tool-block-step4",+   "title": "Official Tool Block, Step 4 (Q6): a pocket 1 mm inside the front face's outline",+   "official": true,+   "source": "https://www.solidworks.com/sites/default/files/2017-12/CSWASampleExam.pdf (Dassault CSWA Sample Exam, 2017 edition; archive http://web.archive.org/web/20251230104817/https://www.solidworks.com/sites/default/files/2017-12/CSWASampleExam.pdf)",+   "expected": {+    "massG": 432.58,+    "tolerancePct": 1.0+   },+   "material": {+    "name": "AISI 1020",+    "densityKgM3": 7900+   },+   "skipped": "needs ops the bridge does not have yet: offsetEntities"+  }+ ]+}\ No newline at end of file
tools/cswa/tb34.pyadded+77
@@ -0,0 +1,77 @@+import math, sys+sys.path.insert(0,'.')+from tb2 import toolblock, area+def clip_halfplane(poly, nx, ny, c):+    # keep points with nx*x+ny*y <= c+    out=[]; n=len(poly)+    for i in range(n):+        P=poly[i]; Q=poly[(i+1)%n]+        pin=nx*P[0]+ny*P[1]<=c; qin=nx*Q[0]+ny*Q[1]<=c+        if pin: out.append(P)+        if pin!=qin:+            t=(c-nx*P[0]-ny*P[1])/((nx*(Q[0]-P[0])+ny*(Q[1]-P[1])))+            out.append((P[0]+t*(Q[0]-P[0]),P[1]+t*(Q[1]-P[1])))+    return out+def clip_disc(poly,cx,cy,r,n=720):+    for k in range(n):+        a=2*math.pi*k/n; nx,ny=math.cos(a),math.sin(a)+        poly=clip_halfplane(poly,nx,ny,nx*cx+ny*cy+r)+        if not poly: break+    return poly+def circle_poly(cx,cy,r,n=2000): return [(cx+r*math.cos(2*math.pi*i/n),cy+r*math.sin(2*math.pi*i/n)) for i in range(n)]+A,B,C=86,58,44+prof,_,info,P=toolblock(A,B,C,top=B-33.0,redge=B-57.0)+Aprof=area(P)   # outer profile without holes+hole14=math.pi*49; hole11=math.pi*5.5**2+xstep=(A-52)-14.0   # hole coords+Pstep=clip_halfplane(P,1,0,xstep); Astep=area(Pstep)+print("profile area (no holes) %.2f ; step region (x<=%.0f) area %.2f"%(Aprof,xstep,Astep))+target3=628.18/0.0079; target4=432.58/0.0079+def vol3(cx,cy,zslot=24.0,zstep=19.0):+    Aslot=area(clip_disc(P,cx,cy,41.0))+    V=Aprof*C - Astep*zstep - Aslot*zslot - hole14*(C-zstep) - hole11*(C-zslot)+    return V,Aslot+xR=A-14.0+# hypotheses for R41 center+yc_flank36 = -11+math.sqrt(41**2-(xR-(43+29*(22/34.0)))**2)+cands=[("center on right edge, thru flank@36 -> (72,%.2f)"%yc_flank36,(xR,yc_flank36)),+       ("center top-right corner (72,25)",(xR,25.0)),+       ("pixel fit (72.4,28.6)",(72.4,28.6)),+       ("center (72,28.0)",(xR,28.0)),("center (72,29.5)",(xR,29.5))]+for name,(cx,cy) in cands:+    V,As=vol3(cx,cy); print("STEP3 %-50s slotA=%.1f V=%.1f mass=%.2f (key 628.18, diff %+.2f%%)"%(name,As,V,V*0.0079,(V/target3-1)*100))+# sensitivity: slot z-width 24 vs step side+cx,cy=xR,yc_flank36+for zs in (22,24,26):+    V,_=vol3(cx,cy,zslot=zs); print("   zslot=%d -> mass %.2f"%(zs,V*0.0079))+# STEP 4: pocket. Outline = outer profile offset 1 inward, clipped to x>=xstep+1 and y>=-13; depth 32 from front (leaves 12 at back)+def offset_inward(poly,d,n=None):+    # approximate inward offset by clipping with every edge's half-plane shifted by d (valid for convex-ish boundary parts; polygon here is non-convex, so do per-edge clipping only on edges we care about -> use generic approach: clip by each edge halfplane shifted inward)+    out=poly+    m=len(poly)+    # signed area to know orientation+    s=sum(poly[i][0]*poly[(i+1)%m][1]-poly[(i+1)%m][0]*poly[i][1] for i in range(m))+    ccw = s>0+    for i in range(m):+        P0=poly[i]; P1=poly[(i+1)%m]+        ex,ey=P1[0]-P0[0],P1[1]-P0[1]; L=math.hypot(ex,ey)+        if L<1e-9: continue+        # outward normal+        nx,ny=(ey/L,-ex/L) if ccw else (-ey/L,ex/L)+        c=nx*P0[0]+ny*P0[1]-d+        # only clip with edges that are on the right-lobe region boundary (x>xstep-5) to avoid the notch/left lobe edges eating the pocket wrongly+        if max(P0[0],P1[0])<xstep-1: continue+        if P0[1]<-13.5 and P1[1]<-13.5 and max(P0[0],P1[0])<xR-29: continue  # skip V-notch edges (below pocket floor)+        out=clip_halfplane(out,nx,ny,c)+        if not out: break+    return out+Ppk=offset_inward(P,1.0)+Ppk=clip_halfplane(Ppk,-1,0,-(xstep+1.0))   # x >= xstep+1+Ppk=clip_halfplane(Ppk,0,-1,13.0)           # y >= -13+Apk=area(Ppk); Apk_in=area(clip_disc(Ppk,cx,cy,41.0)); Apk_out=Apk-Apk_in+print("pocket area total %.2f (inside slot disc %.2f, outside %.2f); bbox x %.2f..%.2f y %.2f..%.2f"%(Apk,Apk_in,Apk_out,min(p[0] for p in Ppk),max(p[0] for p in Ppk),min(p[1] for p in Ppk),max(p[1] for p in Ppk)))+V3,_=vol3(cx,cy)+for name,pv in [("pocket depth 32 (floor 12 at back)",Apk_out*32+(Apk_in-hole11)*8),+                ("pocket depth 32, hole not excluded",Apk_out*32+Apk_in*8),+                ("pocket depth 12 only (front ear 8 + 4 into slot)",Apk_out*12+(Apk_in-hole11)*8)]:+    V4=V3-pv; print("STEP4 %-45s V=%.1f mass=%.2f (key 432.58, diff %+.2f%%)"%(name,V4,V4*0.0079,(V4/target4-1)*100))
uninstall.sh