Nav refactoring: - Split nav-data.sx (32 forms) into 6 files: nav-geography, nav-language, nav-applications, nav-etc, nav-tools, nav-tree - Add Tools top-level nav category with SX Tools and Services pages - New services-tools.sx page documenting the rose-ash-services MCP server JS build fixes (fixes 5 Playwright failures): - Wire web/web-signals.sx into JS build (stores, events, resources) - Add cek-try primitive to JS platform (island hydration error handling) - Merge PRIMITIVES into getRenderEnv (island env was missing primitives) - Rename web/signals.sx → web/web-signals.sx to avoid spec/ collision New MCP tools: - sx_trace: step-through CEK evaluation showing lookups, calls, returns - sx_deps: dependency analysis — free symbols + cross-file resolution - sx_build_manifest: show build contents for JS and OCaml targets - sx_harness_eval extended: multi-file loading + setup expressions Deep path bug fix: - Native OCaml list-replace and navigate bypass CEK callback chain - Fixes sx_replace_node and sx_read_subtree corruption on paths 6+ deep Tests: 1478/1478 JS full suite, 91/91 Playwright Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
96 lines
3.0 KiB
Python
96 lines
3.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Output JS build manifest as structured text for the MCP server."""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
_HERE = os.path.dirname(os.path.abspath(__file__))
|
|
_PROJECT = os.path.abspath(os.path.join(_HERE, "..", ".."))
|
|
if _PROJECT not in sys.path:
|
|
sys.path.insert(0, _PROJECT)
|
|
|
|
from hosts.javascript.platform import (
|
|
ADAPTER_FILES, ADAPTER_DEPS, SPEC_MODULES, SPEC_MODULE_ORDER,
|
|
PRIMITIVES_JS_MODULES, _ALL_JS_MODULES, EXTENSION_NAMES,
|
|
)
|
|
|
|
|
|
def extract_primitives(js_code: str) -> list[str]:
|
|
"""Extract PRIMITIVES["name"] registrations from JS code."""
|
|
return sorted(set(re.findall(r'PRIMITIVES\["([^"]+)"\]', js_code)))
|
|
|
|
|
|
def main():
|
|
# Core spec files (always included)
|
|
core_files = [
|
|
"evaluator.sx (frames + eval + CEK)",
|
|
"freeze.sx (serializable state)",
|
|
"content.sx (content-addressed computation)",
|
|
"render.sx (core renderer)",
|
|
"web-forms.sx (defstyle, deftype, defeffect)",
|
|
]
|
|
|
|
# Adapters
|
|
adapter_lines = []
|
|
for name, (filename, label) in sorted(ADAPTER_FILES.items()):
|
|
deps = ADAPTER_DEPS.get(name, [])
|
|
dep_str = f" (deps: {', '.join(deps)})" if deps else ""
|
|
adapter_lines.append(f" {name:18s} {filename:22s} {label}{dep_str}")
|
|
|
|
# Spec modules
|
|
module_lines = []
|
|
for name in SPEC_MODULE_ORDER:
|
|
if name in SPEC_MODULES:
|
|
filename, label = SPEC_MODULES[name]
|
|
module_lines.append(f" {name:18s} {filename:22s} {label}")
|
|
|
|
# Extensions
|
|
ext_lines = [f" {name}" for name in sorted(EXTENSION_NAMES)]
|
|
|
|
# Primitive modules
|
|
prim_lines = []
|
|
for mod_name in sorted(_ALL_JS_MODULES):
|
|
if mod_name in PRIMITIVES_JS_MODULES:
|
|
prims = extract_primitives(PRIMITIVES_JS_MODULES[mod_name])
|
|
prim_lines.append(f" {mod_name} ({len(prims)}): {', '.join(prims)}")
|
|
|
|
# Current build file
|
|
build_path = os.path.join(_PROJECT, "shared", "static", "scripts", "sx-browser.js")
|
|
build_info = ""
|
|
if os.path.exists(build_path):
|
|
size = os.path.getsize(build_path)
|
|
mtime = os.path.getmtime(build_path)
|
|
from datetime import datetime
|
|
ts = datetime.fromtimestamp(mtime).strftime("%Y-%m-%d %H:%M:%S")
|
|
# Count PRIMITIVES in actual build
|
|
with open(build_path) as f:
|
|
content = f.read()
|
|
actual_prims = extract_primitives(content)
|
|
build_info = f"\nCurrent build: {size:,} bytes, {ts}, {len(actual_prims)} primitives registered"
|
|
|
|
print(f"""JS Build Manifest
|
|
=================
|
|
{build_info}
|
|
|
|
Core files (always included):
|
|
{chr(10).join(' ' + f for f in core_files)}
|
|
|
|
Adapters ({len(ADAPTER_FILES)}):
|
|
{chr(10).join(adapter_lines)}
|
|
|
|
Spec modules ({len(SPEC_MODULES)}, order: {' → '.join(SPEC_MODULE_ORDER)}):
|
|
{chr(10).join(module_lines)}
|
|
|
|
Extensions ({len(EXTENSION_NAMES)}):
|
|
{chr(10).join(ext_lines)}
|
|
|
|
Primitive modules ({len(_ALL_JS_MODULES)}):
|
|
{chr(10).join(prim_lines)}""")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|