@kudzujs/core 0.8.25 → 0.8.26

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.
@@ -256,6 +256,12 @@ This queue orders the next investigations by general migration value. Start only
256
256
  - Normalization pass results and finalized ModuleIR cross-slot references now fail closed at their compiler boundaries.
257
257
  - Node 22 compatibility, required Chrome coverage, packed-package installation, version alignment, and post-publish registry checks are explicit release gates.
258
258
 
259
+ ### Completed In 0.8.26
260
+
261
+ - The maintained commerce runner requires byte-identical output by default while explicit expected deltas preserve historical benchmark reproduction.
262
+ - The standard suite counts exact route-entry transforms across repeated, distinct, and new-build sources and protects the safe keyed bulk-mount guard plus its per-root fallback.
263
+ - Goal B records which build, output, keyed, Worker, integration, and heap evidence exists; no new optimization is authorized without another reproduced material loss.
264
+
259
265
  ## Cross-Cutting Performance Gates
260
266
 
261
267
  Every migration feature must preserve:
package/PERFORMANCE.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
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
4
 
5
+ ## 0.8.26 Goal B Benchmark Hardening
6
+
7
+ The checked-in `benchmark:commerce` runner now requires byte-identical candidate output by default. `EXPECTED_CHANGES` is reserved for explicitly recorded historical comparisons; the route-entry reuse path also has a focused transform-count regression test in the ordinary suite.
8
+
9
+ After that runner update, seven alternating `v0.8.24` versus current-tree builds on the same Linux machine verified 1,011 pages, 3,056 files, and no changed deploy hash. The 14,766.5 ms and 12,202.4 ms medians validate the maintained runner and released-tree direction, but are not attributed to route-entry reuse alone because the compared revisions include all `0.8.25` compiler-boundary changes.
10
+
11
+ ```text
12
+ v0.8.24: [14311.1,14766.5,15294.2,14718.0,13440.6,15245.2,15007.0]
13
+ current: [12202.4,12243.2,11701.2,12320.8,11994.6,12461.4,12073.3]
14
+ ```
15
+
5
16
  ## 0.8.25 Route Entry Transform Reuse
6
17
 
7
18
  Measured UTC 2026-08-10 on an Intel Core i5-9500 with 6 cores, Linux 6.17.0-19-generic, Node 24.14.0, and npm 11.9.0. The public 1,000-product storefront fixture at `f2d5be1` generated 1,011 pages against the `0.8.24` tree plus the same compiler-boundary safety changes in both targets.
@@ -122,7 +133,7 @@ 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,
122
133
 
123
134
  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.
124
135
 
125
- 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:
136
+ 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 explicitly configured historical `assets/kudzu-list.js` delta, and restores the external app's package symlink afterward:
126
137
 
127
138
  ```bash
128
139
  git clone https://github.com/SimYunSup/kudzu-based-bench.git /tmp/kudzu-based-bench
@@ -134,6 +145,7 @@ ln -s "$PWD/node_modules" /tmp/kudzu-0.8.23/node_modules
134
145
  APP_ROOT=/tmp/kudzu-based-bench/apps/shop-kudzu \
135
146
  BASELINE_ROOT=/tmp/kudzu-0.8.23 \
136
147
  CANDIDATE_ROOT="$PWD" RUNS=21 CATALOG_SIZE=1000 \
148
+ EXPECTED_CHANGES=assets/kudzu-list.js \
137
149
  npm run benchmark:commerce
138
150
  ```
139
151
 
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.25 - Exact route-entry reuse.** Byte-identical generated route entries share one build-local transform result, compiler boundaries fail closed, and package release gates verify what is installed and published. The 1,011-page benchmark measures a 9.17% build improvement with identical deploy output. Read the [release notes](./RELEASES.md#0825---exact-route-entry-reuse), open the [release page](https://github.com/kudzujs/kudzu/releases/tag/v0.8.25), or follow the [architecture packet](./docs/next-architecture/README.md).
17
+ **Latest release: 0.8.26 - Goal B benchmark hardening.** Commerce comparisons now require byte-identical output by default, and the standard suite protects exact route-entry transform reuse plus safe keyed bulk-mount selection. Read the [release notes](./RELEASES.md#0826---goal-b-benchmark-hardening), open the [release page](https://github.com/kudzujs/kudzu/releases/tag/v0.8.26), 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.26 - Goal B benchmark hardening
4
+
5
+ Kudzu 0.8.26 makes the retained Goal B optimizations reproducible and directly regression-tested without changing generated runtime behavior or authoring support.
6
+
7
+ ### Changed in 0.8.26
8
+
9
+ - `benchmark:commerce` requires byte-identical candidate output by default; `EXPECTED_CHANGES` explicitly preserves historical comparisons with known artifact deltas.
10
+ - The standard suite verifies that exact route-entry sources transform once per build, distinct sources do not collide, and a new build owns a fresh transform map.
11
+ - List runtime generation tests retain the measured bulk-mount threshold, majority guards, nested/owner exclusions, and per-root fallback.
12
+ - The architecture packet now covers `0.8.25`, records Goal B baseline evidence and deliberate gaps, and closes the retained-experiment checklist.
13
+
14
+ ### Performance Validation
15
+
16
+ - Seven alternating `v0.8.24` and current-tree commerce builds emitted 1,011 pages and 3,056 files with no changed deploy hash.
17
+ - The measured medians were 14,766.5 ms and 12,202.4 ms. This validates the maintained runner and release direction but is not attributed to one optimization because the revisions include all `0.8.25` compiler-boundary changes.
18
+ - No new runtime bytes, scheduler, persistent cache, retained tree, or public browser capability was added.
19
+
20
+ ### Validation
21
+
22
+ - `npm run check`, `npm run test:package`, and all 175 tests pass.
23
+ - The exact-output commerce runner passed seven alternating 1,011-page builds.
24
+ - No accepted syntax, runtime behavior, DOM ownership, effect cleanup, or `create-kudzu` template changed.
25
+
26
+ ### Upgrade
27
+
28
+ ```bash
29
+ npm install @kudzujs/core@^0.8.26
30
+ ```
31
+
3
32
  ## 0.8.25 - Exact route-entry reuse
4
33
 
5
34
  Kudzu 0.8.25 removes measured repeated esbuild work from large multi-route builds, strengthens compiler boundary validation, and makes package publication gates explicit without changing generated deploy bytes or browser behavior.
@@ -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 | Active | The first measured bulk keyed restoration optimization is retained; continue one reproduced loss at a time. |
10
+ | B: optimization benchmarks | Active | Keyed restoration, no-op normalization, and exact route-entry transform reuse are retained; continue only when another current fixture reproduces a material loss. |
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
 
@@ -1,6 +1,6 @@
1
1
  # Current Compiler Architecture
2
2
 
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.
3
+ This maps the current `0.8.26` 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
 
@@ -15,7 +15,7 @@ This maps the current `0.8.24` architecture built on the completed `0.8.23` Goal
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. |
16
16
  | Main semantic analysis | [`framework/compiler/source-compiler.mjs`](../../framework/compiler/source-compiler.mjs), `createKudzuTransformer()` | Produces transformed source plus explicit component, handler, binding, derived, keyed, and effect ownership results. |
17
17
  | Component ownership analysis | [`framework/compiler/analysis/component-analysis.mjs`](../../framework/compiler/analysis/component-analysis.mjs) | Retains ordered JSON-safe owner and specialization records for state, setters, props, refs, IDs, direct signal links, and source provenance; AST identity remains private to its source-local session. |
18
- | Per-source descriptor registration | [`framework/compiler/descriptor-session.mjs`](../../framework/compiler/descriptor-session.mjs), `createSemanticArtifact()`, `createDescriptorSession()` | Keeps AST descriptors private during analysis, then finalizes deterministic JSON-safe HandlerIR, BindingIR, DerivedIR, KeyedBlockIR, EffectIR, imports, and client roots into ModuleIR. |
18
+ | Per-source descriptor registration | [`framework/compiler/descriptor-session.mjs`](../../framework/compiler/descriptor-session.mjs), `createSemanticArtifact()`, `createDescriptorSession()` | Keeps AST descriptors private during analysis, then finalizes deterministic JSON-safe HandlerIR, BindingIR, DerivedIR, KeyedBlockIR, EffectIR, imports, and client roots into ModuleIR and validates every local slot reference. |
19
19
  | Command IR and codegen | [`framework/compiler/optimize/command-specialization.mjs`](../../framework/compiler/optimize/command-specialization.mjs), [`framework/compiler/ir/module-ir.mjs`](../../framework/compiler/ir/module-ir.mjs), [`framework/compiler/codegen/command-codegen.mjs`](../../framework/compiler/codegen/command-codegen.mjs) | Supported command handlers specialize to JSON-safe ModuleIR, then emit the existing `__kBehavior` AST without changing route plans. |
20
20
  | Source compilation | [`framework/compiler/source-compiler.mjs`](../../framework/compiler/source-compiler.mjs), `compileSource()` | Runs TypeScript with the Kudzu transformer, rejects surviving React/Router references, and returns a JSON-safe project-relative build module, component analysis, ModuleIR, optional handler module, and imported assets without filesystem writes. |
21
21
  | Handler/evaluator lowering | [`framework/compiler/handler-lowering.mjs`](../../framework/compiler/handler-lowering.mjs) | Completes source-local callback/binding/list AST rewriting and diagnostics before the JSON-safe IR boundary. |
@@ -27,7 +27,7 @@ This maps the current `0.8.24` architecture built on the completed `0.8.23` Goal
27
27
  | Route capability projection | [`framework/compiler/route-capability-planner.mjs`](../../framework/compiler/route-capability-planner.mjs), `planRouteCapabilities()` | Validates RouteIR v1 and purely folds rendered plans and route facts into CapabilityIR v1. |
28
28
  | Effect entry generation | [`framework/compiler/effect-codegen.mjs`](../../framework/compiler/effect-codegen.mjs) | Generates ordinary, dependency, owned, and navigable effect entries from rendered descriptors. |
29
29
  | Runtime generation | [`framework/compiler/runtime-codegen.mjs`](../../framework/compiler/runtime-codegen.mjs), [`framework/compiler/list-runtime-codegen.mjs`](../../framework/compiler/list-runtime-codegen.mjs), [`framework/compiler/param-codegen.mjs`](../../framework/compiler/param-codegen.mjs) | Consumes versioned contracts, specializes authored capability sources with fail-closed anchors, and returns source/define results without filesystem ownership. |
30
- | Artifact emission | `framework/build.mjs` | Selects required files from CapabilityIR and writes or bundles generated sources with esbuild. |
30
+ | Artifact emission | `framework/build.mjs` | Selects required files from CapabilityIR and writes or bundles generated sources with esbuild. Byte-identical native, parameter, and effect route entries reuse one exact-source transform result within the current build only. |
31
31
  | Browser capabilities | [`framework/*.js`](../../framework/) | Small optional modules for commands, bindings, lists, effects, native handlers, serialization, parameters, and navigation; no component runtime. |
32
32
  | Opt-in navigation | [`framework/navigation-runtime.js`](../../framework/navigation-runtime.js) plus `framework/build.mjs` navigation configuration/emission | Fetches and validates complete same-origin documents, replaces only the marked route range, manages route/layout disposal, history, focus, finite prefetch retention, and native fallback. |
33
33
  | Development serving | [`framework/dev-server.mjs`](../../framework/dev-server.mjs) and [`framework/dev-state.js`](../../framework/dev-state.js) | Rebuild/watch/SSE and response-only short-lived state restoration; never changes production `dist/`. |
@@ -50,6 +50,7 @@ src/pages entries + config
50
50
  -> planRouteCapabilities(RouteIR records, route facts)
51
51
  -> CapabilityIR v1
52
52
  -> specialize and emit only selected runtime/capability ESM
53
+ -> reuse exact generated route-entry transforms within this build
53
54
  -> write route index.html, CSS/assets, Worker graphs, rewrites, and .kudzu/kudzu-plan.json
54
55
  -> optional afterBuild()
55
56
  ```
@@ -33,6 +33,19 @@ The maintained benchmark measured a 26.3 ms restoration median. For top-level fl
33
33
 
34
34
  The `0.8.25` investigation isolated repeated esbuild work by comparing ordinary transformation with build-local reuse keyed by the complete generated route-entry source. Seven alternating 1,011-page builds measured 13,851.0 ms and 12,581.4 ms medians, a 9.17% improvement, with identical emitted paths and hashes. The retained implementation applies only to native, parameter, and effect route entries and keeps no data beyond one build.
35
35
 
36
+ ### Baseline Coverage Status
37
+
38
+ | Area | Current evidence | Status |
39
+ |---|---|---|
40
+ | Build and artifact graph | Worker and commerce clean builds, emitted manifests, deterministic hashes, raw/gzip JavaScript and Worker bytes | Recorded |
41
+ | Static exclusion | Complete-site and representative fixture comparisons plus static zero-JavaScript assertions | Recorded |
42
+ | Keyed operations | Append, filter, bulk restoration, reverse, retained/released identity, state reset, and handler checks | Recorded |
43
+ | Worker ownership | Throughput, cadence, bounded history, stale writes, and repeated start/termination/listener ownership | Recorded |
44
+ | Command, binding, effect, and navigation semantics | Maintained integration and Chrome behavior tests | Correctness recorded; no standalone timing baseline because no material loss is currently reproduced |
45
+ | Heap trend | Repeated ownership counters and bounded fixture data | No general heap series; add one only when a reproduced ownership or memory loss requires it |
46
+
47
+ The broad baseline list is an investigation inventory, not a requirement to manufacture timings without a candidate. New timing or heap work begins only when a current fixture reproduces the corresponding loss.
48
+
36
49
  ## Candidate Order
37
50
 
38
51
  1. Profile the largest measured loss in a maintained fixture.
@@ -70,4 +83,4 @@ Reject an optimization that:
70
83
  - [x] Select one measured loss, not a speculative hotspot.
71
84
  - [x] Add one minimal benchmark or reuse a maintained one.
72
85
  - [x] Record before/after raw arrays and artifacts.
73
- - [ ] Revert experiments that do not clear correctness and materiality gates.
86
+ - [x] Keep no experiment that fails correctness or materiality gates in the release tree.
@@ -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.24` are completed scopes represented by package/release records.
3
+ This is an execution sequence, not release history. `0.8.16` through `0.8.26` 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
 
@@ -15,6 +15,8 @@ Keep each patch behavior-preserving and independently reviewable. If a boundary
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
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. |
18
+ | `0.8.25` | Reuse byte-identical generated native, parameter, and effect route-entry transforms within one build and strengthen compiler/release boundaries. | Alternating 1,011-page builds improve materially with identical deploy hashes; normalization and ModuleIR fail closed; Node, Chrome, package, and registry gates pass. |
19
+ | `0.8.26` | Harden Goal B benchmark reproducibility and ordinary regression coverage without changing runtime behavior. | Commerce comparison defaults to exact output; route transform counts and keyed bulk/fallback guards are protected by the standard suite; baseline coverage and limits are explicit. |
18
20
 
19
21
  ## Sequence Rules
20
22
 
@@ -389,13 +389,13 @@ async function writeJavaScript(file, source, minify, define) {
389
389
  await writeFile(file, code)
390
390
  }
391
391
 
392
- async function writeRouteEntry(file, source, minify, transforms) {
392
+ export async function writeRouteEntry(file, source, minify, transforms, transformSource = transform, write = writeFile) {
393
393
  let code = transforms.get(source)
394
394
  if (code === undefined) {
395
- code = minify ? (await transform(source, { format: "esm", legalComments: "none", minify, target: "es2022" })).code : source
395
+ code = minify ? (await transformSource(source, { format: "esm", legalComments: "none", minify, target: "es2022" })).code : source
396
396
  transforms.set(source, code)
397
397
  }
398
- await writeFile(file, code)
398
+ await write(file, code)
399
399
  }
400
400
 
401
401
  async function writeBundledJavaScript(file, source, minify, define) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kudzujs/core",
3
- "version": "0.8.25",
3
+ "version": "0.8.26",
4
4
  "description": "HTML-first TSX framework with synchronous state semantics and no virtual DOM",
5
5
  "type": "module",
6
6
  "license": "MIT",