New hierarchy: Geography (Reactive Islands, Hypermedia Lakes, Marshes, Isomorphism), Language (Docs, Specs, Bootstrappers, Testing), Applications (CSSX, Protocols), Etc (Essays, Philosophy, Plans). All routes updated to match: /reactive/* → /geography/reactive/*, /docs/* → /language/docs/*, /essays/* → /etc/essays/*, etc. Updates nav-data.sx, all defpage routes, API endpoints, internal links across 43 files. Enhanced find-nav-match for nested group resolution. Also includes: page-helpers-demo sf-total fix (reduce instead of set!), rebootstrapped sx-browser.js and sx_ref.py, defensive slice/rest guards. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
283 lines
26 KiB
Plaintext
283 lines
26 KiB
Plaintext
;; ---------------------------------------------------------------------------
|
|
;; Runtime Slicing
|
|
;; ---------------------------------------------------------------------------
|
|
|
|
(defcomp ~plan-runtime-slicing-content ()
|
|
(~doc-page :title "Runtime Slicing"
|
|
|
|
(~doc-section :title "The Problem" :id "problem"
|
|
(p "sx-browser.js is the full SX client runtime — evaluator, parser, renderer, engine, morph, signals, routing, orchestration, boot. Every page loads all of it.")
|
|
|
|
(div :class "overflow-x-auto rounded border border-stone-200 mb-4"
|
|
(table :class "w-full text-left text-sm"
|
|
(thead (tr :class "border-b border-stone-200 bg-stone-100"
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "File")
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Raw")
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Gzipped")
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Min+Gz")))
|
|
(tbody
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "sx-browser.js")
|
|
(td :class "px-3 py-2 text-stone-700" "354KB")
|
|
(td :class "px-3 py-2 text-stone-700" "75KB")
|
|
(td :class "px-3 py-2 text-stone-700" "44KB"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "sx-ref.js")
|
|
(td :class "px-3 py-2 text-stone-700" "244KB")
|
|
(td :class "px-3 py-2 text-stone-700" "49KB")
|
|
(td :class "px-3 py-2 text-stone-700" "29KB"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "React + ReactDOM")
|
|
(td :class "px-3 py-2 text-stone-700" "—")
|
|
(td :class "px-3 py-2 text-stone-700" "—")
|
|
(td :class "px-3 py-2 text-stone-700" "~5KB + ~40KB")))))
|
|
|
|
(p "Most pages are L0 (pure hypermedia — server renders, client morphs). They don't need the parser, the evaluator, the full primitive set, signals, or client-side routing. They need morph + swap + trigger dispatch. That's a fraction of the runtime.")
|
|
(p "The runtime should be sliceable: each page declares what level it operates at, and the bootstrapper emits only the code that level requires."))
|
|
|
|
;; -----------------------------------------------------------------------
|
|
;; Tiers
|
|
;; -----------------------------------------------------------------------
|
|
|
|
(~doc-section :title "Tiers" :id "tiers"
|
|
(p "Four tiers, matching the " (a :href "/geography/reactive/plan" :class "text-violet-700 underline" "reactive islands") " levels:")
|
|
|
|
(div :class "overflow-x-auto rounded border border-stone-200 mb-4"
|
|
(table :class "w-full text-left text-sm"
|
|
(thead (tr :class "border-b border-stone-200 bg-stone-100"
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Tier")
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "What")
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Modules")
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Target (min+gz)")))
|
|
(tbody
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-semibold text-stone-800" "L0 Hypermedia")
|
|
(td :class "px-3 py-2 text-stone-700" "Morph, swap, trigger dispatch, history")
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-600" "engine, boot (partial)")
|
|
(td :class "px-3 py-2 text-stone-700" "~5KB"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-semibold text-stone-800" "L1 DOM Ops")
|
|
(td :class "px-3 py-2 text-stone-700" "L0 + toggle!, set-attr!, on-event, class-list ops")
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-600" "+ DOM adapter (partial)")
|
|
(td :class "px-3 py-2 text-stone-700" "~8KB"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-semibold text-stone-800" "L2 Islands")
|
|
(td :class "px-3 py-2 text-stone-700" "L1 + signals, computed, effect, defisland hydration")
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-600" "+ signals, DOM adapter (full)")
|
|
(td :class "px-3 py-2 text-stone-700" "~15KB"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-semibold text-stone-800" "L3 Full Eval")
|
|
(td :class "px-3 py-2 text-stone-700" "L2 + parser, evaluator, all primitives, client routing, component resolution")
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-600" "everything")
|
|
(td :class "px-3 py-2 text-stone-700" "~44KB (current)")))))
|
|
|
|
(p "90% of typical pages are L0. A blog post, a product listing, a checkout form — server renders, client morphs on navigation. The full evaluator only loads for pages that do client-side rendering or have reactive islands.")
|
|
|
|
(div :class "rounded border border-amber-200 bg-amber-50 p-4 mt-4"
|
|
(p :class "text-amber-900 font-medium" "Progressive loading")
|
|
(p :class "text-amber-800" "A user navigating an L0 page downloads ~5KB. If they navigate to an L2 page (reactive island), the delta (~10KB) loads on demand. The runtime grows with need, never speculatively.")))
|
|
|
|
;; -----------------------------------------------------------------------
|
|
;; The slicer is SX
|
|
;; -----------------------------------------------------------------------
|
|
|
|
(~doc-section :title "The Slicer is SX" :id "slicer-is-sx"
|
|
(p "Per the " (a :href "/etc/plans/self-hosting-bootstrapper" :class "text-violet-700 underline" "self-hosting principle") ", the slicer is not a build tool — it's a spec module. " (code "slice.sx") " analyzes the spec's own dependency graph and determines which defines belong to which tier.")
|
|
(p (code "js.sx") " (the self-hosting SX-to-JavaScript translator) already compiles the full spec. Slicing is a filter: " (code "js.sx") " translates only the defines that " (code "slice.sx") " selects for a given tier.")
|
|
|
|
(~doc-code :code (highlight ";; slice.sx — determine which defines each tier needs\n;;\n;; Input: the full list of defines from all spec files\n;; Output: a filtered list for the requested tier\n\n(define tier-deps\n ;; Which spec modules each tier requires\n {:L0 (list \"engine\" \"boot-partial\")\n :L1 (list \"engine\" \"boot-partial\" \"dom-partial\")\n :L2 (list \"engine\" \"boot-partial\" \"dom-partial\"\n \"signals\" \"dom-island\")\n :L3 (list \"eval\" \"render\" \"parser\"\n \"engine\" \"orchestration\" \"boot\"\n \"dom\" \"signals\" \"router\")})\n\n(define slice-defines\n (fn (tier all-defines)\n ;; 1. Get the module list for this tier\n ;; 2. Walk each define's dependency references\n ;; 3. Include a define only if ALL its deps are\n ;; satisfiable within the tier's module set\n ;; 4. Return the filtered define list\n (let ((modules (get tier-deps tier)))\n (filter\n (fn (d) (tier-satisfies? modules (define-deps d)))\n all-defines))))" "lisp"))
|
|
|
|
(p "The pipeline becomes:")
|
|
(ol :class "list-decimal pl-5 text-stone-700 space-y-2"
|
|
(li (code "slice.sx") " analyzes the spec and produces a define list per tier")
|
|
(li (code "js.sx") " translates each define list to JavaScript (same translator, different input)")
|
|
(li "The bootstrapper wraps each tier's output with its platform interface (the hand-written JS glue)")
|
|
(li "Output: one " (code ".js") " file per tier, or a single file with tier markers for runtime splitting"))
|
|
|
|
(p "Because " (code "js.sx") " is self-hosting, slicing is just function composition: " (code "(js-translate-file (slice-defines :L0 all-defines))") ". No new translator. No new build tool. The same 1,382-line " (code "js.sx") " that produces the full runtime produces every tier."))
|
|
|
|
;; -----------------------------------------------------------------------
|
|
;; Dependency analysis
|
|
;; -----------------------------------------------------------------------
|
|
|
|
(~doc-section :title "Define-Level Dependency Analysis" :id "deps"
|
|
(p "The slicer needs to know which defines reference which other defines. This is a simpler version of what " (code "deps.sx") " does for components — but at the define level, not the component level.")
|
|
|
|
(~doc-code :code (highlight ";; Walk a define's body AST, collect all symbol references\n;; that resolve to other top-level defines.\n;;\n;; (define morph-children\n;; (fn (old-node new-node)\n;; ...uses morph-node, morph-attrs, create-element...))\n;;\n;; → deps: #{morph-node morph-attrs create-element}\n\n(define define-refs\n (fn (body all-define-names)\n ;; Collect all symbols in body that appear in all-define-names\n (let ((refs (make-set)))\n (walk-ast body\n (fn (node)\n (when (and (symbol? node)\n (set-has? all-define-names (symbol-name node)))\n (set-add! refs (symbol-name node)))))\n refs)))" "lisp"))
|
|
|
|
(p "From these per-define deps, we build the full dependency graph and compute transitive closures. A tier's define set is the transitive closure of its entry points:")
|
|
|
|
(div :class "overflow-x-auto rounded border border-stone-200 mb-4"
|
|
(table :class "w-full text-left text-sm"
|
|
(thead (tr :class "border-b border-stone-200 bg-stone-100"
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Tier")
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Entry points")
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Pulls in")))
|
|
(tbody
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-semibold text-stone-800" "L0")
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-600" "morph-node, process-swap, dispatch-trigger, push-url")
|
|
(td :class "px-3 py-2 text-stone-700" "morph-attrs, morph-children, create-element, extract-swap-config — the morph/swap subgraph"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-semibold text-stone-800" "L1")
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-600" "L0 + toggle-class!, set-attr!, add-event-listener!")
|
|
(td :class "px-3 py-2 text-stone-700" "DOM manipulation helpers — small subgraph"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-semibold text-stone-800" "L2")
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-600" "L1 + signal, deref, reset!, computed, effect, render-dom-island")
|
|
(td :class "px-3 py-2 text-stone-700" "Signal runtime + reactive DOM adapter"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-semibold text-stone-800" "L3")
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-600" "L2 + eval-expr, sx-parse, render-to-dom, resolve-component-by-cid")
|
|
(td :class "px-3 py-2 text-stone-700" "Everything — full evaluator, parser, all ~80 primitives"))))))
|
|
|
|
;; -----------------------------------------------------------------------
|
|
;; Platform interface slicing
|
|
;; -----------------------------------------------------------------------
|
|
|
|
(~doc-section :title "Platform Interface Slicing" :id "platform"
|
|
(p "The bootstrapped code (from js.sx) is only half the story. Each define also depends on platform primitives — the hand-written JS glue that js.sx doesn't produce. These live in " (code "bootstrap_js.py") "'s PLATFORM_* blocks.")
|
|
(p "The slicer must track platform deps too:")
|
|
|
|
(~doc-code :code (highlight ";; Platform primitives referenced by tier\n;;\n;; L0 needs: createElement, setAttribute, morphAttrs,\n;; fetch (for sx-get/post), pushState, replaceState\n;;\n;; L1 adds: classList.toggle, addEventListener\n;;\n;; L2 adds: createComment, createTextNode, domRemove,\n;; domChildNodes — the reactive DOM primitives\n;;\n;; L3 adds: everything in PLATFORM_PARSER_JS,\n;; full DOM adapter, async IO bridge\n\n(define platform-deps\n {:L0 (list :dom-morph :fetch :history)\n :L1 (list :dom-morph :fetch :history :dom-events)\n :L2 (list :dom-morph :fetch :history :dom-events\n :dom-reactive :signal-constructors)\n :L3 (list :dom-morph :fetch :history :dom-events\n :dom-reactive :signal-constructors\n :parser :evaluator :async-io)})" "lisp"))
|
|
|
|
(p "The platform JS blocks in " (code "bootstrap_js.py") " are already organized by adapter (" (code "PLATFORM_DOM_JS") ", " (code "PLATFORM_ENGINE_PURE_JS") ", etc). Slicing further subdivides these into the minimal set each tier needs.")
|
|
(p "This subdivision also happens in SX: " (code "slice.sx") " declares which platform blocks each tier requires. " (code "js.sx") " doesn't need to change — it translates defines. The bootstrapper script reads the slice spec and assembles the platform preamble accordingly."))
|
|
|
|
;; -----------------------------------------------------------------------
|
|
;; Progressive loading
|
|
;; -----------------------------------------------------------------------
|
|
|
|
(~doc-section :title "Progressive Loading" :id "progressive"
|
|
(p "The simplest approach: one file per tier. The server knows each page's tier (from " (code "defpage") " metadata or component analysis) and serves the right script tag.")
|
|
(p "Better: a base file (L0) that all pages load, plus tier deltas loaded on demand.")
|
|
|
|
(~doc-code :code (highlight ";; Server emits the appropriate script for the page's tier\n;;\n;; L0 page (blog post, product listing):\n;; <script src=\"/static/scripts/sx-L0.js\"></script>\n;;\n;; L2 page (reactive island):\n;; <script src=\"/static/scripts/sx-L0.js\"></script>\n;; <script src=\"/static/scripts/sx-L2-delta.js\"></script>\n;;\n;; Client-side navigation from L0 → L2:\n;; 1. L0 runtime handles the swap\n;; 2. New page declares tier=L2 in response header\n;; 3. L0 runtime loads sx-L2-delta.js dynamically\n;; 4. Island hydration proceeds\n\n(define page-tier\n (fn (page)\n ;; Analyze the page's component tree\n ;; If any component is defisland → L2\n ;; If any component uses on-event/toggle! → L1\n ;; Otherwise → L0\n (cond\n ((page-has-islands? page) :L2)\n ((page-has-dom-ops? page) :L1)\n (true :L0))))" "lisp"))
|
|
|
|
(~doc-subsection :title "SX-Tier Response Header"
|
|
(p "The server includes the page's tier in the response:")
|
|
(~doc-code :code (highlight "HTTP/1.1 200 OK\nSX-Tier: L0\nSX-Components: ~card:bafy...,~nav:bafy...\n\n;; or for an island page:\nSX-Tier: L2\nSX-Components: ~counter-island:bafy..." "http"))
|
|
(p "On client-side navigation, the engine reads " (code "SX-Tier") " from the response. If the new page requires a higher tier than currently loaded, it fetches the delta script before processing the swap. The delta script registers its additional primitives and the swap proceeds."))
|
|
|
|
(~doc-subsection :title "Cache Behavior"
|
|
(p "Each tier file is content-hashed (like the current " (code "sx_js_hash") " mechanism). Cache-forever semantics. A user who visits any L0 page caches the L0 runtime permanently. If they later visit an L2 page, only the ~10KB delta downloads.")
|
|
(p "Combined with " (a :href "/etc/plans/environment-images" :class "text-violet-700 underline" "environment images") ": the image CID includes the tier. An L0 image is smaller than an L3 image — it contains fewer primitives, no parser state, no evaluator. The standalone HTML bundle for an L0 page is tiny.")))
|
|
|
|
;; -----------------------------------------------------------------------
|
|
;; Automatic tier detection
|
|
;; -----------------------------------------------------------------------
|
|
|
|
(~doc-section :title "Automatic Tier Detection" :id "auto-detect"
|
|
(p (code "deps.sx") " already classifies components as pure or IO-dependent. Extend it to classify pages by tier:")
|
|
|
|
(~doc-code :code (highlight ";; Extend deps.sx with tier analysis\n;;\n;; Walk the page's component tree:\n;; - Any defisland → L2 minimum\n;; - Any on-event, toggle!, set-attr! call → L1 minimum \n;; - Any client-eval'd component (SX wire + defcomp) → L3\n;; - Otherwise → L0\n;;\n;; The tier is the MAX of all components' requirements.\n\n(define component-tier\n (fn (comp)\n (cond\n ((island? comp) :L2)\n ((has-dom-ops? (component-body comp)) :L1)\n (true :L0))))\n\n(define page-tier\n (fn (page-def)\n (let ((comp-tiers (map component-tier\n (page-all-components page-def))))\n (max-tier comp-tiers))))" "lisp"))
|
|
|
|
(p "This runs at registration time (same phase as " (code "compute_all_deps") "). Each " (code "PageDef") " gains a " (code "tier") " field. The server uses it to select the script tag. No manual annotation needed — the tier is derived from what the page actually uses."))
|
|
|
|
;; -----------------------------------------------------------------------
|
|
;; What L0 actually needs
|
|
;; -----------------------------------------------------------------------
|
|
|
|
(~doc-section :title "What L0 Actually Needs" :id "l0-detail"
|
|
(p "L0 is the critical tier — it's what most pages load. Every byte matters. Let's be precise about what it contains:")
|
|
|
|
(div :class "overflow-x-auto rounded border border-stone-200 mb-4"
|
|
(table :class "w-full text-left text-sm"
|
|
(thead (tr :class "border-b border-stone-200 bg-stone-100"
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Function")
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Purpose")
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Source")))
|
|
(tbody
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-700" "morph-node")
|
|
(td :class "px-3 py-2 text-stone-700" "DOM diffing — update existing DOM from new HTML")
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "engine.sx"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-700" "morph-attrs")
|
|
(td :class "px-3 py-2 text-stone-700" "Attribute diffing on a single element")
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "engine.sx"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-700" "morph-children")
|
|
(td :class "px-3 py-2 text-stone-700" "Child node reconciliation")
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "engine.sx"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-700" "process-swap")
|
|
(td :class "px-3 py-2 text-stone-700" "Apply sx-swap directive (innerHTML, outerHTML, etc)")
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "engine.sx"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-700" "dispatch-trigger")
|
|
(td :class "px-3 py-2 text-stone-700" "Process sx-trigger attributes (click, submit, load, etc)")
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "engine.sx"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-700" "sx-fetch")
|
|
(td :class "px-3 py-2 text-stone-700" "Make sx-get/sx-post requests, process response")
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "orchestration.sx"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-700" "push-url / replace-url")
|
|
(td :class "px-3 py-2 text-stone-700" "History management for sx-push-url")
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "engine.sx"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-700" "boot-triggers")
|
|
(td :class "px-3 py-2 text-stone-700" "Scan DOM for sx-* attributes, wire up event listeners")
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "boot.sx"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-stone-700" "resolve-suspense")
|
|
(td :class "px-3 py-2 text-stone-700" "Fill in streamed suspense slots")
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "boot.sx")))))
|
|
|
|
(p "That's roughly 20-30 defines from engine.sx + orchestration.sx + boot.sx, plus their transitive deps. No parser, no evaluator, no primitives beyond what those defines call internally. The platform JS is just: fetch wrapper, DOM helpers (createElement, setAttribute, morphing), history API, and event delegation.")
|
|
|
|
(p "Target: " (strong "~5KB min+gz") " — competitive with htmx (10KB) while being semantically richer (morph-based, not innerHTML-based)."))
|
|
|
|
;; -----------------------------------------------------------------------
|
|
;; Build pipeline
|
|
;; -----------------------------------------------------------------------
|
|
|
|
(~doc-section :title "Build Pipeline" :id "pipeline"
|
|
(p "The pipeline uses the same tools that already exist — " (code "js.sx") " for translation, " (code "bootstrap_js.py") " for platform assembly — but feeds them filtered define lists.")
|
|
|
|
(~doc-code :code (highlight ";; Build all tiers\n;;\n;; 1. Load all spec .sx files\n;; 2. Extract all defines (same as current bootstrap)\n;; 3. Run slice.sx to partition defines by tier\n;; 4. For each tier:\n;; a. js.sx translates the tier's define list\n;; b. Platform assembler wraps with minimal platform JS\n;; c. Output: sx-L{n}.js\n;; 5. Compute deltas: L1-delta = L1 - L0, L2-delta = L2 - L1, etc.\n\n;; The bootstrapper script orchestrates this:\n;;\n;; python bootstrap_js.py --tier L0 -o sx-L0.js\n;; python bootstrap_js.py --tier L1 --delta -o sx-L1-delta.js\n;; python bootstrap_js.py --tier L2 --delta -o sx-L2-delta.js\n;; python bootstrap_js.py -o sx-browser.js # full (L3, backward compat)" "lisp"))
|
|
|
|
(p "The " (code "--delta") " flag emits only the defines not present in the previous tier. The delta file calls " (code "Sx.extend()") " to register its additions into the already-loaded runtime.")
|
|
|
|
(div :class "rounded border border-violet-200 bg-violet-50 p-4 mt-4"
|
|
(p :class "text-violet-900 font-medium" "Self-hosting all the way")
|
|
(p :class "text-violet-800" (code "slice.sx") " is spec. " (code "js.sx") " is spec. The bootstrapper script (" (code "bootstrap_js.py") ") is the thin host-specific glue that reads slice output, calls js.sx via the evaluator, and wraps with platform JS. The slicer could itself be bootstrapped to JavaScript and run in a browser build tool — but that's a future concern.")))
|
|
|
|
;; -----------------------------------------------------------------------
|
|
;; Spec modules
|
|
;; -----------------------------------------------------------------------
|
|
|
|
(~doc-section :title "Spec Modules" :id "spec-modules"
|
|
(div :class "overflow-x-auto rounded border border-stone-200 mb-4"
|
|
(table :class "w-full text-left text-sm"
|
|
(thead (tr :class "border-b border-stone-200 bg-stone-100"
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Module")
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Functions")
|
|
(th :class "px-3 py-2 font-medium text-stone-600" "Depends on")))
|
|
(tbody
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "slice.sx")
|
|
(td :class "px-3 py-2 text-stone-700" (code "define-refs") ", " (code "define-dep-graph") ", " (code "slice-defines") ", " (code "tier-entry-points") ", " (code "page-tier") ", " (code "component-tier"))
|
|
(td :class "px-3 py-2 text-stone-600" "deps.sx (component analysis), eval.sx (AST walking)"))
|
|
(tr :class "border-b border-stone-100"
|
|
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "js.sx")
|
|
(td :class "px-3 py-2 text-stone-700" (code "js-translate-file") " — already exists, unchanged")
|
|
(td :class "px-3 py-2 text-stone-600" "eval.sx (runs on evaluator)")))))
|
|
|
|
(p "One new spec file (" (code "slice.sx") "), one existing translator (" (code "js.sx") "), one modified host script (" (code "bootstrap_js.py") " gains " (code "--tier") " and " (code "--delta") " flags)."))
|
|
|
|
;; -----------------------------------------------------------------------
|
|
;; Relationships
|
|
;; -----------------------------------------------------------------------
|
|
|
|
(~doc-section :title "Relationships" :id "relationships"
|
|
(ul :class "list-disc pl-5 text-stone-700 space-y-1"
|
|
(li (a :href "/etc/plans/environment-images" :class "text-violet-700 underline" "Environment Images") " — tiered images are smaller. An L0 image omits the parser, evaluator, and most primitives.")
|
|
(li (a :href "/etc/plans/content-addressed-components" :class "text-violet-700 underline" "Content-Addressed Components") " — component CID resolution is L3-only. L0 pages don't resolve components client-side.")
|
|
(li (a :href "/geography/reactive/plan" :class "text-violet-700 underline" "Reactive Islands") " — L2 tier is defined by island presence. The signal runtime is the L1→L2 delta.")
|
|
(li (a :href "/etc/plans/isomorphic-architecture" :class "text-violet-700 underline" "Isomorphic Architecture") " — client-side page rendering is L3. Most pages don't need it."))
|
|
|
|
(div :class "rounded border border-amber-200 bg-amber-50 p-3 mt-2"
|
|
(p :class "text-amber-800 text-sm" (strong "Depends on: ") (code "js.sx") " (complete), " (code "deps.sx") " (complete), " (code "bootstrap_js.py") " adapter selection (exists). " (strong "New: ") (code "slice.sx") " spec module.")))))
|