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.")) (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" (~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" (~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") (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 :class "space-y-4"
(div (div
(h4 :class "font-semibold text-stone-700" "1. Transitive closure analyzer (deps.sx)") (h4 :class "font-semibold text-stone-700" "1. Transitive closure (deps.sx)")
(p "The spec defines 9 functions for dependency analysis. The core algorithm:") (p "9 functions that walk the component graph. The core:")
(ul :class "list-disc pl-5 text-stone-700 space-y-1" (~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"))
(li "scan-refs: walk a component body AST, collect all Symbol refs starting with ~") (p (code "scan-refs") " walks a component body AST collecting " (code "~") " symbols. "
(li "transitive-deps: recursively follow component references through the env") (code "transitive-deps") " follows references recursively through the env. "
(li "compute-all-deps: batch-compute and cache deps for all components in env") (code "compute-all-deps") " batch-computes and caches deps for every component. "
(li "Handle circular references safely via seen-set")) "Circular references terminate safely via a 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")))
(div (div
(h4 :class "font-semibold text-stone-700" "2. Runtime component scanning") (h4 :class "font-semibold text-stone-700" "2. Page 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.")) (~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 (div
(h4 :class "font-semibold text-stone-700" "3. Per-page CSS classes") (h4 :class "font-semibold text-stone-700" "3. Per-page CSS scoping")
(p "page-css-classes collects Tailwind classes from all components in a page bundle, enabling per-page CSS extraction.")) (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 (div
(h4 :class "font-semibold text-stone-700" "4. Platform interface") (h4 :class "font-semibold text-stone-700" "4. Platform interface")
(p "The spec declares 6 platform functions that each host implements natively:") (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 font-mono text-sm" (ul :class "list-disc pl-5 text-stone-700 space-y-1"
(li "component-deps / component-set-deps!") (li (code "component-deps") " / " (code "component-set-deps!") " — read/write the cached deps set on a component object")
(li "component-css-classes") (li (code "component-css-classes") " — read pre-scanned CSS class names from a component")
(li "env-components") (li (code "env-components") " — enumerate all component entries in an environment")
(li "regex-find-all / scan-css-classes"))))) (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" (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/ref/deps.sx — canonical spec (9 functions, 6 platform declarations)")
(li "shared/sx/deps.py — dispatcher (SX_USE_REF → bootstrapped, else fallback)") (li "Bootstrapped to all host targets via --spec-modules deps")))
(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")))
(~doc-subsection :title "Verification" (~doc-subsection :title "Verification"
(ul :class "list-disc pl-5 text-stone-700 space-y-1" (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 "15 dedicated tests: scan, transitive closure, circular deps, compute-all, components-needed")
(li "541 total Python tests pass with zero regressions") (li "Bootstrapped output verified on both host targets")
(li "JS deps functions verified in Node.js (scanRefs, transitiveDeps, computeAllDeps, componentsNeeded)") (li "Full test suite passes with zero regressions")
(li "Both bootstrapped and fallback code paths produce identical results")))) (li (a :href "/plans/bundle-analyzer" :class "text-violet-700 underline" "Live bundle analyzer") " shows real per-page savings on this app"))))
;; ----------------------------------------------------------------------- ;; -----------------------------------------------------------------------
;; Phase 2 ;; Phase 2