Phase 7b: page render plans — per-page boundary optimizer

Add page-render-plan to deps.sx: given page source + env + IO names,
computes a dict mapping each needed component to "server" or "client",
with server/client lists and IO dep collection. 5 new spec tests.

Integration:
- PageDef.render_plan field caches the plan at registration
- compute_page_render_plans() called from auto_mount_pages()
- Client page registry includes :render-plan per page
- Affinity demo page shows per-page render plans

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 00:02:53 +00:00
parent a70ff2b153
commit 2da80c69ed
14 changed files with 214 additions and 5 deletions

View File

@@ -840,6 +840,25 @@ async def execute_page_streaming_oob(
# Blueprint mounting
# ---------------------------------------------------------------------------
def compute_page_render_plans(service_name: str) -> None:
"""Pre-compute and cache render plans for all pages in a service.
Must be called after components are loaded (compute_all_deps/io_refs done)
and pages are registered. Stores plans on PageDef.render_plan.
"""
from .parser import serialize
from .deps import page_render_plan, get_all_io_names
from .jinja_bridge import _COMPONENT_ENV
io_names = get_all_io_names()
pages = get_all_pages(service_name)
for page_def in pages.values():
if page_def.content_expr is not None:
content_src = serialize(page_def.content_expr)
page_def.render_plan = page_render_plan(content_src, _COMPONENT_ENV, io_names)
logger.info("Computed render plans for %d pages in %s", len(pages), service_name)
def auto_mount_pages(app: Any, service_name: str) -> None:
"""Auto-mount all registered defpages for a service directly on the app.
@@ -849,6 +868,10 @@ def auto_mount_pages(app: Any, service_name: str) -> None:
Also mounts the /sx/data/ endpoint for client-side data fetching.
"""
pages = get_all_pages(service_name)
# Pre-compute render plans (which components render where)
compute_page_render_plans(service_name)
for page_def in pages.values():
_mount_one_page(app, service_name, page_def)
logger.info("Auto-mounted %d defpages for %s", len(pages), service_name)