Rewrite Phase 1 plan: express in SX terms, not Python

Remove Python-specific references (deps.py, sx_ref.py, bootstrap_py.py,
test_deps.py). Phase 1 is about deps.sx the spec module — hosts are
interchangeable. Show SX code examples, describe platform interface
abstractly, link to live bundle analyzer for proof.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-06 12:26:22 +00:00
parent e36a036873
commit 9ac1d273e2

View File

@@ -630,58 +630,54 @@
(p :class "text-green-800" "Per-page component bundles instead of sending every definition to every page. Smaller payloads, faster boot, better cache hit rates."))
(~doc-subsection :title "The Problem"
(p "client_components_tag() in jinja_bridge.py serializes ALL entries in _COMPONENT_ENV. The sx_page() template sends everything or nothing based on a single global hash. No mechanism determines which components a page actually needs."))
(p "The page boot payload serializes every component definition in the environment. A page that uses 5 components still receives all 50+. No mechanism determines which components a page actually needs — the boundary between \"loaded\" and \"used\" is invisible."))
(~doc-subsection :title "Implementation"
(p "Phase 1 follows the spec-first architecture: the dependency analysis algorithm is defined in "
(p "The dependency analysis algorithm is defined in "
(a :href "/specs/deps" :class "text-violet-700 underline" "deps.sx")
" and bootstrapped to both Python (sx_ref.py) and JavaScript (sx-ref.js). A thin dispatcher in deps.py routes to the bootstrapped implementation when SX_USE_REF=1.")
" — a spec module bootstrapped to every host. Each host loads it via " (code "--spec-modules deps") " and provides 6 platform functions. The spec is the single source of truth; hosts are interchangeable.")
(div :class "space-y-4"
(div
(h4 :class "font-semibold text-stone-700" "1. Transitive closure analyzer (deps.sx)")
(p "The spec defines 9 functions for dependency analysis. The core algorithm:")
(ul :class "list-disc pl-5 text-stone-700 space-y-1"
(li "scan-refs: walk a component body AST, collect all Symbol refs starting with ~")
(li "transitive-deps: recursively follow component references through the env")
(li "compute-all-deps: batch-compute and cache deps for all components in env")
(li "Handle circular references safely via seen-set"))
(~doc-code :code (highlight "(define (transitive-deps name env)\n (let ((key (if (starts-with? name \"~\") name\n (concat \"~\" name)))\n (seen (set-create)))\n (transitive-deps-walk key env seen)\n (set-remove seen key)))" "lisp")))
(h4 :class "font-semibold text-stone-700" "1. Transitive closure (deps.sx)")
(p "9 functions that walk the component graph. The core:")
(~doc-code :code (highlight "(define (transitive-deps name env)\n (let ((key (if (starts-with? name \"~\") name\n (concat \"~\" name)))\n (seen (set-create)))\n (transitive-deps-walk key env seen)\n (set-remove seen key)))" "lisp"))
(p (code "scan-refs") " walks a component body AST collecting " (code "~") " symbols. "
(code "transitive-deps") " follows references recursively through the env. "
(code "compute-all-deps") " batch-computes and caches deps for every component. "
"Circular references terminate safely via a seen-set."))
(div
(h4 :class "font-semibold text-stone-700" "2. Runtime component scanning")
(p "scan-components-from-source uses regex to find (~name patterns in serialized SX. components-needed combines scanning with transitive closure to get the full set of components a page requires."))
(h4 :class "font-semibold text-stone-700" "2. Page scanning")
(~doc-code :code (highlight "(define (components-needed page-source env)\n (let ((direct (scan-components-from-source page-source))\n (all-needed (set-create)))\n (for-each (fn (name) ...\n (set-add! all-needed name)\n (set-union! all-needed (component-deps comp)))\n direct)\n all-needed))" "lisp"))
(p (code "scan-components-from-source") " finds " (code "(~name") " patterns in serialized SX via regex. " (code "components-needed") " combines scanning with the cached transitive closure to produce the minimal component set for a page."))
(div
(h4 :class "font-semibold text-stone-700" "3. Per-page CSS classes")
(p "page-css-classes collects Tailwind classes from all components in a page bundle, enabling per-page CSS extraction."))
(h4 :class "font-semibold text-stone-700" "3. Per-page CSS scoping")
(p (code "page-css-classes") " unions the CSS classes from only the components in the page bundle. Pages that don't use a component never pay for its styles."))
(div
(h4 :class "font-semibold text-stone-700" "4. Platform interface")
(p "The spec declares 6 platform functions that each host implements natively:")
(ul :class "list-disc pl-5 text-stone-700 space-y-1 font-mono text-sm"
(li "component-deps / component-set-deps!")
(li "component-css-classes")
(li "env-components")
(li "regex-find-all / scan-css-classes")))))
(p "The spec declares 6 functions each host implements natively — the only host-specific code:")
(ul :class "list-disc pl-5 text-stone-700 space-y-1"
(li (code "component-deps") " / " (code "component-set-deps!") " — read/write the cached deps set on a component object")
(li (code "component-css-classes") " — read pre-scanned CSS class names from a component")
(li (code "env-components") " — enumerate all component entries in an environment")
(li (code "regex-find-all") " / " (code "scan-css-classes") " — host-native regex and CSS scanning")))))
(~doc-subsection :title "Files"
(~doc-subsection :title "Spec module"
(p "deps.sx is loaded as a " (strong "spec module") " — an optional extension to the core spec. The bootstrapper flag " (code "--spec-modules deps") " includes it in the generated output alongside the core evaluator, parser, and renderer. The same mechanism can carry future modules (e.g., io-detection for Phase 2) without changing the bootstrapper architecture.")
(ul :class "list-disc pl-5 text-stone-700 space-y-1 font-mono text-sm"
(li "shared/sx/ref/deps.sx — canonical spec (9 functions)")
(li "shared/sx/deps.py — dispatcher (SX_USE_REF → bootstrapped, else fallback)")
(li "shared/sx/ref/bootstrap_py.py — spec module + platform deps")
(li "shared/sx/ref/bootstrap_js.py — spec module + platform deps")
(li "shared/sx/ref/sx_ref.py — regenerated with deps module")
(li "shared/static/scripts/sx-ref.js — regenerated with deps module")
(li "shared/sx/tests/test_deps.py — 15 tests")))
(li "shared/sx/ref/deps.sx — canonical spec (9 functions, 6 platform declarations)")
(li "Bootstrapped to all host targets via --spec-modules deps")))
(~doc-subsection :title "Verification"
(ul :class "list-disc pl-5 text-stone-700 space-y-1"
(li "15 dedicated deps tests pass (scan, transitive, circular, compute-all, components-needed)")
(li "541 total Python tests pass with zero regressions")
(li "JS deps functions verified in Node.js (scanRefs, transitiveDeps, computeAllDeps, componentsNeeded)")
(li "Both bootstrapped and fallback code paths produce identical results"))))
(li "15 dedicated tests: scan, transitive closure, circular deps, compute-all, components-needed")
(li "Bootstrapped output verified on both host targets")
(li "Full test suite passes with zero regressions")
(li (a :href "/plans/bundle-analyzer" :class "text-violet-700 underline" "Live bundle analyzer") " shows real per-page savings on this app"))))
;; -----------------------------------------------------------------------
;; Phase 2