SOLIDWORKS Bridge
Public Made by Adomby adom
Launch, model and quit SOLIDWORKS from any Adom container. Nothing is ever lost.
Launch, sign-in and readiness — swx
Read this before starting SOLIDWORKS, while waiting through a launch or a 3DEXPERIENCE sign-in, or when deciding whether it is ready. Part of the solidworks-bridge skill — SKILL.md beside this folder has the rules that never bend. Trust each verb's own reply (_hint, errorCode) over anything written here.
Install, launch, sign-in
This edition cannot be launched by COM, so do not try. The install here is SOLIDWORKS Connected / Makers (3DEXPERIENCE), and
swx_statusreportscanLaunchProgrammatically:false. COM can ATTACH to a session that is already running; it cannot create one. That is a property of the edition, not a limitation of the bridge, so there is no argument or retry that changes it.The launch that works is the Platform's own shortcut.
swx_startinvokes the 3DEXPERIENCE Platform.lnk, which startsCATSTART.exe, which startsSWXDesktopLauncher.exe, which startssldworks.exe. The launcher chain then exits — oncesldworks.exeis up there is no launcher process left to poll or to reap.The
shellExecuteroute hands back a real handle, proven live 2026-09-11. It invokes throughShellExecuteExWwithSEE_MASK_NOCLOSEPROCESS; the live run got a process handle back (CATSTART pid 131272, creation time 1789148101) and that chain reached the launcher'sRun Begin. This matters because the bridge's law is no handle, no kill: it may only clean up a chain the invoke itself handed back. On this machine that world is confirmed.stage:"helperSignIn"means a human has to type a password — you cannot. A cold launch can stop at the 3DEXPERIENCE ID window: a NATIVE WebView2 window, classDSYSysLoginPanelWebView2Class, title "Login | 3DEXPERIENCE ID | Dassault Systemes", owned bySWXDesktopLauncher.exein the bridge's own chain. UIA sees NO controls inside it, so nothing can read or fill it — this bridge included. As of 0.6.0 the bridge recognises the window, reportshelperSignIn, PAUSES every launch deadline while it is on screen (a waiting human is not a stall), never kills or escalates the chain, and toasts the user that sign-in is needed. Your move is to keep polling and, if the user asks what to do, tell them to sign in and to tick Remember me once so later launches do not stop here. The bridge never asks for, stores or transmits a password.How long
helperSignInlasts depends on the user answering the window, not on any timer the bridge owns. Do not convert it into a failure.Read
launch.stageand act on it, fromswx_statusor fromswx_start:stageWhat to do invokedThe route was just invoked. Poll swx_status.launcherStartedChain running, Run Beginnot reached. This is the stage that stalls; the bridge cleans up and tries the next route itself. Do not invoke the shortcut any other way.runBeginThe chain is really building. Keep polling; sldworks.exeappears within seconds.helperSignInOnly the user can clear it. Poll; tell them to look at their screen. sldworksUpThe application exists, COM does not answer yet. Keep polling. attachingPolling for the COM server. Keep polling; do not launch again. attachedCOM is usable. This is the only success — carry on. stalledThat route stalled and its chain was cleaned up. The bridge is trying the next route. Nothing for you to retry. exhaustedEvery route was tried and none attached. ASK THE USER to start SOLIDWORKS from the Start Menu or the Platform. The three milestones that matter operationally are
runBegin(the chain is really building),sldworksUp(the application exists) andattached(COM is usable, and the only success).stillLaunching:truemeans a launch this bridge started is still in flight. Callingswx_startagain does NOT start a second chain — it attaches to the one in flight. That is deliberate: four launcher chains once ended up on a user's desktop because a caller retried. Polling withswx_startis therefore safe, and a second invocation by any other route is not.swx_stopquits ONLY a session with zero documents open, andforcedoes not waive that (forcewaives the UNSAVED question only). If documents are open, close them first, or drain leaked conversion temporaries withswx_close_import_temps.Treat a quit as close to a one-way door. On this edition relaunching after a quit takes 1-3 minutes and can stop at the sign-in window again, which only the user can answer. Do not quit to tidy up.
Is it ready?
attachedis notready. MEASURED 2026-10-01: document commands sent 8 s after COM attach crashed SOLIDWORKS while its 3DEXPERIENCE add-in was still initialising.swx_startnow reportsstage:"starting"(stillStarting:true) until SOLIDWORKS has finished starting, thenstage:"ready";swx_statussayssolidworks.readyand what it is based on (readiness.basedOn,readiness.performanceLog.verdictandwhy, and therule). EVERY verb that reaches SOLIDWORKS waits — the gate is the default since 0.9.5, and only a short list of verbs that never reach COM (status, start, describe, the disk and window verbs, kill) is exempt. They refusehost_app_startingwithretryAfterSecondsuntil then — wait that long and call again; never try to get around it.readinessTimedOut:truemeans it has been over five minutes: look at the user's screen (a dialog, a sign-in) rather than forcing anything.How ready is decided. The performance log only speaks for THIS session (written since the process started); a log from an earlier session is
notThisSession, nevercomplete. COM'sStartupProcessCompletedis true before the start finishes (measured), so it is never enough alone on a machine whose log writes 3DEXPERIENCE markers. An add-in loaded on demand after the start (a quiet log, an add-in other than 3DEXPERIENCE, COM true) does not make a started session "starting" again. A session that never loads the platform add-in (it can be disabled) is ready once its log is quiet and COM agrees; a log still being written holds the start. A session older than ten minutes whose COM says the start completed is never held by the log unless add-in loads are still appearing (longRunningSession), and a session seen ready stays ready across a bridge update.state:"unverifiable"— nothing can verify the start. After the grace (readsAllowed:true) READ verbs run; anything that creates, opens, saves, closes or changes a document refuses withstartingUnverifiable:true("cannot verify startup completed"). The clock never authorises a document command.Quitting during startup: under
userAuthorized:true,swx_stopwithmaxRung:"c"or"d"runs with the COM rungs skipped — the window-message rungs need neither COM nor a finished start.bridge_readiness(ab-level, never spawns anything) answers "is SOLIDWORKS installed / is the bridge warm" — use it for what-do-I-have questions.swx_readinessis the bridge's own read-only probe;swx_statusis the everyday state check (detection + COM attach + open docs);swx_get_app_stateis the one to POLL while something long runs.If SOLIDWORKS is not installed verbs return
errorCode:"host_app_not_installed". Dassault publishes NO silent installer — desktop trial serials come from a reseller, the Makers edition from the 3DEXPERIENCE Platform store. Don't tell the user to go download it; surface the returned_hint.If SOLIDWORKS is not running,
swx_startstarts it — including the Connected editions. Pass areason(it is written for the person whose desktop this is, and it is the only thing this verb needs — starting an application creates nothing and destroys nothing).- On classic desktop installs it attaches over COM.
- On 3DEXPERIENCE / Connected editions (including Design Professional
for Makers) it invokes the shortcut the Platform installed, which runs
CATSTART.exe -run SWXDesktopLauncher.exewith that user's tenant and registry. That is the launch Dassault sanctions. - A cold Connected start runs 1-3 minutes and may stop at a 3DEXPERIENCE
sign-in only the user can answer.
swx_startreturnsstarted:true, stillLaunching:truewhile it is coming up — that is not a failure. Pollswx_statusuntilrunning:true, or callswx_startagain, which ATTACHES to what is already coming up.waitSeconds:<n>(up to 240) blocks instead of polling. Never invoke the launcher any other way meanwhile — two launches means two sign-in windows on somebody's desktop. - Calling
swx_startduring a launch launches NOTHING (v0.4.0). It answersstillLaunching:true, launchedNow:falsewith the livestage(launcherStarted/runBegin/helperSignIn/sldworksUp/attaching), its age, and what to do — and it needs noreasonwhile an attempt is in flight, so polling with it is always safe.swx_statuscarries the samelaunchblock. - A stalled launcher recovers itself. The launcher chain sometimes starts
and then stops at
SecurityContext:without ever loggingRun Begin— it then sits idle forever and SOLIDWORKS never appears. A supervisor inside the bridge watches the launcher's OWN log, and on a stall it ends only theCATSTART/SWXDesktopLauncherchain it started itself and tries the next launch route, remembering whichever one works. There is nothing for you to retry, and nothing for you to clean up. - NO HANDLE, NO KILL — and the same rule for evidence. A launcher log is
read as this bridge's own only when the launcher's own writing-thread id
resolves to a process in our chain, or it is the sole candidate with no
other launch running; otherwise
unattributedLog:trueand it is not used. On a route that cannot say what it started, no log is attributed at all. One consequence worth knowing: if SOLIDWORKS comes up onexplorerorcmdStart, the launch SUCCEEDS and the route is never remembered —attachedproves SOLIDWORKS is usable, not that our route did it. - NO HANDLE, NO KILL. A process is only ever ended when the INVOKE ITSELF
handed back its root (
ShellExecuteExW's process handle, orStart-Process -PassThru's pid) and it descends from that root. TheexplorerandcmdStartroutes cannot say what they started, so a stall on either reportscleanup:"notAttributable"and terminates nothing — the response says a launcher chain may remain that the bridge cannot identify, which the user can end from Task Manager. If a route leaves something the bridge cannot account for, the machine STOPS rather than starting another chain beside it. - If SOLIDWORKS is running but unreachable,
swx_startwill not start a second one. It answershost_app_hung(Windows says the window is not responding AND a COM call exceeded its budget — only the user can end it),host_app_exhausted(NewDocumentcame back with no document — the one signal that proves it; close the bridge's own documents, then ASK THE USER to restart, and do not retry in a loop), orhost_app_com_unreachable(usually a sign-in window: ask the user to look at their screen).swx_status.solidworks.memoryAdvisoryreports a very large session as an OBSERVATION — a 13 GB SOLIDWORKS can be perfectly healthy, and this bridge no longer calls one out of room on a threshold. - "Not responding" is not "dead".
swx_status.solidworks.verdictisbusy/dead/unknown, from the CPU and memory DELTA across two reads (cpuActiveSeconds,memoryDeltaMB). A session at 17.9 GB was not-responding with a COM timeout for five minutes while burning 70% of a core — and it recovered.busymeans tell the user to wait; onlydead(no CPU over ≥15s, memory flat, no dialog) means only they can end it. One reading never says dead — poll again. - After a failed attempt the bridge waits (
host_app_launch_backoff, growing with each consecutive failure) and then tries ONE route rather than re-sweeping the plan. Retrying in a loop is how four launcher chains ended up on somebody's desktop; the honest move while it waits is to ASK THE USER to start SOLIDWORKS from their Start Menu. - Crash-reporter recovery ships OFF (
launch.crashRecovery:"off"). When armed it clicks the crash reporter's "Restart SOLIDWORKS Design" button once — but only on a window OWNED by the SOLIDWORKS being launched, and only when ab structurally confirms the button exists. It is disabled by default because the reply shape it reads has never been seen on a real desktop.
NEVER kill the 3DEXPERIENCE launcher daemons.
3DEXPERIENCELauncher.exe,3DEXPERIENCELauncherSysTray.exeand3DEXPERIENCELauncherService.exeare the Platform's own background services and carry the user's Platform session. They are not required for a launch (a successful launch on 2026-09-04 ran with no Backbone at all), so killing one buys nothing and breaks something that is not yours — and a real user launch rebuilds them, which is the fix if they are genuinely broken. The bridge's own kill allowlist is exactly two images,CATSTART.exeandSWXDesktopLauncher.exe, and only instances it created itself, terminated by pid. Do not reach fortaskkill/process_killagainst any of this yourself;sldworks.exeincluded (that isswx_kill, and it is gated behind the user's explicit opt-in).errorCode:"host_app_launch_blocked"now means only one thing: the bridge could not FIND a shortcut, not that the edition cannot be launched.swx_statusreportssolidworks.shortcutandsolidworks.launchRouteso you can see what it found; if the user has a shortcut elsewhere,SWX_SOLIDWORKS_SHORTCUT=<path to the .lnk>points the bridge at it. Do not runsldworks.exeyourself viashell_executeorlaunch_process— launching it DIRECTLY, bypassing the launcher chain, is what produces the "SOLIDWORKS Design must be launched from the 3DEXPERIENCE Platform" modal.
waitingOn:"userSignIn"onswx_start/swx_statusmeans a 3DEXPERIENCE ID login is up and the launch is waiting for the user to sign in.signInWindowis{hwnd, title, ownerImage, host, recognizedBy}; it was a bare title before 0.9.23. Any login window on the machine counts, found by class or title OR by content (an Edit "Email or username" or "Password" in it). Measured 2026-10-12: the platform updaterSWXDesktopUpdate.exeshowed a login titled just "3DEXPERIENCE" (host:"desktopUpdate") and the Visualize start was parked behind it.swx_start {app:"visualize"}now saysstage:"waitingOn"withvisualize.parkedBehindinstead ofstage:"launching". Only the user can answer it; tell them, and pollswx_status.ab's policy keeps the password with the user (measured 2026-10-12).
pup_credential_revealrefuses a bridge: "requires a VERIFIED local transport … this request arrived with origin "bridge"". Since 0.9.25swx_sign_inPREPARES the page before it asks for the password: it fills the user name from the vault's host list (no secret, no toast) and presses Continue. A refused reveal then answerssign_in_vault_policywithabSaid,pagePrepared {page, userNameFilled}andwaysOut. The user types the password in the window that is left on page 2; nothing is retried or worked around. ab issue #237 asks for a fill verb that keeps the secret inside ab. Other vault refusals (consent pending or denied) carrypagePreparedtoo.Page 2, read right (0.9.26, measured 2026-10-12). A page that holds the password box is page 2, even though it also shows the user-name box. That box is prefilled and READ-ONLY, so the bridge leaves it alone (a read-only refusal means "prefilled") and goes on to ask for the password once.
cookieBanneris true only for accept/reject BUTTONS; a "Manage cookies" link is not a banner. A failed set is never blamed on a banner, and no cookie toast goes out unless a banner is there. "Remember me" is toggled in the background and reported from its read-back state. The updater's tree is cold (14 nodes, the frame only) until probed, then stays awake (~37 nodes).Signing in for the user —
swx_sign_in {reason}(0.9.13). Only for a launch this bridge started whose own launcher is showing the 3DEXPERIENCE ID window. It reads the window's inventory (control types, names, IsPassword — never values; also inswx_status.signInInventoryevery time the window appears), takes the login from the user's pup vault ON THEIR LAPTOP through ab (pup_credential_reveal— the user clicks a consent toast "Sign in to SOLIDWORKS with your saved 3DEXPERIENCE login" EVERY time; an unanswered toast issign_in_consent_pending, and calling again re-attaches to it), types it through UI Automation, ticks "Remember me" if there is one, presses the sign-in button and checks the window actually closed. The password never appears in its reply, the log or the ledger. It fails closed:sign_in_credential_missing(the reply carries the import command for the user),sign_in_window_unrecognized(with the inventory),sign_in_needs_user(a code / second step: the user is notified),sign_in_rejected— never retried; later calls refusesign_in_rejected_beforeuntil the user says the saved password changed (userConfirmedNewPassword:true, on their word only).swx_start {signIn:"auto"}lets the bridge do it once by itself; the default is to wait for the user.The measured login flow (two pages, a lazy tree, a cookie banner, real keystrokes only while the user is idle) is in the solidworks-sign-in skill, which ships with this one.
Any login window, on the user's say-so:
swx_sign_in {reason, userAuthorized:true}also answers a 3DEXPERIENCE ID login window the bridge's launch did not raise — SOLIDWORKS Visualize's, or the platform updater's. Addwindow:"visualize"/"solidworks"/"desktopUpdate"/ an hwnd when several are open; the reply'swindownames the owning process. A named hwnd is checked by its CONTENT and never refused because a census missed it; with neither field in it the reply issign_in_window_not_a_login, withfound(every control looked for and what came back).When the tree shows only the frame (the updater's login, measured: 14 nodes),
swx_sign_infinds each control withdesktop_find_control. It looks up by automation id first, then role and exact name, then role and name-contains, and never by a role alone. It clears each field and then sets it by automation id. The user name cannot be read back on that host (readBack: "unreadable"), and "Remember me" is a label whose state cannot be read (rememberTicked: null).pages[].locatedsays how each page was read.
# Launch, sign-in and readiness — swx
Read this before starting SOLIDWORKS, while waiting through a launch or a 3DEXPERIENCE sign-in, or when deciding whether it is ready. Part of the `solidworks-bridge` skill — `SKILL.md` beside this folder has the rules that never bend. Trust each verb's own reply (`_hint`, `errorCode`) over anything written here.
## Install, launch, sign-in
- **This edition cannot be launched by COM, so do not try.** The install here is
SOLIDWORKS Connected / Makers (3DEXPERIENCE), and `swx_status` reports
`canLaunchProgrammatically:false`. COM can ATTACH to a session that is already
running; it cannot create one. That is a property of the edition, not a
limitation of the bridge, so there is no argument or retry that changes it.
- **The launch that works is the Platform's own shortcut.** `swx_start` invokes
the 3DEXPERIENCE Platform `.lnk`, which starts `CATSTART.exe`, which starts
`SWXDesktopLauncher.exe`, which starts `sldworks.exe`. The launcher chain then
exits — once `sldworks.exe` is up there is no launcher process left to poll or
to reap.
- **The `shellExecute` route hands back a real handle, proven live 2026-09-11.**
It invokes through `ShellExecuteExW` with `SEE_MASK_NOCLOSEPROCESS`; the live
run got a process handle back (CATSTART pid 131272, creation time 1789148101)
and that chain reached the launcher's `Run Begin`. This matters because the
bridge's law is **no handle, no kill**: it may only clean up a chain the invoke
itself handed back. On this machine that world is confirmed.
- **`stage:"helperSignIn"` means a human has to type a password — you cannot.**
A cold launch can stop at the 3DEXPERIENCE ID window: a NATIVE WebView2 window,
class `DSYSysLoginPanelWebView2Class`, title
"Login | 3DEXPERIENCE ID | Dassault Systemes", owned by `SWXDesktopLauncher.exe`
in the bridge's own chain. UIA sees NO controls inside it, so nothing can read
or fill it — this bridge included. As of 0.6.0 the bridge recognises the window,
reports `helperSignIn`, PAUSES every launch deadline while it is on screen (a
waiting human is not a stall), never kills or escalates the chain, and toasts
the user that sign-in is needed. Your move is to keep polling and, if the user
asks what to do, tell them to sign in and to tick **Remember me** once so later
launches do not stop here. The bridge never asks for, stores or transmits a
password.
- **How long `helperSignIn` lasts depends on the user answering the window**, not
on any timer the bridge owns. Do not convert it into a failure.
- **Read `launch.stage` and act on it**, from `swx_status` or from `swx_start`:
| `stage` | What to do |
|---|---|
| `invoked` | The route was just invoked. Poll `swx_status`. |
| `launcherStarted` | Chain running, `Run Begin` not reached. This is the stage that stalls; the bridge cleans up and tries the next route itself. Do not invoke the shortcut any other way. |
| `runBegin` | The chain is really building. Keep polling; `sldworks.exe` appears within seconds. |
| `helperSignIn` | Only the user can clear it. Poll; tell them to look at their screen. |
| `sldworksUp` | The application exists, COM does not answer yet. Keep polling. |
| `attaching` | Polling for the COM server. Keep polling; do not launch again. |
| `attached` | COM is usable. This is the only success — carry on. |
| `stalled` | That route stalled and its chain was cleaned up. The bridge is trying the next route. Nothing for you to retry. |
| `exhausted` | Every route was tried and none attached. ASK THE USER to start SOLIDWORKS from the Start Menu or the Platform. |
The three milestones that matter operationally are **`runBegin`** (the chain is
really building), **`sldworksUp`** (the application exists) and **`attached`**
(COM is usable, and the only success).
- **`stillLaunching:true` means a launch this bridge started is still in flight.**
Calling `swx_start` again does NOT start a second chain — it attaches to the one
in flight. That is deliberate: four launcher chains once ended up on a user's
desktop because a caller retried. Polling with `swx_start` is therefore safe,
and a second invocation by any other route is not.
- **`swx_stop` quits ONLY a session with zero documents open, and `force` does not
waive that** (`force` waives the UNSAVED question only). If documents are open,
close them first, or drain leaked conversion temporaries with
`swx_close_import_temps`.
- **Treat a quit as close to a one-way door.** On this edition relaunching after a
quit takes 1-3 minutes and can stop at the sign-in window again, which only the
user can answer. Do not quit to tidy up.
## Is it ready?
- **`attached` is not `ready`.** MEASURED 2026-10-01: document commands sent 8 s
after COM attach crashed SOLIDWORKS while its 3DEXPERIENCE add-in was still
initialising. `swx_start` now reports `stage:"starting"` (`stillStarting:true`)
until SOLIDWORKS has finished starting, then `stage:"ready"`; `swx_status` says
`solidworks.ready` and what it is based on (`readiness.basedOn`,
`readiness.performanceLog.verdict` and `why`, and the `rule`). EVERY verb
that reaches SOLIDWORKS waits — the gate is the default since 0.9.5, and only
a short list of verbs that never reach COM (status, start, describe, the disk
and window verbs, kill) is exempt. They refuse `host_app_starting` with
`retryAfterSeconds` until then — wait that long and call again; never try to
get around it. `readinessTimedOut:true` means it has been over five minutes:
look at the user's screen (a dialog, a sign-in) rather than forcing anything.
- **How ready is decided.** The performance log only speaks for THIS session
(written since the process started); a log from an earlier session is
`notThisSession`, never `complete`. COM's `StartupProcessCompleted` is true
before the start finishes (measured), so it is never enough alone on a
machine whose log writes 3DEXPERIENCE markers. An add-in loaded on demand
after the start (a quiet log, an add-in other than 3DEXPERIENCE, COM true)
does not make a started session "starting" again. A session that never
loads the platform add-in (it can be disabled) is ready once its log is quiet
and COM agrees; a log still being written holds the start. A session older
than ten minutes whose COM says the start completed is never held by the log
unless add-in loads are still appearing (`longRunningSession`), and a session
seen ready stays ready across a bridge update.
- **`state:"unverifiable"`** — nothing can verify the start. After the grace
(`readsAllowed:true`) READ verbs run; anything that creates, opens, saves,
closes or changes a document refuses with `startingUnverifiable:true`
("cannot verify startup completed"). The clock never authorises a document
command.
- **Quitting during startup:** under `userAuthorized:true`, `swx_stop` with
`maxRung:"c"` or `"d"` runs with the COM rungs skipped — the window-message
rungs need neither COM nor a finished start.
- `bridge_readiness` (ab-level, never spawns anything) answers "is SOLIDWORKS
installed / is the bridge warm" — use it for what-do-I-have questions.
- `swx_readiness` is the bridge's own read-only probe; `swx_status` is the
everyday state check (detection + COM attach + open docs);
`swx_get_app_state` is the one to POLL while something long runs.
- **If SOLIDWORKS is not installed** verbs return
`errorCode:"host_app_not_installed"`. Dassault publishes NO silent
installer — desktop trial serials come from a reseller, the Makers edition
from the 3DEXPERIENCE Platform store. Don't tell the user to go download it;
surface the returned `_hint`.
- **If SOLIDWORKS is not running, `swx_start` starts it — including the
Connected editions.** Pass a `reason` (it is written for the person whose
desktop this is, and it is the only thing this verb needs — starting an
application creates nothing and destroys nothing).
- On classic desktop installs it attaches over COM.
- On **3DEXPERIENCE / Connected** editions (including *Design Professional
for Makers*) it invokes **the shortcut the Platform installed**, which runs
`CATSTART.exe -run SWXDesktopLauncher.exe` with that user's tenant and
registry. That is the launch Dassault sanctions.
- **A cold Connected start runs 1-3 minutes** and may stop at a 3DEXPERIENCE
sign-in only the user can answer. `swx_start` returns
`started:true, stillLaunching:true` while it is coming up — that is **not a
failure**. Poll `swx_status` until `running:true`, or call `swx_start`
again, which ATTACHES to what is already coming up. `waitSeconds:<n>` (up
to 240) blocks instead of polling. **Never invoke the launcher any other
way meanwhile** — two launches means two sign-in windows on somebody's
desktop.
- **Calling `swx_start` during a launch launches NOTHING** (v0.4.0). It
answers `stillLaunching:true, launchedNow:false` with the live `stage`
(`launcherStarted` / `runBegin` / `helperSignIn` / `sldworksUp` /
`attaching`), its age, and what to do — and it needs no `reason` while an
attempt is in flight, so polling with it is always safe. `swx_status`
carries the same `launch` block.
- **A stalled launcher recovers itself.** The launcher chain sometimes starts
and then stops at `SecurityContext:` without ever logging `Run Begin` — it
then sits idle forever and SOLIDWORKS never appears. A supervisor inside
the bridge watches the launcher's OWN log, and on a stall it ends **only
the `CATSTART`/`SWXDesktopLauncher` chain it started itself** and tries the
next launch route, remembering whichever one works. **There is nothing for
you to retry, and nothing for you to clean up.**
- **NO HANDLE, NO KILL — and the same rule for evidence.** A launcher log is
read as this bridge's own only when the launcher's own writing-thread id
resolves to a process in our chain, or it is the sole candidate with no
other launch running; otherwise `unattributedLog:true` and it is not used.
On a route that cannot say what it started, no log is attributed at all. One consequence worth knowing:
if SOLIDWORKS comes up on `explorer` or `cmdStart`, the launch SUCCEEDS and
the route is never remembered — `attached` proves SOLIDWORKS is usable, not
that our route did it.
- **NO HANDLE, NO KILL.** A process is only ever ended when the INVOKE ITSELF
handed back its root (`ShellExecuteExW`'s process handle, or
`Start-Process -PassThru`'s pid) and it descends from that root. The
`explorer` and `cmdStart` routes cannot say what they started, so a stall on
either reports `cleanup:"notAttributable"` and **terminates nothing** — the
response says a launcher chain may remain that the bridge cannot identify,
which the user can end from Task Manager. If a route leaves something the
bridge cannot account for, the machine STOPS rather than starting another
chain beside it.
- **If SOLIDWORKS is running but unreachable, `swx_start` will not start a
second one.** It answers `host_app_hung` (Windows says the window is not
responding AND a COM call exceeded its budget — only the user can end it),
`host_app_exhausted` (**`NewDocument` came back with no document** — the one
signal that proves it; close the bridge's own documents, then ASK THE USER
to restart, and do not retry in a loop), or `host_app_com_unreachable`
(usually a sign-in window: ask the user to look at their screen).
`swx_status.solidworks.memoryAdvisory` reports a very large session as an
OBSERVATION — a 13 GB SOLIDWORKS can be perfectly healthy, and this bridge
no longer calls one out of room on a threshold.
- **"Not responding" is not "dead".** `swx_status.solidworks.verdict` is
`busy` / `dead` / `unknown`, from the CPU and memory DELTA across two reads
(`cpuActiveSeconds`, `memoryDeltaMB`). A session at 17.9 GB was
not-responding with a COM timeout for five minutes while burning 70% of a
core — and it recovered. `busy` means **tell the user to wait**; only `dead`
(no CPU over ≥15s, memory flat, no dialog) means only they can end it. One
reading never says dead — poll again.
- **After a failed attempt the bridge waits** (`host_app_launch_backoff`,
growing with each consecutive failure) and then tries ONE route rather than
re-sweeping the plan. Retrying in a loop is how four launcher chains ended
up on somebody's desktop; the honest move while it waits is to ASK THE USER
to start SOLIDWORKS from their Start Menu.
- **Crash-reporter recovery ships OFF** (`launch.crashRecovery:"off"`). When
armed it clicks the crash reporter's "Restart SOLIDWORKS Design" button
once — but only on a window OWNED by the SOLIDWORKS being launched, and only
when ab structurally confirms the button exists. It is disabled by default
because the reply shape it reads has never been seen on a real desktop.
- **NEVER kill the 3DEXPERIENCE launcher daemons.** `3DEXPERIENCELauncher.exe`,
`3DEXPERIENCELauncherSysTray.exe` and `3DEXPERIENCELauncherService.exe` are
the Platform's own background services and carry the user's Platform session.
They are **not required** for a launch (a successful launch on 2026-09-04 ran
with no Backbone at all), so killing one buys nothing and breaks something
that is not yours — and **a real user launch rebuilds them**, which is the fix
if they are genuinely broken. The bridge's own kill allowlist is exactly two
images, `CATSTART.exe` and `SWXDesktopLauncher.exe`, and only instances it
created itself, terminated by pid. Do not reach for `taskkill` /
`process_kill` against any of this yourself; `sldworks.exe` included (that is
`swx_kill`, and it is gated behind the user's explicit opt-in).
- `errorCode:"host_app_launch_blocked"` now means only one thing: **the
bridge could not FIND a shortcut**, not that the edition cannot be
launched. `swx_status` reports `solidworks.shortcut` and
`solidworks.launchRoute` so you can see what it found; if the user has a
shortcut elsewhere, `SWX_SOLIDWORKS_SHORTCUT=<path to the .lnk>` points the
bridge at it. Do not run `sldworks.exe` yourself via `shell_execute` or
`launch_process` — launching it DIRECTLY, bypassing the launcher chain, is
what produces the *"SOLIDWORKS Design must be launched from the
3DEXPERIENCE Platform"* modal.
- **`waitingOn:"userSignIn"`** on `swx_start` / `swx_status` means a
3DEXPERIENCE ID login is up and the launch is waiting for the user to sign in.
`signInWindow` is `{hwnd, title, ownerImage, host, recognizedBy}`; it was a
bare title before 0.9.23. Any login window on the machine counts, found by
class or title OR by content (an Edit "Email or username" or "Password" in
it). Measured 2026-10-12: the platform updater `SWXDesktopUpdate.exe` showed a
login titled just "3DEXPERIENCE" (`host:"desktopUpdate"`) and the Visualize
start was parked behind it. `swx_start {app:"visualize"}` now says
`stage:"waitingOn"` with `visualize.parkedBehind` instead of
`stage:"launching"`. Only the user can answer it; tell them, and poll
`swx_status`.
- **ab's policy keeps the password with the user (measured 2026-10-12).**
`pup_credential_reveal` refuses a bridge: "requires a VERIFIED local transport
… this request arrived with origin "bridge"". Since 0.9.25 `swx_sign_in`
PREPARES the page before it asks for the password: it fills the user name from
the vault's host list (no secret, no toast) and presses Continue. A refused
reveal then answers `sign_in_vault_policy` with `abSaid`, `pagePrepared {page,
userNameFilled}` and `waysOut`. The user types the password in the window
that is left on page 2; nothing is retried or worked around. ab issue #237
asks for a fill verb that keeps the secret inside ab. Other vault refusals
(consent pending or denied) carry `pagePrepared` too.
- **Page 2, read right (0.9.26, measured 2026-10-12).** A page that holds the
password box is page 2, even though it also shows the user-name box. That box
is prefilled and READ-ONLY, so the bridge leaves it alone (a read-only
refusal means "prefilled") and goes on to ask for the password once.
`cookieBanner` is true only for accept/reject BUTTONS; a "Manage cookies" link
is not a banner. A failed set is never blamed on a banner, and no cookie toast
goes out unless a banner is there. "Remember me" is toggled in the background
and reported from its read-back state. The updater's tree is cold (14 nodes,
the frame only) until probed, then stays awake (~37 nodes).
- **Signing in for the user — `swx_sign_in {reason}`** (0.9.13). Only for a
launch this bridge started whose own launcher is showing the 3DEXPERIENCE ID
window. It reads the window's inventory (control types, names, IsPassword —
never values; also in `swx_status.signInInventory` every time the window
appears), takes the login from the user's pup vault ON THEIR LAPTOP through
ab (`pup_credential_reveal` — the user clicks a consent toast "Sign in to
SOLIDWORKS with your saved 3DEXPERIENCE login" EVERY time; an unanswered toast
is `sign_in_consent_pending`, and calling again re-attaches to it), types it through UI Automation, ticks "Remember me" if there is
one, presses the sign-in button and checks the window actually closed. The
password never appears in its reply, the log or the ledger. It fails closed:
`sign_in_credential_missing` (the reply carries the import command for the
user), `sign_in_window_unrecognized` (with the inventory),
`sign_in_needs_user` (a code / second step: the user is notified),
`sign_in_rejected` — never retried; later calls refuse
`sign_in_rejected_before` until the user says the saved password changed
(`userConfirmedNewPassword:true`, on their word only).
`swx_start {signIn:"auto"}` lets the bridge do it once by itself; the default
is to wait for the user.
- **The measured login flow** (two pages, a lazy tree, a cookie banner, real
keystrokes only while the user is idle) is in the **solidworks-sign-in**
skill, which ships with this one.
- **Any login window, on the user's say-so:** `swx_sign_in {reason,
userAuthorized:true}` also answers a 3DEXPERIENCE ID login window the
bridge's launch did not raise — SOLIDWORKS Visualize's, or the platform
updater's. Add `window:"visualize"` / `"solidworks"` / `"desktopUpdate"` / an
hwnd when several are open; the reply's `window` names the owning process. A
named hwnd is checked by its CONTENT and never refused because a census missed
it; with neither field in it the reply is `sign_in_window_not_a_login`, with
`found` (every control looked for and what came back).
- **When the tree shows only the frame** (the updater's login, measured: 14
nodes), `swx_sign_in` finds each control with `desktop_find_control`. It looks
up by automation id first, then role and exact name, then role and
name-contains, and never by a role alone. It clears each field and then sets
it by automation id. The user name cannot be read back on that host
(`readBack: "unreadable"`), and "Remember me" is a label whose state cannot be
read (`rememberTicked: null`). `pages[].located` says how each page was read.