Catch missed content edits from tree restructure

The fe39fcb commit captured the file moves (git mv stages those automatically)
but didn't catch the content edits I made afterward — npm package rename
(@mizan/runtime → @mizan/base), path updates in Makefile/Dockerfile/examples,
and doc updates were all left unstaged at commit time.

This commit lands those:
- npm rename: 3 frontend package.jsons (base/vue/svelte) + mizan-base/src/index.ts + 4 codegen templates
- path updates: Makefile, Dockerfile.test, two Gitea workflows, four example/harness configs
- doc updates: CLAUDE.md, ROADMAP.md, ISSUES.md, docs/AFI_ARCHITECTURE.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-06 01:26:04 -04:00
parent fe39fcb229
commit 9d2781b52c
21 changed files with 63 additions and 76 deletions

View File

@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
defaults: defaults:
run: run:
working-directory: django working-directory: backends/mizan-django
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
defaults: defaults:
run: run:
working-directory: react working-directory: frontends/mizan-react
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@@ -10,23 +10,21 @@ Django + React ships first. The protocol is language-agnostic (proven by mizan-t
## Package Layout ## Package Layout
Two layers per side. Per-framework adapters wrap a single shared kernel; codegen targets the adapter. Tree organized by role. Per-framework adapters wrap a single shared kernel; codegen targets the adapter.
**Backend protocol adapters** — implement the wire protocol on a server stack: ```
backends/ server protocol adapters
- `mizan-django/` Django adapter mizan-django/ Django adapter
- `mizan-ts/` TypeScript adapter (proves the protocol is language-agnostic) mizan-ts/ TypeScript adapter (proves the protocol is language-agnostic)
frontends/ client kernel + per-framework adapters
**Frontend kernel + framework adapters** — kernel is the imperative client primitive set; each framework adapter wraps the kernel in its own idiomatic constructs: mizan-base/ framework-agnostic kernel; owns data, status, error; adapters subscribe
mizan-react/ React contexts + hooks over the kernel
- `mizan-runtime/` — framework-agnostic kernel; owns data, status, error; adapters subscribe mizan-vue/ Vue composables over the kernel
- `mizan-react/` — React contexts + hooks over the kernel mizan-svelte/ Svelte stores/runes over the kernel
- `mizan-vue/` — Vue composables over the kernel cores/ shared language-level primitives (currently empty; mizan-python forthcoming)
- `mizan-svelte/` — Svelte stores/runes over the kernel workers/ runtime workers / bridges
mizan-ssr/ Bun subprocess used by the Django template backend
**SSR worker:** ```
- `mizan-ssr/` — Bun subprocess used by the Django template backend
--- ---
@@ -444,7 +442,7 @@ urlpatterns = [
## Codegen — Current State ## Codegen — Current State
The codegen is two-stage and per-framework. Stage 1 (in `mizan-django/generate/`) emits the framework-agnostic protocol layer (`callXxx` for mutations, `fetchXxx` for context bundles, types). Stage 2 emits per-framework hooks/composables/stores that subscribe to the `mizan-runtime` kernel. The codegen is two-stage and per-framework. Stage 1 (in `mizan-django/generate/`) emits the framework-agnostic protocol layer (`callXxx` for mutations, `fetchXxx` for context bundles, types). Stage 2 emits per-framework hooks/composables/stores that subscribe to the `mizan-base` kernel.
**What's in place:** **What's in place:**

View File

@@ -24,7 +24,7 @@ Identified by domain expert review (Cloudflare, Serverless, Vercel, React Query,
## Remaining Critical ## Remaining Critical
### C6. No loading/error/stale states in runtime ### C6. No loading/error/stale states in runtime
**File:** `mizan-runtime/src/index.ts` **File:** `mizan-base/src/index.ts`
The kernel stores only `{params, refetch}`. No `data`, `status`, `error`. Every adapter reinvents loading tracking. Blocks stale-while-revalidate. The kernel stores only `{params, refetch}`. No `data`, `status`, `error`. Every adapter reinvents loading tracking. Blocks stale-while-revalidate.
## Remaining High ## Remaining High
@@ -103,7 +103,7 @@ Context listeners called inside `setContextStore()` updater.
### A1. Legacy MizanProvider not yet removed ### A1. Legacy MizanProvider not yet removed
**File:** `mizan-react/src/context.tsx` (~750 lines) **File:** `mizan-react/src/context.tsx` (~750 lines)
Superseded by the kernel (`mizan-runtime`) + generated React adapter (`useSyncExternalStore`). Still exported as `MizanProvider`, `useMizan`, `useMizanContext`, etc. Must be deleted or replaced with thin shims that call `configure()` + delegate to the new generated hooks. Superseded by the kernel (`mizan-base`) + generated React adapter (`useSyncExternalStore`). Still exported as `MizanProvider`, `useMizan`, `useMizanContext`, etc. Must be deleted or replaced with thin shims that call `configure()` + delegate to the new generated hooks.
### A2. Allauth pending extraction ### A2. Allauth pending extraction
**File:** `legacy/allauth/` (44 files) **File:** `legacy/allauth/` (44 files)
@@ -131,7 +131,7 @@ Written before the kernel rewrite. References to MizanProvider responsibilities
## Test Coverage Gaps ## Test Coverage Gaps
### T1. No tests for C6 kernel state machine ### T1. No tests for C6 kernel state machine
**File:** `mizan-runtime/` has no `tests/` directory at all **File:** `mizan-base/` has no `tests/` directory at all
The state-owning kernel has zero unit tests. No coverage of: The state-owning kernel has zero unit tests. No coverage of:
- `registerContext` returning `getState/subscribe/refetch/unregister` - `registerContext` returning `getState/subscribe/refetch/unregister`
- Status transitions: idle → loading → success/error - Status transitions: idle → loading → success/error

View File

@@ -1,7 +1,7 @@
.PHONY: install test test-django test-react test-integration docker-up docker-down clean .PHONY: install test test-django test-react test-integration docker-up docker-down clean
DJANGO = packages/mizan-django DJANGO = backends/mizan-django
REACT = packages/mizan-react REACT = frontends/mizan-react
# ─── Setup ─────────────────────────────────────────────────────────────────── # ─── Setup ───────────────────────────────────────────────────────────────────

View File

@@ -20,7 +20,7 @@
- **HMAC cache keying** — origin-side cache with cross-language HMAC conformance (Python + TypeScript pin) - **HMAC cache keying** — origin-side cache with cross-language HMAC conformance (Python + TypeScript pin)
- **Edge manifest** — `python manage.py export_edge_manifest`; both RPC and view-path functions - **Edge manifest** — `python manage.py export_edge_manifest`; both RPC and view-path functions
- **SSR bridge** — Django template backend → persistent Bun subprocess via JSON-RPC - **SSR bridge** — Django template backend → persistent Bun subprocess via JSON-RPC
- **`mizan-runtime` kernel** — framework-agnostic imperative client primitives (data/status/error owned by kernel) - **`mizan-base` kernel** — framework-agnostic imperative client primitives (data/status/error owned by kernel)
- **Two-stage codegen** — Stage 1 emits framework-agnostic protocol layer; Stage 2 emits per-framework hooks (React, Vue, Svelte) - **Two-stage codegen** — Stage 1 emits framework-agnostic protocol layer; Stage 2 emits per-framework hooks (React, Vue, Svelte)
- **`mizan-ts`** — TypeScript backend adapter; proves the protocol is language-agnostic - **`mizan-ts`** — TypeScript backend adapter; proves the protocol is language-agnostic
@@ -28,7 +28,7 @@
### Next (in progress) ### Next (in progress)
- **React adapter wrapper layer** — codegen emits `MizanContext` provider, `useMizan` hook, `DjangoError` class on top of the `mizan-runtime` kernel. Equivalent wrapper layers for Vue and Svelte adapters. The harness in `examples/django-react-site` is blocked on this. - **React adapter wrapper layer** — codegen emits `MizanContext` provider, `useMizan` hook, `DjangoError` class on top of the `mizan-base` kernel. Equivalent wrapper layers for Vue and Svelte adapters. The harness in `examples/django-react-site` is blocked on this.
- **Legacy `MizanProvider` removal (A1)** — `mizan-react/src/context.tsx` (~750 lines) replaced by codegen-emitted wrappers. Blocks v1 `mizan-react` publishing. - **Legacy `MizanProvider` removal (A1)** — `mizan-react/src/context.tsx` (~750 lines) replaced by codegen-emitted wrappers. Blocks v1 `mizan-react` publishing.
- **Forms migration to kernel (A3)** — `mizan-react/src/forms.ts` (~1163 lines) currently consumes legacy `MizanProvider`. Rewrite to use `mizanCall` from the kernel. Blocks A1. - **Forms migration to kernel (A3)** — `mizan-react/src/forms.ts` (~1163 lines) currently consumes legacy `MizanProvider`. Rewrite to use `mizanCall` from the kernel. Blocks A1.
- **Allauth extraction (A2)** — `legacy/allauth/` becomes `mizan-django-allauth` package consuming Mizan's public API. - **Allauth extraction (A2)** — `legacy/allauth/` becomes `mizan-django-allauth` package consuming Mizan's public API.

View File

@@ -23,7 +23,7 @@ export function generateReactAdapter(schema) {
'// AUTO-GENERATED by mizan — do not edit', '// AUTO-GENERATED by mizan — do not edit',
'', '',
"import { createContext, useContext, useState, useEffect, useCallback, useRef, useSyncExternalStore, type ReactNode } from 'react'", "import { createContext, useContext, useState, useEffect, useCallback, useRef, useSyncExternalStore, type ReactNode } from 'react'",
"import { registerContext, mizanFetch, mizanCall, type ContextState } from '@mizan/runtime'", "import { registerContext, mizanFetch, mizanCall, type ContextState } from '@mizan/base'",
'', '',
] ]
@@ -172,8 +172,8 @@ export function generateReactAdapter(schema) {
// ── Re-export runtime types ───────────────────────────────────────── // ── Re-export runtime types ─────────────────────────────────────────
lines.push("export type { ContextState } from '@mizan/runtime'") lines.push("export type { ContextState } from '@mizan/base'")
lines.push("export { configure, initSession, MizanError } from '@mizan/runtime'") lines.push("export { configure, initSession, MizanError } from '@mizan/base'")
lines.push('') lines.push('')
return lines.join('\n') return lines.join('\n')

View File

@@ -18,7 +18,7 @@ export function generateSvelteAdapter(schema) {
'// AUTO-GENERATED by mizan — do not edit', '// AUTO-GENERATED by mizan — do not edit',
'', '',
"import { readable, type Readable } from 'svelte/store'", "import { readable, type Readable } from 'svelte/store'",
"import { registerContext, type ContextState } from '@mizan/runtime'", "import { registerContext, type ContextState } from '@mizan/base'",
'', '',
] ]
@@ -70,8 +70,8 @@ export function generateSvelteAdapter(schema) {
} }
lines.push('') lines.push('')
lines.push("export type { ContextState } from '@mizan/runtime'") lines.push("export type { ContextState } from '@mizan/base'")
lines.push("export { configure, initSession, MizanError } from '@mizan/runtime'") lines.push("export { configure, initSession, MizanError } from '@mizan/base'")
lines.push('') lines.push('')
return lines.join('\n') return lines.join('\n')

View File

@@ -18,7 +18,7 @@ export function generateVueAdapter(schema) {
'// AUTO-GENERATED by mizan — do not edit', '// AUTO-GENERATED by mizan — do not edit',
'', '',
"import { ref, computed, onMounted, onUnmounted, onServerPrefetch, type ComputedRef } from 'vue'", "import { ref, computed, onMounted, onUnmounted, onServerPrefetch, type ComputedRef } from 'vue'",
"import { registerContext, type ContextState } from '@mizan/runtime'", "import { registerContext, type ContextState } from '@mizan/base'",
'', '',
] ]
@@ -96,8 +96,8 @@ export function generateVueAdapter(schema) {
lines.push('') lines.push('')
} }
lines.push("export type { ContextState } from '@mizan/runtime'") lines.push("export type { ContextState } from '@mizan/base'")
lines.push("export { configure, initSession, MizanError } from '@mizan/runtime'") lines.push("export { configure, initSession, MizanError } from '@mizan/base'")
lines.push('') lines.push('')
return lines.join('\n') return lines.join('\n')

View File

@@ -80,7 +80,7 @@ export function generateContextFile(ctxName, ctxMeta, functions) {
const lines = [ const lines = [
'// AUTO-GENERATED by mizan — do not edit', '// AUTO-GENERATED by mizan — do not edit',
'', '',
"import { mizanFetch } from '@mizan/runtime'", "import { mizanFetch } from '@mizan/base'",
'', '',
] ]
@@ -133,7 +133,7 @@ export function generateMutationFile(fn) {
const lines = [ const lines = [
'// AUTO-GENERATED by mizan — do not edit', '// AUTO-GENERATED by mizan — do not edit',
'', '',
"import { mizanCall } from '@mizan/runtime'", "import { mizanCall } from '@mizan/base'",
'', '',
] ]

View File

@@ -5,32 +5,21 @@ server-client unification layer.
## Package layout ## Package layout
Two layers per side. Independent packages, single shared protocol. Tree organized by role.
**Backend protocol adapters** — implement the wire protocol on a ```
server stack: backends/ server protocol adapters
mizan-django/ Django adapter
| Package | Role | mizan-ts/ TypeScript adapter (proves the protocol is language-agnostic)
|---|---| frontends/ client kernel + per-framework adapters
| `mizan-django` | Django adapter | mizan-base/ framework-agnostic kernel; owns data, status, error; adapters subscribe
| `mizan-ts` | TypeScript adapter (proves the protocol is language-agnostic) | mizan-react/ React contexts + hooks over the kernel
mizan-vue/ Vue composables over the kernel
**Frontend kernel + framework adapters** the kernel is the mizan-svelte/ Svelte stores/runes over the kernel
imperative client primitive set; each framework adapter wraps the cores/ shared language-level primitives (mizan-python forthcoming)
kernel in its own idiomatic constructs: workers/ runtime workers / bridges
mizan-ssr/ Bun subprocess used by the Django template backend
| Package | Role | ```
|---|---|
| `mizan-runtime` | Framework-agnostic client kernel — owns data, status, error; adapters subscribe |
| `mizan-react` | React contexts + hooks over the kernel |
| `mizan-vue` | Vue composables over the kernel |
| `mizan-svelte` | Svelte stores/runes over the kernel |
**SSR worker:**
| Package | Role |
|---|---|
| `mizan-ssr` | Bun subprocess used by the Django template backend |
## Two orthogonal products ## Two orthogonal products
@@ -42,7 +31,7 @@ compose.
## Kernel model ## Kernel model
The client kernel (`mizan-runtime`) is the one hard thing. Per- The client kernel (`mizan-base`) is the one hard thing. Per-
framework adapters are thin idiomatic wrappers around it. Codegen framework adapters are thin idiomatic wrappers around it. Codegen
emits typed bindings against the framework adapter's surface, not emits typed bindings against the framework adapter's surface, not
against the raw kernel — so a React developer gets `useEcho()` and against the raw kernel — so a React developer gets `useEcho()` and

View File

@@ -7,7 +7,7 @@
"build": "vite build" "build": "vite build"
}, },
"dependencies": { "dependencies": {
"@rythazhur/mizan": "file:../../../packages/mizan-react", "@rythazhur/mizan": "file:../../../frontends/mizan-react",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0" "react-dom": "^19.0.0"
}, },

View File

@@ -2,7 +2,7 @@ import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react' import react from '@vitejs/plugin-react'
import path from 'path' import path from 'path'
const reactPkg = path.resolve(__dirname, '../../../packages/mizan-react/src') const reactPkg = path.resolve(__dirname, '../../../frontends/mizan-react/src')
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()],

View File

@@ -8,7 +8,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Install mizan from local source with channels support # Install mizan from local source with channels support
COPY packages/mizan-django/ /app/django/ COPY backends/mizan-django/ /app/django/
RUN pip install --no-cache-dir /app/django[channels] daphne RUN pip install --no-cache-dir /app/django[channels] daphne
# Copy example app # Copy example app

View File

@@ -10,9 +10,9 @@ export default {
source: { source: {
django: { django: {
managePath: path.join(root, 'examples/django-react-site/backend/manage.py'), managePath: path.join(root, 'examples/django-react-site/backend/manage.py'),
command: [path.join(root, 'packages/mizan-django/.venv/bin/python')], command: [path.join(root, 'backends/mizan-django/.venv/bin/python')],
env: { env: {
PYTHONPATH: `${path.join(root, 'packages/mizan-django/src')}:${path.join(root, 'examples/django-react-site/backend')}`, PYTHONPATH: `${path.join(root, 'backends/mizan-django/src')}:${path.join(root, 'examples/django-react-site/backend')}`,
DJANGO_SETTINGS_MODULE: 'testapp.settings', DJANGO_SETTINGS_MODULE: 'testapp.settings',
}, },
}, },

View File

@@ -7,7 +7,7 @@
"dev": "vite --port 5174" "dev": "vite --port 5174"
}, },
"dependencies": { "dependencies": {
"@rythazhur/mizan": "file:../../../packages/mizan-react", "@rythazhur/mizan": "file:../../../frontends/mizan-react",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"zod": "^4.3.6" "zod": "^4.3.6"

View File

@@ -2,7 +2,7 @@ import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react' import react from '@vitejs/plugin-react'
import path from 'path' import path from 'path'
const reactPkg = path.resolve(__dirname, '../../../packages/mizan-react/src') const reactPkg = path.resolve(__dirname, '../../../frontends/mizan-react/src')
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()],

View File

@@ -1,5 +1,5 @@
{ {
"name": "@mizan/runtime", "name": "@mizan/base",
"version": "0.1.0", "version": "0.1.0",
"description": "Mizan client runtime — context registry, invalidation, fetch. Zero framework dependencies.", "description": "Mizan client runtime — context registry, invalidation, fetch. Zero framework dependencies.",
"type": "module", "type": "module",

View File

@@ -1,5 +1,5 @@
/** /**
* @mizan/runtime — The client state kernel. * @mizan/base — The client state kernel.
* *
* Zero framework dependencies. React, Vue, Svelte — all import from here. * Zero framework dependencies. React, Vue, Svelte — all import from here.
* *

View File

@@ -1,11 +1,11 @@
{ {
"name": "@mizan/svelte", "name": "@mizan/svelte",
"version": "0.1.0", "version": "0.1.0",
"description": "Mizan Svelte adapter — stores generated from @mizan/runtime.", "description": "Mizan Svelte adapter — stores generated from @mizan/base.",
"type": "module", "type": "module",
"peerDependencies": { "peerDependencies": {
"svelte": ">=4", "svelte": ">=4",
"@mizan/runtime": ">=0.1.0" "@mizan/base": ">=0.1.0"
}, },
"license": "MIT" "license": "MIT"
} }

View File

@@ -1,11 +1,11 @@
{ {
"name": "@mizan/vue", "name": "@mizan/vue",
"version": "0.1.0", "version": "0.1.0",
"description": "Mizan Vue adapter — composables generated from @mizan/runtime.", "description": "Mizan Vue adapter — composables generated from @mizan/base.",
"type": "module", "type": "module",
"peerDependencies": { "peerDependencies": {
"vue": ">=3", "vue": ">=3",
"@mizan/runtime": ">=0.1.0" "@mizan/base": ">=0.1.0"
}, },
"license": "MIT" "license": "MIT"
} }