@ape-egg/vibe 1.3.2 → 1.6.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/CHANGELOG.md CHANGED
@@ -1,5 +1,200 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.6.1] - 2026-02-12
4
+
5
+ ### Fixed
6
+
7
+ - **Compiler output directory handling** - Fixed duplicate file generation in output
8
+ - Compiler now properly handles source and output paths without preserving source directory structure
9
+ - Files from `./src` are now correctly written to root of output directory (e.g., `compiled/index.html`) instead of `compiled/src/index.html`
10
+ - Canonicalized source path for reliable comparison and path stripping
11
+ - Updated all processing functions to use canonical source path for relative path calculation
12
+
13
+ - **Manifest detection improvements** - Better handling of directory URLs and extensionless paths
14
+ - Directory URLs now normalized: `/compiled/` → `/compiled/index.html`
15
+ - Extensionless URLs now normalized: `/compiled/mypage` → `/compiled/mypage.html`
16
+ - Fixes manifest detection when visiting pages without explicit `.html` extension
17
+ - Enables proper hyperspeed loading for directory index pages
18
+
19
+ ---
20
+
21
+ ## [1.6.0] - 2026-02-12
22
+
23
+ ### Added
24
+
25
+ - **Watch mode** - Compiler now supports file watching with incremental compilation
26
+ - New `--watch` flag monitors source files for changes and automatically recompiles
27
+ - Intelligent change detection tracks affected files and their dependencies
28
+ - Transitive dependency tracking: changes to components trigger recompilation of pages using them
29
+ - Blacklist support: watch mode respects SKIP_FILES patterns (tests/, node_modules/, etc.)
30
+ - Debounced file events (300ms) prevent excessive compilation during rapid changes
31
+ - Outputs only changed files for fast incremental builds
32
+ - First compile shows full output, subsequent compiles show only deltas
33
+ - **Reserved element validation** - Compiler now prevents component naming conflicts
34
+ - New `reservedElements` config option (replaces `excludeTags`)
35
+ - Defaults to all HTML5 elements plus "component" keyword
36
+ - User-provided values append to defaults (not replace)
37
+ - Case-sensitive validation: `nav.html` → Error, `Nav.html` → OK
38
+ - Compile-time error with clear message showing conflicting filename
39
+ - Prevents runtime confusion between HTML elements and custom components
40
+ - **Component path case-sensitivity** - Component paths are now treated as case-sensitive
41
+ - `<component src="path/to/MyComponent.html">` and `<component src="path/to/mycomponent.html">` are different
42
+ - Both runtime and compiler preserve exact case in paths
43
+ - Cache keys include full case-sensitive path
44
+ - Enables PascalCase naming convention for components while supporting any casing
45
+
46
+ ### Changed
47
+
48
+ - **Component inlining architecture** - Complete rewrite from iterative to recursive fetching
49
+ - Removed MAX_ITERATIONS constant and loop-based approach
50
+ - `fetch_component_recursive()` now returns fully resolved content with all nested components inlined
51
+ - Components are cached only after being fully resolved (prevents incomplete content in cache)
52
+ - `inline_component_elements()` now does single pass (no loops)
53
+ - Significant performance improvement: sub-100ms compilation for complex nested components
54
+ - **Framework element handling** - `<component>` is now recognized as a framework element
55
+ - Never transformed to `<div>` regardless of `--elements-as-is` flag
56
+ - Custom elements (e.g., `<card>`, `<text>`) are transformed when `elements_as_is: false`
57
+ - Framework elements vs custom elements properly distinguished in compiler
58
+ - Wrapper `<component>` tags remain after inlining (expected by runtime)
59
+ - **Component inlining behavior** - Custom elements are always inlined
60
+ - `<card>` → transformed to `<component>` → inlined even with `--components-as-is`
61
+ - `--components-as-is` only affects explicit `<component src="...">` tags
62
+ - Consistent behavior: custom elements compile away, framework elements remain
63
+ - **Path normalization** - Component paths now consistently normalized
64
+ - All paths start with `/` (unless external URL)
65
+ - Cache uses normalized paths to prevent duplicates (`/components/nav.html` vs `./components/nav.html`)
66
+ - Fixes cache pollution from different path formats for same component
67
+ - **Config naming** - `excludeTags` renamed to `reservedElements` throughout codebase
68
+ - Better describes purpose (reserved from use as component names)
69
+ - Updated in Rust compiler, config files, and documentation
70
+ - Backward compatible: old config key still works but deprecated
71
+
72
+ ### Fixed
73
+
74
+ - Watch mode was compiling blacklisted files (tests/, node_modules/)
75
+ - Component inlining created infinite nested wrappers (100+ levels)
76
+ - Empty headlines in tests due to broken external component fetching
77
+ - Path case normalization could cause duplicates in component cache
78
+ - Accessibility transformation incorrectly converting `<component>` to divs
79
+ - Test expectations mismatched actual framework element behavior
80
+
81
+ ### Performance
82
+
83
+ - Watch mode incremental compilation: ~100ms for typical changes
84
+ - First full compilation: ~300-500ms
85
+ - Component fetching: recursive approach 10x faster than iterative (no MAX_ITERATIONS overhead)
86
+ - Path normalization prevents redundant fetches of same component
87
+
88
+ ---
89
+
90
+ ## [1.5.0] - 2026-02-09
91
+
92
+ ### Added
93
+
94
+ - **Nested iteration compilation** - Compiler now handles infinitely nested `<!-- each -->` blocks
95
+ - Recursive processing in `iteration_optimizer.rs` with depth counting for comment pair matching
96
+ - Nested loops compile to IIFEs (Immediately Invoked Function Expressions) with template literals
97
+ - Inner iterations inlined directly into outer batch functions for optimal performance
98
+ - Example: `<!-- each categories as cat --><!-- each cat.items as item -->` compiles to single optimized function
99
+ - **QuickJS JavaScript runtime** - Full expression evaluation at compile time
100
+ - Embedded QuickJS engine (`rquickjs = "0.6"`) for JavaScript evaluation in Rust
101
+ - No external dependencies - increases binary size by ~1-2MB
102
+ - Evaluates any JavaScript expression: `@[categories.length]`, `@[items[0]]`, `@[user.name.toUpperCase()]`
103
+ - State set in global scope: `Object.assign(globalThis, $)` matches Vibe runtime behavior
104
+ - Fast evaluation: ~160ms overhead for 35 files (~5ms per file)
105
+ - **Complete pre-rendering** - Zero FOUC with all bindings pre-rendered for SEO
106
+ - All `@[expression]` bindings evaluated and stamped into HTML at compile time
107
+ - Handles property access (`@[user.name]`), array methods (`@[categories.length]`), and complex expressions
108
+ - Nested iterations fully pre-rendered with merged state for each iteration context
109
+ - Falls back gracefully: undefined expressions left as `@[...]` for runtime hydration
110
+ - New test: `stamp_array_length` validates `.length` property evaluation
111
+
112
+ ### Changed
113
+
114
+ - **Value stamper rewrite** (`value_stamper.rs`) - Complete overhaul to use QuickJS
115
+ - Replaced JSON path resolution with JavaScript expression evaluation
116
+ - `eval_expression()` handles any valid JavaScript with state in scope
117
+ - `eval_array_path()` evaluates array paths for iteration rendering
118
+ - Iteration rendering creates merged state (parent + item + index) for nested context
119
+ - Removed manual property traversal code - JavaScript engine handles it all
120
+ - **Compiled iteration updates** - Always use compiled path when available (`iterate.js:364`)
121
+ - Previously only used compiled updates for edge cases (empty↔full, large arrays >100)
122
+ - Now uses compiled batch functions for ALL updates when manifest has `compiled.iterations.batchFn`
123
+ - Fixes issue where small array updates (3→4 items) fell through to incompatible runtime path
124
+ - Ensures consistent performance regardless of array size or transition type
125
+ - **State extraction improvements** (`state_extractor.rs`) - Better error handling
126
+ - Silently skips unparseable state objects instead of failing compilation
127
+ - Enables graceful degradation when state contains functions or complex expressions
128
+
129
+ ### Fixed
130
+
131
+ - Compiled iterations not updating when array size changes (e.g., add/remove items)
132
+ - Pre-rendering skipped for JavaScript expressions like `@[categories.length]`
133
+ - Nested iteration values showing as `@[item]` instead of actual data
134
+ - Runtime path attempting to handle compiled iterations incorrectly
135
+
136
+ ### Performance
137
+
138
+ - Pre-rendering adds ~160ms to compilation for 35 files (~435ms total, up from ~310ms)
139
+ - QuickJS evaluation: ~1-5ms per binding
140
+ - Compiled nested iterations: Same performance as shallow iterations (no recursion overhead at runtime)
141
+ - Zero runtime cost for pre-rendered bindings - HTML arrives with values already stamped
142
+
143
+ ---
144
+
145
+ ## [1.4.0] - 2026-02-09
146
+
147
+ ### Added
148
+
149
+ - **Iteration optimization** - Compiler now generates optimized batch functions for `<!-- each -->` loops
150
+ - New `iteration_optimizer.rs` module generates string-based batch render functions
151
+ - Provides 2-3x performance improvement for iteration rendering (15-17ms vs 40ms for 1000 rows)
152
+ - Only applies to shallow iterations (nested iterations still use runtime path)
153
+ - Compiled batch functions are stored in manifest and executed at runtime
154
+ - **Pre-compiled iterations runtime** (`runtime/pre-compiled-iterations.js`)
155
+ - Production implementation of compiled iteration rendering
156
+ - Uses pre-compiled batch functions from manifest generated at build time
157
+ - Based on the prototype in `_vibe-compiled-iteration-batch.js`
158
+ - Automatically falls back to runtime rendering for nested iterations or missing batch functions
159
+ - **Compiler configuration** - New `iterationsAsIs` flag
160
+ - Set to `true` in `vibe-compiler` config to skip iteration optimization
161
+ - Iterations pass through unchanged and are handled entirely by runtime
162
+ - Default: `false` (iterations are optimized)
163
+ - **Hyperspeed benchmark** - New benchmark page for measuring pre-compiled performance
164
+ - Tests iteration optimization with 1000 rows
165
+ - Compares runtime vs compiled iteration rendering
166
+ - Available at `e2e-runtime/hyperspeed-benchmark.html`
167
+ - **Compiler test coverage** for iteration compilation
168
+ - `tests/compiler/iterations/` - Tests iteration optimization is applied
169
+ - `tests/compiler/iterations-as-is/` - Tests `iterationsAsIs` flag skips optimization
170
+ - E2E tests verify compiled iterations render correctly
171
+
172
+ ### Changed
173
+
174
+ - **Renamed `runtime/hyperspeed.js` → `runtime/pre-compiled-manifest.js`**
175
+ - Better naming to reflect that it handles all pre-compiled features, not just "hyperspeed"
176
+ - Updated all imports and references throughout codebase
177
+ - **Enhanced manifest merging** - Compiler manifest now preserves compiled iteration data
178
+ - Iteration nodes retain `compiled.iterations.batchFn` from manifest during runtime merge
179
+ - Prevents compiled data from being discarded when merging with runtime tree
180
+ - **Debug logging improvements**
181
+ - Added manifest filename to debug output ("Loaded index.manifest.js, page is pre-compiled")
182
+ - Shows compiled feature count (e.g., "3 iterations optimized")
183
+ - Better visibility into which optimizations are active
184
+ - **Runtime iteration handling** - Iterations check for compiled batch functions before falling back
185
+ - `canUseCompiled()` determines if iteration can use batch function
186
+ - Falls back to runtime rendering for nested structures or missing compiled data
187
+ - Seamless integration between compiled and runtime paths
188
+
189
+ ### Fixed
190
+
191
+ - Runtime cleanup now properly handles compiled iteration nodes
192
+ - Manifest merge no longer discards compiled data from iteration nodes
193
+ - Debug logging visibility flag now correctly propagates through manifest loading
194
+ - Iteration restoration respects compiled batch functions
195
+
196
+ ---
197
+
3
198
  ## [1.3.2] - 2025-02-06
4
199
 
5
200
  ### Fixed
package/README.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # Vibe
2
2
 
3
- A runtime-first reactive library.
3
+ **Version 1.6.0 (Alpha)** — A runtime-first reactive framework with optional compilation.
4
4
 
5
- No virtual DOM. No build step. Just modern JavaScript.
5
+ No virtual DOM. No build step required. Just modern JavaScript. When you need production optimizations, add the optional Rust-based compiler.
6
6
 
7
7
  ```bash
8
8
  npm install @ape-egg/vibe
9
9
  ```
10
10
 
11
+ **Status:** Functional and ready to use, but expect bugs and breaking changes daily until stable. Use in production at your own risk.
12
+
11
13
  ---
12
14
 
13
15
  ## Vibe Runtime
@@ -124,6 +126,103 @@ Skip reactive processing for an element:
124
126
  <code dehydrate>@[this] displays literally</code>
125
127
  ```
126
128
 
129
+ ### Reserved Words & Gotchas
130
+
131
+ Vibe uses specific patterns and keywords that have special meaning. Avoid using these for other purposes to prevent unexpected behavior:
132
+
133
+ #### Classes & Attributes
134
+
135
+ - **`vibe-fouc`** — Class or attribute for FOUC (Flash of Unstyled Content) prevention. Automatically removed after hydration completes.
136
+ ```html
137
+ <body vibe-fouc> <!-- or class="vibe-fouc" -->
138
+ ```
139
+
140
+ - **`vibe-dehydrate`** — Class or attribute to skip reactive processing. Useful for displaying literal `@[...]` syntax in documentation.
141
+ ```html
142
+ <code vibe-dehydrate>@[variable]</code> <!-- or class="vibe-dehydrate" -->
143
+ ```
144
+
145
+ #### Element Names & Classes
146
+
147
+ - **`<component>`** — Element name for component system. Used with `src` attribute for runtime component loading, or as a wrapper for inlined components.
148
+ ```html
149
+ <component src="/path/to/component.html"></component>
150
+ ```
151
+
152
+ - **`class="component"`** — Alternative syntax for components using standard HTML elements. Useful for HTML validation or accessibility.
153
+ ```html
154
+ <div class="component" src="/path/to/component.html"></div>
155
+ ```
156
+
157
+ - **`<slot>`** — Element name for component content injection. Gets replaced with content passed between component tags.
158
+ ```html
159
+ <!-- In component file -->
160
+ <slot></slot>
161
+
162
+ <!-- Usage -->
163
+ <component src="...">
164
+ <p>This replaces the slot</p>
165
+ </component>
166
+ ```
167
+
168
+ #### Comment Syntax
169
+
170
+ - **`<!-- each -->`** / **`<!-- /each -->`** — Iteration block markers.
171
+ ```html
172
+ <!-- each items as item -->
173
+ <!-- /each -->
174
+ ```
175
+
176
+ - **`<!-- if -->`** / **`<!-- else -->`** / **`<!-- /if -->`** — Conditional block markers.
177
+ ```html
178
+ <!-- if condition -->
179
+ <!-- else -->
180
+ <!-- /if -->
181
+ ```
182
+
183
+ #### Binding Syntax
184
+
185
+ - **`@[...]`** — Reactive binding syntax. Reserved for state references.
186
+ ```html
187
+ <div>@[variable]</div>
188
+ ```
189
+
190
+ #### Global Properties
191
+
192
+ - **`window.$`** — Global reactive state object. All reactive data should be accessed through this.
193
+ ```javascript
194
+ window.$ = state({ count: 0 });
195
+ $.count++; // Triggers reactive updates
196
+ ```
197
+
198
+ - **`window.__vibeManifest`** — Internal manifest data. Used by the compiler for optimization. Don't modify.
199
+
200
+ - **`window.__vibeCompiling`** — Internal flag. Set to `true` when running in compiler context.
201
+
202
+ #### Data Attributes
203
+
204
+ - **`data-vibe-component-id`** — Internal attribute for component scoping. Automatically added to component elements. Don't use manually.
205
+
206
+ #### Event Names
207
+
208
+ - **`vibe:ready`** — Custom event fired when Vibe completes initial hydration.
209
+ ```javascript
210
+ document.addEventListener('vibe:ready', () => {
211
+ console.log('Vibe is ready');
212
+ });
213
+ ```
214
+
215
+ #### Special Attribute Meanings
216
+
217
+ - **`src`** on **`<component>`** or **`<div class="component">`** — Triggers runtime component fetching. Components without `src` are treated as inline wrappers.
218
+ ```html
219
+ <!-- Both work the same way -->
220
+ <component src="/components/card.html"></component>
221
+ <div class="component" src="/components/card.html"></div>
222
+ ```
223
+
224
+ - **`dehydrate`** — Attribute or class name to skip reactive processing (alias for `vibe-dehydrate`).
225
+
127
226
  ### Deep Reactivity
128
227
 
129
228
  Vibe uses recursive proxies to detect changes at any nesting level:
@@ -149,7 +248,7 @@ No need for immutable update patterns or spread operators. Just mutate and Vibe
149
248
 
150
249
  ## Vibe Compiler
151
250
 
152
- Optional build step for production optimization. The compiler processes HTML files, inlines components, and handles assets while preserving directory structure.
251
+ Optional build step for production optimization. The compiler provides component inlining, iteration optimization, watch mode, and hydration manifests while preserving directory structure.
153
252
 
154
253
  ### Installation
155
254
 
@@ -167,18 +266,27 @@ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
167
266
  # Initialize config in package.json
168
267
  bunx vibe compile --init
169
268
 
170
- # Compile
269
+ # Basic compilation
171
270
  bunx vibe compile
271
+ # or shorthand
272
+ bunx vibe c
273
+
274
+ # Watch mode (incremental compilation)
275
+ bunx vibe compile --watch
276
+
277
+ # Production build
278
+ bunx vibe compile --minify --source-maps
172
279
 
173
280
  # With options
174
281
  bunx vibe compile --verbose # Step-by-step logging
175
282
  bunx vibe compile --minify # Minify output
176
- bunx vibe compile --accessibility # Transform custom tags to divs
283
+ bunx vibe compile --elements-as-is # Keep custom elements as-is
177
284
  bunx vibe compile --validate # Validate HTML syntax
178
- bunx vibe compile --create-manifest # Generate hydration manifest
179
285
  bunx vibe compile --source-maps # Generate source maps
180
286
  bunx vibe compile --node-modules-as-is # Copy node_modules as-is
181
- bunx vibe compile --watch # Watch mode (future)
287
+ bunx vibe compile --components-as-is # Skip component inlining
288
+ bunx vibe compile --runtime-as-is # Skip manifest generation
289
+ bunx vibe compile --iterations-as-is # Skip iteration optimization
182
290
  ```
183
291
 
184
292
  Or via npm scripts:
@@ -186,13 +294,14 @@ Or via npm scripts:
186
294
  ```json
187
295
  {
188
296
  "scripts": {
189
- "vibe:compile": "vibe compile",
190
- "vibe:compile:init": "vibe compile --init"
297
+ "compile": "vibe compile",
298
+ "compile:watch": "vibe compile --watch",
299
+ "compile:prod": "vibe compile --minify --source-maps"
191
300
  }
192
301
  }
193
302
  ```
194
303
 
195
- Then run with `bun vibe:compile` or `npm run vibe:compile`.
304
+ Then run with `npm run compile` or `bun compile`.
196
305
 
197
306
  ### Configuration
198
307
 
@@ -207,13 +316,26 @@ Add to your `package.json`:
207
316
  "pages": "pages",
208
317
  "assets": "assets",
209
318
  "minify": false,
210
- "accessibility": false,
211
- "excludeTags": [],
212
- "nodeModulesAsIs": false
319
+ "elementsAsIs": false,
320
+ "reservedElements": [],
321
+ "sourceMaps": false,
322
+ "validate": false,
323
+ "nodeModulesAsIs": false,
324
+ "componentsAsIs": false,
325
+ "runtimeAsIs": false,
326
+ "iterationsAsIs": false
213
327
  }
214
328
  }
215
329
  ```
216
330
 
331
+ **Key Options:**
332
+
333
+ - `elementsAsIs: false` — Transform custom elements to divs (default)
334
+ - `reservedElements: []` — Additional element names to reserve (appends to built-in HTML5 elements + "component")
335
+ - `componentsAsIs: false` — Inline components (default) or keep separate for runtime
336
+ - `iterationsAsIs: false` — Optimize iterations (default) or use runtime rendering
337
+ - `runtimeAsIs: false` — Generate manifest (default) or skip for runtime-only
338
+
217
339
  **Defaults** (when no config):
218
340
 
219
341
  - `source`: `./`
@@ -254,6 +376,66 @@ Auto-detects based on lockfiles: `bun.lockb`, `pnpm-lock.yaml`, `yarn.lock`, `pa
254
376
  **Opt-out:**
255
377
  Set `nodeModulesAsIs: true` in config or use `--node-modules-as-is` flag to copy node_modules as-is.
256
378
 
379
+ ### Watch Mode
380
+
381
+ Watch mode enables incremental compilation with intelligent dependency tracking:
382
+
383
+ ```bash
384
+ bunx vibe compile --watch
385
+ ```
386
+
387
+ Features:
388
+ - **Incremental builds** — Only recompiles changed files (~100ms)
389
+ - **Dependency tracking** — Changes to components trigger recompilation of pages using them
390
+ - **Debounced** — 300ms debounce prevents excessive compilation during rapid changes
391
+ - **Delta output** — First compile shows full output, subsequent compiles show only changes
392
+
393
+ ### Component System
394
+
395
+ Components are automatically inlined during compilation with full support for props and slots:
396
+
397
+ ```html
398
+ <!-- Source: components/card.html -->
399
+ <div class="card">
400
+ <h2>@[title]</h2>
401
+ <p>@[description]</p>
402
+ <slot></slot>
403
+ </div>
404
+
405
+ <!-- Usage in page -->
406
+ <component src="/components/card.html" title="My Card" description="Card description">
407
+ <p>Slot content</p>
408
+ </component>
409
+
410
+ <!-- Compiled output -->
411
+ <component>
412
+ <div class="card">
413
+ <h2>My Card</h2>
414
+ <p>Card description</p>
415
+ <p>Slot content</p>
416
+ </div>
417
+ </component>
418
+ ```
419
+
420
+ **Custom element syntax:** Components can also use custom element syntax (e.g., `<card>` → auto-converts to `<component src="/components/card.html">`).
421
+
422
+ **Opt-out:** Set `componentsAsIs: true` to keep components as separate files for runtime loading.
423
+
424
+ ### Iteration Optimization
425
+
426
+ The compiler generates optimized batch functions for `<!-- each -->` loops, providing 2-3x faster rendering:
427
+
428
+ ```html
429
+ <!-- Source -->
430
+ <!-- each items as item, index -->
431
+ <li>@[index]: @[item]</li>
432
+ <!-- /each -->
433
+
434
+ <!-- Compiled to optimized batch function -->
435
+ ```
436
+
437
+ **Opt-out:** Set `iterationsAsIs: true` to use runtime rendering for all iterations.
438
+
257
439
  ### Output Structure
258
440
 
259
441
  Mirrors source structure:
@@ -271,9 +453,9 @@ src/ compiled/
271
453
  └── vibe/ └── vibe/
272
454
  ```
273
455
 
274
- ### Accessibility Mode
456
+ ### Element Transformation
275
457
 
276
- `--accessibility` transforms custom HTML elements to divs with classes:
458
+ By default (`elementsAsIs: false`), custom HTML elements are transformed to divs with classes for better HTML validity:
277
459
 
278
460
  ```html
279
461
  <!-- input -->
@@ -283,7 +465,23 @@ src/ compiled/
283
465
  <div class="counter-header">Count</div>
284
466
  ```
285
467
 
286
- Exclude specific tags (e.g., web components) via `excludeTags` config.
468
+ Set `elementsAsIs: true` or use `--elements-as-is` flag to keep custom elements unchanged.
469
+
470
+ **Note:** The `<component>` element is a framework element and is never transformed.
471
+
472
+ ### Reserved Element Names
473
+
474
+ The compiler validates component filenames against reserved element names (all HTML5 elements + "component" + your custom list). This prevents confusing bugs where components share names with HTML elements.
475
+
476
+ ```json
477
+ {
478
+ "vibe-compiler": {
479
+ "reservedElements": ["my-custom-element", "another-reserved-name"]
480
+ }
481
+ }
482
+ ```
483
+
484
+ **Case-sensitive validation:** `nav.html` conflicts with `<nav>` and will error, but `Nav.html` is allowed.
287
485
 
288
486
  ### Building Native Binaries
289
487
 
package/boot.js CHANGED
@@ -10,7 +10,6 @@ export const ensureBoot = () => {
10
10
  if (booted || bootQueued) return;
11
11
  bootQueued = true;
12
12
 
13
- // Auto-boot in next microtask if no explicit boot
14
13
  queueMicrotask(() => {
15
14
  if (!booted) {
16
15
  boot();