@three-blocks/devtools 1.0.0-alpha.190.g3ffe5c0ecc9c → 1.0.0-alpha.193.g4eb273dec3a7

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.
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+ import {b,c}from'./chunk-NE7SC2BX.js';import {a as a$3}from'./chunk-ZT6T2W4B.js';import {a as a$2,c as c$2}from'./chunk-ZDNZCQUQ.js';import {a as a$1,c as c$1,d,f,e,i,j,k}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import _ from'process';import {createServer}from'http';import {createRequire}from'module';import {mkdtemp,rm,lstat,readFile,unlink,mkdir,readdir,realpath}from'fs/promises';import y from'path';import {tmpdir}from'os';import {pathToFileURL}from'url';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 {transformThreeWebgpuProviderHooks,transformThreeWebgpuCaptureInstrumentation}from'three-blocks/vite';function T(r){if(/^0\.185\./u.test(r))return THREE_WEBGPU_R185_COMPATIBILITY;if(r===THREE_R186DEV_VERSION)return THREE_WEBGPU_R186DEV_COMPATIBILITY;throw new Error(`Three.js ${r} is outside the supported shader compatibility contracts.`)}a(T,"shaderCompatibilityForThree");var O=52,Ae="timing.local.json",je="timing.json",de="parity.json",Q=4096,lr=4096;function se(r,e,t=8192){if(typeof r!="string"||r.length===0||r.length>t||/[\u0000\u007f]/u.test(r))throw new Error(`${e} must be a bounded non-empty string.`);return r}a(se,"boundedString");function S(r,e,t=true){if(typeof r!="number"||!Number.isFinite(r)||r<0||t&&!Number.isSafeInteger(r))throw new Error(`${e} must be a non-negative ${t?"integer":"finite number"}.`);return r}a(S,"nonNegativeNumber");function pr(r){if(!a$2(r))throw new Error("Shader capture stats are missing.");let e={buildCalls:S(r.buildCalls,"capture stats.buildCalls"),renderBuilds:S(r.renderBuilds,"capture stats.renderBuilds"),computeBuilds:S(r.computeBuilds,"capture stats.computeBuilds"),registeredBuilds:S(r.registeredBuilds,"capture stats.registeredBuilds"),registeredRenderBuilds:S(r.registeredRenderBuilds,"capture stats.registeredRenderBuilds"),registeredComputeBuilds:S(r.registeredComputeBuilds,"capture stats.registeredComputeBuilds"),buildMs:S(r.buildMs,"capture stats.buildMs",false),syncBuildMs:S(r.syncBuildMs,"capture stats.syncBuildMs",false),asyncBuildElapsedMs:S(r.asyncBuildElapsedMs,"capture stats.asyncBuildElapsedMs",false),precompiledSetupMs:S(r.precompiledSetupMs,"capture stats.precompiledSetupMs",false),maxSyncBuildMs:S(r.maxSyncBuildMs??r.syncBuildMs,"capture stats.maxSyncBuildMs",false),maxPrecompiledSetupMs:S(r.maxPrecompiledSetupMs??r.precompiledSetupMs,"capture stats.maxPrecompiledSetupMs",false),hydrationMs:S(r.hydrationMs??0,"capture stats.hydrationMs",false),maxHydrationMs:S(r.maxHydrationMs??r.hydrationMs??0,"capture stats.maxHydrationMs",false),injected:S(r.injected,"capture stats.injected"),injectedRender:S(r.injectedRender,"capture stats.injectedRender"),injectedCompute:S(r.injectedCompute,"capture stats.injectedCompute"),missed:S(r.missed,"capture stats.missed"),missedRender:S(r.missedRender,"capture stats.missedRender"),missedCompute:S(r.missedCompute,"capture stats.missedCompute"),...Array.isArray(r.missedKeys)&&r.missedKeys.every(t=>typeof t=="string")?{missedKeys:r.missedKeys.slice(0,Q)}:{}};if(e.renderBuilds+e.computeBuilds!==e.buildCalls||e.registeredRenderBuilds+e.registeredComputeBuilds!==e.registeredBuilds||e.injectedRender+e.injectedCompute!==e.injected||e.missedRender+e.missedCompute!==e.missed||e.registeredBuilds>e.buildCalls||Math.abs(e.syncBuildMs+e.asyncBuildElapsedMs-e.buildMs)>.001||e.maxSyncBuildMs>e.syncBuildMs+.001||e.maxPrecompiledSetupMs>e.precompiledSetupMs+.001||e.maxHydrationMs>e.hydrationMs+.001)throw new Error("Shader capture stats totals are inconsistent.");return e}a(pr,"captureStats");function mr(r){if(!Array.isArray(r)||r.length>Q)throw new Error("Shader capture skipped builds are invalid.");return r.map((e,t)=>{if(!a$2(e)||e.kind!=="render"&&e.kind!=="compute")throw new Error(`Shader capture skipped build ${t} is invalid.`);return {kind:e.kind,name:se(e.name,`skipped build ${t} name`,512),reason:se(e.reason,`skipped build ${t} reason`)}})}a(mr,"skippedBuilds");function hr(r){let e=0,t=0,n=0,i=0;for(let s of Object.values(r.entries)){let a=r.states[s];a!==void 0&&((a.vertex!==null||a.fragment!==null)&&e++,a.vertex!==null&&t++,a.fragment!==null&&n++,a.compute!==null&&i++);}return {render:e,vertex:t,fragment:n,compute:i}}a(hr,"shaderCoverage");function it(r,e){if(!a$2(r))throw new Error("Shader capture payload must be an object.");if(r.scene!==e.scene)throw new Error(`Shader capture scene does not match "${e.scene}".`);if(r.protocolVersion!==2)throw new Error("Shader capture protocolVersion must be 2.");let t=T(e.runtime.three);if(r.compatibility!==t)throw new Error(`Shader capture compatibility must be "${t}".`);if(!a$2(r.entries))throw new Error("Shader capture entries must be an object.");if(typeof r.requiresSetup!="boolean")throw new Error("Shader capture requiresSetup must be boolean.");let n=Object.keys(r.entries).length;if(n===0||n>Q)throw new Error(`Shader capture must contain 1...${Q} entries.`);if(!Array.isArray(r.errors)||r.errors.length>lr)throw new Error("Shader capture errors are invalid.");let i=r.errors.map((p,o)=>se(p,`capture error ${o}`,64*1024));if(i.length>0)throw new Error(`Shader capture failed:
3
+ - ${i.join(`
4
+ - `)}`);let s=mr(r.skipped),a=pr(r.stats),d=a$2(r.timing)?r.timing:void 0,u=d===void 0?void 0:Object.fromEntries(["launch","firstRequest","readiness","lastBuild","settled","posted"].flatMap(p=>{let o=d[p];if(o===void 0)return [];if(typeof o!="number"||!Number.isFinite(o)||o<0)throw new Error(`Shader capture timing.${p} is invalid.`);return [[p,o]]})),m;if(r.provenance!==void 0){if(!a$2(r.provenance)||typeof r.provenance.userAgent!="string"||r.provenance.userAgent.length>1024||typeof r.provenance.adapter!="string"||r.provenance.adapter.length>1024||!Array.isArray(r.provenance.features)||r.provenance.features.length>256||!r.provenance.features.every(p=>typeof p=="string"&&p.length<=128))throw new Error("Shader capture provenance is invalid.");m={userAgent:r.provenance.userAgent,adapter:r.provenance.adapter,features:[...new Set(r.provenance.features)].sort()};}let h=parsePrecompiledManifest({version:PRECOMPILED_MANIFEST_VERSION,scene:e.scene,three:e.runtime.three,threeBlocks:e.runtime.threeBlocks,runtime:{id:t,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION},...r.automatic===void 0?{}:{automatic:r.automatic},requiresSetup:r.requiresSetup,modules:r.modules,nodes:r.nodes,layouts:r.layouts,attributePlans:r.attributePlans,updatePlans:r.updatePlans,requirementPlans:r.requirementPlans,states:r.states,entries:r.entries}),g=hr(h);if(a.registeredRenderBuilds<g.render||a.registeredComputeBuilds<g.compute)throw new Error("Shader capture did not live-build every distinct registered render/compute entry.");return {scene:e.scene,manifest:h,skipped:s,stats:a,coverage:g,...u===void 0?{}:{timing:u},...m===void 0?{}:{provenance:m}}}a(it,"validateShaderCapture");function B(r,e=0){let t=" ".repeat(e),n=" ".repeat(e+1);if(Array.isArray(r))return r.length===0?"[]":r.every(s=>s===null||["number","string","boolean"].includes(typeof s))?JSON.stringify(r):`[
5
+ ${r.map(s=>`${n}${B(s,e+1)}`).join(`,
6
+ `)}
7
+ ${t}]`;if(r!==null&&typeof r=="object"){let s=r,a=Object.keys(s).sort();return a.length===0?"{}":`{
8
+ ${a.map(d=>{let u=s[d];return `${n}${JSON.stringify(d)}: ${B(u,e+1)}`}).join(`,
9
+ `)}
10
+ ${t}}`}let i=JSON.stringify(r);if(i===void 0)throw new Error("Shader artifact contains a non-serializable value.");return i}a(B,"stableStringify");function fr(r){return ["// GENERATED FILE \u2014 do not edit by hand.","// Produced by @three-blocks/devtools.","import type { PrecompiledManifest } from 'three-blocks/shaders';","",`export default ${B(r)} satisfies PrecompiledManifest;`,""].join(`
11
+ `)}a(fr,"serializeShaderManifest");function Te(r,e){if(typeof r!="string"||r.length===0||r.length>256||/[\u0000-\u001f\u007f]/u.test(r))throw new Error(`${e} is invalid.`);return r}a(Te,"timingLabel");function ae(r){if(!a$2(r)||r.schemaVersion!==3||r.source!=="latest-local-capture"&&r.source!=="committed-capture"||typeof r.receiptHash!="string"||!/^[a-f0-9]{64}$/u.test(r.receiptHash)||typeof r.measuredAt!="string"||!Number.isFinite(Date.parse(r.measuredAt))||!a$2(r.scenes))throw new Error("Shader timing is invalid.");let e={};for(let[n,i]of Object.entries(r.scenes)){if(n.length===0||n.length>128||!a$2(i))throw new Error("Shader timing scene is invalid.");let s={builds:S(i.builds,`timing ${n}.builds`),setupMeasured:i.setupMeasured===true,liveBuildMs:S(i.liveBuildMs,`timing ${n}.liveBuildMs`,false),precompiledBuildMs:S(i.precompiledBuildMs,`timing ${n}.precompiledBuildMs`,false),avoidedBuildMs:S(i.avoidedBuildMs,`timing ${n}.avoidedBuildMs`,false),runs:S(i.runs,`timing ${n}.runs`),spreadMs:S(i.spreadMs,`timing ${n}.spreadMs`,false)};if(s.runs<1)throw new Error(`Shader timing runs are invalid for scene "${n}".`);if(Math.abs(s.avoidedBuildMs-Math.max(0,s.liveBuildMs-s.precompiledBuildMs))>.001)throw new Error(`Shader timing delta is inconsistent for scene "${n}".`);e[n]=s;}if(Object.keys(e).length===0)throw new Error("Shader timing contains no scenes.");let t={schemaVersion:3,receiptHash:r.receiptHash,measuredAt:r.measuredAt,scenes:e};return r.source==="latest-local-capture"?{...t,source:"latest-local-capture"}:{...t,source:"committed-capture",adapter:Te(r.adapter,"Shader timing adapter"),platform:Te(r.platform,"Shader timing platform")}}a(ae,"parseShaderTiming");function X(r){return /^[a-z0-9][a-z0-9_-]{0,63}$/u.test(r)}a(X,"validParityScene");function Pe(r){return typeof r=="string"&&Number.isFinite(Date.parse(r))}a(Pe,"validParityTimestamp");function ce(r){if(!a$2(r))throw new Error("Shader parity evidence is invalid.");if(r.schemaVersion===1){if(typeof r.receiptHash!="string"||!/^[a-f0-9]{64}$/u.test(r.receiptHash)||!Pe(r.verifiedAt)||!Array.isArray(r.scenes)||r.scenes.length===0||r.scenes.length>64||!r.scenes.every(n=>typeof n=="string"&&X(n)))throw new Error("Shader parity evidence is invalid.");return {schemaVersion:1,receiptHash:r.receiptHash,verifiedAt:r.verifiedAt,scenes:[...new Set(r.scenes)].sort()}}if(r.schemaVersion!==2||!a$2(r.scenes))throw new Error("Shader parity evidence is invalid.");let e=Object.entries(r.scenes);if(e.length===0||e.length>64)throw new Error("Shader parity evidence is invalid.");let t={};for(let[n,i]of e.sort(([s],[a])=>s.localeCompare(a))){if(!X(n)||!a$2(i)||typeof i.fingerprint!="string"||!/^[a-f0-9]{64}$/u.test(i.fingerprint)||!Pe(i.verifiedAt))throw new Error("Shader parity evidence is invalid.");t[n]={fingerprint:i.fingerprint,verifiedAt:i.verifiedAt};}return {schemaVersion:2,scenes:t}}a(ce,"parseShaderParityEvidence");function oe(r,e){let t=r.scenes[e];if(t===void 0)throw new Error(`Shader receipt has no scene "${e}" for parity evidence.`);return c$1(B({runtime:{three:r.runtime.three,threeBlocks:r.runtime.threeBlocks,threeBlocksShaderClosure:r.runtime.threeBlocksShaderClosure},...r.tool===void 0?{}:{tool:r.tool},scene:t}))}a(oe,"shaderSceneParityFingerprint");async function ke(r,e,t,n){let i=y.join(r,t);try{if(!await d(i))return;let s=await lstat(i);if(s.isSymbolicLink()||!s.isFile()||s.size>1024*1024)return;let a=ae(JSON.parse(await readFile(i,"utf8")));return a.source===n&&a.receiptHash===c$1(e)?a:void 0}catch{return}}a(ke,"readShaderTimingFile");async function st(r,e){return await ke(r,e,Ae,"latest-local-capture")??await ke(r,e,je,"committed-capture")}a(st,"readShaderTiming");async function Oe(r,e){let t=y.join(r,de);try{if(!await d(t))return;let n=await lstat(t);if(n.isSymbolicLink()||!n.isFile()||n.size>1024*1024)return;let i=ce(JSON.parse(await readFile(t,"utf8"))),s=c$2(JSON.parse(Buffer.from(e).toString("utf8"))),a={};if(i.schemaVersion===1){if(i.receiptHash!==c$1(e))return;for(let d of i.scenes)s.scenes[d]!==void 0&&(a[d]={fingerprint:oe(s,d),verifiedAt:i.verifiedAt});}else for(let[d,u]of Object.entries(i.scenes))s.scenes[d]===void 0||u.fingerprint!==oe(s,d)||(a[d]=u);return Object.keys(a).length===0?void 0:{schemaVersion:2,scenes:a}}catch{return}}a(Oe,"readShaderParityEvidence");async function Ie(r,e,t){let n=await Z(r),i=y.join(n,"meta.json"),s=await lstat(i);if(s.isSymbolicLink()||!s.isFile())throw new Error("Shader receipt must be a regular file before timing.");let a=await readFile(i),d=new Date().toISOString(),u=Object.fromEntries(Object.entries(e).sort(([g],[p])=>g.localeCompare(p))),m=ae({schemaVersion:3,receiptHash:c$1(a),measuredAt:d,source:"latest-local-capture",scenes:u});if(await f(y.join(n,Ae),`${B(m)}
12
+ `),t===void 0)return {local:m};let h=ae({schemaVersion:3,receiptHash:c$1(a),measuredAt:d,source:"committed-capture",adapter:t.adapter,platform:t.platform,scenes:u});return await f(y.join(n,je),`${B(h)}
13
+ `),{local:m,committed:h}}a(Ie,"writeShaderTimings");async function at(r,e){return (await Ie(r,e)).local}a(at,"writeShaderLocalTiming");async function ot(r,e,t){if(e.length===0||e.length>64||e.some(p=>!X(p)))throw new Error("Shader parity evidence must contain 1...64 valid scene keys.");let n=await Z(r),i=y.join(n,"meta.json"),s=await lstat(i);if(s.isSymbolicLink()||!s.isFile())throw new Error("Shader receipt must be a regular file before parity evidence.");let a=await readFile(i);if(t!==void 0&&c$1(a)!==c$1(t))throw new Error("Shader receipt changed during browser parity verification; completed observations were not attached to the new receipt.");let d=c$2(JSON.parse(a.toString("utf8"))),u=await Oe(n,a),m=new Date().toISOString(),h={...u?.scenes};for(let p of [...new Set(e)].sort())h[p]={fingerprint:oe(d,p),verifiedAt:m};let g=ce({schemaVersion:2,scenes:h});return await f(y.join(n,de),`${B(g)}
14
+ `),g}a(ot,"writeShaderParityEvidence");async function dt(r,e,t){if(e.length===0||e.length>64||e.some(h=>!X(h)))throw new Error("Shader parity invalidation must contain 1...64 valid scene keys.");let n=await Z(r),i=await readFile(y.join(n,"meta.json"));if(c$1(i)!==c$1(t))throw new Error("Shader receipt changed before prior parity evidence could be invalidated.");let s=await Oe(n,i);if(s===void 0)return;let a=new Set(e),d=Object.fromEntries(Object.entries(s.scenes).filter(([h])=>!a.has(h))),u=y.join(n,de);if(Object.keys(d).length===0){await unlink(u).catch(h=>{if(!a$2(h)||h.code!=="ENOENT")throw h});return}let m=ce({schemaVersion:2,scenes:d});await f(u,`${B(m)}
15
+ `);}a(dt,"removeShaderParityEvidence");async function ct(r,e,t){let n=await Ie(r,e,t);if(n.committed===void 0)throw new Error("Committed shader timing was not written.");return {local:n.local,committed:n.committed}}a(ct,"writeShaderTimingTwins");async function Ce(r){if(!await d(r)){await mkdir(r);return}let e=await lstat(r);if(e.isSymbolicLink()||!e.isDirectory())throw new Error(`Shader artifact path is not a real directory: ${r}.`)}a(Ce,"assertDirectory");async function Z(r){let e=y.resolve(r),t=y.join(e,".three-blocks");await Ce(t);let n=y.join(t,"shaders");return await Ce(n),n}a(Z,"artifactRoot");async function ut(r){let e$1=await Z(r.root),t=T(r.runtime.three),n=y.resolve(r.root),i$1=y.resolve(n,r.publicDirectory??"public");if(!e(n,i$1)||i$1===n)throw new Error("Shader public directory must stay inside the project root.");let s=y.join(i$1,"three-blocks","shaders");await mkdir(s,{recursive:true}),await i(n,s,"Shader static-asset directory");let a={},d=[];for(let o of [...r.scenes].sort((l,f)=>l.key.localeCompare(f.key))){let l=r.captures.get(o.key),f$1=r.inputs.get(o.key);if(f$1===void 0)throw new Error(`Shader input matrix is missing scene "${o.key}".`);if(l===void 0){let E=r.previousReceipt?.scenes[o.key];if(E===void 0)throw new Error(`Capture matrix is missing scene "${o.key}".`);let F=await readFile(y.join(e$1,E.artifact));if(c$1(F)!==E.artifactHash)throw new Error(`Preserved shader artifact checksum differs for scene "${o.key}".`);if(E.asset!==void 0&&E.assetHash!==void 0){let N=await readFile(y.join(i$1,E.asset));if(c$1(N)!==E.assetHash)throw new Error(`Preserved static shader manifest checksum differs for scene "${o.key}".`)}a[o.key]={...E,inputs:Object.fromEntries(Object.entries(f$1).sort(([N],[z])=>N.localeCompare(z)))},d.push(E.artifact),E.asset!==void 0&&d.push(y.relative(n,y.join(i$1,E.asset)).split(y.sep).join("/"));continue}if(l.scene!==o.key||l.manifest.scene!==o.key)throw new Error(`Capture matrix scene "${o.key}" is inconsistent.`);let w=`${o.key}.webgpu.ts`,R=fr(l.manifest);await f(y.join(e$1,w),R),d.push(w);let P=`three-blocks/shaders/${o.key}.json`,k=`${B(l.manifest)}
16
+ `;await f(y.join(i$1,P),k),d.push(y.relative(n,y.join(i$1,P)).split(y.sep).join("/"));let J=l.skipped.filter(E=>E.kind==="render").length,C=l.skipped.length-J;a[o.key]={artifact:w,artifactHash:c$1(R),asset:P,assetHash:c$1(k),inputs:Object.fromEntries(Object.entries(f$1).sort(([E],[F])=>E.localeCompare(F))),coverage:l.coverage,bytes:Buffer.byteLength(R),skipped:{render:J,compute:C}};}let u=[...r.captures.values()].find(o=>o.provenance!==void 0)?.provenance??r.previousReceipt?.runtime.capture,m={schemaVersion:2,runtime:{...r.runtime,...u===void 0?{}:{capture:u}},tool:{name:"@three-blocks/devtools",version:a$3,compatibility:t,transform:O,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION},scenes:a},h=new Set(d);for(let o of await readdir(e$1,{withFileTypes:true}))if(!(!o.name.endsWith(".webgpu.ts")||h.has(o.name))){if(o.isSymbolicLink()||!o.isFile())throw new Error(`Orphan shader artifact is not a regular file: ${o.name}.`);await unlink(y.join(e$1,o.name));}let g=new Set(r.scenes.map(o=>`${o.key}.json`)),p=new Set(Object.values(r.previousReceipt?.scenes??{}).map(o=>o.asset===void 0?void 0:y.posix.basename(o.asset)).filter(o=>o!==void 0));try{let o=c$2(JSON.parse(await readFile(y.join(e$1,"meta.json"),"utf8")));for(let l of Object.values(o.scenes))l.asset!==void 0&&p.add(y.posix.basename(l.asset));}catch{}for(let o of await readdir(s,{withFileTypes:true}))if(!(!o.name.endsWith(".json")||g.has(o.name))&&p.has(o.name)){if(o.isSymbolicLink()||!o.isFile())throw new Error(`Orphan shader static asset is not a regular file: ${o.name}.`);await unlink(y.join(s,o.name));}return await f(y.join(e$1,"meta.json"),`${B(m)}
17
+ `),d.push("meta.json"),{directory:e$1,receipt:m,files:d}}a(ut,"writeShaderArtifacts");var Le="three-blocks.shader-capture.runtime.v1";var G;async function $(){G===void 0&&(G=(async()=>{let e=createRequire(y.join(process.cwd(),"package.json")).resolve("@three-blocks/devtools/browser/shader-capture"),t=y.resolve(y.dirname(e),"../..");return (await j(t,e,a$1.metadata,"Shader capture browser runtime")).data.toString("utf8")})());let r=G;try{return await r}catch(e){throw G===r&&(G=void 0),e}}a($,"loadShaderCaptureRuntimeSource");var De="virtual:three-blocks-shader-capture-client",$e="\0three-blocks:shader-capture-client",le="virtual:three-blocks-shader-capture-runtime",Fe="\0three-blocks:shader-capture-runtime";async function He(){let r=await $(),e=r.replace(/\bexport\{[^{}]*\};?\s*$/u,"");if(e===r)throw new Error("Shader capture browser runtime no longer has the expected final ESM export list.");return e}a(He,"loadShaderCaptureRuntimeScriptSource");function br(r){let e=r.split("?",1)[0];return e===void 0?false:e.split(y.sep).join("/").endsWith("/build/three.webgpu.js")}a(br,"isThreeWebGPUModule");function Ue(r){let e=/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/u.exec(r);return e?.[1]==="0"&&e[2]==="185"}a(Ue,"supportedVersion");function Er(r,e,t={}){if(!Ue(e))throw new Error(`Shader provider transform ${THREE_WEBGPU_R185_COMPATIBILITY} supports Three.js 0.185.x; received "${e}".`);let n=transformThreeWebgpuProviderHooks(r,{threeVersion:e,...t.threeRevision===void 0?{}:{threeRevision:t.threeRevision},id:"three/build/three.webgpu.js"}),i=n.state==="already-applied",s=n.code;return t.instrumentCapture&&(s=transformThreeWebgpuCaptureInstrumentation(s,{...t.captureRuntimeImport===void 0?{}:{runtimeImport:t.captureRuntimeImport}}).code),{code:s,alreadyPresent:i,captureApplied:t.instrumentCapture===true}}a(Er,"applyShaderProviderTransform");var Rr=/this\.trackTimestamp\s*=\s*\(\s*parameters\.trackTimestamp\s*===\s*true\s*\);/gu,vr="Object.defineProperty( this, 'trackTimestamp', { get: () => false, set: () => {} } );";function Ve(r,e={}){if(!Ue(r))throw new Error(`Shader provider transform ${THREE_WEBGPU_R185_COMPATIBILITY} supports Three.js 0.185.x; received "${r}".`);let t={seen:false,applied:false,alreadyPresent:false};return {plugin:{name:"three-blocks:shader-provider-transform",enforce:"pre",config(){return {optimizeDeps:{exclude:["three","three/webgpu","three/tsl"]},resolve:{dedupe:["three"]}}},resolveId(i){return e.capture&&i===De?$e:e.capture&&i===le?Fe:null},async load(i){return e.capture?i===Fe?$():i===$e?[`export * from '${le}';`,`import { configureThreeBlocksShaderCapture } from '${le}';`,`configureThreeBlocksShaderCapture( ${JSON.stringify({capture:e.capture.capture,forceLive:e.capture.forceLive,settleFrames:e.capture.settleFrames,settleTimeoutMs:e.capture.settleTimeoutMs,visibilityGuard:e.capture.visibilityGuard,captureId:e.capture.captureId,sessionKey:e.capture.sessionKey,token:e.capture.token,readiness:e.capture.readiness??{},transform:O})} );`].join(`
18
+ `):null:null},transform(i,s){if(!br(s))return null;t.seen=true,t.id=s;try{let a=Er(i,r,{instrumentCapture:e.capture!==void 0,...e.capture!==void 0?{captureRuntimeImport:De}:{}}),d=e.disableTimestampQueries===!0?a.code.replace(Rr,vr):a.code;if(e.disableTimestampQueries===!0&&d===a.code)throw new Error("Three.js timestamp tracking anchor drifted; refusing software WebGPU capture.");return t.applied=!0,t.alreadyPresent=a.alreadyPresent,t.captureApplied=a.captureApplied,d===i?null:{code:d,map:null}}catch(a){throw t.error=a instanceof Error?a.message:String(a),a}}},status:t}}a(Ve,"createShaderProviderTransform");function pe(r){if(r.error)throw new Error(r.error);if(!r.seen||!r.applied)throw new Error(`The version-gated shader provider transform was not applied (${r.seen?"module seen":"three/webgpu not seen"}).`)}a(pe,"assertShaderProviderTransform");var Qe="/__three-blocks/shaders/capture",te="/__three-blocks/shaders/telemetry",Xe="/__three-blocks/shaders/runtime.js",Ze="/__three-blocks/shaders/bootstrap.js",er="/__three-blocks/shaders/bridge.js",rr=a$1.manifest*2,fe=/^[a-z0-9][a-z0-9_-]{0,63}$/u,tr=64,nr=2e3,xr=[/is not valid JSON/iu,/WebGPU is experimental/iu];async function Ar(){try{return (await import('playwright')).chromium}catch(r){throw new Error('Shader browser work requires the optional "playwright" package. Install it in the project and run `npx playwright install chromium`.',{cause:r})}}a(Ar,"loadChromium");async function jr(r){let e;try{e=createRequire(y.join(r,"package.json")).resolve("vite");}catch(n){throw new Error("Shader capture requires Vite in the target project.",{cause:n})}let t=await import(pathToFileURL(e).href);if(typeof t.createServer!="function")throw new Error(`The target project's Vite entry does not export createServer(): ${e}`);return t.createServer}a(jr,"loadProjectCreateServer");var ye=class{static{a(this,"CaptureInbox");}#e=new Map;#r=new Map;wait(e,t){let n=this.#r.get(e);if(n!==void 0)return this.#r.delete(e),Promise.resolve(n);if(this.#e.has(e))throw new Error(`A shader capture is already waiting for scene "${e}".`);return new Promise((i,s)=>{let a=setTimeout(()=>{this.#e.delete(e),s(new Error(`Shader capture "${e}" timed out after ${t}ms.`));},t);this.#e.set(e,{resolve:i,reject:s,timer:a});})}receive(e){if(!a$2(e)||typeof e.scene!="string"||!fe.test(e.scene))throw new Error("Capture POST has no safe scene key.");if(!this.#r.has(e.scene)&&!this.#e.has(e.scene)&&this.#r.size>=tr)throw new Error("Capture POST exceeds the scene inbox limit.");let t=this.#e.get(e.scene);t?(clearTimeout(t.timer),this.#e.delete(e.scene),t.resolve(e)):this.#r.set(e.scene,e);}cancel(e,t){let n=this.#e.get(e);n&&(clearTimeout(n.timer),this.#e.delete(e),n.reject(t));}rejectAll(e){for(let t of this.#e.values())clearTimeout(t.timer),t.reject(e);this.#e.clear(),this.#r.clear();}};async function Or(r,e){let t=await Promise.race([e.then(n=>({kind:"capture",value:n})),r.then(()=>({kind:"navigation"}))]);return t.kind==="capture"?t.value:e}a(Or,"waitForShaderCaptureAcrossNavigation");var ge=class{static{a(this,"TelemetryHub");}#e=new Map;#r=new Map;markFirstRequest(e){fe.test(e)&&!this.#r.has(e)&&this.#r.set(e,Date.now());}firstRequest(e){return this.#r.get(e)}receive(e){if(!a$2(e)||typeof e.scene!="string"||!fe.test(e.scene))throw new Error("Shader telemetry has no bounded scene key.");if(!this.#e.has(e.scene)&&this.#e.size>=tr)throw new Error("Shader telemetry exceeds the scene limit.");this.#e.set(e.scene,e);}read(e){return this.#e.get(e)}clear(e){this.#e.delete(e),this.#r.delete(e);}},Ir=a(async(r,e,t,n,i)=>{let s=0;for(;r.__threeBlocksParityUsesAnimationLoop!==true&&s<e;)await n(),s+=1;if(r.__threeBlocksParityUsesAnimationLoop===true){let a=Number(r.__threeBlocksParityCompletedFrame||0),d=Number(t),u=Number.isSafeInteger(d)&&d>=a?d:a+e;for(r.__threeBlocksParityTargetFrame=u;Number(r.__threeBlocksParityCompletedFrame||0)<u;)await n();}return await i(),Number(r.__threeBlocksParityCompletedFrame||0)},"settleShaderParityFrames");function Se(r){return `(() => {
19
+ const root = globalThis;
20
+ const scene = new URL(location.href).searchParams.get('captureId')
21
+ || 'default';
22
+ const randomSeed = (value) => {
23
+ let state = 2166136261;
24
+ for (let index = 0; index < value.length; index++) state = Math.imul(state ^ value.charCodeAt(index), 16777619) >>> 0;
25
+ return state === 0 ? 0x9e3779b9 : state;
26
+ };
27
+ const advanceRandom = (state) => {
28
+ state ^= state << 13;
29
+ state ^= state >>> 17;
30
+ state ^= state << 5;
31
+ return state >>> 0;
32
+ };
33
+ const parityMode = new URL(location.href).searchParams.get('threeBlocksShaderMode');
34
+ if (parityMode === 'live' || parityMode === 'precompiled') {
35
+ root.__threeBlocksParityEpoch = 1700000000000;
36
+ root.__threeBlocksParityTime = 0;
37
+ Date.now = () => root.__threeBlocksParityEpoch + Number(root.__threeBlocksParityTime || 0);
38
+ }
39
+ const randomStreams = new Map();
40
+ Math.random = () => {
41
+ const stackLine = String(new Error().stack || '').split('\\n')[2] || 'unknown';
42
+ const originIndex = stackLine.indexOf(location.origin);
43
+ const callsite = (originIndex >= 0 ? stackLine.slice(0, originIndex) : stackLine).trim() || 'anonymous';
44
+ const next = advanceRandom(randomStreams.get(callsite) ?? randomSeed(scene + '|' + callsite));
45
+ randomStreams.set(callsite, next);
46
+ return next / 4294967296;
47
+ };
48
+ const readiness = { workerReady: false, assetsReady: false, textReady: false, compileEnd: false, firstFrame: false };
49
+ const stats = { buildCalls: 0, renderBuilds: 0, computeBuilds: 0, registeredBuilds: 0, registeredRenderBuilds: 0, registeredComputeBuilds: 0, buildMs: 0, syncBuildMs: 0, asyncBuildElapsedMs: 0, precompiledSetupMs: 0, maxSyncBuildMs: 0, maxPrecompiledSetupMs: 0, hydrationMs: 0, maxHydrationMs: 0, injected: 0, injectedRender: 0, injectedCompute: 0, missed: 0, missedRender: 0, missedCompute: 0, missedKeys: [] };
50
+ const settleParityFrames = ${Ir.toString()};
51
+ const settle = (frames, requestedTarget) => settleParityFrames(
52
+ root,
53
+ frames,
54
+ requestedTarget,
55
+ () => new Promise((resolve) => requestAnimationFrame(resolve)),
56
+ () => new Promise((resolve) => setTimeout(resolve, 100)),
57
+ );
58
+ const bridge = { protocolVersion: 1, compatibility: ${JSON.stringify(r)}, transform: ${O}, readiness, stats, settle };
59
+ root.__threeBlocksShaderTools = bridge;
60
+ requestAnimationFrame(() => requestAnimationFrame(() => { readiness.firstFrame = true; }));
61
+ const poll = async () => {
62
+ try {
63
+ const response = await fetch('/__three-blocks/shaders/telemetry?scene=' + encodeURIComponent(scene), { cache: 'no-store' });
64
+ if (response.status !== 204 && response.ok) {
65
+ const payload = await response.json();
66
+ if (payload.protocolVersion !== 1 || payload.compatibility !== bridge.compatibility || payload.transform !== bridge.transform) throw new Error('incompatible shader telemetry');
67
+ Object.assign(stats, payload.stats);
68
+ readiness.workerReady = true;
69
+ if (payload.settled === true) {
70
+ readiness.assetsReady = true;
71
+ readiness.textReady = true;
72
+ readiness.compileEnd = true;
73
+ }
74
+ const smoke = root.__threeBlocksSmoke && typeof root.__threeBlocksSmoke === 'object' ? root.__threeBlocksSmoke : { protocolVersion: 1, worker: { offscreenCanvas: true, visible: true }, readiness: {} };
75
+ smoke.readiness = { ...(smoke.readiness || {}), ...readiness };
76
+ root.__threeBlocksSmoke = smoke;
77
+ }
78
+ } catch {}
79
+ setTimeout(poll, 40);
80
+ };
81
+ void poll();
82
+ })();`}a(Se,"publicBridgeScript");function ir(r,e,t,n,i=false){let s=new URL(r.url??"/","http://three-blocks.invalid"),a=s.pathname;if(i&&r.method==="GET"&&/^\/three-blocks\/shaders\/[a-z0-9][a-z0-9_-]{0,63}\.json$/u.test(a))return e.statusCode=204,e.end(),true;if(a===te&&r.method==="GET"){let p=s.searchParams.get("scene")??"",o=n.read(p);return o===void 0?(e.statusCode=204,e.end()):(e.statusCode=200,e.setHeader("Content-Type","application/json"),e.end(JSON.stringify(o))),true}let d=a===Qe,u=a===te;if(!d&&!u)return false;if(r.method!=="POST")return e.statusCode=405,e.end("POST required"),true;let m=[],h=0,g=false;return r.on("data",p=>{h+=p.byteLength,h>rr?g=true:m.push(p);}),r.on("end",()=>{if(g){e.statusCode=413,e.end("capture payload too large");return}try{let p=JSON.parse(Buffer.concat(m).toString("utf8"));u?n.receive(p):t.receive(p),e.statusCode=204,e.end();}catch(p){e.statusCode=400,e.end(p instanceof Error?p.message:String(p));}}),true}a(ir,"handleCaptureEndpoint");function Lr(r,e,t,n){return {name:"three-blocks:shader-capture-endpoint",transformIndexHtml(){return [{tag:"script",children:Se(n),injectTo:"head-prepend"}]},configureServer(i){i.middlewares.use((s,a,d)=>{let m=new URL(s.url??"/","http://three-blocks.invalid").searchParams.get("captureId");m!==null&&e.markFirstRequest(m),!ir(s,a,r,e,t)&&d();});}}}a(Lr,"captureEndpointPlugin");function We(r,e,t){let n=new URL(e.url,r);for(let[i,s]of Object.entries(t))n.searchParams.set(i,s);return n.href}a(We,"browserUrl");function Dr(r,e){let t=new URL(e.url,r);for(let n of ["capture","precompiled"])t.searchParams.delete(n);return t.searchParams.set("captureId",e.key),t.searchParams.set("threeBlocksShaderMode","precompiled"),t.searchParams.set("tbStats","1"),t.href}a(Dr,"publishedBrowserUrl");function qe(r){return xr.some(e=>e.test(r))}a(qe,"knownNoise");async function L(r){let e;try{await Promise.race([r(),new Promise(t=>{e=setTimeout(t,nr);})]);}catch{}finally{e&&clearTimeout(e);}}a(L,"closeBrowserResource");async function Ke(r){let e;try{return await Promise.race([r().catch(()=>null),new Promise(t=>{e=setTimeout(()=>t(null),nr);})])}finally{e!==void 0&&clearTimeout(e);}}a(Ke,"readPageDiagnostic");function me(r){let e=a(()=>{},"resolveFirst"),t=new Promise(a=>{e=a;}),n={console:[],page:[],first:t},i=false,s=a(a=>{i||(i=true,e(new Error(a)));},"report");return r.on("console",a=>{let d=a.type()==="warning"&&/\[three-blocks\/shaders\].*(?:has no entry|manifest miss|hydration)/iu.test(a.text());if(a.type()!=="error"&&!d||qe(a.text()))return;let u=a.location().url,m=u.length>0?`${a.text()} (${u})`:a.text();n.console.push(m),s(`Browser console ${d?"warning":"error"}: ${m}`);}),r.on("pageerror",a=>{if(qe(a.message))return;let d=a.stack||a.message;n.page.push(d),s(`Browser page error: ${d}`);}),r.on("crash",()=>s("Browser page crashed before shader capture completed.")),r.on("close",()=>s("Browser page closed before shader capture completed.")),n}a(me,"collectErrors");function W(r,e,t=false){return typeof r[e]=="boolean"?r[e]:t}a(W,"booleanField");function $r(r){if(!a$2(r))throw new Error("Browser shader stats are unavailable.");let e=a((t,n=true)=>{let i=r[t];if(typeof i!="number"||!Number.isFinite(i)||i<0||n&&!Number.isSafeInteger(i))throw new Error(`Browser shader stats.${t} is invalid.`);return i},"read");return {buildCalls:e("buildCalls"),renderBuilds:e("renderBuilds"),computeBuilds:e("computeBuilds"),registeredBuilds:e("registeredBuilds"),registeredRenderBuilds:e("registeredRenderBuilds"),registeredComputeBuilds:e("registeredComputeBuilds"),buildMs:e("buildMs",false),syncBuildMs:e("syncBuildMs",false),asyncBuildElapsedMs:e("asyncBuildElapsedMs",false),precompiledSetupMs:e("precompiledSetupMs",false),maxSyncBuildMs:e("maxSyncBuildMs",false),maxPrecompiledSetupMs:e("maxPrecompiledSetupMs",false),hydrationMs:e("hydrationMs",false),maxHydrationMs:e("maxHydrationMs",false),injected:e("injected"),injectedRender:e("injectedRender"),injectedCompute:e("injectedCompute"),missed:e("missed"),missedRender:e("missedRender"),missedCompute:e("missedCompute"),...Array.isArray(r.missedKeys)&&r.missedKeys.every(t=>typeof t=="string")?{missedKeys:r.missedKeys}:{}}}a($r,"parseStats");function ee(r,e,t,n,i){if(!a$2(r))throw new Error("The page did not expose the public shader devtools bridge.");if(!t&&r.protocolVersion!==1)throw new Error(`Scene "${e.key}" exposed an unsupported shader bridge protocol.`);let s=r.readiness;if(!a$2(s))throw new Error("The shader bridge readiness snapshot is invalid.");let a={workerReady:W(s,"workerReady"),assetsReady:W(s,"assetsReady"),textReady:e.requiresText?W(s,"textReady"):true,compileEnd:W(s,"compileEnd"),firstFrame:W(s,"firstFrame",t)};if(!a.workerReady||!a.assetsReady||!a.textReady||!a.compileEnd)throw new Error(`Scene "${e.key}" did not reach worker/assets/text/compile readiness.`);let d=t?i:r.compatibility,u=t?O:r.transform;if(d!==i||u!==O)throw new Error(`Scene "${e.key}" exposed incompatible shader bridge metadata.`);return pe(n),{compatibility:i,transform:u,readiness:a,stats:$r(r.stats)}}a(ee,"parseBridge");async function re(r,e){return r.evaluate(t=>{let n=globalThis;if(!t)return n.__threeBlocksShaderTools??null;let i=n.__threeBlocks,s=n.__threeBlocksTslStats;if(!i||typeof i!="object")return null;let a=i;return {readiness:{workerReady:a.workerReady===true,assetsReady:a.loadEnd===true||a.assetsReady===true,textReady:a.textReady===true,compileEnd:a.compileEnd===true,firstFrame:true},stats:s}},e)}a(re,"readBridge");async function q(r,e,t,n){return r.evaluate(async i=>{let a$1=globalThis.__threeBlocksShaderTools;if(a$1&&typeof a$1=="object"){let m=Reflect.get(a$1,"settle");if(typeof m=="function"){let h=await m(i.frames,i.targetFrame);return typeof h=="number"&&Number.isSafeInteger(h)?h:0}}if(!i.legacy||!i.modulePath)throw new Error("The public shader bridge does not provide deterministic settle().");let d=await import(i.modulePath);if(!d.store||typeof d.store!="object")throw new Error("Legacy deterministic store is unavailable.");let u=d.store;return u.recordFrameCount=0,u.recordFrameRate=60,u.recordTotalFrames=i.frames,u.recording=true,await new Promise((m,h)=>{let g=Date.now(),p=a(()=>{if(u.recording===false)return m();if(Date.now()-g>i.timeoutMs)return h(new Error("Legacy deterministic settle timed out."));setTimeout(p,25);},"poll");p();}),0},{frames:t,targetFrame:n,legacy:e.bridge.legacyLab,modulePath:e.bridge.deterministicModule??null,timeoutMs:e.timeoutMs})}a(q,"settlePage");async function Je(r,e,t){e.readiness.selector===void 0&&e.readiness.global===void 0||await Promise.race([r.waitForFunction(n=>{let i=globalThis;if(n.selector!==void 0&&i.document?.querySelector(n.selector)==null)return false;if(n.global===void 0)return true;let s=i;for(let u of n.global.split(".")){if((typeof s!="object"||s===null)&&typeof s!="function")return false;s=Reflect.get(s,u);}if(s===true)return true;if(typeof s!="object"||s===null||typeof Reflect.get(s,"then")!="function")return false;let a=i.__threeBlocksReadinessState,d=a instanceof Map?a:new Map;return a instanceof Map||(i.__threeBlocksReadinessState=d),d.has(s)||(d.set(s,false),Promise.resolve(s).then(()=>d.set(s,true),()=>d.set(s,false))),d.get(s)===true},e.readiness,{timeout:e.timeoutMs}),t.first.then(n=>Promise.reject(n))]);}a(Je,"waitForConfiguredReadiness");async function ze(r){let e=r.locator("canvas"),n=(await e.evaluateAll(i=>i.map((s,a)=>{let d=s.getBoundingClientRect();return {index:a,area:Math.max(0,d.width)*Math.max(0,d.height)}}))).sort((i,s)=>s.area-i.area)[0];if(n===void 0||n.area<=0)throw new Error("Published page has no visible renderer canvas.");return Buffer.from(await e.nth(n.index).screenshot({type:"png"}))}a(ze,"primaryCanvasScreenshot");async function he(r,e,t,n,i,s){let a=sr(n,i),d=await He(),u=`(() => {
83
+ const runtime = globalThis[Symbol.for(${JSON.stringify(Le)})];
84
+ if (!runtime || typeof runtime.configureThreeBlocksShaderCapture !== 'function') {
85
+ throw new Error('@three-blocks/devtools attached shader capture runtime is incompatible.');
86
+ }
87
+ runtime.configureThreeBlocksShaderCapture(${JSON.stringify(a).replaceAll("<","\\u003c")});
88
+ })();`;await r.addInitScript({content:`${d}
89
+ ${u}`}),await r.addInitScript({content:Se(s)}),await r.route("**/*",async m=>{let h=m.request(),g=new URL(h.url()),p=g.pathname;if(h.method()==="GET"&&n!=="precompiled"&&/^\/three-blocks\/shaders\/[a-z0-9][a-z0-9_-]{0,63}\.json$/u.test(p)){await m.fulfill({status:204});return}if(p===te&&h.method()==="GET"){let f=t.read(g.searchParams.get("scene")??"");await m.fulfill(f===void 0?{status:204}:{status:200,contentType:"application/json",body:JSON.stringify(f)});return}let o=p===Qe,l=p===te;if((o||l)&&h.method()==="POST"){let f=h.postDataBuffer()??Buffer.alloc(0);if(f.byteLength>rr){await m.fulfill({status:413,body:"capture payload too large"});return}try{let w=JSON.parse(f.toString("utf8"));l?t.receive(w):e.receive(w),await m.fulfill({status:204});}catch(w){await m.fulfill({status:400,body:w instanceof Error?w.message:String(w)});}return}await m.continue();});}a(he,"configureAttachedContext");var Fr=Object.freeze({".avif":"image/avif",".css":"text/css; charset=utf-8",".gif":"image/gif",".html":"text/html; charset=utf-8",".ico":"image/x-icon",".jpeg":"image/jpeg",".jpg":"image/jpeg",".js":"text/javascript; charset=utf-8",".json":"application/json; charset=utf-8",".mjs":"text/javascript; charset=utf-8",".mp4":"video/mp4",".png":"image/png",".svg":"image/svg+xml",".wasm":"application/wasm",".webm":"video/webm",".webp":"image/webp",".woff":"font/woff",".woff2":"font/woff2"});function Nr(r){let e=[`<script src="${er}"></script>`,`<script type="module" src="${Ze}"></script>`].join(""),t=/<head(?:\s[^>]*)?>/iu.exec(r);return t===null?`${e}${r}`:`${r.slice(0,t.index+t[0].length)}${e}${r.slice(t.index+t[0].length)}`}a(Nr,"injectStaticShaderCaptureHtml");function Hr(r,e){let t=sr(r,e);return [`import { configureThreeBlocksShaderCapture } from ${JSON.stringify(Xe)};`,`configureThreeBlocksShaderCapture( ${JSON.stringify(t).replaceAll("<","\\u003c")} );`].join(`
90
+ `)}a(Hr,"staticCaptureBootstrap");function sr(r,e){return {capture:r==="capture",forceLive:r!=="precompiled",settleFrames:e.settleFrames,settleTimeoutMs:e.settleTimeoutMs??3e4,readiness:e.readiness,transform:O}}a(sr,"shaderCaptureConfiguration");async function Ur(r,e){let t=await k(r,e,a=>/\.(?:c|m)?js$/u.test(a),16384),n=false,i=false,s;for(let a of t){let d=(await j(r,a,a$1.texture,"Static application JavaScript")).data.toString("utf8");if(d.includes("nodeBuilderStateProvider")&&(n=true),d.includes("three-blocks.shader-capture.runtime.v1")&&(i=true,s??=a),n&&i)break}if(!n||!i)throw new Error("The static build does not contain the Three.js shader capture transform. Run `shaders capture` without an explicit driver or URL to preview adapter wiring and build automatically, or add the manual adapter from the package README and rebuild.");return {seen:true,applied:true,alreadyPresent:false,captureApplied:true,...s===void 0?{}:{id:s}}}a(Ur,"inspectStaticCaptureTransform");async function Vr(r,e$1){let t;try{t=decodeURIComponent(e$1);}catch{return}if(t.includes("\0"))return;let n=t.replace(/^\/+/u,""),i=y.resolve(r,n.length===0?"index.html":n);if(!e(r,i)||i===r||(await d(i)&&(await lstat(i)).isDirectory()&&(i=y.join(i,"index.html")),!await d(i)&&y.extname(i).length===0&&(i=y.join(r,"index.html")),!await d(i)))return;let s=await j(r,i,a$1.texture,"Static application asset");return {data:s.data,file:s.path}}a(Vr,"staticRequestFile");async function Gr(r,e$1,t,n,i){let s=await realpath(r.root),a=await realpath(y.resolve(s,r.serve));if(!e(s,a)||a===s)throw new Error("--serve must name a built application directory inside the project root.");let d=await Ur(s,a),u=await $(),m=Hr(e$1,t),h=Se(T(r.runtime.three)),g=createServer((o,l)=>{(async()=>{if(ir(o,l,n,i,e$1!=="precompiled"))return;let f=new URL(o.url??"/","http://three-blocks.invalid");if(o.method!=="GET"&&o.method!=="HEAD"){l.statusCode=405,l.end("GET or HEAD required");return}let w=f.pathname===Xe?u:f.pathname===Ze?m:f.pathname===er?h:void 0;if(w!==void 0){l.statusCode=200,l.setHeader("Content-Type","text/javascript; charset=utf-8"),l.setHeader("Cache-Control","no-store"),l.end(o.method==="HEAD"?void 0:w);return}let R=await Vr(a,f.pathname);if(R===void 0){l.statusCode=404,l.end("Not found");return}let P=y.extname(R.file).toLowerCase(),k=P===".html"?Buffer.from(Nr(R.data.toString("utf8"))):R.data;l.statusCode=200,l.setHeader("Content-Type",Fr[P]??"application/octet-stream"),l.setHeader("Content-Length",String(k.byteLength)),l.setHeader("Cache-Control","no-store"),l.end(o.method==="HEAD"?void 0:k);})().catch(f=>{if(l.headersSent)return l.destroy(f instanceof Error?f:void 0);l.statusCode=500,l.end(f instanceof Error?f.message:String(f));});});await new Promise((o,l)=>{g.once("error",l),g.listen(0,"127.0.0.1",()=>{g.off("error",l),o();});});let p=g.address();if(!p||typeof p=="string")throw new Error("Static capture server did not expose an ephemeral TCP address.");return {server:g,baseUrl:`http://127.0.0.1:${p.port}`,transform:d}}a(Gr,"startStaticShaderServer");function Wr(r,e,t){return r===e?true:t&&r!==void 0&&r!=="capture"&&e!=="capture"}a(Wr,"canReuseShaderBrowserSession");function Ye(r){let e=r instanceof Error?r.message:String(r);return e.includes("Execution context was destroyed")&&e.includes("navigation")}a(Ye,"isRetryableShaderObservationNavigation");var K=class{static{a(this,"PlaywrightShaderDriver");}#e;#r=new ye;#n=new ge;#l;#p;#s;#a;#t;#i;#m;#d;#h;#c=0;#u;constructor(e){this.#e=e;}#o(){return this.#l?.status??this.#p??{seen:false,applied:false,alreadyPresent:false}}async#f(e){if(this.#t?.isConnected()===true)return;this.#t=void 0;let t=await Ar();this.#u??=await mkdtemp(y.join(tmpdir(),"three-blocks-shader-cache-")),this.#t=await t.launch({headless:c(this.#e.headed===true),args:[...b(),`--disk-cache-dir=${this.#u}`],timeout:e.timeoutMs}),this.#c=0;}async#y(e,t){let n=this.#s!==void 0||this.#a!==void 0||this.#e.url!==void 0&&this.#i!==void 0,i=this.#a!==void 0?this.#d===e:Wr(this.#d,e,t.bridge.legacyLab);if(n&&i){this.#d=e,await this.#f(t);return}if(n&&await this.close(),this.#d=e,this.#e.url!==void 0){let s=new URL(this.#e.url);if(!["http:","https:"].includes(s.protocol)||s.username||s.password||s.hash)throw new Error("Attached shader URL must be an HTTP(S) URL without credentials or a fragment.");this.#i=s.href,this.#p={seen:true,applied:true,alreadyPresent:false,captureApplied:true,id:"attached-application"},await this.#f(t);return}if(this.#e.serve!==void 0)try{let s=await Gr({root:this.#e.root,runtime:this.#e.runtime,serve:this.#e.serve,...this.#e.headed===void 0?{}:{headed:this.#e.headed}},e,t,this.#r,this.#n);this.#a=s.server,this.#p=s.transform,this.#i=s.baseUrl,await this.#f(t);return}catch(s){throw await this.close(),s}this.#l=Ve(this.#e.runtime.three,{disableTimestampQueries:_.env.THREE_BLOCKS_SOFTWARE_WEBGPU==="1",...t.bridge.legacyLab?{}:{capture:{capture:e==="capture",forceLive:e!=="precompiled",settleFrames:t.settleFrames,settleTimeoutMs:t.settleTimeoutMs??3e4,readiness:t.readiness}}}),this.#m={THREE_BLOCKS_SHADER_TOOL:_.env.THREE_BLOCKS_SHADER_TOOL,THREE_BLOCKS_PRECOMPILE_CAPTURE_SERVER:_.env.THREE_BLOCKS_PRECOMPILE_CAPTURE_SERVER},_.env.THREE_BLOCKS_SHADER_TOOL="1",_.env.THREE_BLOCKS_PRECOMPILE_CAPTURE_SERVER="1";try{let s=await jr(this.#e.root);this.#s=await s({root:this.#e.root,logLevel:"error",plugins:[this.#l.plugin,Lr(this.#r,this.#n,e!=="precompiled",T(this.#e.runtime.three))],server:{host:"127.0.0.1",port:0}}),await this.#s.listen();let a=this.#s.httpServer?.address();if(!a||typeof a=="string")throw new Error("Vite did not expose an ephemeral TCP address.");this.#i=`http://127.0.0.1:${a.port}`,await this.#f(t);}catch(s){throw await this.close(),s}}async capture(e,t){let n=Date.now();if(await this.#y("capture",t),!this.#t||!this.#i)throw new Error("Shader browser driver did not start.");let i=this.#t,s=await i.newContext({viewport:t.viewport});this.#e.url!==void 0&&await he(s,this.#r,this.#n,"capture",t,T(this.#e.runtime.three));let a$1=await s.newPage(),d=me(a$1);this.#n.clear(e.key);let u=this.#r.wait(e.key,t.timeoutMs),m=Promise.race([u,d.first.then(o=>Promise.reject(o))]),h=a(()=>{},"resolveDisconnected"),g=new Promise(o=>{h=o;}),p=a(()=>h(new Error("Shader capture browser disconnected before posting a manifest.")),"onDisconnected");i.on("disconnected",p);try{let o=a$1.goto(We(this.#i,e,{threeBlocksShaderCapture:"1",capture:"1",captureId:e.key,captureFrames:String(Math.max(4,t.settleFrames)),settleFrames:String(t.settleFrames)}),{waitUntil:"domcontentloaded",timeout:t.timeoutMs}),l=await Or(o,Promise.race([m,g.then(w=>Promise.reject(w))]));pe(this.#o());let f=[...d.page,...d.console];if(f.length>0)throw new Error(`Capture browser errors:
91
+ - ${f.join(`
92
+ - `)}`);return a$2(l)?{...l,timing:{...a$2(l.timing)?l.timing:{},launch:n,...this.#n.firstRequest(e.key)===void 0?{}:{firstRequest:this.#n.firstRequest(e.key)},posted:Date.now()}}:l}catch(o){let l=o instanceof Error?o:new Error(String(o));this.#r.cancel(e.key,l),await u.catch(()=>{});let f=this.#n.read(e.key);if(l.message.includes("timed out")){let w=await Ke(()=>a$1.evaluate(()=>{let R=globalThis,P=R.__threeBlocksShaderTools,k=P&&typeof P=="object"?P:void 0,J=R.document,C=Reflect.get(R,Symbol.for("three-blocks.shader-capture.cache-value.v1")),E=R.location,F=E!==null&&typeof E=="object"&&typeof Reflect.get(E,"href")=="string"?String(Reflect.get(E,"href")):"http://three-blocks.invalid/",N=new URL(F).searchParams.get("captureId")??"default",z=C!==null&&typeof C=="object"&&typeof Reflect.get(C,"registrations")=="function"?Reflect.apply(Reflect.get(C,"registrations"),C,[N]):void 0;return {documentReadyState:J?.readyState??null,parityTargetFrame:Number(R.__threeBlocksParityTargetFrame??0),parityCompletedFrame:Number(R.__threeBlocksParityCompletedFrame??0),readiness:k?.readiness??null,captureCache:C!==null&&typeof C=="object"?{activeScene:Reflect.get(C,"activeScene")??null,registrations:Array.isArray(z)?z.slice(0,16).map(M=>M!==null&&typeof M=="object"?{key:Reflect.get(M,"key")??null,kind:Reflect.get(M,"kind")??null}:null):null}:null,threeRuntimeResources:performance.getEntriesByType("resource").map(M=>M.name).filter(M=>M.includes("three.webgpu"))}}));throw new Error(`${l.message} Last capture state for "${e.key}": ${JSON.stringify({page:w,telemetry:f??null,transform:this.#o()})}`)}throw l}finally{i.off("disconnected",p),await L(()=>s.close()),this.#c++,(!i.isConnected()||this.#c>=(t.browserRelaunchScenes??8))&&(this.#t===i&&(this.#t=void 0),await L(()=>i.close()),this.#c=0);}}async observe(e,t,n,i){for(let s=0;s<2;s++)try{return await this.#g(e,t,n,i)}catch(a){if(s===0&&Ye(a))continue;throw a}throw new Error(`Shader observation retry was exhausted for scene "${e.key}".`)}async#g(e,t,n,i){if(await this.#y(t,n),!this.#t||!this.#i)throw new Error("Shader browser driver did not start.");let s=await this.#t.newContext({viewport:n.viewport});this.#e.url!==void 0&&await he(s,this.#r,this.#n,t,n,T(this.#e.runtime.three));let a=await s.newPage(),d=me(a);this.#n.clear(e.key);try{await a.goto(We(this.#i,e,{threeBlocksShaderCapture:"1",threeBlocksShaderMode:t,captureId:e.key,...t==="live"?{precompiled:"0"}:{}}),{waitUntil:"domcontentloaded",timeout:n.timeoutMs}),await Promise.race([a.waitForFunction(n.bridge.legacyLab?"globalThis.__threeBlocks?.compileEnd === true":"globalThis.__threeBlocksShaderTools?.readiness?.compileEnd === true",void 0,{timeout:n.timeoutMs}),d.first.then(o=>Promise.reject(o))]),ee(await re(a,n.bridge.legacyLab),e,n.bridge.legacyLab,this.#o(),T(this.#e.runtime.three)),await Je(a,n,d),await Promise.race([a.waitForFunction(n.bridge.legacyLab?"true":"globalThis.__threeBlocksShaderTools?.readiness?.firstFrame === true",void 0,{timeout:n.timeoutMs}),d.first.then(o=>Promise.reject(o))]),await q(a,n,1);let u=Buffer.from(await a.screenshot({type:"png"})),m=e.parityFrames??n.parity.frames,h=await q(a,n,m,i),g=Buffer.from(await a.screenshot({type:"png"}));e.parityFrames!==void 0&&m<n.parity.frames&&await q(a,n,n.parity.frames-m);let p=ee(await re(a,n.bridge.legacyLab),e,n.bridge.legacyLab,this.#o(),T(this.#e.runtime.three));return this.#h===void 0&&(this.#h=await a.evaluate(async()=>{let o=Reflect.get(navigator,"gpu"),l=typeof o=="object"&&o!==null?Reflect.get(o,"requestAdapter"):void 0,f=typeof l=="function"?await Reflect.apply(l,o,[]):void 0,w=typeof f=="object"&&f!==null?Reflect.get(f,"info"):void 0,R=["description","device","architecture","vendor"].flatMap(P=>{let k=typeof w=="object"&&w!==null?Reflect.get(w,P):void 0;return typeof k=="string"&&k.length>0?[k]:[]});return {adapter:[...new Set(R)].join(" \xB7 ")||"WebGPU adapter",platform:navigator.platform||navigator.userAgent}})),{scene:e.key,mode:t,...p,frame:h,firstFrameScreenshot:u,screenshot:g,errors:[...d.page,...d.console]}}catch(u){let m=u instanceof Error?u:new Error(String(u));if(/(?:timed?\s*out|timeout)/iu.test(m.message)){let h=this.#n.read(e.key),g=await Ke(()=>a.evaluate(()=>{let p=globalThis,o=p.__threeBlocksShaderTools,l=o&&typeof o=="object"?o:void 0;return {documentReadyState:p.document?.readyState??null,parityTargetFrame:Number(p.__threeBlocksParityTargetFrame??0),parityCompletedFrame:Number(p.__threeBlocksParityCompletedFrame??0),readiness:l?.readiness??null,threeRuntimeResources:performance.getEntriesByType("resource").map(w=>w.name).filter(w=>w.includes("three.webgpu"))}}));throw new Error(`${m.message} Last ${t} state for "${e.key}": ${JSON.stringify({page:g,telemetry:h??null})}`)}throw m}finally{await L(()=>s.close());}}async observePublished(e,t){for(let n=0;n<2;n++)try{return await this.#S(e,t)}catch(i){if(n===0&&Ye(i))continue;throw i}throw new Error(`Published shader observation retry was exhausted for scene "${e.key}".`)}async#S(e,t){if(await this.#y("precompiled",t),!this.#t||!this.#i)throw new Error("Shader browser driver did not start.");let n=await this.#t.newContext({viewport:t.viewport});this.#e.url!==void 0&&await he(n,this.#r,this.#n,"precompiled",t,T(this.#e.runtime.three));let i=await n.newPage(),s=me(i);this.#n.clear(e.key);try{await i.goto(Dr(this.#i,e),{waitUntil:"domcontentloaded",timeout:t.timeoutMs}),await Promise.race([i.waitForFunction(t.bridge.legacyLab?"globalThis.__threeBlocks?.compileEnd === true":"globalThis.__threeBlocksShaderTools?.readiness?.compileEnd === true",void 0,{timeout:t.timeoutMs}),s.first.then(h=>Promise.reject(h))]),await Je(i,t,s),ee(await re(i,t.bridge.legacyLab),e,t.bridge.legacyLab,this.#o(),T(this.#e.runtime.three)),await q(i,t,2);let a=await ze(i),d=await q(i,t,120),u=await ze(i),m=ee(await re(i,t.bridge.legacyLab),e,t.bridge.legacyLab,this.#o(),T(this.#e.runtime.three));return {scene:e.key,mode:"precompiled",...m,frame:d,firstFrameScreenshot:a,beforeScreenshot:a,screenshot:u,errors:[...s.page,...s.console]}}finally{await L(()=>n.close());}}timingEnvironment(){return this.#h??{adapter:"WebGPU adapter",platform:`${_.platform}/${_.arch}`}}async close(){this.#r.rejectAll(new Error("Shader browser driver closed.")),this.#t&&await L(()=>this.#t?.close()??Promise.resolve());let e=this.#s?.httpServer,t=e?Reflect.get(e,"closeAllConnections"):void 0;if(e&&typeof t=="function"&&Reflect.apply(t,e,[]),this.#s&&await L(()=>this.#s?.close()??Promise.resolve()),this.#a){let n=this.#a;n.closeAllConnections(),await L(()=>new Promise(i=>{n.close(()=>i());}));}if(this.#t=void 0,this.#s=void 0,this.#a=void 0,this.#i=void 0,this.#l=void 0,this.#p=void 0,this.#d=void 0,this.#h=void 0,this.#c=0,this.#u!==void 0&&(await rm(this.#u,{recursive:true,force:true}),this.#u=void 0),this.#m){for(let[n,i]of Object.entries(this.#m))i===void 0?delete _.env[n]:_.env[n]=i;this.#m=void 0;}}};function Ut(r){return new K(r)}a(Ut,"createPlaywrightShaderDriver");function Vt(r){return new K(r)}a(Vt,"createStaticPlaywrightShaderDriver");function Gt(r){return new K(r)}a(Gt,"createAttachedPlaywrightShaderDriver");
93
+ export{T as a,O as b,it as c,B as d,st as e,at as f,ot as g,dt as h,ct as i,ut as j,Or as k,Ir as l,Se as m,Wr as n,Ye as o,Ut as p,Vt as q,Gt as r};
@@ -1,18 +1,18 @@
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 x(e){return typeof e=="string"&&Ye.test(e)}a(x,"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)||!x(e.generator.version)))throw new Error("three-blocks.json has invalid generator metadata.");if(!c(e.runtime)||!x(e.runtime.three)||!x(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)||!x(e.runtime.three)||!x(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"||!x(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 _(e,r){let t=p.relative(e,r);return t===""||!p.isAbsolute(t)&&t!==".."&&!t.startsWith(`..${p.sep}`)}a(_,"isWithin");function P(e){return JSON.stringify(e)}a(P,"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: ${P(e)}.`);if(!o.isFile())throw new Error(`${t} must be a regular file: ${P(e)}.`);if(o.size>r)throw new Error(`${t} exceeds the ${r}-byte inspection limit: ${P(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 j(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: ${P(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(j,"writeAtomicRegularFile");async function je(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(je,"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(!_(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(!_(s,d))throw new Error(`${t} resolves outside its allowed directory.`);return d}a(v,"canonicalDirectoryWithin");async function I(e,r,t,n){let i=p.resolve(e),o=p.resolve(r);if(!_(i,o)||i===o)throw new Error(`${n} escapes its allowed directory.`);let s=await Ae(o,t,n),d=await realpath(i);if(!_(d,s.path)||d===s.path)throw new Error(`${n} resolves outside its allowed directory.`);return s}a(I,"readRegularFileWithin");async function Ir(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: ${P(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: ${P(y)}.`)}}return s.sort()}a(Ir,"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,Ce=64,xe=64,Pe={schemaVersion:1,scenes:[{key:"default",url:"/"}]};function _e(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(_e,"safeProjectDirectory");function sr(e,r){let t=_e(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 Ie(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(Ie,"safeBrowserUrl");function ar(e){if(!Array.isArray(e)||e.length===0||e.length>Ce)throw new Error(`Shader config scenes must contain 1...${Ce} 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>xe))throw new Error(`Shader config scene "${t.key}" inputs must contain 1...${xe} 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:Ie(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 H(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&&Ie(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:_e(e.publicDir,"Shader publicDir","public"),allowLiveBuilds:e.allowLiveBuilds!==false}}a(H,"parseShaderToolConfig");async function Vr(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 I(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(Vr,"findShaderProjectRoot");async function te(e){let r=await realpath(e),t=p.join(r,ne);if(await b(t)){let i=await I(r,t,$.metadata,"Shader configuration");return H(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 H({schemaVersion:1,scenes:[{key:i.template,url:"/",requiresText:i.features.text}]})}return H(Pe)}a(te,"loadShaderToolConfig");async function Hr(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 I(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(Hr,"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=Pe,o=H(i),s=await je(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=50,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),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)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.");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:
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:
3
3
  - ${i.join(`
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},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):`[
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(`,
6
6
  `)}
7
7
  ${t}]`;if(e!==null&&typeof e=="object"){let o=e,s=Object.keys(o).sort();return s.length===0?"{}":`{
8
8
  ${s.map(d=>{let l=o[d];return `${n}${JSON.stringify(d)}: ${T(l,r+1)}`}).join(`,
9
9
  `)}
10
10
  ${t}}`}let i=JSON.stringify(e);if(i===void 0)throw new Error("Shader artifact contains a non-serializable value.");return i}a(T,"stableStringify");function gr(e){return ["// GENERATED FILE \u2014 do not edit by hand.","// Produced by @three-blocks/devtools.","import type { PrecompiledManifest } from 'three-blocks/shaders';","",`export default ${T(e)} satisfies PrecompiledManifest;`,""].join(`
11
- `)}a(gr,"serializeShaderManifest");function Oe(e,r){if(typeof e!="string"||e.length===0||e.length>256||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${r} is invalid.`);return e}a(Oe,"timingLabel");function de(e){if(!c(e)||e.schemaVersion!==3||e.source!=="latest-local-capture"&&e.source!=="committed-capture"||typeof e.receiptHash!="string"||!/^[a-f0-9]{64}$/u.test(e.receiptHash)||typeof e.measuredAt!="string"||!Number.isFinite(Date.parse(e.measuredAt))||!c(e.scenes))throw new Error("Shader timing is invalid.");let r={};for(let[n,i]of Object.entries(e.scenes)){if(n.length===0||n.length>128||!c(i))throw new Error("Shader timing scene is invalid.");let o={builds:m(i.builds,`timing ${n}.builds`),liveBuildMs:m(i.liveBuildMs,`timing ${n}.liveBuildMs`,false),precompiledBuildMs:m(i.precompiledBuildMs,`timing ${n}.precompiledBuildMs`,false),avoidedBuildMs:m(i.avoidedBuildMs,`timing ${n}.avoidedBuildMs`,false),runs:m(i.runs,`timing ${n}.runs`),spreadMs:m(i.spreadMs,`timing ${n}.spreadMs`,false)};if(o.runs<1)throw new Error(`Shader timing runs are invalid for scene "${n}".`);if(Math.abs(o.avoidedBuildMs-Math.max(0,o.liveBuildMs-o.precompiledBuildMs))>.001)throw new Error(`Shader timing delta is inconsistent for scene "${n}".`);r[n]=o;}if(Object.keys(r).length===0)throw new Error("Shader timing contains no scenes.");let t={schemaVersion:3,receiptHash:e.receiptHash,measuredAt:e.measuredAt,scenes:r};return e.source==="latest-local-capture"?{...t,source:"latest-local-capture"}:{...t,source:"committed-capture",adapter:Oe(e.adapter,"Shader timing adapter"),platform:Oe(e.platform,"Shader timing platform")}}a(de,"parseShaderTiming");function W(e){return /^[a-z0-9][a-z0-9_-]{0,63}$/u.test(e)}a(W,"validParityScene");function Ne(e){return typeof e=="string"&&Number.isFinite(Date.parse(e))}a(Ne,"validParityTimestamp");function me(e){if(!c(e))throw new Error("Shader parity evidence is invalid.");if(e.schemaVersion===1){if(typeof e.receiptHash!="string"||!/^[a-f0-9]{64}$/u.test(e.receiptHash)||!Ne(e.verifiedAt)||!Array.isArray(e.scenes)||e.scenes.length===0||e.scenes.length>64||!e.scenes.every(n=>typeof n=="string"&&W(n)))throw new Error("Shader parity evidence is invalid.");return {schemaVersion:1,receiptHash:e.receiptHash,verifiedAt:e.verifiedAt,scenes:[...new Set(e.scenes)].sort()}}if(e.schemaVersion!==2||!c(e.scenes))throw new Error("Shader parity evidence is invalid.");let r=Object.entries(e.scenes);if(r.length===0||r.length>64)throw new Error("Shader parity evidence is invalid.");let t={};for(let[n,i]of r.sort(([o],[s])=>o.localeCompare(s))){if(!W(n)||!c(i)||typeof i.fingerprint!="string"||!/^[a-f0-9]{64}$/u.test(i.fingerprint)||!Ne(i.verifiedAt))throw new Error("Shader parity evidence is invalid.");t[n]={fingerprint:i.fingerprint,verifiedAt:i.verifiedAt};}return {schemaVersion:2,scenes:t}}a(me,"parseShaderParityEvidence");function ce(e,r){let t=e.scenes[r];if(t===void 0)throw new Error(`Shader receipt has no scene "${r}" for parity evidence.`);return R(T({runtime:{three:e.runtime.three,threeBlocks:e.runtime.threeBlocks,threeBlocksShaderClosure:e.runtime.threeBlocksShaderClosure},...e.tool===void 0?{}:{tool:e.tool},scene:t}))}a(ce,"shaderSceneParityFingerprint");async function z(e,r,t,n){let i=p.join(e,t);try{if(!await b(i))return;let o=await lstat(i);if(o.isSymbolicLink()||!o.isFile()||o.size>1024*1024)return;let s=de(JSON.parse(await readFile(i,"utf8")));return s.source===n&&s.receiptHash===R(r)?s:void 0}catch{return}}a(z,"readShaderTimingFile");async function st(e,r){let t=await z(e,r,pe,"latest-local-capture");return t?.source==="latest-local-capture"?t:void 0}a(st,"readShaderLocalTiming");async function at(e,r){return await z(e,r,pe,"latest-local-capture")??await z(e,r,le,"committed-capture")}a(at,"readShaderTiming");async function Ve(e,r){let t=p.join(e,fe);try{if(!await b(t))return;let n=await lstat(t);if(n.isSymbolicLink()||!n.isFile()||n.size>1024*1024)return;let i=me(JSON.parse(await readFile(t,"utf8"))),o=F(JSON.parse(Buffer.from(r).toString("utf8"))),s={};if(i.schemaVersion===1){if(i.receiptHash!==R(r))return;for(let d of i.scenes)o.scenes[d]!==void 0&&(s[d]={fingerprint:ce(o,d),verifiedAt:i.verifiedAt});}else for(let[d,l]of Object.entries(i.scenes))o.scenes[d]===void 0||l.fingerprint!==ce(o,d)||(s[d]=l);return Object.keys(s).length===0?void 0:{schemaVersion:2,scenes:s}}catch{return}}a(Ve,"readShaderParityEvidence");async function dt(e,r){let t=await z(e,r,le,"committed-capture");return t?.source==="committed-capture"?t:void 0}a(dt,"readShaderCommittedTiming");async function He(e,r,t){let n=await G(e),i=p.join(n,"meta.json"),o=await lstat(i);if(o.isSymbolicLink()||!o.isFile())throw new Error("Shader receipt must be a regular file before timing.");let s=await readFile(i),d=new Date().toISOString(),l=Object.fromEntries(Object.entries(r).sort(([y],[h])=>y.localeCompare(h))),g=de({schemaVersion:3,receiptHash:R(s),measuredAt:d,source:"latest-local-capture",scenes:l});if(await j(p.join(n,pe),`${T(g)}
12
- `),t===void 0)return {local:g};let f=de({schemaVersion:3,receiptHash:R(s),measuredAt:d,source:"committed-capture",adapter:t.adapter,platform:t.platform,scenes:l});return await j(p.join(n,le),`${T(f)}
13
- `),{local:g,committed:f}}a(He,"writeShaderTimings");async function ct(e,r){return (await He(e,r)).local}a(ct,"writeShaderLocalTiming");async function ut(e,r,t){if(r.length===0||r.length>64||r.some(h=>!W(h)))throw new Error("Shader parity evidence must contain 1...64 valid scene keys.");let n=await G(e),i=p.join(n,"meta.json"),o=await lstat(i);if(o.isSymbolicLink()||!o.isFile())throw new Error("Shader receipt must be a regular file before parity evidence.");let s=await readFile(i);if(t!==void 0&&R(s)!==R(t))throw new Error("Shader receipt changed during browser parity verification; completed observations were not attached to the new receipt.");let d=F(JSON.parse(s.toString("utf8"))),l=await Ve(n,s),g=new Date().toISOString(),f={...l?.scenes};for(let h of [...new Set(r)].sort())f[h]={fingerprint:ce(d,h),verifiedAt:g};let y=me({schemaVersion:2,scenes:f});return await j(p.join(n,fe),`${T(y)}
14
- `),y}a(ut,"writeShaderParityEvidence");async function pt(e,r,t){if(r.length===0||r.length>64||r.some(f=>!W(f)))throw new Error("Shader parity invalidation must contain 1...64 valid scene keys.");let n=await G(e),i=await readFile(p.join(n,"meta.json"));if(R(i)!==R(t))throw new Error("Shader receipt changed before prior parity evidence could be invalidated.");let o=await Ve(n,i);if(o===void 0)return;let s=new Set(r),d=Object.fromEntries(Object.entries(o.scenes).filter(([f])=>!s.has(f))),l=p.join(n,fe);if(Object.keys(d).length===0){await unlink(l).catch(f=>{if(!c(f)||f.code!=="ENOENT")throw f});return}let g=me({schemaVersion:2,scenes:d});await j(l,`${T(g)}
15
- `);}a(pt,"removeShaderParityEvidence");async function lt(e,r,t){let n=await He(e,r,t);if(n.committed===void 0)throw new Error("Committed shader timing was not written.");return {local:n.local,committed:n.committed}}a(lt,"writeShaderTimingTwins");async function Be(e){if(!await b(e)){await mkdir(e);return}let r=await lstat(e);if(r.isSymbolicLink()||!r.isDirectory())throw new Error(`Shader artifact path is not a real directory: ${e}.`)}a(Be,"assertDirectory");async function G(e){let r=p.resolve(e),t=p.join(r,".three-blocks");await Be(t);let n=p.join(t,"shaders");return await Be(n),n}a(G,"artifactRoot");async function ft(e){let r=await G(e.root),t=ie(e.runtime.three),n=p.resolve(e.root),i=p.resolve(n,e.publicDirectory??"public");if(!_(n,i)||i===n)throw new Error("Shader public directory must stay inside the project root.");let o=p.join(i,"three-blocks","shaders");await mkdir(o,{recursive:true}),await v(n,o,"Shader static-asset directory");let s={},d=[];for(let u of [...e.scenes].sort((k,M)=>k.key.localeCompare(M.key))){let k=e.captures.get(u.key),M=e.inputs.get(u.key);if(M===void 0)throw new Error(`Shader input matrix is missing scene "${u.key}".`);if(k===void 0){let S=e.previousReceipt?.scenes[u.key];if(S===void 0)throw new Error(`Capture matrix is missing scene "${u.key}".`);let X=await readFile(p.join(r,S.artifact));if(R(X)!==S.artifactHash)throw new Error(`Preserved shader artifact checksum differs for scene "${u.key}".`);if(S.asset!==void 0&&S.assetHash!==void 0){let Z=await readFile(p.join(i,S.asset));if(R(Z)!==S.assetHash)throw new Error(`Preserved static shader manifest checksum differs for scene "${u.key}".`)}s[u.key]={...S,inputs:Object.fromEntries(Object.entries(M).sort(([Z],[qe])=>Z.localeCompare(qe)))},d.push(S.artifact),S.asset!==void 0&&d.push(p.relative(n,p.join(i,S.asset)).split(p.sep).join("/"));continue}if(k.scene!==u.key||k.manifest.scene!==u.key)throw new Error(`Capture matrix scene "${u.key}" is inconsistent.`);let K=`${u.key}.webgpu.ts`,q=gr(k.manifest);await j(p.join(r,K),q),d.push(K);let Y=`three-blocks/shaders/${u.key}.json`,ge=`${T(k.manifest)}
16
- `;await j(p.join(i,Y),ge),d.push(p.relative(n,p.join(i,Y)).split(p.sep).join("/"));let Se=k.skipped.filter(S=>S.kind==="render").length,Ke=k.skipped.length-Se;s[u.key]={artifact:K,artifactHash:R(q),asset:Y,assetHash:R(ge),inputs:Object.fromEntries(Object.entries(M).sort(([S],[X])=>S.localeCompare(X))),coverage:k.coverage,bytes:Buffer.byteLength(q),skipped:{render:Se,compute:Ke}};}let l=[...e.captures.values()].find(u=>u.provenance!==void 0)?.provenance??e.previousReceipt?.runtime.capture,g={schemaVersion:2,runtime:{...e.runtime,...l===void 0?{}:{capture:l}},tool:{name:"@three-blocks/devtools",version:oe,compatibility:t,transform:ue,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION},scenes:s},f=new Set(d);for(let u of await readdir(r,{withFileTypes:true}))if(!(!u.name.endsWith(".webgpu.ts")||f.has(u.name))){if(u.isSymbolicLink()||!u.isFile())throw new Error(`Orphan shader artifact is not a regular file: ${u.name}.`);await unlink(p.join(r,u.name));}let y=new Set(e.scenes.map(u=>`${u.key}.json`)),h=new Set(Object.values(e.previousReceipt?.scenes??{}).map(u=>u.asset===void 0?void 0:p.posix.basename(u.asset)).filter(u=>u!==void 0));try{let u=F(JSON.parse(await readFile(p.join(r,"meta.json"),"utf8")));for(let k of Object.values(u.scenes))k.asset!==void 0&&h.add(p.posix.basename(k.asset));}catch{}for(let u of await readdir(o,{withFileTypes:true}))if(!(!u.name.endsWith(".json")||y.has(u.name))&&h.has(u.name)){if(u.isSymbolicLink()||!u.isFile())throw new Error(`Orphan shader static asset is not a regular file: ${u.name}.`);await unlink(p.join(o,u.name));}return await j(p.join(r,"meta.json"),`${T(g)}
17
- `),d.push("meta.json"),{directory:r,receipt:g,files:d}}a(ft,"writeShaderArtifacts");var B;async function J(){B===void 0&&(B=(async()=>{let r=createRequire(p.join(process.cwd(),"package.json")).resolve("@three-blocks/devtools/browser/shader-capture"),t=p.resolve(p.dirname(r),"../..");return (await I(t,r,$.metadata,"Shader capture browser runtime")).data.toString("utf8")})());let e=B;try{return await e}catch(r){throw B===e&&(B=void 0),r}}a(J,"loadShaderCaptureRuntimeSource");var Ue="virtual:three-blocks-shader-capture-client",We="\0three-blocks:shader-capture-client",ye="virtual:three-blocks-shader-capture-runtime",ze="\0three-blocks:shader-capture-runtime";async function Ct(){let e=await J(),r=e.replace(/\bexport\{[^{}]*\};?\s*$/u,"");if(r===e)throw new Error("Shader capture browser runtime no longer has the expected final ESM export list.");return r}a(Ct,"loadShaderCaptureRuntimeScriptSource");function Rr(e){let r=e.split("?",1)[0];return r===void 0?false:r.split(p.sep).join("/").endsWith("/build/three.webgpu.js")}a(Rr,"isThreeWebGPUModule");function Je(e){let r=/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/u.exec(e);return r?.[1]==="0"&&r[2]==="185"}a(Je,"supportedVersion");function kr(e,r,t={}){if(!Je(r))throw new Error(`Shader provider transform ${THREE_WEBGPU_R185_COMPATIBILITY} supports Three.js 0.185.x; received "${r}".`);let n=transformThreeWebgpuProviderHooks(e,{threeVersion:r,...t.threeRevision===void 0?{}:{threeRevision:t.threeRevision},id:"three/build/three.webgpu.js"}),i=n.state==="already-applied",o=n.code;return t.instrumentCapture&&(o=transformThreeWebgpuCaptureInstrumentation(o,{...t.captureRuntimeImport===void 0?{}:{runtimeImport:t.captureRuntimeImport}}).code),{code:o,alreadyPresent:i,captureApplied:t.instrumentCapture===true}}a(kr,"applyShaderProviderTransform");var Tr=/this\.trackTimestamp\s*=\s*\(\s*parameters\.trackTimestamp\s*===\s*true\s*\);/gu,Ar="Object.defineProperty( this, 'trackTimestamp', { get: () => false, set: () => {} } );";function xt(e,r={}){if(!Je(e))throw new Error(`Shader provider transform ${THREE_WEBGPU_R185_COMPATIBILITY} supports Three.js 0.185.x; received "${e}".`);let t={seen:false,applied:false,alreadyPresent:false};return {plugin:{name:"three-blocks:shader-provider-transform",enforce:"pre",config(){return {optimizeDeps:{exclude:["three","three/webgpu","three/tsl"]},resolve:{dedupe:["three"]}}},resolveId(i){return r.capture&&i===Ue?We:r.capture&&i===ye?ze:null},async load(i){return r.capture?i===ze?J():i===We?[`export * from '${ye}';`,`import { configureThreeBlocksShaderCapture } from '${ye}';`,`configureThreeBlocksShaderCapture( ${JSON.stringify({capture:r.capture.capture,forceLive:r.capture.forceLive,settleFrames:r.capture.settleFrames,settleTimeoutMs:r.capture.settleTimeoutMs,visibilityGuard:r.capture.visibilityGuard,captureId:r.capture.captureId,sessionKey:r.capture.sessionKey,token:r.capture.token,readiness:r.capture.readiness??{},transform:ue})} );`].join(`
18
- `):null:null},transform(i,o){if(!Rr(o))return null;t.seen=true,t.id=o;try{let s=kr(i,e,{instrumentCapture:r.capture!==void 0,...r.capture!==void 0?{captureRuntimeImport:Ue}:{}}),d=r.disableTimestampQueries===!0?s.code.replace(Tr,Ar):s.code;if(r.disableTimestampQueries===!0&&d===s.code)throw new Error("Three.js timestamp tracking anchor drifted; refusing software WebGPU capture.");return t.applied=!0,t.alreadyPresent=s.alreadyPresent,t.captureApplied=s.captureApplied,d===i?null:{code:d,map:null}}catch(s){throw t.error=s instanceof Error?s.message:String(s),s}}},status:t}}a(xt,"createShaderProviderTransform");function Pt(e){if(e.error)throw new Error(e.error);if(!e.seen||!e.applied)throw new Error(`The version-gated shader provider transform was not applied (${e.seen?"module seen":"three/webgpu not seen"}).`)}a(Pt,"assertShaderProviderTransform");export{fe as A,yr as B,ot as C,T as D,gr as E,st as F,at as G,Ve as H,dt as I,ct as J,ut as K,pt as L,lt as M,ft as N,J as O,Ue as P,Ct as Q,Rr as R,kr as S,xt as T,Pt as U,c as a,Ee as b,F as c,$ as d,re as e,R as f,b as g,_ as h,j as i,$r as j,v as k,I as l,Ir as m,ne as n,Lr as o,vr as p,H as q,Vr as r,te as s,Hr as t,Ur as u,ie as v,oe as w,ue as x,pe as y,le as z};
11
+ `)}a(gr,"serializeShaderManifest");function Be(e,r){if(typeof e!="string"||e.length===0||e.length>256||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${r} is invalid.`);return e}a(Be,"timingLabel");function de(e){if(!c(e)||e.schemaVersion!==3||e.source!=="latest-local-capture"&&e.source!=="committed-capture"||typeof e.receiptHash!="string"||!/^[a-f0-9]{64}$/u.test(e.receiptHash)||typeof e.measuredAt!="string"||!Number.isFinite(Date.parse(e.measuredAt))||!c(e.scenes))throw new Error("Shader timing is invalid.");let r={};for(let[n,i]of Object.entries(e.scenes)){if(n.length===0||n.length>128||!c(i))throw new Error("Shader timing scene is invalid.");let o={builds:m(i.builds,`timing ${n}.builds`),setupMeasured:i.setupMeasured===true,liveBuildMs:m(i.liveBuildMs,`timing ${n}.liveBuildMs`,false),precompiledBuildMs:m(i.precompiledBuildMs,`timing ${n}.precompiledBuildMs`,false),avoidedBuildMs:m(i.avoidedBuildMs,`timing ${n}.avoidedBuildMs`,false),runs:m(i.runs,`timing ${n}.runs`),spreadMs:m(i.spreadMs,`timing ${n}.spreadMs`,false)};if(o.runs<1)throw new Error(`Shader timing runs are invalid for scene "${n}".`);if(Math.abs(o.avoidedBuildMs-Math.max(0,o.liveBuildMs-o.precompiledBuildMs))>.001)throw new Error(`Shader timing delta is inconsistent for scene "${n}".`);r[n]=o;}if(Object.keys(r).length===0)throw new Error("Shader timing contains no scenes.");let t={schemaVersion:3,receiptHash:e.receiptHash,measuredAt:e.measuredAt,scenes:r};return e.source==="latest-local-capture"?{...t,source:"latest-local-capture"}:{...t,source:"committed-capture",adapter:Be(e.adapter,"Shader timing adapter"),platform:Be(e.platform,"Shader timing platform")}}a(de,"parseShaderTiming");function W(e){return /^[a-z0-9][a-z0-9_-]{0,63}$/u.test(e)}a(W,"validParityScene");function Oe(e){return typeof e=="string"&&Number.isFinite(Date.parse(e))}a(Oe,"validParityTimestamp");function me(e){if(!c(e))throw new Error("Shader parity evidence is invalid.");if(e.schemaVersion===1){if(typeof e.receiptHash!="string"||!/^[a-f0-9]{64}$/u.test(e.receiptHash)||!Oe(e.verifiedAt)||!Array.isArray(e.scenes)||e.scenes.length===0||e.scenes.length>64||!e.scenes.every(n=>typeof n=="string"&&W(n)))throw new Error("Shader parity evidence is invalid.");return {schemaVersion:1,receiptHash:e.receiptHash,verifiedAt:e.verifiedAt,scenes:[...new Set(e.scenes)].sort()}}if(e.schemaVersion!==2||!c(e.scenes))throw new Error("Shader parity evidence is invalid.");let r=Object.entries(e.scenes);if(r.length===0||r.length>64)throw new Error("Shader parity evidence is invalid.");let t={};for(let[n,i]of r.sort(([o],[s])=>o.localeCompare(s))){if(!W(n)||!c(i)||typeof i.fingerprint!="string"||!/^[a-f0-9]{64}$/u.test(i.fingerprint)||!Oe(i.verifiedAt))throw new Error("Shader parity evidence is invalid.");t[n]={fingerprint:i.fingerprint,verifiedAt:i.verifiedAt};}return {schemaVersion:2,scenes:t}}a(me,"parseShaderParityEvidence");function ce(e,r){let t=e.scenes[r];if(t===void 0)throw new Error(`Shader receipt has no scene "${r}" for parity evidence.`);return R(T({runtime:{three:e.runtime.three,threeBlocks:e.runtime.threeBlocks,threeBlocksShaderClosure:e.runtime.threeBlocksShaderClosure},...e.tool===void 0?{}:{tool:e.tool},scene:t}))}a(ce,"shaderSceneParityFingerprint");async function z(e,r,t,n){let i=p.join(e,t);try{if(!await b(i))return;let o=await lstat(i);if(o.isSymbolicLink()||!o.isFile()||o.size>1024*1024)return;let s=de(JSON.parse(await readFile(i,"utf8")));return s.source===n&&s.receiptHash===R(r)?s:void 0}catch{return}}a(z,"readShaderTimingFile");async function st(e,r){let t=await z(e,r,pe,"latest-local-capture");return t?.source==="latest-local-capture"?t:void 0}a(st,"readShaderLocalTiming");async function at(e,r){return await z(e,r,pe,"latest-local-capture")??await z(e,r,le,"committed-capture")}a(at,"readShaderTiming");async function He(e,r){let t=p.join(e,fe);try{if(!await b(t))return;let n=await lstat(t);if(n.isSymbolicLink()||!n.isFile()||n.size>1024*1024)return;let i=me(JSON.parse(await readFile(t,"utf8"))),o=F(JSON.parse(Buffer.from(r).toString("utf8"))),s={};if(i.schemaVersion===1){if(i.receiptHash!==R(r))return;for(let d of i.scenes)o.scenes[d]!==void 0&&(s[d]={fingerprint:ce(o,d),verifiedAt:i.verifiedAt});}else for(let[d,l]of Object.entries(i.scenes))o.scenes[d]===void 0||l.fingerprint!==ce(o,d)||(s[d]=l);return Object.keys(s).length===0?void 0:{schemaVersion:2,scenes:s}}catch{return}}a(He,"readShaderParityEvidence");async function dt(e,r){let t=await z(e,r,le,"committed-capture");return t?.source==="committed-capture"?t:void 0}a(dt,"readShaderCommittedTiming");async function ve(e,r,t){let n=await G(e),i=p.join(n,"meta.json"),o=await lstat(i);if(o.isSymbolicLink()||!o.isFile())throw new Error("Shader receipt must be a regular file before timing.");let s=await readFile(i),d=new Date().toISOString(),l=Object.fromEntries(Object.entries(r).sort(([y],[h])=>y.localeCompare(h))),g=de({schemaVersion:3,receiptHash:R(s),measuredAt:d,source:"latest-local-capture",scenes:l});if(await x(p.join(n,pe),`${T(g)}
12
+ `),t===void 0)return {local:g};let f=de({schemaVersion:3,receiptHash:R(s),measuredAt:d,source:"committed-capture",adapter:t.adapter,platform:t.platform,scenes:l});return await x(p.join(n,le),`${T(f)}
13
+ `),{local:g,committed:f}}a(ve,"writeShaderTimings");async function ct(e,r){return (await ve(e,r)).local}a(ct,"writeShaderLocalTiming");async function ut(e,r,t){if(r.length===0||r.length>64||r.some(h=>!W(h)))throw new Error("Shader parity evidence must contain 1...64 valid scene keys.");let n=await G(e),i=p.join(n,"meta.json"),o=await lstat(i);if(o.isSymbolicLink()||!o.isFile())throw new Error("Shader receipt must be a regular file before parity evidence.");let s=await readFile(i);if(t!==void 0&&R(s)!==R(t))throw new Error("Shader receipt changed during browser parity verification; completed observations were not attached to the new receipt.");let d=F(JSON.parse(s.toString("utf8"))),l=await He(n,s),g=new Date().toISOString(),f={...l?.scenes};for(let h of [...new Set(r)].sort())f[h]={fingerprint:ce(d,h),verifiedAt:g};let y=me({schemaVersion:2,scenes:f});return await x(p.join(n,fe),`${T(y)}
14
+ `),y}a(ut,"writeShaderParityEvidence");async function pt(e,r,t){if(r.length===0||r.length>64||r.some(f=>!W(f)))throw new Error("Shader parity invalidation must contain 1...64 valid scene keys.");let n=await G(e),i=await readFile(p.join(n,"meta.json"));if(R(i)!==R(t))throw new Error("Shader receipt changed before prior parity evidence could be invalidated.");let o=await He(n,i);if(o===void 0)return;let s=new Set(r),d=Object.fromEntries(Object.entries(o.scenes).filter(([f])=>!s.has(f))),l=p.join(n,fe);if(Object.keys(d).length===0){await unlink(l).catch(f=>{if(!c(f)||f.code!=="ENOENT")throw f});return}let g=me({schemaVersion:2,scenes:d});await x(l,`${T(g)}
15
+ `);}a(pt,"removeShaderParityEvidence");async function lt(e,r,t){let n=await ve(e,r,t);if(n.committed===void 0)throw new Error("Committed shader timing was not written.");return {local:n.local,committed:n.committed}}a(lt,"writeShaderTimingTwins");async function Ne(e){if(!await b(e)){await mkdir(e);return}let r=await lstat(e);if(r.isSymbolicLink()||!r.isDirectory())throw new Error(`Shader artifact path is not a real directory: ${e}.`)}a(Ne,"assertDirectory");async function G(e){let r=p.resolve(e),t=p.join(r,".three-blocks");await Ne(t);let n=p.join(t,"shaders");return await Ne(n),n}a(G,"artifactRoot");async function ft(e){let r=await G(e.root),t=ie(e.runtime.three),n=p.resolve(e.root),i=p.resolve(n,e.publicDirectory??"public");if(!M(n,i)||i===n)throw new Error("Shader public directory must stay inside the project root.");let o=p.join(i,"three-blocks","shaders");await mkdir(o,{recursive:true}),await V(n,o,"Shader static-asset directory");let s={},d=[];for(let u of [...e.scenes].sort((k,I)=>k.key.localeCompare(I.key))){let k=e.captures.get(u.key),I=e.inputs.get(u.key);if(I===void 0)throw new Error(`Shader input matrix is missing scene "${u.key}".`);if(k===void 0){let S=e.previousReceipt?.scenes[u.key];if(S===void 0)throw new Error(`Capture matrix is missing scene "${u.key}".`);let X=await readFile(p.join(r,S.artifact));if(R(X)!==S.artifactHash)throw new Error(`Preserved shader artifact checksum differs for scene "${u.key}".`);if(S.asset!==void 0&&S.assetHash!==void 0){let Z=await readFile(p.join(i,S.asset));if(R(Z)!==S.assetHash)throw new Error(`Preserved static shader manifest checksum differs for scene "${u.key}".`)}s[u.key]={...S,inputs:Object.fromEntries(Object.entries(I).sort(([Z],[Ke])=>Z.localeCompare(Ke)))},d.push(S.artifact),S.asset!==void 0&&d.push(p.relative(n,p.join(i,S.asset)).split(p.sep).join("/"));continue}if(k.scene!==u.key||k.manifest.scene!==u.key)throw new Error(`Capture matrix scene "${u.key}" is inconsistent.`);let q=`${u.key}.webgpu.ts`,K=gr(k.manifest);await x(p.join(r,q),K),d.push(q);let Y=`three-blocks/shaders/${u.key}.json`,ge=`${T(k.manifest)}
16
+ `;await x(p.join(i,Y),ge),d.push(p.relative(n,p.join(i,Y)).split(p.sep).join("/"));let Se=k.skipped.filter(S=>S.kind==="render").length,qe=k.skipped.length-Se;s[u.key]={artifact:q,artifactHash:R(K),asset:Y,assetHash:R(ge),inputs:Object.fromEntries(Object.entries(I).sort(([S],[X])=>S.localeCompare(X))),coverage:k.coverage,bytes:Buffer.byteLength(K),skipped:{render:Se,compute:qe}};}let l=[...e.captures.values()].find(u=>u.provenance!==void 0)?.provenance??e.previousReceipt?.runtime.capture,g={schemaVersion:2,runtime:{...e.runtime,...l===void 0?{}:{capture:l}},tool:{name:"@three-blocks/devtools",version:oe,compatibility:t,transform:ue,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION},scenes:s},f=new Set(d);for(let u of await readdir(r,{withFileTypes:true}))if(!(!u.name.endsWith(".webgpu.ts")||f.has(u.name))){if(u.isSymbolicLink()||!u.isFile())throw new Error(`Orphan shader artifact is not a regular file: ${u.name}.`);await unlink(p.join(r,u.name));}let y=new Set(e.scenes.map(u=>`${u.key}.json`)),h=new Set(Object.values(e.previousReceipt?.scenes??{}).map(u=>u.asset===void 0?void 0:p.posix.basename(u.asset)).filter(u=>u!==void 0));try{let u=F(JSON.parse(await readFile(p.join(r,"meta.json"),"utf8")));for(let k of Object.values(u.scenes))k.asset!==void 0&&h.add(p.posix.basename(k.asset));}catch{}for(let u of await readdir(o,{withFileTypes:true}))if(!(!u.name.endsWith(".json")||y.has(u.name))&&h.has(u.name)){if(u.isSymbolicLink()||!u.isFile())throw new Error(`Orphan shader static asset is not a regular file: ${u.name}.`);await unlink(p.join(o,u.name));}return await x(p.join(r,"meta.json"),`${T(g)}
17
+ `),d.push("meta.json"),{directory:r,receipt:g,files:d}}a(ft,"writeShaderArtifacts");var N;async function J(){N===void 0&&(N=(async()=>{let r=createRequire(p.join(process.cwd(),"package.json")).resolve("@three-blocks/devtools/browser/shader-capture"),t=p.resolve(p.dirname(r),"../..");return (await $(t,r,_.metadata,"Shader capture browser runtime")).data.toString("utf8")})());let e=N;try{return await e}catch(r){throw N===e&&(N=void 0),r}}a(J,"loadShaderCaptureRuntimeSource");var Ue="virtual:three-blocks-shader-capture-client",We="\0three-blocks:shader-capture-client",ye="virtual:three-blocks-shader-capture-runtime",ze="\0three-blocks:shader-capture-runtime";async function jt(){let e=await J(),r=e.replace(/\bexport\{[^{}]*\};?\s*$/u,"");if(r===e)throw new Error("Shader capture browser runtime no longer has the expected final ESM export list.");return r}a(jt,"loadShaderCaptureRuntimeScriptSource");function Rr(e){let r=e.split("?",1)[0];return r===void 0?false:r.split(p.sep).join("/").endsWith("/build/three.webgpu.js")}a(Rr,"isThreeWebGPUModule");function Je(e){let r=/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/u.exec(e);return r?.[1]==="0"&&r[2]==="185"}a(Je,"supportedVersion");function kr(e,r,t={}){if(!Je(r))throw new Error(`Shader provider transform ${THREE_WEBGPU_R185_COMPATIBILITY} supports Three.js 0.185.x; received "${r}".`);let n=transformThreeWebgpuProviderHooks(e,{threeVersion:r,...t.threeRevision===void 0?{}:{threeRevision:t.threeRevision},id:"three/build/three.webgpu.js"}),i=n.state==="already-applied",o=n.code;return t.instrumentCapture&&(o=transformThreeWebgpuCaptureInstrumentation(o,{...t.captureRuntimeImport===void 0?{}:{runtimeImport:t.captureRuntimeImport}}).code),{code:o,alreadyPresent:i,captureApplied:t.instrumentCapture===true}}a(kr,"applyShaderProviderTransform");var Tr=/this\.trackTimestamp\s*=\s*\(\s*parameters\.trackTimestamp\s*===\s*true\s*\);/gu,Ar="Object.defineProperty( this, 'trackTimestamp', { get: () => false, set: () => {} } );";function Pt(e,r={}){if(!Je(e))throw new Error(`Shader provider transform ${THREE_WEBGPU_R185_COMPATIBILITY} supports Three.js 0.185.x; received "${e}".`);let t={seen:false,applied:false,alreadyPresent:false};return {plugin:{name:"three-blocks:shader-provider-transform",enforce:"pre",config(){return {optimizeDeps:{exclude:["three","three/webgpu","three/tsl"]},resolve:{dedupe:["three"]}}},resolveId(i){return r.capture&&i===Ue?We:r.capture&&i===ye?ze:null},async load(i){return r.capture?i===ze?J():i===We?[`export * from '${ye}';`,`import { configureThreeBlocksShaderCapture } from '${ye}';`,`configureThreeBlocksShaderCapture( ${JSON.stringify({capture:r.capture.capture,forceLive:r.capture.forceLive,settleFrames:r.capture.settleFrames,settleTimeoutMs:r.capture.settleTimeoutMs,visibilityGuard:r.capture.visibilityGuard,captureId:r.capture.captureId,sessionKey:r.capture.sessionKey,token:r.capture.token,readiness:r.capture.readiness??{},transform:ue})} );`].join(`
18
+ `):null:null},transform(i,o){if(!Rr(o))return null;t.seen=true,t.id=o;try{let s=kr(i,e,{instrumentCapture:r.capture!==void 0,...r.capture!==void 0?{captureRuntimeImport:Ue}:{}}),d=r.disableTimestampQueries===!0?s.code.replace(Tr,Ar):s.code;if(r.disableTimestampQueries===!0&&d===s.code)throw new Error("Three.js timestamp tracking anchor drifted; refusing software WebGPU capture.");return t.applied=!0,t.alreadyPresent=s.alreadyPresent,t.captureApplied=s.captureApplied,d===i?null:{code:d,map:null}}catch(s){throw t.error=s instanceof Error?s.message:String(s),s}}},status:t}}a(Pt,"createShaderProviderTransform");function Ct(e){if(e.error)throw new Error(e.error);if(!e.seen||!e.applied)throw new Error(`The version-gated shader provider transform was not applied (${e.seen?"module seen":"three/webgpu not seen"}).`)}a(Ct,"assertShaderProviderTransform");export{fe as A,yr as B,ot as C,T as D,gr as E,st as F,at as G,He as H,dt as I,ct as J,ut as K,pt as L,lt as M,ft as N,J as O,Ue as P,jt as Q,Rr as R,kr as S,Pt as T,Ct as U,c as a,Ee as b,F as c,_ as d,re as e,R as f,b as g,M as h,x as i,_r as j,V as k,$ as l,$r as m,ne as n,Lr as o,Vr as p,v as q,Hr as r,te as s,vr as t,Ur as u,ie as v,oe as w,ue as x,pe as y,le as z};
package/dist/cli.js CHANGED
@@ -5,20 +5,20 @@ ${e}
5
5
  `:t),n.includes("--yes"))return true;if(!a.stdin.isTTY||!a.stderr.isTTY)throw new Error("Adapter wiring needs consent. Review the diff above, then rerun with --yes; no files were changed.");let{createInterface:i}=await import('readline/promises'),r=i({input:a.stdin,output:a.stderr});try{let c=await r.question("Apply this patch? (y/N) ");return /^y(?:es)?$/iu.test(c.trim())}finally{r.close();}}a$1(ce,"approveAdapterPatch");function C(e){return w?{update(){},stop(){}}:h(e)}a$1(C,"wait");function le(){let e$1=a$1(f=>b$1.accent(f),"c"),t=a$1(f=>b$1.dim(f),"d"),i=c.mark?`${c.mark} `:"",r=[["Inspect",[[`${e$1("status")}`,`project report: shaders, text, browser evidence ${t("\u2014 no browser, no GPU")}`],[`${e$1("shaders")}`,"verify shader freshness and exit 1 with the exact recovery command"],[`${e$1("shaders status")} ${t("[--check]")}`,`per-scene shader freshness ${t("(--check exits 1 when not fresh)")}`],[`${e$1("text status")}`,"text atlas coverage"]]],["Produce",[[`${e$1("shaders capture")} ${t("[--if-stale] [--commit-timing] [--driver static --serve dist]")}`,"capture shaders plus a local timing estimate; during development use the overlay Capture button"],[`${e$1("shaders watch")} ${t("[--debounce <ms>]")}`,"recapture automatically while you work"],[`${e$1("text generate")} ${t("[--config <path>]")}`,"regenerate MSDF text atlases"],[`${e$1("environment bake")} ${t("[--size 256]")}`,"bake the PMREM room environment to KTX2"]]],["Verify",[[`${e$1("shaders test")}`,"median timing + zero-build + compute + pixel parity gate"],[`${e$1("shaders test --parity-only")}`,"one correctness pair per scene; no timing or published-page soak"],[`${e$1("browser smoke")} ${t("[--route /] [--hmr <module>]")}`,"boot the dev app, verify worker lifecycle + HMR"],[`${e$1("browser preview")} ${t("[--route /]...")}`,"build + serve production, verify precompiled hydration"]]]],c$1=["",`${i}${b$1.bold("three-blocks devtools")} ${b$1.dim(`v${a$2}`)}`,b$1.dim("WebGPU shader precompilation and verification for Three Blocks projects."),"",`${b$1.bold("Usage")}`,` ${e$1("three-blocks-devtools")} ${t("[command] [options] [--json]")}`];for(let[f,d]of r)c$1.push("",b$1.bold(f),...e(d,{indent:2,maxWidth:a$3.width-2}));c$1.push("",b$1.bold("Options"),...e([[t("--json"),"stable machine-readable report on stdout"],[t("--reporter <plain|json>"),"select the stable terminal or CI reporter"],[t("--root <path>"),"project root (defaults to the nearest three-blocks project)"],[t("--headed"),"show the automation browser window"],[t("--runs <n>"),"shader timing captures after warmup (default 5)"],[t("--parity-only"),"skip timing warmup/repeats and the published-page soak"],[t("--commit-timing"),"also write shareable hardware-labelled build timing"],[t("--skip-browser"),"check shader schema and freshness without browser parity"],[t("--driver <vite|static>"),"capture through Vite or an already-built static app"],[t("--serve <path>"),"built application directory for --driver static"],[t("--url <url>"),"attach to an already-running transformed application"],[t("--yes"),"apply a previewed framework adapter patch non-interactively"]],{indent:2,maxWidth:a$3.width-2}),"",b$1.dim("During development, use the in-page overlay Capture button for one-click recapture."),b$1.dim("`shaders capture` remains the explicit isolated-browser fallback for batch and CI."),""),f(c$1.join(`
6
6
  `));}a$1(le,"help");function pe(e){return e?`${e.render} render \xB7 ${e.compute} compute`:"no coverage"}a$1(pe,"coverageText");function Q(e){return e<100?e.toFixed(1):Math.round(e).toString()}a$1(Q,"milliseconds");function A(e,t,i){return `${e} ${d(t,12)} ${i}`}a$1(A,"row");function oe(e$1){if(e$1.skipped)return A(c.tick,"shaders",`fresh ${c.dot} capture skipped ${b$1.dim(`(--if-stale) \xB7 ${e$1.reason}`)}`);let t=Math.max(0,Math.round((e$1.durationMs??0)/1e3)),i=e$1.scenes.length,r=[A(c.tick,"shaders",`captured in ${t} s ${c.dot} wrote ${i} shader scene${i===1?"":"s"}`)];e$1.configuration?.created===true&&r.push(b$1.dim(` created ${e$1.configuration.file} with the default "/" capture route`));for(let f of e$1.scenes)r.push(A(c.tick,f.scene,`${pe(f.coverage)} ${c.dot} ${b$1.dim(`${f.attempts} attempt${f.attempts===1?"":"s"}`)}`));let c$1=e$1.scenes.flatMap(f=>{let d=f.timing;if(d?.launch===void 0||d.firstRequest===void 0||d.readiness===void 0||d.lastBuild===void 0||d.settled===void 0||d.posted===void 0)return [];let m=a$1((M,l)=>`${Q(Math.max(0,l-M))} ms`,"elapsed");return [[f.scene,`launch\u2192request ${m(d.launch,d.firstRequest)} ${c.dot} ready ${m(d.firstRequest,d.readiness)} ${c.dot} last build ${m(d.readiness,d.lastBuild)} ${c.dot} settle ${m(d.lastBuild,d.settled)} ${c.dot} post ${m(d.settled,d.posted)}`]]});return c$1.length>0&&r.push("",b$1.bold("Capture stages"),...e(c$1,{indent:2,maxWidth:a$3.width-2})),e$1.measurement!==void 0&&r.push(` TSL builds at startup: ${e$1.measurement.beforeBuilds} \u2192 ${e$1.measurement.afterBuilds} ${c.dot} \u2248${Q(Math.abs(e$1.measurement.firstFrameDeltaMs))} ms TSL work avoided (single-capture estimate)`),r.push(b$1.dim(" a running dev server reloads on its own; otherwise refresh the page")),r.join(`
7
7
  `)}a$1(oe,"formatShaderCapture");function fe(e){let t=[A(c.tick,"shaders",`no-GPU ${e.noGpu.state} ${c.dot} browser ${e.browser}`)];for(let i of e.scenes){let r=e.timing?.scenes[i.scene],c$1=r===void 0?`${i.coverage.render+i.coverage.compute} TSL build${i.coverage.render+i.coverage.compute===1?"":"s"} skipped`:`${r.builds} TSL build${r.builds===1?"":"s"} skipped ${c.dot} \u2248${Q(r.avoidedBuildMs)} ms \xB1 ${Q(r.spreadMs)} TSL work avoided ${c.dot} median of ${r.runs} ${c.dot} Latest local capture`,f=r!==void 0&&r.spreadMs>r.avoidedBuildMs*.4?` ${c.dot} ${b$1.warn("noisy measurement \u2014 close other GPU apps and re-run")}`:"";t.push(A(c.tick,i.scene,`${c$1} ${c.dot} ${i.coverage.compute} compute ${c.dot} ${(i.parity.diffRatio*100).toFixed(3)}% pixel diff${f}`));}return t.join(`
8
- `)}a$1(fe,"formatShaderTest");async function he(){if(se!==void 0)throw new Error(se);if(y==="help"||y==="--help"||n.includes("--help"))return le();if(y==="version"||n.includes("--version")){f(w?JSON.stringify({version:a$2}):a$2);return}if(y==="browser"){let{formatBrowserPreviewReport:d,formatBrowserSmokeReport:m,runBrowserPreview:M,runBrowserSmoke:l}=await import('./browser-smoke-HB7ZXQGR.js'),{findProjectRoot:S}=await import('./status-CFJSWBDI.js');if(E==="preview"){let U=b("--root")??await S(),j=ue("--route"),I=b("--build-mode"),P=b("--expect-shaders")??"precompiled";if(P!=="precompiled"&&P!=="live")throw new Error('--expect-shaders must be "precompiled" or "live".');let T=$("--width"),B=$("--height"),J=$("--timeout"),D=$("--settle"),O=$("--min-luminance"),z=C("building and verifying the production bundle"),o;try{o=await M({root:U,...j.length===0?{}:{routes:j},...I===void 0?{}:{buildMode:I},expectShaders:P,text:n.includes("--text"),...J===void 0?{}:{timeoutMs:J},...D===void 0?{}:{settleMs:D},...O===void 0?{}:{minimumLuminance:O},...T===void 0&&B===void 0?{}:{viewport:{width:T??1024,height:B??640}},headed:n.includes("--headed")});}finally{z.stop();}a.stdout.write(`${w?JSON.stringify(o,null,2):d(o)}
8
+ `)}a$1(fe,"formatShaderTest");async function he(){if(se!==void 0)throw new Error(se);if(y==="help"||y==="--help"||n.includes("--help"))return le();if(y==="version"||n.includes("--version")){f(w?JSON.stringify({version:a$2}):a$2);return}if(y==="browser"){let{formatBrowserPreviewReport:d,formatBrowserSmokeReport:m,runBrowserPreview:M,runBrowserSmoke:l}=await import('./browser-smoke-MKYIJVVA.js'),{findProjectRoot:S}=await import('./status-76TXXSRT.js');if(E==="preview"){let U=b("--root")??await S(),j=ue("--route"),I=b("--build-mode"),P=b("--expect-shaders")??"precompiled";if(P!=="precompiled"&&P!=="live")throw new Error('--expect-shaders must be "precompiled" or "live".');let T=$("--width"),B=$("--height"),J=$("--timeout"),D=$("--settle"),O=$("--min-luminance"),z=C("building and verifying the production bundle"),o;try{o=await M({root:U,...j.length===0?{}:{routes:j},...I===void 0?{}:{buildMode:I},expectShaders:P,text:n.includes("--text"),...J===void 0?{}:{timeoutMs:J},...D===void 0?{}:{settleMs:D},...O===void 0?{}:{minimumLuminance:O},...T===void 0&&B===void 0?{}:{viewport:{width:T??1024,height:B??640}},headed:n.includes("--headed")});}finally{z.stop();}a.stdout.write(`${w?JSON.stringify(o,null,2):d(o)}
9
9
  `),o.passed||(a.exitCode=1);return}if(E!=="smoke")throw new Error(`Unsupported browser command "${E??""}".`);let x=b("--root")??await S(),h=$("--width"),k=$("--height"),R=b("--route"),_=$("--timeout"),q=$("--settle"),L=$("--min-luminance"),g=b("--hmr");if(n.includes("--webgl")&&n.includes("--unsupported-worker"))throw new Error("--webgl and --unsupported-worker are mutually exclusive.");let W=C(`smoking ${R??"/"} in a real browser`),v;try{v=await l({root:x,...R===void 0?{}:{route:R},..._===void 0?{}:{timeoutMs:_},...q===void 0?{}:{settleMs:q},...L===void 0?{}:{minimumLuminance:L},...g===void 0?{}:{hmrModule:g},forceWebgl:n.includes("--webgl"),unsupportedWorker:n.includes("--unsupported-worker"),expectTextGenerationFailure:n.includes("--expect-text-generation-failure"),...h===void 0&&k===void 0?{}:{viewport:{width:h??1024,height:k??640}},headed:n.includes("--headed")});}finally{W.stop();}a.stdout.write(`${w?JSON.stringify(v,null,2):m(v)}
10
- `),v.passed||(a.exitCode=1);return}if(y==="environment"){if(E!=="bake")throw new Error(`Unsupported environment command "${E??""}".`);let{bakeRoomEnvironment:d,formatEnvironmentBakeReport:m}=await import('./environment-bake-5P4IAL4O.js'),{findProjectRoot:M}=await import('./status-CFJSWBDI.js'),l=b("--root")??await M(),S=$("--size"),x=b("--output"),h=$("--timeout"),k=C("baking the room environment on the GPU"),R;try{R=await d({root:l,...S===void 0?{}:{size:S},...x===void 0?{}:{output:x},...h===void 0?{}:{timeoutMs:h},compression:n.includes("--no-zstd")?"none":"zstd",headed:n.includes("--headed")});}finally{k.stop();}a.stdout.write(`${w?JSON.stringify(R,null,2):m(R)}
11
- `);return}if(y==="shaders"){let{findShaderProjectRoot:d}=await import('./shader-config-BYBJUL3C.js'),m=E??"status";if(!["status","capture","test","watch"].includes(m))throw new Error(`Unsupported shader command "${m}".`);let M=b("--root"),l=await d(M),S=b("--driver");if(S!==void 0&&S!=="vite"&&S!=="static")throw new Error('--driver must be "vite" or "static".');let x=S,h=b("--serve"),k=b("--url");if(m==="status"){let{inspectShaderMatrix:g}=await import('./shader-workflow-SO7WCR4Y.js'),{formatShaderMatrixStatus:W}=await import('./status-CFJSWBDI.js'),v=await g(l);a.stdout.write(`${w?JSON.stringify(v,null,2):W(v)}
12
- `),(n.includes("--check")||E===void 0)&&v.state!=="fresh"&&(a.exitCode=1);return}if(m==="capture"){let{captureShaders:g}=await import('./shader-workflow-SO7WCR4Y.js'),{applyShaderAutoWire:W,hasRegisterDevtoolsCall:v,inspectShaderAutoWire:U}=await import('./shader-autowire-DCODBFMX.js'),{buildShaderCaptureProject:j,startNextShaderCaptureServer:I}=await import('./shader-project-runner-GUR3LTYS.js'),{inferShaderCaptureTarget:P}=await import('./shader-config-BYBJUL3C.js'),T=x,B=h,J=k,D,O,z;try{if(T===void 0&&B===void 0&&J===void 0){let o=await U(l);if(!o.configured&&o.plan!==void 0){if(!await ce(o.plan.diff))throw new Error("Adapter wiring was declined; no files were changed.");await W(o.plan);}else if(!o.configured&&o.bundler!=="vite"&&o.bundler!=="unknown")throw new Error(`${o.reason} No files were changed.`);if(o.bundler==="next")O=C("starting the project-local Next.js capture server"),D=await I(l),J=D.url,O.update("capturing shader scenes");else if(o.bundler==="webpack"||o.bundler==="esbuild"||o.bundler==="rollup"){O=C(`building the ${o.bundler} capture target`),await j(l);let N=await P(l);if(N.driverKind!=="static"||N.serve===void 0)throw new Error(`${o.bundler} build completed but no dist/, build/, or out/index.html was found; pass --driver static --serve <directory>.`);T="static",B=N.serve,O.update("capturing shader scenes");}}O??=C("capturing shader scenes"),z=await g({root:l,headed:n.includes("--headed"),ifStale:n.includes("--if-stale"),commitTiming:n.includes("--commit-timing"),...T===void 0?{}:{driverKind:T},...B===void 0?{}:{serve:B},...J===void 0?{}:{url:J},onSceneStart:a$1((o,N,K)=>O?.update(`capturing ${b$1.accent(o)} ${b$1.dim(`(${N+1}/${K})`)}`),"onSceneStart"),onSceneRetry:a$1((o,N,K,re,V)=>{let ae=V instanceof Error&&/timed out/iu.test(V.message),ne=`capture attempt ${N}/${K} for "${o}" after ${ae?`timeout (${Math.round(re/1e3)} s burned)`:`failure (${V instanceof Error?V.message:String(V)})`}`;a.stderr.write(w?`${JSON.stringify({type:"shader-capture-retry",scene:o,attempt:N,total:K,timeoutMs:re,message:ne})}
10
+ `),v.passed||(a.exitCode=1);return}if(y==="environment"){if(E!=="bake")throw new Error(`Unsupported environment command "${E??""}".`);let{bakeRoomEnvironment:d,formatEnvironmentBakeReport:m}=await import('./environment-bake-5P4IAL4O.js'),{findProjectRoot:M}=await import('./status-76TXXSRT.js'),l=b("--root")??await M(),S=$("--size"),x=b("--output"),h=$("--timeout"),k=C("baking the room environment on the GPU"),R;try{R=await d({root:l,...S===void 0?{}:{size:S},...x===void 0?{}:{output:x},...h===void 0?{}:{timeoutMs:h},compression:n.includes("--no-zstd")?"none":"zstd",headed:n.includes("--headed")});}finally{k.stop();}a.stdout.write(`${w?JSON.stringify(R,null,2):m(R)}
11
+ `);return}if(y==="shaders"){let{findShaderProjectRoot:d}=await import('./shader-config-BYBJUL3C.js'),m=E??"status";if(!["status","capture","test","watch"].includes(m))throw new Error(`Unsupported shader command "${m}".`);let M=b("--root"),l=await d(M),S=b("--driver");if(S!==void 0&&S!=="vite"&&S!=="static")throw new Error('--driver must be "vite" or "static".');let x=S,h=b("--serve"),k=b("--url");if(m==="status"){let{inspectShaderMatrix:g}=await import('./shader-workflow-AAH3FM4U.js'),{formatShaderMatrixStatus:W}=await import('./status-76TXXSRT.js'),v=await g(l);a.stdout.write(`${w?JSON.stringify(v,null,2):W(v)}
12
+ `),(n.includes("--check")||E===void 0)&&v.state!=="fresh"&&(a.exitCode=1);return}if(m==="capture"){let{captureShaders:g}=await import('./shader-workflow-AAH3FM4U.js'),{applyShaderAutoWire:W,hasRegisterDevtoolsCall:v,inspectShaderAutoWire:U}=await import('./shader-autowire-DCODBFMX.js'),{buildShaderCaptureProject:j,startNextShaderCaptureServer:I}=await import('./shader-project-runner-GUR3LTYS.js'),{inferShaderCaptureTarget:P}=await import('./shader-config-BYBJUL3C.js'),T=x,B=h,J=k,D,O,z;try{if(T===void 0&&B===void 0&&J===void 0){let o=await U(l);if(!o.configured&&o.plan!==void 0){if(!await ce(o.plan.diff))throw new Error("Adapter wiring was declined; no files were changed.");await W(o.plan);}else if(!o.configured&&o.bundler!=="vite"&&o.bundler!=="unknown")throw new Error(`${o.reason} No files were changed.`);if(o.bundler==="next")O=C("starting the project-local Next.js capture server"),D=await I(l),J=D.url,O.update("capturing shader scenes");else if(o.bundler==="webpack"||o.bundler==="esbuild"||o.bundler==="rollup"){O=C(`building the ${o.bundler} capture target`),await j(l);let N=await P(l);if(N.driverKind!=="static"||N.serve===void 0)throw new Error(`${o.bundler} build completed but no dist/, build/, or out/index.html was found; pass --driver static --serve <directory>.`);T="static",B=N.serve,O.update("capturing shader scenes");}}O??=C("capturing shader scenes"),z=await g({root:l,headed:n.includes("--headed"),ifStale:n.includes("--if-stale"),commitTiming:n.includes("--commit-timing"),...T===void 0?{}:{driverKind:T},...B===void 0?{}:{serve:B},...J===void 0?{}:{url:J},onSceneStart:a$1((o,N,K)=>O?.update(`capturing ${b$1.accent(o)} ${b$1.dim(`(${N+1}/${K})`)}`),"onSceneStart"),onSceneRetry:a$1((o,N,K,re,V)=>{let ae=V instanceof Error&&/timed out/iu.test(V.message),ne=`capture attempt ${N}/${K} for "${o}" after ${ae?`timeout (${Math.round(re/1e3)} s burned)`:`failure (${V instanceof Error?V.message:String(V)})`}`;a.stderr.write(w?`${JSON.stringify({type:"shader-capture-retry",scene:o,attempt:N,total:K,timeoutMs:re,message:ne})}
13
13
  `:`${ne}
14
14
  `);},"onSceneRetry")});}finally{O?.stop(),await D?.close();}if(a.stdout.write(`${w?JSON.stringify(z,null,2):oe(z)}
15
15
  `),!await v(l)){let o="Add registerDevtools({ renderer }) from three-blocks/devtools so committed shader artifacts hydrate in development and production.";a.stderr.write(w?`${JSON.stringify({type:"shader-runtime-registration",state:"missing",message:o})}
16
16
  `:`${c.warn} ${o}
17
- `);}return}if(m==="test"){let g=b("--mode");if(g!==void 0&&g!=="strict")throw new Error('--mode currently supports only "strict".');let{testShaders:W}=await import('./shader-workflow-SO7WCR4Y.js'),v=C("verifying precompiled shaders against the live baseline"),U=$("--runs"),j;try{j=await W({root:l,headed:n.includes("--headed"),skipBrowser:n.includes("--skip-browser"),...x===void 0?{}:{driverKind:x},...h===void 0?{}:{serve:h},...k===void 0?{}:{url:k},...U===void 0?{}:{runs:U},parityOnly:n.includes("--parity-only"),commitTiming:n.includes("--commit-timing"),onSceneStart:a$1((I,P,T)=>v.update(`verifying ${b$1.accent(I)} ${b$1.dim(`(${P+1}/${T})`)}`),"onSceneStart")});}finally{v.stop();}a.stdout.write(`${w?JSON.stringify(j,null,2):fe(j)}
18
- `);return}let R=$("--debounce"),{watchShaders:_}=await import('./shader-watch-Z3VGP4QB.js'),q=new AbortController;a.once("SIGINT",()=>q.abort()),a.once("SIGTERM",()=>q.abort());let L=await _({root:l,headed:n.includes("--headed"),...x===void 0?{}:{driverKind:x},...h===void 0?{}:{serve:h},...k===void 0?{}:{url:k},...R===void 0?{}:{debounceMs:R},signal:q.signal,onResult(g){a.stdout.write(`${w?JSON.stringify(g):oe(g)}
17
+ `);}return}if(m==="test"){let g=b("--mode");if(g!==void 0&&g!=="strict")throw new Error('--mode currently supports only "strict".');let{testShaders:W}=await import('./shader-workflow-AAH3FM4U.js'),v=C("verifying precompiled shaders against the live baseline"),U=$("--runs"),j;try{j=await W({root:l,headed:n.includes("--headed"),skipBrowser:n.includes("--skip-browser"),...x===void 0?{}:{driverKind:x},...h===void 0?{}:{serve:h},...k===void 0?{}:{url:k},...U===void 0?{}:{runs:U},parityOnly:n.includes("--parity-only"),commitTiming:n.includes("--commit-timing"),onSceneStart:a$1((I,P,T)=>v.update(`verifying ${b$1.accent(I)} ${b$1.dim(`(${P+1}/${T})`)}`),"onSceneStart")});}finally{v.stop();}a.stdout.write(`${w?JSON.stringify(j,null,2):fe(j)}
18
+ `);return}let R=$("--debounce"),{watchShaders:_}=await import('./shader-watch-EI5D7GCN.js'),q=new AbortController;a.once("SIGINT",()=>q.abort()),a.once("SIGTERM",()=>q.abort());let L=await _({root:l,headed:n.includes("--headed"),...x===void 0?{}:{driverKind:x},...h===void 0?{}:{serve:h},...k===void 0?{}:{url:k},...R===void 0?{}:{debounceMs:R},signal:q.signal,onResult(g){a.stdout.write(`${w?JSON.stringify(g):oe(g)}
19
19
  `);},onError(g){a.stderr.write(`${w?JSON.stringify({error:g.message}):`${c.cross} ${b$1.danger(g.message)}`}
20
- `);}});w||f(A(c.ring,"watching",b$1.dim(L.root))),await L.done;return}if(y==="text"&&E&&E!=="status"){if(E!=="generate")throw new Error(`Unsupported text command "${E}".`);let{generateTextAtlases:d$1}=await import('./text-atlas-BHPSDU7C.js'),{findProjectRoot:m}=await import('./status-CFJSWBDI.js'),M=n.indexOf("--config"),l=M===-1?"three-blocks.text.ts":n[M+1];if(l===void 0||l.startsWith("--"))throw new Error("--config requires a project-relative path.");let S=await m(),x=C("generating MSDF text atlases"),h;try{h=await d$1(S,l);}finally{x.stop();}if(w)a.stdout.write(`${JSON.stringify(h,null,2)}
21
- `);else {f(A(c.tick,"text",`${h.glyphs} glyphs ${c.dot} ${h.atlases.length} atlas${h.atlases.length===1?"":"es"} regenerated`));for(let k of h.updatedFiles)f(` ${d(b$1.dim("updated"),12)} ${b$1.dim(k)}`);}return}if(!["status","text"].includes(y))throw new Error(`Unknown command "${y}".`);let{formatThreeBlocksStatus:e,inspectThreeBlocksStatus:t,threeBlocksStatusIsFresh:i}=await import('./status-CFJSWBDI.js'),r=await t(),c$1=(r.text);if(y==="text"&&!c$1)throw new Error("This project does not enable the text feature.");let f$1=y==="text"?c$1:r;a.stdout.write(`${w?JSON.stringify(f$1,null,2):y==="status"?e(r):JSON.stringify(f$1,null,2)}
20
+ `);}});w||f(A(c.ring,"watching",b$1.dim(L.root))),await L.done;return}if(y==="text"&&E&&E!=="status"){if(E!=="generate")throw new Error(`Unsupported text command "${E}".`);let{generateTextAtlases:d$1}=await import('./text-atlas-BHPSDU7C.js'),{findProjectRoot:m}=await import('./status-76TXXSRT.js'),M=n.indexOf("--config"),l=M===-1?"three-blocks.text.ts":n[M+1];if(l===void 0||l.startsWith("--"))throw new Error("--config requires a project-relative path.");let S=await m(),x=C("generating MSDF text atlases"),h;try{h=await d$1(S,l);}finally{x.stop();}if(w)a.stdout.write(`${JSON.stringify(h,null,2)}
21
+ `);else {f(A(c.tick,"text",`${h.glyphs} glyphs ${c.dot} ${h.atlases.length} atlas${h.atlases.length===1?"":"es"} regenerated`));for(let k of h.updatedFiles)f(` ${d(b$1.dim("updated"),12)} ${b$1.dim(k)}`);}return}if(!["status","text"].includes(y))throw new Error(`Unknown command "${y}".`);let{formatThreeBlocksStatus:e,inspectThreeBlocksStatus:t,threeBlocksStatusIsFresh:i}=await import('./status-76TXXSRT.js'),r=await t(),c$1=(r.text);if(y==="text"&&!c$1)throw new Error("This project does not enable the text feature.");let f$1=y==="text"?c$1:r;a.stdout.write(`${w?JSON.stringify(f$1,null,2):y==="status"?e(r):JSON.stringify(f$1,null,2)}
22
22
  `),y==="status"&&n.includes("--check")&&!i(r)&&(a.exitCode=1);}a$1(he,"main");he().catch(e=>{let t=e instanceof Error?e.message:String(e);w?a.stderr.write(`${JSON.stringify({error:t})}
23
23
  `):a.stderr.write(`${c.cross} ${b$1.danger(t)}
24
24
  `),a.exitCode=1;});
package/dist/index.d.ts CHANGED
@@ -247,18 +247,20 @@ declare function ensureShaderToolConfig(root: string): Promise<EnsuredShaderTool
247
247
  /** Published devtools protocol/package version. Kept dependency-free for instant CLI startup. */
248
248
  declare const SHADER_DEVTOOLS_VERSION: "0.1.0";
249
249
 
250
- declare const SHADER_PROVIDER_TRANSFORM_VERSION: 50;
250
+ declare const SHADER_PROVIDER_TRANSFORM_VERSION: 52;
251
251
  declare const SHADER_LOCAL_TIMING_FILE: "timing.local.json";
252
252
  declare const SHADER_COMMITTED_TIMING_FILE: "timing.json";
253
253
  declare const SHADER_PARITY_EVIDENCE_FILE: "parity.json";
254
254
  interface ShaderSceneTiming {
255
255
  /** Number of registered render/compute NodeBuilder builds covered by the manifest. */
256
256
  readonly builds: number;
257
+ /** True when the A/B measured and subtracted precompiled setup and hydration. */
258
+ readonly setupMeasured?: boolean;
257
259
  /** Cumulative NodeBuilder time observed while shaders build live. */
258
260
  readonly liveBuildMs: number;
259
- /** Observed precompiled time, or zero for the single-capture hydration estimate. */
261
+ /** Observed precompiled NodeBuilder setup/hydration time, or zero for a capture-only estimate. */
260
262
  readonly precompiledBuildMs: number;
261
- /** Non-negative live minus precompiled NodeBuilder time. */
263
+ /** Non-negative live minus precompiled NodeBuilder setup/hydration time. */
262
264
  readonly avoidedBuildMs: number;
263
265
  /** One for a capture estimate; greater than one for warmed live/precompiled medians. */
264
266
  readonly runs: number;
@@ -309,6 +311,20 @@ interface ShaderCaptureStats {
309
311
  readonly registeredRenderBuilds: number;
310
312
  readonly registeredComputeBuilds: number;
311
313
  readonly buildMs: number;
314
+ /** Synchronous `build()` time. */
315
+ readonly syncBuildMs?: number;
316
+ /** `buildAsync()` wall time, including yielded time between stages. */
317
+ readonly asyncBuildElapsedMs?: number;
318
+ /** Synchronous `prepareForHydration()` time retained by hydration. */
319
+ readonly precompiledSetupMs?: number;
320
+ /** Longest synchronous `build()` call. */
321
+ readonly maxSyncBuildMs?: number;
322
+ /** Longest synchronous `prepareForHydration()` call. */
323
+ readonly maxPrecompiledSetupMs?: number;
324
+ /** Total synchronous declaration/binding replay time. */
325
+ readonly hydrationMs?: number;
326
+ /** Longest synchronous declaration/binding replay call. */
327
+ readonly maxHydrationMs?: number;
312
328
  readonly injected: number;
313
329
  readonly injectedRender: number;
314
330
  readonly injectedCompute: number;
@@ -338,6 +354,7 @@ interface ShaderCapturePayload extends Pick<PrecompiledManifest, 'modules' | 'no
338
354
  readonly automatic?: {
339
355
  readonly prefix: string;
340
356
  };
357
+ readonly requiresSetup: boolean;
341
358
  readonly skipped: readonly ShaderSkippedBuild[];
342
359
  readonly errors: readonly string[];
343
360
  readonly stats: ShaderCaptureStats;
@@ -412,6 +429,8 @@ interface ShaderBrowserObservation {
412
429
  readonly stats: ShaderCaptureStats;
413
430
  /** Application animation frame frozen for deterministic live/precompiled parity. */
414
431
  readonly frame: number;
432
+ /** First observable rendered frame, before configured settling. */
433
+ readonly firstFrameScreenshot: Buffer;
415
434
  readonly screenshot: Buffer;
416
435
  readonly errors: readonly string[];
417
436
  }
@@ -592,9 +611,9 @@ interface TestShadersOptions {
592
611
  interface ShaderSceneTestResult {
593
612
  readonly scene: string;
594
613
  readonly coverage: ShaderCoverage;
595
- readonly live: Omit<ShaderBrowserObservation, 'screenshot'>;
596
- readonly precompiled: Omit<ShaderBrowserObservation, 'screenshot'>;
597
- readonly published?: Omit<ShaderPublishedObservation, 'beforeScreenshot' | 'screenshot'>;
614
+ readonly live: Omit<ShaderBrowserObservation, 'firstFrameScreenshot' | 'screenshot'>;
615
+ readonly precompiled: Omit<ShaderBrowserObservation, 'firstFrameScreenshot' | 'screenshot'>;
616
+ readonly published?: Omit<ShaderPublishedObservation, 'beforeScreenshot' | 'firstFrameScreenshot' | 'screenshot'>;
598
617
  readonly parity: Omit<ShaderParityResult, 'diff'>;
599
618
  readonly runtimeMotion?: {
600
619
  readonly differentPixels: number;