@kudzujs/core 0.14.0 → 0.14.1

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/PERFORMANCE.md CHANGED
@@ -2,6 +2,33 @@
2
2
 
3
3
  Reproducibility classes: `npm run benchmark`, `npm run benchmark:keyed`, `npm run benchmark:native`, `npm run benchmark:module-cache`, `npm run benchmark:project-navigation`, `npm run benchmark:project-state`, and `npm run benchmark:source-scale` are maintained in this repository; `npm run benchmark:commerce` is a maintained paired runner over the public external storefront; older excluded-workspace sections are historical provenance only and are not current framework rankings.
4
4
 
5
+ ## 0.14.1 Nested Object-State Collections
6
+
7
+ Measured 2026-08-26 on Linux x64 with Node 24.14.0 and Chrome
8
+ 142.0.7444.175.
9
+
10
+ The project route now roots its selected project table and nested issue rows in
11
+ one direct `projectData.projects` field. Required Chrome proves immutable
12
+ whole-object replacement, nested insert/update/reorder/remove/re-add, retained
13
+ identity, latest handlers, descendant state release, and fresh remount. `/help`
14
+ remains 0 B JavaScript.
15
+
16
+ The application emits 44 files totaling 164,305 raw / 52,185 aggregate gzip
17
+ bytes with deploy SHA-256
18
+ `0a3b7e10b3447a76a9c04ef34ad7c2bfa30400ea53c9d16fc85b1c7cbf2ea203`.
19
+ The two-route session remains 17 JavaScript files and totals 74,826 raw / 26,204
20
+ aggregate gzip bytes. The delta from `0.14.0` includes the authored nested issue
21
+ controls and handlers plus one build-time validation-line edit and one production
22
+ list-runtime line; no semantic primitive, IR kind, compiler pass, runtime concept,
23
+ or public API was added.
24
+
25
+ Table update samples are
26
+ `[0.8, 0.8, 0.7, 0.8, 0.9, 0.8, 0.8]` ms, with a 0.8 ms median and 0.7/0.9 ms
27
+ minimum/maximum. Navigation samples are
28
+ `[3.7, 4.1, 4.5, 3.9, 4.2, 3.9, 4.3]` ms, with a 4.1 ms median and 3.7/4.5 ms
29
+ minimum/maximum. The navigation ranges overlap the `0.14.0` release evidence;
30
+ no improvement or regression claim is made.
31
+
5
32
  `npm run benchmark:source-scale` generates its fixture outside the repository so 50,000 lines of synthetic source are not tracked. The default topology is 50 pages plus 450 route-owned imported modules. Generation is excluded from timing; fresh-process samples separately report source reads, reachable-graph discovery, source compilation, clean production build, compiler-result and deploy digests, output files/bytes, cache counters, and peak RSS. `ROUTES`, `MODULES_PER_ROUTE`, `FILLER_LINES`, `WARMUPS`, and `RUNS` may reduce or expand the fixture without changing the default acceptance floor. `TARGET_ROOT` measures another checkout; `BASELINE_ROOT` alternates that checkout with the current tree and requires identical deploy output.
6
33
 
7
34
  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.
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.14.x`: the compiler API and supported TSX surface may change.
16
16
 
17
- **Latest release: 0.14.0 - Project table CRUD and identity.** Native table structure, ordinary state, collection selectors, and keyed ownership compose complete project CRUD with retained row identity and no data-grid runtime. Read the [release notes](./RELEASES.md#0140---project-table-crud-and-identity), open the [release page](https://github.com/kudzujs/kudzu/releases/tag/v0.14.0), or follow the [architecture packet](./docs/next-architecture/README.md).
17
+ **Latest release: 0.14.1 - Nested and object-state collections.** Direct immutable array fields of ordinary object state now compose root and nested keyed ownership with retained identity, latest handlers, and exact row-state release. Read the [release notes](./RELEASES.md#0141---nested-and-object-state-collections), open the [release page](https://github.com/kudzujs/kudzu/releases/tag/v0.14.1), 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,55 @@
1
1
  # Kudzu Releases
2
2
 
3
+ ## 0.14.1 - Nested And Object-State Collections
4
+
5
+ Kudzu 0.14.1 lets one direct immutable array field of ordinary object state own
6
+ a root keyed collection and its nested direct-property lists.
7
+
8
+ ### Changed in 0.14.1
9
+
10
+ - Allowed compiler-proven object-state collection roots without authored field
11
+ state.
12
+ - Initialized binding-backed roots before nested row ownership mounts.
13
+ - Preserved project and issue DOM identity through immutable replacement and
14
+ nested update, reorder, and removal.
15
+ - Preserved latest-item handlers and released descendant row state exactly.
16
+ - Recreated removed and re-added nested rows with fresh local state.
17
+ - Updated `create-kudzu@0.1.123` to generate projects on
18
+ `@kudzujs/core@^0.14.1`.
19
+
20
+ ### Output Evidence
21
+
22
+ - The application emits 44 files totaling 164,305 raw / 52,185 aggregate gzip
23
+ bytes with deploy digest
24
+ `0a3b7e10b3447a76a9c04ef34ad7c2bfa30400ea53c9d16fc85b1c7cbf2ea203`.
25
+ - The maintained two-route session remains 17 JavaScript files and totals
26
+ 74,826 raw / 26,204 aggregate gzip bytes; `/help` remains 0 B JavaScript.
27
+ - No semantic primitive, IR kind, compiler pass, runtime concept, or public API
28
+ was added. One build-time validation line changed and one list-runtime line
29
+ was added.
30
+
31
+ ### Validation
32
+
33
+ - Required Chrome proves immutable whole-object replacement, nested issue
34
+ insert, update, reorder, removal, re-addition, retained identity, latest
35
+ handlers, descendant state release, and fresh remount.
36
+ - The complete suite passes 274 tests, package smoke, and serialized required-
37
+ Chrome execution.
38
+ - Seven fresh Chrome profiles record a 0.8 ms table-update median with a
39
+ 0.7-0.9 ms range and a 4.1 ms navigation median with a 3.7-4.5 ms range.
40
+
41
+ ### Limits
42
+
43
+ Collection roots require one direct static array field and immutable whole-
44
+ object replacement. Dynamic or computed paths, mutation, and non-array fields
45
+ remain unsupported.
46
+
47
+ ### Upgrade
48
+
49
+ ```sh
50
+ npm install @kudzujs/core@^0.14.1
51
+ ```
52
+
3
53
  ## 0.14.0 - Project Table CRUD And Identity
4
54
 
5
55
  Kudzu 0.14.0 composes a complete native project table from ordinary state,
@@ -918,6 +918,37 @@ generates projects on `@kudzujs/core@^0.14.0`.
918
918
  - **Done condition:** direct immutable paths cover the application journey and
919
919
  nearby dynamic forms fail clearly.
920
920
 
921
+ Release evidence complete. The first failure replaced the project route's
922
+ separate array state with one direct `projectData.projects` field and failed at
923
+ build time because nested lists required their source ownership signal itself to
924
+ contain an array. The compiler already emitted a binding-backed root
925
+ `KeyedBlockIR`, its selector states, and the nested issue child block. Build-time
926
+ list validation now allows an object-valued signal only for a compiler-proven
927
+ `ownerField`; root lists still require arrays and nested non-array fields still
928
+ fail. Browser mounting initializes binding-backed roots with children from their
929
+ serialized state before the evaluator module loads, preserving the existing
930
+ parent prototype and ownership path.
931
+
932
+ Required Chrome proves immutable whole-object replacement, nested issue insert,
933
+ update, reorder, removal, re-addition, retained project/issue identity, latest
934
+ issue handlers, descendant state release, and fresh remount. Existing dynamic
935
+ object-property, alias, mutation, mutating-sort, and non-array diagnostics retain
936
+ the negative boundary, while `/help` remains complete HTML with 0 B JavaScript.
937
+ The slice adds zero semantic primitives, IR kinds, compiler passes,
938
+ normalization rules, adapters, runtime concepts, or public APIs. It changes one
939
+ build-time validation line and adds one production list-runtime line.
940
+
941
+ The release emits 44 files totaling 164,305 raw / 52,185 aggregate gzip bytes
942
+ with deploy SHA-256
943
+ `0a3b7e10b3447a76a9c04ef34ad7c2bfa30400ea53c9d16fc85b1c7cbf2ea203`.
944
+ The two-route session remains 17 JavaScript files totaling 74,826 raw / 26,204
945
+ aggregate gzip bytes. Seven fresh Chrome 142 profiles record table
946
+ update samples of `[0.8, 0.8, 0.7, 0.8, 0.9, 0.8, 0.8]` ms, a 0.8 ms median and
947
+ 0.7/0.9 ms range, plus navigation samples of
948
+ `[3.7, 4.1, 4.5, 3.9, 4.2, 3.9, 4.3]` ms, a 4.1 ms median and 3.7/4.5 ms range.
949
+ `0.14.1` publishes this accepted packet, and `create-kudzu@0.1.123` generates
950
+ projects on `@kudzujs/core@^0.14.1`.
951
+
921
952
  ### `0.14.2`: Infinite Loading Composition
922
953
 
923
954
  - **Purpose:** prove sentinel-driven incremental loading before virtualization.
@@ -1395,5 +1426,6 @@ release transaction where possible or document and publish a forward-fix patch.
1395
1426
  | `0.13.2` | Released | Preserve multistep validation, versioned persistence, stale-save rejection, conflict retention, and reset evidence. | None |
1396
1427
  | `0.13.3` | Released | Preserve the published upload validation, cancellation, retry, route cleanup, and attachment mutation evidence. | None |
1397
1428
  | `0.14.0` | Released | Preserve native table CRUD, retained identity, keyboard access, and measured update evidence. | None |
1398
- | `0.14.1` | Active | Add the first failing nested/object-state collection fixture. | None |
1399
- | `0.14.2` onward | Blocked | Complete or explicitly close `0.14.1` first. | Ordered patch boundary |
1429
+ | `0.14.1` | Released | Preserve immutable object-state replacement, nested keyed identity, latest handlers, and exact row release. | None |
1430
+ | `0.14.2` | Active | Add the first failing infinite-loading composition fixture. | None |
1431
+ | `0.14.3` onward | Blocked | Complete or explicitly close `0.14.2` first. | Ordered patch boundary |
@@ -66,7 +66,7 @@ Keep each patch behavior-preserving and independently reviewable. If a boundary
66
66
 
67
67
  ## Generator Versions
68
68
 
69
- `create-kudzu@0.1.122` retains the explicit install instructions and generates projects with `@kudzujs/core@^0.14.0`.
69
+ `create-kudzu@0.1.123` retains the explicit install instructions and generates projects with `@kudzujs/core@^0.14.1`.
70
70
 
71
71
  ## Release Boundary
72
72
 
@@ -100,6 +100,6 @@ A direct setter or inline/simple `const` setter callback may cross one same-file
100
100
 
101
101
  `kudzu.config` may opt one emitted shared-layout group into same-document navigation with legacy `navigation: { routes: ["/product", "/items/[id]"] }`, or multiple groups with `navigation: { groups: [{ routes: [...] }, { routes: [...] }] }`. The forms are mutually exclusive. Identities are globally unique emitted exact paths or `runtimeParams` patterns; each group uses one page-exported layout function identity. Runtime records securely match concrete pathnames under `base`, and their cache-safe parameter initializer runs before route DOM/effects mount on every transition. Each group receives a deterministic route-hashed asset specialized to only its records, pattern decoder, and effect/parameter lifecycle needs. Cross-group and ungrouped anchors remain native and are not prefetched; overlapping path domains across groups fail the build. Route effect entries export cache-safe layout and route mount functions: layout effects, including conditional/keyed DOM-owned effects, persist for the group session; route effects receive a fresh owner registry after each route insertion; and non-persisted page disposal cleans route before layout. Direct primitive state, runtime parameter, and keyed-item property dependencies and cleanup are supported. Fragment payloads and coordinated View Transitions are not implemented.
102
102
 
103
- A direct object-state prop may expose one-segment static fields when its same-file or relative-imported child directly maps an array field. Scalar bindings and that selected array effect dependency reuse the parent signal, existing `Object.is` comparison, and binding-backed keyed ownership without field state or a browser component. Dynamic paths, aliases, mutation, child state/ref/ID hooks, and opaque call-site values remain unsupported.
103
+ A direct object-state prop may expose one-segment static fields when its same-file or relative-imported child directly maps an array field. Scalar bindings and that selected array effect dependency reuse the parent signal, existing `Object.is` comparison, and binding-backed keyed ownership without field state or a browser component. A direct static array field of local object state may also root a keyed selector pipeline with nested direct-property lists; immutable whole-object replacement reuses the same binding-backed root and nested ownership. Dynamic paths, aliases, mutation, child state/ref/ID hooks, opaque call-site values, and non-array collection fields remain unsupported.
104
104
 
105
105
  Cross-framework performance tables are historical snapshots from excluded workspaces and are not current rankings. `npm run benchmark` tracks the Worker build/graph fixture; `RUNS=21 npm run benchmark:keyed` tracks large keyed restoration; `BASELINE_ROOT=... npm run benchmark:native` tracks native dispatch and exact artifact changes. Current methodology, raw arrays, external-fixture limits, and artifact deltas live in `PERFORMANCE.md` and the web docs.
@@ -316,7 +316,7 @@ export function list(items, keyField, render, ownerField, selector = [], indexed
316
316
  const source = items?.[bindingMarker] ? bindingDescriptor(items) : undefined
317
317
  if (source) items = createInternalState(items.value)
318
318
  if (Array.isArray(items)) items = createInternalState(items)
319
- if (!items?.[signalMarker] || !Array.isArray(items.value)) throw new Error("A keyed list must use local array state or a supported imported static array")
319
+ if (!items?.[signalMarker] || (!ownerField && !Array.isArray(items.value))) throw new Error("A keyed list must use local array state or a supported imported static array")
320
320
  const selectorStateMap = new Map(selectorStates)
321
321
  for (const [name, state] of selectorStateMap) if (!state?.[signalMarker]) throw new Error(`Rendered collection selector state ${JSON.stringify(name)} must be framework state`)
322
322
  let values = items.value
@@ -96,6 +96,7 @@ function mountLists(root) {
96
96
  ownedLists.set(list.owner, lists)
97
97
  listRegistrations.set(start, { list, owner: list.owner })
98
98
  } else if (descriptor.source) {
99
+ if (descriptor.children) updateList(list)
99
100
  const load = {}
100
101
  listLoads.set(start, load)
101
102
  loadListEvaluator(descriptor.source).then(evaluator => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kudzujs/core",
3
- "version": "0.14.0",
3
+ "version": "0.14.1",
4
4
  "description": "HTML-first TSX framework with synchronous state semantics and no virtual DOM",
5
5
  "type": "module",
6
6
  "license": "MIT",