Commit Graph

116 Commits

Author SHA1 Message Date
917a487195 Add deps and engine test specs, bootstrap engine to Python
New test specs (test-deps.sx: 33 tests, test-engine.sx: 37 tests) covering
component dependency analysis and engine pure functions. All 6 spec modules
now have formal SX tests: eval (81), parser (39), router (18), render (23),
deps (33), engine (37) = 231 total.

- Add engine as spec module in bootstrap_py.py (alongside deps)
- Add primitive aliases (trim, replace, parse_int, upper) for engine functions
- Fix parse-int to match JS parseInt semantics (strip trailing non-digits)
- Regenerate sx_ref.py with --spec-modules deps,engine
- Update all three test runners (run.js, run.py, sx-test-runner.js)
- Add Dependencies and Engine nav items and testing page entries
- Wire deps-source/engine-source through testing overview UI

Node.js: 231/231 pass. Python: 226/231 (5 pre-existing parser/router gaps).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:01:33 +00:00
6421a23223 Update isomorphic plan: Phase 6 status badge, demo section, file list
- Add Complete badge with live demo link to Phase 6 section
- Replace Verification with Demonstration + What to verify sections
- Update Files list: boot.sx spec, bootstrap_js.py, demo files
- Add streaming/suspense and client IO to Current State summary

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:35:57 +00:00
a05d642461 Phase 6: Streaming & Suspense — chunked HTML with suspense resolution
Server streams HTML shell with ~suspense placeholders immediately,
then sends resolution <script> chunks as async IO completes. Browser
renders loading skeletons instantly, replacing them with real content
as data arrives via __sxResolve().

- defpage :stream true opts pages into streaming response
- ~suspense component renders fallback with data-suspense attr
- resolve-suspense in boot.sx (spec) + bootstrapped to sx-browser.js
- __sxPending queue handles resolution before sx-browser.js loads
- execute_page_streaming() async generator with concurrent IO tasks
- Streaming demo page at /isomorphism/streaming with 1.5s simulated delay

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:34:10 +00:00
85083a0fff Formalise Phase 5 (Client IO Proxy) as complete
Phase 5 was solved by IO proxy registration + async DOM renderer +
JavaScript Promises — no continuations needed on the client side.
Continuations remain a prerequisite for Phase 6 (server-side streaming).

Updated plan status: Phases 1-5 complete. Phase 4 moved from Partial.
Renumbered: streaming/suspense is now Phase 6, full iso is Phase 7.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:03:07 +00:00
624d1872e3 Fix testing pages: move read-spec-file into :data for client routing
read-spec-file is a server-only page helper. When the client router
tried to evaluate :content, it couldn't find the function. Move all
file reads into the :data expression (evaluated server-side) so
:content only references data bindings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:14:15 +00:00
3119b8e310 Add Testing as top-level docs section with per-module specs
New /testing/ section with 6 pages: overview (all specs), evaluator,
parser, router, renderer, and runners. Each page runs tests server-side
(Python) and offers a browser "Run tests" button (JS). Modular browser
runner (sxRunModularTests) loads framework + per-spec sources from DOM.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:37:30 +00:00
99a78a70b3 Merge remote-tracking branch 'origin/main' into worktree-iso-phase-4
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 3m54s
# Conflicts:
#	sx/sx/essays.sx
#	sx/sx/nav-data.sx
#	sx/sxc/pages/docs.sx
2026-03-07 11:28:48 +00:00
72148fa4c0 Add Separation of Concerns essay
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
The web's HTML/CSS/JS split separates the framework's concerns,
not the application domain's. Real separation of concerns is
domain-specific and cannot be prescribed by a platform.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:24:27 +00:00
b6ba7ad6be Merge branch 'worktree-iso-phase-4' into macros
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 3m22s
2026-03-07 11:10:27 +00:00
6f403c0c2d Add server-side test runner to /specs/testing page
Python evaluator runs test.sx at page load, results shown alongside
the browser runner. Both hosts prove the same 81 tests from the same
spec file — server on render, client on click.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:10:24 +00:00
3ab26635ce Merge branch 'worktree-iso-phase-4' into macros
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
2026-03-07 11:06:09 +00:00
9b3b2ea224 Add testing section to Strange Loops essay
SX testing SX is the strange loop made concrete — the language proves
its own correctness using its own macros. Links to /specs/testing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:06:06 +00:00
e89c496dc8 Merge branch 'worktree-iso-phase-4' into macros 2026-03-07 11:00:51 +00:00
7eb158c79f Add live browser test runner to /specs/testing page
sx-browser.js evaluates test.sx directly in the browser — click
"Run 81 tests" to see SX test itself. Uses the same Sx global that
rendered the page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:00:37 +00:00
e9d86d628b Make test.sx self-executing: evaluators run it directly, no codegen
test.sx now defines deftest/defsuite as macros. Any host that provides
5 platform functions (try-call, report-pass, report-fail, push-suite,
pop-suite) can evaluate the file directly — no bootstrap compilation
step needed for JS.

- Added defmacro for deftest (wraps body in thunk, catches via try-call)
- Added defmacro for defsuite (push/pop suite context stack)
- Created run.js: sx-browser.js evaluates test.sx directly (81/81 pass)
- Created run.py: Python evaluator evaluates test.sx directly (81/81 pass)
- Deleted bootstrap_test_js.py and generated test_sx_spec.js
- Updated testing docs page to reflect self-executing architecture

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 10:50:28 +00:00
754e7557f5 Add self-hosting SX test spec: 81 tests bootstrap to Python + JS
The test framework is written in SX and tests SX — the language proves
its own correctness. test.sx defines assertion helpers (assert-equal,
assert-true, assert-type, etc.) and 15 test suites covering literals,
arithmetic, comparison, strings, lists, dicts, predicates, special forms,
lambdas, higher-order forms, components, macros, threading, truthiness,
and edge cases.

Two bootstrap compilers emit native tests from the same spec:
- bootstrap_test.py → pytest (81/81 pass)
- bootstrap_test_js.py → Node.js TAP using sx-browser.js (81/81 pass)

Also adds missing primitives to spec and Python evaluator: boolean?,
string-length, substring, string-contains?, upcase, downcase, reverse,
flatten, has-key?. Fixes number? to exclude booleans, append to
concatenate lists.

Includes testing docs page in SX app at /specs/testing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 10:41:53 +00:00
9ac90a787d Merge branch 'worktree-iso-phase-4' into macros 2026-03-07 09:14:07 +00:00
cb0990feb3 Dynamic IO proxy: derive proxied primitives from component io_refs
Replace hardcoded IO primitive lists on both client and server with
data-driven registration. Page registry entries carry :io-deps (list
of IO primitive names) instead of :has-io boolean. Client registers
proxied IO on demand per page via registerIoDeps(). Server builds
allowlist from component analysis.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 09:13:53 +00:00
8c89311182 Essay: make clear the entire site was built by agentic AI, no editor, no Lisp experience
Rewrote the closing sections to state plainly: every spec file, bootstrapper,
component, page, and deployment was produced through Claude in a terminal.
No VS Code, no vi, no prior Lisp. The proof that SX is AI-amenable is
that this site exists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 09:10:45 +00:00
a745de7e35 New essay: SX and AI — why s-expressions are ideal for AI code generation
Covers syntax tax (zero for s-expressions), uniform representation,
spec fits in context window, trivial structural validation, self-documenting
components, token efficiency (~40% fewer than JSX), free composability,
and the instant feedback loop with no build step.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 09:04:51 +00:00
a5f5373a63 Merge branch 'worktree-iso-phase-4' into macros 2026-03-07 08:48:51 +00:00
c2a85ed026 Fix async IO demo: use ~doc-code instead of raw!, fix JS highlight
highlight returns SxExpr (SX source with colored spans), not raw HTML.
Must render via evaluator (~doc-code :code), not (raw! ...). Also
replace JavaScript example with SX (no JS highlighter exists).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 08:48:48 +00:00
69ced865db Merge branch 'worktree-iso-phase-1' into macros
# Conflicts:
#	shared/sx/helpers.py
#	shared/sx/pages.py
#	sx/sx/nav-data.sx
#	sx/sx/plans.sx
#	sx/sxc/pages/docs.sx
2026-03-07 08:38:32 +00:00
2b0a45b337 Fix code block rendering: escape newlines/tabs in syntax highlighter output
highlight_sx/python/bash produced SX string literals with literal newline
and tab characters, breaking the wire format parser. Add centralized
_escape() helper that properly escapes \n, \t, \r (plus existing \\ and
" escaping). Code blocks now render with correct indentation and syntax
highlighting in both server and client renders.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 08:35:33 +00:00
feb368f7fb Add plans audit: status overview + fragment protocol, glue decoupling, social sharing pages
Audit all plan files and create documentation pages for what remains:
- Status overview with green/amber/stone badges for all 15 plans
- Fragment Protocol: what exists (GET), what remains (POST sexp, structured response)
- Glue Decoupling: 25+ cross-app imports to eliminate via glue service layer
- Social Sharing: 6-phase OAuth-based sharing to major platforms

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 08:35:27 +00:00
79fa1411dc Phase 5: async IO rendering — components call IO primitives client-side
Wire async rendering into client-side routing: pages whose component
trees reference IO primitives (highlight, current-user, etc.) now
render client-side via Promise-aware asyncRenderToDom. IO calls proxy
through /sx/io/<name> endpoint, which falls back to page helpers.

- Add has-io flag to page registry entries (helpers.py)
- Remove IO purity filter — include IO-dependent components in bundles
- Extend try-client-route with 4 paths: pure, data, IO, data+IO
- Convert tryAsyncEvalContent to callback style, add platform mapping
- IO proxy falls back to page helpers (highlight works via proxy)
- Demo page: /isomorphism/async-io with inline highlight calls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 08:12:42 +00:00
59c935e394 Fix route order: specific routes before wildcard <slug> catch-all
Client router uses first-match, so /isomorphism/data-test was matching
the /isomorphism/<slug> wildcard instead of the specific data-test route.
Moved bundle-analyzer, routing-analyzer, data-test before the wildcard.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:07:02 +00:00
9278be9fe2 Mark Phase 4 complete in sx-docs, link to data-test demo
- Phase 4 section: green "Complete" badge with live data test link
- Documents architecture: resolve-page-data, server endpoint, data cache
- Lists files, 30 unit tests, verification steps
- Renumber: Phase 5 = async continuations, Phase 6 = streaming, Phase 7 = full iso
- Update Phase 3 to note :data pages now also client-routable
- Add data-test to "pages that fall through" list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:41:15 +00:00
60b58fdff7 Add cache unit tests (10) and update data-test demo for TTL
- 10 new tests: cache key generation, set/get, TTL expiry, overwrite,
  key independence, complex nested data
- Update data-test.sx with cache verification instructions:
  navigate away+back within 30s → client+cache, after 30s → new fetch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:18:11 +00:00
a657d0831c Phase 4: Client-side rendering of :data pages via abstract resolve-page-data
Spec layer (orchestration.sx):
- try-client-route now handles :data pages instead of falling back to server
- New abstract primitive resolve-page-data(name, params, callback) — platform
  decides transport (HTTP, IPC, cache, etc)
- Extracted swap-rendered-content and resolve-route-target helpers

Platform layer (bootstrap_js.py):
- resolvePageData() browser implementation: fetches /sx/data/<name>, parses
  SX response, calls callback. Other hosts provide their own transport.

Server layer (pages.py):
- evaluate_page_data() evaluates :data expr, serializes result as SX
- auto_mount_page_data() mounts /sx/data/ endpoint with per-page auth
- _build_pages_sx now computes component deps for all pages (not just pure)

Test page at /isomorphism/data-test exercises the full pipeline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:46:30 +00:00
9d0cffb84d Fix special-forms.sx path resolution in container
Three levels of ../ overshot from /app/sxc/pages/ to /. Use same
two-level pattern with /app/shared fallback as _read_spec_file.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:16:21 +00:00
eee2954559 Update reference docs: fix event names, add demos, document sx-boost target
- Remove sx:afterSettle (not dispatched), rename sx:sendError → sx:requestError
- Add sx:clientRoute event (Phase 3 client-side routing)
- Add working demos for all 10 events (afterRequest, afterSwap, requestError,
  clientRoute, sseOpen, sseMessage, sseError were missing demos)
- Update sx-boost docs: configurable target selector, client routing behavior
- Remove app-specific nav logic from orchestration.sx, use sx:clientRoute event
- Pass page content deps to sx_response for component loading after server fallback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:12:38 +00:00
b9003eacb2 Fix unclosed paren in content-addressed components plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:07:42 +00:00
7229335d22 Add content-addressed components plan to sx-docs
7-phase plan: canonical serialization, CID computation, component
manifests, IPFS storage & resolution cascade, security model (purity
verification, content verification, eval limits, trust tiers),
wire format integration with prefetch system, and federated sharing
via AP component registry actors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 22:55:13 +00:00
e38534a898 Expand prefetch plan: full strategy spectrum and components+data split
Add prefetch strategies section covering the full timing spectrum:
eager bundle (initial load), idle timer (requestIdleCallback), viewport
(IntersectionObserver), mouse trajectory prediction, hover, mousedown,
and the components+data hybrid for :data pages. Add declarative
configuration via defpage :prefetch metadata and sx-prefetch attributes.
Update rollout to 7 incremental steps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 22:43:52 +00:00
daf76c3e5b Add predictive component prefetching plan to sx-docs
4-phase design: server endpoint for on-demand component defs,
SX-specced client prefetch logic (hover/viewport triggers),
boundary declarations, and bootstrap integration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 22:30:26 +00:00
dd1c1c9a3c Add routing-analyzer-data to boundary declarations
Missing declaration caused SX_BOUNDARY_STRICT crash on startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 16:12:43 +00:00
cf5e767510 Phase 3: Client-side routing with SX page registry + routing analyzer demo
Add client-side route matching so pure pages (no IO deps) can render
instantly without a server roundtrip. Page metadata serialized as SX
dict literals (not JSON) in <script type="text/sx-pages"> blocks.

- New router.sx spec: route pattern parsing and matching (6 pure functions)
- boot.sx: process page registry using SX parser at startup
- orchestration.sx: intercept boost links for client routing with
  try-first/fallback — client attempts local eval, falls back to server
- helpers.py: _build_pages_sx() serializes defpage metadata as SX
- Routing analyzer demo page showing per-page client/server classification
- 32 tests for Phase 2 IO detection (scan_io_refs, transitive_io_refs,
  compute_all_io_refs, component_pure?) + fallback/ref parity
- 37 tests for Phase 3 router functions + page registry serialization
- Fix bootstrap_py.py _emit_let cell variable initialization bug
- Fix missing primitive aliases (split, length, merge) in bootstrap_py.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 15:47:56 +00:00
631394989c Add not-prose to all code blocks to enforce stone-100 background
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 4m32s
Tailwind's prose class applies dark backgrounds to pre/code elements,
overriding the intended bg-stone-100. Adding not-prose to every code
container div across docs, specs, and examples pages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 14:35:49 +00:00
a0e39f0014 Fix bundle analyzer source display: override prose styling + add syntax highlighting
- Add not-prose class to escape Tailwind typography dark pre/code backgrounds
- Use (highlight source "lisp") for syntax-highlighted component source
- Add missing bg-blue-500 bg-amber-500 to @css annotation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 14:30:18 +00:00
55adbf6463 Fix bundle analyzer source readability: white bg, darker text
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 14:03:52 +00:00
fbfd203746 Bundle analyzer: drill-down component tree with SX source viewer
Click a page row to expand its component bundle tree. Each component
shows pure/IO badge, IO refs, dep count. Click a component to expand
its full defcomp SX source. Uses <details>/<summary> for zero-JS
expand/collapse.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:59:55 +00:00
65ed8a8941 Replace tagline with the sx identity cycle
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:43:39 +00:00
54814b4258 Update deps spec description and isomorphism roadmap for Phase 2
- deps.sx spec description now covers both Phase 1 (bundling) and Phase 2
  (IO detection, pure/IO classification, host obligation for selective
  expansion)
- Isomorphism roadmap context updated: boundary slides automatically
  based on IO detection, not future tense
- Current State section adds dependency analysis and IO detection bullets
- Phase 1 spec module note updated: 14 functions, 8 platform declarations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:38:21 +00:00
0ba7ebe349 Phase 2: IO detection & selective expansion in deps.sx
Extend the spec with IO scanning functions (scan-io-refs, transitive-io-refs,
compute-all-io-refs, component-pure?) that detect IO primitive references in
component ASTs. Components are classified as pure (no IO deps, safe for client
rendering) or IO-dependent (must expand server-side).

The partial evaluator (_aser) now uses per-component IO metadata instead of
the global _expand_components toggle: IO-dependent components expand server-
side, pure components serialize for client. Layout slot context still expands
all components for backwards compat.

Spec: 5 new functions + 2 platform interface additions in deps.sx
Host: io_refs field + is_pure property on Component, compute_all_io_refs()
Bootstrap: both sx_ref.py and sx-ref.js updated with IO functions
Bundle analyzer: shows pure/IO classification per page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:19:17 +00:00
652e7f81c8 Add Isomorphism as top-level section in sx-docs
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 4m34s
Move isomorphic architecture roadmap and bundle analyzer from Plans
into their own top-level "Isomorphism" section. The roadmap is the
default page at /isomorphism/, bundle analyzer at /isomorphism/bundle-analyzer.

Plans section retains reader macros and SX-Activity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 12:57:17 +00:00
44d5414bc6 Split boundary.sx: separate language contract from app-specific declarations
boundary.sx was mixing three concerns in one file:
- Core SX I/O primitives (the language contract)
- Deployment-specific layout I/O (app architecture)
- Per-service page helpers (fully app-specific)

Now split into three tiers:
1. shared/sx/ref/boundary.sx — core I/O only (frag, query, current-user, etc.)
2. shared/sx/ref/boundary-app.sx — deployment layout contexts (*-header-ctx, *-ctx)
3. {service}/sx/boundary.sx — per-service page helpers

The boundary parser loads all three tiers automatically. Validation error
messages now point to the correct file for each tier.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 12:41:38 +00:00
a90c8bf3fc Fix: use len (not count) in analyzer.sx — matches primitives.sx
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 12:36:13 +00:00
a06400370a Fix: use count instead of length in analyzer.sx
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 12:33:04 +00:00
9ac1d273e2 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>
2026-03-06 12:26:22 +00:00