Split signals: core spec (spec/signals.sx) + web extensions (web/signals.sx)

Core reactive primitives (signal, deref, reset!, swap!, computed, effect,
batch, notify-subscribers, dispose-computed, with-island-scope,
register-in-scope) moved to spec/signals.sx — pure SX, zero platform
dependencies. Usable by any host: web, CLI, embedded, server, harness.

Web extensions (marsh scopes, stores, event bridge, resource) remain in
web/signals.sx, which now depends on spec/signals.sx.

Updated all load paths:
- hosts/ocaml/bin/sx_server.ml — loads spec/signals.sx before web/signals.sx
- hosts/ocaml/bin/run_tests.ml — loads both in order
- hosts/ocaml/browser/bundle.sh + sx-platform.js — loads core-signals.sx first
- shared/sx/ocaml_bridge.py — loads spec/signals.sx before web extensions

1116/1116 OCaml tests pass. Browser reactive island preview works.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-26 00:23:35 +00:00
parent b1690a92c4
commit b104663481
7 changed files with 294 additions and 407 deletions

View File

@@ -384,7 +384,14 @@ class OcamlBridge:
# All directories loaded into the Python env
all_dirs = list(set(_watched_dirs) | _dirs_from_cache)
# Isomorphic libraries: signals, rendering, web forms
# Core spec: signals (must load before web/signals.sx extensions)
spec_dir = os.path.join(os.path.dirname(__file__), "../../spec")
if os.path.isdir(spec_dir):
for spec_file in ["signals.sx"]:
path = os.path.normpath(os.path.join(spec_dir, spec_file))
if os.path.isfile(path):
all_files.append(path)
# Isomorphic libraries: signals extensions, rendering, web forms
web_dir = os.path.join(os.path.dirname(__file__), "../../web")
if os.path.isdir(web_dir):
for web_file in ["signals.sx", "adapter-html.sx", "adapter-sx.sx",