boot-init prints SX_VERSION (build timestamp) to console on startup.
tryClientRoute logs why it falls through: has-data, no content, eval
failed, #main-panel not found. tryEvalContent logs the actual error.
Added logWarn platform function.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
tryClientRoute now logs why it falls through: has-data, no content,
eval failed, or #main-panel not found. tryEvalContent logs the actual
error on catch. Added logWarn platform function (console.warn).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
bind-event now checks tryClientRoute before executeRequest for GET
clicks on links. Previously only boost links (inside [sx-boost]
containers) attempted client routing — explicit sx-get links like
~nav-link always hit the network. Now essay/doc nav links render
client-side when possible.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All nav links use sx-select="#main-panel" to extract content from
responses. The index partial must include this wrapper so the select
finds it, matching the pattern used by test-detail-section.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Filter cards: target #test-results (the actual response container)
instead of sx-select #main-panel (not present in partial response).
Back link: use innerHTML swap into #main-panel (no sx-select needed).
Results route: use sx_response() for correct content-type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The /results endpoint returns SX wire format but was sending it with
content-type text/html. The SX engine couldn't process it, so raw
s-expressions appeared as text and the browser tried to resolve
quoted strings like "a.jpg" as URLs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Filter card links (/?filter=failed) were blanking the page because the
index route always returned full HTML, even for SX-Request. Now returns
sx_response() partial like test_detail already does.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
eval-cond and process-bindings were hand-written platform JS in
bootstrap_js.py rather than specced in .sx files. This violated the
SX host architecture principle. Now specced in render.sx as shared
render adapter helpers, bootstrapped to both JS and Python.
eval-cond handles both scheme-style ((test body) ...) and clojure-style
(test body test body ...) cond clauses. Returns unevaluated body
expression for the adapter to render in its own mode.
process-bindings evaluates let-binding pairs and returns extended env.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The platform evalCond helper (used by render-to-html and render-to-dom)
only handled clojure-style (test body test body ...) but components use
scheme-style ((test body) (test body) ...). This caused "Not callable:
true" errors when rendering cond with nested clause pairs, breaking the
test dashboard and any page using scheme-style cond.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The test app's bp/dashboard/routes.py imports from sxc.pages.renders
but the Dockerfile wasn't copying the sxc directory into the image.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The SX parser produces native Python dicts for {:key val} syntax, but
both JSEmitter and PyEmitter had no dict case in emit() — falling through
to str(expr) which output raw AST. This broke client-side routing because
process-page-scripts used {"parsed" (parse-route-pattern ...)} and the
function call was emitted as a JS array of Symbols instead of an actual
function call.
Add _emit_native_dict() to both bootstrappers + 8 unit tests.
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>
The spec classifies components as pure vs IO-dependent. Each host's
async partial evaluator must act on this: expand IO-dependent server-
side, serialize pure for client. This is host infrastructure, not SX
semantics — documented as a contract in the spec.
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 files use define-page-helper which isn't an SX eval form —
they're parsed by boundary_parser.py. Exclude them from load_sx_dir()
to prevent EvalError on startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In Docker, each service's sx/ dir is copied directly to /app/sx/,
not /app/{service}/sx/. Add fallback search for /app/sx/boundary.sx
alongside the dev glob pattern.
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>
Add SX_USE_REF=1 to production docker-compose.yml so all services
use the spec-bootstrapped evaluator, renderer, and deps analysis.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
deps.sx is now a spec module that both bootstrap_py.py and bootstrap_js.py
can include via --spec-modules deps. Platform functions (component-deps,
component-set-deps!, component-css-classes, env-components, regex-find-all,
scan-css-classes) implemented natively in both Python and JS.
- Fix deps.sx: env-get-or → env-get, extract nested define to top-level
- bootstrap_py.py: SPEC_MODULES, PLATFORM_DEPS_PY, mangle entries, CLI arg
- bootstrap_js.py: SPEC_MODULES, PLATFORM_DEPS_JS, mangle entries, CLI arg
- Regenerate sx_ref.py and sx-ref.js with deps module
- deps.py: thin dispatcher (SX_USE_REF=1 → bootstrapped, else fallback)
- scan_components_from_sx now returns ~prefixed names (consistent with spec)
Verified: 541 Python tests pass, JS deps tested with Node.js, both code
paths (fallback + bootstrapped) produce identical results.
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>
Spec (eval.sx, primitives.sx):
- Named let: (let loop ((i 0)) body) — self-recursive lambda with TCO
- letrec: mutually recursive local bindings with closure patching
- dynamic-wind: entry/exit guards with wind stack for future continuations
- eq?/eqv?/equal?: identity, atom-value, and deep structural equality
Implementation (evaluator.py, async_eval.py, primitives.py):
- Both sync and async evaluators implement all four forms
- 33 new tests covering all forms including TCO at 10k depth
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>