- Remove old raw! layout components (~app-head, ~app-layout, ~oob-response,
~header-row, ~menu-row, ~oob-header, ~header-child) from layout.sexp
- Convert nav-tree fragment from Jinja HTML to sexp source, fixing the
"Unexpected character: ." parse error caused by HTML leaking into sexp
- Add _as_sexp() helper to safely coerce HTML fragments to ~rich-text
- Fix federation/sexp/search.sexpr extra closing paren
- Remove dead _html() wrappers from blog and account sexp_components
- Remove stale render import from cart sexp_components
- Add dev_watcher.py to auto-reload on .sexp/.sexpr/.js/.css changes
- Add test_parse_all.py to parse-check all 59 sexpr/sexp files
- Fix test assertions for sx- attribute prefix (was hx-)
- Add sexp.js version logging for cache debugging
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Declarative relation registry via defrelation s-expressions with
cardinality enforcement (one-to-one, one-to-many, many-to-many),
registry-aware relate/unrelate/can-relate API endpoints, generic
container-nav fragment, and relation-driven UI components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 9 new shared s-expression components (cart-mini, auth-menu,
account-nav-item, calendar-entry-nav, calendar-link-nav, market-link-nav,
post-card, base-shell, error-page) and wire them into all fragment route
handlers. 404/403 error pages now render entirely via s-expressions as a
full-page proof-of-concept, with Jinja fallback on failure.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>