Commit Graph

411 Commits

Author SHA1 Message Date
5aa13a99d1 Wire SX_USE_REF=1 switching through all route intermediaries
jinja_bridge, helpers, handlers, query_executor now conditionally
import from ref/sx_ref and ref/async_eval_ref when SX_USE_REF=1.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 22:17:26 +00:00
7982a07f94 Add adapter-sx.sx transpilation, async wrapper, and SX_USE_REF switching
- Transpile adapter-sx.sx (aser) alongside adapter-html.sx for SX wire format
- Add platform functions: serialize, escape_string, is_special_form, is_ho_form,
  aser_special (with proper control-flow-through-aser dispatch)
- SxExpr wrapping prevents double-quoting in aser output
- async_eval_ref.py: async wrapper with I/O primitives, RequestContext,
  async_render, async_eval_to_sx, async_eval_slot_to_sx
- SX_USE_REF=1 env var switches shared.sx imports to transpiled backend
- 68 comparison tests (test_sx_ref.py), 289 total tests passing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 22:05:35 +00:00
4534fb9fee Add bootstrap_py.py: transpile SX spec to Python evaluator
Mirrors bootstrap_js.py pattern — reads the .sx reference spec files
(eval.sx, render.sx, adapter-html.sx) and emits a standalone Python
evaluator module (sx_ref.py) that can be compared against the
hand-written evaluator.py / html.py.

Key transpilation techniques:
- Nested IIFE lambdas for let bindings: (lambda a: body)(val)
- _sx_case helper for case/type dispatch
- Short-circuit and/or via Python ternaries
- Functions with set! emitted as def with _cells dict for mutation
- for-each with inline fn emitted as Python for loops
- Statement-level cond emitted as if/elif/else chains

Passes 27/27 comparison tests against hand-written evaluator.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 19:32:01 +00:00
9cde15c3ce Skip DB registration in standalone mode (fixes sx-web.org startup)
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 4m5s
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>
2026-03-05 16:53:05 +00:00
6a98c39937 Use existing Caddy for sx-web.org routing
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m44s
Single Caddy instance handles all domains. sx-web stack joins
externalnet instead of running its own Caddy (port conflict).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:41:36 +00:00
60ed828e0e Merge branch 'macros'
# Conflicts:
#	blog/bp/post/admin/routes.py
#	events/sxc/pages/calendar.py
#	events/sxc/pages/entries.py
#	events/sxc/pages/slots.py
#	events/sxc/pages/tickets.py
2026-03-05 16:40:06 +00:00
0f4520d987 Add standalone mode for sx-web.org deployment
- 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>
2026-03-05 16:39:21 +00:00
5fff83ae79 Add header and event detail pages, fix copyright, rename essay
- Detail pages for all 18 HTTP headers with descriptions, example usage,
  direction badges (request/response/both), and live demos for SX-Prompt,
  SX-Trigger, SX-Retarget
- Detail pages for all 10 DOM events with descriptions, example usage,
  and live demos for beforeRequest, afterSettle, responseError,
  validationFailed
- Header and event table rows now link to their detail pages
- Fix copyright symbol on home page (was literal \u00a9, now actual ©)
- Rename "Godel, Escher, Bach" essay to "Strange Loops" with updated summary
- Remove duplicate script injection from bootstrapper page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:25:15 +00:00
1797bd4b16 Add Bootstrappers section, essays index, specs prose, layout fixes
- 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>
2026-03-05 16:12:38 +00:00
436848060d Merge branch 'worktree-sx-loop-cleanup' into macros
# Conflicts:
#	blog/sx/sx_components.py
#	federation/sx/profile.sx
#	federation/sx/sx_components.py
#	orders/sx/sx_components.py
2026-03-05 16:08:36 +00:00
c1ad6fd8d4 Replace Python sx_call loops with data-driven SX defcomps using map
Move rendering logic from Python for-loops building sx_call strings into
SX defcomp components that use map/lambda over data dicts. Python now
serializes display data into plain dicts and passes them via a single
sx_call; the SX layer handles iteration and conditional rendering.

Covers orders (rows, items, calendar, tickets), federation (timeline,
search, actors, profile activities), and blog (cards, pages, filters,
snippets, menu items, tag groups, page search, nav OOB).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:03:29 +00:00
cea009084f Fix sx-browser.js navigation bugs: CSS tracking meta tag and stale verb info
Two fixes for sx-browser.js (spec-compiled) vs sx.js (hand-written):

1. CSS meta tag mismatch: initCssTracking read meta[name="sx-css-hash"]
   but the page template uses meta[name="sx-css-classes"]. This left
   _cssHash empty, causing the server to send ALL CSS as "new" on every
   navigation, appending duplicate rules that broke Tailwind responsive
   ordering (e.g. menu bar layout).

2. Stale verb info after morph: execute-request used captured verbInfo
   from bind time. After morph updated element attributes (e.g. during
   OOB nav swap), click handlers still fired with old URLs. Now re-reads
   verb info from the element first, matching sx.js behavior.

Also includes: render-expression dispatch in eval.sx, NIL guard for
preload cache in bootstrap_js.py, and helpers.py switched to
sx-browser.js.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 15:28:56 +00:00
af77fc32c7 Move spec metadata from Python to SX, add orchestration to spec viewer
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>
2026-03-05 13:34:58 +00:00
d696735f95 Merge branch 'worktree-sx-meta-eval' into macros
# Conflicts:
#	shared/static/scripts/sx-browser.js
2026-03-05 13:20:36 +00:00
bea071a039 Add CSSX and boot adapters to SX spec (style dictionary + browser lifecycle)
- cssx.sx: on-demand CSS style dictionary (variant splitting, atom resolution, content-addressed hashing, style merging)
- boot.sx: browser boot lifecycle (script processing, mount/hydrate/update, component caching, head element hoisting)
- bootstrap_js.py: platform JS for cssx (FNV-1a hash, regex, CSS injection) and boot (localStorage, cookies, DOM mounting)
- Rebuilt sx-browser.js (136K) and sx-ref.js (148K) with all adapters

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 13:20:29 +00:00
1c7346ab37 Resolve merge conflict in generated sx-browser.js 2026-03-05 13:04:44 +00:00
d07a408c89 Merge branch 'worktree-sx-meta-eval' into macros 2026-03-05 13:04:35 +00:00
eac0fce8f7 Split orchestration from engine into separate adapter
engine.sx now contains only pure logic: parsing, morph, swap, headers,
retry, target resolution, etc. orchestration.sx contains the browser
wiring: request execution, trigger binding, SSE, boost, post-swap
lifecycle, and init. Dependency is one-way: orchestration → engine.

Bootstrap compiler gains "orchestration" as a separate adapter with
deps on engine+dom. Engine-only builds get morph/swap without the
full browser runtime.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 13:04:27 +00:00
639f96fe6b Merge branch 'worktree-sx-meta-eval' into macros 2026-03-05 12:54:48 +00:00
d4b23aae4c Add engine orchestration to SX spec (fetch, triggers, swap, SSE, history, init)
29 orchestration functions written in SX + adapter style: request pipeline
(execute-request, do-fetch, handle-fetch-success), trigger binding (poll,
intersect, load, revealed, event), post-swap processing, OOB swaps, boost,
SSE, inline handlers, preload, history/popstate, and engine-init. Platform
JS implementations in bootstrap_js.py for all browser-specific operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 12:54:39 +00:00
3197022299 Restructure Specs section into Architecture, Core, and Adapters pages
- 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>
2026-03-05 11:55:59 +00:00
7c99002345 Merge sx-browser.js into macros 2026-03-05 11:52:06 +00:00
157a32b426 Add sx-browser.js — browser-only build from SX spec (dom+engine)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 11:52:03 +00:00
ab50fb5f56 Merge core+adapter SX ref restructure into macros 2026-03-05 11:50:04 +00:00
daeecab310 Restructure SX ref spec into core + selectable adapters
Split monolithic render.sx into core (tag registries, shared utils) plus
four adapter .sx files: adapter-html (server HTML strings), adapter-sx
(SX wire format), adapter-dom (browser DOM nodes), and engine (SxEngine
triggers, morphing, swaps). All adapters written in s-expressions with
platform interface declarations for JS bridge functions.

Bootstrap compiler now accepts --adapters flag to emit targeted builds:
  -a html        → server-only (1108 lines)
  -a dom,engine  → browser-only (1634 lines)
  -a html,sx     → server with SX wire (1169 lines)
  (default)      → all adapters (1800 lines)

Fixes: keyword arg i-counter desync in reduce across all adapters,
render-aware special forms (let/if/when/cond/map) in HTML adapter,
component children double-escaping, ~prefixed macro dispatch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 11:49:44 +00:00
7ecbf19c11 Add Specs section, Reflexive Web essay, fix highlight and dev caching
- 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>
2026-03-05 11:49:05 +00:00
6fa843016b Gate server-side component expansion with contextvar, fix nth arg order, add GEB essay and manifesto links
- 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>
2026-03-05 11:03:50 +00:00
4a515f1a0d Add canonical SX language spec reference to CLAUDE.md
Points AI and developers to shared/sx/ref/ as the authoritative
source for SX semantics — eval rules, type system, rendering modes,
component calling convention, and platform interface.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:36:22 +00:00
824396c7b0 Merge branch 'worktree-sx-meta-eval' into macros 2026-03-05 10:23:45 +00:00
dea4f52454 Expand known components server-side in _aser to fix nested highlight calls
_aser previously serialized all ~component calls for client rendering.
Components whose bodies call Python-only functions (e.g. highlight) would
fail on the client with "Undefined symbol". Now _aser expands components
that are defined in the env via _aser_component, producing SX wire format
with tag-level bodies inlined. Unknown components still serialize as-is.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:20:24 +00:00
a9526c4fa1 Update reference SX spec to match sx.js macros branch (CSSX, dict literals, new primitives)
- eval.sx: Add defstyle, defkeyframes, defhandler special forms; add ho-for-each
- parser.sx: Add dict {...} literal parsing and quasiquote/unquote sugar
- primitives.sx: Add parse-datetime, split-ids, css, merge-styles primitives
- render.sx: Add StyleValue handling, SVG filter elements, definition forms in render, fix render-to-html to handle HTML tags directly
- bootstrap_js.py: Add StyleValue type, buildKeyframes, isEvery platform helper, new primitives (format-date, parse-datetime, split-ids, css, merge-styles), dict/quasiquote parser, expose render functions as primitives
- sx-ref.js: Regenerated — 132/132 tests passing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:17:28 +00:00
4a3a510a23 Merge branch 'macros' into worktree-sx-meta-eval 2026-03-05 10:03:15 +00:00
e1ae81f736 Add bootstrap compiler: reference SX spec → JavaScript
bootstrap_js.py reads the reference .sx specification (eval.sx, render.sx)
and transpiles the defined evaluator functions into standalone JavaScript.
The output sx-ref.js is a fully functional SX evaluator bootstrapped from
the s-expression spec, comparable against the hand-written sx.js.

Key features:
- JSEmitter class transpiles SX AST → JS (fn→function, let→IIFE, cond→ternary, etc.)
- Platform interface (types, env ops, primitives) implemented as native JS
- Post-transpilation fixup wraps callLambda to handle both Lambda objects and primitives
- 93/93 tests passing: arithmetic, strings, control flow, closures, HO forms,
  components, macros, threading, dict ops, predicates

Fixed during development:
- Bool before int isinstance check (Python bool is subclass of int)
- SX NIL sentinel detection (not Python None)
- Cond style detection (determine Scheme vs Clojure once, not per-pair)
- Predicate null safety (x != null instead of x && to avoid 0-as-falsy in SX)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 09:58:48 +00:00
8c69e329e0 Fix dict kwarg evaluation in renderComponentDOM, no-cache static in dev
Dict values (e.g. {:X-CSRFToken csrf}) passed as component kwargs were
not being evaluated through sxEval — symbols stayed unresolved in the DOM.
Also add Cache-Control: no-cache headers for /static/ in dev mode so
browser always fetches fresh JS/CSS without needing hard refresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 09:37:07 +00:00
235428628a Add reference SX evaluator written in s-expressions
Meta-circular evaluator: the SX language specifying its own semantics.
A thin bootstrap compiler per target (JS, Python, Rust) reads these
.sx files and emits a native evaluator.

Files:
- eval.sx: Core evaluator — type dispatch, special forms, TCO trampoline,
  lambda/component/macro invocation, higher-order forms
- primitives.sx: Declarative specification of ~80 built-in pure functions
- render.sx: Three rendering modes (DOM, HTML string, SX wire format)
- parser.sx: Tokenizer, parser, and serializer specification

Platform-specific concerns (DOM ops, async I/O, HTML emission) are
declared as interfaces that each target implements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 09:31:40 +00:00
64aa417d63 Replace JSON sx-headers with SX dict expressions, fix blog like component
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m6s
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>
2026-03-05 09:25:28 +00:00
2a04aaad5e Fix market header ImportError and sx docs menu bar 3 OOB insertion
- 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>
2026-03-05 08:50:48 +00:00
51ebf347ba Move events/market/blog composition from Python to .sx defcomps (Phase 9)
Continues the pattern of eliminating Python sx_call tree-building in favour
of data-driven .sx defcomps. POST/PUT/DELETE routes now pass plain data
(dicts, lists, scalars) and let .sx handle iteration, conditionals, and
layout via map/let/when/if. Single response components wrap OOB swaps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 08:17:09 +00:00
1d59023571 Move events composition from Python to .sx defcomps (Phase 9)
Convert all 14 events page helpers from returning sx_call() strings
to returning data dicts. Defpage expressions compose SX components
with data bindings using map/fn/if/when.

Complex sub-panels (entry tickets config, buy form, posts panel,
options buttons, entry nav menu) returned as SxExpr from existing
render functions which remain for HTMX handler use.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 02:30:46 +00:00
877e776977 Move market composition from Python to .sx defcomps (Phase 8)
Convert 5 market page helpers from returning sx_call() strings to
returning data dicts. Defpages now use :data + :content pattern.
Admin panel uses inline map/fn for CRUD item composition.
Removed market-admin-content helper (placeholder inlined in defpage).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 02:10:55 +00:00
1560207097 Move blog composition from Python to .sx defcomps (Phase 7)
Convert all 8 blog page helpers from returning sx_call() strings to
returning data dicts. Defpages now use :data + :content pattern:
helpers load data, SX composes markup. Newsletter options and footer
badges composed inline with map/fn in defpage expressions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 02:10:55 +00:00
aed4c03537 Fix highlight undefined symbol by expanding component results server-side
When defpage content expressions use case/if branches that resolve to
component calls (e.g. `(case slug "intro" (~docs-intro-content) ...)`),
_aser serializes them for the client. Components containing Python-only
helpers like `highlight` then fail with "Undefined symbol" on the client.

Add _maybe_expand_component_result() which detects when the evaluated
result (SxExpr or string) is a component call starting with "(~" and
re-parses + expands it through async_eval_slot_to_sx server-side.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 01:52:45 +00:00
dfccd113fc Move sx docs page helpers from Python to pure SX composition (Phase 6)
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>
2026-03-05 01:49:04 +00:00
b15025befd Fix highlight undefined symbol by expanding component strings server-side
Page helpers returning SX component call strings (e.g. "(~docs-intro-content)")
were sent to the client unexpanded. Components containing Python-only helpers
like `highlight` then failed with "Undefined symbol" on the client. Now
async_eval_slot_to_sx re-parses and expands these strings server-side.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 01:45:04 +00:00
0144220427 Move cart composition from Python to .sx defcomps (Phase 5)
- render_orders_rows: Python loop building row-pairs → ~cart-orders-rows-content
  defcomp that maps over order data and handles pagination sentinel
- render_checkout_error_page: conditional order badge composition →
  ~cart-checkout-error-from-data defcomp
- Remove unused SxExpr import

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 01:27:54 +00:00
c71ca6754d Move blog composition from Python to .sx defcomps (Phase 4)
- Settings form: ~135 lines raw HTML → ~blog-settings-form-content defcomp
- Data introspection: ~110 lines raw HTML → ~blog-data-table-content with
  recursive ~blog-data-model-content defcomps, Python extracts ORM data only
- Preview: sx_call composition → ~blog-preview-content defcomp
- Entries browser: ~65 lines raw HTML → ~blog-entries-browser-content +
  ~blog-calendar-browser-item + ~blog-associated-entries-from-data defcomps
- Editor panels: sx_call composition in both helpers.py and renders.py →
  ~blog-editor-content and ~blog-edit-content composition defcomps
- renders.py: 178 → 25 lines (87% reduction)
- routes.py _render_associated_entries: data extraction → single sx_call

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 01:24:37 +00:00
e81d77437e Move market composition from Python to .sx defcomps (Phase 3)
Python sxc/pages/ functions no longer build nested sx_call chains or
reference leaf component names. Instead they extract data (URLs, prices,
CSRF, cart state) and call a single top-level composition defcomp with
pure data values. The .sx defcomps handle all component-to-component
wiring, iteration (map), and conditional rendering.

New .sx composition defcomps:
- headers.sx: ~market-header-from-data, ~market-desktop-nav-from-data,
  ~market-product-header-from-data, ~market-product-admin-header-from-data
- prices.sx: ~market-prices-header-from-data, ~market-card-price-from-data
- navigation.sx: ~market-mobile-nav-from-data
- cards.sx: ~market-product-cards-content, ~market-card-from-data,
  ~market-cards-content, ~market-landing-from-data
- detail.sx: ~market-product-detail-from-data, ~market-detail-gallery-from-data,
  ~market-detail-info-from-data
- meta.sx: ~market-product-meta-from-data
- filters.sx: ~market-desktop-filter-from-data, ~market-mobile-chips-from-data,
  ~market-mobile-filter-content-from-data, plus 6 sub-composition defcomps

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 01:11:57 +00:00
36a0bd8577 Move sx docs markup from Python to .sx files (Phase 2)
Migrate ~2,500 lines of SX markup from Python string concatenation in
essays.py to proper .sx defcomp definitions:

- docs-content.sx: 8 defcomps for docs pages (intro, getting-started,
  components, evaluator, primitives, css, server-rendering, home)
- protocols.sx: 6 defcomps for protocol documentation pages
- essays.sx: 9 essay defcomps (pure content, no params)
- examples.sx: template defcomp receiving data values, calls highlight
  internally — Python passes raw code strings, never SX
- reference.sx: 6 defcomps for data-driven reference pages

essays.py reduced from 2,699 to 619 lines. Docs/protocol/essay
functions become one-liners returning component names. Example functions
use sx_call to pass data values to the template. Reference functions
pass data-built component trees via SxExpr.

renders.py: removed _code, _example_code, _placeholder,
_clear_components_btn (now handled by .sx templates).
helpers.py: removed inline hero code building, uses ~sx-home-content.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 00:22:17 +00:00
4298d5be16 Fix sx docs pages leaking raw s-expressions and missing sub-row
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>
2026-03-04 23:02:23 +00:00
1077fae815 Merge branch 'worktree-sx-layout-conversion' into macros
# Conflicts:
#	blog/sxc/pages/layouts.py
#	cart/sxc/pages/layouts.py
#	events/sxc/pages/helpers.py
#	events/sxc/pages/layouts.py
#	market/sxc/pages/layouts.py
#	sx/sxc/pages/layouts.py
2026-03-04 22:25:52 +00:00