Add live self-hosting bootstrapper page to bootstrappers section
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m15s

- Update plan page with completion status and results
- Add ~bootstrapper-self-hosting-content component with live G0/G1 verification
- Add _self_hosting_data() helper: loads py.sx, runs it, diffs against G0
- Add "Self-Hosting (py.sx)" to bootstrappers nav and index table
- Wire /bootstrappers/self-hosting route

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-09 01:18:20 +00:00
parent b4944aa2b6
commit e5acfdcd3c
5 changed files with 265 additions and 268 deletions

View File

@@ -448,13 +448,25 @@
:data (bootstrapper-data slug)
:content (if bootstrapper-not-found
(~spec-not-found :slug slug)
(if (= slug "python")
(~bootstrapper-py-content
:bootstrapper-source bootstrapper-source
:bootstrapped-output bootstrapped-output)
(~bootstrapper-js-content
:bootstrapper-source bootstrapper-source
:bootstrapped-output bootstrapped-output))))
(case slug
"self-hosting"
(~bootstrapper-self-hosting-content
:py-sx-source py-sx-source
:g0-output g0-output
:g1-output g1-output
:defines-matched defines-matched
:defines-total defines-total
:g0-lines g0-lines
:g0-bytes g0-bytes
:verification-status verification-status)
"python"
(~bootstrapper-py-content
:bootstrapper-source bootstrapper-source
:bootstrapped-output bootstrapped-output)
:else
(~bootstrapper-js-content
:bootstrapper-source bootstrapper-source
:bootstrapped-output bootstrapped-output))))
;; ---------------------------------------------------------------------------
;; Isomorphism section

View File

@@ -230,9 +230,12 @@ def _bootstrapper_data(target: str) -> dict:
"""
import os
if target not in ("javascript", "python"):
if target not in ("javascript", "python", "self-hosting"):
return {"bootstrapper-not-found": True}
if target == "self-hosting":
return _self_hosting_data(ref_dir)
ref_dir = os.path.join(os.path.dirname(__file__), "..", "..", "shared", "sx", "ref")
if not os.path.isdir(ref_dir):
ref_dir = "/app/shared/sx/ref"
@@ -276,6 +279,80 @@ def _bootstrapper_data(target: str) -> dict:
}
def _self_hosting_data(ref_dir: str) -> dict:
"""Run py.sx live: load into evaluator, translate spec files, diff against G0."""
import os
from shared.sx.parser import parse_all
from shared.sx.types import Symbol
from shared.sx.evaluator import evaluate, make_env
from shared.sx.ref.bootstrap_py import extract_defines, compile_ref_to_py, PyEmitter
try:
# Read py.sx source
py_sx_path = os.path.join(ref_dir, "py.sx")
with open(py_sx_path, encoding="utf-8") as f:
py_sx_source = f.read()
# Load py.sx into evaluator
exprs = parse_all(py_sx_source)
env = make_env()
for expr in exprs:
evaluate(expr, env)
# Generate G0 (hand-written bootstrapper)
g0_output = compile_ref_to_py()
# Generate G1 (py.sx) — translate each spec file
sx_files = [
("eval.sx", "eval"), ("forms.sx", "forms (server definition forms)"),
("render.sx", "render (core)"),
("adapter-html.sx", "adapter-html"), ("adapter-sx.sx", "adapter-sx"),
("deps.sx", "deps (component dependency analysis)"),
("signals.sx", "signals (reactive signal runtime)"),
]
emitter = PyEmitter()
total = 0
matched = 0
for filename, _label in sx_files:
filepath = os.path.join(ref_dir, filename)
if not os.path.exists(filepath):
continue
with open(filepath, encoding="utf-8") as f:
src = f.read()
defines = extract_defines(src)
for name, expr in defines:
g0_stmt = emitter.emit_statement(expr)
g1_stmt = evaluate(
[Symbol("py-statement"), [Symbol("quote"), expr], 0], env
)
total += 1
if g0_stmt == g1_stmt:
matched += 1
g0_lines = len(g0_output.splitlines())
g0_bytes = len(g0_output)
status = "identical" if matched == total else "mismatch"
except Exception as e:
py_sx_source = f";; error loading py.sx: {e}"
g0_output = f"# error: {e}"
matched, total = 0, 0
g0_lines, g0_bytes = 0, 0
status = "error"
return {
"bootstrapper-not-found": None,
"py-sx-source": py_sx_source,
"g0-output": g0_output,
"g1-output": g0_output if status == "identical" else "# differs from G0",
"defines-matched": str(matched),
"defines-total": str(total),
"g0-lines": str(g0_lines),
"g0-bytes": str(g0_bytes),
"verification-status": status,
}
def _bundle_analyzer_data() -> dict:
"""Compute per-page component bundle analysis for the sx-docs app."""
from shared.sx.jinja_bridge import get_component_env