#cnc #dwc #gsender #ui #comparison #reprapfirmware #grblhal #voroncascade #porting
# Overview
This note is a deep, feature-by-feature comparison of **Duet Web Control (DWC)** — the browser UI shipped with RepRapFirmware — and **gSender** — Sienci Labs' Electron-based sender for Grbl/grblHAL CNCs. The goal is not to pick a winner but to map the two surfaces against each other so future porting efforts (most likely "what gSender features would be valuable to graft onto DWC for a CNC build") have a clear gap list to work from.
Context: this analysis is part of the [[RepRapFirmware and MillenniumOS on BTT Scylla]] decision for the [[Voron Cascade BOM|Voron Cascade]]. The Cascade officially ships with grblHAL + gSender, but the alternative path is RRF + MillenniumOS + DWC. The biggest UX delta in that swap is *exactly* this DWC↔gSender pair.
Versions surveyed:
- DWC 3.5–3.6 (current stable per [Duet3D documentation](https://docs.duet3d.com/User_manual/Reference/Duet_Web_Control_Manual))
- gSender 1.6.0 (released 2026-04-15) through 1.6.2 (released 2026-05-26) per the [gSender README](https://github.com/Sienci-Labs/gsender/blob/master/README.md)
# Architecture
The two tools differ at a fundamental level — this drives most of the downstream feature differences.
## Duet Web Control
- **Type:** Browser-based single-page application (Vue.js).
- **Where it runs:** *Inside* the controller. The Duet (or STM32 board via TeamGloomy) serves DWC as a static web app from its onboard flash/SD; the browser is just rendering.
- **Connection model:** HTTP/WebSocket between browser and controller. Either the controller hosts a WiFi AP or it joins your LAN.
- **State source:** RepRapFirmware's **object model** — a live JSON tree exposing every aspect of the machine (axes, sensors, spindles, tools, network, plugins, etc.) that DWC subscribes to over the rr_model API.
- **No sender process.** Job files live on the controller's SD card; RRF reads them directly. No PC needs to stay connected during a job — close your laptop, the job keeps running.
- **Update model:** Drop a new DWC zip onto the SD card via the System tab → reboot. Plugins extend the UI without a rebuild.
- **Multi-client:** Multiple browsers can connect to the same controller simultaneously; both see live state from the same object model.
## gSender
- **Type:** Electron desktop application (also runs on Pi via the same Electron build). Web-based UI under the hood but packaged as a native app.
- **Where it runs:** *On a PC/Pi alongside* the controller. Not on the controller itself.
- **Connection model:** USB serial (primary) or Ethernet (newer grblHAL boards). The sender opens the COM port, becomes the master, and streams gcode line-by-line.
- **State source:** Grbl/grblHAL's `?` status report polling plus EEPROM `
queries. State is reconstructed by the sender, not exposed by the controller.
- **Sender process required.** The PC must stay connected for the duration of a job (unless the controller's SD card is used as an alternate runner — newer grblHAL boards support this, but it bypasses gSender for the job-running portion).
- **Update model:** Download a new release installer per OS. Plugins not supported in the same first-class way DWC has them; customization happens in the Automations / Macros system.
- **Single-client by design.** Two gSender instances cannot share a controller — the serial port is exclusive. Remote mode exposes a web view of a running gSender instance, but the master is still the one PC.
## What this architecture difference *means*
- DWC's "always-on, hands-off" model is a structural win for CNC reliability — a USB cable wiggling free or a laptop going to sleep can't kill a job.
- gSender's PC-side architecture is a structural win for visualization fidelity, file editing, and integration with the OS (file associations, gamepad/HID, drag-and-drop, etc.).
- DWC's object model means the firmware *is* the source of truth and plugins can subscribe to anything. gSender has to parse status reports and EEPROM dumps, which is more brittle and is the source of most of its "compatibility with newer firmware" release-notes churn.
# Feature parity matrix
A summary view; deep dives follow.
| Capability | DWC | gSender |
|---|---|---|
| Browser-based | ✅ native | ⚠️ via Remote mode only |
| Native desktop app | ❌ | ✅ Electron |
| Touchscreen-friendly default | ⚠️ adapts but not optimized for it | ✅ designed for it |
| Mobile / tablet adaptive | ✅ | ⚠️ portrait mode in 1.6.0+ |
| Job runs without host PC | ✅ (canonical) | ⚠️ only via SD card workflow (1.6.0+) |
| 3D toolpath preview | ⚠️ via GCode Viewer plugin | ✅ built-in, no machine needed |
| Toolpath visualization during job | ⚠️ basic via plugin | ✅ live with processed-lines hide |
| Built-in gcode editor with syntax | ⚠️ plain text editor | ✅ 1.6.0+ with highlighting |
| Macros | ✅ powerful (RRF meta gcode + object model) | ✅ with variables, can be assigned shortcuts |
| Probing workflow | ⚠️ generic; MOS adds canned cycles | ✅ comprehensive built-in |
| Surfacing / stock prep wizards | ❌ | ✅ surfacing, rounding, XY squaring, movement tuning |
| Job recovery / start-from-line | ⚠️ resume from pause; no native start-from-line | ✅ built-in |
| Outline / dry-run | ⚠️ via macro; simulation mode exists | ✅ built-in outline + check mode |
| Tool change wizard | ✅ via MOS (M4000/M4001) | ✅ built-in, with ATC support in 1.6.0+ |
| Pendant / gamepad | ⚠️ via M-codes/serial pendant, custom plugins | ✅ first-class gamepad support |
| Keyboard shortcuts | ⚠️ minimal | ✅ extensive, configurable |
| Plugin system | ✅ built-in marketplace since 3.2 | ⚠️ no plugin marketplace; Automations + Config |
| Remote access over LAN | ✅ native (it's a web app) | ⚠️ via Remote mode (limited) |
| Multi-client | ✅ | ❌ |
| Webcam integration | ✅ built-in | ❌ |
| RS485/Modbus VFD support | ✅ via RRF 3.6 + ArborCTL (limited VFD list) | ✅ via grblHAL spindle plugins (HY, MODVFD, GS20, YL620, etc.) |
| Sleep prevention during job | not needed (job runs on controller) | ✅ built-in PowerSaveBlock |
| Firmware flashing from UI | ⚠️ via System tab upload | ✅ built-in flash tool |
| EEPROM / `
-settings editor | ✅ all RRF config is files (no EEPROM) | ✅ 1.6.0+ EEPROM editor |
| Theme support | ✅ light/dark | ✅ light/dark + Lite mode |
| Internationalization | ✅ multiple languages | ⚠️ English-primary |
# Deep dives
## Job execution model
This is the headline difference and underlies most of the others.
**DWC.** A gcode job lives on the controller's SD card. You upload it via the Jobs tab (drag and drop in the browser), optionally simulate it (RRF computes a precise time estimate without moving anything), then "Start". From that point the controller is autonomous. RRF reads the file off SD, executes it, and DWC just renders the live state from the object model. You can close the browser, drop network, lose power to your laptop — the job continues. If WiFi comes back you reconnect and see live progress. `pause.g` / `resume.g` / `cancel.g` are user-editable macros that run automatically when those events fire.
**gSender.** A gcode job is opened from your local filesystem. gSender parses it client-side, renders a 3D preview, computes an estimated time, then streams the file to the controller line-by-line over USB serial. The PC is in the loop for every line. If the PC sleeps, dies, disconnects, or freezes, the job dies with it. PowerSaveBlock is built in specifically to mitigate this. Start-from-line and pause/resume are gSender features, not controller features.
Implications:
- For unattended long-running jobs, DWC's model is more robust.
- For tight feedback loops while developing a job (load file, preview, run, tweak), gSender's local-file model is faster — no upload step.
- The Cascade BOM defaults to grblHAL + gSender largely because that workflow is what hobby CNC users expect.
## Visualization
**gSender.** Strong. Built-in 3D toolpath viewer based on the same lineage as CNCjs. Renders the entire loaded file as a 3D path; head position is shown live during the job; processed (already-cut) lines can be hidden in 1.6.0+; tool-based coloring; lite mode for low-end hardware. Visualization works *without* a controller connected, so you can preview a file on a laptop before walking to the shop.
**DWC.** Weaker by default. The "GCode Viewer" plugin (third-party, install from the Plugin marketplace) adds 3D toolpath preview, but it's not on by default and the rendering is less polished than gSender's. RRF's simulation mode runs the file in the firmware (no movement) and gives you a time estimate but not a live preview during the job in the same way gSender does. Height map visualization (for bed mesh probing) is built-in and excellent — but that's a 3D-printing feature that rarely matters on a CNC.
This is one of the clearest gSender wins and a clear porting target if you were extending DWC for CNC.
## Probing
**gSender.** Comprehensive built-in probing UI. XYZ touch plate support with corner selection, Z-only mode, configurable touch plate dimensions, auto-diameter probe support, safe continuity detection to prevent broken tools, probe-type toggle directly in the probe drawer (1.6.1+). Walks the user through the workflow visually.
**DWC.** Generic. RRF supports probing via `M558` and `G38.x` and the Z-probe shows up in the machine status pane. Out of the box there are no canned probing cycles — those are the value MillenniumOS adds on top: corner probe, bore probe, vise probe, surface, all guided by dialog boxes via `M291`. So the *RRF + MOS* combination matches or exceeds gSender's probing UX. *DWC alone* does not.
The relevant comparison for a Cascade-on-RRF build is therefore "gSender probing vs MillenniumOS probing," not "gSender vs DWC."
## Macros and scripting
**DWC.** Macros are gcode files under `/macros/` (user) or `/sys/` (system). They use RRF's "meta gcode" — `if`, `while`, `var`, `global`, expressions, and direct access to the object model (`spindles[0].active`, `move.axes[0].machinePosition`, etc.). This is unusually powerful: macros can read sensors, do math, branch, message the user via `M291`, and persist state across runs. MillenniumOS is itself just a tree of meta-gcode macros. The macro page in DWC lists files, runs them on click, edits them in the browser.
**gSender.** Macros are gcode snippets stored in gSender's local config. They support variables (a Sienci extension), can be reordered, can be bound to keyboard shortcuts and individual macro buttons. Less powerful than RRF meta gcode — there is no expression language, no object-model access, no conditionals. For most hobby CNC jobs this is fine; for sophisticated automation (e.g. ArborCTL-style VFD daemons), gSender macros are not the right tool.
DWC's macro power is one of the clearest DWC wins. It is also less obvious — users see the "Macros" button and assume parity.
## Touch / pendant / hardware control
**gSender.** Strong. First-class gamepad support — recognizes a variety of controllers, configurable bindings, profiles importable/exportable, dedicated jogging behaviour. Extensive keyboard shortcuts, all individually rebindable, with categories. Designed-in touchscreen layouts; gSender works well on a wall-mounted tablet running the Electron build (or via Remote mode in a browser, with some caveats). Portrait mode added in 1.6.0.
**DWC.** Generic. Touchscreens work — DWC is responsive and the mobile layout collapses well — but there is no purpose-built kiosk mode and no built-in gamepad support. CNC pendants are handled at the firmware level (USB-HID pendants talking to RRF via a plugin, or a wired pendant with rotary encoder via dedicated pins). Keyboard shortcuts in DWC are minimal.
This is the second-clearest gSender win, and the most obvious porting opportunity if you were trying to make DWC feel "CNC-native" rather than "3D-printer with a CNC tab."
## File management
**DWC.** Files live on the controller. Jobs (`/gcodes`), macros (`/macros`), and system files (`/sys`) each get their own tab. Drag-and-drop upload, in-browser editing with a basic text editor, subdirectory organization. Right-click menus for rename/delete/download. Multi-SD-card support if the board has external storage.
**gSender.** Files live locally. The traditional workflow is "load a gcode file from the PC, send it directly." With 1.6.0+, there's now SD-card-file-management support for grblHAL devices (yModem over USB, FTP over Ethernet) so files can be uploaded to the controller and run from there — closing some of the gap with DWC's model. Built-in gcode editor with syntax highlighting (1.6.0+) is nicer than DWC's plain text editor.
The file-editing UX in gSender 1.6.0 is a clear improvement candidate for DWC.
## Plugin ecosystem
**DWC.** First-class plugin support since 3.2. Plugins are zip files dropped onto the System tab; activated from Settings → Machine-Specific → Plugins. Built-in plugins (Height Map, GCode Viewer, On-Screen Keyboard) and third-party plugins (BtnCmd for custom dashboards, Object Model viewer, etc.) extend the UI without rebuilding it. Each activated plugin adds a menu item.
**gSender.** No plugin system in the DWC sense. Customization happens via the Automations editor (start/stop gcode blocks, tool-change hooks, event-driven gcode injection), Macros, Config, and gamepad profiles. To extend gSender meaningfully you fork the codebase and recompile.
DWC's plugin model is a clear DWC win and a non-trivial gap on the gSender side.
## Spindle and VFD control
**DWC + RRF.** Spindle declared via `M950 R<n> C"<pin>" L<min>:<max>` (PWM) or via `M575 P<chan> B<baud> S7` + Modbus macros (RS485). The dashboard shows spindle state and active RPM from the object model. `M3`/`M4`/`M5` work standard. ArborCTL (alpha) adds VFD-specific profiles for Shihlin SL3, Huanyang HY02D223B, Yalang YL620A. See [[G-Penny H100 VFD Modbus Integration]] for the H100-specific story.
**gSender + grblHAL.** Spindle setup tool (1.6.0+) with sienciHAL and grblHAL core variants. Spindle dropdown lists configured spindles. VFD support via grblHAL's `Plugins_spindle`: Huanyang HY, Huanyang GT, GS20, YL620, generic MODVFD. RPM is set via `S` or `M3 S<n>`, status reported back. Spindle/Laser drawer has live overrides.
Functionally similar. gSender's spindle UX is slightly cleaner because it's first-class in the UI; RRF's is more flexible because it's all in the firmware and macros.
## Probing and toolsetting workflows
(See also the Probing section above.)
**gSender.** Touch-plate probing is a guided multi-step UI: place plate → select corner → set thickness → run probe. Auto-diameter probes supported. Z-only mode, XYZ mode. Probe results update the WCS automatically. Tool-length probing is part of the tool-change wizard.
**DWC + MillenniumOS.** Probing is also a guided multi-step UI but the guidance comes from `M291` dialog boxes the MOS macros emit. The `G6500` family of macros — bore probe, web probe, corner probe, surface probe, vise probe — are powerful and well-tested. Toolsetting is fully automated via `M4000`/`M4001` if a toolsetter is wired (`M558 K1 P8`). Deflection compensation is computed by the install wizard.
For a Milo or a Milo-shaped machine like the Cascade, MillenniumOS probing is *more* sophisticated than gSender's, but it's also tied to a specific gcode dialect and post-processor (Fusion360 / FreeCAD MOS posts).
## ATC (Automatic Tool Changer) workflows
**gSender.** Added full ATC support in 1.6.0: tool table, timeline, remapping, controls, ATC setup tool. Tool changes can be M0 (manual pause), pause-and-prompt, run-a-macro, or full automatic ATC. Sienci ATC is the primary target but the framework is generic enough for third-party ATCs.
**DWC + MillenniumOS.** MOS implements tool management via `M4000` (tool definition with name, radius, length) and `M4001` (active tool selection), and tool changes run `tpre.g` and `tpost.g` macros. ATC support is community-maintained and varies in maturity; the core MOS workflow assumes manual tool changes with toolsetter verification.
Slight gSender lead on packaged ATC UX; MOS's tool-management gcodes are more programmable.
## Connection management
**DWC.** Bookmark the IP/hostname, open a browser. That's it. WiFi credentials are entered once in `network.g`. Multiple clients can connect. SSL/TLS not native (HTTP only) — fine on a LAN, awkward over the public internet.
**gSender.** Auto-discovers USB serial devices; configurable baud rate. Ethernet support with custom ports and auto-reconnect (1.6.0+). Single client. Remote mode lets a browser view the gSender instance, including synced settings (1.6.0+).
## Firmware update
**DWC.** Drop `RepRapFirmware.bin` and `DuetWiFiServer.bin` into the System tab → reboot → controller flashes itself. Same workflow for DWC updates and plugin installs.
**gSender.** Built-in firmware flash tool. Auto-detects grblHAL builds for Sienci hardware (e.g. selects grblHAL firmware when `SLB_DFU` is detected). Walks the user through the flash.
Comparable; both are good. gSender's tighter integration with Sienci hardware specifically is a slight edge for that ecosystem.
## Visualization fidelity (during a job)
**DWC.** Limited. Position counters update live, the dashboard shows axis state, and the height map visualization is great — but live toolpath progress is not visualized in the DWC default UI. The GCode Viewer plugin closes some of this gap.
**gSender.** Strong. The 3D viewer renders the entire toolpath, shows current head position live, can hide processed lines so the remaining work is visible, and supports lite mode for performance. Good enough to use as the primary "what is my machine doing right now" view.
This is the single biggest UX gap and the most obvious porting candidate.
## Job time estimation
**DWC + RRF.** Run the file in simulation mode; RRF executes the gcode through the motion planner without moving the machine and produces a precise time estimate that accounts for accel/jerk. Very accurate. Saved to the file's metadata so the Jobs list shows estimated time alongside the filename.
**gSender.** Estimates time at file load time using parsed gcode and EEPROM settings. Improved continually (rotary support, feed-override handling, M0/M1 pause handling). Decent for typical hobby work; less accurate than RRF's simulation for complex jobs.
Slight DWC/RRF win on precision; gSender wins on ergonomics (no extra step to get the estimate).
## Lite / performance modes
**gSender.** "Lite mode" reduces rendering load for low-end PCs or large gcode files. Indicator is shown when active. Visualization can be disabled entirely.
**DWC.** No equivalent — but no equivalent is needed, because rendering load isn't on the controller. The browser does whatever the browser does; if the browser is on a slow tablet, it'll be slow regardless.
## Webcam
**DWC.** Built-in webcam panel (configure URL → image embedded in dashboard).
**gSender.** No native webcam panel.
A small but real gap if you're trying to mill from another room.
## What MillenniumOS adds on top of DWC
Because the Cascade-on-RRF path includes MOS, the practical comparison is "gSender vs DWC + MOS":
- Canned probing cycles (`G6500` family) that rival or exceed gSender's
- Toolsetter integration with `M4000`/`M4001`
- Variable Spindle Speed Control (VSSC)
- A configuration wizard (`G8000`) that walks new machinists through deflection cal, datum tool setup, etc.
- A Milo-flavored Fusion360/FreeCAD post-processor with safety preamble + tool metadata
MOS does *not* add: visualization, gamepad support, gcode editor, surfacing wizard, outline/check-mode UX, kiosk-mode touch UI. Those remain gSender wins.
# Where each shines
## DWC shines
- Unattended, long-running jobs where the host PC must not be in the loop.
- Multi-client visibility (operator at the machine + supervisor on a laptop).
- Powerful, scriptable macros via RRF meta-gcode and the object model.
- First-class plugin system for extending the UI without forking.
- Adaptive layout that genuinely works on phones, tablets, and desktops from the same codebase.
- Webcam integration.
- Job time estimation via in-firmware simulation.
## gSender shines
- Touchscreen-first, kiosk-style operation at the machine.
- Live 3D toolpath visualization during a job.
- Probing wizards, surfacing tool, stock-prep gadgets, outline/check-mode UX.
- Gamepad and keyboard-shortcut driven control.
- Built-in gcode editor with syntax highlighting.
- Tight integration with Sienci hardware (LongMill, AltMill, sienciHAL).
- Faster iteration loop (load file → preview → run, no upload step).
# Porting opportunities
What gSender features would be valuable to port to DWC (or to a DWC plugin)? In rough order of impact:
1. **Live 3D toolpath visualization with processed-lines hide.** The GCode Viewer plugin is a starting point but lags gSender's polish. Build a proper DWC plugin that uses the RRF object model's `move.axes[].machinePosition` to drive a head marker over a Three.js-rendered toolpath.
2. **Surfacing / stock-prep wizards.** gSender's surfacing, stock rounding, and XY squaring tools generate gcode for common ad-hoc operations. These are entirely gcode generators, no firmware coupling — they should port cleanly as a DWC plugin that drops gcode into the macros directory and runs it.
3. **Touchscreen-optimized "carve mode" layout.** DWC's adaptive layout is good for tablets in general but a dedicated kiosk-mode that hides everything except DRO + jog + run-job + e-stop would close the "machinist UI" gap.
4. **Gamepad support.** Browser Gamepad API works fine; map axis input to RRF jog commands via `M120`/`G91`/`G0`/`M121`. Configurable bindings + profile import/export.
5. **Outline / check-mode UX.** RRF can already do "simulate file"; what's missing is the explicit "trace the bounding box at safe height" button that gSender exposes. Trivial macro wrapped in a plugin button.
6. **Configurable keyboard shortcuts.** Browser-side, no firmware involvement. Just a settings panel + an event listener.
7. **Webcam isn't backwards** — DWC already has it. gSender lacks it. Adding webcam support to gSender is a gSender-side issue.
8. **EEPROM editor isn't backwards either** — RRF uses files (`config.g`), not EEPROM, so DWC's "edit config.g" *is* the EEPROM editor, and arguably nicer than gSender's view-and-edit grid because it has comments and structure.
Things that are not portable:
- gSender's job-runner model — it's host-side by design; you couldn't make DWC stream from a PC without rewriting both halves.
- DWC's plugin marketplace — gSender's monolithic Electron build means plugins would require a real plugin architecture, which is more than a "port."
- RRF meta-gcode macro power — gSender's macros are intentionally simple; adding meta-gcode would mean reimplementing a chunk of RRF on the host.
# Recommendation for the Cascade build
If RRF + MOS is the chosen stack, the highest-leverage UI improvements (in priority order) are:
1. ==Install the GCode Viewer plugin in DWC to close the visualization gap before first cuts.==
2. ==Decide on the kiosk strategy — Pi + touchscreen running a locked-down DWC tab, a wall-mounted tablet, or a USB-HID CNC pendant.== Each is a separate project; pick one.
3. ==Pre-build a small library of DWC dashboard buttons (via the BtnCmd plugin) for the most-common operations: home, run last job, return to safe-Z, zero WCS, run probe, e-stop. This is the touchscreen UX without writing custom code.==
4. ==Audit MillenniumOS's probing/toolsetting flows against gSender's; for any gap that matters, write a MOS-style macro to fill it (e.g. a "trace bounding box at safe height" macro for outline-style dry runs).==
If grblHAL + gSender is the chosen stack, the analogous list:
1. ==Run gSender on a Pi or tablet at the machine — the touch UX is its biggest strength, use it.==
2. ==Configure the Automations editor to inject the equivalent of MOS's safety preamble (spindle warmup, coolant on, dust collection on) before every job.==
3. ==Document custom macros (variables and all) in a backup workflow so they survive a gSender reinstall — they live in the gSender config, not on the controller.==
4. ==Plan for the "what if the PC dies mid-job" failure mode: SD-card-file workflow (1.6.0+) gives a fallback, but the operator needs to know how to trigger it from the controller front panel or pendant.==
# References
- [[RepRapFirmware and MillenniumOS on BTT Scylla]] — broader Cascade build plan and DWC frontend TODO
- [[G-Penny H100 VFD Modbus Integration]] — the VFD-control corner of this UI comparison
- [[Voron Cascade BOM]] — current parts list including the controller choice
- [[LLM Note Spec]] — note structure spec
# Source links
- [gSender README on GitHub](https://github.com/Sienci-Labs/gsender/blob/master/README.md) — features list and changelog through 1.6.2
- [gSender 1.6.0 release post](https://sienci.com/2026/04/16/gsender-1-6-0-release/) — the big feature release (gcode editor, SD card mgmt, ATC, EEPROM editor)
- [gSender 1.6.1 release](https://sienci.com/2026/04/30/gsender-1-6-1/)
- [gSender Edge 1.6.0-3](https://sienci.com/2026/02/03/gsender-edge-1-6-0-3/)
- [Sienci gSender landing page](https://sienci.com/gsender/)
- [gSender documentation](https://sienci.com/gsender-documentation/)
- [Duet Web Control Manual](https://docs.duet3d.com/User_manual/Reference/Duet_Web_Control_Manual) — comprehensive feature walkthrough
- [DWC GitHub repository](https://github.com/Duet3D/DuetWebControl) — source
- [DWC-CNC fork](https://github.com/Duet3D/DWC-CNC) — historical; CNC-specific UI tweaks merged into DWC 3.4 mainline
- [DWC Plugin Repository](https://plugins.duet3d.com/) — community plugins
- [BtnCmd plugin (custom dashboards in DWC)](https://github.com/MintyTrebor/BtnCmd) — closest thing to gSender-style dashboards inside DWC
- [grblHAL Plugins_spindle README](https://github.com/grblHAL/Plugins_spindle/blob/master/README.md) — VFD driver layer that pairs with gSender
- [MillenniumOS GitHub](https://github.com/MillenniumMachines/MillenniumOS) — the "ops layer" that closes most of DWC's CNC gaps for the Cascade path