Level 2-3: lake morphing — server content flows through reactive islands

Lake tag (lake :id "name" children...) creates server-morphable slots
within islands. During morph, the engine enters hydrated islands and
updates data-sx-lake elements by ID while preserving surrounding
reactive DOM (signals, effects, event listeners).

Specced in .sx, bootstrapped to JS and Python:
- adapter-dom.sx: render-dom-lake, reactive-attr marks data-sx-reactive-attrs
- adapter-html.sx: render-html-lake SSR output
- adapter-sx.sx: lake serialized in wire format
- engine.sx: morph-island-children (lake-by-ID matching),
  sync-attrs skips reactive attributes
- ~sx-header uses lakes for logo and copyright
- Hegelian essay updated with lake code example

Also includes: lambda nil-padding for missing args, page env ordering fix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 14:29:54 +00:00
parent d5e416e478
commit 9b9fc6b6a5
15 changed files with 351 additions and 63 deletions

View File

@@ -236,10 +236,11 @@ async def execute_page(
if url_params is None:
url_params = {}
# Build environment
env = dict(get_component_env())
# Build environment — closure first (page-local defines), then fresh
# component env on top so hot-reloaded components take priority.
env = dict(page_def.closure)
env.update(get_component_env())
env.update(get_page_helpers(service_name))
env.update(page_def.closure)
# Inject URL params as kebab-case symbols
for key, val in url_params.items():
@@ -416,9 +417,9 @@ async def execute_page_streaming(
if url_params is None:
url_params = {}
env = dict(get_component_env())
env = dict(page_def.closure)
env.update(get_component_env())
env.update(get_page_helpers(service_name))
env.update(page_def.closure)
for key, val in url_params.items():
kebab = key.replace("_", "-")
env[kebab] = val
@@ -662,9 +663,9 @@ async def execute_page_streaming_oob(
if url_params is None:
url_params = {}
env = dict(get_component_env())
env = dict(page_def.closure)
env.update(get_component_env())
env.update(get_page_helpers(service_name))
env.update(page_def.closure)
for key, val in url_params.items():
kebab = key.replace("_", "-")
env[kebab] = val
@@ -1045,9 +1046,9 @@ async def evaluate_page_data(
url_params = {}
# Build environment (same as execute_page)
env = dict(get_component_env())
env = dict(page_def.closure)
env.update(get_component_env())
env.update(get_page_helpers(service_name))
env.update(page_def.closure)
for key, val in url_params.items():
kebab = key.replace("_", "-")