@kudzujs/core 0.8.15 → 0.8.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION_ROADMAP.md +247 -0
- package/PERFORMANCE.md +212 -0
- package/README.md +1 -1
- package/RELEASES.md +32 -0
- package/docs/next-architecture/README.md +42 -0
- package/docs/next-architecture/compiler-current-architecture.md +71 -0
- package/docs/next-architecture/goal-a-compiler-foundation.md +152 -0
- package/docs/next-architecture/goal-b-optimization-benchmarks.md +59 -0
- package/docs/next-architecture/goal-c-state-resource-research.md +50 -0
- package/docs/next-architecture/goal-d-routing-compatibility-decisions.md +51 -0
- package/docs/next-architecture/performance-gates.md +50 -0
- package/docs/next-architecture/versioning.md +42 -0
- package/framework/README.md +6 -1
- package/framework/build.mjs +103 -617
- package/framework/compiler/collection-analysis.mjs +187 -0
- package/framework/compiler/descriptor-session.mjs +222 -0
- package/framework/compiler/event-command-pass.mjs +35 -0
- package/framework/compiler/react-migration-pass.mjs +3 -2
- package/framework/compiler/route-capability-planner.mjs +118 -0
- package/framework/compiler/zustand-pass.mjs +95 -0
- package/package.json +4 -1
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# React Migration Roadmap
|
|
2
|
+
|
|
3
|
+
This document is the source of truth for Kudzu's product direction, architecture invariants, and future development order. Read it before extending React-shaped syntax or browser capabilities.
|
|
4
|
+
|
|
5
|
+
[`GOAL_A.md`](./GOAL_A.md) and [`GOAL_B.md`](./GOAL_B.md) are completed capability-validation records. Their commerce and realtime dashboard fixtures prove general lifecycle, navigation, async-workflow, and Worker capabilities; they are not separate product verticals or future priority lists.
|
|
6
|
+
|
|
7
|
+
## North Star
|
|
8
|
+
|
|
9
|
+
An AI should be able to migrate ordinary React-shaped TypeScript and TSX to CDN-deployable static HTML, CSS, and only the route-specific ESM capabilities actually used, with minimal source restructuring.
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
ordinary React-shaped TSX
|
|
13
|
+
-> Kudzu compiler specialization
|
|
14
|
+
-> complete static HTML + CSS + capability-specific ESM
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Kudzu is a general migration compiler. Shops, dashboards, documentation, blogs, landing pages, forms, and administration screens are outcomes built on the same compiler model. No application category defines Kudzu's architecture.
|
|
18
|
+
|
|
19
|
+
Syntax compatibility does not mean reproducing React wholesale. Kudzu accepts the statically analyzable subset it can lower to build-time output and direct browser capabilities. Unsupported nearby patterns must fail at build time with a file, line, and actionable explanation.
|
|
20
|
+
|
|
21
|
+
## Product Invariants
|
|
22
|
+
|
|
23
|
+
- Never add React as a runtime or production dependency.
|
|
24
|
+
- Never add a VDOM, hydration pass, retained browser component tree, generic component rerenderer, or hook dispatcher.
|
|
25
|
+
- Static routes ship zero client JavaScript.
|
|
26
|
+
- Interactive routes ship only the capabilities they use.
|
|
27
|
+
- Prefer build-time execution whenever all inputs are available during the build.
|
|
28
|
+
- State setters update logical state immediately and batch direct DOM writes at synchronous-turn boundaries.
|
|
29
|
+
- Preserve familiar function components, props, children, JSX, hooks, conditions, collections, and event handlers where Kudzu can compile them safely.
|
|
30
|
+
- Prefer compiler specialization over asking migrated applications to replace ordinary declarative React UI with imperative DOM code.
|
|
31
|
+
- Unknown browser-only data receives a static shell plus only the ESM needed to obtain and patch it.
|
|
32
|
+
- Native document navigation and ordinary `<a>` elements are the default.
|
|
33
|
+
- Same-document navigation remains explicit, route-group scoped, complete-document based, and recoverable through native navigation.
|
|
34
|
+
- Do not add compatibility APIs speculatively. A real or reduced conventional React fixture must fail first.
|
|
35
|
+
|
|
36
|
+
## Data And Route Decisions
|
|
37
|
+
|
|
38
|
+
Classify each migrated screen before changing the framework.
|
|
39
|
+
|
|
40
|
+
| Requirement | Kudzu treatment |
|
|
41
|
+
|---|---|
|
|
42
|
+
| Data and route known at build time | Async component or `getStaticPaths()`; emit complete HTML |
|
|
43
|
+
| Interaction after user input | Existing event compiler; emit handler ESM only |
|
|
44
|
+
| Data available only after browser mount | Inline `useEffect`; emit one route-specific effect graph |
|
|
45
|
+
| Route IDs known at build time | Bracket route plus `getStaticPaths()` |
|
|
46
|
+
| Route value known only from the URL | Static fallback plus compiled pathname parameter reader |
|
|
47
|
+
| Normal navigation | Native `<a>` document navigation |
|
|
48
|
+
| Proven same-document requirement | Explicit shared-layout route group with complete-document fallback |
|
|
49
|
+
| High-frequency browser processing | Relative Worker or imperative resource owned by an effect when a fixture proves it |
|
|
50
|
+
| Dataset too large for direct DOM | Pagination or windowing; do not render an unbounded tree |
|
|
51
|
+
|
|
52
|
+
Do not add `getStaticProps`, request-time SSR, an SPA router, a stream runtime, or a virtualization system until a reduced migration fixture proves the existing treatments insufficient.
|
|
53
|
+
|
|
54
|
+
## Completed Foundation
|
|
55
|
+
|
|
56
|
+
The following are available building blocks, not future vertical roadmaps:
|
|
57
|
+
|
|
58
|
+
- Async build-time components, `getStaticPaths()`, runtime path parameters, metadata, base paths, public assets, CSS, CSS Modules, and post-build hooks.
|
|
59
|
+
- React import normalization for supported named/aliased hooks, direct `React.*` members, fragments, same-file `memo`, inline `useCallback`, direct intrinsic `forwardRef`, top-level `useId`, and analyzable `useMemo` expressions and collections.
|
|
60
|
+
- Function components, props, children, context, direct bindings, conditions, controlled form properties, refs, and synchronous or async handlers.
|
|
61
|
+
- `useState`, independent repeated non-keyed child state with conditional mount ownership, reduced relative-imported `useReducer`, direct dispatch specialization, and reduced Zustand-shaped shared state proven by migration fixtures.
|
|
62
|
+
- Mount and dependency effects with cleanup, route/layout lifetimes, conditional/keyed ownership, stale-write isolation, and relative TypeScript Workers.
|
|
63
|
+
- Keyed local-state and imported static collections, pure selectors, nested direct-property lists, recursive and directly exported row specialization, static/keyed component reuse, analyzable specialized prop spreads, serializable literal defaults, direct intrinsic rest forwarding, forwarded JSX children, latest-item handlers, row state/effects/refs, and stable keyed identity.
|
|
64
|
+
- Complete-document native fallback and optional shared-layout navigation groups with parameter initialization, finite prefetch caching, focus, history, cleanup, and independent capability output.
|
|
65
|
+
- React-shaped SVG presentation attributes, direct `clsx` lowering, fixed-locale reactive `Intl.NumberFormat` display formatting, relative TypeScript handler helpers, and source-located diagnostics.
|
|
66
|
+
|
|
67
|
+
Completed fixtures such as commerce, TodoMVC, nested order data, Zustand state, landing pages, and realtime Workers are evidence that these compiler capabilities compose. They do not set the product's domain or automatically justify broader package compatibility.
|
|
68
|
+
|
|
69
|
+
## Development Selection Rule
|
|
70
|
+
|
|
71
|
+
Future work begins with an actual React application or a reduced fixture derived from one.
|
|
72
|
+
|
|
73
|
+
1. Build the source with the current compiler before restructuring it.
|
|
74
|
+
2. Inventory the first unsupported ordinary React pattern.
|
|
75
|
+
3. Reduce that pattern to the smallest executable fixture.
|
|
76
|
+
4. Confirm the pattern is general React authoring rather than one application's architecture.
|
|
77
|
+
5. Reuse an existing compiler/runtime capability before adding a new one.
|
|
78
|
+
6. Implement the narrowest shared specialization that preserves familiar source.
|
|
79
|
+
7. Add source diagnostics for the supported boundary and nearby rejected forms.
|
|
80
|
+
8. Prove static output, browser behavior, identity/cleanup, and zero-cost exclusion.
|
|
81
|
+
9. Measure output bytes, build time, and the affected browser operation.
|
|
82
|
+
10. Update public support and limit documentation.
|
|
83
|
+
|
|
84
|
+
An unsupported item is not automatically backlog work. Arbitrary callbacks, packages, and React semantics remain unsupported until independent migration evidence justifies a safe static specialization.
|
|
85
|
+
|
|
86
|
+
## Active Fixture Queue
|
|
87
|
+
|
|
88
|
+
This queue orders the next investigations by general migration value. Start only the highest item for which a real failing fixture exists.
|
|
89
|
+
|
|
90
|
+
### Completed In 0.8.0
|
|
91
|
+
|
|
92
|
+
- Relative zero-argument custom hooks expose direct shorthand state/setter pairs and state-capturing callbacks to one top-level caller destructuring.
|
|
93
|
+
- Writable React Router search parameters use native inline `URLSearchParams` updaters, push/replace history, signal recommits, and `popstate` synchronization.
|
|
94
|
+
- Guarded `localStorage` restoration and persistence compose through existing mount/dependency effects, preserving deterministic static fallbacks without a storage runtime.
|
|
95
|
+
- Reachable source compilation excludes unused React/Vite modules while preserving source diagnostics for every reachable module.
|
|
96
|
+
- Direct imported immutable maps fold to static HTML, and relative structured calculations reevaluate consumed scalar fields through existing binding ESM.
|
|
97
|
+
- Direct event-only package imports bundle into route handlers without executing during static rendering.
|
|
98
|
+
- Production Tailwind output, Inter assets, direct native SVG charts, and Excel export compose without adding Tailwind, Recharts, or a package runtime to Kudzu.
|
|
99
|
+
- FIRE migration validation covers all fourteen routes, URL/storage updates and reload, reset, presets, chart identity, Quiz recommendation, keyed Debt updates, Excel workbook creation, and zero-JavaScript Home/Books/Apps output.
|
|
100
|
+
|
|
101
|
+
### Completed In 0.8.1
|
|
102
|
+
|
|
103
|
+
- A direct custom-hook reset action may batch literal updates across its returned state/setter pairs. Imported callback literals are synthesized into existing behavior commands, and the FIRE Standard reset now remains owned by its hook while URL and storage effects observe the same commit.
|
|
104
|
+
|
|
105
|
+
### Completed In 0.8.2
|
|
106
|
+
|
|
107
|
+
- A direct array field from one top-level synchronous relative calculation result may feed a keyed intrinsic list. Route-specific evaluator ESM refreshes a compiler-owned array anchor before the existing list reconciler runs, preserving keyed SVG namespace, latest item handlers, and DOM identity without a chart or component runtime.
|
|
108
|
+
- The FIRE Standard projection exposes eleven calculated yearly points as accessible keyed SVG circles. Input commits update coordinates and labels while retaining every year node alongside the existing reactive path.
|
|
109
|
+
|
|
110
|
+
### Characterized In 0.8.3
|
|
111
|
+
|
|
112
|
+
- A direct clipboard action returned by a relative custom hook compiles through existing async native-handler ESM, including application-owned success and rejection state, without a clipboard runtime.
|
|
113
|
+
- A dependency effect using `setTimeout()` with directly returned `clearTimeout()` cleanup provides debounced synchronization; dependency changes and conditional unmount cancel pending work through existing effect ownership.
|
|
114
|
+
- The React/Vite migration fixture verifies latest-only debounce commits, unmount cancellation, fresh remount, clipboard success/failure, and zero JavaScript on its static sibling.
|
|
115
|
+
- Parent state plus focus, keyboard, and click handlers on calculated keyed SVG points drives an external accessible tooltip through existing native-handler and binding ESM. Recalculation preserves point identity and gives retained handlers the latest labels; the static sibling remains JavaScript-free.
|
|
116
|
+
|
|
117
|
+
### Completed In 0.8.5
|
|
118
|
+
|
|
119
|
+
- A directly returned relative custom-hook callback may own one private `null`-initialized timeout ref, directly clear its previous value, and assign one literal-delay `setTimeout()` whose callback updates hook state.
|
|
120
|
+
- One empty-dependency effect directly clears the latest timer on cleanup. The compiler lowers the ref to a hidden state slot shared by existing native-handler and effect contexts, so conditional unmount cancels pending work and remount starts fresh without a timer runtime.
|
|
121
|
+
- The React/Vite migration fixture verifies timer replacement, latest-only firing, conditional cleanup, fresh remount, source diagnostics for dynamic delays, and zero timer-specific runtime bytes.
|
|
122
|
+
|
|
123
|
+
### Completed In 0.8.7
|
|
124
|
+
|
|
125
|
+
- The FIRE migration's detailed Withdrawal and Debt charts compose from relative calculation fields, reactive SVG paths, calculated keyed SVG points, and ordinary parent state without a chart runtime.
|
|
126
|
+
- Withdrawal renders two series and 31 yearly targets. Debt renders remaining-balance comparisons plus cumulative principal and interest with monthly targets.
|
|
127
|
+
- Pointer, focus, click, Space, and Enter update external accessible tooltips. Input and debt-list changes preserve retained point and path identity while handlers read current labels.
|
|
128
|
+
- Home, Books, and Apps remain JavaScript-free. The expanded charts require no compiler or runtime change.
|
|
129
|
+
- A React Notes migration proved selected keyed rows need direct primitive parent state in ordinary class and ARIA expressions. Kudzu now reevaluates only retained row expressions on that state commit, preserving row identity without a component rerender.
|
|
130
|
+
- The supported boundary is a pure flat-row text or attribute expression combining the direct item/index with direct primitive parent state. Object/array state, arbitrary captures, nested-row parent state, and structural conditions remain diagnosed.
|
|
131
|
+
|
|
132
|
+
### Completed In 0.8.8
|
|
133
|
+
|
|
134
|
+
- The React Notes editor now retains its ordinary `notes.map(note => activeId === note.id && <Editor key={note.id} />)` source shape. Kudzu normalizes expression-bodied `condition && <Row />` and `condition ? <Row /> : null` keyed maps into existing pure filter selectors.
|
|
135
|
+
- False rows own no DOM or hooks; true-to-false transitions clean up state, effects, and refs, while re-entry creates fresh keyed ownership. Retained siblings preserve identity.
|
|
136
|
+
- Conditions may combine the current item with direct primitive parent state. Nested rows accept item-only conditions; map indexes, alternate JSX fallbacks, arbitrary captures, and impure predicates remain diagnosed.
|
|
137
|
+
- Imported build-known item-only conditions still fold to complete zero-JavaScript HTML, and no runtime capability was added.
|
|
138
|
+
|
|
139
|
+
### Completed In 0.8.9
|
|
140
|
+
|
|
141
|
+
- A React Notes migration preserves its Provider, relative `useNotes()` alias, consumer components, and parameterized CRUD actions. A direct custom-hook `useContext(Context)` return resolves one local or named relative Context module whose Provider value exposes direct state/setter pairs and synchronous actions.
|
|
142
|
+
- Context actions inline into existing route handler ESM and compile to concrete state operations. Private captures, dynamic Provider objects, and multiple Provider implementations remain diagnosed; no browser Context tree, callback registry, or shared runtime was added.
|
|
143
|
+
|
|
144
|
+
### Completed In 0.8.10
|
|
145
|
+
|
|
146
|
+
- A reduced shadcn/Radix-shaped dialog migration replaces package-owned Portal and Context behavior with the native `<dialog>` element while preserving a relative `forwardRef` component, props, children, object refs, and ordinary JSX handlers.
|
|
147
|
+
- Browser validation covers modal top-layer behavior, initial focus, confirm and cancel paths, and explicit trigger-focus restoration. Complete dialog HTML is pre-rendered, React and Radix are absent from output, and native event output remains specialized to the route's actual events.
|
|
148
|
+
- This is a source migration recipe rather than Radix package compatibility. `Portal`, `asChild`/`Slot`, element cloning, and arbitrary compound-component Context remain unsupported.
|
|
149
|
+
|
|
150
|
+
### Completed In 0.8.11
|
|
151
|
+
|
|
152
|
+
- A reduced React Hook Form-shaped signup migration replaces `useForm`, registration spreads, and submit wrappers with native controls, constraint validation, `FormData`, one direct async submit handler, and application-owned result state.
|
|
153
|
+
- Browser validation covers required and email constraints, submitting state, server-error ARIA, success cleanup, and retained uncontrolled values. Complete form HTML is pre-rendered, the route emits only one `submit` listener, the static sibling remains JavaScript-free, and React Hook Form is absent from output.
|
|
154
|
+
- This is a source migration recipe rather than React Hook Form package compatibility. Controllers, watchers, resolvers, dirty/touched proxies, dynamic field registration, and schema package execution during render remain unsupported.
|
|
155
|
+
- A reduced TanStack Query-shaped migration classifies build-known reads into async page rendering and browser-only reads into one dependency effect with application-owned loading, error, result, and primitive refetch state.
|
|
156
|
+
- Dependency replacement now invalidates prior unowned effect invocations before cleanup in both single-dependency and general runners. Delayed fetch setters from superseded invocations cannot overwrite newer keyed result state.
|
|
157
|
+
- Browser validation covers a fast refetch winning over a delayed response, cleanup ordering, HTTP failure, recovery, complete zero-JavaScript build output, and a static zero-JavaScript sibling. Query clients, Providers, caches, retries, deduplication, query-key arrays, optimistic updates, Suspense, and background refetch remain unsupported.
|
|
158
|
+
|
|
159
|
+
### Completed In 0.8.12
|
|
160
|
+
|
|
161
|
+
- A reduced Lucide React-shaped migration moves only used icons into one relative TSX module with direct intrinsic SVG roots, destructured size/stroke defaults, explicit prop forwarding, and no package factory or runtime.
|
|
162
|
+
- Static output preserves meaningful `role`/`title` labeling, decorative `aria-hidden`, explicit dimensions and fill overrides, `currentColor`, and normalized stroke attributes. The route ships no JavaScript, and an unreachable icon module is not compiled.
|
|
163
|
+
- Final route plans now gate handler emission, so build-folded component conditions cannot leave dead evaluator JavaScript in deploy artifacts. Dynamic icon lookup, `createLucideIcon()`, package-owned factories, and a generic icon runtime remain unsupported.
|
|
164
|
+
|
|
165
|
+
### Completed In 0.8.13
|
|
166
|
+
|
|
167
|
+
- A reduced fixture from [Memos](https://github.com/usememos/memos) preserves its memo-outline scroll spy: native heading links, active `aria-current`, smooth scrolling, hash replacement, capture-phase scroll/resize listeners, and animation-frame coalescing with cleanup.
|
|
168
|
+
- One effect-owned `useRef(0)` lowers to a serializable mutable effect capture when a local frame callback resets it and cleanup cancels the pending frame. Existing effect ownership handles setup, listener removal, and document disposal without state, a retained component, or an animation runtime.
|
|
169
|
+
- Chrome validation covers burst coalescing, active-heading updates, outline clicks, hash replacement, pending-frame cancellation, listener cleanup, and a zero-JavaScript static sibling. Ref aliases, cross-effect/event use, nonzero initializers, multiple scheduling assignments, and missing cancellation remain unsupported.
|
|
170
|
+
- A reduced fixture from [Excalidraw](https://github.com/excalidraw/excalidraw) preserves its active-room progressive sharing shape: a readonly collaboration URL, a Web Share button gated by `"share" in navigator`, direct `navigator.share()`, clipboard fallback, and accessible application-owned status.
|
|
171
|
+
- Browser capability conditions lower to a false static state plus one existing mount effect and state-owned conditional branch. Supported browsers mount the Share DOM and handler; unsupported browsers keep both out of the document and accessibility tree. Node's build-time `navigator` can no longer fold browser capability UI incorrectly.
|
|
172
|
+
- Chrome validation covers supported and unsupported capability paths, exact share/copy payloads, status updates, conditional handler ownership, and a zero-JavaScript static sibling. Dynamic properties, escaped capability values, composed tests, `navigator.canShare()`, QR package execution, collaboration transport, and general browser-expression rendering remain unsupported.
|
|
173
|
+
- A reduced fixture from [Cal.com](https://github.com/calcom/cal.diy) inlines the exact static `useSyncExternalStore` core of its shared media-query hook for 768px and 1024px Booker breakpoints. False server snapshots preserve desktop-first static HTML while browser changes update layout and visible-day density.
|
|
174
|
+
- Static media-query stores lower to existing primitive state and owned effects with exact `change` listener cleanup. No external-store runtime or media-query capability module is added; the work also fixes existing state-select text bindings so effect commits update optimized derived text as attributes already did.
|
|
175
|
+
- Chrome validation covers desktop fallback, tablet/mobile transitions, two subscriptions, document cleanup, ignored post-disposal changes, and a zero-JavaScript static sibling. Parameterized/imported hooks, dynamic queries, arbitrary stores, legacy listener APIs, and non-boolean snapshots remain unsupported.
|
|
176
|
+
|
|
177
|
+
### Completed In 0.8.14
|
|
178
|
+
|
|
179
|
+
- A reduced fixture from [colonni's blog](https://colonni.xyz/ko/posts/math-for-development) emits build-known MDX as static HTML without `eval()` or `new Function()`, generates `/ko` and `/en` through `getStaticPaths()`, prefixes native Link replacements from the build-known locale, and chooses a stored or browser-preferred locale at `/` while preserving query and hash. Request-time `Accept-Language` negotiation remains a host/edge concern.
|
|
180
|
+
- The blog's WalkingDog-shaped canvas lifecycle moves resource-private mutable values into one inline effect while retaining a direct canvas object ref. Bare `IntersectionObserver`, `performance`, recursive animation frames, keyboard/click listeners, and exact cleanup compile to one route-specific effect module without a canvas runtime.
|
|
181
|
+
- Chrome validation covers locale detection and redirect, prefixed links, static MDX, clipboard copy, reactive tabs, visible and hidden frame behavior, retained local drawing state, keyboard/click updates, exact disposal, and a zero-JavaScript static sibling. Component-level mutable value refs, callbacks shared across effects or handlers, arbitrary canvas graphs, and arbitrary runtime MDX remain unsupported.
|
|
182
|
+
|
|
183
|
+
### Completed In 0.8.15
|
|
184
|
+
|
|
185
|
+
- Build orchestration, ordered normalization, shared AST scope analysis, React and Router migration, browser resource passes, Worker compilation, development serving, and effect/handler code generation now have explicit module boundaries.
|
|
186
|
+
- Page and imported-source normalization share one pipeline with parent-pointer repair after each pass, while custom-hook timer metadata returns explicitly instead of using an AST-identity `WeakMap` side channel.
|
|
187
|
+
- The refactor preserves accepted syntax, source diagnostics, generated capability selection, static-route zero JavaScript, Worker determinism, browser ownership behavior, and all existing migration boundaries.
|
|
188
|
+
- Public documentation now presents Kudzu as a compiler that specializes supported React-shaped TSX into complete HTML and route-specific browser capabilities.
|
|
189
|
+
|
|
190
|
+
### Completed In 0.8.16
|
|
191
|
+
|
|
192
|
+
- Per-source handler, effect, binding, list-evaluator, and client-import registration belongs to one descriptor session rather than build orchestration.
|
|
193
|
+
- Pure collection expression and selector analysis is shared directly by React migration, reactive JSX, effects, and keyed-list discovery without a callback owned by `build.mjs`.
|
|
194
|
+
- Serializable route plans project through one pure capability manifest before runtime specialization and artifact emission.
|
|
195
|
+
- Component specialization, effect analysis, and keyed-list ownership remain in the main transformer until their AST-identity side tables can be replaced by explicit analysis results rather than moved behind large context objects.
|
|
196
|
+
- The continuation packet under `docs/next-architecture` fixes the Goal A patch sequence, output/performance gates, and explicit decision boundaries for deferred optimization, state/resource research, routing, and React compatibility.
|
|
197
|
+
|
|
198
|
+
## Cross-Cutting Performance Gates
|
|
199
|
+
|
|
200
|
+
Every migration feature must preserve:
|
|
201
|
+
|
|
202
|
+
- zero JavaScript for unaffected static routes;
|
|
203
|
+
- no new shared runtime bytes for routes that do not use the capability;
|
|
204
|
+
- complete initial HTML where data is build-known;
|
|
205
|
+
- direct DOM identity and cleanup semantics;
|
|
206
|
+
- no unexplained material build or browser regression;
|
|
207
|
+
- honest comparisons with matched content and behavior.
|
|
208
|
+
|
|
209
|
+
Production measurements receive one warm-up and at least seven interleaved builds. Browser measurements use rotating fresh profiles; use more runs when ranges overlap. Record raw/gzip artifacts, environment, raw arrays, medians, known losses, and deliberate limits.
|
|
210
|
+
|
|
211
|
+
## AI Migration Workflow
|
|
212
|
+
|
|
213
|
+
When migrating a React application:
|
|
214
|
+
|
|
215
|
+
1. Inspect routes, data timing, hooks, browser globals, router usage, packages, forms, and expected behavior.
|
|
216
|
+
2. Preserve ordinary React-shaped source where current Kudzu supports it.
|
|
217
|
+
3. Move build-known fetches into async pages/components.
|
|
218
|
+
4. Use `getStaticPaths()` for build-known dynamic routes.
|
|
219
|
+
5. Use native anchors unless same-document navigation is an explicit requirement.
|
|
220
|
+
6. Build and run browser checks after each route.
|
|
221
|
+
7. Reduce the first blocker before extending the compiler.
|
|
222
|
+
8. Measure generated HTML, raw/gzip JavaScript, build time, and affected interactions.
|
|
223
|
+
9. Document both the new support and its deliberate boundary.
|
|
224
|
+
|
|
225
|
+
## Explicit Non-Goals
|
|
226
|
+
|
|
227
|
+
- Running arbitrary React applications unchanged.
|
|
228
|
+
- React runtime, package ecosystem, islands, VDOM, hydration, or retained components.
|
|
229
|
+
- Shipping component functions to reproduce React rerender semantics.
|
|
230
|
+
- A default SPA router or global client application runtime.
|
|
231
|
+
- Request-time SSR, server actions, or a hidden application server.
|
|
232
|
+
- General state, stream, scheduler, widget, plugin, chart, map, editor, or virtualization frameworks.
|
|
233
|
+
- Implementing speculative compatibility because an API exists in React.
|
|
234
|
+
|
|
235
|
+
## Completion Definition
|
|
236
|
+
|
|
237
|
+
A migration feature is complete only when:
|
|
238
|
+
|
|
239
|
+
- it comes from a real or reduced conventional React fixture;
|
|
240
|
+
- ordinary source structure is preserved where safely compilable;
|
|
241
|
+
- static HTML remains the initial document;
|
|
242
|
+
- generated JavaScript is capability-specific and absent when unused;
|
|
243
|
+
- diagnostics explain unsupported nearby forms;
|
|
244
|
+
- browser tests prove behavior, ownership, and identity where applicable;
|
|
245
|
+
- performance and output impact are recorded;
|
|
246
|
+
- `npm run check` and `npm test` pass;
|
|
247
|
+
- public documentation states support, limits, and architecture tradeoffs.
|
package/PERFORMANCE.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Performance Records
|
|
2
|
+
|
|
3
|
+
## 0.8.16 Compiler Analysis Boundaries
|
|
4
|
+
|
|
5
|
+
Measured UTC 2026-08-08 on Apple M3, 8 logical CPUs, 8 GiB RAM, macOS 26.5.2 / Darwin 25.5.0, Node 25.6.1, and npm 11.18.0. Baseline `0.8.15` commit `8405d29` and the `0.8.16` release candidate used detached worktrees on the same temporary volume with identical installed dependencies.
|
|
6
|
+
|
|
7
|
+
The tracked `worker-effects` fixture received two warm-ups per target followed by 21 clean production builds in round-robin alternating order. Cleanup remained outside timing. The measured distributions overlap; the 3.75% median difference remains below the 5% architecture gate and does not establish a material regression.
|
|
8
|
+
|
|
9
|
+
| Target | Build median | Worker raw / gzip | Window raw / gzip |
|
|
10
|
+
|---|---:|---:|---:|
|
|
11
|
+
| 0.8.15 baseline | 787.0 ms | 907 B / 475 B | 12,148 B / 5,427 B |
|
|
12
|
+
| 0.8.16 candidate | 816.5 ms | 907 B / 475 B | 12,148 B / 5,427 B |
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
0.8.15: [762.5,793.7,937.8,820.7,775.9,766.4,807.2,742.7,772.0,757.6,823.0,752.7,814.2,827.2,917.4,787.0,755.1,798.5,742.1,806.8,785.8]
|
|
16
|
+
0.8.16: [893.1,653.9,915.2,816.5,800.1,747.1,801.5,749.8,951.8,830.3,723.5,780.4,904.4,821.6,957.0,757.9,918.0,809.5,739.3,844.6,950.9]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The artifact comparison is exact for both graphs. It measures compiler clean-build startup plus the existing Worker fixture, not browser update latency or cross-framework performance.
|
|
20
|
+
|
|
21
|
+
## 0.7.12 Keyed Local State
|
|
22
|
+
|
|
23
|
+
Measured UTC 2026-08-02 on Apple M3, 8 logical CPUs, 8 GiB RAM, macOS 26.5.2 / Darwin 25.5.0, Node 25.6.1, npm 11.18.0, and Chrome 150.0.7871.187.
|
|
24
|
+
|
|
25
|
+
Targets were Kudzu 0.7.12 at commit `05e5cc248d425b0f30549cd0649df99291c5aa38`, React/React DOM 19.2.8, Vue 3.5.40, Svelte 5.56.8, and Vite 8.2.0. The Vite plugins were React 6.0.5, Vue 6.0.8, and Svelte 7.2.0.
|
|
26
|
+
|
|
27
|
+
### Fixture
|
|
28
|
+
|
|
29
|
+
- 1,000 keyed rows with matching visible content and controls.
|
|
30
|
+
- Each row owns local editing state and conditionally creates a read-only input.
|
|
31
|
+
- Operations run in order: edit row 500, reverse, remove row 500, re-add row 500.
|
|
32
|
+
- Edit and reverse retain row 500 DOM identity; reverse also retains its input and editing state.
|
|
33
|
+
- Removal disconnects the old row and input; re-add creates fresh non-editing DOM and state.
|
|
34
|
+
- All 28 measured browser profiles passed content, order, identity, and reset checks.
|
|
35
|
+
|
|
36
|
+
Kudzu emitted pre-rendered HTML plus capability ESM. React, Vue, and Svelte used Vite production CSR from an empty shell. Browser operation timing started only after each target had 1,000 rows, so it excludes initial rendering. Total output and JavaScript sizes are not architecture-equivalent comparisons.
|
|
37
|
+
|
|
38
|
+
### Method
|
|
39
|
+
|
|
40
|
+
- Builds: one clean warm-up per target, then seven clean measured builds in round-robin rotated order; cleanup remained outside timing.
|
|
41
|
+
- Browser: 31 round-robin rotated unthrottled runs per target, each in a fresh Chrome profile. A separate seven-profile run used 4x CDP CPU throttling.
|
|
42
|
+
- Timing: one in-page promise installs a <code>MutationObserver</code>, records <code>performance.now()</code>, dispatches the click, and resolves only after terminal DOM and identity predicates pass.
|
|
43
|
+
- Initial JavaScript: unique external module-script/static-import closure plus inline module bodies. Raw size is summed bytes; gzip is one deterministic compression over path-sorted concatenated bytes.
|
|
44
|
+
- Total output: sum of all regular production files.
|
|
45
|
+
|
|
46
|
+
### Medians
|
|
47
|
+
|
|
48
|
+
| Target | Initial rows | JS raw | JS gzip | Total output | Build | Edit | Reverse | Remove | Re-add |
|
|
49
|
+
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|
|
|
50
|
+
| Kudzu | Yes | 26,117 B | 8,610 B | 940,710 B | 238.051 ms | 0.5 ms | 4.2 ms | 1.3 ms | 1.9 ms |
|
|
51
|
+
| React CSR | No | 191,163 B | 59,564 B | 191,260 B | 185.665 ms | 2.1 ms | 7.5 ms | 2.4 ms | 1.9 ms |
|
|
52
|
+
| Vue CSR | No | 61,652 B | 24,018 B | 61,749 B | 198.550 ms | 0.9 ms | 3.8 ms | 1.3 ms | 0.9 ms |
|
|
53
|
+
| Svelte CSR | No | 35,208 B | 13,686 B | 35,305 B | 279.240 ms | 0.8 ms | 20.1 ms | 1.6 ms | 1.3 ms |
|
|
54
|
+
|
|
55
|
+
### Raw Build Times
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
Kudzu: [235.435, 238.051, 237.118, 250.086, 254.562, 251.422, 237.609]
|
|
59
|
+
React: [187.010, 185.665, 186.299, 185.506, 183.472, 186.375, 184.815]
|
|
60
|
+
Vue: [200.253, 198.494, 197.007, 203.240, 198.550, 197.475, 200.469]
|
|
61
|
+
Svelte:[281.211, 285.172, 278.421, 279.240, 277.810, 279.036, 281.426]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Corrected Browser Distributions
|
|
65
|
+
|
|
66
|
+
The first seven-profile run used external CDP polling and was discarded: protocol roundtrips added roughly 42–49 ms to reverse and produced unstable 4–10 ms bands for short operations. The corrected run measures completion entirely in-page. Values below are min / median / max across 31 fresh profiles.
|
|
67
|
+
|
|
68
|
+
| Target | Edit | Reverse | Remove | Re-add |
|
|
69
|
+
|---|---:|---:|---:|---:|
|
|
70
|
+
| Kudzu | 0.3 / 0.5 / 0.6 | 3.7 / 4.2 / 4.8 | 0.9 / 1.3 / 1.8 | 1.7 / 1.9 / 3.0 |
|
|
71
|
+
| React CSR | 1.9 / 2.1 / 2.4 | 7.1 / 7.5 / 8.3 | 2.0 / 2.4 / 3.4 | 1.7 / 1.9 / 2.7 |
|
|
72
|
+
| Vue CSR | 0.7 / 0.9 / 1.0 | 3.5 / 3.8 / 4.1 | 1.1 / 1.3 / 1.6 | 0.8 / 0.9 / 1.2 |
|
|
73
|
+
| Svelte CSR | 0.6 / 0.8 / 1.2 | 19.2 / 20.1 / 21.6 | 1.4 / 1.6 / 1.8 | 1.2 / 1.3 / 1.5 |
|
|
74
|
+
|
|
75
|
+
### Corrected 4x CPU Medians
|
|
76
|
+
|
|
77
|
+
| Target | Edit | Reverse | Remove | Re-add |
|
|
78
|
+
|---|---:|---:|---:|---:|
|
|
79
|
+
| Kudzu | 2.3 ms | 17.3 ms | 5.9 ms | 8.6 ms |
|
|
80
|
+
| React CSR | 8.5 ms | 30.3 ms | 10.5 ms | 8.4 ms |
|
|
81
|
+
| Vue CSR | 3.2 ms | 14.8 ms | 5.4 ms | 4.1 ms |
|
|
82
|
+
| Svelte CSR | 3.5 ms | 78.6 ms | 6.3 ms | 6.1 ms |
|
|
83
|
+
|
|
84
|
+
The observer validates DOM mutation completion, not paint or compositor presentation. Synthetic clicks exclude hardware input latency, and 0.1 ms timer quantization matters for sub-millisecond edits. The fixture measures one keyed local-state workload, not general framework performance.
|
|
85
|
+
|
|
86
|
+
## 2026-08-03 Structural SVG And Link Lowering
|
|
87
|
+
|
|
88
|
+
Measured on Intel Core i5-9500 (6 cores), 32 GB RAM, Linux 6.17.0-19-generic, Node 24.14.0, npm 11.9.0, and Chrome 142.0.7444.175. The worktree was based on Kudzu 0.7.21 with the unreleased structural SVG and React Router `Link` changes.
|
|
89
|
+
|
|
90
|
+
The structural fixture rendered 1,000 keyed rows plus one reactive conditional. SVG and HTML targets used the same state and operation sequence: conditional toggle, row 500 update, reverse, row 500 removal, and one append. All 31 fresh profiles per target passed content, namespace, and retained reverse-identity checks. Builds received one clean warm-up followed by seven clean round-robin runs; cleanup was outside timing. Browser targets alternated order across 31 fresh profiles each, with completion measured in-page by `MutationObserver`.
|
|
91
|
+
|
|
92
|
+
### Medians
|
|
93
|
+
|
|
94
|
+
| Target | Build | JS raw | JS gzip | Total output | Conditional | Update | Reverse | Remove | Add |
|
|
95
|
+
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|
|
|
96
|
+
| SVG | 404.291 ms | 23,989 B | 8,079 B | 149,500 B | 0.8 ms | 1.9 ms | 8.3 ms | 2.4 ms | 3.5 ms |
|
|
97
|
+
| HTML control | 391.427 ms | 23,656 B | 8,000 B | 144,894 B | 0.7 ms | 1.8 ms | 8.3 ms | 2.5 ms | 3.6 ms |
|
|
98
|
+
|
|
99
|
+
SVG added 333 B raw / 79 B aggregate gzip JavaScript to this matched capability graph. Its build median was 3.29% higher. Browser medians differed by +0.1 ms conditional, +0.1 ms update, 0.0 ms reverse, -0.1 ms remove, and -0.1 ms add. The sub-millisecond differences are within timer quantization and overlapping fresh-profile ranges; no material SVG browser regression was established.
|
|
100
|
+
|
|
101
|
+
The static `Link` fixture and an already base-prefixed native-anchor control emitted byte-identical 248 B HTML, zero JavaScript, and no other files. Their clean build medians were 269.386 ms and 267.514 ms respectively, a 0.70% difference within the observed run variation.
|
|
102
|
+
|
|
103
|
+
### Raw Build Times
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
SVG: [379.646, 389.564, 435.431, 429.248, 423.114, 395.475, 404.291]
|
|
107
|
+
HTML: [373.381, 379.176, 420.158, 431.850, 401.762, 391.427, 381.916]
|
|
108
|
+
Link: [255.944, 276.585, 262.099, 322.057, 269.386, 259.338, 302.837]
|
|
109
|
+
Anchor:[262.150, 267.514, 262.529, 272.420, 270.237, 261.387, 279.634]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Raw Browser Times
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
SVG conditional: [0.8,0.8,0.7,0.8,0.7,1.5,1.0,0.8,0.9,0.8,0.8,0.7,0.8,1.1,0.6,0.6,0.7,0.9,0.7,0.8,0.9,1.5,0.9,0.8,0.8,0.8,0.7,1.0,0.7,0.6,0.9]
|
|
116
|
+
SVG update: [1.9,1.7,1.8,1.5,1.7,2.2,2.2,2.8,2.0,1.9,1.7,2.9,1.7,1.9,1.7,1.6,1.9,1.9,1.9,1.8,3.8,3.3,2.1,3.3,1.8,1.7,1.7,1.8,1.9,1.7,1.9]
|
|
117
|
+
SVG reverse: [9.1,7.9,8.3,7.4,7.9,12.7,12.5,10.2,12.8,8.0,7.9,10.0,7.9,8.4,7.7,7.5,7.3,9.1,8.6,9.0,9.8,9.1,9.2,9.9,8.0,8.2,7.7,7.9,7.8,8.4,7.6]
|
|
118
|
+
SVG remove: [2.4,2.1,2.5,2.2,2.3,3.4,3.3,4.1,8.9,2.7,2.2,2.7,2.3,2.6,3.2,2.3,2.1,3.0,2.3,2.6,3.6,4.1,6.3,2.4,2.5,2.1,2.3,2.2,2.3,2.1,2.3]
|
|
119
|
+
SVG add: [3.4,3.3,4.4,2.9,3.1,8.1,5.3,13.0,4.1,6.0,3.2,4.0,3.4,3.6,4.4,3.1,3.0,4.0,3.6,4.0,6.4,4.3,4.9,3.5,3.3,2.9,3.3,2.9,3.4,3.1,3.2]
|
|
120
|
+
HTML conditional:[0.6,0.6,0.6,0.5,0.8,0.8,2.0,4.1,0.8,0.7,2.6,0.7,0.6,0.6,0.7,0.6,0.6,0.6,1.0,0.7,0.7,0.7,1.1,0.8,0.9,0.9,0.7,0.7,0.7,1.5,0.7]
|
|
121
|
+
HTML update: [1.9,1.7,1.8,1.7,2.2,2.8,2.2,1.8,1.8,2.0,1.9,1.8,1.7,1.8,1.7,1.6,1.5,1.4,1.9,2.2,2.6,5.1,2.0,2.8,2.1,1.9,1.7,1.8,1.7,1.8,1.9]
|
|
122
|
+
HTML reverse: [7.4,6.4,6.9,7.3,10.6,10.3,15.3,27.8,8.4,11.6,7.2,8.8,7.1,6.9,6.6,6.5,6.2,6.2,10.3,11.6,8.2,10.6,14.2,11.3,8.5,8.4,7.0,8.6,8.3,6.7,7.0]
|
|
123
|
+
HTML remove: [2.6,2.1,2.2,2.3,3.6,3.7,6.1,10.2,2.4,3.4,2.4,4.7,2.0,2.2,2.0,2.3,2.1,2.1,3.0,3.7,2.3,3.0,2.8,7.0,5.1,2.8,2.3,2.2,2.6,2.5,2.2]
|
|
124
|
+
HTML add: [3.7,3.2,3.1,3.7,4.2,6.6,11.7,8.8,3.3,6.7,3.3,5.5,3.1,3.0,3.0,3.3,2.9,2.9,8.7,7.9,3.3,5.6,4.2,6.0,3.8,7.0,3.3,3.3,3.2,3.3,3.6]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The browser ranges were SVG conditional 0.6–1.5 ms, update 1.5–3.8 ms, reverse 7.3–12.8 ms, remove 2.1–8.9 ms, add 2.9–13.0 ms; HTML conditional 0.5–4.1 ms, update 1.4–5.1 ms, reverse 6.2–27.8 ms, remove 2.0–10.2 ms, add 2.9–11.7 ms. Measurements cover DOM mutation completion, not paint/compositing, and use unthrottled synthetic clicks. The SVG and HTML markup is behavior-matched but not byte-identical, so total HTML/output differences are not attributed solely to namespace support.
|
|
128
|
+
|
|
129
|
+
The maintained Worker benchmark also passed on this worktree: build runs `[874.5, 778.5, 757.3, 880.3, 713.7, 672.8, 515.3]` ms, median 757.3 ms; Worker graph 907 B raw / 477 B gzip; window graph 11,960 B raw / 5,353 B gzip. Its historical M3 build timings are not comparable to this Linux machine.
|
|
130
|
+
|
|
131
|
+
## 2026-08-04 Large React Migration
|
|
132
|
+
|
|
133
|
+
Measured on Intel Core i5-9500, Linux 6.17.0-19-generic, Node 24.14.0, npm 11.9.0, and Chrome 142.0.7444.175. The worktree was based on Kudzu 0.7.25 with unreleased React-compatible JSX typing, setter-adapter component specialization, and TypeScript-only collection-wrapper unwrapping.
|
|
134
|
+
|
|
135
|
+
The generated Trailboard fixture contains 2,000 imported records, 500 initially rendered keyed cards, one reactive search reducing the list to one card, one keyed row-local state update, and 53 routes including 50 report pages. React/Vite has 60 source files, 2,561 lines, and 279,966 bytes; Kudzu has 58 source files, 2,440 lines, and 273,752 bytes because file routes replace the React root/router entries.
|
|
136
|
+
|
|
137
|
+
Builds received one warm-up followed by seven alternating clean TypeScript-check plus production-build runs. Browser targets alternated across seven runs, each with a new Chrome profile and warm local server. An in-page async evaluation measured navigation start to the expected 500-card DOM, event dispatch to the one-card filtered DOM, and click dispatch to the row-local state attribute update.
|
|
138
|
+
|
|
139
|
+
### Medians
|
|
140
|
+
|
|
141
|
+
| Metric | React/Vite | Kudzu | Kudzu difference |
|
|
142
|
+
|---|---:|---:|---:|
|
|
143
|
+
| Clean typecheck + build | 3,188.27 ms | 2,759.69 ms | -13.44% |
|
|
144
|
+
| Initial 500-card DOM | 261.80 ms | 280.10 ms | +6.99% |
|
|
145
|
+
| Filter 500 cards to one | 13.90 ms | 28.30 ms | +103.60% |
|
|
146
|
+
| Toggle keyed row state | 5.80 ms | 5.30 ms | -8.62% |
|
|
147
|
+
| JavaScript gzip | 97,885 B | 12,191 B | -87.55% |
|
|
148
|
+
|
|
149
|
+
Kudzu's filter path is the clear loss in this fixture and is the next measured optimization candidate. Initial readiness and row-local state are in overlapping fresh-profile ranges, while the build and JavaScript-size wins are material.
|
|
150
|
+
|
|
151
|
+
### Selector Optimization Follow-up
|
|
152
|
+
|
|
153
|
+
The collection evaluator was changed to cache selector state reads for one execution and avoid recursive rest-array allocation, `slice()`, and `map()` in hot expression nodes. A second seven-run alternating fresh-profile measurement used the same fixture and method.
|
|
154
|
+
|
|
155
|
+
| Metric | Baseline | Optimized | Change |
|
|
156
|
+
|---|---:|---:|---:|
|
|
157
|
+
| Kudzu filter 500 cards to one | 28.30 ms | 22.00 ms | -22.26% |
|
|
158
|
+
| React filter control | 13.90 ms | 13.60 ms | -2.16% |
|
|
159
|
+
| Kudzu gap versus React | +103.60% | +61.76% | -41.84 points |
|
|
160
|
+
| Kudzu JavaScript gzip | 12,191 B | 12,310 B | +0.98% |
|
|
161
|
+
|
|
162
|
+
The allocation/state-cache change materially improves the path without changing list ownership or cleanup semantics. The remaining gap is concentrated in generic keyed reconciliation and per-row ownership cleanup when 499 mounted rows are removed at once. An attempted detached batch cleanup was discarded because it broke the remove-all/add-new-key transition; it is not part of the retained change.
|
|
163
|
+
|
|
164
|
+
```text
|
|
165
|
+
Optimized Kudzu filter: [22.8, 22.5, 20.8, 19.2, 22.0, 22.5, 20.7]
|
|
166
|
+
Optimized React filter: [14.9, 14.9, 15.6, 12.9, 13.6, 13.4, 12.9]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Indexed Row Release Follow-up
|
|
170
|
+
|
|
171
|
+
Profiling separated selector evaluation, which took about 3 ms, from the remaining per-row lifecycle work. The compiler now marks keyed rows for direct state-indexed release only when they have row-local state but no row effects, nested lists, or shared text targets. Binding and condition registrations are released by state ID; all other row shapes retain the existing DOM-owned unmount path.
|
|
172
|
+
|
|
173
|
+
Because the seven-run ranges overlapped, the final isolated measurement used one warm-up and 21 alternating samples:
|
|
174
|
+
|
|
175
|
+
| Metric | React/Vite | Kudzu | Kudzu difference |
|
|
176
|
+
|---|---:|---:|---:|
|
|
177
|
+
| Clean typecheck + build | 3,024.33 ms | 2,664.58 ms | -11.90% |
|
|
178
|
+
| Initial 500-card DOM | 256.90 ms | 256.00 ms | -0.35% |
|
|
179
|
+
| Filter 500 cards to one | 13.90 ms | 13.50 ms | -2.88% |
|
|
180
|
+
| Toggle keyed row state | 5.70 ms | 5.30 ms | -7.02% |
|
|
181
|
+
| JavaScript gzip | 97,885 B | 12,442 B | -87.29% |
|
|
182
|
+
|
|
183
|
+
The final Kudzu filter median is 52.30% below the preserved 28.30 ms baseline and 2.88% faster than React on the matched operation. The fast path adds 132 B gzip over the selector-only follow-up. Raw 21-run arrays and generated reports are stored in the benchmark fixture.
|
|
184
|
+
|
|
185
|
+
### Artifacts
|
|
186
|
+
|
|
187
|
+
| Target | HTML raw / gzip | CSS raw / gzip | JS raw / gzip |
|
|
188
|
+
|---|---:|---:|---:|
|
|
189
|
+
| React/Vite | 168 / 143 B | 3,649 / 1,365 B | 465,830 / 97,885 B |
|
|
190
|
+
| Kudzu | 702,854 / 65,355 B | 4,225 / 1,442 B | 30,175 / 12,191 B |
|
|
191
|
+
|
|
192
|
+
React/Vite emits one CSR shell, while Kudzu's HTML total includes 53 complete documents. The initial-readiness comparison therefore measures the product delivery difference rather than equivalent markup. Gzip totals sum files independently; clients do not download all 53 Kudzu documents for one route.
|
|
193
|
+
|
|
194
|
+
### Raw Build Times
|
|
195
|
+
|
|
196
|
+
```text
|
|
197
|
+
React: [3156.83, 3190.33, 3155.66, 3188.27, 3115.12, 3201.29, 3268.69]
|
|
198
|
+
Kudzu: [2777.83, 2792.51, 2659.28, 2655.26, 2706.48, 2759.69, 2812.61]
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Raw Browser Times
|
|
202
|
+
|
|
203
|
+
```text
|
|
204
|
+
React initial: [293.3, 230.8, 272.6, 292.0, 261.8, 261.8, 235.7]
|
|
205
|
+
Kudzu initial: [277.3, 280.6, 287.9, 292.4, 276.1, 254.8, 280.1]
|
|
206
|
+
React filter: [13.9, 15.5, 15.3, 14.4, 13.0, 13.5, 13.8]
|
|
207
|
+
Kudzu filter: [28.3, 31.7, 29.1, 28.9, 26.4, 24.4, 24.1]
|
|
208
|
+
React toggle: [5.7, 6.1, 5.8, 5.8, 5.6, 5.8, 5.7]
|
|
209
|
+
Kudzu toggle: [5.2, 5.4, 5.3, 5.6, 5.3, 5.2, 5.3]
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The reproducible fixture, benchmark harness, environment record, and JSON results are under `/home/kft/Documents/etc/demo/large-benchmark`.
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Kudzu compiles ordinary React-shaped TypeScript and TSX into complete static HTM
|
|
|
14
14
|
|
|
15
15
|
> Experimental `0.8.x`: the compiler API and supported TSX surface may change.
|
|
16
16
|
|
|
17
|
-
**Latest release: 0.8.
|
|
17
|
+
**Latest release: 0.8.16 - Compiler analysis boundaries.** Per-source descriptors, pure collection analysis, command specialization, Zustand migration, and route capability planning now have focused compiler ownership while preserving generated output and runtime behavior. Read the [release notes](./RELEASES.md#0816---compiler-analysis-boundaries), open the [release page](https://kudzujs.cloud/releases/0.8.16), or follow the [next architecture packet](./docs/next-architecture/README.md).
|
|
18
18
|
|
|
19
19
|
- [Documentation](https://kudzujs.cloud/docs)
|
|
20
20
|
- [Installation guide](https://kudzujs.cloud/docs#install)
|
package/RELEASES.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Kudzu Releases
|
|
2
2
|
|
|
3
|
+
## 0.8.16 - Compiler analysis boundaries
|
|
4
|
+
|
|
5
|
+
Kudzu 0.8.16 continues the behavior-preserving compiler decomposition: source-local descriptors, the pure collection language, command fast paths, reduced Zustand migration, and route capability projection now have explicit ownership outside build orchestration.
|
|
6
|
+
|
|
7
|
+
### Changed in 0.8.16
|
|
8
|
+
|
|
9
|
+
- One descriptor session owns deterministic native-handler, effect, reactive-binding, list-evaluator, and client-import registration for each source module.
|
|
10
|
+
- Collection roots, aliases, imported transforms, selector pipelines, and pure expression IR are shared directly by React migration, reactive JSX, effects, and keyed-list discovery.
|
|
11
|
+
- Direct setter arithmetic and literals remain compact command descriptors instead of becoming generic browser handler functions.
|
|
12
|
+
- Reduced Zustand store analysis and normalization now share one focused compiler pass while retaining the existing accepted and rejected migration boundary.
|
|
13
|
+
- Rendered route plans project through one pure capability manifest before runtime specialization and artifact emission.
|
|
14
|
+
- Route capability metadata is keyed by route identity, and effect descriptor registry ownership remains private to the source descriptor session.
|
|
15
|
+
|
|
16
|
+
### Architecture continuation
|
|
17
|
+
|
|
18
|
+
- `docs/next-architecture` records the current compiler responsibility map, Goal A through D decisions, the `0.8.17` through `0.8.22` Goal A sequence, version policy, and performance gates.
|
|
19
|
+
- Goal A proceeds with a sparse JSON-safe ModuleIR and one Counter command vertical slice next; it does not add a VDOM, hydration, component rerender, store/resource runtime, router, or React island.
|
|
20
|
+
- Component specialization, keyed-list ownership, and effect analysis remain in the main transformer until their AST-identity side tables can be replaced by explicit results rather than hidden behind large context objects.
|
|
21
|
+
|
|
22
|
+
### Validation
|
|
23
|
+
|
|
24
|
+
- `build.mjs` is 3,837 lines, down from 4,351 in 0.8.15, while retaining build orchestration and the intentionally coupled semantic transformer.
|
|
25
|
+
- The complete suite passes 163/163 tests, including focused descriptor, collection IR, command, Zustand, and capability-manifest contracts.
|
|
26
|
+
- A 21-run round-robin comparison on the same Apple M3 temp volume retained exact Worker and window graph bytes. The `0.8.16` 816.5 ms median was 3.75% above the `0.8.15` 787.0 ms baseline with overlapping distributions, below the 5% architecture gate; raw arrays and environment are recorded in `PERFORMANCE.md`.
|
|
27
|
+
- `create-kudzu` remains 0.1.101 because its template already accepts `@kudzujs/core@^0.8.15` and did not change.
|
|
28
|
+
|
|
29
|
+
### Upgrade
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install @kudzujs/core@^0.8.16
|
|
33
|
+
```
|
|
34
|
+
|
|
3
35
|
## 0.8.15 - Compiler architecture
|
|
4
36
|
|
|
5
37
|
Kudzu 0.8.15 makes the compiler's actual architecture explicit in source and public documentation: React-shaped TSX is normalized, analyzed into capability descriptors, and emitted as complete HTML plus route-specific ESM.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Kudzu Architecture Continuation
|
|
2
|
+
|
|
3
|
+
This directory is the continuation packet after `0.8.15`. Planned versions remain plans until package metadata and release records mark them complete.
|
|
4
|
+
|
|
5
|
+
The top-level [`GOAL_A.md`](../../GOAL_A.md) and [`GOAL_B.md`](../../GOAL_B.md) are historical completed capability records. Do not overwrite or reinterpret them. The Goal A/B/C/D names in this directory refer to the next architecture discussion:
|
|
6
|
+
|
|
7
|
+
| Goal | Decision | Start condition |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| A: compiler foundation | Approved for execution | Continue with `0.8.17` after the `0.8.16` analysis-boundary release |
|
|
10
|
+
| B: optimization benchmarks | Deferred | Goal A complete and its output baseline recorded |
|
|
11
|
+
| C: state/resource model | Research only | Reduced fixtures expose a limitation |
|
|
12
|
+
| D: routing compatibility | Current behavior preserved | Revisit only with migration evidence and invariant review |
|
|
13
|
+
|
|
14
|
+
## Required Invariants
|
|
15
|
+
|
|
16
|
+
- Every route remains a complete static HTML document.
|
|
17
|
+
- Build-known static routes emit zero JavaScript.
|
|
18
|
+
- Interactive routes emit only capabilities they use.
|
|
19
|
+
- React, hydration, a VDOM, retained browser components, and React islands remain forbidden.
|
|
20
|
+
- Native anchors are the default; same-document navigation remains explicit and route-group scoped.
|
|
21
|
+
- Compiler specialization preserves ordinary React-shaped TSX where it can be analyzed safely.
|
|
22
|
+
- Unsupported nearby forms fail with source-located diagnostics.
|
|
23
|
+
|
|
24
|
+
## Reading Order
|
|
25
|
+
|
|
26
|
+
1. [`compiler-current-architecture.md`](./compiler-current-architecture.md): exact current responsibilities and data flow.
|
|
27
|
+
2. [`goal-a-compiler-foundation.md`](./goal-a-compiler-foundation.md): approved extraction and generator work.
|
|
28
|
+
3. [`versioning.md`](./versioning.md): planned patch sequence and completion rules.
|
|
29
|
+
4. [`performance-gates.md`](./performance-gates.md): output, build, and browser gates.
|
|
30
|
+
5. [`goal-b-optimization-benchmarks.md`](./goal-b-optimization-benchmarks.md): deferred measured optimization.
|
|
31
|
+
6. [`goal-c-state-resource-research.md`](./goal-c-state-resource-research.md): research boundary only.
|
|
32
|
+
7. [`goal-d-routing-compatibility-decisions.md`](./goal-d-routing-compatibility-decisions.md): routing and islands decisions.
|
|
33
|
+
|
|
34
|
+
## Resume Checklist
|
|
35
|
+
|
|
36
|
+
- [ ] Read [`MIGRATION_ROADMAP.md`](../../MIGRATION_ROADMAP.md) and this directory before planning migration work.
|
|
37
|
+
- [ ] Confirm `package.json` still reports the actual current version; never infer release status from this plan.
|
|
38
|
+
- [ ] Inspect the worktree and preserve unrelated or uncommitted changes.
|
|
39
|
+
- [ ] Start only the next incomplete Goal A patch in [`versioning.md`](./versioning.md).
|
|
40
|
+
- [ ] Preserve accepted syntax, diagnostics, route plans, HTML, asset selection, and browser ownership behavior.
|
|
41
|
+
- [ ] Run the repository checks required by that implementation patch and record output deltas.
|
|
42
|
+
- [ ] Update this packet when a planned boundary changes; update release records only when a release actually occurs.
|