@three-blocks/devtools 1.0.0-alpha.208.g664cb7c258f9 → 1.0.1-alpha.216.ge2b647f547c7

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,71 +1,88 @@
1
1
  # @three-blocks/devtools
2
2
 
3
- ## 1.0.0-alpha.208.g664cb7c258f9
4
-
5
- - Tools: Baked Motion depth encoding no longer treats an unset quality value as lossless.
6
-
7
- - Tools: Mesh to Splat now installs beside administrator-owned engine caches on Windows.
8
-
9
- - Tools: Mesh to Splat, OAV, and VAV are now installable from the Blender hub.
10
-
11
- - Website: The examples gallery now shows 22 scenes while four examples are being remade.
12
-
13
- - Website: Gaussian Splat Morph now fits comfortably on mobile screens.
14
-
15
- - Website: 3D smoke now responds to touch and starts inside live documentation previews.
16
-
17
- - Website: Examples stay interactive with arrow navigation and source-only controls.
18
-
19
- - Tools: The presentation now plays real examples and leads with free access and lifetime licensing.
20
-
21
- - Tools: The presentation Studio now starts on port 3001.
22
-
23
- - Devtools: Fresh scene receipts now precompile automatically while edited scenes stay live.
24
-
25
- - Website: Baked Motion controls now stay compact on narrow and short screens.
26
-
27
- - Website: Spotlight Type no longer flashes blank while its canvas text initializes.
28
-
29
- - Website: Alpha release badges stay compact and red while development builds use yellow.
30
-
31
- - CLI: Splat-engine downloads now install reliably on Windows and support both Mac architectures.
32
-
33
- - Tools: Private tool releases now deliver the current Blender and CLI bundles.
34
-
35
- - Devtools: Shader traces now measure replay, skip PMREM setup, and support Three.js r186dev.
36
-
37
- - Devtools: Compute shaders now warm asynchronously and ocean shaders hydrate without setup.
38
-
39
- - Starter: The starter now offers only Minimal and the MSDF-powered Website.
40
-
41
- - Starter: Website demos now rebuild with the current Devtools during local development.
42
-
43
- - Tools: Example parity now reuses evidence when captures and execution contracts are unchanged.
44
-
45
- - Tools: Example optimization now retries browser startup and times out stalled parity checks.
46
-
47
- - Website: Mobile navigation now opens from a responsive menu on every page.
48
-
49
- - Website: Ocean water fills mobile screens without camera controls fighting touch.
50
-
51
- - Website: Skinned text now starts quickly from a prebuilt Japanese MSDF atlas.
52
-
53
- - Website: The overview sphere is floor-centered and pushes the pile more strongly.
54
-
55
- - Website: Spotlight Type stays steady while scrolling.
56
-
57
- - Website: Mobile smoke responds forcefully while water fills portrait screens and follows touch.
58
-
59
- - Website: The 3D smoke scene now uses a clean, star-free sky.
60
-
61
- - Website: Liquid Bunny stays clearly lit in portrait views.
62
-
63
- - Website: Baked Motion loading posters now match the live scene size on portrait screens.
64
-
65
- - Website: Release pages show the exact version with a short changelog.
66
-
67
- - Packages: Built from `664cb7c258f9`.
68
-
3
+ ## 1.0.1-alpha.216.ge2b647f547c7
4
+
5
+ - Packages: Three.js 186dev now uses upstream asynchronous compute compilation.
6
+
7
+ - Starter: New projects now use the current runtime without stale shader receipts.
8
+
9
+ - Tools: Mesh to Splat now ignores render-hidden collections when framing captures.
10
+
11
+ - Library: Vertex Animation Video now fails cleanly when numerical tracks cannot be decoded.
12
+
13
+ - Packages: Built from `e2b647f547c7`.
14
+
15
+
16
+ ## 1.0.0
17
+
18
+ ### Minor Changes
19
+
20
+ - 623e341: Measure and report the shader-precompilation win across the runtime overlay, Vite receipts, and CLI. Dev sessions now observe first-load TSL build time without changing the shader-provider closure, while `shaders test` records a warmup-discarded median-of-N A/B with spread and optional hardware-labelled committed evidence.
21
+
22
+ Make shader claims follow runtime truth: unhydrated caches no longer claim skipped work, adopted apps can run `three-blocks status` without scaffold metadata, page-owned stats panels visibly follow their shared controls, and production bundles continue to erase the observer and overlay.
23
+
24
+ ### Patch Changes
25
+
26
+ - 803708b: Devtools: Compute shaders now warm asynchronously and ocean shaders hydrate without setup.
27
+ - 9f20a06: Make Three Blocks devtools a one-line renderer registration across Vite, Next.js, webpack, and bare browser modules. Existing Vite apps now get page ownership and shader inspection from `three-blocks.shaders.json` automatically, the runtime mounts its fallback overlay, and production-aware bundlers select an import-free no-op that preserves both stable devtools exports. The overlay reports real registered shader builds from the renderer hook for page- and worker-owned apps; timing remains attributed to the matching local A/B receipt.
28
+
29
+ When a first shader capture lands, the Vite plugin invalidates transforms that were cached while the manifest glob was empty before reloading the page, so the same running dev session hydrates the new precompiled artifact.
30
+
31
+ Align CLI and Vite shader inspection on one metadata precedence: explicit plugin options, then scaffold-owned `three-blocks.json`, then custom-app `three-blocks.shaders.json`. Projects containing both files therefore report and capture the same authoritative scene matrix.
32
+
33
+ Unify public commands under `npx three-blocks`, remove the legacy capture endpoint and `precompile.config.mjs` reader, and keep built-in text fonts checksum-pinned without shipping their binary payload in the devtools package archive. Custom worker shells can now reuse the `three-blocks/app` stats controllers and structural smoke bridge instead of maintaining parallel page/worker implementations.
34
+
35
+ - 3693904: Move stats panels into the dev overlay, add page-owned renderer adoption through `three-blocks/devtools`, and remove scaffold-owned stats code. Page-owned Vite setups are inferred automatically when scaffold metadata is absent; worker texture previews also keep working when `WebGPURenderer` uses its WebGL fallback backend.
36
+
37
+ The browser verifier now activates stats through the public smoke controls, proves texture transfer stops after disable, classifies recovered text-fallback errors across both browser channels, and preloads its synthetic probe dependencies to avoid Vite optimizer reload races.
38
+
39
+ `stats: true` now enables stats only for the development server. Production stats require the explicit object form: `stats: { production: true }`.
40
+
41
+ - 35c7bd9: Website: Release pages show the exact version with a short changelog.
42
+ - acb4ece: Align package and generated-project notices with the lifetime per-Project commercial license, identify the legal licensor, and ship complete third-party attributions with the core package.
43
+ - 9f20a06: Precompiled shader capture now preserves distinct storage access views that share one underlying buffer, so a read-only WGSL binding hydrates as read-only instead of collapsing onto its read-write owner. Hydration also verifies storage-buffer and storage-texture access modes against the captured WGSL before a pipeline is created. WebGPU validates the shader/layout pairing asynchronously, so an access drift between capture and replay used to escape the non-strict live fallback and re-submit an invalid pipeline every frame (observed as `GPUValidationError: The buffer type in the shader (ReadOnlyStorage) is not compatible with the type in the layout (Storage)` spam on `compute_csr_raster`). The provider now replicates three r185's `WebGPUBindingUtils` layout rules per binding slot and turns any remaining mismatch into a synchronous hydration failure, which falls back to live TSL compilation for that key exactly as the fail-soft contract promises.
44
+ - 803708b: Devtools: Shader traces now measure replay, skip PMREM setup, and support Three.js r186dev.
45
+ - 4c4eab8: Tools: Example optimization now retries browser startup and times out stalled parity checks.
46
+ - ece8639: Define devtools as a WebGPU-only shader precompilation workflow. Runtime registration now rejects `WebGLRenderer`, the docs lead with stable shader registration, capture, manifest injection, and parity verification, and shader capture uses the consuming project's Vite runtime for Vite 8 compatibility.
47
+ - Updated dependencies [72bbb71]
48
+ - Updated dependencies [803708b]
49
+ - Updated dependencies [dc934a2]
50
+ - Updated dependencies [e67d56b]
51
+ - Updated dependencies [acb4ece]
52
+ - Updated dependencies [3693904]
53
+ - Updated dependencies [e67d56b]
54
+ - Updated dependencies [e67d56b]
55
+ - Updated dependencies [e67d56b]
56
+ - Updated dependencies [72bbb71]
57
+ - Updated dependencies [623e341]
58
+ - Updated dependencies [9f20a06]
59
+ - Updated dependencies [3693904]
60
+ - Updated dependencies [e67d56b]
61
+ - Updated dependencies [acb4ece]
62
+ - Updated dependencies [35c7bd9]
63
+ - Updated dependencies [72bbb71]
64
+ - Updated dependencies [acb4ece]
65
+ - Updated dependencies [e8b569c]
66
+ - Updated dependencies [e67d56b]
67
+ - Updated dependencies [e67d56b]
68
+ - Updated dependencies [623e341]
69
+ - Updated dependencies [72bbb71]
70
+ - Updated dependencies [72bbb71]
71
+ - Updated dependencies [e8b569c]
72
+ - Updated dependencies [9f20a06]
73
+ - Updated dependencies [623e341]
74
+ - Updated dependencies [4eb273d]
75
+ - Updated dependencies [623e341]
76
+ - Updated dependencies [37e7f64]
77
+ - Updated dependencies [803708b]
78
+ - Updated dependencies [623e341]
79
+ - Updated dependencies [72bbb71]
80
+ - Updated dependencies [9811acd]
81
+ - Updated dependencies [5feae2c]
82
+ - Updated dependencies [ece8639]
83
+ - Updated dependencies [5e3cc44]
84
+ - Updated dependencies [803708b]
85
+ - three-blocks@0.2.0
69
86
 
70
87
  This changelog is generated from Changesets.
71
88
 
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## Add Devtools to a Vite app
6
6
 
7
- The Three Blocks starter already installs and configures this package. Pin the command engine in an adopted project when you need offline, version-locked commands:
7
+ The Three Blocks starter already installs and configures this package. An adopted project installs it once; every `npx three-blocks` command in this document runs the project's own copy:
8
8
 
9
9
  ```bash
10
10
  npm install --save-dev @three-blocks/devtools
@@ -47,9 +47,9 @@ The overlay changes from **Live** to **Precompiled** after a fresh capture loads
47
47
 
48
48
  ### Three.js r185 compatibility patch
49
49
 
50
- Shader precompilation supports Three.js `>=0.185.0 <0.186.0`. Every adapter applies the same version-gated transform to `three/build/three.webgpu.js` in memory and never writes `node_modules`. Exact source anchors fail closed on unknown or partially patched builds. Current captures require precompiled manifest version `3` and shader receipt transform version `51`; recapture older artifacts instead of editing them.
50
+ Shader precompilation supports Three.js `>=0.185.0 <0.186.0`. Every adapter applies the same version-gated transform to `three/build/three.webgpu.js` in memory and never writes `node_modules`. Exact source anchors fail closed on unknown or partially patched builds. Current captures require precompiled manifest version `3` and shader receipt transform version `53`; recapture older artifacts instead of editing them.
51
51
 
52
- The [Three.js WebGPU compatibility reference](../../docs/maintenance/three-webgpu-release-compatibility.md) defines the released r185 patches, source markers, removal conditions, and verification gates.
52
+ The [Devtools guide](https://threejs-blocks.com/docs/tools/devtools) lists the released r185 patches behind that transform.
53
53
 
54
54
  ### Manual bundler adapters
55
55
 
@@ -150,7 +150,7 @@ Artifact writes are transactional. `meta.json` records runtime, tool, schema, so
150
150
 
151
151
  `shaders test` first repeats the GPU-free matrix inspection. Its browser gate proves that the live baseline builds every registered render pipeline and compute kernel. The fresh path must perform zero registered builds, report no misses, reach first-frame readiness, render non-black output, and match deterministic pixels.
152
152
 
153
- Successful scenes are checkpointed against their scene receipt and the shared runtime and tool contract. A later run can resume at the missing scene. `--parity-only` runs one live and precompiled pair without timing warmups, repeats, or the published-page soak. The default mode retains those measurements and production-page checks. A parity observation is capped at 10 seconds. Failures write live, precompiled, and diff PNGs under `.three-blocks/shaders/parity/`.
153
+ Successful scenes are checkpointed against their scene receipt and the shared runtime and tool contract. A later run can resume at the missing scene. `--parity-only` runs one live and precompiled pair without timing warmups, repeats, or the published-page soak. The default mode retains those measurements and production-page checks. A parity observation is bounded by the per-scene `timeoutMs`, 240 seconds by default. Failures write live, precompiled, and diff PNGs under `.three-blocks/shaders/parity/`.
154
154
 
155
155
  ### Verify a browser integration
156
156
 
@@ -162,7 +162,7 @@ npx three-blocks browser preview --route /
162
162
 
163
163
  The smoke gate loads the project's Vite config on an ephemeral loopback port. It requires the visible OffscreenCanvas worker plus `workerReady`, `assetsReady`, and `compileEnd`. It also requires `textReady` when the Vite text configuration is enabled. Every configured Draco and KTX2 route is fetched, the lazy Meshopt decoder is initialized, and page or console errors fail the run. The gate checks the WebGPU screenshot and readable 2D panels for an all-black frame.
164
164
 
165
- The command reads the starter's built-in readiness check. Application tutorials describe the visible **Starting**, **Ready**, **Precompiled**, and **Live** states instead of this maintainer contract. Contributors can inspect the exact protocol in the [maintainer browser-verification reference](../../docs/maintenance/browser-verification.md).
165
+ The command reads the starter's built-in readiness check. Application tutorials describe the visible **Starting**, **Ready**, **Precompiled**, and **Live** states instead of this maintainer contract.
166
166
 
167
167
  `--hmr project_relative_module` emits a synthetic watcher change through Vite for an already loaded scene module. It runs the HMR graph without changing source and verifies that the browser acknowledges the update while lifecycle readiness remains stable.
168
168
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {b,a as a$3}from'./chunk-KLGY4Q2M.js';import'./chunk-76WRV5MZ.js';import'./chunk-JMS5NTP7.js';import'./chunk-5RSAQ74G.js';import'./chunk-HLYATKSG.js';import {a as a$2,b as b$1,c as c$1}from'./chunk-NE7SC2BX.js';import'./chunk-ZT6T2W4B.js';import'./chunk-NEWSG5RX.js';import {a as a$1}from'./chunk-ZDNZCQUQ.js';import {j,a as a$4,c}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {randomUUID}from'crypto';import {mkdir,realpath,writeFile,rename,rm}from'fs/promises';import F from'path';import {PNG}from'pngjs';var ye="virtual:three-blocks-devtools/browser-smoke",ve=`\0${ye}`,Ke=`/@id/__x00__${ye}`,Be=9e4;async function Ee(){try{let[e,r]=await Promise.all([import('playwright'),import('vite')]);return {chromium:e.chromium,vite:r}}catch(e){throw new Error('Browser smoke and preview require the optional "playwright" and "vite" packages. Install both in the project and run `npx playwright install chromium`.',{cause:e})}}a(Ee,"loadBrowserSmokeTools");function V(e,r,o,t,n){let a=e??n;if(!Number.isSafeInteger(a)||a<o||a>t)throw new Error(`${r} must be an integer in ${o}...${t}.`);return a}a(V,"boundedInteger");function _e(e,r,o,t,n){let a=e??n;if(!Number.isFinite(a)||a<o||a>t)throw new Error(`${r} must be a finite number in ${o}...${t}.`);return a}a(_e,"boundedRatio");function Pe(e){let r=e??"/";if(r.length===0||r.length>2048||/[\u0000-\u001f\u007f]/u.test(r))throw new Error("Browser smoke route must be a bounded project URL.");let o=new URL(r,"http://three-blocks.invalid/");if(o.origin!=="http://three-blocks.invalid"||o.hash.length>0)throw new Error("Browser smoke route must stay within the project and have no fragment.");return `${o.pathname}${o.search}`}a(Pe,"safeRoute");function N(e,r){return e[r]===true}a(N,"booleanField");function $(e,r){if(!a$1(e)||!a$1(e.value))return {source:"missing",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:r,textReady:!r,firstFrame:false};let o=e.value,t=e.source==="public";if(t&&o.protocolVersion!==1)return {source:"public",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:r,textReady:!r,firstFrame:false};let n=a$1(o.readiness)?o.readiness:o,a=o.worker,d=t&&a$1(a)?a.offscreenCanvas===true&&a.visible===true:a===true;return {source:t?"public":"legacy",backend:t&&a$1(a)?a.offscreenCanvas===true?"OffscreenCanvas":"MainThread":a===true?"OffscreenCanvas":"unknown",worker:d,workerReady:N(n,"workerReady"),assetsReady:N(n,"assetsReady")||N(n,"loadEnd"),compileEnd:N(n,"compileEnd"),textEnabled:r,textReady:!r||N(n,"textReady"),firstFrame:N(n,"firstFrame")}}a($,"parseBrowserSmokeLifecycle");function ie(e){let r=PNG.sync.read(e),o=Math.floor(r.width*.25),t=Math.floor(r.width*.75),n=Math.floor(r.height*.25),a=Math.floor(r.height*.75),d=0,c=0;for(let f=n;f<a;f+=2)for(let p=o;p<t;p+=2){let h=(f*r.width+p)*4,l=r.data[h],i=r.data[h+1],s=r.data[h+2];l===void 0||i===void 0||s===void 0||(d+=Math.max(l,i,s),c+=1);}return c===0?0:d/c}a(ie,"screenshotLuminance");function Je(){return `
2
+ import {b,a as a$3}from'./chunk-D6DGT5CE.js';import'./chunk-76WRV5MZ.js';import'./chunk-JMS5NTP7.js';import'./chunk-LVY4EXVQ.js';import'./chunk-TGOUAHMD.js';import {a as a$2,b as b$1,c as c$1}from'./chunk-NE7SC2BX.js';import'./chunk-ZT6T2W4B.js';import'./chunk-NEWSG5RX.js';import {a as a$1}from'./chunk-ZDNZCQUQ.js';import {j,a as a$4,c}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {randomUUID}from'crypto';import {mkdir,realpath,writeFile,rename,rm}from'fs/promises';import F from'path';import {PNG}from'pngjs';var ye="virtual:three-blocks-devtools/browser-smoke",ve=`\0${ye}`,Ke=`/@id/__x00__${ye}`,Be=9e4;async function Ee(){try{let[e,r]=await Promise.all([import('playwright'),import('vite')]);return {chromium:e.chromium,vite:r}}catch(e){throw new Error('Browser smoke and preview require the optional "playwright" and "vite" packages. Install both in the project and run `npx playwright install chromium`.',{cause:e})}}a(Ee,"loadBrowserSmokeTools");function V(e,r,o,t,n){let a=e??n;if(!Number.isSafeInteger(a)||a<o||a>t)throw new Error(`${r} must be an integer in ${o}...${t}.`);return a}a(V,"boundedInteger");function _e(e,r,o,t,n){let a=e??n;if(!Number.isFinite(a)||a<o||a>t)throw new Error(`${r} must be a finite number in ${o}...${t}.`);return a}a(_e,"boundedRatio");function Pe(e){let r=e??"/";if(r.length===0||r.length>2048||/[\u0000-\u001f\u007f]/u.test(r))throw new Error("Browser smoke route must be a bounded project URL.");let o=new URL(r,"http://three-blocks.invalid/");if(o.origin!=="http://three-blocks.invalid"||o.hash.length>0)throw new Error("Browser smoke route must stay within the project and have no fragment.");return `${o.pathname}${o.search}`}a(Pe,"safeRoute");function N(e,r){return e[r]===true}a(N,"booleanField");function $(e,r){if(!a$1(e)||!a$1(e.value))return {source:"missing",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:r,textReady:!r,firstFrame:false};let o=e.value,t=e.source==="public";if(t&&o.protocolVersion!==1)return {source:"public",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:r,textReady:!r,firstFrame:false};let n=a$1(o.readiness)?o.readiness:o,a=o.worker,d=t&&a$1(a)?a.offscreenCanvas===true&&a.visible===true:a===true;return {source:t?"public":"legacy",backend:t&&a$1(a)?a.offscreenCanvas===true?"OffscreenCanvas":"MainThread":a===true?"OffscreenCanvas":"unknown",worker:d,workerReady:N(n,"workerReady"),assetsReady:N(n,"assetsReady")||N(n,"loadEnd"),compileEnd:N(n,"compileEnd"),textEnabled:r,textReady:!r||N(n,"textReady"),firstFrame:N(n,"firstFrame")}}a($,"parseBrowserSmokeLifecycle");function ie(e){let r=PNG.sync.read(e),o=Math.floor(r.width*.25),t=Math.floor(r.width*.75),n=Math.floor(r.height*.25),a=Math.floor(r.height*.75),d=0,c=0;for(let f=n;f<a;f+=2)for(let p=o;p<t;p+=2){let h=(f*r.width+p)*4,l=r.data[h],i=r.data[h+1],s=r.data[h+2];l===void 0||i===void 0||s===void 0||(d+=Math.max(l,i,s),c+=1);}return c===0?0:d/c}a(ie,"screenshotLuminance");function Je(){return `
3
3
  import * as THREE from 'three/webgpu';
4
4
  import { createAssetLoaderRegistry, createAssetManager, createThreeAssetAdapters, defineAssets } from 'three-blocks/assets';
5
5
  import { SceneHotReloader } from 'three-blocks/hmr';
@@ -1,5 +1,5 @@
1
1
  import {a}from'./chunk-EI7MMDWY.js';import {createHash,randomUUID}from'crypto';import {lstat,open,realpath,mkdir,rename,rm,link,readdir,readFile,unlink}from'fs/promises';import p from'path';import {THREE_WEBGPU_R185_COMPATIBILITY,THREE_R186DEV_VERSION,THREE_WEBGPU_R186DEV_COMPATIBILITY,parsePrecompiledManifest,SHADER_HYDRATION_SCHEMA_VERSION,SHADER_RECIPE_SCHEMA_VERSION,SHADER_ADDRESS_SCHEMA_VERSION,PRECOMPILED_MANIFEST_VERSION}from'three-blocks/shaders';import {createRequire}from'module';import {transformThreeWebgpuProviderHooks,transformThreeWebgpuCaptureInstrumentation}from'three-blocks/vite';var D=/^[a-f0-9]{64}$/,Ye=/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,127}$/,be=/^[a-z0-9][a-z0-9_-]{0,63}$/,we=/^[0-9A-Za-z][0-9A-Za-z._/-]{0,127}$/;function c(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}a(c,"isRecord");function P(e){return typeof e=="string"&&Ye.test(e)}a(P,"isSafeVersion");function Q(e){if(e.length===0||e.length>512||e.includes("\\")||/[\u0000-\u001f\u007f]/.test(e))return false;let r=e.split("/");return !e.startsWith("/")&&r.every(t=>t.length>0&&t!=="."&&t!=="..")}a(Q,"isSafeRelativePath");function Ee(e){if(!c(e)||e.schemaVersion!==2)throw new Error("three-blocks.json must use schemaVersion 2.");if(typeof e.template!="string"||!be.test(e.template))throw new Error("three-blocks.json has an invalid default shader scene key.");if(!Array.isArray(e.layers)||!e.layers.every(r=>typeof r=="string"&&we.test(r))||new Set(e.layers).size!==e.layers.length)throw new Error("three-blocks.json has invalid layers.");if(e.generator!==void 0&&(!c(e.generator)||typeof e.generator.name!="string"||!we.test(e.generator.name)||!P(e.generator.version)))throw new Error("three-blocks.json has invalid generator metadata.");if(!c(e.runtime)||!P(e.runtime.three)||!P(e.runtime.threeBlocks))throw new Error("three-blocks.json has invalid runtime versions.");if(!c(e.features)||typeof e.features.text!="boolean")throw new Error("three-blocks.json has invalid feature metadata.");if(!c(e.protocol)||e.protocol.resultFile!==1)throw new Error("three-blocks.json has an unsupported protocol schema.");if(e.artifacts!==void 0){if(!c(e.artifacts)||typeof e.artifacts.shaders!="string"||!["fresh","pending"].includes(e.artifacts.shaders)||typeof e.artifacts.text!="string"||!["fresh","pending","not-applicable"].includes(e.artifacts.text))throw new Error("three-blocks.json has invalid artifact metadata.");if(e.features.text?e.artifacts.text==="not-applicable":e.artifacts.text!=="not-applicable")throw new Error("three-blocks.json text artifact state does not match the text capability.")}return {schemaVersion:2,template:e.template,layers:e.layers,...e.generator===void 0?{}:{generator:{name:e.generator.name,version:e.generator.version}},runtime:{three:e.runtime.three,threeBlocks:e.runtime.threeBlocks},features:{text:e.features.text},...e.artifacts===void 0?{}:{artifacts:{shaders:e.artifacts.shaders,text:e.artifacts.text}},protocol:{resultFile:1}}}a(Ee,"parseProjectMetadata");function Xe(e){if(!c(e))throw new Error("Shader coverage is missing.");for(let r of ["render","vertex","fragment","compute"])if(typeof e[r]!="number"||!Number.isSafeInteger(e[r])||e[r]<0)throw new Error(`Shader coverage.${r} must be a non-negative integer.`);return e}a(Xe,"parseCoverage");function Ze(e,r){if(!c(e))throw new Error(`Shader receipt inputs for "${r}" are invalid.`);let t=Object.entries(e);if(t.length===0||t.length>4096)throw new Error(`Shader receipt inputs for "${r}" must contain between 1 and 4096 files.`);for(let[n,i]of t)if(!Q(n)||typeof i!="string"||!D.test(i))throw new Error(`Shader receipt input for "${r}" is invalid.`)}a(Ze,"parseInputs");function F(e){if(!c(e)||e.schemaVersion!==2||!c(e.runtime)||!P(e.runtime.three)||!P(e.runtime.threeBlocks)||typeof e.runtime.threeBlocksShaderClosure!="string"||!D.test(e.runtime.threeBlocksShaderClosure)||!c(e.scenes))throw new Error("Shader meta.json does not match receipt schema 2.");if(e.runtime.capture!==void 0&&(!c(e.runtime.capture)||typeof e.runtime.capture.userAgent!="string"||e.runtime.capture.userAgent.length>1024||typeof e.runtime.capture.adapter!="string"||e.runtime.capture.adapter.length>1024||!Array.isArray(e.runtime.capture.features)||e.runtime.capture.features.length>256||!e.runtime.capture.features.every(t=>typeof t=="string"&&t.length>0&&t.length<=128)))throw new Error("Shader meta.json has invalid browser capture provenance.");let r=Object.entries(e.scenes);if(r.length===0)throw new Error("Shader meta.json contains no scenes.");for(let[t,n]of r){if(!be.test(t)||!c(n)||typeof n.artifact!="string"||!Q(n.artifact)||!n.artifact.endsWith(".webgpu.ts")||typeof n.artifactHash!="string"||!D.test(n.artifactHash))throw new Error(`Shader receipt for "${t}" is invalid.`);if(n.asset===void 0!=(n.assetHash===void 0)||n.asset!==void 0&&(typeof n.asset!="string"||!Q(n.asset)||!n.asset.endsWith(".json")||typeof n.assetHash!="string"||!D.test(n.assetHash)))throw new Error(`Shader static asset receipt for "${t}" is invalid.`);if(Ze(n.inputs,t),Xe(n.coverage),n.bytes!==void 0&&(!Number.isSafeInteger(n.bytes)||Number(n.bytes)<0))throw new Error(`Shader receipt byte count for "${t}" is invalid.`);if(n.skipped!==void 0&&(!c(n.skipped)||!Number.isSafeInteger(n.skipped.render)||Number(n.skipped.render)<0||!Number.isSafeInteger(n.skipped.compute)||Number(n.skipped.compute)<0))throw new Error(`Shader receipt skipped-build counts for "${t}" are invalid.`)}if(e.tool!==void 0&&(!c(e.tool)||e.tool.name!=="@three-blocks/devtools"||!P(e.tool.version)||typeof e.tool.compatibility!="string"||!Number.isSafeInteger(e.tool.transform)||!Number.isSafeInteger(e.tool.address)||!Number.isSafeInteger(e.tool.recipe)||!Number.isSafeInteger(e.tool.hydration)))throw new Error("Shader meta.json has invalid tool compatibility metadata.");return e}a(F,"parseShaderReceipt");var _=Object.freeze({metadata:1024*1024,receipt:2*1024*1024,manifest:32*1024*1024,semanticInput:8*1024*1024,semanticTotal:64*1024*1024,metrics:8*1024*1024,texture:128*1024*1024,packageJson:1024*1024});function re(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"?e.code:void 0}a(re,"errorCode");function R(e){return createHash("sha256").update(e).digest("hex")}a(R,"sha256");async function b(e){try{return await lstat(e),!0}catch(r){if(re(r)==="ENOENT")return false;throw r}}a(b,"pathExists");function M(e,r){let t=p.relative(e,r);return t===""||!p.isAbsolute(t)&&t!==".."&&!t.startsWith(`..${p.sep}`)}a(M,"isWithin");function C(e){return JSON.stringify(e)}a(C,"displayPath");async function Ae(e,r,t){let n=await open(e,"r");try{let[i,o,s]=await Promise.all([lstat(e),n.stat(),realpath(e)]);if(i.isSymbolicLink())throw new Error(`${t} must not be a symbolic link: ${C(e)}.`);if(!o.isFile())throw new Error(`${t} must be a regular file: ${C(e)}.`);if(o.size>r)throw new Error(`${t} exceeds the ${r}-byte inspection limit: ${C(e)}.`);let d=await n.readFile();if(d.byteLength>r)throw new Error(`${t} grew beyond the ${r}-byte inspection limit while being read.`);return {path:s,data:d}}finally{await n.close();}}a(Ae,"readBoundedRegularFile");async function x(e,r){let t=p.dirname(e);await mkdir(t,{recursive:true});try{if((await lstat(e)).isSymbolicLink())throw new Error(`Atomic write target must not be a symbolic link: ${C(e)}.`)}catch(o){if(re(o)!=="ENOENT")throw o}let n=p.join(t,`.${p.basename(e)}.${process.pid}.${randomUUID()}.tmp`),i;try{i=await open(n,"wx",384),await i.writeFile(r),await i.sync(),await i.close(),i=void 0,await rename(n,e);}finally{await i?.close().catch(()=>{}),await rm(n,{force:true});}}a(x,"writeAtomicRegularFile");async function xe(e,r){let t=p.dirname(e);await mkdir(t,{recursive:true});let n=p.join(t,`.${p.basename(e)}.${process.pid}.${randomUUID()}.tmp`),i;try{i=await open(n,"wx",384),await i.writeFile(r),await i.sync(),await i.close(),i=void 0;try{return await link(n,e),!0}catch(o){if(re(o)==="EEXIST")return !1;throw o}}finally{await i?.close().catch(()=>{}),await rm(n,{force:true});}}a(xe,"writeNewRegularFile");async function _r(e,r,t){return Ae(e,r,t)}a(_r,"readExternalRegularFile");async function V(e,r,t){let n=p.resolve(e),i=p.resolve(r);if(!M(n,i))throw new Error(`${t} escapes its allowed directory.`);let o=await lstat(i);if(o.isSymbolicLink())throw new Error(`${t} must not be a symbolic link.`);if(!o.isDirectory())throw new Error(`${t} must be a directory.`);let[s,d]=await Promise.all([realpath(n),realpath(i)]);if(!M(s,d))throw new Error(`${t} resolves outside its allowed directory.`);return d}a(V,"canonicalDirectoryWithin");async function $(e,r,t,n){let i=p.resolve(e),o=p.resolve(r);if(!M(i,o)||i===o)throw new Error(`${n} escapes its allowed directory.`);let s=await Ae(o,t,n),d=await realpath(i);if(!M(d,s.path)||d===s.path)throw new Error(`${n} resolves outside its allowed directory.`);return s}a($,"readRegularFileWithin");async function $r(e,r,t,n=8192){let o=[await V(e,r,"Inspected directory")],s=[],d=0;for(;o.length>0;){let l=o.shift();if(l===void 0)break;let g=(await readdir(l,{withFileTypes:true})).sort((f,y)=>f.name.localeCompare(y.name));for(let f of g){if(d+=1,d>n)throw new Error(`Inspected directory exceeds the ${n}-entry limit.`);let y=p.join(l,f.name);if(f.isSymbolicLink())throw new Error(`Inspected directory contains a symbolic link: ${C(p.relative(e,y))}.`);if(f.isDirectory()){o.push(await V(e,y,"Nested inspected directory"));continue}if(f.isFile()&&t(f.name))s.push(y);else if(t(f.name))throw new Error(`Semantic input is not a regular file: ${C(y)}.`)}}return s.sort()}a($r,"listRegularFilesRecursively");var ne="three-blocks.shaders.json",Lr=".three-blocks/shaders",Vr=".three-blocks/shaders/parity",ir=/^[a-z0-9][a-z0-9_-]{0,63}$/u,or=/^[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/u,je=64,Pe=64,Ce={schemaVersion:1,scenes:[{key:"default",url:"/"}]};function Me(e,r,t){if(e===void 0)return t;if(typeof e!="string"||e.length===0||e.length>512||p.isAbsolute(e)||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${r} must be a bounded project-relative directory.`);let n=p.posix.normalize(e.replaceAll("\\","/")).replace(/\/+$/u,"");if(n==="."||n===".."||n.startsWith("../"))throw new Error(`${r} must stay inside the project.`);return n}a(Me,"safeProjectDirectory");function sr(e,r){let t=Me(e,r,"");if(typeof e!="string"||e.endsWith("/"))throw new Error(`${r} must be a project-relative file.`);return t}a(sr,"safeProjectFile");function A(e,r,t,n,i){if(e===void 0)return i;if(!Number.isSafeInteger(e)||Number(e)<t||Number(e)>n)throw new Error(`${r} must be an integer in ${t}...${n}.`);return Number(e)}a(A,"boundedInteger");function _e(e,r,t){if(e===void 0)return t;if(typeof e!="number"||!Number.isFinite(e)||e<0||e>1)throw new Error(`${r} must be a finite ratio in 0...1.`);return e}a(_e,"finiteRatio");function $e(e,r){if(typeof e!="string"||e.length===0||e.length>2048||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${r} must be a bounded project-relative URL.`);let t;try{t=new URL(e,"http://three-blocks.invalid/");}catch{throw new Error(`${r} is not a valid URL.`)}if(t.origin!=="http://three-blocks.invalid"||t.hash.length>0)throw new Error(`${r} must stay within the project and must not contain a fragment.`);return `${t.pathname}${t.search}`}a($e,"safeBrowserUrl");function ar(e){if(!Array.isArray(e)||e.length===0||e.length>je)throw new Error(`Shader config scenes must contain 1...${je} entries.`);let r=new Set;return e.map((t,n)=>{if(!c(t)||typeof t.key!="string"||!ir.test(t.key))throw new Error(`Shader config scene ${n} has an invalid key.`);if(r.has(t.key))throw new Error(`Shader config scene key "${t.key}" is duplicated.`);r.add(t.key);let i=t.parityFrames,o=t.maxDiffRatio;if(t.inputs!==void 0&&(!Array.isArray(t.inputs)||t.inputs.length===0||t.inputs.length>Pe))throw new Error(`Shader config scene "${t.key}" inputs must contain 1...${Pe} files.`);let s=t.inputs===void 0?void 0:t.inputs.map((d,l)=>sr(d,`Shader config scene "${t.key}" input ${l}`));if(s!==void 0&&new Set(s).size!==s.length)throw new Error(`Shader config scene "${t.key}" inputs must be unique.`);if(t.runtimeMotion!==void 0&&typeof t.runtimeMotion!="boolean")throw new Error(`Shader config scene "${t.key}" runtimeMotion must be a boolean.`);return {key:t.key,url:$e(t.url,`Shader config scene "${t.key}" URL`),requiresText:t.requiresText===true,...s===void 0?{}:{inputs:s},...i===void 0?{}:{parityFrames:A(i,`Shader config scene "${t.key}" parityFrames`,0,1e4,0)},...o===void 0?{}:{maxDiffRatio:_e(o,`Shader config scene "${t.key}" maxDiffRatio`,.01)},...t.runtimeMotion===true?{runtimeMotion:true}:{}}})}a(ar,"parseScenes");function v(e){if(!c(e)||e.schemaVersion!==void 0&&e.schemaVersion!==1)throw new Error("Shader config must use schemaVersion 1.");let r=e.viewport;if(r!==void 0&&!c(r))throw new Error("Shader config viewport must be an object.");let t=e.parity;if(t!==void 0&&!c(t))throw new Error("Shader config parity must be an object.");let n=e.bridge;if(n!==void 0&&!c(n))throw new Error("Shader config bridge must be an object.");let i=c(n)?n.deterministicModule:void 0;i!==void 0&&$e(i,"Shader deterministic module");let o=e.readiness;if(o!==void 0&&!c(o))throw new Error("Shader config readiness must be an object.");let s=c(o)?o.selector:void 0;if(s!==void 0&&(typeof s!="string"||s.length===0||s.length>512||/[\u0000-\u001f\u007f]/u.test(s)))throw new Error("Shader readiness selector must be a bounded, non-empty CSS selector.");let d=c(o)?o.global:void 0;if(d!==void 0&&(typeof d!="string"||!or.test(d)))throw new Error("Shader readiness global must be a dot-separated JavaScript property path.");return {schemaVersion:1,scenes:ar(e.scenes),settleFrames:A(e.settleFrames,"Shader settleFrames",0,1e4,60),settleTimeoutMs:A(e.settleTimeoutMs,"Shader settleTimeoutMs",1e3,15*6e4,3e4),browserRelaunchScenes:A(e.browserRelaunchScenes,"Shader browserRelaunchScenes",1,64,8),timeoutMs:A(e.timeoutMs,"Shader timeoutMs",1e3,15*6e4,24e4),viewport:{width:A(c(r)?r.width:void 0,"Shader viewport width",64,8192,1024),height:A(c(r)?r.height:void 0,"Shader viewport height",64,8192,640)},parity:{frames:A(c(t)?t.frames:void 0,"Shader parity frames",0,1e4,90),channelTolerance:A(c(t)?t.channelTolerance:void 0,"Shader parity channelTolerance",0,255,8),maxDiffRatio:_e(c(t)?t.maxDiffRatio:void 0,"Shader parity maxDiffRatio",.01)},bridge:{legacyLab:c(n)&&n.legacyLab===true,...typeof i=="string"?{deterministicModule:i}:{}},readiness:{...typeof s=="string"?{selector:s}:{},...typeof d=="string"?{global:d}:{}},publicDir:Me(e.publicDir,"Shader publicDir","public"),allowLiveBuilds:e.allowLiveBuilds!==false}}a(v,"parseShaderToolConfig");async function Hr(e=process.cwd()){let r=p.resolve(e);for(;;){if(await b(p.join(r,ne))||await b(p.join(r,"three-blocks.json")))return realpath(r);let t=p.join(r,"package.json");if(await b(t)){let i=await $(r,t,_.packageJson,"Project package.json"),o;try{o=JSON.parse(i.data.toString("utf8"));}catch{throw new Error(`Project package.json is not valid JSON: ${t}.`)}if(c(o)&&[o.dependencies,o.devDependencies,o.peerDependencies,o.optionalDependencies].filter(c).some(l=>typeof l.three=="string"||typeof l["three-blocks"]=="string"||typeof l["@three-blocks/devtools"]=="string"))return realpath(r)}let n=p.dirname(r);if(n===r)throw new Error(`No Three Blocks shader project found from ${JSON.stringify(p.resolve(e))}; add Three.js to package.json or pass --root.`);r=n;}}a(Hr,"findShaderProjectRoot");async function te(e){let r=await realpath(e),t=p.join(r,ne);if(await b(t)){let i=await $(r,t,_.metadata,"Shader configuration");return v(JSON.parse(i.data.toString("utf8")))}let n=p.join(r,"three-blocks.json");if(await b(n)){let i=Ee(JSON.parse(await readFile(n,"utf8")));return v({schemaVersion:1,scenes:[{key:i.template,url:"/",requiresText:i.features.text}]})}return v(Ce)}a(te,"loadShaderToolConfig");async function vr(e){let r=await realpath(e);for(let o of ["vite.config.ts","vite.config.mts","vite.config.js","vite.config.mjs","vite.config.cts","vite.config.cjs"])if(await b(p.join(r,o)))return {driverKind:"vite",reason:`Detected ${o}.`};let t,n=p.join(r,"package.json");if(await b(n)){let o=await $(r,n,_.packageJson,"Project package.json"),s=JSON.parse(o.data.toString("utf8"));c(s)&&(t=s);}let i=a(o=>[t?.dependencies,t?.devDependencies,t?.peerDependencies,t?.optionalDependencies].some(s=>c(s)&&typeof s[o]=="string"),"hasDependency");if(i("vite"))return {driverKind:"vite",reason:"Detected the Vite dependency."};for(let o of ["dist","build","out"])if(await b(p.join(r,o,"index.html")))return {driverKind:"static",serve:o,reason:`Detected the built ${o}/index.html application.`};if(i("next"))throw new Error("Detected Next.js without an attach URL. Run `shaders capture` without an explicit driver or URL to preview the withThreeBlocksNext adapter and start a project-local capture server, or pass --url <local-url> for a server you manage.");if(i("webpack")||i("esbuild")||i("rollup"))throw new Error("Detected a non-Vite bundler but no static index.html. Run `shaders capture` without an explicit driver or URL to preview adapter wiring and build the project, or build it yourself and pass --driver static --serve <directory>.");return {driverKind:"vite",reason:"Using the Vite golden-path driver."}}a(vr,"inferShaderCaptureTarget");async function Ur(e){let r=await realpath(e),t=p.join(r,ne);if(await b(t))return {config:await te(r),file:t,created:false};let n=p.join(r,"three-blocks.json");if(await b(n))return {config:await te(r),file:n,created:false};let i=Ce,o=v(i),s=await xe(t,`${JSON.stringify(i,null,2)}
2
- `);return {config:s?o:await te(r),file:t,created:s}}a(Ur,"ensureShaderToolConfig");function ie(e){if(/^0\.185\./u.test(e))return THREE_WEBGPU_R185_COMPATIBILITY;if(e===THREE_R186DEV_VERSION)return THREE_WEBGPU_R186DEV_COMPATIBILITY;throw new Error(`Three.js ${e} is outside the supported shader compatibility contracts.`)}a(ie,"shaderCompatibilityForThree");var oe="0.1.0";var ue=52,pe="timing.local.json",le="timing.json",fe="parity.json",U=4096,fr=4096;function ae(e,r,t=8192){if(typeof e!="string"||e.length===0||e.length>t||/[\u0000\u007f]/u.test(e))throw new Error(`${r} must be a bounded non-empty string.`);return e}a(ae,"boundedString");function m(e,r,t=true){if(typeof e!="number"||!Number.isFinite(e)||e<0||t&&!Number.isSafeInteger(e))throw new Error(`${r} must be a non-negative ${t?"integer":"finite number"}.`);return e}a(m,"nonNegativeNumber");function mr(e){if(!c(e))throw new Error("Shader capture stats are missing.");let r={buildCalls:m(e.buildCalls,"capture stats.buildCalls"),renderBuilds:m(e.renderBuilds,"capture stats.renderBuilds"),computeBuilds:m(e.computeBuilds,"capture stats.computeBuilds"),registeredBuilds:m(e.registeredBuilds,"capture stats.registeredBuilds"),registeredRenderBuilds:m(e.registeredRenderBuilds,"capture stats.registeredRenderBuilds"),registeredComputeBuilds:m(e.registeredComputeBuilds,"capture stats.registeredComputeBuilds"),buildMs:m(e.buildMs,"capture stats.buildMs",false),syncBuildMs:m(e.syncBuildMs,"capture stats.syncBuildMs",false),asyncBuildElapsedMs:m(e.asyncBuildElapsedMs,"capture stats.asyncBuildElapsedMs",false),precompiledSetupMs:m(e.precompiledSetupMs,"capture stats.precompiledSetupMs",false),maxSyncBuildMs:m(e.maxSyncBuildMs??e.syncBuildMs,"capture stats.maxSyncBuildMs",false),maxPrecompiledSetupMs:m(e.maxPrecompiledSetupMs??e.precompiledSetupMs,"capture stats.maxPrecompiledSetupMs",false),hydrationMs:m(e.hydrationMs??0,"capture stats.hydrationMs",false),maxHydrationMs:m(e.maxHydrationMs??e.hydrationMs??0,"capture stats.maxHydrationMs",false),injected:m(e.injected,"capture stats.injected"),injectedRender:m(e.injectedRender,"capture stats.injectedRender"),injectedCompute:m(e.injectedCompute,"capture stats.injectedCompute"),missed:m(e.missed,"capture stats.missed"),missedRender:m(e.missedRender,"capture stats.missedRender"),missedCompute:m(e.missedCompute,"capture stats.missedCompute"),...Array.isArray(e.missedKeys)&&e.missedKeys.every(t=>typeof t=="string")?{missedKeys:e.missedKeys.slice(0,U)}:{}};if(r.renderBuilds+r.computeBuilds!==r.buildCalls||r.registeredRenderBuilds+r.registeredComputeBuilds!==r.registeredBuilds||r.injectedRender+r.injectedCompute!==r.injected||r.missedRender+r.missedCompute!==r.missed||r.registeredBuilds>r.buildCalls||Math.abs(r.syncBuildMs+r.asyncBuildElapsedMs-r.buildMs)>.001||r.maxSyncBuildMs>r.syncBuildMs+.001||r.maxPrecompiledSetupMs>r.precompiledSetupMs+.001||r.maxHydrationMs>r.hydrationMs+.001)throw new Error("Shader capture stats totals are inconsistent.");return r}a(mr,"captureStats");function hr(e){if(!Array.isArray(e)||e.length>U)throw new Error("Shader capture skipped builds are invalid.");return e.map((r,t)=>{if(!c(r)||r.kind!=="render"&&r.kind!=="compute")throw new Error(`Shader capture skipped build ${t} is invalid.`);return {kind:r.kind,name:ae(r.name,`skipped build ${t} name`,512),reason:ae(r.reason,`skipped build ${t} reason`)}})}a(hr,"skippedBuilds");function yr(e){let r=0,t=0,n=0,i=0;for(let o of Object.values(e.entries)){let s=e.states[o];s!==void 0&&((s.vertex!==null||s.fragment!==null)&&r++,s.vertex!==null&&t++,s.fragment!==null&&n++,s.compute!==null&&i++);}return {render:r,vertex:t,fragment:n,compute:i}}a(yr,"shaderCoverage");function ot(e,r){if(!c(e))throw new Error("Shader capture payload must be an object.");if(e.scene!==r.scene)throw new Error(`Shader capture scene does not match "${r.scene}".`);if(e.protocolVersion!==2)throw new Error("Shader capture protocolVersion must be 2.");let t=ie(r.runtime.three);if(e.compatibility!==t)throw new Error(`Shader capture compatibility must be "${t}".`);if(!c(e.entries))throw new Error("Shader capture entries must be an object.");if(typeof e.requiresSetup!="boolean")throw new Error("Shader capture requiresSetup must be boolean.");let n=Object.keys(e.entries).length;if(n===0||n>U)throw new Error(`Shader capture must contain 1...${U} entries.`);if(!Array.isArray(e.errors)||e.errors.length>fr)throw new Error("Shader capture errors are invalid.");let i=e.errors.map((h,u)=>ae(h,`capture error ${u}`,64*1024));if(i.length>0)throw new Error(`Shader capture failed:
2
+ `);return {config:s?o:await te(r),file:t,created:s}}a(Ur,"ensureShaderToolConfig");function ie(e){if(/^0\.185\./u.test(e))return THREE_WEBGPU_R185_COMPATIBILITY;if(e===THREE_R186DEV_VERSION)return THREE_WEBGPU_R186DEV_COMPATIBILITY;throw new Error(`Three.js ${e} is outside the supported shader compatibility contracts.`)}a(ie,"shaderCompatibilityForThree");var oe="0.1.0";var ue=53,pe="timing.local.json",le="timing.json",fe="parity.json",U=4096,fr=4096;function ae(e,r,t=8192){if(typeof e!="string"||e.length===0||e.length>t||/[\u0000\u007f]/u.test(e))throw new Error(`${r} must be a bounded non-empty string.`);return e}a(ae,"boundedString");function m(e,r,t=true){if(typeof e!="number"||!Number.isFinite(e)||e<0||t&&!Number.isSafeInteger(e))throw new Error(`${r} must be a non-negative ${t?"integer":"finite number"}.`);return e}a(m,"nonNegativeNumber");function mr(e){if(!c(e))throw new Error("Shader capture stats are missing.");let r={buildCalls:m(e.buildCalls,"capture stats.buildCalls"),renderBuilds:m(e.renderBuilds,"capture stats.renderBuilds"),computeBuilds:m(e.computeBuilds,"capture stats.computeBuilds"),registeredBuilds:m(e.registeredBuilds,"capture stats.registeredBuilds"),registeredRenderBuilds:m(e.registeredRenderBuilds,"capture stats.registeredRenderBuilds"),registeredComputeBuilds:m(e.registeredComputeBuilds,"capture stats.registeredComputeBuilds"),buildMs:m(e.buildMs,"capture stats.buildMs",false),syncBuildMs:m(e.syncBuildMs,"capture stats.syncBuildMs",false),asyncBuildElapsedMs:m(e.asyncBuildElapsedMs,"capture stats.asyncBuildElapsedMs",false),precompiledSetupMs:m(e.precompiledSetupMs,"capture stats.precompiledSetupMs",false),maxSyncBuildMs:m(e.maxSyncBuildMs??e.syncBuildMs,"capture stats.maxSyncBuildMs",false),maxPrecompiledSetupMs:m(e.maxPrecompiledSetupMs??e.precompiledSetupMs,"capture stats.maxPrecompiledSetupMs",false),hydrationMs:m(e.hydrationMs??0,"capture stats.hydrationMs",false),maxHydrationMs:m(e.maxHydrationMs??e.hydrationMs??0,"capture stats.maxHydrationMs",false),injected:m(e.injected,"capture stats.injected"),injectedRender:m(e.injectedRender,"capture stats.injectedRender"),injectedCompute:m(e.injectedCompute,"capture stats.injectedCompute"),missed:m(e.missed,"capture stats.missed"),missedRender:m(e.missedRender,"capture stats.missedRender"),missedCompute:m(e.missedCompute,"capture stats.missedCompute"),...Array.isArray(e.missedKeys)&&e.missedKeys.every(t=>typeof t=="string")?{missedKeys:e.missedKeys.slice(0,U)}:{}};if(r.renderBuilds+r.computeBuilds!==r.buildCalls||r.registeredRenderBuilds+r.registeredComputeBuilds!==r.registeredBuilds||r.injectedRender+r.injectedCompute!==r.injected||r.missedRender+r.missedCompute!==r.missed||r.registeredBuilds>r.buildCalls||Math.abs(r.syncBuildMs+r.asyncBuildElapsedMs-r.buildMs)>.001||r.maxSyncBuildMs>r.syncBuildMs+.001||r.maxPrecompiledSetupMs>r.precompiledSetupMs+.001||r.maxHydrationMs>r.hydrationMs+.001)throw new Error("Shader capture stats totals are inconsistent.");return r}a(mr,"captureStats");function hr(e){if(!Array.isArray(e)||e.length>U)throw new Error("Shader capture skipped builds are invalid.");return e.map((r,t)=>{if(!c(r)||r.kind!=="render"&&r.kind!=="compute")throw new Error(`Shader capture skipped build ${t} is invalid.`);return {kind:r.kind,name:ae(r.name,`skipped build ${t} name`,512),reason:ae(r.reason,`skipped build ${t} reason`)}})}a(hr,"skippedBuilds");function yr(e){let r=0,t=0,n=0,i=0;for(let o of Object.values(e.entries)){let s=e.states[o];s!==void 0&&((s.vertex!==null||s.fragment!==null)&&r++,s.vertex!==null&&t++,s.fragment!==null&&n++,s.compute!==null&&i++);}return {render:r,vertex:t,fragment:n,compute:i}}a(yr,"shaderCoverage");function ot(e,r){if(!c(e))throw new Error("Shader capture payload must be an object.");if(e.scene!==r.scene)throw new Error(`Shader capture scene does not match "${r.scene}".`);if(e.protocolVersion!==2)throw new Error("Shader capture protocolVersion must be 2.");let t=ie(r.runtime.three);if(e.compatibility!==t)throw new Error(`Shader capture compatibility must be "${t}".`);if(!c(e.entries))throw new Error("Shader capture entries must be an object.");if(typeof e.requiresSetup!="boolean")throw new Error("Shader capture requiresSetup must be boolean.");let n=Object.keys(e.entries).length;if(n===0||n>U)throw new Error(`Shader capture must contain 1...${U} entries.`);if(!Array.isArray(e.errors)||e.errors.length>fr)throw new Error("Shader capture errors are invalid.");let i=e.errors.map((h,u)=>ae(h,`capture error ${u}`,64*1024));if(i.length>0)throw new Error(`Shader capture failed:
3
3
  - ${i.join(`
4
4
  - `)}`);let o=hr(e.skipped),s=mr(e.stats),d=c(e.timing)?e.timing:void 0,l=d===void 0?void 0:Object.fromEntries(["launch","firstRequest","readiness","lastBuild","settled","posted"].flatMap(h=>{let u=d[h];if(u===void 0)return [];if(typeof u!="number"||!Number.isFinite(u)||u<0)throw new Error(`Shader capture timing.${h} is invalid.`);return [[h,u]]})),g;if(e.provenance!==void 0){if(!c(e.provenance)||typeof e.provenance.userAgent!="string"||e.provenance.userAgent.length>1024||typeof e.provenance.adapter!="string"||e.provenance.adapter.length>1024||!Array.isArray(e.provenance.features)||e.provenance.features.length>256||!e.provenance.features.every(h=>typeof h=="string"&&h.length<=128))throw new Error("Shader capture provenance is invalid.");g={userAgent:e.provenance.userAgent,adapter:e.provenance.adapter,features:[...new Set(e.provenance.features)].sort()};}let f=parsePrecompiledManifest({version:PRECOMPILED_MANIFEST_VERSION,scene:r.scene,three:r.runtime.three,threeBlocks:r.runtime.threeBlocks,runtime:{id:t,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION},...e.automatic===void 0?{}:{automatic:e.automatic},requiresSetup:e.requiresSetup,modules:e.modules,nodes:e.nodes,layouts:e.layouts,attributePlans:e.attributePlans,updatePlans:e.updatePlans,requirementPlans:e.requirementPlans,states:e.states,entries:e.entries}),y=yr(f);if(s.registeredRenderBuilds<y.render||s.registeredComputeBuilds<y.compute)throw new Error("Shader capture did not live-build every distinct registered render/compute entry.");return {scene:r.scene,manifest:f,skipped:o,stats:s,coverage:y,...l===void 0?{}:{timing:l},...g===void 0?{}:{provenance:g}}}a(ot,"validateShaderCapture");function T(e,r=0){let t=" ".repeat(r),n=" ".repeat(r+1);if(Array.isArray(e))return e.length===0?"[]":e.every(o=>o===null||["number","string","boolean"].includes(typeof o))?JSON.stringify(e):`[
5
5
  ${e.map(o=>`${n}${T(o,r+1)}`).join(`,
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {d as d$2,b as b$2,c as c$3,g as g$2}from'./chunk-76WRV5MZ.js';import {g as g$1}from'./chunk-JMS5NTP7.js';import {a as a$3,c as c$2,b,d as d$1}from'./chunk-5RSAQ74G.js';import {a as a$1,c,b as b$1}from'./chunk-ZDNZCQUQ.js';import {j,d,i,a as a$2,c as c$1}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {realpath}from'fs/promises';import h from'path';var te=".three-blocks/runtime/status.json",re=256*1024,H="three-blocks browser smoke",se=["three-blocks.json","three-blocks.shaders.json","three-blocks.text.ts"];function Q(e){return "kind"in e&&e.kind==="adopted"}a(Q,"isAdoptedProjectStatus");async function O(e,t,r,s){let n=await j(e,t,r,s);return JSON.parse(n.data.toString("utf8"))}a(O,"readJsonWithin");var ne=["starting","worker ready","assets ready","compiled","first frame","updating","error"],ae=["ready","generating","fallback","missing","invalid"],oe=["WebGPU","WebGL"],ie=["OffscreenCanvas","MainThread"],de=/^[0-9A-Za-z][0-9A-Za-z._-]{0,63}$/,X=16,K=1e9;function g(e,t,r,s=[]){if(!a$1(e))throw new Error(`${t} must be an object.`);let n=new Set([...r,...s]);for(let o of r)if(!Object.hasOwn(e,o))throw new Error(`${t}.${o} is required.`);for(let o of Object.keys(e))if(!n.has(o))throw new Error(`${t}.${o} is not supported by schema v1.`);return e}a(g,"exactRecord");function A(e,t,r){if(typeof e!="string"||!t.includes(e))throw new Error(`${r} has an unsupported value.`);return e}a(A,"enumValue");function p(e,t){if(typeof e!="boolean")throw new Error(`${t} must be a boolean.`);return e}a(p,"booleanValue");function Y(e,t){return e===null?null:p(e,t)}a(Y,"nullableBoolean");function E(e,t){if(typeof e!="number"||!Number.isSafeInteger(e)||e<0||e>K)throw new Error(`${t} must be a non-negative integer no greater than ${K}.`);return e}a(E,"boundedCounter");function ce(e){if(typeof e!="string"||e.length>32)throw new Error("Runtime status receipt observedAt must be a bounded ISO timestamp.");let t=Date.parse(e);if(!Number.isFinite(t)||new Date(t).toISOString()!==e)throw new Error("Runtime status receipt observedAt must be an exact ISO timestamp.");return e}a(ce,"observedTimestamp");function ue(e){if(e===null)return null;if(typeof e!="string"||e.length===0||e.length>2048||/[\u0000-\u001f\u007f]/u.test(e))throw new Error("Runtime status receipt error must be null or one bounded display-safe line.");return e}a(ue,"receiptError");function le(e){if(!Array.isArray(e)||e.length>X)throw new Error(`Runtime status receipt assets.codecs must contain at most ${X} entries.`);let t=e.map((r,s)=>{let n=g(r,`Runtime status receipt assets.codecs[${s}]`,["name","available","decoded"]);if(typeof n.name!="string"||!de.test(n.name))throw new Error(`Runtime status receipt assets.codecs[${s}].name is invalid.`);let o=p(n.available,`Runtime status receipt assets.codecs[${s}].available`),a=p(n.decoded,`Runtime status receipt assets.codecs[${s}].decoded`);if(a&&!o)throw new Error(`Runtime status receipt codec ${JSON.stringify(n.name)} cannot be decoded when unavailable.`);return {name:n.name,available:o,decoded:a}});if(new Set(t.map(r=>r.name)).size!==t.length)throw new Error("Runtime status receipt assets.codecs must have unique names.");return t}a(le,"parseRuntimeCodecs");function me(e){if(e.assetsReady&&!e.workerReady)throw new Error("Runtime lifecycle assetsReady requires workerReady.");if(e.compiled&&!e.assetsReady)throw new Error("Runtime lifecycle compiled requires assetsReady.");if(e.firstFrame&&!e.compiled)throw new Error("Runtime lifecycle firstFrame requires compiled.");let t=e.state==="starting"?[false,false,false,false]:e.state==="worker ready"?[true,false,false,false]:e.state==="assets ready"?[true,true,false,false]:e.state==="compiled"?[true,true,true,false]:e.state==="first frame"||e.state==="updating"?[true,true,true,true]:null;if(t!==null&&![e.workerReady,e.assetsReady,e.compiled,e.firstFrame].every((r,s)=>r===t[s]))throw new Error(`Runtime lifecycle flags do not match state ${JSON.stringify(e.state)}.`)}a(me,"validateLifecycle");function pe(e){let t=g(e,"Runtime status receipt",["schemaVersion","observedAt","worker","assets","hmr","stats","lifecycle","shaders","error"],["text"]);if(t.schemaVersion!==1)throw new Error("Runtime status receipt must use schemaVersion 1.");let r=g(t.worker,"Runtime status receipt worker",["backend","renderer","protocolVersion"]);if(r.protocolVersion!==1)throw new Error("Runtime status receipt worker.protocolVersion must be 1.");let s=g(t.assets,"Runtime status receipt assets",["codecs","resources"]),n=g(t.hmr,"Runtime status receipt hmr",["capabilities","outcome"]),o=g(n.capabilities,"Runtime status receipt hmr.capabilities",["scene","component","assetManifest","workerRestart"]),a=g(n.outcome,"Runtime status receipt hmr.outcome",["attempted","succeeded","rollbackPreserved","workerRestarted"]),d=p(a.attempted,"Runtime status receipt hmr.outcome.attempted"),l=Y(a.succeeded,"Runtime status receipt hmr.outcome.succeeded"),m=Y(a.rollbackPreserved,"Runtime status receipt hmr.outcome.rollbackPreserved"),y=p(a.workerRestarted,"Runtime status receipt hmr.outcome.workerRestarted");if(d?l===null||m===null:l!==null||m!==null||y)throw new Error("Runtime status receipt HMR outcome fields are inconsistent with attempted.");let k={scene:p(o.scene,"Runtime status receipt hmr.capabilities.scene"),component:p(o.component,"Runtime status receipt hmr.capabilities.component"),assetManifest:p(o.assetManifest,"Runtime status receipt hmr.capabilities.assetManifest"),workerRestart:p(o.workerRestart,"Runtime status receipt hmr.capabilities.workerRestart")};if(d&&!k.scene)throw new Error("Runtime status receipt cannot attempt HMR without the scene capability.");if(y&&!k.workerRestart)throw new Error("Runtime status receipt cannot restart a worker without the workerRestart capability.");let x=g(t.stats,"Runtime status receipt stats",["snapshots","textures","workerProfiler","mainPanels"]),R=g(t.lifecycle,"Runtime status receipt lifecycle",["state","workerReady","assetsReady","compiled","firstFrame"]),S={state:A(R.state,ne,"Runtime status receipt lifecycle.state"),workerReady:p(R.workerReady,"Runtime status receipt lifecycle.workerReady"),assetsReady:p(R.assetsReady,"Runtime status receipt lifecycle.assetsReady"),compiled:p(R.compiled,"Runtime status receipt lifecycle.compiled"),firstFrame:p(R.firstFrame,"Runtime status receipt lifecycle.firstFrame")};me(S);let V=g(t.shaders,"Runtime status receipt shaders",["mode","pipelines"]),P=A(V.mode,["precompiled","live"],"Runtime status receipt shaders.mode"),T=E(V.pipelines,"Runtime status receipt shaders.pipelines");if(P==="precompiled"&&T===0)throw new Error("A precompiled runtime receipt must observe at least one shader pipeline.");let f;if(t.text!==void 0){let I=g(t.text,"Runtime status receipt text",["state","atlases","glyphs","requiredGlyphs"]);if(f={state:A(I.state,ae,"Runtime status receipt text.state"),atlases:E(I.atlases,"Runtime status receipt text.atlases"),glyphs:E(I.glyphs,"Runtime status receipt text.glyphs"),requiredGlyphs:E(I.requiredGlyphs,"Runtime status receipt text.requiredGlyphs")},f.state==="ready"&&(f.atlases===0||f.requiredGlyphs===0||f.glyphs<f.requiredGlyphs))throw new Error("A ready text receipt must cover a non-empty required glyph set with at least one atlas.")}let b=ue(t.error);if(S.state==="error"?b===null:b!==null)throw new Error("Runtime status receipt error must be present only when lifecycle.state is error.");return {schemaVersion:1,observedAt:ce(t.observedAt),worker:{backend:A(r.backend,ie,"Runtime status receipt worker.backend"),renderer:A(r.renderer,oe,"Runtime status receipt worker.renderer"),protocolVersion:1},assets:{codecs:le(s.codecs),resources:E(s.resources,"Runtime status receipt assets.resources")},hmr:{capabilities:k,outcome:{attempted:d,succeeded:l,rollbackPreserved:m,workerRestarted:y}},stats:{snapshots:E(x.snapshots,"Runtime status receipt stats.snapshots"),textures:E(x.textures,"Runtime status receipt stats.textures"),workerProfiler:p(x.workerProfiler,"Runtime status receipt stats.workerProfiler"),mainPanels:p(x.mainPanels,"Runtime status receipt stats.mainPanels")},lifecycle:S,shaders:{mode:P,pipelines:T},...f===void 0?{}:{text:f},error:b}}a(pe,"parseRuntimeStatusReceipt");function he(e,t){return e.render===t.render&&e.vertex===t.vertex&&e.fragment===t.fragment&&e.compute===t.compute}a(he,"sameCoverage");async function ee(e=process.cwd()){let t=h.resolve(e);for(;;){if((await Promise.all(se.map(s=>d(h.join(t,s))))).some(Boolean))return realpath(t);let r=h.dirname(t);if(r===t)return realpath(h.resolve(e));t=r;}}a(ee,"findProjectRoot");async function fe(e,t){let r=t.template,s=h.join(e,".three-blocks","shaders"),n=h.join(s,"meta.json");if(!await d(s)||!await d(n))return {state:"missing",scene:r,reason:t.artifacts?.shaders==="pending"?"The selected template has no verified shader capture yet.":".three-blocks/shaders/meta.json is absent."};try{let o=await i(e,s,"Shader artifact directory"),a=c(await O(o,n,a$2.receipt,"Shader receipt")),d=a.scenes[r];if(d===void 0)return {state:"invalid",scene:r,reason:`Shader receipt has no "${r}" scene.`};let l=await j(o,h.join(o,d.artifact),a$2.manifest,"Shader manifest");if(c$1(l.data)!==d.artifactHash)return {state:"invalid",scene:r,reason:"The selected shader manifest checksum does not match its receipt."};let m=a$3(l.data.toString("utf8"),l.path,r);if(!he(m,d.coverage))return {state:"invalid",scene:r,reason:"Shader receipt coverage does not match the manifest entries.",coverage:m};let{three:y,threeBlocks:k,threeBlocksShaderClosure:x}=await c$2(e);if(a.runtime.three!==y||t.runtime.three!==y||a.runtime.threeBlocks!==k||t.runtime.threeBlocks!==k)return {state:"stale",scene:r,reason:`Installed runtime versions (${y}, ${k}) do not match the metadata and shader receipt.`,coverage:m};if(a.runtime.threeBlocksShaderClosure!==x)return {state:"stale",scene:r,reason:"The installed three-blocks/shaders runtime closure differs from the capture receipt.",coverage:m};let R=await b(e),S=Object.keys(R),V=Object.keys(d.inputs),P=S.filter(b=>!Object.hasOwn(d.inputs,b)),T=V.filter(b=>!Object.hasOwn(R,b)),f=S.filter(b=>Object.hasOwn(d.inputs,b)&&d.inputs[b]!==R[b]);return P.length>0||T.length>0||f.length>0?{state:"stale",scene:r,reason:`${P.length} added, ${T.length} removed, and ${f.length} changed semantic shader inputs.`,coverage:m,...f.length>0?{changedInputs:f}:{},...P.length>0?{addedInputs:P}:{},...T.length>0?{removedInputs:T}:{}}:{state:"fresh",scene:r,reason:"Manifest, installed shader runtime closure, and the shader-relevant source snapshot match.",coverage:m}}catch(o){return {state:"invalid",scene:r,reason:o instanceof Error?o.message:String(o)}}}a(fe,"inspectShaders");async function ye(e,t){if(t.artifacts?.text==="pending")return {state:"missing",reason:"The template has no verified text artifacts yet.",atlases:[]};let r=await g$1(e);return {state:r.state,reason:r.reason,atlases:r.atlases.map(s=>({name:s.font.key,glyphs:s.codePoints.length,width:s.texture.width,height:s.texture.height}))}}a(ye,"inspectText");function Re(e,t){if(e.lifecycle.assetsReady&&e.assets.codecs.some(r=>!r.available))throw new Error("Runtime status receipt claims assets ready while a configured codec is unavailable.");if(t.features.text!==(e.text!==void 0))throw new Error("Runtime status receipt text observation does not match three-blocks.json.")}a(Re,"validateRuntimeReceiptForProject");async function be(e,t){let r=h.join(e,...te.split("/"));if(!await d(r))return {kind:"absent",receipt:null,reason:"No browser observation receipt is available."};try{let s=await i(e,h.dirname(r),"Runtime status receipt directory"),n=pe(await O(s,h.join(s,h.basename(r)),re,"Runtime status receipt"));return Re(n,t),{kind:"valid",receipt:n,reason:n.error??`Browser observation captured at ${n.observedAt}.`}}catch(s){return {kind:"invalid",receipt:null,reason:`Runtime status receipt is invalid: ${s instanceof Error?s.message:String(s)}`}}}a(be,"inspectRuntimeReceipt");function ge(){return {scene:false,component:false,assetManifest:false,workerRestart:false}}a(ge,"emptyCapabilities");function we(){return {attempted:false,succeeded:null,rollbackPreserved:null,workerRestarted:false}}a(we,"emptyOutcome");function ke(){return []}a(ke,"configuredCodecs");function Se(e,t,r){if(t.state!=="fresh")return "three-blocks shaders capture";if(r!==void 0&&r.state!=="ready")return "three-blocks text generate";let s=e.receipt;return e.kind!=="valid"||s===null||s.lifecycle.state==="error"?H:s.text!==void 0&&s.text.state!=="ready"?"three-blocks text generate":H}a(Se,"recoveryCommand");async function xe(e=process.cwd()){let t=await ee(e),r=b$1(await O(t,h.join(t,"three-blocks.json"),a$2.metadata,"Project metadata")),s=await fe(t,r),n=r.features.text?await ye(t,r):void 0,o=await be(t,r),a=o.receipt,d=o.kind==="invalid",l=d||a?.lifecycle.state==="error",m=a===null?{state:d?"error":"starting",backend:null,renderer:null,protocolVersion:1}:{state:l?"error":a.lifecycle.workerReady?"worker ready":"starting",backend:a.worker.backend,renderer:a.worker.renderer,protocolVersion:a.worker.protocolVersion},y=a===null?{state:d?"error":"starting",codecs:ke(),resources:0}:{state:l?"error":a.lifecycle.assetsReady?"assets ready":"starting",codecs:a.assets.codecs,resources:a.assets.resources},k=a===null?{state:d?"error":"starting",capabilities:ge(),outcome:we()}:{state:l||a.hmr.outcome.attempted&&(a.hmr.outcome.succeeded!==true||a.hmr.outcome.rollbackPreserved!==true)?"error":a.hmr.outcome.attempted?"first frame":"starting",capabilities:a.hmr.capabilities,outcome:a.hmr.outcome},x=a===null?{state:d?"error":"starting",snapshots:0,textures:0,workerProfiler:false,mainPanels:false}:{state:l?"error":a.stats.snapshots>0&&a.stats.workerProfiler&&a.stats.mainPanels?"first frame":"starting",...a.stats},R=a===null?{state:d?"error":"starting",mode:null,pipelines:0,artifactState:s.state}:{state:l?"error":a.lifecycle.compiled?s.state==="fresh"?a.shaders.mode:s.state:a.lifecycle.state,mode:a.shaders.mode,pipelines:a.shaders.pipelines,artifactState:s.state},S=n===void 0?void 0:a?.text===void 0?{state:d?"error":"starting",atlases:0,glyphs:0,requiredGlyphs:0}:{state:l?"error":n.state==="ready"?a.text.state:n.state,atlases:a.text.atlases,glyphs:a.text.glyphs,requiredGlyphs:a.text.requiredGlyphs};return {schemaVersion:1,root:t,metadata:r,configuration:{worker:m,assets:y,hmr:k,optimization:R,stats:x,...S===void 0?{}:{text:S}},runtime:{state:d?"error":a?.lifecycle.state??"starting",observed:a!==null,observedAt:a?.observedAt??null,reason:o.reason,recovery:Se(o,s,n),observation:a},shaders:s,...n?{text:n}:{}}}a(xe,"inspectProject");async function Z(e){let[t,r]=await Promise.all([d(h.join(e,"three-blocks.shaders.json")),d(h.join(e,"three-blocks.text.ts"))]),[s,n]=await Promise.all([t?d$1(e):Promise.resolve(void 0),r?g$1(e):Promise.resolve(void 0)]);return {schemaVersion:1,root:e,kind:"adopted",markers:{shaders:t,text:r},...s===void 0?{}:{shaders:s},...n===void 0?{}:{text:n}}}a(Z,"inspectAdoptedProject");async function qe(e=process.cwd()){let t=await ee(e),r=h.join(t,"three-blocks.json");if(await d(r)){try{b$1(await O(t,r,a$2.metadata,"Project metadata"));}catch{return Z(t)}return xe(t)}return Z(t)}a(qe,"inspectThreeBlocksStatus");function Ge(e){return Q(e)?(e.markers.shaders||e.markers.text)&&(e.shaders===void 0||e.shaders.state==="fresh")&&(e.text===void 0||e.text.state==="ready"):e.shaders.state==="fresh"&&(e.text===void 0||e.text.state==="ready")&&e.runtime.state!=="error"}a(Ge,"threeBlocksStatusIsFresh");function $e(e){return e==="ktx2"?"KTX2":e==="draco"?"Draco":e==="meshopt"?"Meshopt":e}a($e,"codecName");function ve(e,t=Date.now()){let r=t-Date.parse(e);if(!Number.isFinite(r)||r<0)return e;let s=Math.round(r/1e3);if(s<60)return "just now";let n=Math.round(s/60);if(n<60)return `${n} minute${n===1?"":"s"} ago`;let o=Math.round(n/60);return o<48?`${o} hour${o===1?"":"s"} ago`:`${Math.round(o/24)} days ago`}a(ve,"relativeTime");function w(e,t,r){return `${e} ${d$2(t,12)} ${r}`}a(w,"row");function v(e,t){return ` ${d$2(b$2.dim(e),12)} ${b$2.dim(t)}`}a(v,"subRow");function Pe(e){return e<100?e.toFixed(1):Math.round(e).toString()}a(Pe,"milliseconds");function Te(e){return e?`${e.render} render \xB7 ${e.compute} compute`:"no coverage"}a(Te,"coverageText");function je(e){let t=[w(g$2(e.state),"shaders",`${e.state==="fresh"?"fresh":b$2.warn(e.state)} ${c$3.dot} ${b$2.dim(e.reason)}`)];for(let r of e.scenes){let s=r.timing,n=s?.source==="committed-capture"?s.adapter??"captured adapter":"this capture",o=s===void 0?"":s.runs>1?`measured median of ${s.runs}`:"single-capture estimate",a=s===void 0?"":`\u2248${Pe(s.avoidedBuildMs)} ms TSL work avoided`,d=s===void 0?r.state==="fresh"?` ${c$3.dot} ${b$2.dim("capture again to record a timing estimate")}`:"":` ${c$3.dot} ${b$2.dim(`${a} \xB7 ${o} \xB7 ${n}`)}`;t.push(w(g$2(r.state),r.scene,`${r.state} ${c$3.dot} ${Te(r.coverage)}${d}`)),s!==void 0&&s.spreadMs>s.avoidedBuildMs*.4&&t.push(v("measure",b$2.warn("noisy measurement \u2014 close other GPU apps and re-run")));let l=[...r.changedInputs??[],...r.addedInputs??[],...r.removedInputs??[]];l.length>0&&t.push(v("changed",l.join(", ")));}return e.state!=="fresh"&&t.push(`${c$3.info} ${b$2.accent("three-blocks shaders capture")}`),t.join(`
2
+ import {d as d$2,b as b$2,c as c$3,g as g$2}from'./chunk-76WRV5MZ.js';import {g as g$1}from'./chunk-JMS5NTP7.js';import {a as a$3,c as c$2,b,d as d$1}from'./chunk-LVY4EXVQ.js';import {a as a$1,c,b as b$1}from'./chunk-ZDNZCQUQ.js';import {j,d,i,a as a$2,c as c$1}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {realpath}from'fs/promises';import h from'path';var te=".three-blocks/runtime/status.json",re=256*1024,H="three-blocks browser smoke",se=["three-blocks.json","three-blocks.shaders.json","three-blocks.text.ts"];function Q(e){return "kind"in e&&e.kind==="adopted"}a(Q,"isAdoptedProjectStatus");async function O(e,t,r,s){let n=await j(e,t,r,s);return JSON.parse(n.data.toString("utf8"))}a(O,"readJsonWithin");var ne=["starting","worker ready","assets ready","compiled","first frame","updating","error"],ae=["ready","generating","fallback","missing","invalid"],oe=["WebGPU","WebGL"],ie=["OffscreenCanvas","MainThread"],de=/^[0-9A-Za-z][0-9A-Za-z._-]{0,63}$/,X=16,K=1e9;function g(e,t,r,s=[]){if(!a$1(e))throw new Error(`${t} must be an object.`);let n=new Set([...r,...s]);for(let o of r)if(!Object.hasOwn(e,o))throw new Error(`${t}.${o} is required.`);for(let o of Object.keys(e))if(!n.has(o))throw new Error(`${t}.${o} is not supported by schema v1.`);return e}a(g,"exactRecord");function A(e,t,r){if(typeof e!="string"||!t.includes(e))throw new Error(`${r} has an unsupported value.`);return e}a(A,"enumValue");function p(e,t){if(typeof e!="boolean")throw new Error(`${t} must be a boolean.`);return e}a(p,"booleanValue");function Y(e,t){return e===null?null:p(e,t)}a(Y,"nullableBoolean");function E(e,t){if(typeof e!="number"||!Number.isSafeInteger(e)||e<0||e>K)throw new Error(`${t} must be a non-negative integer no greater than ${K}.`);return e}a(E,"boundedCounter");function ce(e){if(typeof e!="string"||e.length>32)throw new Error("Runtime status receipt observedAt must be a bounded ISO timestamp.");let t=Date.parse(e);if(!Number.isFinite(t)||new Date(t).toISOString()!==e)throw new Error("Runtime status receipt observedAt must be an exact ISO timestamp.");return e}a(ce,"observedTimestamp");function ue(e){if(e===null)return null;if(typeof e!="string"||e.length===0||e.length>2048||/[\u0000-\u001f\u007f]/u.test(e))throw new Error("Runtime status receipt error must be null or one bounded display-safe line.");return e}a(ue,"receiptError");function le(e){if(!Array.isArray(e)||e.length>X)throw new Error(`Runtime status receipt assets.codecs must contain at most ${X} entries.`);let t=e.map((r,s)=>{let n=g(r,`Runtime status receipt assets.codecs[${s}]`,["name","available","decoded"]);if(typeof n.name!="string"||!de.test(n.name))throw new Error(`Runtime status receipt assets.codecs[${s}].name is invalid.`);let o=p(n.available,`Runtime status receipt assets.codecs[${s}].available`),a=p(n.decoded,`Runtime status receipt assets.codecs[${s}].decoded`);if(a&&!o)throw new Error(`Runtime status receipt codec ${JSON.stringify(n.name)} cannot be decoded when unavailable.`);return {name:n.name,available:o,decoded:a}});if(new Set(t.map(r=>r.name)).size!==t.length)throw new Error("Runtime status receipt assets.codecs must have unique names.");return t}a(le,"parseRuntimeCodecs");function me(e){if(e.assetsReady&&!e.workerReady)throw new Error("Runtime lifecycle assetsReady requires workerReady.");if(e.compiled&&!e.assetsReady)throw new Error("Runtime lifecycle compiled requires assetsReady.");if(e.firstFrame&&!e.compiled)throw new Error("Runtime lifecycle firstFrame requires compiled.");let t=e.state==="starting"?[false,false,false,false]:e.state==="worker ready"?[true,false,false,false]:e.state==="assets ready"?[true,true,false,false]:e.state==="compiled"?[true,true,true,false]:e.state==="first frame"||e.state==="updating"?[true,true,true,true]:null;if(t!==null&&![e.workerReady,e.assetsReady,e.compiled,e.firstFrame].every((r,s)=>r===t[s]))throw new Error(`Runtime lifecycle flags do not match state ${JSON.stringify(e.state)}.`)}a(me,"validateLifecycle");function pe(e){let t=g(e,"Runtime status receipt",["schemaVersion","observedAt","worker","assets","hmr","stats","lifecycle","shaders","error"],["text"]);if(t.schemaVersion!==1)throw new Error("Runtime status receipt must use schemaVersion 1.");let r=g(t.worker,"Runtime status receipt worker",["backend","renderer","protocolVersion"]);if(r.protocolVersion!==1)throw new Error("Runtime status receipt worker.protocolVersion must be 1.");let s=g(t.assets,"Runtime status receipt assets",["codecs","resources"]),n=g(t.hmr,"Runtime status receipt hmr",["capabilities","outcome"]),o=g(n.capabilities,"Runtime status receipt hmr.capabilities",["scene","component","assetManifest","workerRestart"]),a=g(n.outcome,"Runtime status receipt hmr.outcome",["attempted","succeeded","rollbackPreserved","workerRestarted"]),d=p(a.attempted,"Runtime status receipt hmr.outcome.attempted"),l=Y(a.succeeded,"Runtime status receipt hmr.outcome.succeeded"),m=Y(a.rollbackPreserved,"Runtime status receipt hmr.outcome.rollbackPreserved"),y=p(a.workerRestarted,"Runtime status receipt hmr.outcome.workerRestarted");if(d?l===null||m===null:l!==null||m!==null||y)throw new Error("Runtime status receipt HMR outcome fields are inconsistent with attempted.");let k={scene:p(o.scene,"Runtime status receipt hmr.capabilities.scene"),component:p(o.component,"Runtime status receipt hmr.capabilities.component"),assetManifest:p(o.assetManifest,"Runtime status receipt hmr.capabilities.assetManifest"),workerRestart:p(o.workerRestart,"Runtime status receipt hmr.capabilities.workerRestart")};if(d&&!k.scene)throw new Error("Runtime status receipt cannot attempt HMR without the scene capability.");if(y&&!k.workerRestart)throw new Error("Runtime status receipt cannot restart a worker without the workerRestart capability.");let x=g(t.stats,"Runtime status receipt stats",["snapshots","textures","workerProfiler","mainPanels"]),R=g(t.lifecycle,"Runtime status receipt lifecycle",["state","workerReady","assetsReady","compiled","firstFrame"]),S={state:A(R.state,ne,"Runtime status receipt lifecycle.state"),workerReady:p(R.workerReady,"Runtime status receipt lifecycle.workerReady"),assetsReady:p(R.assetsReady,"Runtime status receipt lifecycle.assetsReady"),compiled:p(R.compiled,"Runtime status receipt lifecycle.compiled"),firstFrame:p(R.firstFrame,"Runtime status receipt lifecycle.firstFrame")};me(S);let V=g(t.shaders,"Runtime status receipt shaders",["mode","pipelines"]),P=A(V.mode,["precompiled","live"],"Runtime status receipt shaders.mode"),T=E(V.pipelines,"Runtime status receipt shaders.pipelines");if(P==="precompiled"&&T===0)throw new Error("A precompiled runtime receipt must observe at least one shader pipeline.");let f;if(t.text!==void 0){let I=g(t.text,"Runtime status receipt text",["state","atlases","glyphs","requiredGlyphs"]);if(f={state:A(I.state,ae,"Runtime status receipt text.state"),atlases:E(I.atlases,"Runtime status receipt text.atlases"),glyphs:E(I.glyphs,"Runtime status receipt text.glyphs"),requiredGlyphs:E(I.requiredGlyphs,"Runtime status receipt text.requiredGlyphs")},f.state==="ready"&&(f.atlases===0||f.requiredGlyphs===0||f.glyphs<f.requiredGlyphs))throw new Error("A ready text receipt must cover a non-empty required glyph set with at least one atlas.")}let b=ue(t.error);if(S.state==="error"?b===null:b!==null)throw new Error("Runtime status receipt error must be present only when lifecycle.state is error.");return {schemaVersion:1,observedAt:ce(t.observedAt),worker:{backend:A(r.backend,ie,"Runtime status receipt worker.backend"),renderer:A(r.renderer,oe,"Runtime status receipt worker.renderer"),protocolVersion:1},assets:{codecs:le(s.codecs),resources:E(s.resources,"Runtime status receipt assets.resources")},hmr:{capabilities:k,outcome:{attempted:d,succeeded:l,rollbackPreserved:m,workerRestarted:y}},stats:{snapshots:E(x.snapshots,"Runtime status receipt stats.snapshots"),textures:E(x.textures,"Runtime status receipt stats.textures"),workerProfiler:p(x.workerProfiler,"Runtime status receipt stats.workerProfiler"),mainPanels:p(x.mainPanels,"Runtime status receipt stats.mainPanels")},lifecycle:S,shaders:{mode:P,pipelines:T},...f===void 0?{}:{text:f},error:b}}a(pe,"parseRuntimeStatusReceipt");function he(e,t){return e.render===t.render&&e.vertex===t.vertex&&e.fragment===t.fragment&&e.compute===t.compute}a(he,"sameCoverage");async function ee(e=process.cwd()){let t=h.resolve(e);for(;;){if((await Promise.all(se.map(s=>d(h.join(t,s))))).some(Boolean))return realpath(t);let r=h.dirname(t);if(r===t)return realpath(h.resolve(e));t=r;}}a(ee,"findProjectRoot");async function fe(e,t){let r=t.template,s=h.join(e,".three-blocks","shaders"),n=h.join(s,"meta.json");if(!await d(s)||!await d(n))return {state:"missing",scene:r,reason:t.artifacts?.shaders==="pending"?"The selected template has no verified shader capture yet.":".three-blocks/shaders/meta.json is absent."};try{let o=await i(e,s,"Shader artifact directory"),a=c(await O(o,n,a$2.receipt,"Shader receipt")),d=a.scenes[r];if(d===void 0)return {state:"invalid",scene:r,reason:`Shader receipt has no "${r}" scene.`};let l=await j(o,h.join(o,d.artifact),a$2.manifest,"Shader manifest");if(c$1(l.data)!==d.artifactHash)return {state:"invalid",scene:r,reason:"The selected shader manifest checksum does not match its receipt."};let m=a$3(l.data.toString("utf8"),l.path,r);if(!he(m,d.coverage))return {state:"invalid",scene:r,reason:"Shader receipt coverage does not match the manifest entries.",coverage:m};let{three:y,threeBlocks:k,threeBlocksShaderClosure:x}=await c$2(e);if(a.runtime.three!==y||t.runtime.three!==y||a.runtime.threeBlocks!==k||t.runtime.threeBlocks!==k)return {state:"stale",scene:r,reason:`Installed runtime versions (${y}, ${k}) do not match the metadata and shader receipt.`,coverage:m};if(a.runtime.threeBlocksShaderClosure!==x)return {state:"stale",scene:r,reason:"The installed three-blocks/shaders runtime closure differs from the capture receipt.",coverage:m};let R=await b(e),S=Object.keys(R),V=Object.keys(d.inputs),P=S.filter(b=>!Object.hasOwn(d.inputs,b)),T=V.filter(b=>!Object.hasOwn(R,b)),f=S.filter(b=>Object.hasOwn(d.inputs,b)&&d.inputs[b]!==R[b]);return P.length>0||T.length>0||f.length>0?{state:"stale",scene:r,reason:`${P.length} added, ${T.length} removed, and ${f.length} changed semantic shader inputs.`,coverage:m,...f.length>0?{changedInputs:f}:{},...P.length>0?{addedInputs:P}:{},...T.length>0?{removedInputs:T}:{}}:{state:"fresh",scene:r,reason:"Manifest, installed shader runtime closure, and the shader-relevant source snapshot match.",coverage:m}}catch(o){return {state:"invalid",scene:r,reason:o instanceof Error?o.message:String(o)}}}a(fe,"inspectShaders");async function ye(e,t){if(t.artifacts?.text==="pending")return {state:"missing",reason:"The template has no verified text artifacts yet.",atlases:[]};let r=await g$1(e);return {state:r.state,reason:r.reason,atlases:r.atlases.map(s=>({name:s.font.key,glyphs:s.codePoints.length,width:s.texture.width,height:s.texture.height}))}}a(ye,"inspectText");function Re(e,t){if(e.lifecycle.assetsReady&&e.assets.codecs.some(r=>!r.available))throw new Error("Runtime status receipt claims assets ready while a configured codec is unavailable.");if(t.features.text!==(e.text!==void 0))throw new Error("Runtime status receipt text observation does not match three-blocks.json.")}a(Re,"validateRuntimeReceiptForProject");async function be(e,t){let r=h.join(e,...te.split("/"));if(!await d(r))return {kind:"absent",receipt:null,reason:"No browser observation receipt is available."};try{let s=await i(e,h.dirname(r),"Runtime status receipt directory"),n=pe(await O(s,h.join(s,h.basename(r)),re,"Runtime status receipt"));return Re(n,t),{kind:"valid",receipt:n,reason:n.error??`Browser observation captured at ${n.observedAt}.`}}catch(s){return {kind:"invalid",receipt:null,reason:`Runtime status receipt is invalid: ${s instanceof Error?s.message:String(s)}`}}}a(be,"inspectRuntimeReceipt");function ge(){return {scene:false,component:false,assetManifest:false,workerRestart:false}}a(ge,"emptyCapabilities");function we(){return {attempted:false,succeeded:null,rollbackPreserved:null,workerRestarted:false}}a(we,"emptyOutcome");function ke(){return []}a(ke,"configuredCodecs");function Se(e,t,r){if(t.state!=="fresh")return "three-blocks shaders capture";if(r!==void 0&&r.state!=="ready")return "three-blocks text generate";let s=e.receipt;return e.kind!=="valid"||s===null||s.lifecycle.state==="error"?H:s.text!==void 0&&s.text.state!=="ready"?"three-blocks text generate":H}a(Se,"recoveryCommand");async function xe(e=process.cwd()){let t=await ee(e),r=b$1(await O(t,h.join(t,"three-blocks.json"),a$2.metadata,"Project metadata")),s=await fe(t,r),n=r.features.text?await ye(t,r):void 0,o=await be(t,r),a=o.receipt,d=o.kind==="invalid",l=d||a?.lifecycle.state==="error",m=a===null?{state:d?"error":"starting",backend:null,renderer:null,protocolVersion:1}:{state:l?"error":a.lifecycle.workerReady?"worker ready":"starting",backend:a.worker.backend,renderer:a.worker.renderer,protocolVersion:a.worker.protocolVersion},y=a===null?{state:d?"error":"starting",codecs:ke(),resources:0}:{state:l?"error":a.lifecycle.assetsReady?"assets ready":"starting",codecs:a.assets.codecs,resources:a.assets.resources},k=a===null?{state:d?"error":"starting",capabilities:ge(),outcome:we()}:{state:l||a.hmr.outcome.attempted&&(a.hmr.outcome.succeeded!==true||a.hmr.outcome.rollbackPreserved!==true)?"error":a.hmr.outcome.attempted?"first frame":"starting",capabilities:a.hmr.capabilities,outcome:a.hmr.outcome},x=a===null?{state:d?"error":"starting",snapshots:0,textures:0,workerProfiler:false,mainPanels:false}:{state:l?"error":a.stats.snapshots>0&&a.stats.workerProfiler&&a.stats.mainPanels?"first frame":"starting",...a.stats},R=a===null?{state:d?"error":"starting",mode:null,pipelines:0,artifactState:s.state}:{state:l?"error":a.lifecycle.compiled?s.state==="fresh"?a.shaders.mode:s.state:a.lifecycle.state,mode:a.shaders.mode,pipelines:a.shaders.pipelines,artifactState:s.state},S=n===void 0?void 0:a?.text===void 0?{state:d?"error":"starting",atlases:0,glyphs:0,requiredGlyphs:0}:{state:l?"error":n.state==="ready"?a.text.state:n.state,atlases:a.text.atlases,glyphs:a.text.glyphs,requiredGlyphs:a.text.requiredGlyphs};return {schemaVersion:1,root:t,metadata:r,configuration:{worker:m,assets:y,hmr:k,optimization:R,stats:x,...S===void 0?{}:{text:S}},runtime:{state:d?"error":a?.lifecycle.state??"starting",observed:a!==null,observedAt:a?.observedAt??null,reason:o.reason,recovery:Se(o,s,n),observation:a},shaders:s,...n?{text:n}:{}}}a(xe,"inspectProject");async function Z(e){let[t,r]=await Promise.all([d(h.join(e,"three-blocks.shaders.json")),d(h.join(e,"three-blocks.text.ts"))]),[s,n]=await Promise.all([t?d$1(e):Promise.resolve(void 0),r?g$1(e):Promise.resolve(void 0)]);return {schemaVersion:1,root:e,kind:"adopted",markers:{shaders:t,text:r},...s===void 0?{}:{shaders:s},...n===void 0?{}:{text:n}}}a(Z,"inspectAdoptedProject");async function qe(e=process.cwd()){let t=await ee(e),r=h.join(t,"three-blocks.json");if(await d(r)){try{b$1(await O(t,r,a$2.metadata,"Project metadata"));}catch{return Z(t)}return xe(t)}return Z(t)}a(qe,"inspectThreeBlocksStatus");function Ge(e){return Q(e)?(e.markers.shaders||e.markers.text)&&(e.shaders===void 0||e.shaders.state==="fresh")&&(e.text===void 0||e.text.state==="ready"):e.shaders.state==="fresh"&&(e.text===void 0||e.text.state==="ready")&&e.runtime.state!=="error"}a(Ge,"threeBlocksStatusIsFresh");function $e(e){return e==="ktx2"?"KTX2":e==="draco"?"Draco":e==="meshopt"?"Meshopt":e}a($e,"codecName");function ve(e,t=Date.now()){let r=t-Date.parse(e);if(!Number.isFinite(r)||r<0)return e;let s=Math.round(r/1e3);if(s<60)return "just now";let n=Math.round(s/60);if(n<60)return `${n} minute${n===1?"":"s"} ago`;let o=Math.round(n/60);return o<48?`${o} hour${o===1?"":"s"} ago`:`${Math.round(o/24)} days ago`}a(ve,"relativeTime");function w(e,t,r){return `${e} ${d$2(t,12)} ${r}`}a(w,"row");function v(e,t){return ` ${d$2(b$2.dim(e),12)} ${b$2.dim(t)}`}a(v,"subRow");function Pe(e){return e<100?e.toFixed(1):Math.round(e).toString()}a(Pe,"milliseconds");function Te(e){return e?`${e.render} render \xB7 ${e.compute} compute`:"no coverage"}a(Te,"coverageText");function je(e){let t=[w(g$2(e.state),"shaders",`${e.state==="fresh"?"fresh":b$2.warn(e.state)} ${c$3.dot} ${b$2.dim(e.reason)}`)];for(let r of e.scenes){let s=r.timing,n=s?.source==="committed-capture"?s.adapter??"captured adapter":"this capture",o=s===void 0?"":s.runs>1?`measured median of ${s.runs}`:"single-capture estimate",a=s===void 0?"":`\u2248${Pe(s.avoidedBuildMs)} ms TSL work avoided`,d=s===void 0?r.state==="fresh"?` ${c$3.dot} ${b$2.dim("capture again to record a timing estimate")}`:"":` ${c$3.dot} ${b$2.dim(`${a} \xB7 ${o} \xB7 ${n}`)}`;t.push(w(g$2(r.state),r.scene,`${r.state} ${c$3.dot} ${Te(r.coverage)}${d}`)),s!==void 0&&s.spreadMs>s.avoidedBuildMs*.4&&t.push(v("measure",b$2.warn("noisy measurement \u2014 close other GPU apps and re-run")));let l=[...r.changedInputs??[],...r.addedInputs??[],...r.removedInputs??[]];l.length>0&&t.push(v("changed",l.join(", ")));}return e.state!=="fresh"&&t.push(`${c$3.info} ${b$2.accent("three-blocks shaders capture")}`),t.join(`
3
3
  `)}a(je,"formatShaderMatrixStatus");function Ee(e){let t=e.scene,r=e.coverage,s=r?`${r.render} render \xB7 ${r.compute} compute`:"no coverage";if(e.state==="fresh")return [w(g$2("fresh"),t,`fresh ${c$3.dot} ${s} ${c$3.dot} ${b$2.dim("precompiled at runtime")}`)];let n=[w(g$2(e.state),t,`${e.state==="missing"?b$2.dim("missing"):b$2.warn(e.state)} ${c$3.dot} ${b$2.dim(e.reason)}`)],o=[...e.changedInputs??[],...e.addedInputs??[],...e.removedInputs??[]];return o.length>0&&n.push(v("changed",o.join(", "))),n}a(Ee,"shaderRow");function Me(e,t=Date.now()){let r=c$3.mark?`${c$3.mark} `:"",s=e.metadata.runtime,n=[`${r}${b$2.bold("three-blocks")} ${b$2.dim("status")}`,v("project",e.root),"",b$2.bold("Project"),w(c$3.tick,e.metadata.template,`three ${s.three} ${c$3.dot} three-blocks ${s.threeBlocks}`),"",b$2.bold("Shaders"),...Ee(e.shaders)];if(e.text){let d=e.text,l=d.atlases.reduce((m,y)=>m+y.glyphs,0);n.push("",b$2.bold("Text"),w(g$2(d.state),"coverage",d.state==="ready"?`ready ${c$3.dot} ${l} glyphs ${c$3.dot} ${d.atlases.length} atlas${d.atlases.length===1?"":"es"}`:`${b$2.warn(d.state)} ${c$3.dot} ${b$2.dim(d.reason)}`),...d.atlases.map(m=>v("atlas",`${m.name} \xB7 ${m.glyphs} glyphs \xB7 ${m.width}\xD7${m.height}`)));}let o=e.runtime.observation;if(n.push("",b$2.bold("Browser check")),o!==null&&e.runtime.state!=="error"){let d=o.assets.codecs.map(l=>`${$e(l.name)}${l.decoded?"":l.available?" (idle)":" (unavailable)"}`).join(" \xB7 ");n.push(w(c$3.tick,"verified",`${ve(o.observedAt,t)} ${c$3.dot} ${o.worker.renderer} worker ${c$3.dot} ${o.lifecycle.state} ${c$3.dot} ${o.shaders.pipelines} pipeline${o.shaders.pipelines===1?"":"s"} ${o.shaders.mode}`),v("codecs",d||"none configured")),o.hmr.outcome.attempted&&n.push(v("hmr",o.hmr.outcome.succeeded?`update succeeded${o.hmr.outcome.workerRestarted?" \xB7 worker restarted":""}`:"update failed"));}else e.runtime.state==="error"?n.push(w(c$3.cross,"runtime",b$2.danger(e.runtime.reason))):n.push(w(c$3.ring,"unverified",b$2.dim(`no browser run recorded \u2014 ${H}`)));return e.shaders.state==="fresh"&&(e.text===void 0||e.text.state==="ready")&&e.runtime.state!=="error"||n.push("",b$2.bold("Next"),`${c$3.info} ${b$2.accent(e.runtime.recovery)}`),n.join(`
4
4
  `)}a(Me,"formatStatus");function He(e,t=Date.now()){if(!Q(e))return Me(e,t);let r=c$3.mark?`${c$3.mark} `:"",s=e.markers.shaders||e.markers.text,n=[`${r}${b$2.bold("three-blocks")} ${b$2.dim("status")}`,v("project",e.root)];if(!s)return n.push("",`${c$3.dot} ${b$2.dim("no Three Blocks project markers found")}`,` ${b$2.dim("shaders:")} add three-blocks.shaders.json \u2014 /docs/tools/devtools`,` ${b$2.dim("starter:")} npx three-blocks starter`),n.join(`
5
5
  `);if(e.shaders!==void 0&&n.push("",b$2.bold("Shaders"),je(e.shaders)),e.text!==void 0){let o=e.text.atlases.reduce((a,d)=>a+d.codePoints.length,0);n.push("",b$2.bold("Text"),w(g$2(e.text.state),"coverage",e.text.state==="ready"?`ready ${c$3.dot} ${o} glyphs ${c$3.dot} ${e.text.atlases.length} atlas${e.text.atlases.length===1?"":"es"}`:`${b$2.warn(e.text.state)} ${c$3.dot} ${b$2.dim(e.text.reason)}`));}return n.join(`
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {b,e as e$2,a as a$3,d as d$1,c as c$2,j as j$1,i as i$1,f as f$2,h as h$2,g as g$1}from'./chunk-HLYATKSG.js';import {a as a$4}from'./chunk-ZT6T2W4B.js';import {e as e$1,f,b as b$1,h as h$1,g,c as c$3}from'./chunk-NEWSG5RX.js';import {a as a$2,c as c$1}from'./chunk-ZDNZCQUQ.js';import {j,a as a$1,c,d,k,h,e,i,f as f$1}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {realpath,readdir,readFile,lstat,mkdir,writeFile}from'fs/promises';import ve from'os';import P from'path';import {SHADER_ADDRESS_SCHEMA_VERSION,SHADER_RECIPE_SCHEMA_VERSION,SHADER_HYDRATION_SCHEMA_VERSION}from'three-blocks/shaders';import {createRequire}from'module';var Pe=[".ts",".tsx",".mts",".cts",".js",".jsx",".mjs",".cjs",".wgsl",".glsl",".vert",".frag",".json",".css"],Ie=new Set(Pe),Be=/^(?:three-blocks\.shaders\.json|(?:precompile|three-blocks\.shaders)\.config\.(?:cjs|cts|js|mjs|mts|ts))$/u,gr=/(?:^|\/)scene\.(?:cjs|cts|js|jsx|mjs|mts|ts|tsx)$/u,Sr=/\b(?:export\s+)?(?:async\s+)?function\s+createScene\b|\bcreateScene\s*=\s*(?:async\s*)?\(/u,yr=/\b(?:[A-Za-z_$][\w$]*\.)*(?:shaders|shaderCache|sceneShaders)\s*\.\s*(?:material|pipeline|compute|container)\s*\(/u,wr=/\b(import|export)(?!\s*\()\s*(type\b\s*)?(?:[^"'();]*?\bfrom\s*)?["']([^"']+)["']/gu,vr=/\bimport\s*\(\s*["']([^"']+)["']\s*\)/gu,br=/\b(?:import|export)(?!\s*\()\s*(?:[^"'();]*?\bfrom\s*)?["']([^"']+)["']|\bimport\s*\(\s*["']([^"']+)["']\s*\)/gu,Er=/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,127}$/u,Oe=4096,kr="./shaders";function Ye(e,r){let t=P.relative(e,r).split(P.sep).join("/");if(t.length===0||/[\u0000-\u001f\u007f]/u.test(t))throw new Error("Semantic input has an unsafe relative path.");return t}a(Ye,"portableRelativePath");function Ce(e,r){try{return new TextDecoder("utf-8",{fatal:!0}).decode(e)}catch{throw new Error(`Shader-relevant source ${JSON.stringify(r)} is not valid UTF-8.`)}}a(Ce,"sourceText");function Ae(e,r){let t="",n="code";for(let i=0;i<e.length;i++){let s=e[i]??"",a=e[i+1]??"";if(n==="code"){if(s==="/"&&a==="/"){t+=" ",n="line-comment",i++;continue}if(s==="/"&&a==="*"){t+=" ",n="block-comment",i++;continue}if(s==="'"||s==='"'||s==="`"){n=s==="'"?"single":s==='"'?"double":"template",t+=r?s:" ";continue}t+=s;continue}if(n==="line-comment"){s===`
2
+ import {b,e as e$2,a as a$3,d as d$1,c as c$2,j as j$1,i as i$1,f as f$2,h as h$2,g as g$1}from'./chunk-TGOUAHMD.js';import {a as a$4}from'./chunk-ZT6T2W4B.js';import {e as e$1,f,b as b$1,h as h$1,g,c as c$3}from'./chunk-NEWSG5RX.js';import {a as a$2,c as c$1}from'./chunk-ZDNZCQUQ.js';import {j,a as a$1,c,d,k,h,e,i,f as f$1}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {realpath,readdir,readFile,lstat,mkdir,writeFile}from'fs/promises';import ve from'os';import P from'path';import {SHADER_ADDRESS_SCHEMA_VERSION,SHADER_RECIPE_SCHEMA_VERSION,SHADER_HYDRATION_SCHEMA_VERSION}from'three-blocks/shaders';import {createRequire}from'module';var Pe=[".ts",".tsx",".mts",".cts",".js",".jsx",".mjs",".cjs",".wgsl",".glsl",".vert",".frag",".json",".css"],Ie=new Set(Pe),Be=/^(?:three-blocks\.shaders\.json|(?:precompile|three-blocks\.shaders)\.config\.(?:cjs|cts|js|mjs|mts|ts))$/u,gr=/(?:^|\/)scene\.(?:cjs|cts|js|jsx|mjs|mts|ts|tsx)$/u,Sr=/\b(?:export\s+)?(?:async\s+)?function\s+createScene\b|\bcreateScene\s*=\s*(?:async\s*)?\(/u,yr=/\b(?:[A-Za-z_$][\w$]*\.)*(?:shaders|shaderCache|sceneShaders)\s*\.\s*(?:material|pipeline|compute|container)\s*\(/u,wr=/\b(import|export)(?!\s*\()\s*(type\b\s*)?(?:[^"'();]*?\bfrom\s*)?["']([^"']+)["']/gu,vr=/\bimport\s*\(\s*["']([^"']+)["']\s*\)/gu,br=/\b(?:import|export)(?!\s*\()\s*(?:[^"'();]*?\bfrom\s*)?["']([^"']+)["']|\bimport\s*\(\s*["']([^"']+)["']\s*\)/gu,Er=/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,127}$/u,Oe=4096,kr="./shaders";function Ye(e,r){let t=P.relative(e,r).split(P.sep).join("/");if(t.length===0||/[\u0000-\u001f\u007f]/u.test(t))throw new Error("Semantic input has an unsafe relative path.");return t}a(Ye,"portableRelativePath");function Ce(e,r){try{return new TextDecoder("utf-8",{fatal:!0}).decode(e)}catch{throw new Error(`Shader-relevant source ${JSON.stringify(r)} is not valid UTF-8.`)}}a(Ce,"sourceText");function Ae(e,r){let t="",n="code";for(let i=0;i<e.length;i++){let s=e[i]??"",a=e[i+1]??"";if(n==="code"){if(s==="/"&&a==="/"){t+=" ",n="line-comment",i++;continue}if(s==="/"&&a==="*"){t+=" ",n="block-comment",i++;continue}if(s==="'"||s==='"'||s==="`"){n=s==="'"?"single":s==='"'?"double":"template",t+=r?s:" ";continue}t+=s;continue}if(n==="line-comment"){s===`
3
3
  `?(t+=`
4
4
  `,n="code"):t+=" ";continue}if(n==="block-comment"){s==="*"&&a==="/"?(t+=" ",n="code",i++):t+=s===`
5
5
  `?`
@@ -7,8 +7,8 @@ import {b,e as e$2,a as a$3,d as d$1,c as c$2,j as j$1,i as i$1,f as f$2,h as h$
7
7
  `?`
8
8
  `:" ",s===l&&(n="code");}return t}a(Ae,"lexicalSource");function Rr(e){let r=new Set,t=Ae(e,true);for(let n of t.matchAll(wr))n[2]===void 0&&n[3]!==void 0&&r.add(n[3]);for(let n of t.matchAll(vr))n[1]!==void 0&&r.add(n[1]);return [...r].sort()}a(Rr,"importSpecifiers");function xr(e){let r=new Set;for(let t of Ae(e,true).matchAll(br)){let n=t[1]??t[2];n!==void 0&&r.add(n);}return [...r].sort()}a(xr,"runtimeSpecifiers");function Xe(e){return (e.split(/[?#]/u,1)[0]??e).replaceAll("\\","/")}a(Xe,"cleanSpecifier");function Tr(e,r,t){let n=Xe(r),i;if(n.startsWith("./")||n.startsWith("../"))i=P.posix.normalize(P.posix.join(P.posix.dirname(e),n));else if(n.startsWith("@/"))i=`src/${n.slice(2)}`;else if(n.startsWith("/src/"))i=n.slice(1);else return;if(i===".three-blocks"||i.startsWith(".three-blocks/"))return;let s=P.posix.extname(i).toLowerCase(),a=new Set([i]);if(s.length===0||!Ie.has(s)){for(let l of Pe)a.add(`${i}${l}`);for(let l of Pe)a.add(`${i}/index${l}`);}else if([".js",".mjs",".cjs",".jsx"].includes(s)){let l=i.slice(0,-s.length);for(let u of [".ts",".tsx",".mts",".cts"])a.add(`${l}${u}`);}return [...a].find(l=>t.has(l))}a(Tr,"resolveProjectImport");function $r(e,r){let t=Ae(r,false);return gr.test(e)||Sr.test(t)||yr.test(t)}a($r,"isShaderRoot");async function me(e,r){let t=await realpath(e);if(r!==void 0){let o={},h=0;for(let m of r){let b=await j(t,P.join(t,m),a$1.semanticInput,"Declared shader semantic input");if(h+=b.data.byteLength,h>a$1.semanticTotal)throw new Error("Declared shader semantic inputs exceed the total inspection size limit.");o[m]=c(b.data);}return o}let n=new Map,i=P.join(t,"src");if(await d(i))for(let o of await k(t,i,h=>Ie.has(P.extname(h).toLowerCase()))){let h=await j(t,o,a$1.semanticInput,"Shader semantic input");n.set(Ye(t,o),h.data);}for(let o of await readdir(t,{withFileTypes:true})){if(!o.isFile()||!Be.test(o.name)&&!Ie.has(P.extname(o.name).toLowerCase()))continue;let h=await j(t,P.join(t,o.name),a$1.semanticInput,Be.test(o.name)?"Shader configuration input":"Shader semantic input");n.set(o.name,h.data);}if(n.size>Oe)throw new Error(`Shader input discovery exceeds the ${Oe}-file limit.`);let s=new Set,a=new Map;for(let[o,h]of n){if(!o.includes("/")&&Be.test(o)&&s.add(o),!o.startsWith("src/"))continue;let m=Ce(h,o);a.set(o,m),$r(o,m)&&s.add(o);}if(s.size===0)throw new Error("No shader registration or scene source root was found.");let l=new Set,u=[...s].sort();for(;u.length>0;){let o=u.shift();if(o===void 0||l.has(o))continue;let h=n.get(o);if(h===void 0)continue;l.add(o);let m=a.get(o)??Ce(h,o);for(let b of Rr(m)){let x=Tr(o,b,n);x!==void 0&&!l.has(x)&&u.push(x);}u.sort();}let f=0,w={};for(let o of [...l].sort()){let h=n.get(o);if(h===void 0)throw new Error(`Shader input ${JSON.stringify(o)} disappeared during inspection.`);if(f+=h.byteLength,f>a$1.semanticTotal)throw new Error("Semantic shader inputs exceed the total inspection size limit.");w[o]=c(h);}return w}a(me,"snapshotShaderInputs");function je(e){if(typeof e=="string")return e;if(a$2(e))return je(e.import)??je(e.default)}a(je,"conditionalImportTarget");async function Ge(e,r){let t=e;for(;;){let n=P.join(t,"node_modules",...r.split("/"),"package.json");if(await d(n)){let s=await h(n,a$1.packageJson,`${r} package.json`),a=JSON.parse(s.data.toString("utf8"));if(!a$2(a)||a.name!==r||typeof a.version!="string"||!Er.test(a.version))throw new Error(`Installed ${r} package metadata is invalid.`);return {root:P.dirname(s.path),manifest:a}}let i=P.dirname(t);if(i===t)break;t=i;}throw new Error(`Cannot verify the installed ${r} package.`)}a(Ge,"findInstalledPackage");async function Mr(e$1,r){if(!a$2(r.exports))throw new Error("Installed three-blocks package has no public exports map.");let t=je(r.exports[kr]);if(t===void 0||!t.startsWith("./"))throw new Error("Installed three-blocks shader export has no import target.");let n=await realpath(e$1),i=[P.resolve(n,t)],s=new Map,a=0;for(;i.length>0;){let u=i.shift();if(u===void 0)break;let f=await h(u,a$1.semanticInput,"Three Blocks shader runtime module");if(!e(n,f.path)||f.path===n)throw new Error("Three Blocks shader runtime closure escapes its package.");let w=Ye(n,f.path);if(s.has(w))continue;if(a+=f.data.byteLength,a>a$1.semanticTotal)throw new Error("Three Blocks shader runtime closure exceeds the inspection limit.");s.set(w,c(f.data));let o=Ce(f.data,w);for(let h of xr(o)){let m=Xe(h);if(!m.startsWith("./")&&!m.startsWith("../"))continue;let b=P.resolve(P.dirname(f.path),m);if(!e(n,b))throw new Error("Three Blocks shader runtime import escapes its package.");i.push(b);}if(i.sort(),s.size+i.length>Oe)throw new Error("Three Blocks shader runtime closure exceeds the file limit.")}let l=[...s].sort((u,f)=>u[0].localeCompare(f[0])).map(([u,f])=>`${u}\0${f}`).join(`
9
9
  `);return c(l)}a(Mr,"shaderRuntimeClosure");async function se(e){let[r,t]=await Promise.all([Ge(e,"three"),Ge(e,"three-blocks")]);return {three:String(r.manifest.version),threeBlocks:String(t.manifest.version),threeBlocksShaderClosure:await Mr(t.root,t.manifest)}}a(se,"readInstalledShaderRuntime");var Ze=4096,Pr=createRequire(import.meta.url),Qe,R=new Proxy({},{get(e,r){return Qe??=Pr("typescript"),Reflect.get(Qe,r)}});function U(e){let r=e;for(;R.isParenthesizedExpression(r)||R.isAsExpression(r)||R.isSatisfiesExpression(r)||R.isNonNullExpression(r);)r=r.expression;return r}a(U,"unwrap");function Ir(e){if(R.isIdentifier(e)||R.isStringLiteral(e)||R.isNumericLiteral(e))return e.text}a(Ir,"propertyName");function pe(e,r){let t=new Map;for(let n of e.properties){if(!R.isPropertyAssignment(n))throw new Error(`${r} may contain only static property assignments.`);let i=Ir(n.name);if(i===void 0||t.has(i))throw new Error(`${r} contains a computed or duplicate property.`);t.set(i,n.initializer);}return t}a(pe,"properties");function ge(e,r){if(e===void 0)throw new Error(`${r} is missing.`);let t=U(e);if(!R.isObjectLiteralExpression(t))throw new Error(`${r} must be a static object literal.`);return t}a(ge,"objectLiteral");function Se(e,r){if(e===void 0)throw new Error(`${r} is missing.`);let t=U(e);if(!R.isStringLiteral(t)&&!R.isNoSubstitutionTemplateLiteral(t))throw new Error(`${r} must be a string literal.`);return t.text}a(Se,"stringLiteral");function ye(e,r){if(e===void 0)throw new Error(`${r} is missing.`);let t=U(e);if(!R.isNumericLiteral(t))throw new Error(`${r} must be a numeric literal.`);return Number(t.text)}a(ye,"numericLiteral");function er(e,r){if(e===void 0)throw new Error(`${r} is missing.`);let t=U(e);if(!R.isArrayLiteralExpression(t))throw new Error(`${r} must be a static array literal.`);return t.elements}a(er,"arrayLiteral");function Or(e,r){if(e===void 0)throw new Error(`${r} is missing.`);let t=U(e);if(t.kind===R.SyntaxKind.NullKeyword)return null;if(!R.isNumericLiteral(t))throw new Error(`${r} must be null or a numeric literal.`);return Number(t.text)}a(Or,"numericOrNullLiteral");function Cr(e){return e.parseDiagnostics??[]}a(Cr,"parseDiagnostics");function rr(e,r,t,n){let i=R.createSourceFile(r,e,R.ScriptTarget.Latest,true,R.ScriptKind.TS),s=Cr(i);if(s.length>0)throw new Error(`Shader manifest is not valid TypeScript: ${R.flattenDiagnosticMessageText(s[0]?.messageText??"parse error"," ")}`);let a$1=i.statements.filter(R.isExportAssignment).filter(m=>!m.isExportEquals);if(a$1.length!==1)throw new Error("Shader manifest must contain exactly one default export.");let l=pe(ge(a$1[0]?.expression,"Shader manifest default export"),"Shader manifest"),u=l.get("version");if(u===void 0||!R.isNumericLiteral(U(u))||Number(U(u).getText(i))!==3)throw new Error("Shader manifest version must be the numeric literal 3.");if(Se(l.get("scene"),"Shader manifest scene")!==t)throw new Error(`Shader manifest scene does not match "${t}".`);if(n){if(Se(l.get("three"),"Shader manifest Three.js version")!==n.three||Se(l.get("threeBlocks"),"Shader manifest Three Blocks version")!==n.threeBlocks)throw new Error("Shader manifest runtime versions do not match its receipt.");let m=pe(ge(l.get("runtime"),"Shader manifest runtime"),"Shader manifest runtime");if(Se(m.get("id"),"Shader manifest runtime id")!==n.compatibility||ye(m.get("address"),"Shader manifest address schema")!==n.address||ye(m.get("recipe"),"Shader manifest recipe schema")!==n.recipe||ye(m.get("hydration"),"Shader manifest hydration schema")!==n.hydration)throw new Error("Shader manifest runtime compatibility schemas do not match its receipt.")}let f=pe(ge(l.get("entries"),"Shader manifest entries"),"Shader manifest entries");if(f.size===0||f.size>Ze)throw new Error(`Shader manifest must contain between 1 and ${Ze} entries.`);let w=er(l.get("modules"),"Shader manifest modules").map((m,b)=>{let x=U(m);if(!R.isStringLiteral(x)&&!R.isNoSubstitutionTemplateLiteral(x))throw new Error(`Shader manifest module ${b} must be a WGSL string literal.`);if(x.text.length===0)throw new Error(`Shader manifest module ${b} is empty.`);return x.text}),o=er(l.get("states"),"Shader manifest states").map((m,b)=>{let x=pe(ge(m,`Shader manifest state ${b}`),`Shader manifest state ${b}`),E=a(($,I)=>{let L=Or(x.get($),`Shader manifest state ${b} ${$}`);if(L===null)return false;let p=w[L];if(p===void 0||!p.includes(I))throw new Error(`Shader manifest state ${b} ${$} does not reference a ${I} module.`);return true},"moduleAt"),O=E("vertex","@vertex"),C=E("fragment","@fragment"),A=E("compute","@compute");if(A&&(O||C))throw new Error(`Shader manifest state ${b} mixes render and compute stages.`);if(!A&&!O&&!C)throw new Error(`Shader manifest state ${b} contains no shader stage.`);return {vertex:O,fragment:C,compute:A}}),h={render:0,vertex:0,fragment:0,compute:0};for(let[m,b]of f){if(m.length===0||/[\u0000-\u001f\u007f]/.test(m))throw new Error("Shader manifest contains an invalid entry key.");let x=ye(b,`Shader manifest entry "${m}"`),E=o[x];if(E===void 0)throw new Error(`Shader manifest entry "${m}" references an absent state.`);(E.vertex||E.fragment)&&(h.render+=1),E.vertex&&(h.vertex+=1),E.fragment&&(h.fragment+=1),E.compute&&(h.compute+=1);}return h}a(rr,"inspectPrecompiledManifest");function jr(e,r){return e.render===r.render&&e.vertex===r.vertex&&e.fragment===r.fragment&&e.compute===r.compute}a(jr,"sameCoverage");function Ar(e){let r=e.some(n=>n.state==="invalid")?"invalid":e.some(n=>n.state==="missing")?"missing":e.some(n=>n.state==="stale")?"stale":"fresh",t=e.filter(n=>n.state===r);return {state:r,reason:r==="fresh"?`${e.length} configured shader scene${e.length===1?" is":"s are"} fresh.`:t.map(n=>`${n.scene}: ${n.reason}`).join("; ")}}a(Ar,"classifyMatrix");function Dr(e,r){let t=e.tool;if(!t)return "Shader receipt has no public tool compatibility metadata.";if(t.compatibility!==r)return "Shader receipt targets a different runtime compatibility contract.";if(t.transform!==b)return "Shader receipt uses a different provider transform version.";if(t.address!==SHADER_ADDRESS_SCHEMA_VERSION||t.recipe!==SHADER_RECIPE_SCHEMA_VERSION||t.hydration!==SHADER_HYDRATION_SCHEMA_VERSION)return "Shader receipt uses incompatible address, recipe, or hydration schemas."}a(Dr,"exactToolCompatibility");function _r(e,r){let t=Object.keys(r).filter(s=>Object.hasOwn(e,s)&&e[s]!==r[s]),n=Object.keys(r).filter(s=>!Object.hasOwn(e,s)),i=Object.keys(e).filter(s=>!Object.hasOwn(r,s));return {...t.length>0?{changedInputs:t}:{},...n.length>0?{addedInputs:n}:{},...i.length>0?{removedInputs:i}:{}}}a(_r,"inputChanges");async function we(e=process.cwd(),r){let t=await e$1(e),n=await f(t),i$1=P.join(t,b$1),s=a(()=>({schemaVersion:1,root:t,state:"missing",reason:`${b$1}/meta.json is absent.`,scenes:n.scenes.map(a=>({scene:a.key,state:"missing",reason:"No committed shader receipt."}))}),"missing");if(!await d(i$1)||!await d(P.join(i$1,"meta.json")))return s();try{let a=await i(t,i$1,"Shader artifact directory"),l=await j(a,P.join(a,"meta.json"),a$1.receipt,"Shader receipt"),u=c$1(JSON.parse(l.data.toString("utf8"))),f=await e$2(a,l.data),w=r??await se(t),o=a$3(w.three),h=new Set(n.scenes.map(p=>p.key)),b=Object.keys(u.scenes).filter(p=>!h.has(p));if(b.length>0)throw new Error(`Shader receipt contains unconfigured scenes: ${b.join(", ")}.`);let x=Dr(u,o);if(x)throw new Error(x);let E=u.runtime.three!==w.three||u.runtime.threeBlocks!==w.threeBlocks,O=u.runtime.threeBlocksShaderClosure!==w.threeBlocksShaderClosure,C=u.tool?.version!==a$4,A=P.join(t,n.publicDir??"public"),$=[];for(let p of n.scenes){let c$1=u.scenes[p.key];if(!c$1){$.push({scene:p.key,state:"missing",reason:"Scene is absent from the complete receipt matrix."});continue}let M=await j(a,P.join(a,c$1.artifact),a$1.manifest,"Shader manifest");if(c(M.data)!==c$1.artifactHash)throw new Error(`Shader artifact checksum differs for scene "${p.key}".`);if(c$1.asset!==void 0&&c$1.assetHash!==void 0){let N=await j(A,P.join(A,c$1.asset),a$1.manifest,"Static shader manifest");if(c(N.data)!==c$1.assetHash)throw new Error(`Static shader manifest checksum differs for scene "${p.key}".`)}if(c$1.bytes!==void 0&&c$1.bytes!==M.data.byteLength)throw new Error(`Shader artifact byte count differs for scene "${p.key}".`);let S=rr(M.data.toString("utf8"),M.path,p.key,{three:u.runtime.three,threeBlocks:u.runtime.threeBlocks,compatibility:o,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION});if(!jr(S,c$1.coverage))throw new Error(`Shader coverage differs for scene "${p.key}".`);if(!n.allowLiveBuilds&&c$1.skipped&&c$1.skipped.render+c$1.skipped.compute>0)throw new Error(`Scene "${p.key}" contains skipped live builds but allowLiveBuilds is false.`);let j$1=await me(t,p.inputs),v=_r(c$1.inputs,j$1),g=(v.changedInputs?.length??0)+(v.addedInputs?.length??0)+(v.removedInputs?.length??0),y=E||O||C||g>0,T=f?.scenes[p.key],F=T===void 0||f===void 0?void 0:{...T,schemaVersion:f.schemaVersion,measuredAt:f.measuredAt,source:f.source,...f.source==="committed-capture"?{adapter:f.adapter,platform:f.platform}:{}};$.push({scene:p.key,state:y?"stale":"fresh",reason:E?"Installed runtime versions differ from the receipt.":O?"Installed three-blocks/shaders runtime closure differs from the receipt.":C?`Receipt was generated by @three-blocks/devtools ${u.tool?.version??"unknown"}.`:g>0?`${g} semantic shader input${g===1?"":"s"} changed.`:"Manifest, runtime, schemas, transform, and semantic inputs match.",coverage:S,...!y&&F!==void 0&&F.builds===S.render+S.compute?{timing:F}:{},...v});}let I=Ar($),L=I.state==="fresh"&&f!==void 0&&$.every(p=>p.timing!==void 0)?f:void 0;return {schemaVersion:1,root:t,...I,scenes:$,runtime:w,receipt:u,...L===void 0?{}:{timing:L}}}catch(a){let l=a instanceof Error?a.message:String(a);return {schemaVersion:1,root:t,state:"invalid",reason:l,scenes:n.scenes.map(u=>({scene:u.key,state:"invalid",reason:l}))}}}a(we,"inspectShaderMatrix");var dr=".three-blocks/shaders/pending-capture";function Nr(e){return (e instanceof Error?`${e.name}: ${e.message}`:String(e)).includes("ShaderHydrationError:")}a(Nr,"isShaderHydrationFailure");async function Vr(e,r,t){if(r.length===0)return;let n=P.join(e,b$1,"meta.json"),i=await readFile(n);if(c(i)!==c(t))throw new Error("Shader receipt changed before failed scenes could be marked for recapture.");let s=c$1(JSON.parse(i.toString("utf8"))),a=c(t),l=new Set(r),u=c$1({...s,scenes:Object.fromEntries(Object.entries(s.scenes).map(([f,w])=>[f,l.has(f)?{...w,inputs:{...w.inputs,[dr]:a}}:w]))});await f$1(n,`${d$1(u)}
10
- `);}a(Vr,"markShaderScenesForRecapture");function Hr(e,r){return d$1(e)===d$1(r)}a(Hr,"equalSnapshot");async function Rt(e={}){let r=e.root?await realpath(e.root):await e$1(e.start),t=e.config===void 0?await h$1(r):void 0,n=e.config??t?.config??await f(r),i=e.runtime??await se(r),s=n.scenes,a$1,l={},u;if(e.ifStale){let S=await we(r,i);if(S.state==="fresh"&&S.scenes.every(j=>j.timing!==void 0))return {schemaVersion:1,root:r,skipped:true,reason:S.reason,scenes:[]};if(S.state!=="invalid"&&S.receipt!==void 0){let j=S.state==="fresh";s=n.scenes.filter(v=>{let g=S.scenes.find(y=>y.scene===v.key);return g?.state!=="fresh"||j&&g.timing===void 0}),a$1=S.receipt;for(let v of S.scenes){if(v.state!=="fresh"||v.timing===void 0)continue;let{builds:g,liveBuildMs:y,precompiledBuildMs:T,avoidedBuildMs:F,runs:N,spreadMs:q}=v.timing;l[v.scene]={builds:g,liveBuildMs:y,precompiledBuildMs:T,avoidedBuildMs:F,runs:N,spreadMs:q},v.timing.source==="committed-capture"&&v.timing.adapter!==void 0&&v.timing.platform!==void 0&&(u={adapter:v.timing.adapter,platform:v.timing.platform});}}}let f$1=performance.now(),w=a$1!==void 0&&(a$1.runtime.three!==i.three||a$1.runtime.threeBlocks!==i.threeBlocks||a$1.runtime.threeBlocksShaderClosure!==i.threeBlocksShaderClosure||a$1.tool?.version!==a$4)?c(d$1({runtime:a$1.runtime,tool:a$1.tool})):void 0,o=a(async()=>new Map(await Promise.all(n.scenes.map(async S=>[S.key,await me(r,S.inputs)]))),"snapshotInputs"),h=await o(),m=a(async()=>{let S=await o();for(let j of n.scenes){let v=h.get(j.key),g=S.get(j.key);if(v===void 0||g===void 0||!Hr(v,g))throw new Error(`Semantic shader inputs changed during capture for scene "${j.key}"; the current scene was not committed.`)}},"assertInputsUnchanged"),b=e.driver===void 0,x=e.driver===void 0&&e.driverKind===void 0&&e.serve===void 0&&e.url===void 0?await g(r):void 0,E=e.serve??x?.serve,O=e.driverKind??x?.driverKind??(E===void 0?"vite":"static");if(e.url!==void 0&&(e.serve!==void 0||e.driverKind!==void 0))throw new Error("--url cannot be combined with --driver or --serve.");if(O==="vite"&&E!==void 0)throw new Error("--serve requires the static shader driver.");if(O==="static"&&E===void 0&&e.driver===void 0)throw new Error("The static shader driver requires --serve <built-directory>.");let C=e.driver===void 0?await import('./shader-browser-SZJLKYYT.js'):void 0,A=e.driver??(e.url!==void 0?C.createAttachedPlaywrightShaderDriver({root:r,runtime:i,url:e.url,...e.headed!==void 0?{headed:e.headed}:{}}):O==="static"?C.createStaticPlaywrightShaderDriver({root:r,runtime:i,serve:E,...e.headed!==void 0?{headed:e.headed}:{}}):C.createPlaywrightShaderDriver({root:r,runtime:i,...e.headed!==void 0?{headed:e.headed}:{}})),$=new Map,I=[],L=a$1!==void 0&&n.scenes.every(S=>a$1?.scenes[S.key]!==void 0),p=a$1,c$1,M=e.attempts??2;if(!Number.isSafeInteger(M)||M<1||M>5)throw new Error("Shader capture attempts must be an integer in 1...5.");try{for(let[g,y]of s.entries()){e.onSceneStart?.(y.key,g,s.length);let T,F,N=0;for(;N<M;N++)try{if(T=c$2(await A.capture(y,n),{scene:y.key,runtime:i}),T.skipped.length>0&&!n.allowLiveBuilds)throw new Error(`Scene "${y.key}" contains ${T.skipped.length} unregistered live shader build${T.skipped.length===1?"":"s"} while allowLiveBuilds is false.`);break}catch(q){F=q,T=void 0,N+1<M&&e.onSceneRetry?.(y.key,N+2,M,n.timeoutMs,q);}if(!T)throw new Error(`Shader capture "${y.key}" failed after ${M} attempts: ${F instanceof Error?F.message:String(F)}`);if($.set(y.key,T),I.push({scene:y.key,attempts:N+1,coverage:T.coverage,skipped:T.skipped.length,startupBuilds:T.stats.registeredBuilds,startupBuildMs:T.stats.buildMs,...T.timing===void 0?{}:{timing:T.timing}}),L&&p!==void 0){await m();let q=new Map(n.scenes.map(W=>{let re=W.key===y.key?h.get(W.key):p?.scenes[W.key]?.inputs;if(re===void 0)throw new Error(`Shader checkpoint is missing scene "${W.key}".`);return w!==void 0&&!$.has(W.key)&&(re={...re,[dr]:w}),[W.key,re]}));c$1=await j$1({root:r,scenes:n.scenes,captures:new Map([[y.key,T]]),runtime:i,inputs:q,previousReceipt:p,publicDirectory:n.publicDir??"public"}),p=c$1.receipt;}}await m(),c$1??=await j$1({root:r,scenes:n.scenes,captures:$,runtime:i,inputs:h,...a$1===void 0?{}:{previousReceipt:a$1},publicDirectory:n.publicDir??"public"});let S={...l};for(let g of I)S[g.scene]={builds:g.coverage.render+g.coverage.compute,setupMeasured:!1,liveBuildMs:g.startupBuildMs,precompiledBuildMs:0,avoidedBuildMs:g.startupBuildMs,runs:1,spreadMs:0};if(e.commitTiming===!0){let g=u??{adapter:$.values().next().value?.provenance?.adapter??"WebGPU adapter",platform:`${ve.platform()}/${ve.arch()}`};await i$1(r,S,await(A.timingEnvironment?.()??g));}else await f$2(r,S);let j=await readFile(P.join(c$1.directory,"meta.json")),v=await e$2(c$1.directory,j);return {schemaVersion:1,root:r,skipped:!1,reason:`Wrote ${I.length} shader scene${I.length===1?"":"s"}.`,durationMs:performance.now()-f$1,scenes:I,measurement:{beforeBuilds:I.reduce((g,y)=>g+y.startupBuilds,0),afterBuilds:0,firstFrameDeltaMs:-I.reduce((g,y)=>g+y.startupBuildMs,0),source:"capture-build-phase"},...t===void 0?{}:{configuration:{created:t.created,file:t.file}},written:c$1,...v===void 0?{}:{timing:v}}}finally{b&&await A.close();}}a(Rt,"captureShaders");function Wr(e){return ["workerReady","assetsReady",...e.requiresText?["textReady"]:[],"compileEnd","firstFrame"]}a(Wr,"requiredReadiness");function ar(e){if(e.length===0)throw new Error("Cannot take the median of an empty shader timing capture.");let r=[...e].sort((s,a)=>s-a),t=Math.floor(r.length/2),n=r[t];if(n===void 0)throw new Error("Shader timing median is unavailable.");if(r.length%2===1)return n;let i=r[t-1];if(i===void 0)throw new Error("Shader timing median pair is unavailable.");return (i+n)/2}a(ar,"median");function De(e,r,t,n){if(e.scene!==r.key||e.mode!==t)throw new Error(`Browser observation identity differs for scene "${r.key}".`);if(e.compatibility!==n||e.transform!==b)throw new Error(`Browser observation compatibility differs for scene "${r.key}".`);let i=Wr(r).filter(s=>e.readiness[s]!==true);if(i.length>0)throw new Error(`Scene "${r.key}" ${t} observation is missing readiness bits: ${i.join(", ")}.`);if(e.errors.length>0)throw new Error(`Scene "${r.key}" ${t} browser errors:
10
+ `);}a(Vr,"markShaderScenesForRecapture");function Hr(e,r){return d$1(e)===d$1(r)}a(Hr,"equalSnapshot");async function Rt(e={}){let r=e.root?await realpath(e.root):await e$1(e.start),t=e.config===void 0?await h$1(r):void 0,n=e.config??t?.config??await f(r),i=e.runtime??await se(r),s=n.scenes,a$1,l={},u;if(e.ifStale){let S=await we(r,i);if(S.state==="fresh"&&S.scenes.every(j=>j.timing!==void 0))return {schemaVersion:1,root:r,skipped:true,reason:S.reason,scenes:[]};if(S.state!=="invalid"&&S.receipt!==void 0){let j=S.state==="fresh";s=n.scenes.filter(v=>{let g=S.scenes.find(y=>y.scene===v.key);return g?.state!=="fresh"||j&&g.timing===void 0}),a$1=S.receipt;for(let v of S.scenes){if(v.state!=="fresh"||v.timing===void 0)continue;let{builds:g,liveBuildMs:y,precompiledBuildMs:T,avoidedBuildMs:F,runs:N,spreadMs:q}=v.timing;l[v.scene]={builds:g,liveBuildMs:y,precompiledBuildMs:T,avoidedBuildMs:F,runs:N,spreadMs:q},v.timing.source==="committed-capture"&&v.timing.adapter!==void 0&&v.timing.platform!==void 0&&(u={adapter:v.timing.adapter,platform:v.timing.platform});}}}let f$1=performance.now(),w=a$1!==void 0&&(a$1.runtime.three!==i.three||a$1.runtime.threeBlocks!==i.threeBlocks||a$1.runtime.threeBlocksShaderClosure!==i.threeBlocksShaderClosure||a$1.tool?.version!==a$4)?c(d$1({runtime:a$1.runtime,tool:a$1.tool})):void 0,o=a(async()=>new Map(await Promise.all(n.scenes.map(async S=>[S.key,await me(r,S.inputs)]))),"snapshotInputs"),h=await o(),m=a(async()=>{let S=await o();for(let j of n.scenes){let v=h.get(j.key),g=S.get(j.key);if(v===void 0||g===void 0||!Hr(v,g))throw new Error(`Semantic shader inputs changed during capture for scene "${j.key}"; the current scene was not committed.`)}},"assertInputsUnchanged"),b=e.driver===void 0,x=e.driver===void 0&&e.driverKind===void 0&&e.serve===void 0&&e.url===void 0?await g(r):void 0,E=e.serve??x?.serve,O=e.driverKind??x?.driverKind??(E===void 0?"vite":"static");if(e.url!==void 0&&(e.serve!==void 0||e.driverKind!==void 0))throw new Error("--url cannot be combined with --driver or --serve.");if(O==="vite"&&E!==void 0)throw new Error("--serve requires the static shader driver.");if(O==="static"&&E===void 0&&e.driver===void 0)throw new Error("The static shader driver requires --serve <built-directory>.");let C=e.driver===void 0?await import('./shader-browser-IGGE5DDE.js'):void 0,A=e.driver??(e.url!==void 0?C.createAttachedPlaywrightShaderDriver({root:r,runtime:i,url:e.url,...e.headed!==void 0?{headed:e.headed}:{}}):O==="static"?C.createStaticPlaywrightShaderDriver({root:r,runtime:i,serve:E,...e.headed!==void 0?{headed:e.headed}:{}}):C.createPlaywrightShaderDriver({root:r,runtime:i,...e.headed!==void 0?{headed:e.headed}:{}})),$=new Map,I=[],L=a$1!==void 0&&n.scenes.every(S=>a$1?.scenes[S.key]!==void 0),p=a$1,c$1,M=e.attempts??2;if(!Number.isSafeInteger(M)||M<1||M>5)throw new Error("Shader capture attempts must be an integer in 1...5.");try{for(let[g,y]of s.entries()){e.onSceneStart?.(y.key,g,s.length);let T,F,N=0;for(;N<M;N++)try{if(T=c$2(await A.capture(y,n),{scene:y.key,runtime:i}),T.skipped.length>0&&!n.allowLiveBuilds)throw new Error(`Scene "${y.key}" contains ${T.skipped.length} unregistered live shader build${T.skipped.length===1?"":"s"} while allowLiveBuilds is false.`);break}catch(q){F=q,T=void 0,N+1<M&&e.onSceneRetry?.(y.key,N+2,M,n.timeoutMs,q);}if(!T)throw new Error(`Shader capture "${y.key}" failed after ${M} attempts: ${F instanceof Error?F.message:String(F)}`);if($.set(y.key,T),I.push({scene:y.key,attempts:N+1,coverage:T.coverage,skipped:T.skipped.length,startupBuilds:T.stats.registeredBuilds,startupBuildMs:T.stats.buildMs,...T.timing===void 0?{}:{timing:T.timing}}),L&&p!==void 0){await m();let q=new Map(n.scenes.map(W=>{let re=W.key===y.key?h.get(W.key):p?.scenes[W.key]?.inputs;if(re===void 0)throw new Error(`Shader checkpoint is missing scene "${W.key}".`);return w!==void 0&&!$.has(W.key)&&(re={...re,[dr]:w}),[W.key,re]}));c$1=await j$1({root:r,scenes:n.scenes,captures:new Map([[y.key,T]]),runtime:i,inputs:q,previousReceipt:p,publicDirectory:n.publicDir??"public"}),p=c$1.receipt;}}await m(),c$1??=await j$1({root:r,scenes:n.scenes,captures:$,runtime:i,inputs:h,...a$1===void 0?{}:{previousReceipt:a$1},publicDirectory:n.publicDir??"public"});let S={...l};for(let g of I)S[g.scene]={builds:g.coverage.render+g.coverage.compute,setupMeasured:!1,liveBuildMs:g.startupBuildMs,precompiledBuildMs:0,avoidedBuildMs:g.startupBuildMs,runs:1,spreadMs:0};if(e.commitTiming===!0){let g=u??{adapter:$.values().next().value?.provenance?.adapter??"WebGPU adapter",platform:`${ve.platform()}/${ve.arch()}`};await i$1(r,S,await(A.timingEnvironment?.()??g));}else await f$2(r,S);let j=await readFile(P.join(c$1.directory,"meta.json")),v=await e$2(c$1.directory,j);return {schemaVersion:1,root:r,skipped:!1,reason:`Wrote ${I.length} shader scene${I.length===1?"":"s"}.`,durationMs:performance.now()-f$1,scenes:I,measurement:{beforeBuilds:I.reduce((g,y)=>g+y.startupBuilds,0),afterBuilds:0,firstFrameDeltaMs:-I.reduce((g,y)=>g+y.startupBuildMs,0),source:"capture-build-phase"},...t===void 0?{}:{configuration:{created:t.created,file:t.file}},written:c$1,...v===void 0?{}:{timing:v}}}finally{b&&await A.close();}}a(Rt,"captureShaders");function Wr(e){return ["workerReady","assetsReady",...e.requiresText?["textReady"]:[],"compileEnd","firstFrame"]}a(Wr,"requiredReadiness");function ar(e){if(e.length===0)throw new Error("Cannot take the median of an empty shader timing capture.");let r=[...e].sort((s,a)=>s-a),t=Math.floor(r.length/2),n=r[t];if(n===void 0)throw new Error("Shader timing median is unavailable.");if(r.length%2===1)return n;let i=r[t-1];if(i===void 0)throw new Error("Shader timing median pair is unavailable.");return (i+n)/2}a(ar,"median");function De(e,r,t,n){if(e.scene!==r.key||e.mode!==t)throw new Error(`Browser observation identity differs for scene "${r.key}".`);if(e.compatibility!==n||e.transform!==b)throw new Error(`Browser observation compatibility differs for scene "${r.key}".`);let i=Wr(r).filter(s=>e.readiness[s]!==true);if(i.length>0)throw new Error(`Scene "${r.key}" ${t} observation is missing readiness bits: ${i.join(", ")}.`);if(e.errors.length>0)throw new Error(`Scene "${r.key}" ${t} browser errors:
11
11
  - ${e.errors.join(`
12
- - `)}`)}a(De,"assertObservation");function Kr(e,r,t,n){if(r.render>0&&t.stats.registeredRenderBuilds===0)throw new Error(`Scene "${e.key}" live baseline exercised no registered render pipeline.`);if(r.compute>0&&t.stats.registeredComputeBuilds===0)throw new Error(`Scene "${e.key}" live baseline exercised no registered compute kernel.`);cr(e,r,n);}a(Kr,"assertZeroBuild");function cr(e,r,t){if(t.stats.registeredRenderBuilds!==0||t.stats.registeredComputeBuilds!==0){let n=t.stats.missedKeys??[];throw new Error(`Scene "${e.key}" injected path performed ${t.stats.registeredRenderBuilds} render and ${t.stats.registeredComputeBuilds} compute registered live builds.`+(n.length>0?` Missed keys: ${n.join(", ")}.`:""))}if(r.render>0&&t.stats.injectedRender===0)throw new Error(`Scene "${e.key}" injected no render entries.`);if(r.compute>0&&t.stats.injectedCompute===0)throw new Error(`Scene "${e.key}" injected no compute entries.`);if(t.stats.missed!==0||t.stats.missedRender!==0||t.stats.missedCompute!==0)throw new Error(`Scene "${e.key}" injected path reported shader manifest misses.`)}a(cr,"assertPrecompiledZeroBuild");async function zr(e,r,t,n,i){let s=P.join(e,c$3);if(await d(s)){let l=await lstat(s);if(l.isSymbolicLink()||!l.isDirectory())throw new Error("Shader parity artifact directory is not a real directory.")}else await mkdir(s,{recursive:true});let a=[`${r}.live.png`,`${r}.precompiled.png`,`${r}.diff.png`];return await Promise.all([t,n,i].map(async(l,u)=>{let f=a[u];if(f===void 0)throw new Error("Parity artifact mapping failed.");let w=P.join(s,f);if(await d(w)){let o=await lstat(w);if(o.isSymbolicLink()||!o.isFile())throw new Error(`Shader parity target is not a regular file: ${f}.`)}await writeFile(w,l,{mode:384});})),a.map(l=>`${c$3}/${l}`)}a(zr,"writeParityFailure");async function xt(e={}){let r=e.root?await realpath(e.root):await e$1(e.start),t=e.runtime??await se(r),n=a$3(t.three),i=await we(r,t);if(i.state!=="fresh")throw new Error(`Shader no-GPU validation is ${i.state}: ${i.reason}`);if(e.skipBrowser)return {schemaVersion:1,root:r,noGpu:i,browser:"skipped",scenes:[]};if(e.parityOnly===true&&e.commitTiming===true)throw new Error("Parity-only shader verification cannot commit timing.");let s=e.runs??5;if(!Number.isSafeInteger(s)||s<1||s>100)throw new Error("Shader timing runs must be an integer in 1...100.");let a$1=e.config??await f(r),l=await readFile(P.join(r,b$1,"meta.json")),u=c$1(JSON.parse(l.toString("utf8")));if(i.receipt===void 0||d$1(u)!==d$1(i.receipt))throw new Error("Shader receipt changed after no-GPU validation; restart browser parity verification.");let f$1=e.driver===void 0,w=e.driver===void 0&&e.driverKind===void 0&&e.serve===void 0&&e.url===void 0?await g(r):void 0,o=e.serve??w?.serve,h=e.driverKind??w?.driverKind??(o===void 0?"vite":"static");if(e.url!==void 0&&(e.serve!==void 0||e.driverKind!==void 0))throw new Error("--url cannot be combined with --driver or --serve.");if(h==="vite"&&o!==void 0)throw new Error("--serve requires the static shader driver.");if(h==="static"&&o===void 0&&e.driver===void 0)throw new Error("The static shader driver requires --serve <built-directory>.");let m=e.driver===void 0?await import('./shader-browser-SZJLKYYT.js'):void 0,{compareShaderScreenshots:b}=await import('./shader-parity-XPKQQK26.js'),x=a(()=>e.url!==void 0?m.createAttachedPlaywrightShaderDriver({root:r,runtime:t,url:e.url,...e.headed!==void 0?{headed:e.headed}:{}}):h==="static"?m.createStaticPlaywrightShaderDriver({root:r,runtime:t,serve:o,...e.headed!==void 0?{headed:e.headed}:{}}):m.createPlaywrightShaderDriver({root:r,runtime:t,...e.headed!==void 0?{headed:e.headed}:{}}),"createDriver"),E=e.driver??x(),O=e.driver??x();await h$2(r,a$1.scenes.map(L=>L.key),l);let C=[],A={},$=[],I=new Set;try{for(let[p,c]of a$1.scenes.entries()){e.onSceneStart?.(c.key,p,a$1.scenes.length);let M=i.scenes.find(B=>B.scene===c.key);if(!M?.coverage)throw new Error(`Fresh receipt has no coverage for scene "${c.key}".`);let S=M.coverage,j=a(async B=>{let te=B?"live":"precompiled",G=B?"precompiled":"live",Y=B?E:O,oe=B?O:E,K=await Y.observe(c,te,a$1),de=await oe.observe(c,G,a$1,K.frame),k=K.mode==="live"?K:de,X=K.mode==="precompiled"?K:de;De(k,c,"live",n),De(X,c,"precompiled",n),Kr(c,S,k,X);let Fe=a(async(fr,Le,Ne)=>{let V=b(Le,Ne,a$1.parity.channelTolerance,c.maxDiffRatio??a$1.parity.maxDiffRatio);if(V.matches)return V;let hr=await zr(r,c.key,Le,Ne,V.diff),mr=V.nonBlack?`${V.differentPixels}/${V.totalPixels} pixels differ (${(V.diffRatio*100).toFixed(3)}%).`:`rendered output is black (live=${V.baselineLuminance.toFixed(4)}, precompiled=${V.precompiledLuminance.toFixed(4)}).`;throw new Error(`Shader ${fr} parity failed for scene "${c.key}" at completed frames live=${k.frame}, precompiled=${X.frame}: ${mr} Artifacts: ${hr.join(", ")}`)},"compare");await Fe("first frame",k.firstFrameScreenshot,X.firstFrameScreenshot);let ur=await Fe("settled",k.screenshot,X.screenshot);return {live:k,precompiled:X,parity:ur}},"observePair"),v,g,y;if(e.parityOnly===!0)try{v=await j(!0);}catch(B){Nr(B)&&I.add(c.key),$.push({scene:c.key,error:B}),e.onSceneError?.(c.key,B);continue}else {await j(!0);let B=[];for(let k=0;k<s;k++)B.push(await j(k%2===0));let te=B[B.length-1];if(te===void 0)throw new Error(`Shader timing produced no runs for scene "${c.key}".`);if(v=te,g=await O.observePublished(c,a$1),De(g,c,"precompiled",n),cr(c,S,g),y=c.runtimeMotion?b(g.beforeScreenshot,g.screenshot,a$1.parity.channelTolerance,1):void 0,y&&y.diffRatio<1e-4)throw new Error(`Published scene "${c.key}" stopped animating during its normal 120-frame soak (changed ${y.differentPixels}/${y.totalPixels} canvas pixels).`);let G=a(k=>k.stats.buildMs+(k.stats.precompiledSetupMs??0)+(k.stats.hydrationMs??0),"observedNodeBuilderMs"),Y=ar(B.map(k=>G(k.live))),oe=ar(B.map(k=>G(k.precompiled))),K=Math.max(0,Y-oe),de=B.map(k=>Math.max(0,G(k.live)-G(k.precompiled)));A[c.key]={builds:S.render+S.compute,setupMeasured:!0,liveBuildMs:Y,precompiledBuildMs:oe,avoidedBuildMs:K,runs:s,spreadMs:Math.max(...de.map(k=>Math.abs(k-K)))};}let{diff:T,...F}=v.parity,{firstFrameScreenshot:N,screenshot:q,...W}=v.live,{firstFrameScreenshot:re,screenshot:Ur,...lr}=v.precompiled,be;if(g!==void 0){let{beforeScreenshot:B,firstFrameScreenshot:te,screenshot:G,...Y}=g;be=Y;}C.push({scene:c.key,coverage:S,live:W,precompiled:lr,...be===void 0?{}:{published:be},parity:F,...y===void 0?{}:{runtimeMotion:{differentPixels:y.differentPixels,totalPixels:y.totalPixels,diffRatio:y.diffRatio}}}),await g$1(r,[c.key],l);}if(e.parityOnly===!0){if(await Vr(r,[...I],l),$.length>0)throw new Error(`Shader parity failed for ${$.length}/${a$1.scenes.length} scene(s):
12
+ - `)}`)}a(De,"assertObservation");function Kr(e,r,t,n){if(r.render>0&&t.stats.registeredRenderBuilds===0)throw new Error(`Scene "${e.key}" live baseline exercised no registered render pipeline.`);if(r.compute>0&&t.stats.registeredComputeBuilds===0)throw new Error(`Scene "${e.key}" live baseline exercised no registered compute kernel.`);cr(e,r,n);}a(Kr,"assertZeroBuild");function cr(e,r,t){if(t.stats.registeredRenderBuilds!==0||t.stats.registeredComputeBuilds!==0){let n=t.stats.missedKeys??[];throw new Error(`Scene "${e.key}" injected path performed ${t.stats.registeredRenderBuilds} render and ${t.stats.registeredComputeBuilds} compute registered live builds.`+(n.length>0?` Missed keys: ${n.join(", ")}.`:""))}if(r.render>0&&t.stats.injectedRender===0)throw new Error(`Scene "${e.key}" injected no render entries.`);if(r.compute>0&&t.stats.injectedCompute===0)throw new Error(`Scene "${e.key}" injected no compute entries.`);if(t.stats.missed!==0||t.stats.missedRender!==0||t.stats.missedCompute!==0)throw new Error(`Scene "${e.key}" injected path reported shader manifest misses.`)}a(cr,"assertPrecompiledZeroBuild");async function zr(e,r,t,n,i){let s=P.join(e,c$3);if(await d(s)){let l=await lstat(s);if(l.isSymbolicLink()||!l.isDirectory())throw new Error("Shader parity artifact directory is not a real directory.")}else await mkdir(s,{recursive:true});let a=[`${r}.live.png`,`${r}.precompiled.png`,`${r}.diff.png`];return await Promise.all([t,n,i].map(async(l,u)=>{let f=a[u];if(f===void 0)throw new Error("Parity artifact mapping failed.");let w=P.join(s,f);if(await d(w)){let o=await lstat(w);if(o.isSymbolicLink()||!o.isFile())throw new Error(`Shader parity target is not a regular file: ${f}.`)}await writeFile(w,l,{mode:384});})),a.map(l=>`${c$3}/${l}`)}a(zr,"writeParityFailure");async function xt(e={}){let r=e.root?await realpath(e.root):await e$1(e.start),t=e.runtime??await se(r),n=a$3(t.three),i=await we(r,t);if(i.state!=="fresh")throw new Error(`Shader no-GPU validation is ${i.state}: ${i.reason}`);if(e.skipBrowser)return {schemaVersion:1,root:r,noGpu:i,browser:"skipped",scenes:[]};if(e.parityOnly===true&&e.commitTiming===true)throw new Error("Parity-only shader verification cannot commit timing.");let s=e.runs??5;if(!Number.isSafeInteger(s)||s<1||s>100)throw new Error("Shader timing runs must be an integer in 1...100.");let a$1=e.config??await f(r),l=await readFile(P.join(r,b$1,"meta.json")),u=c$1(JSON.parse(l.toString("utf8")));if(i.receipt===void 0||d$1(u)!==d$1(i.receipt))throw new Error("Shader receipt changed after no-GPU validation; restart browser parity verification.");let f$1=e.driver===void 0,w=e.driver===void 0&&e.driverKind===void 0&&e.serve===void 0&&e.url===void 0?await g(r):void 0,o=e.serve??w?.serve,h=e.driverKind??w?.driverKind??(o===void 0?"vite":"static");if(e.url!==void 0&&(e.serve!==void 0||e.driverKind!==void 0))throw new Error("--url cannot be combined with --driver or --serve.");if(h==="vite"&&o!==void 0)throw new Error("--serve requires the static shader driver.");if(h==="static"&&o===void 0&&e.driver===void 0)throw new Error("The static shader driver requires --serve <built-directory>.");let m=e.driver===void 0?await import('./shader-browser-IGGE5DDE.js'):void 0,{compareShaderScreenshots:b}=await import('./shader-parity-XPKQQK26.js'),x=a(()=>e.url!==void 0?m.createAttachedPlaywrightShaderDriver({root:r,runtime:t,url:e.url,...e.headed!==void 0?{headed:e.headed}:{}}):h==="static"?m.createStaticPlaywrightShaderDriver({root:r,runtime:t,serve:o,...e.headed!==void 0?{headed:e.headed}:{}}):m.createPlaywrightShaderDriver({root:r,runtime:t,...e.headed!==void 0?{headed:e.headed}:{}}),"createDriver"),E=e.driver??x(),O=e.driver??x();await h$2(r,a$1.scenes.map(L=>L.key),l);let C=[],A={},$=[],I=new Set;try{for(let[p,c]of a$1.scenes.entries()){e.onSceneStart?.(c.key,p,a$1.scenes.length);let M=i.scenes.find(B=>B.scene===c.key);if(!M?.coverage)throw new Error(`Fresh receipt has no coverage for scene "${c.key}".`);let S=M.coverage,j=a(async B=>{let te=B?"live":"precompiled",G=B?"precompiled":"live",Y=B?E:O,oe=B?O:E,K=await Y.observe(c,te,a$1),de=await oe.observe(c,G,a$1,K.frame),k=K.mode==="live"?K:de,X=K.mode==="precompiled"?K:de;De(k,c,"live",n),De(X,c,"precompiled",n),Kr(c,S,k,X);let Fe=a(async(fr,Le,Ne)=>{let V=b(Le,Ne,a$1.parity.channelTolerance,c.maxDiffRatio??a$1.parity.maxDiffRatio);if(V.matches)return V;let hr=await zr(r,c.key,Le,Ne,V.diff),mr=V.nonBlack?`${V.differentPixels}/${V.totalPixels} pixels differ (${(V.diffRatio*100).toFixed(3)}%).`:`rendered output is black (live=${V.baselineLuminance.toFixed(4)}, precompiled=${V.precompiledLuminance.toFixed(4)}).`;throw new Error(`Shader ${fr} parity failed for scene "${c.key}" at completed frames live=${k.frame}, precompiled=${X.frame}: ${mr} Artifacts: ${hr.join(", ")}`)},"compare");await Fe("first frame",k.firstFrameScreenshot,X.firstFrameScreenshot);let ur=await Fe("settled",k.screenshot,X.screenshot);return {live:k,precompiled:X,parity:ur}},"observePair"),v,g,y;if(e.parityOnly===!0)try{v=await j(!0);}catch(B){Nr(B)&&I.add(c.key),$.push({scene:c.key,error:B}),e.onSceneError?.(c.key,B);continue}else {await j(!0);let B=[];for(let k=0;k<s;k++)B.push(await j(k%2===0));let te=B[B.length-1];if(te===void 0)throw new Error(`Shader timing produced no runs for scene "${c.key}".`);if(v=te,g=await O.observePublished(c,a$1),De(g,c,"precompiled",n),cr(c,S,g),y=c.runtimeMotion?b(g.beforeScreenshot,g.screenshot,a$1.parity.channelTolerance,1):void 0,y&&y.diffRatio<1e-4)throw new Error(`Published scene "${c.key}" stopped animating during its normal 120-frame soak (changed ${y.differentPixels}/${y.totalPixels} canvas pixels).`);let G=a(k=>k.stats.buildMs+(k.stats.precompiledSetupMs??0)+(k.stats.hydrationMs??0),"observedNodeBuilderMs"),Y=ar(B.map(k=>G(k.live))),oe=ar(B.map(k=>G(k.precompiled))),K=Math.max(0,Y-oe),de=B.map(k=>Math.max(0,G(k.live)-G(k.precompiled)));A[c.key]={builds:S.render+S.compute,setupMeasured:!0,liveBuildMs:Y,precompiledBuildMs:oe,avoidedBuildMs:K,runs:s,spreadMs:Math.max(...de.map(k=>Math.abs(k-K)))};}let{diff:T,...F}=v.parity,{firstFrameScreenshot:N,screenshot:q,...W}=v.live,{firstFrameScreenshot:re,screenshot:Ur,...lr}=v.precompiled,be;if(g!==void 0){let{beforeScreenshot:B,firstFrameScreenshot:te,screenshot:G,...Y}=g;be=Y;}C.push({scene:c.key,coverage:S,live:W,precompiled:lr,...be===void 0?{}:{published:be},parity:F,...y===void 0?{}:{runtimeMotion:{differentPixels:y.differentPixels,totalPixels:y.totalPixels,diffRatio:y.diffRatio}}}),await g$1(r,[c.key],l);}if(e.parityOnly===!0){if(await Vr(r,[...I],l),$.length>0)throw new Error(`Shader parity failed for ${$.length}/${a$1.scenes.length} scene(s):
13
13
  `+$.map(p=>{let c=p.error instanceof Error?p.error.message:String(p.error);return ` - ${p.scene}: ${c}`}).join(`
14
14
  `));return {schemaVersion:1,root:r,noGpu:i,browser:"passed",scenes:C}}if(e.commitTiming===!0){let p={adapter:"WebGPU adapter",platform:`${ve.platform()}/${ve.arch()}`},c=await(E.timingEnvironment?.()??p),M=await i$1(r,A,c);return {schemaVersion:1,root:r,noGpu:i,browser:"passed",scenes:C,timing:M.local,committedTiming:M.committed}}let L=await f$2(r,A);return {schemaVersion:1,root:r,noGpu:i,browser:"passed",scenes:C,timing:L}}finally{f$1&&(await O.close(),await E.close());}}a(xt,"testShaders");export{rr as a,me as b,se as c,we as d,Rt as e,xt as f};
@@ -1 +1 @@
1
- import {R,S}from'./chunk-RQEPJ6GC.js';import {a}from'./chunk-EI7MMDWY.js';import {existsSync,readFileSync,readFile}from'fs';import {createRequire}from'module';import d from'path';var m="@three-blocks/devtools/webpack-loader";function y(e){if(typeof e=="string")return e===m;if(Array.isArray(e))return e.some(y);if(e===null||typeof e!="object")return false;let o=e;return o.loader===m||y(o.use)}a(y,"webpackRuleUsesShaderLoader");function T(e){let o=b(process.cwd()),r=a(t=>x(o,t),"exact"),n={...e.resolve?.alias,...r("three")===void 0?{}:{three$:r("three")},...r("three/webgpu")===void 0?{}:{"three/webgpu$":r("three/webgpu")},...r("three/tsl")===void 0?{}:{"three/tsl$":r("three/tsl")},"three/addons":d.join(o.root,"examples/jsm"),"three/examples/jsm":d.join(o.root,"examples/jsm")};return {...e,resolve:{...e.resolve,alias:n}}}a(T,"withTargetThreeAliases");function w(e){let o=T(e),r=o.module?.rules??[];return r.some(y)?o:{...o,module:{...o.module,rules:[...r,{enforce:"pre",test:/three[\\/]build[\\/]three\.webgpu\.js$/u,use:[{loader:m}]}]}}}a(w,"withShaderWebpackRule");function A(e){return w(e)}a(A,"withThreeBlocksWebpack");function B(e){let r=e.webpack;return {...e,webpack(n,...t){let s=r?.call(this,n,...t)??n,i=t[0];return i!==null&&typeof i=="object"&&Reflect.get(i,"isServer")===true?T(s):w(s)}}}a(B,"withThreeBlocksNext");function b(e){let o;try{o=createRequire(d.join(d.resolve(e),"package.json")).resolve("three");}catch(s){throw new Error("The shader adapter could not resolve Three.js from the target project.",{cause:s})}let r=d.dirname(o),n,t;for(;;){let s=d.join(r,"package.json");if(existsSync(s)){let l=JSON.parse(readFileSync(s,"utf8"));if(l.name==="three"){n=s,t=l;break}}let i=d.dirname(r);if(i===r)break;r=i;}if(n===void 0)throw new Error(`The shader adapter could not locate Three.js package metadata from ${o}.`);if(typeof t?.version!="string"||t.version.length===0)throw new Error(`The resolved Three.js package has no version: ${n}`);return {root:d.dirname(n),version:t.version,exports:t.exports}}a(b,"resolveThreePackage");function L(e=process.cwd()){return b(e).version}a(L,"resolveShaderAdapterThreeVersion");function v(e){return {version:e.threeVersion??L(e.root),capture:e.capture??process.env.THREE_BLOCKS_SHADER_TOOL==="1"}}a(v,"resolvedOptions");function _(e,o,r={}){if(!R(o))return null;let n=v(r);return S(e,n.version,{instrumentCapture:n.capture})}a(_,"transformThreeWebGPUModule");function g(e){if(typeof e=="string")return e;if(Array.isArray(e)){for(let r of e){let n=g(r);if(n!==void 0)return n}return}if(e===null||typeof e!="object")return;let o=e;for(let r of ["browser","import","default"]){let n=g(o[r]);if(n!==void 0)return n}}a(g,"exportTarget");function x(e,o){if(e.exports===null||typeof e.exports!="object")return;let r=e.exports,n=o==="three"?".":`./${o.slice(6)}`,t=g(r[n]);if(t!==void 0)return d.resolve(e.root,t);for(let[s,i]of Object.entries(r)){let l=s.indexOf("*");if(l<0)continue;let c=s.slice(0,l),u=s.slice(l+1);if(!n.startsWith(c)||!n.endsWith(u))continue;let f=n.slice(c.length,n.length-u.length),p=g(i);if(p!==void 0)return d.resolve(e.root,p.replaceAll("*",f))}}a(x,"resolveThreeExport");function $(e={}){let o=e.root??process.cwd(),r=b(o),n={version:e.threeVersion??r.version,capture:e.capture??process.env.THREE_BLOCKS_SHADER_TOOL==="1"};return {name:"three-blocks-shader-provider",setup(t){t.onResolve?.({filter:/^three(?:\/.*)?$/},s=>{let i=x(r,s.path);return i===void 0?void 0:{path:i}}),t.onLoad({filter:/three[\\/]build[\\/]three\.webgpu\.js$/},async s=>{let i=await new Promise((c,u)=>{readFile(s.path,"utf8",(f,p)=>{f?u(f):c(p);});});return {contents:S(i,n.version,{instrumentCapture:n.capture}).code,loader:"js"}});}}}a($,"createEsbuildShaderPlugin");function H(e={}){let o=v(e);return {name:"three-blocks-shader-provider",enforce:"pre",transform(r,n){return R(n)?{code:S(r,o.version,{instrumentCapture:o.capture}).code,map:null}:null}}}a(H,"createRollupShaderPlugin");export{m as a,A as b,B as c,L as d,_ as e,$ as f,H as g};
1
+ import {R,S}from'./chunk-2JE5VZXK.js';import {a}from'./chunk-EI7MMDWY.js';import {existsSync,readFileSync,readFile}from'fs';import {createRequire}from'module';import d from'path';var m="@three-blocks/devtools/webpack-loader";function y(e){if(typeof e=="string")return e===m;if(Array.isArray(e))return e.some(y);if(e===null||typeof e!="object")return false;let o=e;return o.loader===m||y(o.use)}a(y,"webpackRuleUsesShaderLoader");function T(e){let o=b(process.cwd()),r=a(t=>x(o,t),"exact"),n={...e.resolve?.alias,...r("three")===void 0?{}:{three$:r("three")},...r("three/webgpu")===void 0?{}:{"three/webgpu$":r("three/webgpu")},...r("three/tsl")===void 0?{}:{"three/tsl$":r("three/tsl")},"three/addons":d.join(o.root,"examples/jsm"),"three/examples/jsm":d.join(o.root,"examples/jsm")};return {...e,resolve:{...e.resolve,alias:n}}}a(T,"withTargetThreeAliases");function w(e){let o=T(e),r=o.module?.rules??[];return r.some(y)?o:{...o,module:{...o.module,rules:[...r,{enforce:"pre",test:/three[\\/]build[\\/]three\.webgpu\.js$/u,use:[{loader:m}]}]}}}a(w,"withShaderWebpackRule");function A(e){return w(e)}a(A,"withThreeBlocksWebpack");function B(e){let r=e.webpack;return {...e,webpack(n,...t){let s=r?.call(this,n,...t)??n,i=t[0];return i!==null&&typeof i=="object"&&Reflect.get(i,"isServer")===true?T(s):w(s)}}}a(B,"withThreeBlocksNext");function b(e){let o;try{o=createRequire(d.join(d.resolve(e),"package.json")).resolve("three");}catch(s){throw new Error("The shader adapter could not resolve Three.js from the target project.",{cause:s})}let r=d.dirname(o),n,t;for(;;){let s=d.join(r,"package.json");if(existsSync(s)){let l=JSON.parse(readFileSync(s,"utf8"));if(l.name==="three"){n=s,t=l;break}}let i=d.dirname(r);if(i===r)break;r=i;}if(n===void 0)throw new Error(`The shader adapter could not locate Three.js package metadata from ${o}.`);if(typeof t?.version!="string"||t.version.length===0)throw new Error(`The resolved Three.js package has no version: ${n}`);return {root:d.dirname(n),version:t.version,exports:t.exports}}a(b,"resolveThreePackage");function L(e=process.cwd()){return b(e).version}a(L,"resolveShaderAdapterThreeVersion");function v(e){return {version:e.threeVersion??L(e.root),capture:e.capture??process.env.THREE_BLOCKS_SHADER_TOOL==="1"}}a(v,"resolvedOptions");function _(e,o,r={}){if(!R(o))return null;let n=v(r);return S(e,n.version,{instrumentCapture:n.capture})}a(_,"transformThreeWebGPUModule");function g(e){if(typeof e=="string")return e;if(Array.isArray(e)){for(let r of e){let n=g(r);if(n!==void 0)return n}return}if(e===null||typeof e!="object")return;let o=e;for(let r of ["browser","import","default"]){let n=g(o[r]);if(n!==void 0)return n}}a(g,"exportTarget");function x(e,o){if(e.exports===null||typeof e.exports!="object")return;let r=e.exports,n=o==="three"?".":`./${o.slice(6)}`,t=g(r[n]);if(t!==void 0)return d.resolve(e.root,t);for(let[s,i]of Object.entries(r)){let l=s.indexOf("*");if(l<0)continue;let c=s.slice(0,l),u=s.slice(l+1);if(!n.startsWith(c)||!n.endsWith(u))continue;let f=n.slice(c.length,n.length-u.length),p=g(i);if(p!==void 0)return d.resolve(e.root,p.replaceAll("*",f))}}a(x,"resolveThreeExport");function $(e={}){let o=e.root??process.cwd(),r=b(o),n={version:e.threeVersion??r.version,capture:e.capture??process.env.THREE_BLOCKS_SHADER_TOOL==="1"};return {name:"three-blocks-shader-provider",setup(t){t.onResolve?.({filter:/^three(?:\/.*)?$/},s=>{let i=x(r,s.path);return i===void 0?void 0:{path:i}}),t.onLoad({filter:/three[\\/]build[\\/]three\.webgpu\.js$/},async s=>{let i=await new Promise((c,u)=>{readFile(s.path,"utf8",(f,p)=>{f?u(f):c(p);});});return {contents:S(i,n.version,{instrumentCapture:n.capture}).code,loader:"js"}});}}}a($,"createEsbuildShaderPlugin");function H(e={}){let o=v(e);return {name:"three-blocks-shader-provider",enforce:"pre",transform(r,n){return R(n)?{code:S(r,o.version,{instrumentCapture:o.capture}).code,map:null}:null}}}a(H,"createRollupShaderPlugin");export{m as a,A as b,B as c,L as d,_ as e,$ as f,H as g};