Commit Graph

514 Commits

Author SHA1 Message Date
ece2aa225d Fix popstate and client routing when no [sx-boost] container exists
handle-popstate falls back to #main-panel when no [sx-boost] element
is found, fixing back button for apps using explicit sx-target attrs.
bindClientRouteClick also checks sx-target on the link itself.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:53:08 +00:00
ac1dc34dad Fix: pass target selector to tryClientRoute from link clicks
bindClientRouteClick was calling tryClientRoute(pathname) without the
target-sel argument. This caused resolve-route-target to return nil,
so client routing ALWAYS fell back to server fetch on link clicks.
Now finds the sx-boost ancestor and passes its target selector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:46:25 +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
f36583b620 Fix: register append!/dict-set! in PRIMITIVES after it is defined
The registrations were in the platform eval block which emits before
var PRIMITIVES = {}. Moved to core.list and core.dict primitive sections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:33:49 +00:00
6772f1141f Register append! and dict-set! as proper primitives
Previously these mutating operations were internal helpers in the JS
bootstrapper but not declared in primitives.sx or registered in the
Python evaluator. Now properly specced and available in both hosts.

Removes mock injections from cache tests — they use real primitives.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:21:17 +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
d3617ab7f3 Phase 4 complete: client data cache + plan update
- Add page data cache in orchestration.sx (30s TTL, keyed by page-name+params)
- Cache hit path: sx:route client+cache (instant render, no fetch)
- Cache miss path: sx:route client+data (fetch, cache, render)
- Fix HTMX response dep computation to include :data pages
- Update isomorphic-sx-plan.md: Phases 1-4 marked done with details,
  reorder remaining phases (continuations→Phase 5, suspense→Phase 6,
  optimistic updates→Phase 7)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:06:22 +00:00
732923a7ef Fix: auto-include router spec module when boot adapter is present
boot.sx uses parse-route-pattern from router.sx, but router was only
included as an opt-in spec module. Now auto-included when boot is in
the adapter set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:53:55 +00:00
b1f9e41027 Add unit tests for Phase 4 page data pipeline (20 tests)
Tests cover: SX wire format roundtrip for data dicts (11 tests),
kebab-case key conversion (4 tests), component dep computation for
:data pages (2 tests), and full pipeline simulation — serialize on
server, parse on client, merge into env, eval content (3 tests).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:49:08 +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
093050059d Remove debug env logging from tryClientRoute
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 22:18:59 +00:00
6a5cb31123 Debug: log env keys and params in tryClientRoute
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 22:15:20 +00:00
bcb58d340f Unknown components throw instead of rendering error box
render-dom-unknown-component now calls (error ...) instead of
creating a styled div. This lets tryEvalContent catch the error
and fall back to server fetch, instead of rendering "Unknown
component: ~name" into the page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 22:12:59 +00:00
b98a8f8c41 Try-first routing: attempt eval, fall back on failure
Remove strict deps check — for case expressions like essay pages,
deps includes ALL branches but only one is taken. Instead, just
try to eval the content. If a component is missing, tryEvalContent
catches the error and we transparently fall back to server fetch.
deps field remains in registry for future prefetching use.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 22:10:35 +00:00
14c5316d17 Add component deps to page registry, check before client routing
Each page entry now includes a deps list of component names needed.
Client checks all deps are loaded before attempting eval — if any
are missing, falls through to server fetch with a clear log message.
No bundle bloat: server sends components for the current page only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 22:06:28 +00:00
3b00a7095a Fix (not) compilation: use isSxTruthy for NIL-safe negation
NIL is a frozen sentinel object ({_nil:true}) which is truthy in JS.
(not expr) compiled to !expr, so (not nil) returned false instead of
true. Fixed to compile as !isSxTruthy(expr) which correctly handles
NIL. This was preventing client-side routing from activating.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 22:01:39 +00:00
719dfbf732 Debug: log each isGetLink condition individually
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:59:58 +00:00
5ea0f5c546 Debug: log mods.delay and isGetLink result
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:59:17 +00:00
74428cc433 Debug: log verbInfo method and url in click handler
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:58:43 +00:00
d1a47e1e52 Restore click handler logging + use logInfo for errors (SES-safe)
SES lockdown may suppress console.error. Use logInfo for error
reporting since we know it works ([sx-ref] prefix visible).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:57:44 +00:00
3d191099e0 Surface all errors: wrap event handlers in try/catch with console.error
- domAddListener wraps callbacks so exceptions always log to console
- Add "sx:route trying <url>" log before tryClientRoute call
- Remove redundant bind-event fired log (replaced with route-specific logs)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:53:54 +00:00
70cf501c49 Debug: log every bind-event click handler firing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:51:04 +00:00
2a978e6e9f Add explicit logging for route decisions in bind-event
- Log "sx:route server fetch <url>" when falling back to network
- Use console.error for eval errors (not console.warn)
- Restructure bind-event to separate client route check from &&-chain

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:44:55 +00:00
3a8ee0dbd6 Fix router.sx: use len not length (correct SX primitive name)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:38:23 +00:00
c346f525d2 Include router spec module in sx-browser.js bootstrap
parseRoutePattern was undefined because the router module
wasn't included in the build. Now passing --spec-modules router.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:37:41 +00:00
79ee3bc46e Fix page registry: process page scripts before mount scripts
The data-mount="body" script replaces the entire body content,
destroying the <script type="text/sx-pages"> tag. Moving
processPageScripts before processSxScripts ensures the page
registry is read before the body is replaced.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:35:59 +00:00
c80b5d674f Add debug logging to page registry pipeline
Server-side: log page count, output size, and first 200 chars in _build_pages_sx.
Client-side: log script tag count, text length, parsed entry count in processPageScripts.
Helps diagnose why pages: 0 routes loaded.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:31:53 +00:00
f08bd403de Remove wrong brace escaping from pages_sx
str.format() doesn't re-process braces inside substituted values,
so the escaping was producing literal doubled braces {{:name...}}
in the output, which the SX parser couldn't parse.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:26:38 +00:00
227444a026 Tighten exception handling in helpers.py
- Remove silent except around content serialization (was hiding bugs)
- Narrow cookie/request-context catches to RuntimeError
- Narrow script hash to OSError
- Log warnings for pretty-print failures instead of silent pass

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:19:26 +00:00
2660d37f9e Remove try/except around page registry build
This was silently masking the str.format() braces bug. If page
registry building fails, it should crash visibly, not serve a
broken page with 0 routes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:17:37 +00:00
d850f7c9c1 Fix page registry: escape braces for str.format()
pages_sx contains SX dict literals with {} (empty closures) which
Python's str.format() interprets as positional placeholders, causing
a KeyError that was silently caught. Escape braces before formatting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:16:35 +00:00
bc9d9e51c9 Log page registry build errors instead of silently swallowing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:14:19 +00:00
eb70e7237e Log route count on boot and no-match on route attempts
Shows "pages: N routes loaded" at startup and
"sx:route no match (N routes) /path" when no route matches,
so we can see if routes loaded and why matching fails.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:10:24 +00:00
a7d09291b8 Add version logging and route decision logging to sx-browser
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>
2026-03-06 21:05:39 +00:00
2d5096be6c Add console logging for client-side routing decisions
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>
2026-03-06 20:43:27 +00:00
f70861c175 Try client-side routing for all sx-get link clicks, not just boost links
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>
2026-03-06 20:31:23 +00:00
78c3ff30dd Wrap index SX response in #main-panel section
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>
2026-03-06 19:59:10 +00:00
756162b63f Fix test dashboard SX swap targets for partial responses
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>
2026-03-06 19:49:27 +00:00
0385be0a0d Fix /results polling: use sx_response() for SX wire format
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m56s
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>
2026-03-06 19:39:55 +00:00
1e52bb33a6 Fix test dashboard: return SX wire format for SX-Request on index route
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 3m43s
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>
2026-03-06 17:55:23 +00:00
a8e61dd0ea Merge specced eval-cond/process-bindings from render.sx
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 4m18s
2026-03-06 16:58:58 +00:00
20ac0fe948 Spec eval-cond and process-bindings in render.sx (remove platform implementations)
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>
2026-03-06 16:58:53 +00:00
2aa0f1d010 Merge evalCond scheme-style fix
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 3m15s
2026-03-06 16:49:51 +00:00
a2d0a8a0fa Fix evalCond in HTML/DOM renderers: handle scheme-style cond clauses
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>
2026-03-06 16:49:42 +00:00