Complete sim config boundary coverage

This commit is contained in:
2026-06-11 06:12:06 +08:00
parent 5bd8f12872
commit 1ab5571ae1
76 changed files with 18975 additions and 146 deletions

View File

@@ -16,6 +16,8 @@ Result file:
```text
wasm-port/build/native/sim-configs/summary.tsv
wasm-port/build/native/sim-configs/class-summary.tsv
wasm-port/build/native/sim-configs/path-matrix.tsv
```
Baseline:
@@ -50,19 +52,52 @@ Remaining failures are explicit LinuxCNC-native baseline edges:
## Target
The first target is not a browser UI feature. It is a repeatable native and
WASM simulation harness that can load and execute all `linuxcnc/configs/sim`
programs that are meaningful in a standalone non-hardware simulation context.
The first target is not a browser UI feature and not a requirement that every
`linuxcnc/configs/sim` `.ngc` program pass through standalone `bin/rs274`.
It is a repeatable native and WASM inventory that classifies every
`configs/sim` program, runs the entries that are meaningful in standalone
native/WASM/browser contexts, and records blocked dependencies for the entries
that require full LinuxCNC task, HAL, UI, Python-remap, or external process
runtime.
Acceptance criteria:
- The native sim-config harness reports all executable sim programs as `PASS`.
- The native sim-config harness reports `unexpected_fail: 0` and writes
`summary.tsv`, `class-summary.tsv`, and `path-matrix.tsv`.
- Macro/remap files are validated by the correct entry point: direct execution
only for real programs, load/parse or remap-call validation for subroutines.
- WASM tests cover the same representative classes after the native harness is
green.
- Any remaining unsupported files are explicitly classified as native GUI or
hardware-only and excluded by rule, not by accident.
- Node WASM inventory executes only entries with a defined standalone/WASM
runtime path and reports `unexpected_fail: 0`.
- Browser coverage remains focused on representative runtime classes rather
than blind full-directory execution.
- Any remaining unsupported files are explicitly classified by dependency, not
by accident.
## Definition Of Done For Full configs/sim Coverage
Full coverage for this project means:
- Inventory complete: every `summary.tsv` `.ngc` entry appears in
`docs/sim-configs-coverage-matrix.md` and generated `path-matrix.tsv`.
- Classification complete: every entry has `main`, `macro_load`, or
`remap_subroutine` class.
- Blocked table complete: full-process, HAL, UI, linuxcncrsh, external
userspace component, Python binding/remap, tool-database, and process user-M
dependencies are recorded explicitly.
- Native source-of-truth complete: `verify_sim_configs.sh` remains the Layer 2
source for per-path status and expected-failure reason.
- Node inventory complete: `verify_sim_configs_inventory_wasm.sh` checks the
native/generated/tracked path sets, runs eligible vendored programs, and
emits stable WASM inventory and skip/block summaries.
Any eligible row with missing vendored machine context is an inventory
failure, not an expected skip.
- Browser class coverage complete: each promoted browser class has a
representative sample and no browser test relies on directory enumeration.
- Expected failures justified: the current eight Layer 2 expected failures are
tied to runtime boundaries or the preserved upstream demo edge.
- No accidental standalone semantic ownership: tests must not pass by changing
G-code semantics, JS interpreter behavior, or project-owned
`Interp::...` implementations.
## Phase 1: Make The Harness A First-Class Test
@@ -80,7 +115,8 @@ validation entry point.
- scan only `linuxcnc/configs/sim`;
- identify `.ngc`, nearest `.ini`, nearest `.tbl`;
- run from the INI directory;
- write `summary.tsv`, stdout, stderr, and interpreter output under
- write `summary.tsv`, `class-summary.tsv`, `path-matrix.tsv`, stdout,
stderr, and interpreter output under
`wasm-port/build/native/sim-configs/`;
- classify programs as `main`, `macro_load`, `remap_subroutine`, or
`unsupported_runtime_edge`;
@@ -252,71 +288,61 @@ wasm-port/tests/native/verify_native_probes.sh
wasm-port/tests/wasm/node/verify_interp_wasm.sh
```
## Phase 4: Bring Up Python Remap Runtime Edges
## Phase 4: Classify Python Remap Runtime Edges
Status: complete for the native sim-config harness. Current checks:
Status: complete for the native sim-config harness and blocked for Layer 4
full inventory. Current native checks:
```text
gmoccapy: total 38, pass 38, fail 0
axis/laser: total 3, pass 3, fail 0
axis/remap main demos: total 6, pass 6, fail 0
VMC_toolchange: total 1, pass 1, fail 0
```
Root cause:
Boundary:
The configs use LinuxCNC Python remap modules. Earlier harness runs failed while
initializing `python/toplevel.py`; current native runs now resolve and execute
these configs under the LinuxCNC `rs274` baseline.
The configs use LinuxCNC Python remap modules. Native LinuxCNC `rs274` can
resolve and execute these configs under the current baseline, but Node/browser
Layer 4 full inventory is intentionally blocked until a Python-remap runtime
boundary is deliberately designed. Do not make these pass in browser by
translating Python remap behavior into JavaScript or by adding project-owned
CNC semantics.
Implementation steps:
Recorded dependency:
1. Preserve upstream behavior where possible:
- `configs/sim/gmoccapy/python/toplevel.py`
- `configs/sim/gmoccapy/python/remap.py`
- `configs/sim/gmoccapy/python/stdglue.py`
- `configs/sim/axis/laser/python/toplevel.py`
- `configs/sim/axis/laser/python/remap.py`
- `configs/sim/axis/remap/*/python/*.py` for Python remap, prolog, epilog,
queue, and tool-change callbacks.
- `configs/sim/axis/vismach/VMC_toolchange/remap.py` and `toplevel.py` for
Python tool-change prolog/epilog handling.
- inspect vendored LinuxCNC Python plugin interfaces;
- identify exact APIs used by:
- `configs/sim/gmoccapy/python/toplevel.py`
- `configs/sim/gmoccapy/python/remap.py`
- `configs/sim/gmoccapy/python/stdglue.py`
- `configs/sim/axis/laser/python/toplevel.py`
- `configs/sim/axis/laser/python/remap.py`
Current policy:
2. Split the implementation into two layers:
- native harness support using the host Python runtime, if available;
- WASM support using a documented adapter boundary or a Python-free
equivalent only for runtime edges, not G-code semantics.
3. Add runtime state adapters required by Python remap:
- selected tool and pocket;
- tool table access;
- interpreter status object fields used by stdglue;
- message/error reporting;
- canonical tool-change side effects needed by `M6`, `M61`, and laser
remaps.
4. Make Python module path resolution match LinuxCNC:
- INI directory is the base directory;
- `PYTHONPATH` includes config `python/` directories;
- remap modules load relative to the sim config.
5. Add narrowly-scoped tests before running all 38 gmoccapy programs. Done:
- one gmoccapy tool-change macro;
- one gmoccapy lathe macro;
- one gmoccapy 5-axis example;
- one laser raster/vector program.
- Keep native inventory as source-of-truth.
- Mark `gmoccapy/*`, `axis/laser/*`, `axis/remap/*/nc_files/*.ngc`, and
`axis/vismach/VMC_toolchange/toolchange.ngc` rows as `L4-PYTHON-REMAP` in
`docs/sim-configs-coverage-matrix.md`.
- Revisit Layer 4 only after the runtime boundary is designed from LinuxCNC
source ownership, not as a browser smoke expansion.
Completion check:
```bash
wasm-port/tests/native/verify_sim_configs.sh --only gmoccapy
wasm-port/tests/native/verify_sim_configs.sh --only axis/laser
wasm-port/tests/native/verify_sim_configs.sh --only axis/remap
wasm-port/tests/native/verify_sim_configs.sh --only VMC_toolchange
```
## Phase 5: Support TWP Remaps Including G69
## Phase 5: Classify TWP Remaps Including G69
Status: mapping complete. The harness now maps
Status: native mapping complete and Layer 4 blocked on Python-remap runtime
ownership. The harness now maps
`axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/*` through the
explicit `xyzacb-trsrn_twp/xyzacb-trsrn.ini` machine config instead of falling
back to `axis/axis.ini`. That loads the TWP `G69` remap declarations correctly,
@@ -329,7 +355,7 @@ Current failures:
`x50y50z150` after `G53.6`; same-directory demos use explicit `G0` motion
words at this point.
Root cause:
Boundary:
The demo programs rely on table/spindle rotary TWP remaps. The original test
mapping fell back to `axis/axis.ini` for these demo files because the actual
@@ -341,26 +367,15 @@ axis/vismach/5axis/table-rotary_spindle-rotary-nutating/
xyzbca-trsrn_twp/xyzbca-trsrn.ini
```
Implementation steps:
Current policy:
1. Improve sim-config mapping. Done:
- if a `.ngc` is under a `demos/` sibling of machine-specific INI
directories, map it to the appropriate TWP INI instead of walking upward
to `axis/axis.ini`;
- encode this as explicit metadata in the harness, not a fragile heuristic.
2. Ensure `SUBROUTINE_PATH` includes `../remap_subs:../demos` as declared by
the TWP INIs.
3. Verify remap subroutines:
- `g69remap.ngc`
- `g531remap.ngc`
- `g533remap.ngc`
- `g536remap.ngc`
4. Add a native test for each failing demo.
- Keep native mapping and expected-failure classification in
`verify_sim_configs.sh`.
- Keep `incremental_repetition_g533.ngc` as `UPSTREAM-DEMO`; do not edit the
upstream G-code or add standalone semantics to force a pass.
- Keep TWP demo Layer 4 rows as `L4-PYTHON-REMAP` until Python remap entry
points such as `g682`, `g69_core`, and `g53x_core` have an intentional
runtime boundary.
Latest result:
@@ -380,13 +395,14 @@ Completion check:
wasm-port/tests/native/verify_sim_configs.sh --only table-rotary_spindle-rotary-nutating
```
## Phase 6: Promote Native Coverage To WASM
## Phase 6: Promote Eligible Native Coverage To WASM
Status: complete for representative Node and browser WASM coverage. Dedicated
Node and browser smokes now pass a representative vendored `configs/sim` subset
through the SDK `runSimConfigProgram()` host boundary, which copies files into
the Emscripten filesystem and forwards execution to existing LinuxCNC-backed C
ABI paths. They cover:
Status: complete for the current representative Node/browser class coverage
and the Node inventory layer. Dedicated Node and browser smokes now pass a
representative vendored `configs/sim` subset through the SDK
`runSimConfigProgram()` host boundary, which copies files into the Emscripten
filesystem and forwards execution to existing LinuxCNC-backed C ABI paths. They
cover:
- `axis/foam/foam.ngc` with `axis_foam.ini`, verifying INI-driven `U/V` axis
mask handling in WASM.
@@ -400,87 +416,214 @@ ABI paths. They cover:
shared `eoffset.tbl`, and `opa_demo.ngc`'s `circles.ngc` subroutine,
verifying the same user-M and `SUBROUTINE_PATH` boundaries against upstream
sim programs.
The Node inventory guard keeps these deterministic `M110`/`M111` rows
unblocked, requires a vendored user-M file, and includes the `opa_demo.ngc`
`circles.ngc` subroutine text in boundary analysis so the reached `M111`
call is accounted for instead of being mistaken for an external user-M
process gap.
- `axis/gladevcp/probe.ngc` as a plain INI/tool-table main-program sample.
- `axis/external_offsets/circles.ngc` as the macro-load class representative,
wrapped only with an added `M2` for load/parse style execution.
- `axis/vismach/5axis/table-dual-rotary/demos/xyzab-tdr-demo.ngc` and
`axis/vismach/5axis/table-rotary-tilting/demos/*` through the existing
five-axis remap execution C ABI.
- `axis/vismach/melfa-sim/example.ngc` and `axis/vismach/puma/puma_cube.ngc`
as additional remap/kinematics machine representatives.
- `woodpecker/on_abort.ngc` as the deterministic on-abort/user-action macro
class representative.
- Node inventory for the eligible vendored program set:
`executed=28`, `passed=28`, `skipped=131`, `unexpected_fail=0`.
- Node inventory skip/block summary:
`ASSET-ONLY=65`, `L4-PYTHON-REMAP=53`, `L4-TOOL-DB=1`,
`L4-USER-M-PROCESS=1`, `NON_MAIN_CLASS=10`, `UPSTREAM-DEMO=1`.
- Node blocked-dependency inventory for the hard blocked row set:
`L4-PYTHON-REMAP=53`, `L4-TOOL-DB=1`, `L4-USER-M-PROCESS=1`.
The inventory reads source `linuxcnc/configs/sim` INI files for dependency
accounting only and writes
`build/wasm/sim-configs-inventory/blocked-dependency-summary.tsv` without
vendoring or executing those blocked families. The blocked summary includes
source-derived `user_m_process_effects` for `millturn`,
`tool_db_protocol_evidence` for `db_demo`, and Python module/remap/prolog/
epilog dependency ownership for Python-remap families. Python-remap rows are
also projected into
`build/wasm/sim-configs-inventory/python-remap-boundary-summary.tsv`, which
keeps all 53 `L4-PYTHON-REMAP` rows inventory-only with
`python_runtime_evidence` and `execution_enabled=0`.
Boundary decisions for the current hard blocks:
- `axis/vismach/millturn/example.ngc` remains `L4-USER-M-PROCESS`. The
source INI declares HAL, HALUI MDI, and UI process dependencies, and the
remap chain enters `remap_subs/428remap.ngc` and `429remap.ngc`, which call
external user-M process codes `M128` and `M129`. Those process scripts live
at `configs/sim/axis/vismach/millturn/mcodes/M128` and `M129`; they use Tcl
LinuxCNC/HAL packages, `emc_init`, `parse_ini`, `hal getp`, and `hal setp`
to change INI axis limit HAL pins after the kinematics switch. The current
LinuxCNC owner is therefore task user-M process dispatch plus HALUI/MDI and
the config-owned Tcl process scripts, not the standalone interpreter. Do not
promote this row until the boundary design in
`docs/full-process-boundary-design.md` has a deterministic state proof for
these HAL pin updates across native, Node, and browser. The Node inventory
guard requires this row to stay non-`REP` in Node and browser while it remains
`L4-USER-M-PROCESS`, and the generated inventory summary must keep it as
`SKIP` with that reason.
- `axis/db_demo/base.ngc` remains `L4-TOOL-DB`. The source INI declares
`[EMCIO]DB_PROGRAM = ./db_nonran.py`, so standalone interpreter execution
would miss LinuxCNC tool-database process startup and protocol/state
behavior. The LinuxCNC owner is `src/emc/task/taskclass.cc` for DB_PROGRAM
activation, `src/emc/tooldata/tooldata_db.cc` for DB process startup and
command/reply protocol, `src/emc/tooldata/tooldata_common.cc` for DB-backed
tooldata behavior, and the config program `configs/sim/axis/db_demo/db.py`.
Do not promote until the boundary design in
`docs/full-process-boundary-design.md` has a LinuxCNC-owned tool database
boundary that proves lookup/update behavior across native and WASM. The Node
inventory guard requires this row to stay non-`REP` in Node and browser while
it remains `L4-TOOL-DB`, and the generated inventory summary must keep it as
`SKIP` with that reason.
- Python-remap/full-process families remain `L4-PYTHON-REMAP`. The blocked
dependency inventory records Python modules, remap/prolog/epilog function
ownership, NGC remap subpaths, and HAL/UI/HALUI declarations for gmoccapy,
axis/laser, axis/remap demos, TWP nutating demos, and VMC tool-change
rows. The Python-specific boundary summary records the same row set as
inventory-only and requires a LinuxCNC-owned Python runtime boundary before
any promotion. Every `L4-PYTHON-REMAP` row must also remain `SKIP` with
`L4-PYTHON-REMAP` in the generated inventory summary. This is an inventory
artifact, not a Layer 4 execution path.
Completion checks:
```bash
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh
wasm-port/tests/browser/verify_interp_browser.sh
```
Remaining work:
Current Layer 4 non-goals:
1. Extend `runtime/core/linuxcnc_wrap/linuxcnc_interp_wasm.cpp` with the same
machine-config entry point used by native tests. Done for the existing
`runFileWithIni()` file-execution path.
- Do not run all 159 programs in browser.
- Do not promote Python remap/full-process/HAL/UI-only families into
Emscripten without LinuxCNC-owned runtime support.
- Do not add JS-owned G-code, remap, tool, kinematics, parameter, or planner
semantics.
2. Extend `runtime/sdk/src/linuxcnc-interp.js` with a host-boundary method such
as:
Browser inventory decision record:
```js
runSimConfigProgram({ iniPath, programPath, files })
```
Done. The method only writes caller-provided text files into the
Emscripten filesystem, applies executable bits for user M-code files, and
forwards execution to the existing LinuxCNC-backed C ABI path. It does not
implement CNC semantics in JavaScript.
3. Copy required sim config files into the Emscripten FS:
- INI;
- tool table;
- parameter file;
- `.ngc` program;
- `SUBROUTINE_PATH` files;
- `USER_M_PATH` handler files or registered adapter handlers.
Done for the representative Node and browser subsets.
4. Add Node WASM coverage. Done:
```text
wasm-port/tests/wasm/node/verify_sim_configs_wasm.mjs
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
```
5. Add representative browser coverage. Done in
`wasm-port/tests/browser/interp_smoke.html` through the existing browser
interpreter smoke and the same `runSimConfigProgram()` SDK boundary as Node.
- Promoted after Node inventory: plain INI/tool-table execution
(`axis/gladevcp/probe.ngc`), deterministic macro/load execution
(`axis/external_offsets/circles.ngc`), deterministic on-abort/user-action
execution (`woodpecker/on_abort.ngc`), TDR/TRT five-axis remap execution,
bridge-mill W-axis remap execution, `melfa-sim`, and PUMA.
The Node inventory guard requires process-declaring representatives such as
`axis/gladevcp/probe.ngc`, `woodpecker/on_abort.ngc`,
`axis/vismach/melfa-sim/example.ngc`, and
`axis/vismach/puma/puma_cube.ngc` to keep their dependency rows in
`boundary-summary.tsv`, match the expected HAL/UI/HALUI/Python process flag
combinations, remain Node/browser `REP` rows, and avoid hard-block promotion
unless the classifier finds a real hard runtime dependency.
- Kept as blocked: TWP `table-rotary_spindle-rotary-nutating`, `gmoccapy`,
`axis/laser`, `axis/remap/*/nc_files`, and VMC tool-change Python remap
families. These are not missing browser staging work; they depend on
Python-remap, prolog/epilog, or full runtime process boundaries that have not
been intentionally exposed in Layer 4.
- Kept out of browser full inventory: remap subroutine assets and macro-only
non-representatives. They remain covered by native inventory, native remap
parse/execute probes, Node inventory where eligible, or a class
representative in browser.
## Phase 7: Documentation And Drift Control
Status: complete for the current representative sim-config WASM/browser
coverage. The documentation and manifest now record the native, Node WASM,
browser, source reuse, and vendor-sync state for the selected sim-config
programs.
Status: complete for the current full `configs/sim` coverage definition. The
documentation and manifest now record native inventory, generated class/path
artifacts, blocked policy, Node inventory, browser class coverage, source
reuse, and vendor-sync state.
1. Update `docs/compatibility-validation.md` with the sim-config matrix. Done.
1. Update `docs/compatibility-validation.md` with the sim-config matrix,
blocked policy, and validation commands. Done.
2. Update `docs/source-reuse-map.md` for newly vendored source files. Done.
2. Add `docs/sim-configs-coverage-matrix.md` as the tracked review surface for
all 159 current native inventory rows. Done.
3. Update `tools/source-manifest.txt` and `tools/verify_vendor_sync.sh` if new
3. Update `docs/source-reuse-map.md` for newly vendored source files. Done.
4. Update `tools/source-manifest.txt` and `tools/verify_vendor_sync.sh` if new
LinuxCNC files are copied into `wasm-port/vendor/linuxcnc`. Done for the
representative `axis/foam`, `axis/geometry`, and `axis/external_offsets`
sim-config files, including the remaining external-offset M111 programs and
`circles.ngc`; no `verify_vendor_sync.sh` logic change was needed.
current representative and inventory-backed sim-config files; no
`verify_vendor_sync.sh` logic change was needed.
4. Preserve the latest result summary as a machine-readable artifact, but do
5. Preserve the latest result summary as a machine-readable artifact, but do
not commit generated logs unless they are intentionally used as fixtures.
Done: generated logs remain under build/test output directories, while the
tracked documentation records only the current summary values and validation
commands.
Done: `summary.tsv` remains the source row set, and `class-summary.tsv` plus
`path-matrix.tsv` are generated artifacts under `build/native/sim-configs/`.
Node inventory also writes `build/wasm/sim-configs-inventory/summary.tsv`
`build/wasm/sim-configs-inventory/skip-summary.tsv`, and
`build/wasm/sim-configs-inventory/boundary-summary.tsv` plus
`build/wasm/sim-configs-inventory/ini-boundary-summary.tsv` for Layer 4
execution, skip/block accounting, and runtime-boundary dependency reporting.
The same inventory now writes the full blocked-boundary handoff artifacts:
`blocked-dependency-summary.tsv`, `full-process-boundary-summary.tsv`,
`user-m-process-boundary-summary.tsv`, `user-m-process-state-targets.tsv`,
`tool-db-process-boundary-summary.tsv`,
`tool-db-process-protocol-gates.tsv`,
`python-remap-boundary-summary.tsv`, `python-remap-family-summary.tsv`,
`boundary-phase-completion-summary.tsv`,
`native-proof-alignment-summary.tsv`, `next-boundary-worklist.tsv`, and
`boundary-proof-gates.tsv`. These remain accounting/proof-gate artifacts;
they do not enable blocked execution or promotion.
The inventory guard checks `skip-summary.tsv` against skip reasons derived
from `path-matrix.tsv`, so aggregate skip counts drift when any blocked or
class policy changes without updating the tracked matrix and inventory.
The inventory guard requires every vendored INI row to have an available
SDK runtime-boundary classifier report; `UNAVAILABLE` is reserved for rows
whose boundary summary records a missing vendored INI.
Hard blocked rows are additionally recorded in
`build/wasm/sim-configs-inventory/blocked-dependency-summary.tsv` without
promotion into standalone/WASM execution. That artifact includes source
owner fields and runtime proof fields such as `user_m_process_files`,
`user_m_process_effects`, `tool_db_protocol_evidence`, and `linuxcnc_owner`,
so `millturn` and `db_demo` remain blocked for dependency-backed reasons
rather than path-only classification. The follow-up boundary design and
required proof for those two blocked rows are tracked in
`docs/full-process-boundary-design.md`. Node inventory also writes
`build/wasm/sim-configs-inventory/full-process-boundary-summary.tsv` for
the designed-but-blocked non-Python full-process rows, including their
`runtime_owner_evidence`, and
`build/wasm/sim-configs-inventory/python-remap-boundary-summary.tsv` for
the Python remap inventory-only row set. The Python boundary and family
summaries include `python_runtime_evidence`. All blocked boundary artifacts
require `execution_enabled=0`.
## Recommended Work Order
## Layer 2 Expected-Failure Policy
1. Harness first: make `verify_sim_configs.sh` reproducible.
2. Axis config next: unblock `U/V/W` failures.
3. TWP mapping: complete; remaining TWP demo failures are Python/HAL remap
runtime edges.
4. User M-code dispatch: small runtime-edge feature, unblocks five files.
5. Python remap runtime: largest block; do it after the harness and smaller
runtime edges are stable.
6. WASM promotion after native parity.
The current Layer 2 baseline remains:
```text
total: 159
pass: 151
fail: 8
timeout: 0
expected_fail: 8
unexpected_fail: 0
```
Do not reduce the eight expected failures by changing upstream G-code, JS
interpreter behavior, or project-owned standalone interpreter semantics. Reducing
this count is only valid if a new LinuxCNC-owned native/runtime entry point can
legitimately supply the missing task/user-M/axis/TWP context while preserving the
strict native baseline as a separately documented source of truth.
## Recommended Next Work
1. Keep `verify_sim_configs.sh`, `path-matrix.tsv`, and
`docs/sim-configs-coverage-matrix.md` in sync whenever the source manifest or
vendored sim-config set changes.
2. Add new Node/browser representatives only when they cover a new runtime class
with a LinuxCNC-owned execution path.
3. Treat Python remap, full-process HAL/UI, tool database, and external
userspace process families as blocked until their runtime boundary is
intentionally designed and the proof criteria in
`docs/full-process-boundary-design.md` are met where applicable.
4. Re-evaluate Layer 2 expected failures only after a new legitimate
LinuxCNC-owned entry point exists.
## Non-Goals