@kudzujs/core 0.8.23 → 0.8.24

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/GOAL_B.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Goal B: Relative TypeScript Worker Capability Proof
2
2
 
3
+ This historical capability milestone is distinct from the active [Goal B optimization program](./docs/next-architecture/goal-b-optimization-benchmarks.md).
4
+
3
5
  Goal B is a completed cross-application compiler-capability proof for one browser-only pattern used by realtime React-shaped applications: a route-owned relative TypeScript module Worker created and cleaned up from an inline `useEffect`.
4
6
 
5
7
  The realtime dashboard is a stress and conformance fixture. It is not a Kudzu product vertical, dashboard API, stream runtime, widget framework, server platform, or claim of ThingsBoard compatibility. [`MIGRATION_ROADMAP.md`](./MIGRATION_ROADMAP.md) remains the source of truth for future fixture-driven migration work.
@@ -102,11 +104,11 @@ The focused fixture emitted a 907 B raw / 477 B gzip Worker graph and an 11,388
102
104
 
103
105
  These numbers are dated conformance evidence. They do not define a dashboard product target.
104
106
 
105
- ## Reproducible 0.7.12 Rerun
107
+ ## Historical 0.7.12 Rerun
106
108
 
107
- At commit `05e5cc2` on Apple M3 / macOS 26.5.2 / Node 25.6.1, `npm run benchmark` measured clean build times of 404.2, 401.3, 408.2, 404.4, 399.9, 408.8, and 402.0 ms after one warm-up, for a 404.2 ms median. The current Worker graph is 907 B raw / 475 B gzip; the complete dashboard window graph is 11,960 B raw / 5,365 B aggregate gzip.
109
+ At commit `05e5cc2` on Apple M3 / macOS 26.5.2 / Node 25.6.1, `npm run benchmark` measured clean build times of 404.2, 401.3, 408.2, 404.4, 399.9, 408.8, and 402.0 ms after one warm-up, for a 404.2 ms median. That rerun's Worker graph was 907 B raw / 475 B gzip; its complete dashboard window graph was 11,960 B raw / 5,365 B aggregate gzip.
108
110
 
109
- Chrome 150.0.7871.187 passed the tracked throughput, cadence, stale-write, bounded-history, and 30-cycle start/termination checks through the focused Worker browser test. These current values differ from the historical completion snapshot because shared window capabilities and the local toolchain changed; the historical values above remain release provenance, not current artifact claims.
111
+ Chrome 150.0.7871.187 passed the tracked throughput, cadence, stale-write, bounded-history, and 30-cycle start/termination checks through the focused Worker browser test. Those rerun values differ from the historical completion snapshot because shared window capabilities and the local toolchain changed; both sets remain release provenance, not current artifact claims.
110
112
 
111
113
  ## Non-Goals
112
114
 
@@ -243,6 +243,13 @@ This queue orders the next investigations by general migration value. Start only
243
243
  - Source graph resolution and shared path conversion have focused owners, while Worker compilation directly owns Worker graph emission.
244
244
  - Complete-site and representative deploy artifacts remain byte-identical to `v0.8.22`; diagnostics, RouteIR, CapabilityIR, browser ownership, and accepted syntax are unchanged.
245
245
 
246
+ ### Completed In 0.8.24
247
+
248
+ - Goal B adds a maintained 2,000-row keyed browser benchmark with fresh-profile timing and ownership checks.
249
+ - Safe large flat-list restoration batches mount-hook discovery, reducing the measured median by 19.77% while retained-heavy append, filter, reverse, identity, state reset, and handler behavior remain unchanged.
250
+ - No-op normalization passes skip redundant recursive parent repair, reducing the measured 1,000-product build median by 6.26% with equivalent output.
251
+ - Identical generated route-entry transformation remains the next evidence-backed Goal B investigation; it is not implemented without an isolated benchmark.
252
+
246
253
  ## Cross-Cutting Performance Gates
247
254
 
248
255
  Every migration feature must preserve:
package/PERFORMANCE.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Performance Records
2
2
 
3
+ Reproducibility classes: `npm run benchmark` and `npm run benchmark:keyed` 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
+
5
+ ## 0.8.24 Measured Goal B Optimizations
6
+
7
+ Measured UTC 2026-08-09 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 151.0.7922.76. Baseline tag `v0.8.23` at `39a065b` and the `0.8.24` candidate used the same local volume and dependencies.
8
+
9
+ The implementation and maintained benchmark patch over `v0.8.23` had SHA-256 `c6c39b0c64f7a5d3271cb9f0286a4c6787aaf7e293744457629e6ea249e9ef76`, produced by:
10
+
11
+ ```bash
12
+ git diff --binary v0.8.23 -- framework/compiler/normalization-pipeline.mjs framework/list-runtime.js test/compiler-passes.test.mjs test/keyed-performance.mjs test/fixtures/keyed-performance/src/pages/index.tsx test/commerce-build-performance.mjs package.json | shasum -a 256
13
+ ```
14
+
15
+ Twenty-one fresh profiles measured 2,000-row restoration at 21.1 ms versus 26.3 ms, a 19.77% improvement. Twenty-one alternating clean builds of the external 1,000-product fixture measured 6,266.5 ms versus 6,684.7 ms, a 6.26% improvement. The keyed route adds 127 B raw / 35 B aggregate gzip JavaScript; the normalization optimization adds no output bytes. Complete methodology, arrays, artifacts, correctness checks, and limitations are in [Goal B Measurement Details](#goal-b-measurement-details).
16
+
17
+ Before release-content updates, the complete site plus `lists`, `keyed-row-hooks`, and `navigation` retained identical deploy file lists. Only `assets/kudzu-list.js` changed; every other deploy file was byte-identical. Their normalized `.kudzu` trees were identical to `v0.8.23`.
18
+
3
19
  ## 0.8.23 Source Compiler Boundary
4
20
 
5
21
  Measured UTC 2026-08-09 on Apple M3, 8 logical CPUs, 8 GiB RAM, macOS 26.5.2 / Darwin 25.5.0, Node 22.23.2, and npm 11.18.0. Baseline tag `v0.8.22` at `60b9bff` and the current `0.8.23` compiler candidate used the same local volume and identical installed dependencies.
@@ -24,6 +40,99 @@ Both targets received one warm-up followed by seven clean `worker-effects` produ
24
40
 
25
41
  Before release-content updates, the complete 135-page site and the `bindings`, `keyed-row-hooks`, `effect-dependencies`, `worker-effects`, `runtime-params`, `navigation`, `config-authoring`, and `event-package` deploy trees had identical file lists and bytes. Their `.kudzu` trees also matched after replacing only each checkout root in existing source-location strings. The invalid-reducer fixture retained the same source file, line, column, and diagnostic text. `build.mjs` decreased from 3,732 to 744 lines; this source-organization metric is not a runtime performance claim.
26
42
 
43
+ ## Goal B Measurement Details
44
+
45
+ Goal B started from clean commit `39a065b4284c74e7bf8ee5e39647ef771f2ba6f6`. On the same Apple M3 environment with Node 22.23.2, the maintained `worker-effects` benchmark measured a 289.9 ms clean-build median, 907 B raw / 477 B gzip Worker graph, and 12,148 B raw / 5,411 B gzip window graph:
46
+
47
+ ```text
48
+ build: [284.3,287.1,293.6,289.9,291.3,286.4,290.7]
49
+ ```
50
+
51
+ After the two candidate optimizations, the same maintained benchmark measured a 286.2 ms median and identical graph sizes. This is a regression check rather than evidence for either optimization:
52
+
53
+ ```text
54
+ build: [286.2,282.1,287.1,286.4,285.4,284.4,287.2]
55
+ ```
56
+
57
+ Chrome 151.0.7922.76 passed the tracked throughput, cadence, bounded-history, stale-write, and 30-cycle ownership checks. The first Node 22 browser attempt returned no Worker data; immediate Node 25 and Node 22 retries passed, so this is recorded as a startup flake rather than a performance result.
58
+
59
+ The preserved external cross-framework workspace then rebuilt its 1,000-row Kudzu fixture against clean `0.8.23` to locate a possible keyed-list loss. This exploratory harness is not maintained in the repository and its historical framework results were not reused. Seven fresh unthrottled Chrome profiles all passed row visibility, retained identity, removal, and fresh re-add checks:
60
+
61
+ | Operation | Median | Raw runs |
62
+ |---|---:|---|
63
+ | Edit row 500 | 0.5 ms | 1.1, 0.6, 0.5, 0.5, 0.6, 0.5, 0.5 |
64
+ | Reverse 1,000 rows | 4.0 ms | 4.8, 3.8, 3.8, 4.2, 4.0, 4.1, 3.8 |
65
+ | Remove row 500 | 1.2 ms | 1.5, 1.1, 1.1, 1.3, 1.2, 1.2, 1.2 |
66
+ | Re-add row 500 | 1.3 ms | 2.3, 1.0, 1.3, 1.5, 1.1, 1.2, 1.4 |
67
+
68
+ That fixture's seven clean builds were `[390.891,389.698,393.034,390.798,389.477,390.258,388.714]` ms for a 390.258 ms median. It emitted 28,243 B raw / 9,245 B aggregate gzip initial JavaScript across eight files and 943,075 B total output across nine files. The absolute build result has no current matched control and does not establish a regression. No browser operation in this exploratory fixture established a material loss.
69
+
70
+ #### Maintained Keyed Restoration Benchmark
71
+
72
+ The repository-owned `npm run benchmark:keyed` fixture renders 2,000 keyed rows with row-local state, a reactive slice, and a reactive string filter. Each revision received one clean build warm-up, 21 measured clean builds, and 21 unthrottled fresh Chrome 151.0.7922.76 profiles. In-page `MutationObserver` completion includes the synchronous state commit and terminal DOM mutation. Every run retained row 1000 and its selected state, appended 33 rows beside 1,967 retained rows, filtered to one row, released row 1, restored row 1 with fresh identity/state and a working handler, and retained row 1000 through reversal.
73
+
74
+ The baseline uses the identical `0.8.24` benchmark harness and fixture copied into a clean `v0.8.23` worktree; only compiler/runtime source differs:
75
+
76
+ ```bash
77
+ git worktree add --detach /tmp/kudzu-0.8.23 v0.8.23
78
+ mkdir -p /tmp/kudzu-0.8.23/test/fixtures/keyed-performance/src/pages
79
+ cp test/keyed-performance.mjs /tmp/kudzu-0.8.23/test/keyed-performance.mjs
80
+ cp test/fixtures/keyed-performance/src/pages/index.tsx /tmp/kudzu-0.8.23/test/fixtures/keyed-performance/src/pages/index.tsx
81
+ ln -s "$PWD/node_modules" /tmp/kudzu-0.8.23/node_modules
82
+ RUNS=21 CHROME_BIN="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" node /tmp/kudzu-0.8.23/test/keyed-performance.mjs
83
+ RUNS=21 CHROME_BIN="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" npm run benchmark:keyed
84
+ ```
85
+
86
+ The measured loss was restoration from one retained row to 2,000 rows. The baseline called `mountDom()` separately for 1,999 connected additions. For top-level flat lists, the candidate calls it once on the connected list parent when more than 32 additions are a majority of both the next rows and their parent children. Nested/parent lists, shared containers dominated by unrelated siblings, and small or retained-heavy updates keep per-root mounting. This reduces repeated mount-hook selector traversal without adding a scheduler, cache, tree, or public API.
87
+
88
+ | Target | Build median | Append 33 | Filter median | Restore median | Reverse median | JavaScript raw / gzip |
89
+ |---|---:|---:|---:|---:|---:|---:|
90
+ | `0.8.23` baseline | 263.0 ms | 2.6 ms | 4.6 ms | 26.3 ms | 6.2 ms | 28,308 B / 10,937 B |
91
+ | Goal B candidate | 265.6 ms | 2.7 ms | 4.6 ms | 21.1 ms | 6.1 ms | 28,435 B / 10,972 B |
92
+
93
+ Restore improved 19.77%, and its 20.4-21.9 ms candidate range did not overlap the 25.7-27.3 ms baseline range. Append, filter, and reverse distributions overlap; no change is claimed. Build distributions overlap; no build improvement is claimed. The deterministic cost is 127 B raw / 35 B aggregate gzip in `kudzu-list.js`.
94
+
95
+ ```text
96
+ baseline build: [261.7,265.9,263.0,263.9,259.4,265.5,261.5,263.4,260.4,261.8,264.7,263.4,260.7,262.7,263.6,264.4,261.5,264.0,261.7,263.5,262.3]
97
+ candidate build: [265.4,271.2,265.2,263.6,266.1,266.7,264.4,317.3,298.2,269.4,269.2,264.1,266.9,268.9,273.6,265.5,262.4,259.4,262.1,265.6,262.0]
98
+ baseline append: [2.8,2.5,2.5,3.0,2.5,2.6,2.8,2.7,2.7,2.8,2.8,2.5,2.6,2.9,2.7,2.6,2.5,2.4,2.7,2.4,2.4]
99
+ candidate append: [2.8,3.0,2.7,2.5,2.7,2.6,2.8,2.8,2.7,2.6,2.8,2.8,3.0,2.8,2.4,2.4,2.4,2.9,2.9,2.7,2.6]
100
+ baseline filter: [4.5,4.5,5.0,4.6,4.5,4.5,4.9,4.8,4.5,4.6,4.7,4.3,4.7,4.8,4.7,4.7,4.6,4.5,4.9,4.4,4.2]
101
+ candidate filter: [4.7,4.8,4.6,4.6,4.7,4.4,4.7,4.5,4.6,4.4,4.7,4.9,4.9,4.6,4.4,4.6,4.6,4.8,4.8,4.3,4.4]
102
+ baseline restore: [26.5,27.3,26.5,26.5,25.8,26.7,26.3,26.4,26.2,26.4,26.6,26.2,27.0,26.6,25.9,25.7,25.9,26.3,26.0,25.9,26.3]
103
+ candidate restore: [21.3,21.7,21.8,21.6,20.4,20.8,20.6,21.5,20.4,20.8,21.8,21.4,21.9,21.0,21.5,20.9,20.8,21.0,21.1,21.1,21.2]
104
+ baseline reverse: [6.2,6.3,6.0,6.4,6.6,7.1,6.4,6.0,6.8,6.3,5.8,5.8,6.4,5.8,6.2,7.1,5.7,6.1,5.8,6.0,5.5]
105
+ candidate reverse: [5.8,6.0,6.2,5.8,5.8,6.1,6.2,6.2,6.3,6.0,6.1,6.2,6.2,6.0,6.3,6.2,5.9,6.3,6.0,5.9,6.3]
106
+ ```
107
+
108
+ #### External 1,000-Product Build
109
+
110
+ The public [`SimYunSup/kudzu-based-bench`](https://github.com/SimYunSup/kudzu-based-bench) commerce fixture at `f2d5be1` generated 1,000 deterministic products and 1,011 complete Kudzu pages. On the same Apple M3 / Node 25.6.1 machine, clean `0.8.23` and the Goal B candidate received one warm-up and 21 alternating clean builds. Output and `.kudzu` cleanup remained outside timing.
111
+
112
+ The paired runner generates the catalog once, alternates the two compiler roots, cleans `dist` and `.kudzu` outside timing, compares relative output manifests and hashes, permits only the recorded `assets/kudzu-list.js` delta, and restores the external app's package symlink afterward:
113
+
114
+ ```bash
115
+ git clone https://github.com/SimYunSup/kudzu-based-bench.git /tmp/kudzu-based-bench
116
+ git -C /tmp/kudzu-based-bench checkout --detach f2d5be1a516c539e30f7125f6870d42b1dd02ecd
117
+ pnpm --dir /tmp/kudzu-based-bench install --force
118
+ pnpm --dir /tmp/kudzu-based-bench run build:commerce
119
+ git worktree add --detach /tmp/kudzu-0.8.23 v0.8.23
120
+ ln -s "$PWD/node_modules" /tmp/kudzu-0.8.23/node_modules
121
+ APP_ROOT=/tmp/kudzu-based-bench/apps/shop-kudzu \
122
+ BASELINE_ROOT=/tmp/kudzu-0.8.23 \
123
+ CANDIDATE_ROOT="$PWD" RUNS=21 CATALOG_SIZE=1000 \
124
+ npm run benchmark:commerce
125
+ ```
126
+
127
+ `applyNormalizationPasses()` previously called TypeScript's recursive parent-pointer repair after every pass, including validators and no-op passes returning the identical `SourceFile`. Every current pass was audited to use immutable factory updates for structural changes. Repairing only a changed root reduced the build median from 6,684.7 ms to 6,266.5 ms, a 6.26% improvement. Both builds emitted 3,056 files; only `assets/kudzu-list.js` differed because of the independently measured keyed restoration optimization. The normalization change itself adds no browser bytes.
128
+
129
+ ```text
130
+ baseline: [6488.0,7095.6,6861.0,6647.7,6563.4,6613.3,6536.1,6529.2,6462.6,6655.9,6684.7,6623.2,6504.9,7618.5,8174.5,9309.1,7611.4,7942.3,8148.2,7191.0,7380.7]
131
+ candidate: [5898.6,5903.9,6108.5,6088.1,5966.4,5913.8,6266.5,6115.1,6014.6,6022.0,6223.1,6357.5,6429.5,6950.8,7887.1,8275.9,7208.9,7306.3,7861.9,6798.8,6859.3]
132
+ ```
133
+
134
+ This external fixture is a candidate-finding and paired Kudzu regression benchmark, not a framework leaderboard result. It uses Kudzu-authored source; the catalog is generated once before timing and both revisions run the same complete Kudzu build. Its published cross-framework runs are sequential with only three build samples, and none of those framework numbers are used for this optimization claim. The paired command requires an existing symlink at `apps/shop-kudzu/node_modules/@kudzujs/core`. The external commit's pnpm 10.20 lock cannot install with `--frozen-lockfile`; `--force` accepts the unchanged lock and is a reproducibility limitation, although baseline and candidate use the same resulting dependency graph.
135
+
27
136
  ## 0.8.22 Versioned Compiler Foundation
28
137
 
29
138
  Measured UTC 2026-08-09 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 tag `v0.8.21` at `ff38092` and the current `0.8.22` compiler candidate used the same local volume and identical installed dependencies.
@@ -420,4 +529,4 @@ React toggle: [5.7, 6.1, 5.8, 5.8, 5.6, 5.8, 5.7]
420
529
  Kudzu toggle: [5.2, 5.4, 5.3, 5.6, 5.3, 5.2, 5.3]
421
530
  ```
422
531
 
423
- The reproducible fixture, benchmark harness, environment record, and JSON results are under `/home/kft/Documents/etc/demo/large-benchmark`.
532
+ The original fixture and harness were stored in an excluded local workspace and are unavailable from this checkout. The arrays above remain historical provenance, not an independently reproducible current claim.
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.23 - Source compiler boundary.** Source normalization, TSX analysis, ModuleIR finalization, handler generation, and build-module generation now belong to a no-write source compiler. `build.mjs` coordinates discovery, source results, RouteIR, CapabilityIR, and artifact emission without analyzing TSX. Read the [release notes](./RELEASES.md#0823---source-compiler-boundary), open the [release page](https://github.com/kudzujs/kudzu/releases/tag/v0.8.23), or follow the [architecture packet](./docs/next-architecture/README.md).
17
+ **Latest release: 0.8.24 - Measured Goal B optimizations.** Large keyed restoration batches mount connected flat-list additions once, and no-op normalization passes skip redundant full-AST parent repair. Maintained and external benchmarks measure 19.77% faster 2,000-row restoration and 6.26% faster 1,000-product builds. Read the [release notes](./RELEASES.md#0824---measured-goal-b-optimizations), open the [release page](https://github.com/kudzujs/kudzu/releases/tag/v0.8.24), 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)
@@ -123,7 +123,7 @@ React-shaped TypeScript/TSX
123
123
  -> complete HTML + route-specific capability ESM
124
124
  ```
125
125
 
126
- - `framework/compiler/normalization-pipeline.mjs` owns pass order and repairs AST parent pointers after every transform.
126
+ - `framework/compiler/normalization-pipeline.mjs` owns pass order and repairs AST parent pointers after structurally changed transforms.
127
127
  - Focused passes own React, React Router, browser-signal, animation-frame, timer, render-control, and Worker validation.
128
128
  - The main transformer produces descriptors; effect and handler codegen modules turn them into route-specific ESM.
129
129
  - Unsupported nearby syntax fails with source-located diagnostics instead of falling back to React or a generic runtime.
package/RELEASES.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # Kudzu Releases
2
2
 
3
+ ## 0.8.24 - Measured Goal B optimizations
4
+
5
+ Kudzu 0.8.24 starts the architecture optimization Goal B with two benchmark-proven optimizations for large keyed restoration and large multi-route builds while preserving complete HTML, direct DOM ownership, and existing compiler output. This is distinct from the completed historical Worker capability milestone in `GOAL_B.md`.
6
+
7
+ ### Changed in 0.8.24
8
+
9
+ - A maintained `npm run benchmark:keyed` fixture measures 2,000 keyed rows with row-local state, reactive slicing/search, bulk restoration, retained-heavy append, reversal, DOM identity, reset state, and restored handlers across fresh Chrome profiles.
10
+ - Top-level flat lists batch mount-hook discovery through their connected parent only when more than 32 additions dominate both the next list and parent children. Nested lists, shared containers, and small or retained-heavy additions keep per-root mounting.
11
+ - `applyNormalizationPasses()` repairs TypeScript parent pointers only after a pass returns a structurally changed `SourceFile`; validators and no-op passes no longer walk the complete AST again.
12
+ - A focused test proves changed normalization output has repaired parent links before the next pass runs.
13
+ - Goal B records identical generated route entries as the next measured esbuild-transform investigation; no cache or generalized build system was added without isolated evidence.
14
+
15
+ ### Performance
16
+
17
+ - Twenty-one fresh Chrome profiles measured 2,000-row restoration at 21.1 ms versus 26.3 ms for `0.8.23`, a 19.77% improvement. A retained-heavy 33-row append showed no material change at 2.7 ms versus 2.6 ms.
18
+ - The keyed route adds 127 B raw / 35 B aggregate gzip JavaScript. Filter, reverse, and clean-build distributions establish no material regression.
19
+ - Twenty-one alternating clean builds of [`SimYunSup/kudzu-based-bench`](https://github.com/SimYunSup/kudzu-based-bench)'s 1,000-product, 1,011-page Kudzu fixture measured 6,266.5 ms versus 6,684.7 ms for `0.8.23`, a 6.26% improvement.
20
+ - Both commerce builds emitted the same 3,056 files. Only `assets/kudzu-list.js` changed for the independently measured runtime optimization; normalization changed no output bytes.
21
+ - Exact keyed worktree setup and the checked-in `benchmark:commerce` paired runner are documented in `PERFORMANCE.md` with raw arrays and limitations.
22
+
23
+ ### Validation
24
+
25
+ - `npm run check` and all 172 tests pass, including the new normalization boundary check.
26
+ - Node 22 focused compiler checks and the maintained Worker benchmark pass.
27
+ - Chrome-backed keyed list, selector, row-hook, Worker ownership, and the new large keyed benchmark checks pass.
28
+ - Before release-content updates, the complete site plus representative list, keyed-row-hook, and navigation builds retained identical file lists; only `assets/kudzu-list.js` changed, and normalized `.kudzu` trees remained identical to `v0.8.23`.
29
+ - No accepted syntax, public API behavior, VDOM, hydration, scheduler, cache, retained browser component tree, or `create-kudzu` template change was added.
30
+
31
+ ### Upgrade
32
+
33
+ ```bash
34
+ npm install @kudzujs/core@^0.8.24
35
+ ```
36
+
3
37
  ## 0.8.23 - Source compiler boundary
4
38
 
5
39
  Kudzu 0.8.23 completes the Goal A compiler foundation by moving source normalization, TSX semantic analysis, ModuleIR finalization, handler generation, and build-module generation behind one explicit no-write source compiler result.
@@ -7,7 +7,7 @@ The top-level [`GOAL_A.md`](../../GOAL_A.md) and [`GOAL_B.md`](../../GOAL_B.md)
7
7
  | Goal | Decision | Start condition |
8
8
  |---|---|---|
9
9
  | A: compiler foundation | Complete in `0.8.23` | The no-write source compiler, RouteIR v1, CapabilityIR v1, generator boundaries, and output baseline are recorded. |
10
- | B: optimization benchmarks | Deferred | Start only by explicit decision from the recorded `0.8.23` baseline. |
10
+ | B: optimization benchmarks | Active | The first measured bulk keyed restoration optimization is retained; continue one reproduced loss at a time. |
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
 
@@ -27,7 +27,7 @@ The top-level [`GOAL_A.md`](../../GOAL_A.md) and [`GOAL_B.md`](../../GOAL_B.md)
27
27
  2. [`goal-a-compiler-foundation.md`](./goal-a-compiler-foundation.md): approved extraction and generator work.
28
28
  3. [`versioning.md`](./versioning.md): planned patch sequence and completion rules.
29
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.
30
+ 5. [`goal-b-optimization-benchmarks.md`](./goal-b-optimization-benchmarks.md): active measurements, retained optimizations, and continuation rules.
31
31
  6. [`goal-c-state-resource-research.md`](./goal-c-state-resource-research.md): research boundary only.
32
32
  7. [`goal-d-routing-compatibility-decisions.md`](./goal-d-routing-compatibility-decisions.md): routing and islands decisions.
33
33
 
@@ -1,6 +1,6 @@
1
1
  # Current Compiler Architecture
2
2
 
3
- This maps 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.24` 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
 
@@ -9,7 +9,7 @@ This maps the completed `0.8.23` Goal A compiler foundation. File and function n
9
9
  | CLI entry | [`bin/kudzu.mjs`](../../bin/kudzu.mjs) | Dispatches build and development commands. |
10
10
  | Build orchestration | [`framework/build.mjs`](../../framework/build.mjs), `build()` | Coordinates config, discovery, source compilation, RouteIR rendering, CapabilityIR projection, generator invocation, artifact emission, and `afterBuild`. |
11
11
  | Reachability/import resolution | [`framework/compiler/source-compiler.mjs`](../../framework/compiler/source-compiler.mjs), `reachableSourceFiles()`; [`framework/compiler/source-graph.mjs`](../../framework/compiler/source-graph.mjs), `resolveSourceImport()` | Starts from page entries, follows relative runtime imports/re-exports and validated Worker references, and excludes unreachable migration source. |
12
- | Ordered normalization | [`framework/compiler/normalization-pipeline.mjs`](../../framework/compiler/normalization-pipeline.mjs), `applyNormalizationPasses()`; [`framework/compiler/source-compiler.mjs`](../../framework/compiler/source-compiler.mjs), `normalizeCompilerSource()` | Applies migration/resource passes in order and repairs TypeScript parent pointers after every pass. Imported source uses the same pipeline. |
12
+ | Ordered normalization | [`framework/compiler/normalization-pipeline.mjs`](../../framework/compiler/normalization-pipeline.mjs), `applyNormalizationPasses()`; [`framework/compiler/source-compiler.mjs`](../../framework/compiler/source-compiler.mjs), `normalizeCompilerSource()` | Applies migration/resource passes in order and repairs TypeScript parent pointers after every structural change. Imported source uses the same pipeline. |
13
13
  | Focused normalization passes | [`framework/compiler/`](../../framework/compiler/) | React, Router, browser signals, animation-frame refs, custom-hook timers, Zustand, and render control each validate and lower a narrow source shape. |
14
14
  | Shared AST/scope helpers | [`framework/compiler/ast-helpers.mjs`](../../framework/compiler/ast-helpers.mjs) | Binding, scope, reference, effect-return, and source-location analysis. |
15
15
  | Pure collection language | [`framework/compiler/collection-analysis.mjs`](../../framework/compiler/collection-analysis.mjs) | Analyzes collection roots/selectors and serializes the allowed pure expression language used by lists and derived dependencies. |
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Status
4
4
 
5
- Deferred until Goal A is complete. Do not combine optimization with the compiler-boundary patches: structural movement would invalidate attribution and make output drift harder to review.
5
+ Active from the completed Goal A baseline at `0.8.23` commit `39a065b`. Maintained keyed restoration and external 1,000-product build measurements authorized the first two narrow optimizations.
6
6
 
7
7
  ## Purpose
8
8
 
@@ -21,6 +21,16 @@ At Goal A completion, record one source revision and the current maintained fixt
21
21
 
22
22
  Historical figures in [`PERFORMANCE.md`](../../PERFORMANCE.md) and the top-level Goal records are provenance, not an automatic current baseline. Reproduce a fixture before using it to approve work.
23
23
 
24
+ ### First Baseline Pass
25
+
26
+ The maintained Worker benchmark measured a 289.9 ms clean-build median, 907 B raw / 477 B gzip Worker graph, and 12,148 B raw / 5,411 B gzip window graph on Node 22. Its Chrome throughput, cadence, stale-write, bounded-history, and repeated ownership gate passed.
27
+
28
+ The preserved external 1,000-row keyed fixture was used only to find a candidate, not as a maintained approval benchmark. Its operations were fast, so a repository-owned benchmark was added for 2,000 rows with local state and reactive search. It measures filtering to one retained row, restoring 1,999 fresh rows, and reversing all rows in fresh Chrome profiles while checking retained identity, released identity, reset state, and restored handlers.
29
+
30
+ The maintained benchmark measured a 26.3 ms restoration median. For top-level flat lists where more than 32 additions are a majority of both the next rows and their parent children, mounting the connected list parent once rather than invoking every mount hook for every new row reduced the median to 21.1 ms (19.77%). A retained-heavy 33-row append stayed on the per-root path and showed no material change at 2.7 ms versus 2.6 ms. The route added 127 B raw / 35 B aggregate gzip JavaScript.
31
+
32
+ [`SimYunSup/kudzu-based-bench`](https://github.com/SimYunSup/kudzu-based-bench) then supplied a 1,000-product, 1,011-page build fixture. Twenty-one alternating clean builds measured 6,684.7 ms for clean `0.8.23` and 6,266.5 ms after skipping parent-pointer repair for normalization passes that return the unchanged AST, a 6.26% improvement. The output retained 3,056 files and only the separately optimized `kudzu-list.js` changed. Full raw arrays and limitations are recorded in [`PERFORMANCE.md`](../../PERFORMANCE.md).
33
+
24
34
  ## Candidate Order
25
35
 
26
36
  1. Profile the largest measured loss in a maintained fixture.
@@ -30,6 +40,8 @@ Historical figures in [`PERFORMANCE.md`](../../PERFORMANCE.md) and the top-level
30
40
 
31
41
  Known historical pressure points include large keyed-list removal/reconciliation and broad runtime specialization, but neither is authorized without a reproduced current loss.
32
42
 
43
+ The next evidence-backed investigation is repeated esbuild transformation of byte-identical generated route entries. The 1,000-product fixture emitted identical effect entries and identical native entries across product routes, but their transformation cost has not yet been isolated from rendering and filesystem work. Reuse transformed source only if an interleaved benchmark establishes a material gain while every route file, URL, define, and byte remains unchanged. Do not add a generalized cache.
44
+
33
45
  ## Benchmark Contract
34
46
 
35
47
  - Match visible content, behavior, errors, accessibility, and navigation semantics.
@@ -51,9 +63,9 @@ Reject an optimization that:
51
63
 
52
64
  ## Continuation Checklist
53
65
 
54
- - [ ] Verify Goal A acceptance is complete.
55
- - [ ] Freeze and record the post-Goal-A baseline revision.
56
- - [ ] Select one measured loss, not a speculative hotspot.
57
- - [ ] Add one minimal benchmark or reuse a maintained one.
58
- - [ ] Record before/after raw arrays and artifacts.
66
+ - [x] Verify Goal A acceptance is complete.
67
+ - [x] Freeze and record the post-Goal-A baseline revision.
68
+ - [x] Select one measured loss, not a speculative hotspot.
69
+ - [x] Add one minimal benchmark or reuse a maintained one.
70
+ - [x] Record before/after raw arrays and artifacts.
59
71
  - [ ] Revert experiments that do not clear correctness and materiality gates.
@@ -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.23` are completed scopes represented by package/release records.
3
+ This is an execution sequence, not release history. `0.8.16` through `0.8.24` 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
 
@@ -14,10 +14,11 @@ Keep each patch behavior-preserving and independently reviewable. If a boundary
14
14
  | `0.8.21` | Replace effect AST side tables with EffectIR covering setup, cleanup, dependencies, ownership, source, and Worker edges. | Route/layout/conditional/list lifetime, stale-write isolation, and exact resource cleanup remain unchanged. |
15
15
  | `0.8.22` | Version the existing RouteIR and CapabilityIR, formalize numeric slots plus readable debug metadata, and extract focused runtime generators. | RouteIR and CapabilityIR reject unsupported versions; runtime generator contracts, output gates, and the recorded benchmark pass. |
16
16
  | `0.8.23` | Forward-fix Goal A by moving source normalization, semantic analysis, ModuleIR finalization, handler generation, and build-module generation behind one no-write source compiler result. | `build.mjs` contains no TSX feature analysis; source results are JSON-safe and project-relative; diagnostics, deploy bytes, tests, and build performance remain equivalent. |
17
+ | `0.8.24` | Start Goal B with measured large keyed restoration and no-op normalization optimizations. | Fresh-profile keyed restoration improves materially; alternating 1,000-product builds improve materially; correctness, output, and byte deltas are recorded. |
17
18
 
18
19
  ## Sequence Rules
19
20
 
20
- - Goal A is complete. Goal B optimization remains deferred until explicitly started from the recorded `0.8.23` baseline.
21
+ - Goal A is complete. Goal B proceeds from the `0.8.23` baseline one repeatable measured loss at a time.
21
22
  - Keep Goal C research out of these patches and publish no store/resource API.
22
23
  - Keep Goal D behavior unchanged: complete HTML, native default, opt-in groups, no islands.
23
24
  - A planned patch may ship under a different actual version only if this table and release-facing documentation are updated before release.
@@ -38,7 +38,7 @@ Reduced Zustand migration stores lower to one ordinary layout-lifetime state slo
38
38
  - `compiler/collection-analysis.mjs`: pure collection expression IR, selector pipeline, alias, and imported-transform analysis.
39
39
  - `compiler/descriptor-session.mjs`: private source-local descriptor registration and deterministic JSON-safe HandlerIR, BindingIR, DerivedIR, KeyedBlockIR, EffectIR, import, and client-root finalization.
40
40
  - `compiler/effect-analysis.mjs`: ordered effect dependency classification and cleanup-owned browser resource validation before EffectIR registration.
41
- - `compiler/normalization-pipeline.mjs`: ordered source normalization with parent-pointer repair after every compiler pass.
41
+ - `compiler/normalization-pipeline.mjs`: ordered source normalization with parent-pointer repair after each structurally changed source root.
42
42
  - `compiler/param-codegen.mjs`: runtime pathname and search-parameter entry generation from rendered route descriptors.
43
43
  - `compiler/react-migration-pass.mjs`: React import, memo, callback, `forwardRef`, and `useId` migration validation and lowering.
44
44
  - `compiler/custom-hook-timer-pass.mjs`: private custom-hook timeout-ref validation and compiler-owned timer-state lowering.
@@ -90,4 +90,4 @@ A direct setter may cross one same-file or relative-imported component boundary
90
90
 
91
91
  `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.
92
92
 
93
- Cross-framework performance tables are historical snapshots from an excluded local benchmark workspace; the current checkout does not contain their competitor fixtures, runners, or raw arrays. The maintained provenance warning and tables live in the web docs. `npm run benchmark` is the tracked reproducible Worker fixture measurement, while the focused Chrome Worker test verifies throughput, cadence, bounded history, stale-write isolation, and route lifecycle behavior.
93
+ 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 with fresh Chrome profiles. Current methodology, raw arrays, external-fixture limits, and artifact deltas live in `PERFORMANCE.md` and the web docs.
@@ -2,8 +2,9 @@ import ts from "typescript"
2
2
 
3
3
  export function applyNormalizationPasses(sourceFile, passes) {
4
4
  for (const pass of passes) {
5
- sourceFile = pass(sourceFile)
6
- ts.setParentRecursive(sourceFile, false)
5
+ const next = pass(sourceFile)
6
+ if (next !== sourceFile) ts.setParentRecursive(next, false)
7
+ sourceFile = next
7
8
  }
8
9
  return sourceFile
9
10
  }
@@ -282,7 +282,8 @@ function updateList(list) {
282
282
  if (run.firstChild) parent.insertBefore(run, list.boundary)
283
283
  ordered = true
284
284
  } else parent.insertBefore(additions, list.boundary)
285
- if (addedNodes) for (const node of addedNodes) mountDom(node)
285
+ if (addedNodes?.length > 32 && addedNodes.length * 2 > next.length && addedNodes.length * 2 > parent.children.length && !list.descriptor.children && !list.descriptor.ownerField) mountDom(parent)
286
+ else if (addedNodes) for (const node of addedNodes) mountDom(node)
286
287
  list.container ??= parent
287
288
  }
288
289
  let anchor = list.boundary
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kudzujs/core",
3
- "version": "0.8.23",
3
+ "version": "0.8.24",
4
4
  "description": "HTML-first TSX framework with synchronous state semantics and no virtual DOM",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -55,6 +55,8 @@
55
55
  "check": "tsc --noEmit && tsc -p test/fixtures/tsconfig.json --noEmit && node ./bin/kudzu.mjs build",
56
56
  "test": "node --test test/*.test.mjs",
57
57
  "benchmark": "node test/performance.mjs",
58
+ "benchmark:keyed": "node test/keyed-performance.mjs",
59
+ "benchmark:commerce": "node test/commerce-build-performance.mjs",
58
60
  "prepublishOnly": "npm run check && npm test",
59
61
  "deploy": "wrangler deploy",
60
62
  "preview": "wrangler dev"