@kudzujs/core 0.12.2 → 0.12.4
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
|
@@ -6,6 +6,54 @@ 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
|
+
## 0.12.4 Nested Layout Evidence Decision
|
|
10
|
+
|
|
11
|
+
Verified 2026-08-24 on Linux x64 with Node 24.14.0 and Chrome
|
|
12
|
+
142.0.7444.175. Six executable route sets fit the existing ownership model: one
|
|
13
|
+
retained layout owner around one replaceable route owner, followed by existing
|
|
14
|
+
conditional, keyed, effect, and DOM ownership. Zero routes prove an intermediate
|
|
15
|
+
retained layout lifetime, so the packet closes by its stop condition without an
|
|
16
|
+
owner chain.
|
|
17
|
+
|
|
18
|
+
Generated output is byte-identical to `0.12.3`: 43 deploy files totaling 123,835
|
|
19
|
+
raw / 45,379 aggregate gzip bytes with SHA-256
|
|
20
|
+
`fb9d24cc01791bf80b67b659738ba62beded6ff6ce14a86a278fa4b34d088acf`.
|
|
21
|
+
The two-route session remains 16 JavaScript files totaling 61,126 raw / 22,663
|
|
22
|
+
aggregate gzip bytes, and `/help` remains 0 B JavaScript.
|
|
23
|
+
|
|
24
|
+
Core semantic LOC remains 5,682 with zero semantic primitives, IR kinds,
|
|
25
|
+
compiler passes, production compiler/runtime lines, runtime concepts, layout
|
|
26
|
+
registries, disposal paths, public APIs, browser files, or browser bytes added.
|
|
27
|
+
No benchmark rerun or latency comparison applies because production and
|
|
28
|
+
generated code are unchanged; the published `0.12.3` 1.8 ms median and 1.5-2.4
|
|
29
|
+
ms range remain provenance rather than a new claim.
|
|
30
|
+
|
|
31
|
+
## 0.12.3 Route Failure And Restoration Policy
|
|
32
|
+
|
|
33
|
+
Measured 2026-08-24 on Linux x64 with Node 24.14.0 and Chrome
|
|
34
|
+
142.0.7444.175. Required Chrome proves current-document retention for fetch and
|
|
35
|
+
response-body transport failures, accessible failure status, restored link
|
|
36
|
+
focus, retry after a failed pending prefetch, invalid-document fallback,
|
|
37
|
+
capability-module fallback, stylesheet fallback, and no pre-commit route
|
|
38
|
+
removal. The maintained application-owned HTTP 500 alert and explicit data
|
|
39
|
+
retry continue to pass.
|
|
40
|
+
|
|
41
|
+
The two-route session uses 16 JavaScript files totaling 61,126 raw / 22,663
|
|
42
|
+
aggregate gzip bytes, an increase of 359 raw bytes from `0.12.2` for
|
|
43
|
+
transport-error classification, status, and focus restoration. The 102-byte
|
|
44
|
+
gzip difference is unpaired and environment-sensitive, so it is not attributed
|
|
45
|
+
to the patch. Navigation
|
|
46
|
+
samples are `[1.5, 1.6, 2.0, 1.7, 1.8, 2.4, 1.8]` ms, with a 1.8 ms median and
|
|
47
|
+
1.5/2.4 ms minimum/maximum. The environment differs from the macOS arm64 Chrome
|
|
48
|
+
151 `0.12.2` measurement, so no latency comparison is claimed.
|
|
49
|
+
|
|
50
|
+
The application emits 43 files totaling 123,835 raw / 45,379 aggregate gzip
|
|
51
|
+
bytes with deploy SHA-256
|
|
52
|
+
`fb9d24cc01791bf80b67b659738ba62beded6ff6ce14a86a278fa4b34d088acf`.
|
|
53
|
+
Core semantic LOC remains 5,682 with no semantic primitive, compiler pass, core
|
|
54
|
+
compiler line, runtime concept, or public API. Navigation runtime source grows
|
|
55
|
+
from 351 to 374 lines. `/help` remains 0 B JavaScript.
|
|
56
|
+
|
|
9
57
|
## 0.12.2 Authentication And Permission Boundary
|
|
10
58
|
|
|
11
59
|
Measured 2026-08-23 on macOS arm64 with Node 25.6.1 and Chrome
|
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.12.x`: the compiler API and supported TSX surface may change.
|
|
16
16
|
|
|
17
|
-
**Latest release: 0.12.
|
|
17
|
+
**Latest release: 0.12.4 - Nested layout evidence decision.** Six executable route sets fit the existing single-layout model, so Kudzu adds no speculative owner chain or browser runtime. Read the [release notes](./RELEASES.md#0124---nested-layout-evidence-decision), open the [release page](https://github.com/kudzujs/kudzu/releases/tag/v0.12.4), 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,101 @@
|
|
|
1
1
|
# Kudzu Releases
|
|
2
2
|
|
|
3
|
+
## 0.12.4 - Nested Layout Evidence Decision
|
|
4
|
+
|
|
5
|
+
Kudzu 0.12.4 reviews executable route ownership evidence and keeps the existing
|
|
6
|
+
single-layout model instead of adding a speculative nested owner chain.
|
|
7
|
+
|
|
8
|
+
### Changed in 0.12.4
|
|
9
|
+
|
|
10
|
+
- Reviewed the project application's list/detail/runtime routes, Apache Answer
|
|
11
|
+
route and authentication shells, Context and Zustand carts, and independent
|
|
12
|
+
navigation groups.
|
|
13
|
+
- Recorded zero routes requiring an intermediate retained layout whose state,
|
|
14
|
+
effects, or DOM survive descendant replacement and dispose on subtree exit.
|
|
15
|
+
- Accepted one shared layout plus static composition, route ownership, native
|
|
16
|
+
document navigation, and disjoint navigation groups as the current boundary.
|
|
17
|
+
- Updated `create-kudzu@0.1.117` to generate projects on
|
|
18
|
+
`@kudzujs/core@^0.12.4`.
|
|
19
|
+
|
|
20
|
+
### Output Evidence
|
|
21
|
+
|
|
22
|
+
- The application remains unchanged at 43 files, 123,835 raw / 45,379 aggregate
|
|
23
|
+
gzip bytes, and deploy digest
|
|
24
|
+
`fb9d24cc01791bf80b67b659738ba62beded6ff6ce14a86a278fa4b34d088acf`.
|
|
25
|
+
- The maintained enhanced session remains 16 JavaScript files totaling 61,126
|
|
26
|
+
raw / 22,663 aggregate gzip bytes; `/help` remains 0 B JavaScript.
|
|
27
|
+
- No semantic primitive, IR kind, compiler pass, production compiler/runtime
|
|
28
|
+
line, runtime concept, layout registry, disposal path, or browser byte was
|
|
29
|
+
added.
|
|
30
|
+
|
|
31
|
+
### Validation
|
|
32
|
+
|
|
33
|
+
- The machine-readable project contract records six reviewed route sets, zero
|
|
34
|
+
qualifying routes, no owner chain, and the reused ownership semantics.
|
|
35
|
+
- The full 273-test suite, package smoke, registry metadata, and fresh
|
|
36
|
+
installation are release gates.
|
|
37
|
+
|
|
38
|
+
### Limits
|
|
39
|
+
|
|
40
|
+
Nested retained-layout owners remain unsupported. Reconsideration requires
|
|
41
|
+
three unrelated executable application routes proving the same intermediate
|
|
42
|
+
lifetime and explicit deepest-first disposal order.
|
|
43
|
+
|
|
44
|
+
### Upgrade
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
npm install @kudzujs/core@^0.12.4
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 0.12.3 - Route Failure And Restoration Policy
|
|
51
|
+
|
|
52
|
+
Kudzu 0.12.3 defines recovery for enhanced route failures without adding an
|
|
53
|
+
error-boundary renderer or client router.
|
|
54
|
+
|
|
55
|
+
### Changed in 0.12.3
|
|
56
|
+
|
|
57
|
+
- Retained the current document when an enhanced navigation fetch or response
|
|
58
|
+
body fails in transit.
|
|
59
|
+
- Announced transport failure through the existing polite status and restored
|
|
60
|
+
focus to the initiating native link for explicit retry.
|
|
61
|
+
- Kept invalid document identity, missing capability modules, and missing
|
|
62
|
+
stylesheets on the existing native fallback path before route disposal.
|
|
63
|
+
- Proved retry after a failed pending prefetch and subsequent click request.
|
|
64
|
+
- Updated `create-kudzu@0.1.116` to generate projects on
|
|
65
|
+
`@kudzujs/core@^0.12.3`.
|
|
66
|
+
|
|
67
|
+
### Output Evidence
|
|
68
|
+
|
|
69
|
+
- The application emits 43 files, 123,835 raw / 45,379 aggregate gzip bytes,
|
|
70
|
+
and deploy digest
|
|
71
|
+
`fb9d24cc01791bf80b67b659738ba62beded6ff6ce14a86a278fa4b34d088acf`.
|
|
72
|
+
- The maintained enhanced session uses 16 JavaScript files totaling 61,126 raw
|
|
73
|
+
/ 22,663 aggregate gzip bytes, 359 raw bytes above `0.12.2`.
|
|
74
|
+
- `/help` remains complete HTML with 0 B JavaScript.
|
|
75
|
+
- No semantic primitive, compiler pass, core compiler line, runtime concept,
|
|
76
|
+
public API, error-boundary renderer, or browser file was added.
|
|
77
|
+
|
|
78
|
+
### Validation
|
|
79
|
+
|
|
80
|
+
- Required Chrome proves retained fetch and body failures, accessible status,
|
|
81
|
+
restored link focus, retry, and native invalid-document/module/style fallback.
|
|
82
|
+
- Seven fresh Chrome profiles record a 1.8 ms navigation median with a 1.5-2.4
|
|
83
|
+
ms range. The host differs from `0.12.2`, so no latency change is claimed.
|
|
84
|
+
- The full 273-test suite, package smoke, registry metadata, and fresh
|
|
85
|
+
installation are release gates.
|
|
86
|
+
|
|
87
|
+
### Limits
|
|
88
|
+
|
|
89
|
+
The retained-document policy covers classified transport failures. Invalid
|
|
90
|
+
documents and assets use native navigation; arbitrary corrupted generated mount
|
|
91
|
+
descriptors are outside this packet.
|
|
92
|
+
|
|
93
|
+
### Upgrade
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
npm install @kudzujs/core@^0.12.3
|
|
97
|
+
```
|
|
98
|
+
|
|
3
99
|
## 0.12.2 - Authentication And Permission Boundary
|
|
4
100
|
|
|
5
101
|
Kudzu 0.12.2 completes the project application's login, restoration,
|
|
@@ -622,10 +622,38 @@ bytes. Seven fresh Chrome profiles record a 1.4 ms navigation median with a
|
|
|
622
622
|
- **Purpose:** decide application-visible handling of navigation/data failures.
|
|
623
623
|
- **Expected boundary:** native fallback and application-owned error UI first.
|
|
624
624
|
- **Acceptance:** invalid document, asset failure, offline/error state, retry,
|
|
625
|
-
focus restoration, and no half-replaced route.
|
|
625
|
+
focus restoration, and no half-replaced route for those precommit failures.
|
|
626
626
|
- **Stop condition:** a generic React-style error-boundary renderer is required.
|
|
627
|
-
- **Done condition:**
|
|
628
|
-
|
|
627
|
+
- **Done condition:** each classified transport, document-validation,
|
|
628
|
+
capability-loading, or stylesheet-loading failure leaves a valid document
|
|
629
|
+
and recoverable navigation path.
|
|
630
|
+
|
|
631
|
+
**Completion evidence:** required Chrome injects deterministic fetch and
|
|
632
|
+
response-body transport rejections through a pending prefetch and click retry,
|
|
633
|
+
then proves the current URL, route DOM, and retained layout remain unchanged.
|
|
634
|
+
The test moves focus away while the request is pending; the existing polite
|
|
635
|
+
navigation status announces the failure and restores the initiating link.
|
|
636
|
+
Activating that link again completes list-to-detail replacement and focuses the
|
|
637
|
+
destination heading.
|
|
638
|
+
Separate invalid-identity, missing-capability-module, and missing-stylesheet
|
|
639
|
+
responses fail before route disposal and recover through the existing native
|
|
640
|
+
document fallback. The maintained HTTP 500 project read still reports an
|
|
641
|
+
application-owned alert and succeeds on explicit retry.
|
|
642
|
+
|
|
643
|
+
Only `navigation-runtime.js` changes: fetch and response-body transport failures
|
|
644
|
+
receive one private error classification, while document validation and asset
|
|
645
|
+
failures keep their existing fallback. The source grows from 351 to 374 lines and adds no
|
|
646
|
+
semantic primitive, ModuleIR kind, compiler pass, core compiler line, runtime
|
|
647
|
+
concept, public API, error-boundary renderer, route registry, or additional
|
|
648
|
+
browser file. The application emits 43 files totaling 123,835 raw / 45,379
|
|
649
|
+
aggregate gzip bytes with deploy SHA-256
|
|
650
|
+
`fb9d24cc01791bf80b67b659738ba62beded6ff6ce14a86a278fa4b34d088acf`.
|
|
651
|
+
The two-route session remains 16 JavaScript files totaling 61,126 raw / 22,663
|
|
652
|
+
aggregate gzip bytes, 359 raw bytes above `0.12.2`; the unpaired,
|
|
653
|
+
environment-sensitive 102-byte gzip difference is not attributed to the patch.
|
|
654
|
+
`/help` remains 0 B JavaScript. Seven fresh Linux x64 Chrome 142 profiles record
|
|
655
|
+
a 1.8 ms median with a 1.5/2.4 ms range. No latency comparison is claimed
|
|
656
|
+
against the macOS arm64 Chrome 151 `0.12.2` samples.
|
|
629
657
|
|
|
630
658
|
### `0.12.4`: Nested Layout Evidence Decision
|
|
631
659
|
|
|
@@ -637,6 +665,39 @@ bytes. Seven fresh Chrome profiles record a 1.4 ms navigation median with a
|
|
|
637
665
|
- **Done condition:** either existing layout composition is accepted or a
|
|
638
666
|
minimal layout-owner chain is approved with explicit disposal order.
|
|
639
667
|
|
|
668
|
+
**Completion evidence:** architecture review covers the project application's
|
|
669
|
+
list, static detail, runtime project, and runtime issue routes; Apache Answer's
|
|
670
|
+
questions, tags, admin, and legal route-shell reduction; its independently
|
|
671
|
+
reduced authentication shell; the Context and Zustand cart reductions; and the
|
|
672
|
+
two disjoint navigation-group shells. All executable evidence fits one retained
|
|
673
|
+
layout owner around one replaceable route owner, followed by existing
|
|
674
|
+
conditional, keyed, effect, and DOM ownership. The project runtime routes use
|
|
675
|
+
native document navigation, the Answer shell is static composition, and the
|
|
676
|
+
independent navigation groups require disjoint top-level owners rather than a
|
|
677
|
+
nested owner chain.
|
|
678
|
+
|
|
679
|
+
No reviewed route proves an intermediate layout whose DOM, state, or effects
|
|
680
|
+
must survive descendant route replacement and then dispose on subtree exit.
|
|
681
|
+
The qualifying evidence count is zero, below the required three unrelated
|
|
682
|
+
routes. The stop condition is met: current nesting is source organization or
|
|
683
|
+
static composition, so this packet accepts the existing single-layout model and
|
|
684
|
+
does not authorize a layout-owner chain. A future review must first prove the
|
|
685
|
+
same otherwise-inexpressible intermediate lifetime in three unrelated
|
|
686
|
+
executable application routes, including leaf-before-intermediate and
|
|
687
|
+
deepest-first disposal requirements.
|
|
688
|
+
|
|
689
|
+
The project application records `closed-by-stop-condition`, the reviewed route
|
|
690
|
+
sets, an empty qualifying-route list, and the reused ownership semantics in its
|
|
691
|
+
machine-readable capability contract. This packet adds zero semantic
|
|
692
|
+
primitives, ModuleIR or RouteIR kinds, compiler passes, production compiler or
|
|
693
|
+
runtime lines, runtime concepts, normalization or adapter rules, public APIs,
|
|
694
|
+
layout registries, disposal paths, browser files, or browser bytes. Existing
|
|
695
|
+
fixtures and output remain unchanged: 43 deploy files totaling 123,835 raw /
|
|
696
|
+
45,379 aggregate gzip bytes with the same deploy digest, a 61,126 raw / 22,663
|
|
697
|
+
aggregate gzip two-route JavaScript session, and 0 B JavaScript on `/help`. No
|
|
698
|
+
benchmark rerun or latency claim applies to a machine-readable evidence decision
|
|
699
|
+
with no generated-output change.
|
|
700
|
+
|
|
640
701
|
## `0.13.x`: Forms
|
|
641
702
|
|
|
642
703
|
### `0.13.0`: Production Form And Server Validation
|
|
@@ -1174,5 +1235,8 @@ release transaction where possible or document and publish a forward-fix patch.
|
|
|
1174
1235
|
| `0.11.4` | Released | Preserve the published bounded pagination, history, refresh, polling cleanup, and exact request-count evidence. | None |
|
|
1175
1236
|
| `0.12.0` | Released | Preserve direct runtime entry, reload, rewrite, and native fallback evidence. | None |
|
|
1176
1237
|
| `0.12.1` | Released | Preserve the published layout/history/focus/scroll evidence. | None |
|
|
1177
|
-
| `0.12.2` |
|
|
1178
|
-
| `0.12.3`
|
|
1238
|
+
| `0.12.2` | Released | Preserve the published authentication and permission evidence. | None |
|
|
1239
|
+
| `0.12.3` | Released | Preserve the published route failure, focused retry, native fallback, and precommit retention evidence. | None |
|
|
1240
|
+
| `0.12.4` | Released | Preserve the published single-layout decision and zero-owner-chain evidence. | None |
|
|
1241
|
+
| `0.13.0` | Active | Complete the production form and server-validation packet. | None |
|
|
1242
|
+
| `0.13.1` onward | Blocked | Complete the `0.13.0` release transaction 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.
|
|
69
|
+
`create-kudzu@0.1.117` retains the explicit install instructions and generates projects with `@kudzujs/core@^0.12.4`.
|
|
70
70
|
|
|
71
71
|
## Release Boundary
|
|
72
72
|
|
|
@@ -28,7 +28,7 @@ document.addEventListener("click", event => {
|
|
|
28
28
|
if (!eligibleClick(event, anchor)) return
|
|
29
29
|
const url = new URL(anchor.href)
|
|
30
30
|
event.preventDefault()
|
|
31
|
-
navigate(url, true)
|
|
31
|
+
navigate(url, true, anchor)
|
|
32
32
|
})
|
|
33
33
|
document.addEventListener("pointerover", event => prefetchAnchor(event.target.closest?.("a[href]")))
|
|
34
34
|
document.addEventListener("focusin", event => prefetchAnchor(event.target.closest?.("a[href]")))
|
|
@@ -111,7 +111,7 @@ function prune(anchors) {
|
|
|
111
111
|
for (const key of documents.keys()) if (!retained.has(key)) documents.delete(key)
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
async function navigate(url, push) {
|
|
114
|
+
async function navigate(url, push, source) {
|
|
115
115
|
await ready
|
|
116
116
|
const record = matchRoute(url.pathname)
|
|
117
117
|
if (!record) return fallback(url, push)
|
|
@@ -158,6 +158,11 @@ async function navigate(url, push) {
|
|
|
158
158
|
styleUpdate?.rollback()
|
|
159
159
|
if (pendingStyleUpdate === styleUpdate) pendingStyleUpdate = undefined
|
|
160
160
|
if (current !== revision || error.name === "AbortError") return
|
|
161
|
+
if (push && error.name === "NavigationRequestError") {
|
|
162
|
+
status.textContent = "Navigation failed. Retry the link."
|
|
163
|
+
if (source?.isConnected) source.focus({ preventScroll: true })
|
|
164
|
+
return
|
|
165
|
+
}
|
|
161
166
|
fallback(url, push)
|
|
162
167
|
if (committed) return
|
|
163
168
|
}
|
|
@@ -172,9 +177,20 @@ async function loadCapabilities(parsed) {
|
|
|
172
177
|
}
|
|
173
178
|
|
|
174
179
|
async function fetchDocument(url, record, signal) {
|
|
175
|
-
|
|
180
|
+
let response
|
|
181
|
+
try {
|
|
182
|
+
response = await fetch(url, { signal, redirect: "manual", headers: { accept: "text/html" } })
|
|
183
|
+
} catch (cause) {
|
|
184
|
+
throw requestError(cause)
|
|
185
|
+
}
|
|
176
186
|
if (!response.ok || response.redirected || response.type === "opaqueredirect" || !response.headers.get("content-type")?.toLowerCase().includes("text/html")) throw new Error("Navigation response is not successful nonredirected HTML")
|
|
177
|
-
|
|
187
|
+
let html
|
|
188
|
+
try {
|
|
189
|
+
html = await response.text()
|
|
190
|
+
} catch (cause) {
|
|
191
|
+
throw requestError(cause)
|
|
192
|
+
}
|
|
193
|
+
const incoming = new DOMParser().parseFromString(html, "text/html")
|
|
178
194
|
const parsed = validate(incoming, record)
|
|
179
195
|
return { incoming, parsed, capabilities: await loadCapabilities(parsed), record }
|
|
180
196
|
}
|
|
@@ -315,6 +331,13 @@ function fallback(url, push) {
|
|
|
315
331
|
else location.reload()
|
|
316
332
|
}
|
|
317
333
|
|
|
334
|
+
function requestError(cause) {
|
|
335
|
+
if (cause?.name === "AbortError") return cause
|
|
336
|
+
const error = new Error("Navigation request failed", { cause })
|
|
337
|
+
error.name = "NavigationRequestError"
|
|
338
|
+
return error
|
|
339
|
+
}
|
|
340
|
+
|
|
318
341
|
function between(start, end) {
|
|
319
342
|
if (start.parentNode !== end.parentNode) throw new Error("Route markers must share a parent")
|
|
320
343
|
const nodes = []
|