@kudzujs/core 0.8.48 → 0.8.49

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.
@@ -2,7 +2,7 @@
2
2
 
3
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
4
 
5
- The executable post-`0.8.48` compiler and large-application sequence is maintained in [`docs/next-architecture/large-application-ai-native-roadmap.md`](./docs/next-architecture/large-application-ai-native-roadmap.md). Follow its PR dependencies for implementation work; this document remains authoritative when selecting or accepting a migration capability.
5
+ The executable post-`0.8.49` compiler and large-application sequence is maintained in [`docs/next-architecture/large-application-ai-native-roadmap.md`](./docs/next-architecture/large-application-ai-native-roadmap.md). Follow its PR dependencies for implementation work; this document remains authoritative when selecting or accepting a migration capability.
6
6
 
7
7
  [`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.
8
8
 
@@ -146,6 +146,7 @@ This queue orders the next investigations by general migration value. Start only
146
146
  - In `0.8.46`, the same Notes migration may omit action-only setters from its public Context type and authored Provider value when the corresponding state remains exposed. Kudzu restores those setters only in build scratch so existing concrete state operations, RouteIR signals, CRUD behavior, and zero-Context runtime output remain unchanged. Fully hidden action state and exposed setters without state remain diagnosed.
147
147
  - In `0.8.47`, a specialized setter-callback child may initialize local state directly from one primitive parent state prop. Build scratch reads the parent signal's build value while retaining the structural prop signal for handlers/effects; direct object/array props, aliases, and composed initializer expressions remain diagnosed.
148
148
  - In `0.8.48`, one setter-callback prop may be called once from each of multiple direct intrinsic event handlers in the specialized leaf. Each call lowers independently to the same parent signal; forwarding fan-out, aliases, non-handler uses, and repeated calls inside one handler remain diagnosed, and no callback registry or handler runtime is added.
149
+ - In `0.8.49`, one component may forward the same destructured setter callback directly through multiple child component `on*` props. Each branch specializes independently to the original parent signal within the existing three-boundary limit; aliases, ordinary props, spreads, and a fourth boundary remain diagnosed.
149
150
 
150
151
  ### Completed In 0.8.10
151
152
 
package/PERFORMANCE.md CHANGED
@@ -6,7 +6,11 @@ Reproducibility classes: `npm run benchmark`, `npm run benchmark:keyed`, `npm ru
6
6
 
7
7
  The maintained 2026-08-13 comparison used Node 24.14.0 and an Intel Core i5-9500 Linux x64 host, one warm-up, and seven alternating fresh-process samples against clean `v0.8.44`. A narrow fast path skips Kudzu semantic transformation for 450 plain `.ts` modules whose runtime edges are exclusively resolvable relative TypeScript imports or exports; all other modules retain the existing transformer. Compile median fell from 2,323.9 ms to 1,413.2 ms (39.2%) and clean-build median from 3,325.3 ms to 2,382.4 ms (28.4%); every paired sample improved. Compile peak-RSS median fell from 571.2 MiB to 552.6 MiB, while build peak RSS was 570.9 MiB versus 568.8 MiB. Compiler scratch fell from 7,328,390 to 1,971,061 bytes. Both targets emitted the same 50 static HTML files, 10,980 bytes, and deploy SHA-256 `e107d78a7f55bc8a1af0ea6e53efeffa19b3d44d21c892484d103fa346e7ba7b`. This is a source-scale compiler comparison, not a cross-framework result.
8
8
 
9
- ## Current 0.8.48 Release Snapshot
9
+ ## Current 0.8.49 Release Snapshot
10
+
11
+ Kudzu 0.8.49 broadens compiler-only setter-callback validation to direct child fan-out while retaining the existing command descriptors and browser runtimes. No new performance claim is made.
12
+
13
+ ## Maintained 0.8.48 Release Snapshot
10
14
 
11
15
  Kudzu 0.8.48 broadens compiler-only setter-callback validation to multiple direct intrinsic handlers while retaining the existing command descriptors and browser runtimes. No new performance claim is made.
12
16
 
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.48 - Multi-handler setter callbacks.** One specialized setter-callback prop may be called once from each of multiple direct intrinsic event handlers. Kudzu lowers every call to the same parent signal without shipping callbacks or a component runtime. Read the [release notes](./RELEASES.md#0848---multi-handler-setter-callbacks), open the [release page](https://github.com/kudzujs/kudzu/releases/tag/v0.8.48), or follow the [architecture packet](./docs/next-architecture/README.md).
17
+ **Latest release: 0.8.49 - Setter callback fan-out.** One component may forward the same destructured setter callback directly to multiple child controls. Kudzu specializes every branch to the original parent signal without shipping callbacks or a component runtime. Read the [release notes](./RELEASES.md#0849---setter-callback-fan-out), open the [release page](https://github.com/kudzujs/kudzu/releases/tag/v0.8.49), or follow the [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,34 @@
1
1
  # Kudzu Releases
2
2
 
3
+ ## 0.8.49 - Setter callback fan-out
4
+
5
+ Kudzu 0.8.49 lets one component forward the same destructured setter callback directly through multiple child component `on*` props.
6
+
7
+ ### Changed in 0.8.49
8
+
9
+ - A specialized component may pass one callback prop directly to multiple child controls.
10
+ - Each child branch specializes independently to the original parent state signal.
11
+ - Fan-out composes with multiple direct intrinsic handlers within the existing three-boundary limit.
12
+ - Aliases, ordinary prop names, spreads, intermediate adapters, and a fourth callback boundary remain source-diagnosed.
13
+
14
+ ### Output and performance
15
+
16
+ - Every leaf continues to emit its existing concrete state-operation descriptor.
17
+ - No callback registry, component runtime, browser runtime module, or public Kudzu API is added.
18
+ - This release makes no new performance claim.
19
+
20
+ ### Validation
21
+
22
+ - `npm run check`, `npm test`, and `npm run test:package` pass with all 214 tests and 164 generated pages.
23
+ - A relative component fans one callback out to two child controls whose click descriptors target the same parent signal.
24
+ - Existing repeated-call and fourth-boundary negative fixtures retain their source diagnostics.
25
+
26
+ ### Upgrade
27
+
28
+ ```bash
29
+ npm install @kudzujs/core@^0.8.49
30
+ ```
31
+
3
32
  ## 0.8.48 - Multi-handler setter callbacks
4
33
 
5
34
  Kudzu 0.8.48 lets one compiler-specialized setter-callback prop be called once from each of multiple direct intrinsic event handlers.
@@ -11,7 +11,7 @@ The top-level [`GOAL_A.md`](../../GOAL_A.md) and [`GOAL_B.md`](../../GOAL_B.md)
11
11
  | C: state/resource model | Research only | Reduced fixtures expose a limitation |
12
12
  | D: routing compatibility | Current behavior preserved | Revisit only with migration evidence and invariant review |
13
13
 
14
- The active post-`0.8.48` implementation sequence is [`large-application-ai-native-roadmap.md`](./large-application-ai-native-roadmap.md). P0.12 validation, property-level object-state dependencies, direct three-boundary callback/ref ownership, direct primitive prop state initialization, repeated direct leaf-handler callback use, collision-free and private Context action setters, measured route-entry output optimization, and the plain TypeScript source-scale fast path are complete; broader prop, callback, ref, and Context dataflow remains migration-backed work. The plan orders compiler semantic generalization, large-application foundations, compatibility boundaries, AI tooling, and production validation without changing the invariants below.
14
+ The active post-`0.8.49` implementation sequence is [`large-application-ai-native-roadmap.md`](./large-application-ai-native-roadmap.md). P0.12 validation, property-level object-state dependencies, direct three-boundary callback/ref ownership, direct primitive prop state initialization, repeated direct leaf-handler callback use, direct child callback fan-out, collision-free and private Context action setters, measured route-entry output optimization, and the plain TypeScript source-scale fast path are complete; broader prop, callback, ref, and Context dataflow remains migration-backed work. The plan orders compiler semantic generalization, large-application foundations, compatibility boundaries, AI tooling, and production validation without changing the invariants below.
15
15
 
16
16
  ## Required Invariants
17
17
 
@@ -1,6 +1,6 @@
1
1
  # Current Compiler Architecture
2
2
 
3
- This maps the current `0.8.48` architecture, built on the completed `0.8.23` Goal A compiler foundation. File and function names are the stable references; line numbers are intentionally omitted because later work may still move code.
3
+ This maps the current `0.8.49` architecture, built on the completed `0.8.23` Goal A compiler foundation. File and function names are the stable references; line numbers are intentionally omitted because later work may still move code.
4
4
 
5
5
  ## Responsibility Map
6
6
 
@@ -379,7 +379,7 @@ function increment(value) { setCount(value + 1) }; increment(count)
379
379
  After the relevant P0 foundations, investigate capabilities in this order:
380
380
 
381
381
  1. Property-level derived dependencies over ordinary object state. **Completed in `0.8.40`:** direct property paths and top-level immutable primitive locals over object state reuse tagged DerivedIR, subscribe to the source signal, and compare selected values with `Object.is`; whole-object and dynamic dependencies remain rejected.
382
- 2. Multi-boundary component/prop/callback/ref/context dataflow. **Three-boundary callback/ref ownership completed in `0.8.43`; collision-free Context action-private state completed in `0.8.44`; action-only Provider setter exposure removed in `0.8.46`; direct primitive prop state initialization completed in `0.8.47`; repeated direct leaf-handler callback use completed in `0.8.48`:** forwarding preserves parent SignalIR, Context action lowering uses compiler-owned aliases when consumer locals reuse Provider state/setter names, action-required setters may remain compiler-only when their state is publicly exposed, specialized children may seed local state from a direct primitive parent signal, and one leaf callback may lower independently in multiple intrinsic handlers. A fourth callback boundary, callback fan-out/aliases, fully hidden Context state, and object/array prop initializers remain fail-closed. Broader prop, callback, ref, and Context graphs remain migration-led work.
382
+ 2. Multi-boundary component/prop/callback/ref/context dataflow. **Three-boundary callback/ref ownership completed in `0.8.43`; collision-free Context action-private state completed in `0.8.44`; action-only Provider setter exposure removed in `0.8.46`; direct primitive prop state initialization completed in `0.8.47`; repeated direct leaf-handler callback use completed in `0.8.48`; direct child callback fan-out completed in `0.8.49`:** forwarding preserves parent SignalIR, Context action lowering uses compiler-owned aliases when consumer locals reuse Provider state/setter names, action-required setters may remain compiler-only when their state is publicly exposed, specialized children may seed local state from a direct primitive parent signal, and one callback may branch through multiple component `on*` props and intrinsic handlers. A fourth callback boundary, callback aliases/non-handler uses, fully hidden Context state, and object/array prop initializers remain fail-closed. Broader prop, callback, ref, and Context graphs remain migration-led work.
383
383
  3. Package-neutral shared state/actions and migration of current Zustand internals.
384
384
  4. Browser-only package imports in owned effect/resource modules.
385
385
  5. ResourceIR from at least two independent WebSocket/SSE/SDK fixtures with the same semantics.
@@ -481,4 +481,4 @@ The first comparison is Kudzu versus React + Vite using the same agent, model, t
481
481
 
482
482
  ## Immediate Decision
483
483
 
484
- PR 1 through PR 12, the `0.8.40` property-dependency slice, the `0.8.41` and `0.8.43` direct multi-boundary callback/ref slices, the `0.8.44` Context alias slice, the `0.8.46` action-only Provider setter slice, the `0.8.47` direct primitive prop initializer slice, the `0.8.48` repeated direct leaf-handler callback slice, and the `0.8.42` measured route-output optimization are complete. Continue broader **component/prop/callback/ref/context dataflow** only from the next real migration blocker. Do not skip directly to a store, resource, router, virtualization, or ecosystem package feature.
484
+ PR 1 through PR 12, the `0.8.40` property-dependency slice, the `0.8.41` and `0.8.43` direct multi-boundary callback/ref slices, the `0.8.44` Context alias slice, the `0.8.46` action-only Provider setter slice, the `0.8.47` direct primitive prop initializer slice, the `0.8.48` repeated direct leaf-handler callback slice, the `0.8.49` direct child callback fan-out slice, and the `0.8.42` measured route-output optimization are complete. Continue broader **component/prop/callback/ref/context dataflow** only from the next real migration blocker. Do not skip directly to a store, resource, router, virtualization, or ecosystem package feature.
@@ -1,6 +1,6 @@
1
1
  # Planned Version Sequence
2
2
 
3
- This is an execution sequence, not release history. `0.8.16` through `0.8.48` are completed scopes represented by package/release records.
3
+ This is an execution sequence, not release history. `0.8.16` through `0.8.49` are completed scopes represented by package/release records.
4
4
 
5
5
  Keep each patch behavior-preserving and independently reviewable. If a boundary proves inseparable, revise this plan before combining releases; do not silently broaden a patch.
6
6
 
@@ -39,6 +39,7 @@ Keep each patch behavior-preserving and independently reviewable. If a boundary
39
39
  | `0.8.46` | Remove action-only setter fields from authored Context Provider APIs. | Compiler scratch restores required setters while Notes CRUD, RouteIR signals, concrete state operations, diagnostics, and zero Context runtime output pass. |
40
40
  | `0.8.47` | Initialize specialized child state from one direct primitive parent state prop. | Build-known primitive seeds, independent state ownership, existing handler specialization, and negative object/expression diagnostics pass without a runtime change. |
41
41
  | `0.8.48` | Allow one setter-callback prop in multiple direct intrinsic handlers. | Each handler lowers once to the same parent signal; repeated same-handler calls and escaped uses fail without a runtime change. |
42
+ | `0.8.49` | Fan one setter-callback prop out through multiple direct child component event props. | Every branch lowers to the original parent signal; aliases, ordinary props, spreads, and the fourth boundary fail without a runtime change. |
42
43
 
43
44
  ## Sequence Rules
44
45
 
@@ -1088,9 +1088,17 @@ function createKudzuTransformer({ semantic, handlerUrl, file, sourceFiles, sourc
1088
1088
  }
1089
1089
  collectReferences(component.body)
1090
1090
  if (!references.length) fail(element, `Setter-callback prop ${JSON.stringify(prop)} must be called by at least one intrinsic event handler`)
1091
- if (references.length === 1 && ts.isJsxExpression(references[0].parent) && ts.isJsxAttribute(references[0].parent.parent) && /^on[A-Z]/.test(references[0].parent.parent.name.text)) continue
1092
1091
  const handlers = new Set()
1093
1092
  for (const reference of references) {
1093
+ if (ts.isJsxExpression(reference.parent) && ts.isJsxAttribute(reference.parent.parent) && /^on[A-Z]/.test(reference.parent.parent.name.text)) {
1094
+ const attribute = reference.parent.parent
1095
+ const tag = attribute.parent?.parent && (ts.isJsxOpeningElement(attribute.parent.parent) || ts.isJsxSelfClosingElement(attribute.parent.parent)) ? attribute.parent.parent.tagName : undefined
1096
+ if (ts.isIdentifier(tag) && tag.text[0] !== tag.text[0].toLowerCase()) continue
1097
+ if (ts.isIdentifier(tag) && !handlers.has(attribute)) {
1098
+ handlers.add(attribute)
1099
+ continue
1100
+ }
1101
+ }
1094
1102
  if (!ts.isCallExpression(reference.parent) || reference.parent.expression !== reference) fail(reference, `Setter-callback prop ${JSON.stringify(prop)} must be called directly inside an intrinsic event handler`)
1095
1103
  let attribute
1096
1104
  for (let current = reference.parent; current && current !== component.body; current = current.parent) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kudzujs/core",
3
- "version": "0.8.48",
3
+ "version": "0.8.49",
4
4
  "description": "HTML-first TSX framework with synchronous state semantics and no virtual DOM",
5
5
  "type": "module",
6
6
  "license": "MIT",