diff --git a/.github/workflows/publish-cvcgl-wasm.yml b/.github/workflows/publish-cvcgl-wasm.yml index 9f2ecb0a..052d643d 100644 --- a/.github/workflows/publish-cvcgl-wasm.yml +++ b/.github/workflows/publish-cvcgl-wasm.yml @@ -102,7 +102,7 @@ jobs: -DCVC_ENABLE_OPENMP=OFF -DDISABLE_CGAL=ON -DCVC_USING_HDF5=OFF \ -DCVC_USING_IMOD_MRC=OFF -DCVC_ENABLE_IMAGEMAGICK=ON -DCVC_ENABLE_FFTW=OFF \ -DCVC_FFT_PROVIDER=none -DCVC_ENABLE_ASSIMP=ON \ - -DCVC_ENABLE_MESHER=OFF -DCVC_ENABLE_SDF=ON -DCVC_STATE_EXEC=ON \ + -DCVC_ENABLE_MESHER=OFF -DCVC_ENABLE_SDF=ON \ -DCVC_BUILD_CVCGL=ON -DCVC_BUILD_EXAMPLES=OFF -DCVC_WASM_PTHREADS=ON cmake --build build-wasm --target cvc cvcGL -j"$(nproc)" cmake --install build-wasm diff --git a/bindings/pycvc/pycvc_exec.cpp b/bindings/pycvc/pycvc_exec.cpp index 428b8987..f2725aee 100644 --- a/bindings/pycvc/pycvc_exec.cpp +++ b/bindings/pycvc/pycvc_exec.cpp @@ -6,10 +6,6 @@ #include "pycvc_exec.h" -#include - -#ifdef CVC_STATE_EXEC - #include #include #include @@ -23,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -634,24 +631,3 @@ std::string Exec::run(const std::string &src) { } } // namespace pycvc - -#else // !CVC_STATE_EXEC - -namespace pycvc { - -struct Exec::ExecImpl {}; - -Exec::Exec(const std::shared_ptr &) { - throw std::runtime_error("pycvc.Exec: this libcvc build was compiled without state_exec"); -} -Exec::~Exec() = default; -void Exec::register_fn(const std::string &, PyObject *) { - throw std::runtime_error("pycvc.Exec: this libcvc build was compiled without state_exec"); -} -std::string Exec::run(const std::string &) { - throw std::runtime_error("pycvc.Exec: this libcvc build was compiled without state_exec"); -} - -} // namespace pycvc - -#endif // CVC_STATE_EXEC diff --git a/bindings/pycvc/pycvc_exec.h b/bindings/pycvc/pycvc_exec.h index c3e4dd04..192de81d 100644 --- a/bindings/pycvc/pycvc_exec.h +++ b/bindings/pycvc/pycvc_exec.h @@ -5,9 +5,6 @@ // environment + scheduler over that app's state root, so registered Python // functions and run() programs all see the same shared tree. A Python function // registered here becomes callable from DSL source like any builtin. -// -// Guarded by CVC_STATE_EXEC (a PUBLIC compile def on the cvc target); when the -// build lacks state_exec, the ctor throws. #pragma once #include diff --git a/bindings/pycvc/test_pycvc_ari.py b/bindings/pycvc/test_pycvc_ari.py index 0be3d20f..6bdf24ba 100644 --- a/bindings/pycvc/test_pycvc_ari.py +++ b/bindings/pycvc/test_pycvc_ari.py @@ -35,7 +35,6 @@ def _child(): ari = pycvc_gl.AriRuntime(view, cam, ui) try: - assert pycvc_gl.AriRuntime.have_state_exec(), "expected state_exec in this build" pinged = {"n": 0} ari.on("ping", lambda: pinged.__setitem__("n", pinged["n"] + 1)) warnings = ari.load(os.path.join(HERE, "demo.ari")) diff --git a/bindings/pycvc/test_pycvc_exec.py b/bindings/pycvc/test_pycvc_exec.py index 53a035e4..e22b7c9e 100644 --- a/bindings/pycvc/test_pycvc_exec.py +++ b/bindings/pycvc/test_pycvc_exec.py @@ -11,25 +11,12 @@ import pycvc -def _exec(app): - """Exec(app), or None if this build lacks state_exec.""" - try: - return pycvc.Exec(app) - except Exception as e: - if "without state_exec" in str(e): - return None - raise - - # ── core DSL evaluation ───────────────────────────────────────────────── def test_arithmetic_and_forms(): app = pycvc.make_app() - ex = _exec(app) - if ex is None: - print(" skip: build has no state_exec") - return + ex = pycvc.Exec(app) assert ex.run("(+ 2 3)") == "5" assert ex.run("(* 6 7)") == "42" assert ex.run("(begin (set x 5) x)") == "5" @@ -40,9 +27,7 @@ def test_arithmetic_and_forms(): def test_parse_error_raises(): app = pycvc.make_app() - ex = _exec(app) - if ex is None: - return + ex = pycvc.Exec(app) try: ex.run("(begin (set x") # unbalanced except Exception: @@ -56,9 +41,7 @@ def test_parse_error_raises(): def test_dsl_reads_and_writes_shared_state(): app = pycvc.make_app() - ex = _exec(app) - if ex is None: - return + ex = pycvc.Exec(app) # Python writes state; DSL reads it. pycvc.state_set(app, "shared.x", "7") assert ex.run('(state-get "shared.x")') == "7" @@ -72,9 +55,7 @@ def test_dsl_reads_and_writes_shared_state(): def test_python_function_called_from_dsl(): app = pycvc.make_app() - ex = _exec(app) - if ex is None: - return + ex = pycvc.Exec(app) ex.register_fn("py-double", lambda x: x * 2) ex.register_fn("py-add", lambda a, b: a + b) @@ -89,9 +70,7 @@ def test_python_function_called_from_dsl(): def test_python_dsl_function_touches_state(): app = pycvc.make_app() - ex = _exec(app) - if ex is None: - return + ex = pycvc.Exec(app) # A Python DSL function that writes state on the shared app. def stash(key, value): @@ -109,9 +88,7 @@ def stash(key, value): def test_python_exception_is_contained(): app = pycvc.make_app() - ex = _exec(app) - if ex is None: - return + ex = pycvc.Exec(app) def boom(*_): raise ValueError("kaboom") @@ -130,9 +107,7 @@ def boom(*_): def test_value_marshaling_types(): app = pycvc.make_app() - ex = _exec(app) - if ex is None: - return + ex = pycvc.Exec(app) seen = {} def capture(x): diff --git a/bindings/pycvc/test_pycvc_integration.py b/bindings/pycvc/test_pycvc_integration.py index 826d50c2..def9818f 100644 --- a/bindings/pycvc/test_pycvc_integration.py +++ b/bindings/pycvc/test_pycvc_integration.py @@ -52,19 +52,13 @@ def on_changed(self, path): # Phase 4: a DSL program calls a Python function that reads the state we just # wrote — Python <-> state <-> DSL, all on the same app. - ex = None - try: - ex = pycvc.Exec(app) - except Exception as e: - if "without state_exec" not in str(e): - raise - if ex is not None: - ex.register_fn("verts", lambda: int(pycvc.state_get(app, "mesh.verts"))) - # (+ 0 (verts)) forces numeric context; equals the vertex count. - assert ex.run("(+ 0 (verts))") == str(surf.num_vertices()) - # A DSL write is visible back in Python. - ex.run('(state-set "dsl.done" "yes")') - assert pycvc.state_get(app, "dsl.done") == "yes" + ex = pycvc.Exec(app) + ex.register_fn("verts", lambda: int(pycvc.state_get(app, "mesh.verts"))) + # (+ 0 (verts)) forces numeric context; equals the vertex count. + assert ex.run("(+ 0 (verts))") == str(surf.num_vertices()) + # A DSL write is visible back in Python. + ex.run('(state-set "dsl.done" "yes")') + assert pycvc.state_get(app, "dsl.done") == "yes" # Phase 5a: drop the meshes into a scene bound to the SAME app (no cvcGL # singleton). num_graphics reflects what we added. diff --git a/cvcpkg/recipes/cvcgl-examples/build-wasm.sh b/cvcpkg/recipes/cvcgl-examples/build-wasm.sh index 2e8ba80a..dfce801d 100755 --- a/cvcpkg/recipes/cvcgl-examples/build-wasm.sh +++ b/cvcpkg/recipes/cvcgl-examples/build-wasm.sh @@ -54,7 +54,6 @@ emcmake cmake -G Ninja \ -DCVC_ENABLE_ASSIMP=ON \ -DCVC_ENABLE_MESHER=OFF \ -DCVC_ENABLE_SDF=ON \ - -DCVC_STATE_EXEC=OFF \ -DCVC_BUILD_CVCGL=ON \ -DCVC_BUILD_EXAMPLES=ON \ -DCVC_WASM_PTHREADS=ON \ diff --git a/cvcpkg/recipes/cvcgl-examples/recipe.yaml b/cvcpkg/recipes/cvcgl-examples/recipe.yaml index 488ec3b9..b5b04e9e 100644 --- a/cvcpkg/recipes/cvcgl-examples/recipe.yaml +++ b/cvcpkg/recipes/cvcgl-examples/recipe.yaml @@ -14,7 +14,10 @@ recipe: # build-pages.py into share/cvcgl-examples/web/, so cvcgl-examples-web serves # the same gallery that deploys to gh-pages. lsystem_forest dropped from the # wasm gallery (irrelevant to navigation). - cvc_revision: 2 + # Bumped 2 -> 3: build-wasm.sh no longer forces state_exec OFF (the + # CVC_STATE_EXEC option is gone; state_exec is always built), so the wasm + # gallery carries the program lanes that Ariadne apps run on. + cvc_revision: 3 maintainer: "cvcpkg group" maintainer_email: "info@cvcpkg.org" maintainer_url: "https://cvcpkg.org" diff --git a/cvcpkg/recipes/libcvc/recipe.yaml b/cvcpkg/recipes/libcvc/recipe.yaml index 75dcd88b..9a7c91ce 100644 --- a/cvcpkg/recipes/libcvc/recipe.yaml +++ b/cvcpkg/recipes/libcvc/recipe.yaml @@ -286,9 +286,9 @@ depends: # The gRPC/xmlrpc network state-transport stack (CVC_USING_XMLRPC + CVC_ENABLE_GRPC). # Scoped to the platforms this recipe actually BUILDS the transport on (the build matrix # below: linux/macos/windows). The wasm-mt bundle (built separately by publish-cvcgl-wasm.yml, - # xmlrpc/grpc OFF, CVC_STATE_EXEC ON) links none of these, so declaring them for wasm made + # xmlrpc/grpc OFF) links none of these, so declaring them for wasm made # `cvcpkg install cvc/libcvc --platform wasm-mt` fail to resolve (abseil/protobuf/grpc are not - # published for wasm). The state_exec evaluator is independent of this stack and stays on. + # published for wasm). The state_exec evaluator is independent of this stack (always built). - name: openssl platforms: [linux, macos, windows] - name: c-ares diff --git a/cvcpkg/recipes/pycvc-gl-cp312/build-wasm.ps1 b/cvcpkg/recipes/pycvc-gl-cp312/build-wasm.ps1 index fc5d064d..43fdf829 100644 --- a/cvcpkg/recipes/pycvc-gl-cp312/build-wasm.ps1 +++ b/cvcpkg/recipes/pycvc-gl-cp312/build-wasm.ps1 @@ -85,7 +85,6 @@ Invoke-CvcWasmCMakeBuild -ExtraArgs @( '-DCVC_ENABLE_ASSIMP=ON', '-DCVC_ENABLE_MESHER=OFF', '-DCVC_ENABLE_SDF=ON', - '-DCVC_STATE_EXEC=OFF', '-DCVC_BUILD_CVCGL=ON', '-DCVC_BUILD_EXAMPLES=OFF', "-DCVC_WASM_PTHREADS=$pthreads", diff --git a/cvcpkg/recipes/pycvc-gl-cp312/build-wasm.sh b/cvcpkg/recipes/pycvc-gl-cp312/build-wasm.sh index 13aec89b..cc4fec90 100644 --- a/cvcpkg/recipes/pycvc-gl-cp312/build-wasm.sh +++ b/cvcpkg/recipes/pycvc-gl-cp312/build-wasm.sh @@ -92,7 +92,6 @@ emcmake cmake -G Ninja \ -DCVC_ENABLE_ASSIMP=ON \ -DCVC_ENABLE_MESHER=OFF \ -DCVC_ENABLE_SDF=ON \ - -DCVC_STATE_EXEC=OFF \ -DCVC_BUILD_CVCGL=ON \ -DCVC_BUILD_EXAMPLES=OFF \ -DCVC_WASM_PTHREADS="${_PTHREADS}" \ diff --git a/docs/ARIADNE.md b/docs/ARIADNE.md index 025dfdc1..8efffe97 100644 --- a/docs/ARIADNE.md +++ b/docs/ARIADNE.md @@ -78,8 +78,8 @@ safety property. You cannot make a "read" slot perform an action, or vice versa. Reactive slots — `visible_when`, `enabled_when` / `disabled_when`, computed `bind` / `text`, `tooltip`, `options`, `repeat.count` — run in a long-lived stackless evaluator -(`class ReactiveEngine`, [`ariadne.cpp:385`](../src/cvc/ariadne/ariadne.cpp), compiled -under `CVC_STATE_EXEC`) over a **default-deny** environment: +(`class ReactiveEngine`, [`ariadne.cpp:385`](../src/cvc/ariadne/ariadne.cpp)) over a +**default-deny** environment: - The value allowlist admits arithmetic, coercion, logic, and side-effect-free state *readers* only (`kAllowed`, [`ariadne.cpp:417`](../src/cvc/ariadne/ariadne.cpp)). @@ -91,9 +91,8 @@ Nothing that writes state, schedules, watches, sends messages, or does I/O is reachable. An off-allowlist symbol does not error loudly — it **fails safe**: the slot degrades to hidden / disabled / empty / last-good value and the frame records a one-shot warning (`take_reactive_warnings`, -[`ariadne.cpp:1682`](../src/cvc/ariadne/ariadne.cpp)). When the build lacks -`CVC_STATE_EXEC` the whole engine is `#ifdef`'d out and reactive slots default to their -fail-safe *shown* state. +[`ariadne.cpp:1682`](../src/cvc/ariadne/ariadne.cpp)). state_exec is always built (there is +no build option to drop it), so the engine is always present. **The read lane never parks.** It is bounded three ways ([`ariadne.cpp:603`](../src/cvc/ariadne/ariadne.cpp)): diff --git a/docs/roadmap/ARIADNE_APPRUNTIME_REFACTOR.md b/docs/roadmap/ARIADNE_APPRUNTIME_REFACTOR.md index 27157b0a..d33218df 100644 --- a/docs/roadmap/ARIADNE_APPRUNTIME_REFACTOR.md +++ b/docs/roadmap/ARIADNE_APPRUNTIME_REFACTOR.md @@ -85,7 +85,6 @@ public: std::vector take_warnings(); bool reload_if_changed(); - static bool have_state_exec(); static bool have_yaml(); }; } diff --git a/docs/roadmap/CVCGL-UI-DSL-ROADMAP.md b/docs/roadmap/CVCGL-UI-DSL-ROADMAP.md index 5c59847d..30cd1a90 100644 --- a/docs/roadmap/CVCGL-UI-DSL-ROADMAP.md +++ b/docs/roadmap/CVCGL-UI-DSL-ROADMAP.md @@ -902,8 +902,8 @@ This is the heart of v0.2. Every `*_when`, `fmt`, dynamic `options`, `repeat.cou computed `bind`, and every `on:`/`on_change:` action is a `state_exec` program over the **same state tree the widgets bind to**. -> **Status — the read-only lane's first field, `visible_when`, is LANDED** (`cvc::ariadne`, -> `CVC_STATE_EXEC`-gated). `Widget::visible_when` is a predicate the walk re-evaluates each +> **Status — the read-only lane's first field, `visible_when`, is LANDED** (`cvc::ariadne`). +> `Widget::visible_when` is a predicate the walk re-evaluates each > frame; falsy → the widget and its subtree are skipped (in a grid, a hidden child consumes > **no** cell). Implementation notes that refine §4.1 below as-built: > - **Default-deny, on mechanisms not just an allowlist.** The between-steps caps cannot see @@ -928,18 +928,16 @@ the **same state tree the widgets bind to**. > aggregate wall-time budget (so N reactive widgets can't together stall a frame). A step > cap returns `done==false`; a time cap throws `evaluation_timeout`; both → fail-safe hide > + one warning. Diagnostics are de-duplicated and drained by `Runtime::take_reactive_warnings()`. -> - **Fail-safe polarity.** A broken/over-budget predicate HIDES the widget (§4.1). The one -> deliberate carve-out: on a build **without** `CVC_STATE_EXEC` a `visible_when` widget is -> SHOWN (+ a one-time warning), not hidden — hiding every reactive widget would gut a -> minimal build. That is a build-config axis, distinct from a per-eval failure on a build -> that *has* the evaluator (which hides). +> - **Fail-safe polarity.** A broken/over-budget predicate HIDES the widget (§4.1). (An earlier +> carve-out SHOWED `visible_when` widgets on builds without state_exec; the `CVC_STATE_EXEC` +> option was removed in #493, so every build has the evaluator.) > > **Also LANDED — `enabled_when` / `disabled_when`** (reactive grey-out, the sibling of > `visible_when`): a widget stays drawn but non-interactive when `enabled_when` is falsy or > `disabled_when` is truthy. Realized through a new backend `begin_disabled()`/`end_disabled()` > scope (non-pure no-op defaults; ImGuiBackend → `ImGui::BeginDisabled/EndDisabled`) wrapping the -> widget and its subtree. Fail-safe DISABLES on a broken predicate; a build without state_exec -> leaves it enabled (+ warns once). Same hardened engine as `visible_when`. +> widget and its subtree. Fail-safe DISABLES on a broken predicate. Same hardened engine as +> `visible_when`. > > **Also LANDED — computed values + `options` + `tooltip`** (on `ReactiveEngine::eval_string` / > `eval_string_list`): a Text whose `bind` is an s-expression (starts with `(`) is a computed @@ -1160,7 +1158,7 @@ other `on:tick`/`on:key` cadence questions. `state-set` (coalesced publisher). No scheduler touched on the draw thread. - **Action fire (during the walk):** never inline. Fast path enqueues an intent; general path calls `execute(ast, opts)→pid`. - > **Program `on:` LANDED** (`ariadne.cpp`, `CVC_STATE_EXEC`): an `on:` value that starts with + > **Program `on:` LANDED** (`ariadne.cpp`): an `on:` value that starts with > `(` — an s-expression, exactly like a computed `bind:`/`tooltip:` — is a **state_exec program** > run at `Runtime::drain()`, not a bare event name. So a flag toggle / reset is **pure `.ari`**, > no C++ handler (`on: (state-set "paused" (if …))`). It shares one bounded runner with the @@ -3848,13 +3846,13 @@ points are before anything renders. **The `init:` block — a state_exec script run on load.** An optional top-level `init:` block carries a `cvc::state_exec` script that runs ONCE at load, for dynamic initialization (seed/compute state before the first frame). The loader only CAPTURES the text into `LoadResult::init_script` (it has no `cvc::app` and -never runs the DSL); `cvc::ariadne::run_init(app, prefix, script, errors)` runs it — a core seam gated by -`CVC_STATE_EXEC` (state_exec is core libcvc, so no VTK), which the host calls after load and BEFORE the +never runs the DSL); `cvc::ariadne::run_init(app, prefix, script, errors)` runs it — a core seam +(state_exec is core libcvc, so no VTK), which the host calls after load and BEFORE the first `render()`. It runs the script under a state_exec **chroot at the document prefix**, so `(state-set "demo.agents" "256")` writes `.demo.agents` — the same key a widget `bind: demo.agents` resolves to (the shared "." separator), and init values win because widget/scene `read_or_seed` only fills keys init left unset. A parse/runtime error is reported (never thrown), not fatal — init is optional -dynamic seeding, not a hard gate; `have_state_exec()` reports whether the build can run it. The run is +dynamic seeding, not a hard gate. The run is **bounded** (a finite step + wall-clock budget on both the process and the run loop, and success requires a `terminated` status) so a looping or blocking init script is reported rather than hanging the app at load. This is a new concept beyond the two §4.1 state_exec lanes (per-frame read + effectful action): a run-once init lane. diff --git a/docs/roadmap/STATE_EXEC_PORTING_PLAN.md b/docs/roadmap/STATE_EXEC_PORTING_PLAN.md index ebe94a86..a8fbc372 100644 --- a/docs/roadmap/STATE_EXEC_PORTING_PLAN.md +++ b/docs/roadmap/STATE_EXEC_PORTING_PLAN.md @@ -2315,7 +2315,8 @@ Map per category: #### Phase 7: CMake Integration + Polish 34. ✅ **CMakeLists.txt** updates — `CVC_STATE_EXEC` and - `CVC_STATE_MEMORY_MANAGER` feature-flag options (default ON). + `CVC_STATE_MEMORY_MANAGER` feature-flag options (default ON). (`CVC_STATE_EXEC` + was later removed in #493 — state_exec is always built.) Conditional source filtering and test target guards (`add_executable`, `target_link_libraries`, `target_compile_features`, `gtest_discover_tests`) wrap all state_exec and memory_manager targets. diff --git a/docs/roadmap/STATE_EXEC_ROADMAP.md b/docs/roadmap/STATE_EXEC_ROADMAP.md index 9c41bf57..248bed07 100644 --- a/docs/roadmap/STATE_EXEC_ROADMAP.md +++ b/docs/roadmap/STATE_EXEC_ROADMAP.md @@ -100,7 +100,7 @@ Full design: [STATE_EXEC_PORTING_PLAN.md](STATE_EXEC_PORTING_PLAN.md) | Component | Status | Tests | |-----------|--------|-------| -| `CVC_STATE_EXEC` feature flag | ✅ Done | — | +| `CVC_STATE_EXEC` feature flag | ✅ Done, later removed (#493) — always built | — | | `CVC_STATE_MEMORY_MANAGER` feature flag | ✅ Done | — | | Doxygen `@file`/`@brief` on all 17 headers | ✅ Done | — | | Benchmark tests | ✅ Done | 7 | diff --git a/inc/cvc/ariadne/app_runtime.h b/inc/cvc/ariadne/app_runtime.h index 3475cb14..e03fc0df 100644 --- a/inc/cvc/ariadne/app_runtime.h +++ b/inc/cvc/ariadne/app_runtime.h @@ -12,10 +12,8 @@ // + a cvcGL SceneAdapter + an AppRuntime. A terminal host would compose an FtxuiBackend // + no adapter over the same AppRuntime. // -// libpython-free (std::function, never PyObject*). The program lanes (init:/on_tick/ -// on_key/on_pointer, register_verb*, the scheduler pump) are no-ops without -// CVC_STATE_EXEC; loading a YAML .ari needs the yaml build. have_state_exec()/have_yaml() -// report which are live. +// libpython-free (std::function, never PyObject*). Loading a YAML .ari needs the yaml +// build; have_yaml() reports whether it is live. #pragma once #include @@ -64,7 +62,7 @@ class AppRuntime { // inline on the drain thread, no args/return). register_async_verb OFFLOADS `work` to the // app compute pool and posts its string result to `done_channel`; the program parks on // (msg-recv "done_channel") and resumes under drain()'s slice budget (the nav_compute - // pattern). Both are no-ops without state_exec. + // pattern). void register_verb(const std::string &name, std::function fn); void register_async_verb(const std::string &name, const std::string &done_channel, std::function work); @@ -96,7 +94,6 @@ class AppRuntime { // --- diagnostics / capabilities --- std::vector take_warnings(); // reactive read-lane diagnostics from the last render bool reload_if_changed(); // §12.5 hot reload if a watched source changed - static bool have_state_exec(); // program lanes + verbs live? static bool have_yaml(); // can load a YAML .ari? private: diff --git a/inc/cvc/ariadne/ariadne.h b/inc/cvc/ariadne/ariadne.h index e07bd039..2e88e89a 100644 --- a/inc/cvc/ariadne/ariadne.h +++ b/inc/cvc/ariadne/ariadne.h @@ -68,8 +68,8 @@ class Runtime { // Unlike a fire-once action `on:`, this submits ONE long-lived, owner-tagged process on the // app-wide scheduler that PARKS between frames (it never re-submits per frame); each drain() // posts it a tick to run the program once. Pass a LoadResult::on_tick_script here after loading. - // "" clears it (kills the resident). A no-op in a build without state_exec. The resident is - // reaped with the Runtime (kill_owner on teardown). + // "" clears it (kills the resident). The resident is reaped with the Runtime (kill_owner on + // teardown). void set_tick_program(std::string script); // §4.6 document-level input handlers — register a state_exec PROGRAM run per input event. Like @@ -79,7 +79,7 @@ class Runtime { // set_key_program handles keyboard events (key_down/key_up); set_pointer_program handles mouse // events (mouse_move/mouse_button_*/mouse_wheel). Pass LoadResult::on_key_script / // on_pointer_script. - // "" clears it. No-ops without state_exec. (Widget-level on_click/on_hover are a separate path.) + // "" clears it. (Widget-level on_click/on_hover are a separate path.) void set_key_program(std::string script); void set_pointer_program(std::string script); @@ -91,16 +91,14 @@ class Runtime { // (the load lint already surfaced those), which clears enforcement. The host feeds these from a // LoadResult (channels: + lint:); pass plain vectors so this header stays independent of the // loader. Calling with `strict=false` and empty lists (the default) disables runtime enforcement. - // A no-op without state_exec. Set once after load, before render/drain; it applies to every - // action + resident. + // Set once after load, before render/drain; it applies to every action + resident. void set_channel_policy(std::vector declared, std::vector global, bool strict, bool quiet); // Feed one input event to the runtime — the host calls this each frame for every event from its // input source (e.g. cvc::gl::SdlInput), BEFORE drain(), so the event is delivered to the // on_key/on_pointer residents this same frame (drain() drains the ingress + pumps). Thread-safe - // (routes through the scheduler's MPSC ingress). A no-op without state_exec, or if no matching - // handler is registered. + // (routes through the scheduler's MPSC ingress). A no-op if no matching handler is registered. void post_input(const InputEvent &ev); // Render one frame: apply any pending tree swap, then walk the tree driving the @@ -115,7 +113,7 @@ class Runtime { // Drain the §4 read-lane diagnostics accumulated during render() — one message per // distinct failing predicate (a parse error, a runtime error, or a per-frame budget - // overrun; or, on a build without state_exec, one note that visible_when was ignored). + // overrun). // De-duplicated for the Runtime's lifetime, so a broken predicate warns ONCE however // many frames it renders. Empty when everything evaluated cleanly. The host may log // these (e.g. after the first frame); ignoring them is safe — the walk already @@ -168,16 +166,12 @@ bool has_widget_type(const std::string &type); // `bind: demo.n` resolves to (a state_exec chroot on the shared "." separator). Run it // at load, BEFORE the first render(), so init values win and widget/scene read_or_seed // defaults only fill keys init left unset. Returns true on success (or an empty -// script); false with a message appended to `errors` on a parse/runtime error, or when -// this build lacks state_exec. Never throws. (The loader stays app-free and only -// captures the script; this is the host/Runtime-side seam that has the app.) +// script); false with a message appended to `errors` on a parse/runtime error. Never +// throws. (The loader stays app-free and only captures the script; this is the +// host/Runtime-side seam that has the app.) bool run_init(cvc::app &app, const std::string &prefix, const std::string &script, std::vector *errors = nullptr); -// Whether this build has state_exec (CVC_STATE_EXEC). When false, run_init cannot -// execute a non-empty init: script (it reports an error instead). -bool have_state_exec(); - // --------------------------------------------------------------------------- // Host-contributed state_exec intrinsics for the PROGRAM lanes (init: and a program `on:` action). // A host binds native functions — e.g. nav verbs `(nav-step)` / `(nav-arrived)` — that a .ari @@ -192,7 +186,7 @@ bool have_state_exec(); // per-frame reactive READ lane (visible_when/computed binds — kept default-deny + // side-effect-free). A program on: runs synchronously on the host thread inside Runtime::drain(), // so an intrinsic that mutates async host state (a worker-thread sim) should ENQUEUE the mutation, -// not do it inline. A no-op in a build without state_exec (the program lanes do not run). +// not do it inline. // --------------------------------------------------------------------------- } // namespace ariadne namespace state_exec { diff --git a/inc/cvc/ariadne/net_intrinsics.h b/inc/cvc/ariadne/net_intrinsics.h index 77a02a34..21ef6877 100644 --- a/inc/cvc/ariadne/net_intrinsics.h +++ b/inc/cvc/ariadne/net_intrinsics.h @@ -25,7 +25,7 @@ // `init:` (no per-frame pump, so a park never resumes) and NOT in the reactive read lane // (visible_when/computed, default-deny). NATIVE ONLY for now: the background-worker model assumes // native threads (wasm needs the §13.8 async-fetch path). A no-op without a compiled cvc::net -// backend or without state_exec. +// backend. namespace cvc { class app; diff --git a/inc/cvc/core/async_task.h b/inc/cvc/core/async_task.h index 7d78c01c..be31599e 100644 --- a/inc/cvc/core/async_task.h +++ b/inc/cvc/core/async_task.h @@ -37,8 +37,6 @@ #ifndef CVC_CORE_ASYNC_TASK_H #define CVC_CORE_ASYNC_TASK_H -#ifdef CVC_STATE_EXEC - #include #include #include @@ -81,6 +79,4 @@ state_exec::value_t future_pool_task(app &a, state_exec::async_scheduler &sched, } // namespace cvc -#endif // CVC_STATE_EXEC - #endif // CVC_CORE_ASYNC_TASK_H diff --git a/inc/cvc/gl/ariadne/AriRuntime.h b/inc/cvc/gl/ariadne/AriRuntime.h index 2cab8dea..f9d1a04e 100644 --- a/inc/cvc/gl/ariadne/AriRuntime.h +++ b/inc/cvc/gl/ariadne/AriRuntime.h @@ -10,8 +10,8 @@ // render test consume it exactly as before. libpython-free (std::function, never // PyObject*). Input is VTK's (widget on_click/on_hover + camera nav arrive through the VTK // interactor -> ImGui); document-level on_key/on_pointer residents need a producer fed via -// post_key/post_pointer (a follow-up seam), never SDL. The program lanes are no-ops without -// CVC_STATE_EXEC; loading a YAML .ari needs the yaml build. +// post_key/post_pointer (a follow-up seam), never SDL. Loading a YAML .ari needs the yaml +// build. #pragma once #include // cvc::ariadne::AppRuntime, SceneAdapter @@ -72,7 +72,6 @@ class AriRuntime { // --- diagnostics / capabilities --- std::vector take_warnings(); bool reload_if_changed(); - static bool have_state_exec(); static bool have_yaml(); private: diff --git a/src/cvc/CMakeLists.txt b/src/cvc/CMakeLists.txt index ccba3a49..9263b210 100644 --- a/src/cvc/CMakeLists.txt +++ b/src/cvc/CMakeLists.txt @@ -348,15 +348,9 @@ if(WIN32) list(REMOVE_ITEM SOURCE_FILES core/state_transport_ipc.cpp) endif() -# state_exec / state_memory_manager feature flags -option(CVC_STATE_EXEC "Enable state_exec DSL evaluator and process scheduler" ON) +# state_memory_manager feature flag option(CVC_STATE_MEMORY_MANAGER "Enable state memory manager with LRU/LFU eviction" ON) -if(NOT CVC_STATE_EXEC) - list(FILTER SOURCE_FILES EXCLUDE REGEX "core/state_exec/") -endif() - -# state_memory_manager feature flag if(NOT CVC_STATE_MEMORY_MANAGER) list(REMOVE_ITEM SOURCE_FILES core/state_memory_manager.cpp core/state_eviction_store.cpp) endif() @@ -1319,9 +1313,6 @@ if(CVC_ENABLE_GRPC) target_include_directories(cvc PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(cvc PRIVATE gRPC::grpc++ protobuf::libprotobuf) endif() -if(CVC_STATE_EXEC) - target_compile_definitions(cvc PUBLIC CVC_STATE_EXEC) -endif() if(CVC_STATE_MEMORY_MANAGER) target_compile_definitions(cvc PUBLIC CVC_STATE_MEMORY_MANAGER) endif() diff --git a/src/cvc/ariadne/app_runtime.cpp b/src/cvc/ariadne/app_runtime.cpp index e23f49e4..f70f8b4a 100644 --- a/src/cvc/ariadne/app_runtime.cpp +++ b/src/cvc/ariadne/app_runtime.cpp @@ -7,17 +7,14 @@ #include // load_file / LoadResult / ChannelDecl / sources_changed #include // register_cvc_uri_handler #include -#include -#include - -#ifdef CVC_STATE_EXEC #include // exec_scheduler().post_message #include // register_fn #include // intrinsics_context, resolve_channel_key #include // value_t #include #include -#endif +#include +#include namespace cvc { namespace ariadne { @@ -36,7 +33,6 @@ void AppRuntime::on(const std::string &event, std::function handler) { rt_.on(event, std::move(handler)); } -bool AppRuntime::have_state_exec() { return cvc::ariadne::have_state_exec(); } bool AppRuntime::have_yaml() { return cvc::ariadne::have_yaml(); } // ── host verbs on the app-wide scheduler ──────────────────────────────────────────────────────── @@ -52,9 +48,8 @@ void AppRuntime::register_async_verb(const std::string &name, const std::string ensure_intrinsics(); } -#ifdef CVC_STATE_EXEC void AppRuntime::ensure_intrinsics() { - if (intrinsicsRegistered_ || !have_state_exec()) + if (intrinsicsRegistered_) return; intrinsicsRegistered_ = true; cvc::app *app = &app_; @@ -97,9 +92,6 @@ void AppRuntime::ensure_intrinsics() { } }); } -#else -void AppRuntime::ensure_intrinsics() {} -#endif // ── document ──────────────────────────────────────────────────────────────────────────────────── diff --git a/src/cvc/ariadne/ariadne.cpp b/src/cvc/ariadne/ariadne.cpp index 7948f3d5..9f41494d 100644 --- a/src/cvc/ariadne/ariadne.cpp +++ b/src/cvc/ariadne/ariadne.cpp @@ -7,14 +7,16 @@ // backend reports the edit committed — so a slider drag costs one state write on // release, not one per frame (writes fan out to observers / replicated peers). +#include +#include +#include +#include #include #include #include #include // §4.6 InputEvent — Runtime::post_input feeds on_key/on_pointer #include #include - -#ifdef CVC_STATE_EXEC #include // §4.7 app-wide action scheduler (exec_scheduler) #include #include // evaluation_timeout / evaluation_interrupted @@ -23,12 +25,6 @@ #include #include #include // §4 read-lane predicate evaluator -#endif - -#include -#include -#include -#include #include #include #include // §11.4 geometry (de)serialize: pin std::locale::classic() so digit grouping @@ -233,20 +229,10 @@ bool has_widget_type(const std::string &type) { return widget_registry().find(type) != widget_registry().end(); } -// --- the init: block runner (state_exec, gated by CVC_STATE_EXEC) ------------ - -bool have_state_exec() { -#ifdef CVC_STATE_EXEC - return true; -#else - return false; -#endif -} +// --- the init: block runner (state_exec) -------------------------------------- -// Host-contributed program-lane intrinsics registry (§ nav verbs et al.). Kept OUTSIDE the -// CVC_STATE_EXEC guard so register/clear are always callable (the providers are simply never -// applied in a build with no program lanes). ActionIntrinsicProvider is state_exec-typed via -// forward-decls. +// Host-contributed program-lane intrinsics registry (§ nav verbs et al.). ActionIntrinsicProvider +// is state_exec-typed via forward-decls. namespace { std::mutex &action_intrinsics_mutex() { static std::mutex m; @@ -273,7 +259,6 @@ void clear_action_intrinsics() { action_intrinsics_registry().clear(); } -#ifdef CVC_STATE_EXEC namespace { // Run `script` as a FULL-ENV state_exec program chrooted to `prefix`, bounded by (max_steps, // max_seconds, max_bytes). Returns "" on a clean, normal finish, else a human diagnostic (no @@ -332,7 +317,6 @@ std::string run_scoped_program(cvc::app &app, const std::string &prefix, const s } } } // namespace -#endif // CVC_STATE_EXEC bool run_init(cvc::app &app, const std::string &prefix, const std::string &script, std::vector *errors) { @@ -342,13 +326,6 @@ bool run_init(cvc::app &app, const std::string &prefix, const std::string &scrip }; if (script.empty()) return true; // nothing to run -#ifndef CVC_STATE_EXEC - (void)app; - (void)prefix; - err("ari: init: script present but this libcvc was built without state_exec " - "(CVC_STATE_EXEC=OFF) — the script did not run"); - return false; -#else // A load-time seed/compute is generous — well above the per-tick action budget (§7.4). static constexpr uint64_t kInitMaxSteps = 10'000'000; static constexpr double kInitMaxSeconds = 5.0; @@ -358,11 +335,9 @@ bool run_init(cvc::app &app, const std::string &prefix, const std::string &scrip return false; } return true; -#endif } // --- §4 read-lane: the per-frame reactive predicate evaluator ---------------- -#ifdef CVC_STATE_EXEC namespace { namespace se = cvc::state_exec; @@ -616,7 +591,6 @@ class ReactiveEngine { std::unordered_map> compiled_; }; } // namespace -#endif // CVC_STATE_EXEC struct Runtime::Impl { cvc::app &app; @@ -626,7 +600,8 @@ struct Runtime::Impl { // §12 channel enforcement: the document's channel policy, installed on every action/resident // ictx. Default (enforce=false, empty) = permissive; set_channel_policy fills it from a // LoadResult. Pointed-to by ictx.channels (non-owning), so it must outlive the contexts — it - // lives here in the Impl, which owns the live_actions_ / residents that reference it. + // lives here in the Impl, which owns the live_actions_ / residents that reference it. Declared + // before them so it destructs after them. cvc::state_exec::channel_policy channel_policy_; Widget root; @@ -651,11 +626,8 @@ struct Runtime::Impl { // §4 read-lane: the reactive predicate evaluator (lazily built on first use so a UI // with no reactive fields pays nothing), plus de-duplicated diagnostics surfaced by - // take_reactive_warnings(). The warnings live regardless of state_exec (the OFF path - // also warns once). reactive_warned keeps the dedup set across drains. -#ifdef CVC_STATE_EXEC + // take_reactive_warnings(). reactive_warned keeps the dedup set across drains. std::unique_ptr reactive; -#endif std::vector reactive_warnings; std::set reactive_warned; int frame_instances = 0; // §3: repeat instances emitted this frame (bounds many repeats) @@ -669,7 +641,6 @@ struct Runtime::Impl { Impl(cvc::app &a, std::string p) : app(a), prefix(std::move(p)) {} ~Impl(); -#ifdef CVC_STATE_EXEC // A submitted `on:` program's persistent context. The intrinsics capture &ictx by // pointer, so — unlike the load-time init: lane's one-scope run — an action that // suspends (await/sleep/msg-recv) needs its context kept alive across frames until the @@ -716,7 +687,6 @@ struct Runtime::Impl { // Deliver one input event: serialize it to a dict and post_message it (NO coalesce — a burst in // one frame must all arrive) onto the key channel (keyboard) or pointer channel (mouse). void deliver_input(const InputEvent &ev); -#endif // §12: the active mount scope during emit. Empty stack = the document prefix; each entry is // a composed sub-prefix pushed when the walk enters a mounted subtree (Widget::scope) and @@ -756,7 +726,6 @@ struct Runtime::Impl { return resolve_bind(current_prefix(), bind); } -#ifdef CVC_STATE_EXEC // Lazily build the read-lane engine (a UI with no reactive fields pays nothing), then point // it at the active mount scope so a mounted fragment's predicates read its own sub-prefix, // matching where its binds resolve. Every reactive helper goes through here. @@ -766,7 +735,6 @@ struct Runtime::Impl { reactive->set_root_path(app, current_prefix()); return *reactive; } -#endif void enqueue(const std::string &event) { if (!event.empty()) @@ -790,12 +758,11 @@ struct Runtime::Impl { void render(); // §4 read-lane: is `w` shown this frame? True when it has no visible_when; otherwise - // the predicate's result (fail-safe HIDDEN on a state_exec build, fail-safe SHOWN on a - // build without state_exec — hiding every reactive widget would gut a minimal build). + // the predicate's result (fail-safe HIDDEN on a broken predicate). bool visible(const Widget &w); // §4 read-lane: is `w` disabled (greyed, non-interactive) this frame? True when // enabled_when is falsy OR disabled_when is truthy. Fail-safe DISABLED on a broken - // predicate; a build without state_exec leaves it enabled (+ warns once). + // predicate. bool disabled(const Widget &w); // §4 read-lane: evaluate a computed-value expression `expr` to a display string. // Fail-safe EMPTY string on a broken predicate (§4.1 fmt→""); warns once. @@ -818,22 +785,15 @@ struct Runtime::Impl { bool Runtime::Impl::visible(const Widget &w) { if (w.visible_when.empty()) return true; -#ifdef CVC_STATE_EXEC const ReactiveEngine::Outcome o = ensure_reactive().eval_bool(w.visible_when, /*dflt=*/false); if (!o.error.empty()) warn_once(o.error); return o.value; -#else - warn_once("ari: visible_when on '" + (w.label.empty() ? w.id : w.label) + - "' ignored — this libcvc was built without state_exec (CVC_STATE_EXEC=OFF)"); - return true; -#endif } bool Runtime::Impl::disabled(const Widget &w) { if (w.enabled_when.empty() && w.disabled_when.empty()) return false; -#ifdef CVC_STATE_EXEC ReactiveEngine &re = ensure_reactive(); // enabled_when falsy -> disabled (fail-safe dflt=false: a broken predicate disables). if (!w.enabled_when.empty()) { @@ -852,55 +812,33 @@ bool Runtime::Impl::disabled(const Widget &w) { return true; } return false; -#else - warn_once("ari: enabled_when/disabled_when on '" + (w.label.empty() ? w.id : w.label) + - "' ignored — this libcvc was built without state_exec (CVC_STATE_EXEC=OFF)"); - return false; // can't evaluate -> leave it functional -#endif } std::string Runtime::Impl::eval_text(const std::string &expr) { -#ifdef CVC_STATE_EXEC const ReactiveEngine::StringOutcome o = ensure_reactive().eval_string(expr, /*dflt=*/std::string()); if (!o.error.empty()) warn_once(o.error); return o.value; -#else - warn_once("ari: computed text expr ignored — this libcvc was built without state_exec " - "(CVC_STATE_EXEC=OFF)"); - return std::string(); -#endif } std::string Runtime::Impl::eval_text_or_literal(const std::string &expr) { -#ifdef CVC_STATE_EXEC const ReactiveEngine::StringOutcome o = ensure_reactive().eval_string(expr, /*dflt=*/std::string()); // Success -> the computed value; failure -> the literal verbatim (no warning: a tooltip that // starts with '(' is far more likely plain text than a broken expression). return o.error.empty() ? o.value : expr; -#else - return expr; // no state_exec -> show the literal -#endif } std::vector Runtime::Impl::eval_options(const std::string &expr) { -#ifdef CVC_STATE_EXEC const ReactiveEngine::StringListOutcome o = ensure_reactive().eval_string_list(expr); if (!o.error.empty()) warn_once(o.error); return o.value; -#else - warn_once("ari: computed options ignored — this libcvc was built without state_exec " - "(CVC_STATE_EXEC=OFF)"); - return {}; -#endif } int Runtime::Impl::eval_count(const std::string &expr) { constexpr int64_t kMaxRepeat = 4096; // a UI with thousands of repeated widgets is pathological -#ifdef CVC_STATE_EXEC const ReactiveEngine::IntOutcome o = ensure_reactive().eval_int(expr, /*dflt=*/0); if (!o.error.empty()) warn_once(o.error); @@ -913,11 +851,6 @@ int Runtime::Impl::eval_count(const std::string &expr) { n = kMaxRepeat; } return static_cast(n); -#else - (void)kMaxRepeat; - warn_once("ari: repeat ignored — this libcvc was built without state_exec (CVC_STATE_EXEC=OFF)"); - return 0; -#endif } void Runtime::Impl::emit_children(const Widget &w) { @@ -1345,10 +1278,8 @@ void Runtime::Impl::render() { planted_holes.clear(); wired_mounts.clear(); } -#ifdef CVC_STATE_EXEC if (reactive) reactive->begin_frame(); // §4: reset the per-frame reactive eval budget -#endif frame_instances = 0; // §3: reset the per-frame repeat-expansion budget scope_stack.clear(); // §12: start every frame at the document scope (RAII keeps it balanced; // this is belt-and-suspenders so one bad frame can't leak into the next) @@ -1362,16 +1293,13 @@ void Runtime::Impl::render() { std::atomic Runtime::Impl::owner_seq{0}; Runtime::Impl::~Impl() { -#ifdef CVC_STATE_EXEC // Reap this document's whole process group so a parked (await/sleep/msg-recv) action never // lingers on the shared app scheduler after its Runtime is gone. Only touch the scheduler if // we ever used it (exec_scheduler() lazily builds it — don't force it at teardown otherwise). if (used_scheduler_) app.exec_scheduler().kill_owner(owner_); -#endif } -#ifdef CVC_STATE_EXEC void Runtime::Impl::submit_action(const QueuedAction &action) { namespace se = cvc::state_exec; const std::string &action_prefix = action.prefix; @@ -1548,7 +1476,6 @@ void Runtime::Impl::deliver_input(const InputEvent &ev) { app.exec_scheduler().post_message(keyboard ? key_channel() : pointer_channel(), se::make_dict(std::move(f))); } -#endif // CVC_STATE_EXEC Runtime::Runtime(cvc::app &app, std::string prefix) : m_(new Impl(app, std::move(prefix))) {} @@ -1566,7 +1493,6 @@ void Runtime::on(std::string event, std::function handler) { } void Runtime::set_tick_program(std::string script) { -#ifdef CVC_STATE_EXEC // Replacing the program kills any running resident so the new body starts fresh next drain. if (m_->tick_resident_pid_ >= 0) { m_->app.exec_scheduler().kill(m_->tick_resident_pid_); @@ -1574,40 +1500,28 @@ void Runtime::set_tick_program(std::string script) { m_->tick_resident_pid_ = -1; } m_->tick_script_ = std::move(script); -#else - (void)script; // residents need state_exec — no-op otherwise -#endif } void Runtime::set_key_program(std::string script) { -#ifdef CVC_STATE_EXEC if (m_->key_resident_pid_ >= 0) { m_->app.exec_scheduler().kill(m_->key_resident_pid_); m_->key_resident_.reset(); m_->key_resident_pid_ = -1; } m_->key_script_ = std::move(script); -#else - (void)script; -#endif } void Runtime::set_pointer_program(std::string script) { -#ifdef CVC_STATE_EXEC if (m_->pointer_resident_pid_ >= 0) { m_->app.exec_scheduler().kill(m_->pointer_resident_pid_); m_->pointer_resident_.reset(); m_->pointer_resident_pid_ = -1; } m_->pointer_script_ = std::move(script); -#else - (void)script; -#endif } void Runtime::set_channel_policy(std::vector declared, std::vector global, bool strict, bool quiet) { -#ifdef CVC_STATE_EXEC // Installed on every action/resident ictx via the &channel_policy_ pointer set in submit_action / // submit_resident, so this applies from the next activation on. `strict` is the enforce switch; // warn/off pass strict=false (the load-time lint already surfaced those), leaving runtime @@ -1617,24 +1531,14 @@ void Runtime::set_channel_policy(std::vector declared, std::vector< m_->channel_policy_.global = std::move(global); m_->channel_policy_.enforce = strict; m_->channel_policy_.quiet = quiet; -#else - (void)declared; - (void)global; - (void)strict; - (void)quiet; -#endif } void Runtime::post_input(const InputEvent &ev) { -#ifdef CVC_STATE_EXEC // Submit the input residents on first use so the delivered event is consumed, not dropped, then // deliver it. The pump in drain() steps the resident; feed input BEFORE drain() for same-frame - // delivery (see the header contract). A no-op without state_exec. + // delivery (see the header contract). m_->ensure_input_residents(); m_->deliver_input(ev); -#else - (void)ev; -#endif } void Runtime::render() { m_->render(); } @@ -1648,24 +1552,17 @@ void Runtime::drain() { // A program action (`on:` starting with '(', like a computed `bind:`/`tooltip:`) runs through // state_exec — the north-star lane: a flag toggle or reset is pure .ari, no C++ handler. if (is_expr(a.event)) { // a program on: (whitespace-tolerant, exactly like a computed bind:) -#ifdef CVC_STATE_EXEC // SUBMIT it to the app-wide scheduler (owner-tagged, chrooted to the action's mount prefix) // and return — no run-to-completion inside drain(). The per-frame pump below advances it; a // quick action still finishes this drain, while an (await …)/(msg-recv …)/(sleep …) parks // and resumes on a later frame instead of blocking the UI thread (§4.7). m_->submit_action(a); -#else - m_->warn_once("ari: on: a program action needs state_exec (CVC_STATE_EXEC=OFF); it did not " - "run [" + - a.event + "]"); -#endif continue; } auto it = m_->handlers.find(a.event); // a bare event name -> the host C++ handler seam if (it != m_->handlers.end() && it->second) it->second(); } -#ifdef CVC_STATE_EXEC // §7.1 resident on:tick: submit the resident once (idempotent), then post it this frame's tick. m_->ensure_tick_resident(); m_->post_tick(); @@ -1676,7 +1573,6 @@ void Runtime::drain() { // bounded slice, then sweep the finished ones. Runs once used_scheduler_ latches. if (m_->used_scheduler_) m_->pump_and_sweep_actions(); -#endif } std::vector Runtime::take_reactive_warnings() { diff --git a/src/cvc/ariadne/loader.cpp b/src/cvc/ariadne/loader.cpp index 7a744e0b..021cccbf 100644 --- a/src/cvc/ariadne/loader.cpp +++ b/src/cvc/ariadne/loader.cpp @@ -16,12 +16,10 @@ #include #include // §12/§13 import: resolve library URIs (file/state/http) #include // CVC_VERSION_STRING (generated from project(VERSION)) -#ifdef CVC_STATE_EXEC // §12 channel lint: parse a script (parser.h) and walk its value_t / symbol / list_ptr AST // (types.h) for the static msg-* channel references. #include #include -#endif #include // §12 import: dirname of a resolved library for nested bases #include #include @@ -1633,9 +1631,7 @@ std::vector parse_customs(Ctx &ctx, const YAML::Node &c) { // §12 channel lint (A) — the fail-fast, load-time pass over a document's STATIC msg-* channel // references, gated on the document declaring a `channels:` block. Only literal channel names are -// visible here; a dynamic `(msg-recv (expr))` name is the runtime policy's job (a follow-up). No-op -// without state_exec (there are no program lanes to lint, and the parser is unavailable). -#ifdef CVC_STATE_EXEC +// visible here; a dynamic `(msg-recv (expr))` name is the runtime policy's job (a follow-up). // Walk a parsed script's value_t tree, collecting the string-literal FIRST arg of every // (msg-send|msg-recv|msg-pending …) call — the static channel references. Depth-bounded. void collect_channel_refs(const cvc::state_exec::value_t &v, std::vector &out, @@ -1676,13 +1672,11 @@ void refs_from_widget(const Widget &w, std::vector &out) { for (const Widget &c : w.children) refs_from_widget(c, out); } -#endif // Run the §12 channel lint against a fully-built LoadResult (root + scripts populated). Sets // r.error on a STRICT violation (fails the load), else appends warnings. A no-op unless the doc // declared a `channels:` block and lint.channels != Off. void lint_channels(Ctx &ctx, LoadResult &r) { -#ifdef CVC_STATE_EXEC if (!r.has_channels_block) return; // no declaration -> enforcement is not active for this document if (r.lint.channels == LintConfig::Mode::Off) { @@ -1727,10 +1721,6 @@ void lint_channels(Ctx &ctx, LoadResult &r) { return; } } -#else - (void)ctx; - (void)r; -#endif } // Parse an already-loaded YAML node into a LoadResult, applying the meta gate. `base_dir` is diff --git a/src/cvc/ariadne/net_intrinsics.cpp b/src/cvc/ariadne/net_intrinsics.cpp index 93e008c6..87004ce0 100644 --- a/src/cvc/ariadne/net_intrinsics.cpp +++ b/src/cvc/ariadne/net_intrinsics.cpp @@ -1,22 +1,19 @@ // Ariadne — async HTTP host intrinsics for the state_exec program lanes (roadmap §13.8). See -// net_intrinsics.h. The whole implementation is gated on CVC_STATE_EXEC (no program lanes without -// it) and on a compiled cvc::net backend (cvc::net::have_http_backend()). +// net_intrinsics.h. The (http-get*) verbs are gated on a compiled cvc::net backend +// (cvc::net::have_http_backend()). -#include // register_action_intrinsics, have_state_exec +#include +#include +#include // register_action_intrinsics #include #include // resolve() — the generic (fetch uri) async resolver #include #include // launch_pool_task — the shared offload-and-park primitive -#include - -#ifdef CVC_STATE_EXEC - -#include -#include #include // exec_scheduler().post_message #include // register_fn — bind the host verb into the lanes #include // resolve_channel_key — scope the reply channel #include // value_t, make_dict/make_list/make_bytes +#include #include #include #include @@ -264,8 +261,6 @@ std::string launch_uri_fetch(cvc::app &app, const std::string &root, } // namespace void register_net_intrinsics(cvc::app &app) { - if (!have_state_exec()) - return; // Warm the lazy per-app singletons on THIS thread before any background worker touches them, so a // worker never races their first construction (the nav_compute discipline). app.computePool(); @@ -346,15 +341,3 @@ void register_net_intrinsics(cvc::app &app) { } // namespace ariadne } // namespace cvc - -#else // !CVC_STATE_EXEC - -namespace cvc { -namespace ariadne { -void register_net_intrinsics(cvc::app & /*app*/) { - // No program lanes without state_exec — nothing to register. -} -} // namespace ariadne -} // namespace cvc - -#endif // CVC_STATE_EXEC diff --git a/src/cvc/core/async_task.cpp b/src/cvc/core/async_task.cpp index 6ad7c965..1e787c8c 100644 --- a/src/cvc/core/async_task.cpp +++ b/src/cvc/core/async_task.cpp @@ -1,13 +1,10 @@ // cvc::async_task — offload a blocking kernel to the compute pool and resume a parked state_exec // process when it finishes. See inc/cvc/core/async_task.h for the contract and the two rules. -#include - -#ifdef CVC_STATE_EXEC - #include #include #include +#include #include // exec_scheduler().post_message #include // resolve_channel_key, make_future, park_on_channel #include @@ -64,5 +61,3 @@ se::value_t future_pool_task(app &a, se::async_scheduler &sched, const std::stri } } // namespace cvc - -#endif // CVC_STATE_EXEC diff --git a/src/cvc/tests/CMakeLists.txt b/src/cvc/tests/CMakeLists.txt index cde17d06..f1fadbc2 100644 --- a/src/cvc/tests/CMakeLists.txt +++ b/src/cvc/tests/CMakeLists.txt @@ -54,25 +54,23 @@ add_executable(state_list_test state_list_test.cpp) if(CVC_STATE_MEMORY_MANAGER) add_executable(state_memory_manager_test state_memory_manager_test.cpp) endif() -if(CVC_STATE_EXEC) - add_executable(state_exec_types_test state_exec_types_test.cpp) - add_executable(state_exec_parser_test state_exec_parser_test.cpp) - add_executable(state_exec_builtins_test state_exec_builtins_test.cpp) - add_executable(state_exec_evaluator_test state_exec_evaluator_test.cpp) - add_executable(state_exec_stackless_evaluator_test state_exec_stackless_evaluator_test.cpp) - add_executable(state_exec_codec_test state_exec_codec_test.cpp) - add_executable(state_exec_unicode_test state_exec_unicode_test.cpp) - add_executable(state_exec_async_test state_exec_async_test.cpp) - add_executable(state_exec_scheduler_test state_exec_scheduler_test.cpp) - add_executable(state_exec_intrinsics_test state_exec_intrinsics_test.cpp) - add_executable(state_exec_coordinator_test state_exec_coordinator_test.cpp) - add_executable(state_exec_bench_test state_exec_bench_test.cpp) - add_executable(state_exec_integration_test state_exec_integration_test.cpp) - add_executable(state_exec_advanced_integration_test state_exec_advanced_integration_test.cpp) - add_executable(state_exec_gaps_test state_exec_gaps_test.cpp) - if(NOT WIN32) - add_executable(state_exec_multiprocess_test state_exec_multiprocess_test.cpp) - endif() +add_executable(state_exec_types_test state_exec_types_test.cpp) +add_executable(state_exec_parser_test state_exec_parser_test.cpp) +add_executable(state_exec_builtins_test state_exec_builtins_test.cpp) +add_executable(state_exec_evaluator_test state_exec_evaluator_test.cpp) +add_executable(state_exec_stackless_evaluator_test state_exec_stackless_evaluator_test.cpp) +add_executable(state_exec_codec_test state_exec_codec_test.cpp) +add_executable(state_exec_unicode_test state_exec_unicode_test.cpp) +add_executable(state_exec_async_test state_exec_async_test.cpp) +add_executable(state_exec_scheduler_test state_exec_scheduler_test.cpp) +add_executable(state_exec_intrinsics_test state_exec_intrinsics_test.cpp) +add_executable(state_exec_coordinator_test state_exec_coordinator_test.cpp) +add_executable(state_exec_bench_test state_exec_bench_test.cpp) +add_executable(state_exec_integration_test state_exec_integration_test.cpp) +add_executable(state_exec_advanced_integration_test state_exec_advanced_integration_test.cpp) +add_executable(state_exec_gaps_test state_exec_gaps_test.cpp) +if(NOT WIN32) + add_executable(state_exec_multiprocess_test state_exec_multiprocess_test.cpp) endif() add_executable(state_delta_codec_test state_delta_codec_test.cpp) add_executable(state_volume_codec_test state_volume_codec_test.cpp) @@ -290,27 +288,25 @@ if(NOT WIN32) ) endif() -if(CVC_STATE_EXEC) - list(APPEND TEST_TARGETS - state_exec_types_test - state_exec_parser_test - state_exec_builtins_test - state_exec_evaluator_test - state_exec_stackless_evaluator_test - state_exec_codec_test - state_exec_unicode_test - state_exec_async_test - state_exec_scheduler_test - state_exec_intrinsics_test - state_exec_coordinator_test - state_exec_bench_test - state_exec_integration_test - state_exec_advanced_integration_test - state_exec_gaps_test - ) - if(NOT WIN32) - list(APPEND TEST_TARGETS state_exec_multiprocess_test) - endif() +list(APPEND TEST_TARGETS + state_exec_types_test + state_exec_parser_test + state_exec_builtins_test + state_exec_evaluator_test + state_exec_stackless_evaluator_test + state_exec_codec_test + state_exec_unicode_test + state_exec_async_test + state_exec_scheduler_test + state_exec_intrinsics_test + state_exec_coordinator_test + state_exec_bench_test + state_exec_integration_test + state_exec_advanced_integration_test + state_exec_gaps_test +) +if(NOT WIN32) + list(APPEND TEST_TARGETS state_exec_multiprocess_test) endif() if(CVC_STATE_MEMORY_MANAGER) @@ -1105,111 +1101,109 @@ target_link_libraries(state_telemetry_aggregator_test GTest::gtest_main ) -if(CVC_STATE_EXEC) - target_link_libraries(state_exec_parser_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) +target_link_libraries(state_exec_parser_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) - target_link_libraries(state_exec_types_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) +target_link_libraries(state_exec_types_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) - target_link_libraries(state_exec_builtins_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) +target_link_libraries(state_exec_builtins_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) - target_link_libraries(state_exec_evaluator_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) +target_link_libraries(state_exec_evaluator_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) - target_link_libraries(state_exec_stackless_evaluator_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) +target_link_libraries(state_exec_stackless_evaluator_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) - target_link_libraries(state_exec_codec_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) - target_link_libraries(state_exec_unicode_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) +target_link_libraries(state_exec_codec_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) +target_link_libraries(state_exec_unicode_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) - target_link_libraries(state_exec_async_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) +target_link_libraries(state_exec_async_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) - target_link_libraries(state_exec_scheduler_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) +target_link_libraries(state_exec_scheduler_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) - target_link_libraries(state_exec_intrinsics_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) +target_link_libraries(state_exec_intrinsics_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) - target_link_libraries(state_exec_coordinator_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) +target_link_libraries(state_exec_coordinator_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) - target_link_libraries(state_exec_bench_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) +target_link_libraries(state_exec_bench_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) - target_link_libraries(state_exec_integration_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) +target_link_libraries(state_exec_integration_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) - target_link_libraries(state_exec_advanced_integration_test +target_link_libraries(state_exec_advanced_integration_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) +if(TARGET state_exec_multiprocess_test) + target_link_libraries(state_exec_multiprocess_test PRIVATE cvc GTest::gtest GTest::gtest_main ) - if(TARGET state_exec_multiprocess_test) - target_link_libraries(state_exec_multiprocess_test - PRIVATE - cvc - GTest::gtest - GTest::gtest_main - ) - endif() endif() if(CVC_STATE_MEMORY_MANAGER) @@ -1421,24 +1415,22 @@ target_compile_features(state_transparent_link_index_test PRIVATE cxx_std_17) target_compile_features(state_sync_adapter_link_forwarding_test PRIVATE cxx_std_17) target_compile_features(state_cross_cluster_link_test PRIVATE cxx_std_17) target_compile_features(state_link_bench_test PRIVATE cxx_std_17) -if(CVC_STATE_EXEC) - target_compile_features(state_exec_parser_test PRIVATE cxx_std_20) - target_compile_features(state_exec_types_test PRIVATE cxx_std_20) - target_compile_features(state_exec_builtins_test PRIVATE cxx_std_20) - target_compile_features(state_exec_evaluator_test PRIVATE cxx_std_20) - target_compile_features(state_exec_stackless_evaluator_test PRIVATE cxx_std_20) - target_compile_features(state_exec_codec_test PRIVATE cxx_std_20) - target_compile_features(state_exec_unicode_test PRIVATE cxx_std_20) - target_compile_features(state_exec_async_test PRIVATE cxx_std_20) - target_compile_features(state_exec_scheduler_test PRIVATE cxx_std_20) - target_compile_features(state_exec_intrinsics_test PRIVATE cxx_std_20) - target_compile_features(state_exec_coordinator_test PRIVATE cxx_std_20) - target_compile_features(state_exec_bench_test PRIVATE cxx_std_20) - target_compile_features(state_exec_integration_test PRIVATE cxx_std_20) - target_compile_features(state_exec_advanced_integration_test PRIVATE cxx_std_20) - if(TARGET state_exec_multiprocess_test) - target_compile_features(state_exec_multiprocess_test PRIVATE cxx_std_20) - endif() +target_compile_features(state_exec_parser_test PRIVATE cxx_std_20) +target_compile_features(state_exec_types_test PRIVATE cxx_std_20) +target_compile_features(state_exec_builtins_test PRIVATE cxx_std_20) +target_compile_features(state_exec_evaluator_test PRIVATE cxx_std_20) +target_compile_features(state_exec_stackless_evaluator_test PRIVATE cxx_std_20) +target_compile_features(state_exec_codec_test PRIVATE cxx_std_20) +target_compile_features(state_exec_unicode_test PRIVATE cxx_std_20) +target_compile_features(state_exec_async_test PRIVATE cxx_std_20) +target_compile_features(state_exec_scheduler_test PRIVATE cxx_std_20) +target_compile_features(state_exec_intrinsics_test PRIVATE cxx_std_20) +target_compile_features(state_exec_coordinator_test PRIVATE cxx_std_20) +target_compile_features(state_exec_bench_test PRIVATE cxx_std_20) +target_compile_features(state_exec_integration_test PRIVATE cxx_std_20) +target_compile_features(state_exec_advanced_integration_test PRIVATE cxx_std_20) +if(TARGET state_exec_multiprocess_test) + target_compile_features(state_exec_multiprocess_test PRIVATE cxx_std_20) endif() if(CVC_STATE_MEMORY_MANAGER) target_compile_features(state_memory_manager_test PRIVATE cxx_std_17) @@ -1714,29 +1706,27 @@ cvc_discover_tests(state_transparent_link_index_test) cvc_discover_tests(state_sync_adapter_link_forwarding_test) cvc_discover_tests(state_cross_cluster_link_test) cvc_discover_tests(state_link_bench_test) -if(CVC_STATE_EXEC) - cvc_discover_tests(state_exec_parser_test) - cvc_discover_tests(state_exec_types_test) - cvc_discover_tests(state_exec_builtins_test) - cvc_discover_tests(state_exec_evaluator_test) - cvc_discover_tests(state_exec_stackless_evaluator_test) - cvc_discover_tests(state_exec_codec_test) - cvc_discover_tests(state_exec_unicode_test) - cvc_discover_tests(state_exec_async_test) - cvc_discover_tests(state_exec_scheduler_test) - cvc_discover_tests(state_exec_intrinsics_test) - cvc_discover_tests(state_exec_coordinator_test) - cvc_discover_tests(state_exec_bench_test) - cvc_discover_tests(state_exec_integration_test) - cvc_discover_tests(state_exec_advanced_integration_test) - if(TARGET state_exec_multiprocess_test) - # Forks real OS processes and replicates state over Unix-domain-socket IPC - # with internal pump deadlines. Under `ctest --parallel` on a loaded CI - # runner the forked children get starved and miss those windows, so - # StateTreeReplication intermittently fails all `until-pass` retries. - # RUN_SERIAL keeps this suite off the shared parallel scheduler. - cvc_discover_tests(state_exec_multiprocess_test PROPERTIES RUN_SERIAL TRUE) - endif() +cvc_discover_tests(state_exec_parser_test) +cvc_discover_tests(state_exec_types_test) +cvc_discover_tests(state_exec_builtins_test) +cvc_discover_tests(state_exec_evaluator_test) +cvc_discover_tests(state_exec_stackless_evaluator_test) +cvc_discover_tests(state_exec_codec_test) +cvc_discover_tests(state_exec_unicode_test) +cvc_discover_tests(state_exec_async_test) +cvc_discover_tests(state_exec_scheduler_test) +cvc_discover_tests(state_exec_intrinsics_test) +cvc_discover_tests(state_exec_coordinator_test) +cvc_discover_tests(state_exec_bench_test) +cvc_discover_tests(state_exec_integration_test) +cvc_discover_tests(state_exec_advanced_integration_test) +if(TARGET state_exec_multiprocess_test) + # Forks real OS processes and replicates state over Unix-domain-socket IPC + # with internal pump deadlines. Under `ctest --parallel` on a loaded CI + # runner the forked children get starved and miss those windows, so + # StateTreeReplication intermittently fails all `until-pass` retries. + # RUN_SERIAL keeps this suite off the shared parallel scheduler. + cvc_discover_tests(state_exec_multiprocess_test PROPERTIES RUN_SERIAL TRUE) endif() if(CVC_STATE_MEMORY_MANAGER) cvc_discover_tests(state_memory_manager_test) diff --git a/src/cvc/tests/ariadne_loader_test.cpp b/src/cvc/tests/ariadne_loader_test.cpp index 096e16f7..f138e1cc 100644 --- a/src/cvc/tests/ariadne_loader_test.cpp +++ b/src/cvc/tests/ariadne_loader_test.cpp @@ -3193,8 +3193,6 @@ TEST(AriadneChannels, MountGrantLowersToLinkHole) { TEST(AriadneChannelLint, StrictUndeclaredChannelFailsLoad) { SKIP_WITHOUT_YAML(); - if (!have_state_exec()) - GTEST_SKIP(); LoadResult r = load_string(R"( channels: - nav.done @@ -3210,8 +3208,6 @@ TEST(AriadneChannelLint, StrictUndeclaredChannelFailsLoad) { TEST(AriadneChannelLint, DeclaredChannelPasses) { SKIP_WITHOUT_YAML(); - if (!have_state_exec()) - GTEST_SKIP(); LoadResult r = load_string(R"( channels: - nav.done @@ -3226,8 +3222,6 @@ TEST(AriadneChannelLint, DeclaredChannelPasses) { TEST(AriadneChannelLint, WarnModeWarnsNotFails) { SKIP_WITHOUT_YAML(); - if (!have_state_exec()) - GTEST_SKIP(); LoadResult r = load_string(R"( lint: channels: warn @@ -3248,8 +3242,6 @@ TEST(AriadneChannelLint, WarnModeWarnsNotFails) { TEST(AriadneChannelLint, OffModeSkipsCheck) { SKIP_WITHOUT_YAML(); - if (!have_state_exec()) - GTEST_SKIP(); LoadResult r = load_string(R"( lint: channels: off @@ -3266,8 +3258,6 @@ TEST(AriadneChannelLint, OffModeSkipsCheck) { TEST(AriadneChannelLint, GlobalRefNeedsDeclaredGlobal) { SKIP_WITHOUT_YAML(); - if (!have_state_exec()) - GTEST_SKIP(); LoadResult ok = load_string(R"( channels: - channel: app.quit @@ -3295,8 +3285,6 @@ TEST(AriadneChannelLint, GlobalRefNeedsDeclaredGlobal) { TEST(AriadneChannelLint, HashChannelExempt) { SKIP_WITHOUT_YAML(); - if (!have_state_exec()) - GTEST_SKIP(); LoadResult r = load_string(R"( channels: - nav.done @@ -3311,8 +3299,6 @@ TEST(AriadneChannelLint, HashChannelExempt) { TEST(AriadneChannelLint, NoChannelsBlockNoEnforcement) { SKIP_WITHOUT_YAML(); - if (!have_state_exec()) - GTEST_SKIP(); LoadResult r = load_string(R"( windows: - window: W @@ -3325,8 +3311,6 @@ TEST(AriadneChannelLint, NoChannelsBlockNoEnforcement) { TEST(AriadneChannelLint, InitScriptLinted) { SKIP_WITHOUT_YAML(); - if (!have_state_exec()) - GTEST_SKIP(); LoadResult r = load_string("channels:\n - a\ninit: '(msg-send \"b\" \"x\")'\nwindows: []\n"); EXPECT_FALSE(r.ok); // the init: script is linted too; "b" is undeclared -> strict fail EXPECT_NE(r.error.find("'b'"), std::string::npos); diff --git a/src/cvc/tests/ariadne_runtime_test.cpp b/src/cvc/tests/ariadne_runtime_test.cpp index 572029ac..1fec596a 100644 --- a/src/cvc/tests/ariadne_runtime_test.cpp +++ b/src/cvc/tests/ariadne_runtime_test.cpp @@ -281,8 +281,6 @@ TEST(AriadneRuntime, ActionsDrainOffTheWalk) { // a flag toggle / reset is pure .ari. The program is chrooted to the widget's prefix, so // (state-set "paused") writes .paused, the same key a widget `bind: paused` resolves to. TEST(AriadneAction, ProgramOnTogglesStateThroughStateExec) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec (CVC_STATE_EXEC=OFF)"; cvc::app app; Runtime rt(app, "ui.demo"); MockBackend mb; @@ -304,8 +302,6 @@ TEST(AriadneAction, ProgramOnTogglesStateThroughStateExec) { // A program `on:` may sequence several state writes in one action (a reset button). TEST(AriadneAction, ProgramOnRunsMultiStatementReset) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -324,8 +320,6 @@ TEST(AriadneAction, ProgramOnRunsMultiStatementReset) { // via the thread-safe exec_scheduler().post_message ingress. This is the marquee async story // (a compute-pool worker waking a parked .ari action) exercised through the real Runtime. TEST(AriadneAction, ProgramActionParksOnMsgRecvAndResumesWhenWorkerDelivers) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec (CVC_STATE_EXEC=OFF)"; cvc::app app; Runtime rt(app, ""); // app-root prefix so the channel/state paths are used as-is MockBackend mb; @@ -360,8 +354,6 @@ TEST(AriadneAction, ProgramActionParksOnMsgRecvAndResumesWhenWorkerDelivers) { // the value the worker delivered. deliver_to_receivers patches the parent frame's pending result // slot (where pop_frame pushed msg-recv's nil placeholder), so the resumed state-set applies it. TEST(AriadneAction, ProgramActionCapturesDeliveredValueFromMsgRecv) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec (CVC_STATE_EXEC=OFF)"; cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -392,8 +384,6 @@ TEST(AriadneAction, ProgramActionCapturesDeliveredValueFromMsgRecv) { // background-thread → parallel_for → post_message); here we hand-roll a joinable std::thread so the // test can join() deterministically before asserting (compute_async is fire-and-forget by design). TEST(AriadneAction, IntrinsicRunsNavStepOnComputePoolAndWakesMsgRecv) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec (CVC_STATE_EXEC=OFF)"; namespace se = cvc::state_exec; cvc::app app; app.computePool(); // warm the lazy per-app singletons on THIS thread before a worker touches @@ -447,8 +437,6 @@ TEST(AriadneAction, IntrinsicRunsNavStepOnComputePoolAndWakesMsgRecv) { // per drain (parking between frames), NOT a fresh action each frame. Proven by re-firing: reset a // flag the body sets, and the next drain sets it again from the SAME resident. TEST(AriadneResident, TickProgramRunsOncePerDrain) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec (CVC_STATE_EXEC=OFF)"; cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -467,8 +455,6 @@ TEST(AriadneResident, TickProgramRunsOncePerDrain) { // set_tick_program("") clears the resident: after clearing, a drain no longer re-fires the body. TEST(AriadneResident, ClearingTickProgramStopsIt) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -487,8 +473,6 @@ TEST(AriadneResident, ClearingTickProgramStopsIt) { // reading the delivered event dict with (get-attr event ...). post_input BEFORE drain -> delivered // this frame (feed-before-drain contract). Keyboard events feed the key resident. TEST(AriadneInput, KeyProgramReceivesPostedEvent) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec (CVC_STATE_EXEC=OFF)"; cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -507,8 +491,6 @@ TEST(AriadneInput, KeyProgramReceivesPostedEvent) { // A burst of events in one frame all deliver (FIFO — no coalescing on the input channel): three // keys posted before one drain, and the resident drains all three (last wins in state). TEST(AriadneInput, KeyBurstAllDeliveredInOrder) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -526,8 +508,6 @@ TEST(AriadneInput, KeyBurstAllDeliveredInOrder) { // Mouse events feed the pointer resident (a separate channel/handler); the body reads coords. TEST(AriadneInput, PointerProgramReceivesMouseEvent) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -551,8 +531,6 @@ TEST(AriadneInput, PointerProgramReceivesMouseEvent) { // and on wasm). Fired like a Button's on: (queued in render(), run in drain()) — NOT the SDL // document-level stream. This is the natively-working widget input path. TEST(AriadneInput, WidgetOnClickFiresWhenBackendReportsClick) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -672,8 +650,6 @@ TEST(AriadneInput, WidgetOnDragStartEndFireOnEdges) { // the item's pointer coords, read with (get-attr event "..."). Assert on button (int -> a stable // string), like the on_pointer test, to avoid double-format brittleness. TEST(AriadneInput, WidgetPointerProgramReceivesEventScope) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -721,8 +697,6 @@ TEST(AriadneRuntime, ImageWidgetResolvesNameAndFallsBackToText) { // The host-intrinsic seam: a host binds a native fn `(host-bump)` into the program lanes, and a // program on: calls it — so a .ari program can invoke a host capability (e.g. a nav verb) inline. TEST(AriadneAction, HostIntrinsicCallableFromProgram) { - if (!have_state_exec()) - GTEST_SKIP(); namespace se = cvc::state_exec; int calls = 0; register_action_intrinsics( @@ -749,8 +723,6 @@ TEST(AriadneAction, HostIntrinsicCallableFromProgram) { // A broken program action fails SAFE: it never throws out of drain(), and it surfaces a one-time // warning (mirroring the read-lane's fail-safe policy) rather than silently doing nothing. TEST(AriadneAction, ProgramOnBrokenWarnsOnceNoThrow) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -913,8 +885,6 @@ TEST(AriadneRuntime, UnregisteredCustomWidgetDrawsPlaceholder) { // --- the init: block runner (run_init, state_exec) --------------------------- TEST(AriadneInit, RunsScopedToPrefix) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec (CVC_STATE_EXEC=OFF)"; cvc::app app; std::vector errs; // A relative path under the chroot prefix -> writes .agents, the same key a @@ -925,8 +895,6 @@ TEST(AriadneInit, RunsScopedToPrefix) { } TEST(AriadneInit, SyntaxErrorReportedNotThrown) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; std::vector errs; const bool ok = run_init(app, "", "(state-set \"x\" ", &errs); // unbalanced @@ -992,8 +960,6 @@ TEST(AriadneRuntime, CustomWidgetUncommittedEscapeDoesNotWrite) { } TEST(AriadneInit, RunawayScriptIsBoundedNotHang) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; std::vector errs; // A non-terminating init must be bounded (step/time cap) and reported — never hang. @@ -1035,8 +1001,6 @@ TEST(AriadneReactive, EmptyPredicateAlwaysShows) { } TEST(AriadneReactive, PredicateShowsThenHidesAsStateChanges) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec (CVC_STATE_EXEC=OFF)"; cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1080,8 +1044,6 @@ TEST(AriadneMountScope, BindsResolveAtSubPrefix) { } TEST(AriadneMountScope, ReactiveReadsResolveAtSubPrefix) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec (CVC_STATE_EXEC=OFF)"; cvc::app app; Runtime rt(app, "ui.demo"); MockBackend mb; @@ -1106,8 +1068,6 @@ TEST(AriadneMountScope, ReactiveReadsResolveAtSubPrefix) { } TEST(AriadneMountScope, RepeatedMountGetsPerInstanceSubPrefix) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec (CVC_STATE_EXEC=OFF)"; cvc::app app; Runtime rt(app, "ui.demo"); MockBackend mb; @@ -1219,8 +1179,6 @@ TEST(AriadneMountScope, ReconcileTearsDownStaleHoles) { } TEST(AriadneMountScope, RepeatedMountLinkTargetsAreIndexed) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec (CVC_STATE_EXEC=OFF)"; cvc::app app; Runtime rt(app, "ui.demo"); MockBackend mb; @@ -1242,8 +1200,8 @@ TEST(AriadneMountScope, RepeatedMountLinkTargetsAreIndexed) { } TEST(AriadneMountScope, MountInitSeedsAtSubPrefix) { - if (!have_state_exec() || !have_yaml()) - GTEST_SKIP() << "needs state_exec + yaml"; + if (!have_yaml()) + GTEST_SKIP() << "needs yaml"; namespace fs = std::filesystem; const fs::path dir = fs::temp_directory_path() / "ariadne_mount_init"; fs::create_directories(dir); @@ -1266,8 +1224,8 @@ TEST(AriadneMountScope, MountInitSeedsAtSubPrefix) { } TEST(AriadneMountScope, MountInitRunsOnceNotPerFrame) { - if (!have_state_exec() || !have_yaml()) - GTEST_SKIP() << "needs state_exec + yaml"; + if (!have_yaml()) + GTEST_SKIP() << "needs yaml"; namespace fs = std::filesystem; const fs::path dir = fs::temp_directory_path() / "ariadne_mount_init_once"; fs::create_directories(dir); @@ -1318,8 +1276,6 @@ TEST(AriadneMountScope, EndToEndLoadCommitsAtSubPrefix) { } TEST(AriadneReactive, FalsePredicateHidesTheWholeSubtree) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1334,8 +1290,6 @@ TEST(AriadneReactive, FalsePredicateHidesTheWholeSubtree) { } TEST(AriadneReactive, BrokenPredicateHidesFailSafeAndWarnsOnce) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1354,8 +1308,6 @@ TEST(AriadneReactive, BrokenPredicateHidesFailSafeAndWarnsOnce) { } TEST(AriadneReactive, WriteIntrinsicIsUnavailableInAPredicate) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1371,8 +1323,6 @@ TEST(AriadneReactive, WriteIntrinsicIsUnavailableInAPredicate) { } TEST(AriadneReactive, PredicateReadsArePrefixScoped) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, "ui.demo"); MockBackend mb; @@ -1389,8 +1339,6 @@ TEST(AriadneReactive, PredicateReadsArePrefixScoped) { } TEST(AriadneReactive, RunawayPredicateIsCappedNotHung) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1410,8 +1358,6 @@ TEST(AriadneReactive, RunawayPredicateIsCappedNotHung) { // scheduler is never pumped; a park there would silent-nil). render() must return, hidden + // reported. TEST(AriadneReactive, ParkVerbInPredicateIsDeniedNotHung) { - if (!have_state_exec()) - GTEST_SKIP(); // Both park verbs (msg-recv AND await) must be denied in the reactive read lane — neither is in // the read-lane allowlist, so a predicate using one is unbound → fail-safe hidden, render // returns. @@ -1433,8 +1379,6 @@ TEST(AriadneReactive, ParkVerbInPredicateIsDeniedNotHung) { // per-activation budget wired in ensure_resident — drain() returns, and the scheduler recovers so a // subsequently-installed healthy resident still fires. TEST(AriadneResident, RunawayTickResidentIsBoundedAndSchedulerRecovers) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1452,8 +1396,6 @@ TEST(AriadneResident, RunawayTickResidentIsBoundedAndSchedulerRecovers) { } TEST(AriadneReactive, StringValueIsTruthyAndUnsetKeyIsCleanlyFalsy) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1471,8 +1413,6 @@ TEST(AriadneReactive, StringValueIsTruthyAndUnsetKeyIsCleanlyFalsy) { } TEST(AriadneReactive, DistinctBrokenPredicatesWarnIndependently) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1490,8 +1430,6 @@ TEST(AriadneReactive, DistinctBrokenPredicatesWarnIndependently) { } TEST(AriadneReactive, HiddenMenuIsSkippedEntirely) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1505,8 +1443,6 @@ TEST(AriadneReactive, HiddenMenuIsSkippedEntirely) { } TEST(AriadneReactive, HiddenGridChildConsumesNoCell) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1527,8 +1463,6 @@ TEST(AriadneReactive, HiddenGridChildConsumesNoCell) { } TEST(AriadneReactive, ReadLaneStillExcludesMaterializersAndSideEffects) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1554,8 +1488,6 @@ TEST(AriadneReactive, ReadLaneStillExcludesMaterializersAndSideEffects) { } TEST(AriadneReactive, CompoundsAndAllowedFormsNowWork) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1577,8 +1509,6 @@ TEST(AriadneReactive, CompoundsAndAllowedFormsNowWork) { } TEST(AriadneReactive, DeniedSpecialFormsAreRejectedNotRun) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1601,8 +1531,6 @@ TEST(AriadneReactive, DeniedSpecialFormsAreRejectedNotRun) { } TEST(AriadneReactive, StateDataDagIsCopiedBoundedNotHung) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; // The full-env init lane plants a physically-tiny SHARED DAG (~30 nodes, 2^30 logical) in // typed data. A read-lane predicate then reads it via state-data-get -> deep_copy. deep_copy @@ -1624,8 +1552,6 @@ TEST(AriadneReactive, StateDataDagIsCopiedBoundedNotHung) { } TEST(AriadneReactive, EnabledWhenGreysOutAndReacts) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1647,8 +1573,6 @@ TEST(AriadneReactive, EnabledWhenGreysOutAndReacts) { } TEST(AriadneReactive, DisabledWhenDisablesWhenTrue) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1663,8 +1587,6 @@ TEST(AriadneReactive, DisabledWhenDisablesWhenTrue) { } TEST(AriadneReactive, EnabledWhenBrokenPredicateDisablesFailSafe) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1690,8 +1612,6 @@ TEST(AriadneReactive, NoEnableFieldsMeansNoDisabledScope) { } TEST(AriadneReactive, ComputedTextValueFromExpression) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1714,8 +1634,6 @@ TEST(AriadneReactive, ComputedTextValueFromExpression) { } TEST(AriadneReactive, ComputedTextBrokenExprIsEmptyAndWarns) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1781,8 +1699,6 @@ TEST(AriadneRuntime, ColorWidgetFallsBackToTextWhenBackendCantDraw) { } TEST(AriadneReactive, ComputedComboOptionsFromExpression) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1796,8 +1712,6 @@ TEST(AriadneReactive, ComputedComboOptionsFromExpression) { } TEST(AriadneReactive, ComputedComboOptionsBrokenExprSkips) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1811,8 +1725,6 @@ TEST(AriadneReactive, ComputedComboOptionsBrokenExprSkips) { } TEST(AriadneReactive, StaticAndComputedTooltips) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1840,8 +1752,6 @@ TEST(AriadneReactive, NoTooltipMeansNoSetTooltip) { } TEST(AriadneReactive, RepeatEmitsNInstancesWithIndexSubstituted) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1863,8 +1773,6 @@ TEST(AriadneReactive, RepeatEmitsNInstancesWithIndexSubstituted) { } TEST(AriadneReactive, RepeatSubstitutesIndexInBindsForDistinctState) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1880,8 +1788,6 @@ TEST(AriadneReactive, RepeatSubstitutesIndexInBindsForDistinctState) { } TEST(AriadneReactive, RepeatBrokenCountEmitsNothing) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1895,8 +1801,6 @@ TEST(AriadneReactive, RepeatBrokenCountEmitsNothing) { } TEST(AriadneReactive, LiteralTooltipStartingWithParenShownVerbatim) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1910,8 +1814,6 @@ TEST(AriadneReactive, LiteralTooltipStartingWithParenShownVerbatim) { } TEST(AriadneReactive, DisabledWidgetStillEmitsItsTooltip) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1935,8 +1837,6 @@ TEST(AriadneReactive, DisabledWidgetStillEmitsItsTooltip) { } TEST(AriadneReactive, RepeatCountOutOfRangeDoubleIsZero) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -1950,8 +1850,6 @@ TEST(AriadneReactive, RepeatCountOutOfRangeDoubleIsZero) { } TEST(AriadneReactive, PredicateEvalsAreIsolatedPerWidget) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -2158,8 +2056,6 @@ static bool msg_delivered(cvc::app &app, Runtime &rt, MockBackend &mb, const std } TEST(AriadneChannelPolicy, StrictRefusesUndeclaredChannel) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -2170,8 +2066,6 @@ TEST(AriadneChannelPolicy, StrictRefusesUndeclaredChannel) { } TEST(AriadneChannelPolicy, AllowsDeclaredChannel) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -2181,8 +2075,6 @@ TEST(AriadneChannelPolicy, AllowsDeclaredChannel) { } TEST(AriadneChannelPolicy, PermissiveWhenNotStrict) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -2192,8 +2084,6 @@ TEST(AriadneChannelPolicy, PermissiveWhenNotStrict) { } TEST(AriadneChannelPolicy, AllowsDeclaredGlobal) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -2204,8 +2094,6 @@ TEST(AriadneChannelPolicy, AllowsDeclaredGlobal) { } TEST(AriadneChannelPolicy, RefusesUndeclaredGlobal) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -2216,8 +2104,6 @@ TEST(AriadneChannelPolicy, RefusesUndeclaredGlobal) { } TEST(AriadneChannelPolicy, ExemptsHashChannel) { - if (!have_state_exec()) - GTEST_SKIP(); cvc::app app; Runtime rt(app, ""); MockBackend mb; @@ -2320,8 +2206,6 @@ std::string node_data_string(cvc::app &app, const char *path) { } // namespace TEST(AriadneNetIntrinsics, HttpGetAsyncAwaitsResponseDict) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec"; if (!cvc::net::have_http_backend()) GTEST_SKIP() << "libcvc built without an HTTP backend"; cvc::app app; @@ -2357,8 +2241,6 @@ TEST(AriadneNetIntrinsics, HttpGetAsyncAwaitsResponseDict) { } TEST(AriadneNetIntrinsics, HttpGetAsyncErrorPathResumesWithErrorDict) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec"; if (!cvc::net::have_http_backend()) GTEST_SKIP() << "libcvc built without an HTTP backend"; cvc::app app; @@ -2389,8 +2271,6 @@ TEST(AriadneNetIntrinsics, HttpGetAsyncErrorPathResumesWithErrorDict) { } TEST(AriadneNetIntrinsics, HttpGetAsyncDoesNotBlockTheScheduler) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec"; if (!cvc::net::have_http_backend()) GTEST_SKIP() << "libcvc built without an HTTP backend"; cvc::app app; @@ -2422,8 +2302,6 @@ TEST(AriadneNetIntrinsics, HttpGetAsyncDoesNotBlockTheScheduler) { // PR-A: the TRANSPARENT verb — (http-get url) self-parks and yields the dict directly, no msg-recv. TEST(AriadneNetIntrinsics, HttpGetTransparentReturnsDictNoMsgRecv) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec"; if (!cvc::net::have_http_backend()) GTEST_SKIP() << "libcvc built without an HTTP backend"; cvc::app app; @@ -2454,8 +2332,6 @@ TEST(AriadneNetIntrinsics, HttpGetTransparentReturnsDictNoMsgRecv) { // PR-A: PROPER await — (await (http-get-async url)) resolves the future returned by the async verb. TEST(AriadneNetIntrinsics, AwaitResolvesHttpGetAsyncFuture) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec"; if (!cvc::net::have_http_backend()) GTEST_SKIP() << "libcvc built without an HTTP backend"; cvc::app app; @@ -2486,8 +2362,6 @@ TEST(AriadneNetIntrinsics, AwaitResolvesHttpGetAsyncFuture) { // self-parks, returning { ok body(bytes) url error }. No HTTP backend needed (a custom scheme // here). TEST(AriadneNetIntrinsics, FetchTransparentResolvesAnyScheme) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec"; cvc::app app; struct Teardown { ~Teardown() { @@ -2522,8 +2396,6 @@ TEST(AriadneNetIntrinsics, FetchTransparentResolvesAnyScheme) { // PR-B: (await (fetch-async uri)) resolves the generic resolver's future. TEST(AriadneNetIntrinsics, FetchAsyncFutureAwaited) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec"; cvc::app app; struct Teardown { ~Teardown() { @@ -2565,8 +2437,6 @@ bool headers_have_prefix(const std::vector &h, const std::string &p // "form" (dict …))) — a form body is percent-encoded with a default Content-Type, and a bearer // token rides in as a header. This is the authenticated form-POST the user asked for. TEST(AriadneNetIntrinsics, HttpRequestPostFormBodyAndBearer) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec"; if (!cvc::net::have_http_backend()) GTEST_SKIP() << "libcvc built without an HTTP backend"; cvc::app app; @@ -2608,8 +2478,6 @@ TEST(AriadneNetIntrinsics, HttpRequestPostFormBodyAndBearer) { // (http-get URL (dict "query" (dict …))) percent-encodes the params into the URL's query string — // the caller never hand-encodes. A space becomes %20 and '&' is escaped so it can't inject a pair. TEST(AriadneNetIntrinsics, HttpGetQueryParamsEncodedIntoUrl) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec"; if (!cvc::net::have_http_backend()) GTEST_SKIP() << "libcvc built without an HTTP backend"; cvc::app app; @@ -2642,8 +2510,6 @@ TEST(AriadneNetIntrinsics, HttpGetQueryParamsEncodedIntoUrl) { // A raw string "body" option is sent verbatim and does NOT get a defaulted Content-Type (only the // "form" helper adds one) — the caller controls the content type. TEST(AriadneNetIntrinsics, HttpRequestRawBodyNoDefaultContentType) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec"; if (!cvc::net::have_http_backend()) GTEST_SKIP() << "libcvc built without an HTTP backend"; cvc::app app; @@ -2677,8 +2543,6 @@ TEST(AriadneNetIntrinsics, HttpRequestRawBodyNoDefaultContentType) { // prior (http-get) yielded, carried via the "body" option) rides through byte-exact — so a fetched // blob can be re-uploaded with a PUT without a lossy text round-trip. TEST(AriadneNetIntrinsics, HttpRequestAsyncPutWithBytesBodyAwaited) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec"; if (!cvc::net::have_http_backend()) GTEST_SKIP() << "libcvc built without an HTTP backend"; cvc::app app; @@ -2718,8 +2582,6 @@ TEST(AriadneNetIntrinsics, HttpRequestAsyncPutWithBytesBodyAwaited) { // a transparent (pool-double n) and a future (pool-double-async n) via the SAME action-intrinsics // seam register_net_intrinsics uses, so both land in the action lane only (never the render lane). TEST(AriadnePoolTask, OffloadedKernelResumesTransparentAndFuture) { - if (!have_state_exec()) - GTEST_SKIP() << "libcvc built without state_exec"; namespace se = cvc::state_exec; cvc::app app; NetIntrinsicsGuard guard; // clears the action intrinsics on teardown diff --git a/src/cvcGL/ariadne/AriRuntime.cpp b/src/cvcGL/ariadne/AriRuntime.cpp index baf1c9bd..3b1e2bde 100644 --- a/src/cvcGL/ariadne/AriRuntime.cpp +++ b/src/cvcGL/ariadne/AriRuntime.cpp @@ -140,7 +140,6 @@ void AriRuntime::post_pointer(int kind, double x, double y, double dx, double dy std::vector AriRuntime::take_warnings() { return app_rt_.take_warnings(); } bool AriRuntime::reload_if_changed() { return app_rt_.reload_if_changed(); } -bool AriRuntime::have_state_exec() { return ari::AppRuntime::have_state_exec(); } bool AriRuntime::have_yaml() { return ari::AppRuntime::have_yaml(); } } // namespace ariadne diff --git a/src/cvcGL/examples/nav_compute.cpp b/src/cvcGL/examples/nav_compute.cpp index 8c5d6c8c..c7295935 100644 --- a/src/cvcGL/examples/nav_compute.cpp +++ b/src/cvcGL/examples/nav_compute.cpp @@ -96,31 +96,28 @@ int main(int argc, char **argv) { // and post the result when it joins. Runs INLINE on the host thread inside Runtime::drain(), so // it MUST submit-and-return, never block — app.compute_async does exactly that (a background pool // worker owns the blocking parallel_for; the caller returns immediately). on_done runs on the - // worker and touches only the one thread-safe seam, exec_scheduler().post_message. Guarded so a - // CVC_STATE_EXEC=OFF build still links (the program lanes just don't run there). - if (ari::have_state_exec()) { - ari::register_action_intrinsics([&app](std::shared_ptr env, - se::intrinsics_context &ictx) { - // §12 channel scoping: the .ari's (msg-recv "nav.done") resolves against this document's - // chroot, so the host must post to the SAME scoped key. Resolve it on THIS (scheduler) - // thread and capture the string — the compute worker must never walk the state tree. - const std::string done = se::resolve_channel_key(ictx.root_path, "nav.done"); - se::builtins::register_fn(env, "nav-step-async", [&app, done](std::span) { - auto arrived = std::make_shared>(0); - const int n = 4096; - app.compute_async( - n, - [arrived](int i) { // stand-in nav kernel: count the "arrived" agents - if ((i % 3) == 0) - arrived->fetch_add(1, std::memory_order_relaxed); - }, - [&app, arrived, done] { - app.exec_scheduler().post_message(done, se::value_t(std::to_string(arrived->load()))); - }); - return se::value_t{}; // nil; the .ari action parks on (msg-recv "nav.done") - }); + // worker and touches only the one thread-safe seam, exec_scheduler().post_message. + ari::register_action_intrinsics([&app](std::shared_ptr env, + se::intrinsics_context &ictx) { + // §12 channel scoping: the .ari's (msg-recv "nav.done") resolves against this document's + // chroot, so the host must post to the SAME scoped key. Resolve it on THIS (scheduler) + // thread and capture the string — the compute worker must never walk the state tree. + const std::string done = se::resolve_channel_key(ictx.root_path, "nav.done"); + se::builtins::register_fn(env, "nav-step-async", [&app, done](std::span) { + auto arrived = std::make_shared>(0); + const int n = 4096; + app.compute_async( + n, + [arrived](int i) { // stand-in nav kernel: count the "arrived" agents + if ((i % 3) == 0) + arrived->fetch_add(1, std::memory_order_relaxed); + }, + [&app, arrived, done] { + app.exec_scheduler().post_message(done, se::value_t(std::to_string(arrived->load()))); + }); + return se::value_t{}; // nil; the .ari action parks on (msg-recv "nav.done") }); - } + }); ari::LoadResult lr = ari::load_file(docPath.c_str()); if (!lr.ok) { diff --git a/src/cvcGL/examples/wasm/build-wasm-demo.sh b/src/cvcGL/examples/wasm/build-wasm-demo.sh index bd67b3c2..a11b1baa 100755 --- a/src/cvcGL/examples/wasm/build-wasm-demo.sh +++ b/src/cvcGL/examples/wasm/build-wasm-demo.sh @@ -92,7 +92,6 @@ emcmake cmake -G Ninja -S "${REPO_ROOT}" -B "${BUILD_DIR}" \ ${CVC_WASM_NAV_WEIGHTS:+-DCVC_WASM_NAV_WEIGHTS="${CVC_WASM_NAV_WEIGHTS}"} \ -DCVC_ENABLE_MESHER=OFF \ -DCVC_ENABLE_SDF=ON \ - -DCVC_STATE_EXEC=OFF \ -DCVC_BUILD_CVCGL=ON \ -DCVC_BUILD_EXAMPLES=ON \ -DCVC_WASM_PTHREADS=${PTHREAD}