- 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>
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>
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>
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>
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>
- 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>
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>
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>
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>
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>
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>
Demonstrates Phase 1 dep analysis in action: computes per-page component
bundles for all sx-docs pages using the deps.sx transitive closure
algorithm, showing needed vs total components with visual progress bars.
- New page at /plans/bundle-analyzer with Python data helper
- New components: ~bundle-analyzer-content, ~analyzer-stat, ~analyzer-row
- Linked from Phase 1 section and Plans nav
- Added sx/sx/ to tailwind content paths
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add deps.sx to the spec navigator in sx-docs (nav-data, specs page).
Update isomorphic architecture plan to show Phase 1 as complete with
link to the canonical spec at /specs/deps.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire web applications as content-addressed SX on IPFS — no server,
no DNS, no hosting, no deployment pipeline. Server becomes an optional
IO provider, not an application host. The application is the content.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reframe Phase 6 from "ActivityPub but SX" to the full vision: a new web
where content, components, parsers, transforms, server/client logic, and
media all share one executable format on IPFS, sandboxed by boundary
enforcement, with Bitcoin-anchored provenance. Updated context section
and nav summary to match.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reader Macros: # dispatch for datum comments (#;), raw strings (#|...|),
and quote shorthand (#').
SX-Activity: ActivityPub federation with SX wire format, IPFS-backed
component registry, content-addressed media, Bitcoin-anchored provenance.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(index-of s needle from?) returns first index of needle in s, or -1.
Optional start offset. Specced in primitives.sx, implemented in both
hand-written primitives.py and bootstrapper templates, rebootstrapped.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New top-level nav section at /plans/ with the 6-phase isomorphic
architecture plan: component distribution, smart boundary, SPA routing,
client IO bridge, streaming suspense, and full isomorphism.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Parses special-forms.sx spec into categorized form cards with syntax,
description, tail-position info, and highlighted examples. Follows the
same pattern as the Primitives page: Python helper returns structured
data, .sx components render it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Both bootstrappers (JS + Python) now gate shift/reset behind --extensions
continuations flag. Without it, using reset/shift errors at runtime.
- JS bootstrapper: extracted Continuation/ShiftSignal types, sfReset/sfShift,
continuation? primitive, and typeOf handling into CONTINUATIONS_JS constant.
Extension wraps evalList, aserSpecial, and typeOf post-transpilation.
- Python bootstrapper: added special-forms.sx validation cross-check against
eval.sx dispatch, warns on mismatches.
- Added shared/sx/ref/special-forms.sx: 36 declarative form specs with syntax,
docs, tail-position, and examples. Used by bootstrappers for validation.
- Added ellipsis (...) support to both parser.py and parser.sx spec.
- Updated continuations essay to reflect optional extension architecture.
- Updated specs page and nav with special-forms.sx entry.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bootstrap shift/reset to both Python and JS targets. The implementation
uses exception-based capture with re-evaluation: reset wraps in try/catch
for ShiftSignal, shift raises to the nearest reset, and continuation
invocation pushes a resume value and re-evaluates the body.
- Add Continuation type and _ShiftSignal to shared/sx/types.py
- Add sf_reset/sf_shift to hand-written evaluator.py
- Add async versions to async_eval.py
- Add shift/reset dispatch to eval.sx spec
- Bootstrap to Python: FIXUPS_PY with sf_reset/sf_shift, regenerate sx_ref.py
- Bootstrap to JS: Continuation/ShiftSignal types, sfReset/sfShift in fixups
- Add continuation? primitive to both bootstrappers and primitives.sx
- Allow callables (including Continuation) in hand-written HO map
- 44 unit tests (22 per evaluator) covering: passthrough, abort, invoke,
double invoke, predicate, stored continuation, nested reset, practical patterns
- Update continuations essay to reflect implemented status with examples
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Optional bolt-on extensions to the SX spec. continuations.sx defines
delimited continuations for all targets. callcc.sx defines full call/cc
for targets where it's native (Scheme, Haskell). Shared continuation
type if both are loaded. Wired into specs section of sx-docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Documents the boundary enforcement model: three tiers, boundary types,
runtime validation, the SX-in-Python rule, and the multi-language story.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add boundary.sx declaring all 34 I/O primitives, 32 page helpers, and 9
allowed boundary types. Runtime validation in boundary.py checks every
registration against the spec — undeclared primitives/helpers crash at
startup with SX_BOUNDARY_STRICT=1 (now set in both dev and prod).
Key changes:
- Move 5 I/O-in-disguise primitives (app-url, asset-url, config,
jinja-global, relations-from) from primitives.py to primitives_io.py
- Remove duplicate url-for/route-prefix from primitives.py (already in IO)
- Fix parse-datetime to return ISO string instead of raw datetime
- Add datetime→isoformat conversion in _convert_result at the edge
- Wrap page helper return values with boundary type validation
- Replace all SxExpr(f"...") patterns with sx_call() or _sx_fragment()
- Add assert declaration to primitives.sx
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The sx app is stateless — no database needed. In standalone mode
(SX_STANDALONE=true), the factory now skips register_db() so the app
doesn't crash trying to connect to a non-existent PostgreSQL.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SX_STANDALONE=true env var: no OAuth, no root header, no cross-service
fragments. Same image runs in both rose-ash cooperative and standalone.
- Factory: added no_oauth parameter to create_base_app()
- Standalone layout defcomps skip ~root-header-auto/~root-mobile-auto
- Fixed Dockerfile: was missing sx/sx/ component directory copy
- CI: deploys sx-web swarm stack on main branch when sx changes
- Stack config at ~/sx-web/ (Caddy → sx_docs, Redis)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New Bootstrappers top-level section with overview index and JS bootstrapper
page that runs bootstrap_js.py and displays both source and generated output
with live script injection (full page load, not SX navigation)
- Essays section: index page with linked cards and summaries, sx-sucks moved
to end of nav, removed "grand tradition" line
- Specs: English prose descriptions alongside all canonical .sx specs, added
Boot/CSSX/Browser spec files to architecture page
- Layout: menu bar nav items wrap instead of overflow, baseline alignment
between label and nav options
- Homepage: added copyright line
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Spec file registry (slugs, filenames, titles, descriptions) now lives in
nav-data.sx as SX data definitions. Python helper reduced to pure file I/O
(read-spec-file). Architecture page updated with engine/orchestration split
and dependency graph.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Architecture intro page explaining the spec's two-layer design
(core language + selectable adapters) with dependency graph
- Split specs into Core (parser, eval, primitives, render) and
Adapters (DOM, HTML, SX wire, SxEngine) overview pages
- Add individual detail pages for all adapter and engine specs
- Update nav with Architecture landing, Core, Adapters, and all
individual spec file links
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix highlight() returning SxExpr so syntax-highlighted code renders
as DOM elements instead of leaking SX source text into the page
- Add Specs section that reads and displays canonical SX spec files
from shared/sx/ref/ with syntax highlighting
- Add "The Reflexive Web" essay on SX becoming a complete LISP with
AI as native participant
- Change logo from (<x>) to (<sx>) everywhere
- Unify all backgrounds to bg-stone-100, center code blocks
- Skip component/style cookie cache in dev mode so .sx edits are
visible immediately on refresh without clearing localStorage
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add _expand_components contextvar so _aser only expands components
during page slot evaluation (fixes highlight on examples, avoids
breaking fragment responses)
- Fix nth arg order (nth coll n) in docs.sx, examples.sx (delete-row,
edit-row, bulk-update)
- Add "Godel, Escher, Bach and SX" essay with Wikipedia links
- Update SX Manifesto: new authors, Wikipedia links throughout,
remove Marx/Engels link
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
sx-headers attributes now use native SX dict format {:key val} instead of
JSON strings. Eliminates manual JSON string construction in both .sx files
and Python callers.
- sx.js: parse sx-headers/sx-vals as SX dict ({: prefix) with JSON fallback,
add _serializeDict for dict→attribute serialization, fix verbInfo scope in
_doFetch error handler
- html.py: serialize dict attribute values via SX serialize() not str()
- All .sx files: {:X-CSRFToken csrf} replaces (str "{\"X-CSRFToken\": ...}")
- All Python callers: {"X-CSRFToken": csrf} dict replaces f-string JSON
- Blog like: extract ~blog-like-toggle, fix POST returning wrong component,
fix emoji escapes in .sx (parser has no \U support), fix card :hx-headers
keyword mismatch, wrap sx_content in SxExpr for evaluation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- market/sx/layouts.sx: Update ~market-header-auto macro to build nav
from data fields via ~market-desktop-nav-from-data instead of
expecting pre-built "desktop-nav" SxExpr (removed in Phase 9)
- shared/sx/primitives_io.py: Import _market_header_data instead of
deleted _desktop_category_nav_sx, return individual data fields
- sx/sx/layouts.sx: Fix ~sx-section-layout-oob to use ~oob-header-sx
for inserting sub-row into always-existing container div
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Nav data, section nav, example content, reference table builders, and
all slug dispatch now live in .sx files. Python helpers reduced to
data-only returns (highlight, primitives-data, reference-data,
attr-detail-data). Deleted essays.py and utils.py entirely.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three issues fixed:
- async_eval_slot_to_sx (and async_eval_to_sx) was calling serialize()
on plain strings returned by page helpers, quoting them as literals
instead of treating them as sx source. Added str check to wrap
directly in SxExpr.
- _render_to_sx_with_env passed layout kwargs only as env free
variables, but _aser_component defaults all declared params to NIL
regardless of env. Now builds the AST with extra_env entries as
keyword args so they bind through normal param mechanism.
- _nav_items_sx returned plain str; changed to SxExpr so nav fragments
serialize unquoted when passed as layout kwargs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>