The kernel is no longer a blind refetch pipe. Each context entry has:
{ data, status: idle|loading|success|error, error }
registerContext() returns { getState, subscribe, refetch, unregister }.
Adapters subscribe to state changes via callbacks. The kernel does
the fetch and notifies subscribers with the new state.
React adapter uses useSyncExternalStore for tear-free reads.
Vue adapter uses ref + subscribe callback.
Svelte adapter uses readable store backed by kernel subscription.
All three adapters also get:
- Mutation hooks with { mutate, isPending, error } (fixes H5)
- Vue: onServerPrefetch for Nuxt SSR (fixes M9)
- Svelte: readable store auto-cleans up on unsubscribe (fixes H9)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
H3: mizanFetch retries 2x on server errors (5xx) and network
failures. 200ms/400ms backoff. Mutations NOT retried (not idempotent).
H6: refreshContext now uses GET /ctx/<name>/ instead of POST /call/.
Context reads go to the context endpoint, not the mutation endpoint.
H11: Python cache key derivation normalizes True→"true",
False→"false", None→"null" for cross-language HMAC consistency
with JavaScript's String() behavior.
H13: Forms isValid now checks that all required fields have been
touched, not just that touched fields have no errors.
M11: execute_function return type updated to include HttpResponseBase
for view-path functions.
M18: registerContext cleanup uses ?. instead of ! to prevent crash
if Map was cleared (already fixed in H2 commit but documenting).
373 Django + 33 React tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
C1+C7: Cache purge now passes user_id and works for view-path
mutations. Extracted _purge_cache_for_invalidation() shared helper
used by both RPC and view-path branches.
C2: initSession retries 3x with backoff. Resets on total failure
so next call tries again instead of permanently broken CSRF.
C3: SSR template backend injects __MIZAN_SSR_DATA__ script tag
with serialized props for client-side hydration.
C4: SSR bridge uses _write_lock to serialize stdin writes from
concurrent Django threads. Prevents JSON interleaving.
C5: SSR bridge registers atexit handler for process cleanup.
No more orphaned Bun processes on Django reload/shutdown.
H1: pendingScoped changed from Map to Array — multiple scoped
invalidations for the same context no longer overwrite.
H2: registerContext uses stableKey() (sorted JSON) instead of
bare JSON.stringify. Property order no longer matters.
H4: Named context providers skip refetch if SSR data exists
(matches global context behavior).
H10: _meta always assigned as fresh dict, preventing shared-dict
mutation across ServerFunction subclasses.
373 Django + 33 React tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
packages/
mizan-runtime/ Framework-agnostic state engine (~150 lines)
Context registry, batched invalidation, fetch primitives
mizan-django/ Django server adapter (was packages/mizan-rpc/adapters/django/)
Codegen moved to mizan-django/generate/
mizan-react/ React adapter (was packages/mizan-csr/adapters/react/)
Removed premature abstractions: mizan-ast, mizan-schema, mizan-rpc,
mizan-csr, mizan-ssr stub packages. The actual architecture is three
concrete packages, not five abstract layers.
mizan-runtime implements the v1 spec: registerContext with params,
scoped invalidation via microtask batching, server-driven invalidation
from mutation responses, mizanFetch for context bundles, mizanCall for
mutations.
264 Django + 33 React tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>