From 524c99e4ff540351d5ebce3563d21aa21ebbcc4c Mon Sep 17 00:00:00 2001 From: giles Date: Wed, 11 Mar 2026 23:11:24 +0000 Subject: [PATCH] Restructure specs into hierarchical sections, add "The Art Chain" essay Specs nav reorganized from flat list into 6 sections with children: Core (5), Adapters (4), Browser (4), Reactive (1), Host Interface (3), Extensions (4). Added missing spec items: adapter-async, signals, boundary, forms, page-helpers, types. Architecture page updated to match. New essay on ars, techne, and the self-making artifact chain. Co-Authored-By: Claude Opus 4.6 --- sx/sx/essays/the-art-chain.sx | 73 +++++++++++++++ sx/sx/nav-data.sx | 98 +++++++++++++------- sx/sx/specs.sx | 162 ++++++++++++++++++++++++---------- sx/sxc/pages/docs.sx | 78 ++++++++-------- 4 files changed, 288 insertions(+), 123 deletions(-) create mode 100644 sx/sx/essays/the-art-chain.sx diff --git a/sx/sx/essays/the-art-chain.sx b/sx/sx/essays/the-art-chain.sx new file mode 100644 index 0000000..ca719da --- /dev/null +++ b/sx/sx/essays/the-art-chain.sx @@ -0,0 +1,73 @@ +;; --------------------------------------------------------------------------- +;; The Art Chain +;; --------------------------------------------------------------------------- + +(defcomp ~essay-the-art-chain () + (~doc-page :title "The Art Chain" + (p :class "text-stone-500 text-sm italic mb-8" + "On making, self-making, and the chain of artifacts that produces itself.") + + (~doc-section :title "I. Ars" :id "ars" + (p :class "text-stone-600" + "The Latin word " (em "ars") " means something made with skill. Not art as in paintings on gallery walls. Art as in " (em "artifice") ", " (em "artifact") ", " (em "artisan") ". The made thing. The Greek " (em "techne") " is the same word — craft, skill, the knowledge of how to make. There was no distinction between art and engineering because there was no distinction to make.") + (p :class "text-stone-600" + "A bridge is " (em "ars") ". A poem is " (em "ars") ". A proof is " (em "ars") ". What makes something art is not its medium or its audience but the fact that it was " (em "made") " — brought into being by someone who knew how to bring it into being. The maker's knowledge is embedded in the made thing. You can read the knowledge back out by studying what was made.") + (p :class "text-stone-600" + "Software is " (em "ars") ". Obviously. It is the most " (em "ars") " thing we have ever built — pure made-ness, structure conjured from nothing, shaped entirely by the maker's skill and intent. There is no raw material. No marble to chisel, no pigment to mix. Just thought, made concrete in symbols.")) + + (~doc-section :title "II. The spec at the centre" :id "spec" + (p :class "text-stone-600" + "SX has a peculiar architecture. At its centre sits a specification — a set of s-expression files that define the language. Not a description of the language. Not documentation " (em "about") " the language. The specification " (em "is") " the language. It is simultaneously a formal definition and executable code. You can read it as a document or run it as a program. It does not describe how to build an SX evaluator; it " (em "is") " an SX evaluator, expressed in the language it defines.") + (p :class "text-stone-600" + "This is the nucleus. Everything else radiates outward from it.") + (~doc-code :code (highlight ";; The spec defines eval-expr\n;; eval-expr evaluates the spec\n;; The spec is an artifact that makes itself\n\n(define eval-expr\n (fn (expr env)\n (cond\n (number? expr) expr\n (string? expr) expr\n (symbol? expr) (env-get env (symbol-name expr))\n (list? expr) (eval-list expr env)\n :else expr)))" "lisp")) + (p :class "text-stone-600" + "From this nucleus, concentric rings unfurl:")) + + (~doc-section :title "III. The rings" :id "rings" + (p :class "text-stone-600" + "The first ring is the " (strong "bootstrapper") ". It reads the spec and emits a native implementation — JavaScript, Python, or any other target. The bootstrapper is a translator: it takes the made thing (the spec) and makes another thing (an implementation) that behaves identically. The spec's knowledge is preserved in the translation. Nothing is added, nothing is lost.") + (p :class "text-stone-600" + "The second ring is the " (strong "platform bridge") ". The spec defines pure logic — evaluation, rendering, parsing. But a running system needs to touch the world: read files, make HTTP requests, manipulate DOM nodes. The platform bridge provides these capabilities. It is the boundary between the made world (the spec) and the found world (the host environment). " (code "boundary.sx") " is literally the membrane — it declares what the host must provide so the spec can function.") + (p :class "text-stone-600" + "The third ring is the " (strong "runtime") " — bootstrapped spec plus platform bridge, assembled into a working system. This is where the spec stops being an idea and starts being a process. It evaluates expressions. It renders pages. It handles requests.") + (p :class "text-stone-600" + "The fourth ring is " (strong "application code") " — components, pages, layouts, written in the language the spec defined. Every " (code "defcomp") " is an artifact made from the tools the spec provided. Every " (code "(div :class \"card\" (p \"hello\"))") " is the spec expressing itself through a developer's intent.") + (p :class "text-stone-600" + "The fifth ring is " (strong "this website") " — which renders the spec's source code using the runtime the spec produced, displayed in components written in the language the spec defines, navigated by an engine the spec specifies. The documentation is the thing documenting itself.")) + + (~doc-section :title "IV. The chain" :id "chain" + (p :class "text-stone-600" + "Each ring is an artifact — a made thing. And each artifact is made " (em "by") " the artifact inside it. The spec makes the bootstrapper's output. The runtime makes the application's output. The application makes the page the user sees. It is a chain of making.") + (p :class "text-stone-600" + "This chain has three properties that are individually common but collectively rare:") + (p :class "text-stone-600" + (strong "Content addressing.") " Each artifact can be identified by the hash of its content. The spec at a given version has a specific hash. The bootstrapped output from that spec has a deterministic hash. A component definition has a hash. Identity " (em "is") " content. You don't ask " (em "where") " an artifact lives — you ask " (em "what") " it is.") + (p :class "text-stone-600" + (strong "Deterministic derivation.") " Given the same spec, the bootstrapper produces the same output. Byte for byte. This is not aspirational — it is verified. The self-hosting bootstrapper (py.sx) proves it: G0 (hand-written bootstrapper) and G1 (self-hosted bootstrapper) produce identical output. The derivation is a pure function. Anyone can run it and verify the result.") + (p :class "text-stone-600" + (strong "Self-verification.") " The spec includes tools that can prove properties about the spec. " (code "prove.sx") " checks primitive semantics. " (code "types.sx") " validates composition. " (code "z3.sx") " translates declarations into verification conditions. These tools are themselves part of the spec, subject to the same verification they perform. The chain can verify itself.") + (p :class "text-stone-600" + "These three properties together — content addressing, deterministic derivation, self-verification — are what a blockchain provides. But here there is no proof-of-work, no tokens, no artificial scarcity, no consensus mechanism between untrusted parties. The \"mining\" is bootstrapping. The \"consensus\" is mathematical proof. The \"value\" is that anyone can take the spec, derive an implementation, and " (em "know") " it is correct.")) + + (~doc-section :title "V. Universal analysis" :id "analysis" + (p :class "text-stone-600" + "Here is the consequence that takes time to absorb: any tool that can analyse the spec can analyse " (em "everything the spec produces") ".") + (p :class "text-stone-600" + "A type checker written in SX that validates the spec's primitives also validates every call to those primitives in every component in every application. A dependency analyser that walks the spec's AST walks application ASTs identically — because application code is expressed in the same structures the spec defines. A theorem prover that verifies the spec's properties verifies the properties of everything downstream.") + (p :class "text-stone-600" + "This is because the rings are not separate systems. They are the " (em "same") " system at different scales. Application code is spec-shaped. Bootstrapped output is spec-derived. Components are spec-evaluated. The analysis surface is uniform from the nucleus to the outermost ring.") + (p :class "text-stone-600" + "And the analysis tools are " (em "inside") " the chain. They are artifacts too, written in SX, subject to the same analysis they perform. The type checker can type-check itself. The prover can prove properties about itself. This is not a bug or a curiosity — it is the point. A system that cannot reason about itself is a system that must be reasoned about from outside, by tools written in other languages, maintained by other processes, trusted for other reasons. A self-analysing system closes the loop.")) + + (~doc-section :title "VI. The art in the chain" :id "art" + (p :class "text-stone-600" + "So what is the art chain? It is a chain of artifacts — made things — where each link produces the next, the whole chain can verify itself, and the chain's identity is its content.") + (p :class "text-stone-600" + "It is not a blockchain in the financial sense. It is not a distributed ledger, a currency, a market. It borrows the structural properties — content addressing, determinism, verification — without the economic machinery. What remains when you strip the economics from a blockchain is a " (em "provenance chain") ": a record of how each thing was made from the thing before it, verifiable by anyone, depending on nothing but the mathematics.") + (p :class "text-stone-600" + "The Art DAG has the right name. It is not a system for processing \"art\" in the colloquial sense — images, videos, media. It is a " (em "directed acyclic graph of made things") ". Each node is an artifact. Each edge is a derivation. The graph is content-addressed. Execution is deterministic. The DAG itself is the art.") + (p :class "text-stone-600" + "And the whole SX system — spec, bootstrappers, runtimes, components, pages, this essay explaining itself — is one continuous act of making. " (em "Ars") " all the way down. Not because it is beautiful (though it sometimes is) or expressive (though it tries to be) but because it is " (em "made") ". Deliberately, skilfully, from nothing, by someone who knew how.") + (p :class "text-stone-600" + "That is what " (em "techne") " always was. We just forgot.")))) diff --git a/sx/sx/nav-data.sx b/sx/sx/nav-data.sx index b3a9d37..b209d12 100644 --- a/sx/sx/nav-data.sx +++ b/sx/sx/nav-data.sx @@ -95,7 +95,9 @@ (dict :label "React is Hypermedia" :href "/etc/essays/react-is-hypermedia" :summary "A React Island is a hypermedia control. Its behavior is specified in SX.") (dict :label "The Hegelian Synthesis" :href "/etc/essays/hegelian-synthesis" - :summary "On the dialectical resolution of the hypertext/reactive contradiction. Thesis: the server renders. Antithesis: the client reacts. Synthesis: the island in the lake."))) + :summary "On the dialectical resolution of the hypertext/reactive contradiction. Thesis: the server renders. Antithesis: the client reacts. Synthesis: the island in the lake.") + (dict :label "The Art Chain" :href "/etc/essays/the-art-chain" + :summary "On making, self-making, and the chain of artifacts that produces itself. Ars, techne, content addressing, and why the spec is the art."))) (define philosophy-nav-items (list (dict :label "The SX Manifesto" :href "/etc/philosophy/sx-manifesto" @@ -110,25 +112,33 @@ :summary "Existence precedes essence — Sartre, Camus, and the absurd freedom of writing a Lisp for the web."))) (define specs-nav-items (list - (dict :label "Architecture" :href "/language/specs/") - (dict :label "Core" :href "/language/specs/core") - (dict :label "Parser" :href "/language/specs/parser") - (dict :label "Evaluator" :href "/language/specs/evaluator") - (dict :label "Primitives" :href "/language/specs/primitives") - (dict :label "Special Forms" :href "/language/specs/special-forms") - (dict :label "Renderer" :href "/language/specs/renderer") - (dict :label "Adapters" :href "/language/specs/adapters") - (dict :label "DOM Adapter" :href "/language/specs/adapter-dom") - (dict :label "HTML Adapter" :href "/language/specs/adapter-html") - (dict :label "SX Wire Adapter" :href "/language/specs/adapter-sx") - (dict :label "Browser" :href "/language/specs/browser") - (dict :label "SxEngine" :href "/language/specs/engine") - (dict :label "Orchestration" :href "/language/specs/orchestration") - (dict :label "Boot" :href "/language/specs/boot") - (dict :label "Continuations" :href "/language/specs/continuations") - (dict :label "call/cc" :href "/language/specs/callcc") - (dict :label "Deps" :href "/language/specs/deps") - (dict :label "Router" :href "/language/specs/router"))) + {:label "Core" :href "/language/specs/core" :children (list + {:label "Parser" :href "/language/specs/parser"} + {:label "Evaluator" :href "/language/specs/evaluator"} + {:label "Primitives" :href "/language/specs/primitives"} + {:label "Special Forms" :href "/language/specs/special-forms"} + {:label "Renderer" :href "/language/specs/renderer"})} + {:label "Adapters" :href "/language/specs/adapters" :children (list + {:label "DOM Adapter" :href "/language/specs/adapter-dom"} + {:label "HTML Adapter" :href "/language/specs/adapter-html"} + {:label "SX Wire Adapter" :href "/language/specs/adapter-sx"} + {:label "Async Adapter" :href "/language/specs/adapter-async"})} + {:label "Browser" :href "/language/specs/browser" :children (list + {:label "SxEngine" :href "/language/specs/engine"} + {:label "Orchestration" :href "/language/specs/orchestration"} + {:label "Boot" :href "/language/specs/boot"} + {:label "Router" :href "/language/specs/router"})} + {:label "Reactive" :href "/language/specs/reactive" :children (list + {:label "Signals" :href "/language/specs/signals"})} + {:label "Host Interface" :href "/language/specs/host" :children (list + {:label "Boundary" :href "/language/specs/boundary"} + {:label "Forms" :href "/language/specs/forms"} + {:label "Page Helpers" :href "/language/specs/page-helpers"})} + {:label "Extensions" :href "/language/specs/extensions" :children (list + {:label "Continuations" :href "/language/specs/continuations"} + {:label "call/cc" :href "/language/specs/callcc"} + {:label "Types" :href "/language/specs/types"} + {:label "Deps" :href "/language/specs/deps"})})) (define testing-nav-items (list (dict :label "Overview" :href "/language/testing/") @@ -260,17 +270,39 @@ (dict :slug "adapter-sx" :filename "adapter-sx.sx" :title "SX Wire Adapter" :desc "Serializes SX for client-side rendering. Component calls stay unexpanded." :prose "The SX wire adapter serializes expressions as SX source text for transmission to the browser, where sx.js renders them client-side. Unlike the HTML adapter, component calls (~name ...) are NOT expanded — they are sent to the client as-is, allowing the browser to render them with its local component registry. HTML tags ARE serialized as s-expression source. This is the format used for SX-over-HTTP responses and the page boot payload.") + (dict :slug "adapter-async" :filename "adapter-async.sx" :title "Async Adapter" + :desc "Async versions of HTML and SX wire adapters for server-side rendering with I/O." + :prose "The async adapter provides async-aware versions of the HTML and SX wire rendering functions. It intercepts I/O operations (database queries, service calls, fragment fetches) during evaluation, awaiting them before continuing. Entry points: async-render (HTML output with awaited I/O), async-aser (SX wire format with awaited I/O). The bootstrapper emits async def and automatic await insertion for all define-async functions. This adapter is what makes server-side SX pages work with real data."))) + +(define browser-spec-items (list (dict :slug "engine" :filename "engine.sx" :title "SxEngine" :desc "Pure logic for fetch, swap, history, SSE, triggers, morph, and indicators." :prose "The engine specifies the pure logic of the browser-side fetch/swap/history system. Like HTMX but native to SX. It defines trigger parsing (click, submit, intersect, poll, load, revealed), swap algorithms (innerHTML, outerHTML, morph, beforebegin, etc.), the morph/diff algorithm for patching existing DOM, history management (push-url, replace-url, popstate), out-of-band swap identification, Server-Sent Events parsing, retry logic with exponential backoff, request header building, response header processing, and optimistic UI updates. This file contains no browser API calls — all platform interaction is in orchestration.sx.") (dict :slug "orchestration" :filename "orchestration.sx" :title "Orchestration" :desc "Browser wiring that binds engine logic to DOM events, fetch, and lifecycle." - :prose "Orchestration is the browser wiring layer. It binds the pure engine logic to actual browser APIs: DOM event listeners, fetch(), AbortController, setTimeout/setInterval, IntersectionObserver, history.pushState, and EventSource (SSE). It implements the full request lifecycle — from trigger through fetch through swap — including CSS tracking, response type detection (SX vs HTML), OOB swap processing, script activation, element boosting, and preload. Dependency is strictly one-way: orchestration depends on engine, never the reverse."))) - -(define browser-spec-items (list - (dict :slug "boot" :filename "boot.sx" :title "Boot" + :prose "Orchestration is the browser wiring layer. It binds the pure engine logic to actual browser APIs: DOM event listeners, fetch(), AbortController, setTimeout/setInterval, IntersectionObserver, history.pushState, and EventSource (SSE). It implements the full request lifecycle — from trigger through fetch through swap — including CSS tracking, response type detection (SX vs HTML), OOB swap processing, script activation, element boosting, and preload. Dependency is strictly one-way: orchestration depends on engine, never the reverse.") + (dict :slug "boot" :filename "boot.sx" :title "Boot" :desc "Browser startup lifecycle: mount, hydrate, script processing." - :prose "Boot handles the browser startup sequence and provides the public API for mounting SX content. On page load it: (1) initializes CSS tracking, (2) processes