@three-blocks/devtools 11.0.0 → 11.1.0-alpha.394.gd927ae9c8e86

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.
Files changed (77) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/NOTICE +26 -0
  3. package/README.md +117 -170
  4. package/dist/asset-optimize-YJGWKD4Y.js +1 -0
  5. package/dist/asset-transforms-ZVZ4RD4L.js +11 -0
  6. package/dist/browser/shader-capture.js +2 -2
  7. package/dist/browser-smoke-4MYMHKWB.js +1 -0
  8. package/dist/chunk-4SVF5BRM.js +2 -0
  9. package/dist/chunk-7X4DHW36.js +1 -0
  10. package/dist/chunk-BBODS5RH.js +5 -0
  11. package/dist/{chunk-IILE5RBI.js → chunk-CMMYXGQ3.js} +1 -2
  12. package/dist/chunk-DCLDEPPB.js +253 -0
  13. package/dist/{chunk-5L2VS3BN.js → chunk-ECQE4D2U.js} +1 -2
  14. package/dist/chunk-IWQV456Z.js +3 -0
  15. package/dist/chunk-LSH64HEU.js +80 -0
  16. package/dist/{chunk-X5OFYHIY.js → chunk-MIJXPQPM.js} +2 -3
  17. package/dist/chunk-NDIPQLTU.js +16 -0
  18. package/dist/{chunk-NPLE7PPF.js → chunk-NJITVI23.js} +1 -2
  19. package/dist/chunk-O5FU2ASS.js +16 -0
  20. package/dist/chunk-QQKHDH26.js +1 -0
  21. package/dist/chunk-S5LI2C2H.js +5 -0
  22. package/dist/chunk-SBUKHO24.js +1 -0
  23. package/dist/chunk-TK566QET.js +1 -0
  24. package/dist/{chunk-65VEJRRT.js → chunk-WNSGAV6N.js} +1 -2
  25. package/dist/chunk-ZG3LO3VB.js +1 -0
  26. package/dist/{chunk-UDUICSME.js → chunk-ZTHZE36A.js} +1 -1
  27. package/dist/cli.d.ts +1 -0
  28. package/dist/cli.js +26 -26
  29. package/dist/environment-bake-ON5I27N7.js +1 -0
  30. package/dist/index.d.ts +24 -12
  31. package/dist/index.js +1 -279
  32. package/dist/{shader-autowire-SPE5DM2X.js → shader-autowire-D2EOG6GF.js} +1 -2
  33. package/dist/shader-browser-6ICBHK3S.js +1 -0
  34. package/dist/shader-capture-server.d.ts +1 -1
  35. package/dist/shader-capture-server.js +1 -1
  36. package/dist/{shader-config-EOFU5D3Y.js → shader-config-AKZEKIRB.js} +1 -2
  37. package/dist/{shader-parity-QXJWR6OZ.js → shader-parity-7DEPQEDI.js} +1 -1
  38. package/dist/{shader-project-runner-S2AID2RJ.js → shader-project-runner-NV4GKHDX.js} +1 -2
  39. package/dist/shader-watch-JBUA4LP5.js +1 -0
  40. package/dist/shader-workflow-5EHHR32D.js +1 -0
  41. package/dist/status-GDVSLQWV.js +1 -0
  42. package/dist/text-atlas-YYWV7S6F.js +1 -0
  43. package/dist/transform.cjs +1 -1
  44. package/dist/transform.js +1 -1
  45. package/dist/webpack-loader.cjs +1 -1
  46. package/dist/webpack-loader.js +1 -1
  47. package/node/index.d.mts +70 -0
  48. package/node/index.mjs +407 -0
  49. package/node/ipc.mjs +31 -0
  50. package/node/layout.mjs +546 -0
  51. package/node/loader.mjs +103 -0
  52. package/node/media.mjs +454 -0
  53. package/node/recording.mjs +67 -0
  54. package/node/worker.mjs +1314 -0
  55. package/package.json +27 -11
  56. package/dist/asset-optimize-GG72JCOX.js +0 -6
  57. package/dist/browser-smoke-KFF7XV7F.js +0 -254
  58. package/dist/chunk-45AVKQQK.js +0 -80
  59. package/dist/chunk-5FT6AZD6.js +0 -82
  60. package/dist/chunk-7N6TU4JG.js +0 -17
  61. package/dist/chunk-EI7MMDWY.js +0 -1
  62. package/dist/chunk-HOZDD6PW.js +0 -2
  63. package/dist/chunk-LKXY5YU2.js +0 -17
  64. package/dist/chunk-MIUIIPS4.js +0 -1
  65. package/dist/chunk-NF4RFSUJ.js +0 -18
  66. package/dist/chunk-QJFPNM6W.js +0 -2
  67. package/dist/chunk-ZT6T2W4B.js +0 -2
  68. package/dist/chunk-ZZLAZ7GJ.js +0 -6
  69. package/dist/environment-bake-BGMGFAVK.js +0 -4
  70. package/dist/shader-browser-H5CB2ZQX.js +0 -2
  71. package/dist/shader-browser-UXXR6QI2.js +0 -1
  72. package/dist/shader-parity-XPKQQK26.js +0 -2
  73. package/dist/shader-watch-EORZ2SEC.js +0 -2
  74. package/dist/shader-workflow-7NQFDQI5.js +0 -2
  75. package/dist/status-PTBB4SW2.js +0 -2
  76. package/dist/text-atlas-UORTLOQJ.js +0 -2
  77. /package/dist/{chunk-TRHSN2DJ.cjs → chunk-LMLJIVNY.cjs} +0 -0
package/dist/cli.js CHANGED
@@ -1,30 +1,30 @@
1
1
  #!/usr/bin/env node
2
- import {c,b,h as h$1,e,a as a$2,f,d}from'./chunk-IILE5RBI.js';import {a as a$1}from'./chunk-ZT6T2W4B.js';import {a}from'./chunk-HOZDD6PW.js';import s from'process';var n=s.argv.slice(2),ae=n.indexOf("--reporter"),H=n.find(e=>e.startsWith("--reporter="))?.slice(11)??(ae===-1?void 0:n[ae+1]),ue=ae!==-1&&(H===void 0||H.startsWith("--"))?'--reporter requires "plain" or "json".':H!==void 0&&H!=="json"&&H!=="plain"?'--reporter must be "plain" or "json".':void 0,h=n.includes("--json")||H==="json",pe=new Set(["--reporter","--root","--route","--build-mode","--expect-shaders","--width","--height","--timeout","--settle","--min-luminance","--hmr","--size","--output","--driver","--serve","--url","--runs","--debounce","--config","--mode","--out","--max-dim","--hdr-max-dim","--quality","--preset"]),se=[];for(let e=0;e<n.length;e++){let t=n[e];if(t!==void 0){if(t.startsWith("--")){pe.has(t)&&e++;continue}se.push(t);}}var y=se[0]??"status",O=se[1];function $(e){let t=n.find(c=>c.startsWith(`${e}=`));if(t!==void 0){let c=t.slice(e.length+1);if(c.length===0)throw new Error(`${e} requires a value.`);return c}let o=n.indexOf(e);if(o===-1)return;let r=n[o+1];if(r===void 0||r.startsWith("--"))throw new Error(`${e} requires a value.`);return r}a($,"optionValue");function fe(e){let t=[];for(let o=0;o<n.length;o++){let r=n[o];if(r!==void 0){if(r.startsWith(`${e}=`)){let c=r.slice(e.length+1);if(c.length===0)throw new Error(`${e} requires a value.`);t.push(c);}else if(r===e){let c=n[o+1];if(c===void 0||c.startsWith("--"))throw new Error(`${e} requires a value.`);t.push(c);}}}return t}a(fe,"optionValues");function k(e){let t=$(e);if(t===void 0)return;let o=Number(t);if(!Number.isFinite(o))throw new Error(`${e} must be a finite number.`);return o}a(k,"numberOption");async function he(e){let t=`Shader provider adapter patch:
2
+ import {c,b as b$1,h,e,a as a$2,f,d}from'./chunk-CMMYXGQ3.js';import {a as a$1}from'./chunk-TK566QET.js';import {g}from'./chunk-NJITVI23.js';import'./chunk-WNSGAV6N.js';import'./chunk-ECQE4D2U.js';import {a}from'./chunk-7X4DHW36.js';import s from'process';var n=s.argv.slice(2),de=n.indexOf("--reporter"),H=n.find(e=>e.startsWith("--reporter="))?.slice(11)??(de===-1?void 0:n[de+1]),ce=de!==-1&&(H===void 0||H.startsWith("--"))?'--reporter requires "plain" or "json".':H!==void 0&&H!=="json"&&H!=="plain"?'--reporter must be "plain" or "json".':void 0,m=n.includes("--json")||H==="json",fe=new Set(["--reporter","--root","--route","--build-mode","--expect-shaders","--width","--height","--timeout","--settle","--min-luminance","--hmr","--size","--output","--driver","--serve","--url","--runs","--debounce","--config","--mode","--out","--max-dim","--hdr-max-dim","--quality","--preset"]),oe=[];for(let e=0;e<n.length;e++){let t=n[e];if(t!==void 0){if(t.startsWith("--")){fe.has(t)&&e++;continue}oe.push(t);}}var y=oe[0]??"status",O=oe[1];function b(e){let t=n.find(i=>i.startsWith(`${e}=`));if(t!==void 0){let i=t.slice(e.length+1);if(i.length===0)throw new Error(`${e} requires a value.`);return i}let a=n.indexOf(e);if(a===-1)return;let d=n[a+1];if(d===void 0||d.startsWith("--"))throw new Error(`${e} requires a value.`);return d}a(b,"optionValue");function me(e){let t=[];for(let a=0;a<n.length;a++){let d=n[a];if(d!==void 0){if(d.startsWith(`${e}=`)){let i=d.slice(e.length+1);if(i.length===0)throw new Error(`${e} requires a value.`);t.push(i);}else if(d===e){let i=n[a+1];if(i===void 0||i.startsWith("--"))throw new Error(`${e} requires a value.`);t.push(i);}}}return t}a(me,"optionValues");function x(e){let t=b(e);if(t===void 0)return;let a=Number(t);if(!Number.isFinite(a))throw new Error(`${e} must be a finite number.`);return a}a(x,"numberOption");async function he(e){let t=`Shader provider adapter patch:
3
3
  ${e}
4
- `;if(s.stderr.write(h?`${JSON.stringify({type:"shader-adapter-diff",diff:e})}
5
- `:t),n.includes("--yes"))return true;if(!s.stdin.isTTY||!s.stderr.isTTY)throw new Error("Adapter wiring needs consent. Review the diff above, then rerun with --yes; no files were changed.");let{createInterface:o}=await import('readline/promises'),r=o({input:s.stdin,output:s.stderr});try{let c=await r.question("Apply this patch? (y/N) ");return /^y(?:es)?$/iu.test(c.trim())}finally{r.close();}}a(he,"approveAdapterPatch");function C(e){return h?{update(){},stop(){}}:h$1(e)}a(C,"wait");function me(){let e$1=a(b$1=>b.accent(b$1),"c"),t=a(b$1=>b.dim(b$1),"d"),o=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"],[`${e$1("assets status")}`,"optimized-asset receipt freshness"]]],["Produce",[[`${e$1("shaders capture")} ${t("[--if-stale] [--commit-timing] [--no-assets]")}`,"capture shaders plus a local timing estimate, then optimize public GLB/.hdr assets; during development use the overlay Capture button"],[`${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"],[`${e$1("assets optimize")} ${t("<file|dir\u2026> [--out <dir>] [--quality high]")}`,"meshopt + slot-aware KTX2 for GLB / image / .hdr inputs"]]],["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=["",`${o}${b.bold("three-blocks devtools")} ${b.dim(`v${a$1}`)}`,b.dim("WebGPU shader precompilation and verification for Three Blocks projects."),"",`${b.bold("Usage")}`,` ${e$1("three-blocks-devtools")} ${t("[command] [options] [--json]")}`];for(let[b$1,a]of r)c$1.push("",b.bold(b$1),...e(a,{indent:2,maxWidth:a$2.width-2}));c$1.push("",b.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("--backend <webgpu|webgl|both>"),"select shader backend lanes (default: config, then both)"],[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"],[t("--out <dir>"),"assets optimize: output directory (default: beside each input)"],[t("--max-dim <px>"),"assets optimize: LDR texture cap (default 2048)"],[t("--quality <default|high>"),"assets optimize: high = UASTC color + higher encoder effort"],[t("--preset <color|normal|data>"),"assets optimize: override the standalone-image preset"],[t("--force"),"assets optimize: re-encode even when cached"]],{indent:2,maxWidth:a$2.width-2}),"",b.dim("During development, use the in-page overlay Capture button for one-click recapture."),b.dim("`shaders capture` remains the explicit isolated-browser fallback for batch and CI."),""),f(c$1.join(`
6
- `));}a(me,"help");function we(e){return e?`${e.render} render \xB7 ${e.compute} compute`:"no coverage"}a(we,"coverageText");function ie(e){return e<100?e.toFixed(1):Math.round(e).toString()}a(ie,"milliseconds");function L(e,t,o){return `${e} ${d(t,12)} ${o}`}a(L,"row");function ce(e$1){if(e$1.skipped)return L(c.tick,"shaders",`fresh ${c.dot} capture skipped ${b.dim(`(--if-stale) \xB7 ${e$1.reason}`)}`);let t=Math.max(0,Math.round((e$1.durationMs??0)/1e3)),o=e$1.scenes.length,r=[L(c.tick,"shaders",`captured in ${t} s ${c.dot} wrote ${o} shader scene${o===1?"":"s"}`)];e$1.configuration?.created===true&&r.push(b.dim(` created ${e$1.configuration.file} with the default "/" capture route`));for(let b$1 of e$1.scenes)r.push(L(c.tick,b$1.scene,`${we(b$1.coverage)} ${c.dot} ${b.dim(`${b$1.attempts} attempt${b$1.attempts===1?"":"s"}`)}`));let c$1=e$1.scenes.flatMap(b=>{let a$1=b.timing;if(a$1?.launch===void 0||a$1.firstRequest===void 0||a$1.readiness===void 0||a$1.lastBuild===void 0||a$1.settled===void 0||a$1.posted===void 0)return [];let m=a((R,l)=>`${ie(Math.max(0,l-R))} ms`,"elapsed");return [[b.scene,`launch\u2192request ${m(a$1.launch,a$1.firstRequest)} ${c.dot} ready ${m(a$1.firstRequest,a$1.readiness)} ${c.dot} last build ${m(a$1.readiness,a$1.lastBuild)} ${c.dot} settle ${m(a$1.lastBuild,a$1.settled)} ${c.dot} post ${m(a$1.settled,a$1.posted)}`]]});return c$1.length>0&&r.push("",b.bold("Capture stages"),...e(c$1,{indent:2,maxWidth:a$2.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${ie(Math.abs(e$1.measurement.firstFrameDeltaMs))} ms TSL work avoided (single-capture estimate)`),r.push(b.dim(" a running dev server reloads on its own; otherwise refresh the page")),r.join(`
7
- `)}a(ce,"formatShaderCapture");function ge(e){let t=[L(c.tick,"shaders",`no-GPU ${e.noGpu.state} ${c.dot} browser ${e.browser}`)];for(let o of e.scenes){let r=e.timing?.scenes[o.scene],c$1=r===void 0?`${o.coverage.render+o.coverage.compute} TSL build${o.coverage.render+o.coverage.compute===1?"":"s"} skipped`:`${r.builds} TSL build${r.builds===1?"":"s"} skipped ${c.dot} \u2248${ie(r.avoidedBuildMs)} ms \xB1 ${ie(r.spreadMs)} TSL work avoided ${c.dot} median of ${r.runs} ${c.dot} Latest local capture`,b$1=r!==void 0&&r.spreadMs>r.avoidedBuildMs*.4?` ${c.dot} ${b.warn("noisy measurement \u2014 close other GPU apps and re-run")}`:"";t.push(L(c.tick,o.scene,`${c$1} ${c.dot} ${o.coverage.compute} compute ${c.dot} ${(o.parity.diffRatio*100).toFixed(3)}% pixel diff${b$1}`));}return t.join(`
8
- `)}a(ge,"formatShaderTest");async function $e(){if(ue!==void 0)throw new Error(ue);if(y==="help"||y==="--help"||n.includes("--help"))return me();if(y==="version"||n.includes("--version")){f(h?JSON.stringify({version:a$1}):a$1);return}if(y==="browser"){let{formatBrowserPreviewReport:a,formatBrowserSmokeReport:m,runBrowserPreview:R,runBrowserSmoke:l}=await import('./browser-smoke-KFF7XV7F.js'),{findProjectRoot:v}=await import('./status-PTBB4SW2.js');if(O==="preview"){let T=$("--root")??await v(),M=fe("--route"),F=$("--build-mode"),A=$("--expect-shaders")??"precompiled";if(A!=="precompiled"&&A!=="live")throw new Error('--expect-shaders must be "precompiled" or "live".');let _=k("--width"),X=k("--height"),P=k("--timeout"),V=k("--settle"),K=k("--min-luminance"),Y=C("building and verifying the production bundle"),z;try{z=await R({root:T,...M.length===0?{}:{routes:M},...F===void 0?{}:{buildMode:F},expectShaders:A,text:n.includes("--text"),...P===void 0?{}:{timeoutMs:P},...V===void 0?{}:{settleMs:V},...K===void 0?{}:{minimumLuminance:K},..._===void 0&&X===void 0?{}:{viewport:{width:_??1024,height:X??640}},headed:n.includes("--headed")});}finally{Y.stop();}s.stdout.write(`${h?JSON.stringify(z,null,2):a(z)}
9
- `),z.passed||(s.exitCode=1);return}if(O!=="smoke")throw new Error(`Unsupported browser command "${O??""}".`);let w=$("--root")??await v(),p=k("--width"),E=k("--height"),S=$("--route"),N=k("--timeout"),G=k("--settle"),I=k("--min-luminance"),j=$("--hmr");if(n.includes("--webgl")&&n.includes("--unsupported-worker"))throw new Error("--webgl and --unsupported-worker are mutually exclusive.");let B=C(`smoking ${S??"/"} in a real browser`),g;try{g=await l({root:w,...S===void 0?{}:{route:S},...N===void 0?{}:{timeoutMs:N},...G===void 0?{}:{settleMs:G},...I===void 0?{}:{minimumLuminance:I},...j===void 0?{}:{hmrModule:j},forceWebgl:n.includes("--webgl"),unsupportedWorker:n.includes("--unsupported-worker"),expectTextGenerationFailure:n.includes("--expect-text-generation-failure"),...p===void 0&&E===void 0?{}:{viewport:{width:p??1024,height:E??640}},headed:n.includes("--headed")});}finally{B.stop();}s.stdout.write(`${h?JSON.stringify(g,null,2):m(g)}
10
- `),g.passed||(s.exitCode=1);return}if(y==="assets"||y==="optimize"){let a$1=y==="optimize"?"optimize":O??"status",m=se.slice(y==="optimize"?1:2),{findProjectRoot:R}=await import('./status-PTBB4SW2.js'),l=$("--root")??await R().catch(()=>s.cwd());if(a$1==="status"){let{formatAssetStatusReport:B,inspectAssets:g}=await import('./asset-optimize-GG72JCOX.js'),T=await g(l);s.stdout.write(`${h?JSON.stringify(T,null,2):B(T)}
11
- `),n.includes("--check")&&T.state==="stale"&&(s.exitCode=1);return}if(a$1!=="optimize")throw new Error(`Unsupported assets command "${a$1}".`);if(m.length===0)throw new Error("assets optimize needs at least one file or directory (.glb, .png, .jpg, .webp, .hdr).");let v=$("--quality");if(v!==void 0&&v!=="default"&&v!=="high")throw new Error('--quality must be "default" or "high".');let w=$("--preset");if(w!==void 0&&w!=="color"&&w!=="normal"&&w!=="data")throw new Error('--preset must be "color", "normal", or "data".');let p=$("--out"),E=k("--max-dim"),S=k("--hdr-max-dim"),{formatAssetOptimizeReport:N,optimizeAssets:G}=await import('./asset-optimize-GG72JCOX.js'),I=C("optimizing assets"),j;try{j=await G({root:l,inputs:m,...p===void 0?{}:{outDir:p},...E===void 0?{}:{maxDimension:E},...S===void 0?{}:{hdrMaxDimension:S},...v===void 0?{}:{quality:v},...w===void 0?{}:{preset:w},force:n.includes("--force"),onProgress:a(B=>I.update(`optimizing ${b.accent(B)}`),"onProgress")});}finally{I.stop();}s.stdout.write(`${h?JSON.stringify(j,null,2):N(j)}
12
- `),j.failed.length>0&&(s.exitCode=1);return}if(y==="environment"){if(O!=="bake")throw new Error(`Unsupported environment command "${O??""}".`);let{bakeRoomEnvironment:a,formatEnvironmentBakeReport:m}=await import('./environment-bake-BGMGFAVK.js'),{findProjectRoot:R}=await import('./status-PTBB4SW2.js'),l=$("--root")??await R(),v=k("--size"),w=$("--output"),p=k("--timeout"),E=C("baking the room environment on the GPU"),S;try{S=await a({root:l,...v===void 0?{}:{size:v},...w===void 0?{}:{output:w},...p===void 0?{}:{timeoutMs:p},compression:n.includes("--no-zstd")?"none":"zstd",headed:n.includes("--headed")});}finally{E.stop();}s.stdout.write(`${h?JSON.stringify(S,null,2):m(S)}
13
- `);return}if(y==="shaders"){let{findShaderProjectRoot:a$1}=await import('./shader-config-EOFU5D3Y.js'),m=O??"status";if(!["status","capture","test","watch"].includes(m))throw new Error(`Unsupported shader command "${m}".`);let R=$("--root"),l=await a$1(R),v=$("--driver");if(v!==void 0&&v!=="vite"&&v!=="static")throw new Error('--driver must be "vite" or "static".');let w=v,p=$("--serve"),E=$("--url"),S=$("--backend");if(S!==void 0&&S!=="webgpu"&&S!=="webgl"&&S!=="both")throw new Error('--backend must be "webgpu", "webgl", or "both".');let N=S;if(m==="status"){let{inspectShaderMatrix:g}=await import('./shader-workflow-7NQFDQI5.js'),{formatShaderMatrixStatus:T}=await import('./status-PTBB4SW2.js'),M=await g(l,void 0,N);s.stdout.write(`${h?JSON.stringify(M,null,2):T(M)}
14
- `),(n.includes("--check")||O===void 0)&&M.state!=="fresh"&&(s.exitCode=1);return}if(m==="capture"){let{captureShaders:g}=await import('./shader-workflow-7NQFDQI5.js'),{applyShaderAutoWire:T,hasRegisterDevtoolsCall:M,inspectShaderAutoWire:F}=await import('./shader-autowire-SPE5DM2X.js'),{buildShaderCaptureProject:A,startNextShaderCaptureServer:_}=await import('./shader-project-runner-S2AID2RJ.js'),{inferShaderCaptureTarget:X}=await import('./shader-config-EOFU5D3Y.js'),P=w,V=p,K=E,Y,z,Q;try{if(P===void 0&&V===void 0&&K===void 0){let d=await F(l);if(!d.configured&&d.plan!==void 0){if(!await he(d.plan.diff))throw new Error("Adapter wiring was declined; no files were changed.");await T(d.plan);}else if(!d.configured&&d.bundler!=="vite"&&d.bundler!=="unknown")throw new Error(`${d.reason} No files were changed.`);if(d.bundler==="next")z=C("starting the project-local Next.js capture server"),Y=await _(l),K=Y.url,z.update("capturing shader scenes");else if(d.bundler==="webpack"||d.bundler==="esbuild"||d.bundler==="rollup"){z=C(`building the ${d.bundler} capture target`),await A(l);let x=await X(l);if(x.driverKind!=="static"||x.serve===void 0)throw new Error(`${d.bundler} build completed but no dist/, build/, or out/index.html was found; pass --driver static --serve <directory>.`);P="static",V=x.serve,z.update("capturing shader scenes");}}z??=C("capturing shader scenes"),Q=await g({root:l,headed:n.includes("--headed"),ifStale:n.includes("--if-stale"),commitTiming:n.includes("--commit-timing"),...N===void 0?{}:{backend:N},...P===void 0?{}:{driverKind:P},...V===void 0?{}:{serve:V},...K===void 0?{}:{url:K},onSceneStart:a((d,x,W)=>z?.update(`capturing ${b.accent(d)} ${b.dim(`(${x+1}/${W})`)}`),"onSceneStart"),onSceneRetry:a((d,x,W,q,D)=>{let Z=D instanceof Error&&/timed out/iu.test(D.message),ee=`capture attempt ${x}/${W} for "${d}" after ${Z?`timeout (${Math.round(q/1e3)} s burned)`:`failure (${D instanceof Error?D.message:String(D)})`}`;s.stderr.write(h?`${JSON.stringify({type:"shader-capture-retry",scene:d,attempt:x,total:W,timeoutMs:q,message:ee})}
4
+ `;if(s.stderr.write(m?`${JSON.stringify({type:"shader-adapter-diff",diff:e})}
5
+ `:t),n.includes("--yes"))return true;if(!s.stdin.isTTY||!s.stderr.isTTY)throw new Error("Adapter wiring needs consent. Review the diff above, then rerun with --yes; no files were changed.");let{createInterface:a}=await import('readline/promises'),d=a({input:s.stdin,output:s.stderr});try{let i=await d.question("Apply this patch? (y/N) ");return /^y(?:es)?$/iu.test(i.trim())}finally{d.close();}}a(he,"approveAdapterPatch");function C(e){return m?{update(){},stop(){}}:h(e)}a(C,"wait");function we(){let e$1=a(h=>b$1.accent(h),"c"),t=a(h=>b$1.dim(h),"d"),a$3=c.mark?`${c.mark} `:"",d=[["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"],[`${e$1("assets status")}`,"optimized-asset receipt freshness"]]],["Produce",[[`${e$1("shaders capture")} ${t("[--if-stale] [--commit-timing] [--no-assets]")}`,"capture shaders plus a local timing estimate, then optimize public GLB/.hdr assets; during development use the overlay Capture button"],[`${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"],[`${e$1("assets optimize")} ${t("<file|dir\u2026> [--out <dir>] [--quality high]")}`,"meshopt + slot-aware KTX2 for GLB / image / .hdr inputs"]]],["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"]]]],i=["",`${a$3}${b$1.bold("three-blocks devtools")} ${b$1.dim(`v${a$1}`)}`,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[h,o]of d)i.push("",b$1.bold(h),...e(o,{indent:2,maxWidth:a$2.width-2}));i.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("--backend <webgpu|webgl|both>"),"select shader backend lanes (default: config, then both)"],[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"],[t("--out <dir>"),"assets optimize: output directory (default: beside each input)"],[t("--max-dim <px>"),"assets optimize: LDR texture cap (default 2048)"],[t("--quality <default|high>"),"assets optimize: high = UASTC color + higher encoder effort"],[t("--preset <color|normal|data>"),"assets optimize: override the standalone-image preset"],[t("--force"),"assets optimize: re-encode even when cached"]],{indent:2,maxWidth:a$2.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(i.join(`
6
+ `));}a(we,"help");function ge(e){return e?`${e.render} render \xB7 ${e.compute} compute`:"no coverage"}a(ge,"coverageText");function se(e){return e<100?e.toFixed(1):Math.round(e).toString()}a(se,"milliseconds");function B(e,t,a){return `${e} ${d(t,12)} ${a}`}a(B,"row");function le(e$1){if(e$1.skipped)return B(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)),a$1=e$1.scenes.length,d=[B(c.tick,"shaders",`captured in ${t} s ${c.dot} wrote ${a$1} shader scene${a$1===1?"":"s"}`)];e$1.configuration?.created===true&&d.push(b$1.dim(` created ${e$1.configuration.file} with the default "/" capture route`));for(let h of e$1.scenes)d.push(B(c.tick,g(h.scene,h.backend),`${ge(h.coverage)} ${c.dot} ${b$1.dim(`${h.attempts} attempt${h.attempts===1?"":"s"}`)}`));let i=e$1.scenes.flatMap(h=>{let o=h.timing;if(o?.launch===void 0||o.firstRequest===void 0||o.readiness===void 0||o.lastBuild===void 0||o.settled===void 0||o.posted===void 0)return [];let w=a((R,l)=>`${se(Math.max(0,l-R))} ms`,"elapsed");return [[g(h.scene,h.backend),`launch\u2192request ${w(o.launch,o.firstRequest)} ${c.dot} ready ${w(o.firstRequest,o.readiness)} ${c.dot} last build ${w(o.readiness,o.lastBuild)} ${c.dot} settle ${w(o.lastBuild,o.settled)} ${c.dot} post ${w(o.settled,o.posted)}`]]});return i.length>0&&d.push("",b$1.bold("Capture stages"),...e(i,{indent:2,maxWidth:a$2.width-2})),e$1.measurement!==void 0&&d.push(` TSL builds at startup: ${e$1.measurement.beforeBuilds} \u2192 ${e$1.measurement.afterBuilds} ${c.dot} \u2248${se(Math.abs(e$1.measurement.firstFrameDeltaMs))} ms TSL work avoided (single-capture estimate)`),d.push(b$1.dim(" a running dev server reloads on its own; otherwise refresh the page")),d.join(`
7
+ `)}a(le,"formatShaderCapture");function $e(e){let t=[B(c.tick,"shaders",`no-GPU ${e.noGpu.state} ${c.dot} browser ${e.browser}`)];e.native&&t.push(B(c.tick,"native raster parity",e.native));for(let a of e.scenes){let d=g(a.scene,a.backend),i=e.timing?.scenes[d],h=i===void 0?`${a.coverage.render+a.coverage.compute} TSL build${a.coverage.render+a.coverage.compute===1?"":"s"} skipped`:`${i.builds} TSL build${i.builds===1?"":"s"} skipped ${c.dot} \u2248${se(i.avoidedBuildMs)} ms \xB1 ${se(i.spreadMs)} TSL work avoided ${c.dot} median of ${i.runs} ${c.dot} Latest local capture`,o=i!==void 0&&i.spreadMs>i.avoidedBuildMs*.4?` ${c.dot} ${b$1.warn("noisy measurement \u2014 close other GPU apps and re-run")}`:"";t.push(B(c.tick,d,`${h} ${c.dot} ${a.coverage.compute} compute ${c.dot} ${(a.parity.diffRatio*100).toFixed(3)}% pixel diff${o}`));}return t.join(`
8
+ `)}a($e,"formatShaderTest");async function be(){if(ce!==void 0)throw new Error(ce);if(y==="help"||y==="--help"||n.includes("--help"))return we();if(y==="version"||n.includes("--version")){f(m?JSON.stringify({version:a$1}):a$1);return}if(y==="browser"){let{formatBrowserPreviewReport:o,formatBrowserSmokeReport:w,runBrowserPreview:R,runBrowserSmoke:l}=await import('./browser-smoke-4MYMHKWB.js'),{findProjectRoot:v}=await import('./status-GDVSLQWV.js');if(O==="preview"){let T=b("--root")??await v(),M=me("--route"),F=b("--build-mode"),A=b("--expect-shaders")??"precompiled";if(A!=="precompiled"&&A!=="live")throw new Error('--expect-shaders must be "precompiled" or "live".');let _=x("--width"),X=x("--height"),P=x("--timeout"),V=x("--settle"),K=x("--min-luminance"),Y=C("building and verifying the production bundle"),z;try{z=await R({root:T,...M.length===0?{}:{routes:M},...F===void 0?{}:{buildMode:F},expectShaders:A,text:n.includes("--text"),...P===void 0?{}:{timeoutMs:P},...V===void 0?{}:{settleMs:V},...K===void 0?{}:{minimumLuminance:K},..._===void 0&&X===void 0?{}:{viewport:{width:_??1024,height:X??640}},headed:n.includes("--headed")});}finally{Y.stop();}s.stdout.write(`${m?JSON.stringify(z,null,2):o(z)}
9
+ `),z.passed||(s.exitCode=1);return}if(O!=="smoke")throw new Error(`Unsupported browser command "${O??""}".`);let g=b("--root")??await v(),p=x("--width"),E=x("--height"),k=b("--route"),N=x("--timeout"),G=x("--settle"),I=x("--min-luminance"),j=b("--hmr");if(n.includes("--webgl")&&n.includes("--unsupported-worker"))throw new Error("--webgl and --unsupported-worker are mutually exclusive.");let J=C(`smoking ${k??"/"} in Node`),$;try{$=await l({root:g,...k===void 0?{}:{route:k},...N===void 0?{}:{timeoutMs:N},...G===void 0?{}:{settleMs:G},...I===void 0?{}:{minimumLuminance:I},...j===void 0?{}:{hmrModule:j},forceWebgl:n.includes("--webgl"),unsupportedWorker:n.includes("--unsupported-worker"),expectTextGenerationFailure:n.includes("--expect-text-generation-failure"),...p===void 0&&E===void 0?{}:{viewport:{width:p??1024,height:E??640}},headed:n.includes("--headed")});}finally{J.stop();}s.stdout.write(`${m?JSON.stringify($,null,2):w($)}
10
+ `),$.passed||(s.exitCode=1);return}if(y==="assets"||y==="optimize"){let o=y==="optimize"?"optimize":O??"status",w=oe.slice(y==="optimize"?1:2),{findProjectRoot:R}=await import('./status-GDVSLQWV.js'),l=b("--root")??await R().catch(()=>s.cwd());if(o==="status"){let{formatAssetStatusReport:J,inspectAssets:$}=await import('./asset-optimize-YJGWKD4Y.js'),T=await $(l);s.stdout.write(`${m?JSON.stringify(T,null,2):J(T)}
11
+ `),n.includes("--check")&&T.state==="stale"&&(s.exitCode=1);return}if(o!=="optimize")throw new Error(`Unsupported assets command "${o}".`);if(w.length===0)throw new Error("assets optimize needs at least one file or directory (.glb, .png, .jpg, .webp, .hdr).");let v=b("--quality");if(v!==void 0&&v!=="default"&&v!=="high")throw new Error('--quality must be "default" or "high".');let g=b("--preset");if(g!==void 0&&g!=="color"&&g!=="normal"&&g!=="data")throw new Error('--preset must be "color", "normal", or "data".');let p=b("--out"),E=x("--max-dim"),k=x("--hdr-max-dim"),{formatAssetOptimizeReport:N,optimizeAssets:G}=await import('./asset-optimize-YJGWKD4Y.js'),I=C("optimizing assets"),j;try{j=await G({root:l,inputs:w,...p===void 0?{}:{outDir:p},...E===void 0?{}:{maxDimension:E},...k===void 0?{}:{hdrMaxDimension:k},...v===void 0?{}:{quality:v},...g===void 0?{}:{preset:g},force:n.includes("--force"),onProgress:a(J=>I.update(`optimizing ${b$1.accent(J)}`),"onProgress")});}finally{I.stop();}s.stdout.write(`${m?JSON.stringify(j,null,2):N(j)}
12
+ `),j.failed.length>0&&(s.exitCode=1);return}if(y==="environment"){if(O!=="bake")throw new Error(`Unsupported environment command "${O??""}".`);let{bakeRoomEnvironment:o,formatEnvironmentBakeReport:w}=await import('./environment-bake-ON5I27N7.js'),{findProjectRoot:R}=await import('./status-GDVSLQWV.js'),l=b("--root")??await R(),v=x("--size"),g=b("--output"),p=x("--timeout"),E=C("baking the room environment on the GPU"),k;try{k=await o({root:l,...v===void 0?{}:{size:v},...g===void 0?{}:{output:g},...p===void 0?{}:{timeoutMs:p},compression:n.includes("--no-zstd")?"none":"zstd",headed:n.includes("--headed")});}finally{E.stop();}s.stdout.write(`${m?JSON.stringify(k,null,2):w(k)}
13
+ `);return}if(y==="shaders"){let{findShaderProjectRoot:o}=await import('./shader-config-AKZEKIRB.js'),w=O??"status";if(!["status","capture","test","watch"].includes(w))throw new Error(`Unsupported shader command "${w}".`);let R=b("--root"),l=await o(R),v=b("--driver");if(v!==void 0&&v!=="vite"&&v!=="static")throw new Error('--driver must be "vite" or "static".');let g=v,p=b("--serve"),E=b("--url"),k=b("--backend");if(k!==void 0&&k!=="webgpu"&&k!=="webgl"&&k!=="both")throw new Error('--backend must be "webgpu", "webgl", or "both".');let N=k;if(w==="status"){let{inspectShaderMatrix:$}=await import('./shader-workflow-5EHHR32D.js'),{formatShaderMatrixStatus:T}=await import('./status-GDVSLQWV.js'),M=await $(l,void 0,N);s.stdout.write(`${m?JSON.stringify(M,null,2):T(M)}
14
+ `),(n.includes("--check")||O===void 0)&&M.state!=="fresh"&&(s.exitCode=1);return}if(w==="capture"){let{captureShaders:$}=await import('./shader-workflow-5EHHR32D.js'),{applyShaderAutoWire:T,hasRegisterDevtoolsCall:M,inspectShaderAutoWire:F}=await import('./shader-autowire-D2EOG6GF.js'),{buildShaderCaptureProject:A,startNextShaderCaptureServer:_}=await import('./shader-project-runner-NV4GKHDX.js'),{inferShaderCaptureTarget:X}=await import('./shader-config-AKZEKIRB.js'),P=g,V=p,K=E,Y,z,Q;try{if(P===void 0&&V===void 0&&K===void 0){let u=await F(l);if(!u.configured&&u.plan!==void 0){if(!await he(u.plan.diff))throw new Error("Adapter wiring was declined; no files were changed.");await T(u.plan);}else if(!u.configured&&u.bundler!=="vite"&&u.bundler!=="unknown")throw new Error(`${u.reason} No files were changed.`);if(u.bundler==="next")z=C("starting the project-local Next.js capture server"),Y=await _(l),K=Y.url,z.update("capturing shader scenes");else if(u.bundler==="webpack"||u.bundler==="esbuild"||u.bundler==="rollup"){z=C(`building the ${u.bundler} capture target`),await A(l);let S=await X(l);if(S.driverKind!=="static"||S.serve===void 0)throw new Error(`${u.bundler} build completed but no dist/, build/, or out/index.html was found; pass --driver static --serve <directory>.`);P="static",V=S.serve,z.update("capturing shader scenes");}}z??=C("capturing shader scenes"),Q=await $({root:l,headed:n.includes("--headed"),ifStale:n.includes("--if-stale"),commitTiming:n.includes("--commit-timing"),...N===void 0?{}:{backend:N},...P===void 0?{}:{driverKind:P},...V===void 0?{}:{serve:V},...K===void 0?{}:{url:K},onSceneStart:a((u,S,W)=>z?.update(`capturing ${b$1.accent(u)} ${b$1.dim(`(${S+1}/${W})`)}`),"onSceneStart"),onSceneRetry:a((u,S,W,D,U)=>{let Z=U instanceof Error&&/timed out/iu.test(U.message),ee=`capture attempt ${S}/${W} for "${u}" after ${Z?`timeout (${Math.round(D/1e3)} s burned)`:`failure (${U instanceof Error?U.message:String(U)})`}`;s.stderr.write(m?`${JSON.stringify({type:"shader-capture-retry",scene:u,attempt:S,total:W,timeoutMs:D,message:ee})}
15
15
  `:`${ee}
16
- `);},"onSceneRetry")});}finally{z?.stop(),await Y?.close();}let J;if(!n.includes("--no-assets"))try{let{discoverPublicAssets:d,optimizeAssets:x}=await import('./asset-optimize-GG72JCOX.js'),{loadShaderToolConfig:W}=await import('./shader-config-EOFU5D3Y.js'),q=(await W(l)).publicDir??"public",D=await d(l,q);if(D.length>0){let Z=C("optimizing project assets");try{J=await x({root:l,inputs:D,onProgress:a(ee=>Z.update(`optimizing ${b.accent(ee)}`),"onProgress")});}finally{Z.stop();}}}catch(d){let x=`Asset optimization skipped: ${d instanceof Error?d.message:String(d)}`;s.stderr.write(h?`${JSON.stringify({type:"asset-optimize-error",message:x})}
17
- `:`${c.warn} ${x}
18
- `);}let le=J===void 0?Q:{...Q,assets:J};if(s.stdout.write(`${h?JSON.stringify(le,null,2):ce(Q)}
19
- `),!h&&J!==void 0){let{formatAssetOptimizeReport:d}=await import('./asset-optimize-GG72JCOX.js'),x=J.results.filter(q=>q.cached).length;f(L(J.failed.length>0?c.warn:c.tick,"assets",`${J.results.length} optimized${x>0?` (${x} cached)`:""} ${c.dot} ${b.dim("meshopt + KTX2, receipt .three-blocks/assets/meta.json")}`));let W=d(J);W.length>0&&f(W.split(`
20
- `).map(q=>` ${q}`).join(`
21
- `));}if(!await M(l)){let d="Add registerDevtools({ renderer }) from three-blocks/devtools so committed shader artifacts hydrate in development and production.";s.stderr.write(h?`${JSON.stringify({type:"shader-runtime-registration",state:"missing",message:d})}
22
- `:`${c.warn} ${d}
23
- `);}return}if(m==="test"){let g=$("--mode");if(g!==void 0&&g!=="strict")throw new Error('--mode currently supports only "strict".');let{testShaders:T}=await import('./shader-workflow-7NQFDQI5.js'),M=C("verifying precompiled shaders against the live baseline"),F=k("--runs"),A;try{A=await T({root:l,headed:n.includes("--headed"),skipBrowser:n.includes("--skip-browser"),...w===void 0?{}:{driverKind:w},...p===void 0?{}:{serve:p},...E===void 0?{}:{url:E},...F===void 0?{}:{runs:F},parityOnly:n.includes("--parity-only"),commitTiming:n.includes("--commit-timing"),...N===void 0?{}:{backend:N},onSceneStart:a((_,X,P)=>M.update(`verifying ${b.accent(_)} ${b.dim(`(${X+1}/${P})`)}`),"onSceneStart")});}finally{M.stop();}s.stdout.write(`${h?JSON.stringify(A,null,2):ge(A)}
24
- `);return}let G=k("--debounce"),{watchShaders:I}=await import('./shader-watch-EORZ2SEC.js'),j=new AbortController;s.once("SIGINT",()=>j.abort()),s.once("SIGTERM",()=>j.abort());let B=await I({root:l,headed:n.includes("--headed"),...w===void 0?{}:{driverKind:w},...p===void 0?{}:{serve:p},...E===void 0?{}:{url:E},...G===void 0?{}:{debounceMs:G},signal:j.signal,onResult(g){s.stdout.write(`${h?JSON.stringify(g):ce(g)}
25
- `);},onError(g){s.stderr.write(`${h?JSON.stringify({error:g.message}):`${c.cross} ${b.danger(g.message)}`}
26
- `);}});h||f(L(c.ring,"watching",b.dim(B.root))),await B.done;return}if(y==="text"&&O&&O!=="status"){if(O!=="generate")throw new Error(`Unsupported text command "${O}".`);let{generateTextAtlases:a}=await import('./text-atlas-UORTLOQJ.js'),{findProjectRoot:m}=await import('./status-PTBB4SW2.js'),R=n.indexOf("--config"),l=R===-1?"three-blocks.text.ts":n[R+1];if(l===void 0||l.startsWith("--"))throw new Error("--config requires a project-relative path.");let v=await m(),w=C("generating MSDF text atlases"),p;try{p=await a(v,l);}finally{w.stop();}if(h)s.stdout.write(`${JSON.stringify(p,null,2)}
27
- `);else {f(L(c.tick,"text",`${p.glyphs} glyphs ${c.dot} ${p.atlases.length} atlas${p.atlases.length===1?"":"es"} regenerated`));for(let E of p.updatedFiles)f(` ${d(b.dim("updated"),12)} ${b.dim(E)}`);}return}if(!["status","text"].includes(y))throw new Error(`Unknown command "${y}".`);let{formatThreeBlocksStatus:e,inspectThreeBlocksStatus:t,threeBlocksStatusIsFresh:o}=await import('./status-PTBB4SW2.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 b$1=y==="text"?c$1:r;s.stdout.write(`${h?JSON.stringify(b$1,null,2):y==="status"?e(r):JSON.stringify(b$1,null,2)}
28
- `),y==="status"&&n.includes("--check")&&!o(r)&&(s.exitCode=1);}a($e,"main");$e().catch(e=>{let t=e instanceof Error?e.message:String(e);h?s.stderr.write(`${JSON.stringify({error:t})}
29
- `):s.stderr.write(`${c.cross} ${b.danger(t)}
16
+ `);},"onSceneRetry")});}finally{z?.stop(),await Y?.close();}let q;if(!n.includes("--no-assets"))try{let{discoverPublicAssets:u,optimizeAssets:S}=await import('./asset-optimize-YJGWKD4Y.js'),{loadShaderToolConfig:W}=await import('./shader-config-AKZEKIRB.js'),D=(await W(l)).publicDir??"public",U=await u(l,D);if(U.length>0){let Z=C("optimizing project assets");try{q=await S({root:l,inputs:U,onProgress:a(ee=>Z.update(`optimizing ${b$1.accent(ee)}`),"onProgress")});}finally{Z.stop();}}}catch(u){let S=`Asset optimization skipped: ${u instanceof Error?u.message:String(u)}`;s.stderr.write(m?`${JSON.stringify({type:"asset-optimize-error",message:S})}
17
+ `:`${c.warn} ${S}
18
+ `);}let pe=q===void 0?Q:{...Q,assets:q};if(s.stdout.write(`${m?JSON.stringify(pe,null,2):le(Q)}
19
+ `),!m&&q!==void 0){let{formatAssetOptimizeReport:u}=await import('./asset-optimize-YJGWKD4Y.js'),S=q.results.filter(D=>D.cached).length;f(B(q.failed.length>0?c.warn:c.tick,"assets",`${q.results.length} optimized${S>0?` (${S} cached)`:""} ${c.dot} ${b$1.dim("meshopt + KTX2, receipt .three-blocks/assets/meta.json")}`));let W=u(q);W.length>0&&f(W.split(`
20
+ `).map(D=>` ${D}`).join(`
21
+ `));}if(!await M(l)){let u="Add registerDevtools({ renderer }) from three-blocks/devtools so committed shader artifacts hydrate in development and production.";s.stderr.write(m?`${JSON.stringify({type:"shader-runtime-registration",state:"missing",message:u})}
22
+ `:`${c.warn} ${u}
23
+ `);}return}if(w==="test"){let $=b("--mode");if($!==void 0&&$!=="strict")throw new Error('--mode currently supports only "strict".');let{testShaders:T}=await import('./shader-workflow-5EHHR32D.js'),M=C("verifying precompiled shaders against the live baseline"),F=x("--runs"),A;try{A=await T({root:l,headed:n.includes("--headed"),skipBrowser:n.includes("--skip-browser"),...g===void 0?{}:{driverKind:g},...p===void 0?{}:{serve:p},...E===void 0?{}:{url:E},...F===void 0?{}:{runs:F},parityOnly:n.includes("--parity-only"),commitTiming:n.includes("--commit-timing"),...N===void 0?{}:{backend:N},onSceneStart:a((_,X,P)=>M.update(`verifying ${b$1.accent(_)} ${b$1.dim(`(${X+1}/${P})`)}`),"onSceneStart")});}finally{M.stop();}s.stdout.write(`${m?JSON.stringify(A,null,2):$e(A)}
24
+ `);return}let G=x("--debounce"),{watchShaders:I}=await import('./shader-watch-JBUA4LP5.js'),j=new AbortController;s.once("SIGINT",()=>j.abort()),s.once("SIGTERM",()=>j.abort());let J=await I({root:l,headed:n.includes("--headed"),...g===void 0?{}:{driverKind:g},...p===void 0?{}:{serve:p},...E===void 0?{}:{url:E},...G===void 0?{}:{debounceMs:G},signal:j.signal,onResult($){s.stdout.write(`${m?JSON.stringify($):le($)}
25
+ `);},onError($){s.stderr.write(`${m?JSON.stringify({error:$.message}):`${c.cross} ${b$1.danger($.message)}`}
26
+ `);}});m||f(B(c.ring,"watching",b$1.dim(J.root))),await J.done;return}if(y==="text"&&O&&O!=="status"){if(O!=="generate")throw new Error(`Unsupported text command "${O}".`);let{generateTextAtlases:o}=await import('./text-atlas-YYWV7S6F.js'),{findProjectRoot:w}=await import('./status-GDVSLQWV.js'),R=n.indexOf("--config"),l=R===-1?"three-blocks.text.ts":n[R+1];if(l===void 0||l.startsWith("--"))throw new Error("--config requires a project-relative path.");let v=await w(),g=C("generating MSDF text atlases"),p;try{p=await o(v,l);}finally{g.stop();}if(m)s.stdout.write(`${JSON.stringify(p,null,2)}
27
+ `);else {f(B(c.tick,"text",`${p.glyphs} glyphs ${c.dot} ${p.atlases.length} atlas${p.atlases.length===1?"":"es"} regenerated`));for(let E of p.updatedFiles)f(` ${d(b$1.dim("updated"),12)} ${b$1.dim(E)}`);}return}if(!["status","text"].includes(y))throw new Error(`Unknown command "${y}".`);let{formatThreeBlocksStatus:e,inspectThreeBlocksStatus:t,threeBlocksStatusIsFresh:a$2}=await import('./status-GDVSLQWV.js'),d$1=await t(),i=(d$1.text);if(y==="text"&&!i)throw new Error("This project does not enable the text feature.");let h=y==="text"?i:d$1;s.stdout.write(`${m?JSON.stringify(h,null,2):y==="status"?e(d$1):JSON.stringify(h,null,2)}
28
+ `),y==="status"&&n.includes("--check")&&!a$2(d$1)&&(s.exitCode=1);}a(be,"main");be().catch(e=>{let t=e instanceof Error?e.message:String(e);m?s.stderr.write(`${JSON.stringify({error:t})}
29
+ `):s.stderr.write(`${c.cross} ${b$1.danger(t)}
30
30
  `),s.exitCode=1;});
@@ -0,0 +1 @@
1
+ export{d as bakeRoomEnvironment,c as captureRoomEnvironment,b as encodeRoomEnvironmentKtx2,e as formatEnvironmentBakeReport,a as validateEnvironmentCubeSize}from'./chunk-IWQV456Z.js';import'./chunk-ZG3LO3VB.js';import'./chunk-ECQE4D2U.js';import'./chunk-7X4DHW36.js';
package/dist/index.d.ts CHANGED
@@ -268,7 +268,7 @@ declare function ensureShaderToolConfig(root: string): Promise<EnsuredShaderTool
268
268
  /** Published devtools protocol/package version. Kept dependency-free for instant CLI startup. */
269
269
  declare const SHADER_DEVTOOLS_VERSION: "0.1.0";
270
270
 
271
- declare const SHADER_PROVIDER_TRANSFORM_VERSION: 63;
271
+ declare const SHADER_PROVIDER_TRANSFORM_VERSION: 64;
272
272
  declare const SHADER_LOCAL_TIMING_FILE: "timing.local.json";
273
273
  declare const SHADER_COMMITTED_TIMING_FILE: "timing.json";
274
274
  declare const SHADER_PARITY_EVIDENCE_FILE: "parity.json";
@@ -311,7 +311,8 @@ interface ShaderTimingEnvironment {
311
311
  readonly platform: string;
312
312
  }
313
313
  interface ShaderSceneParityEvidence {
314
- /** Binds one successful browser comparison to its scene plus shared runtime/tool receipt inputs. */
314
+ readonly execution?: 'node' | 'browser';
315
+ /** Binds one successful renderer comparison to its scene plus shared runtime/tool receipt inputs. */
315
316
  readonly fingerprint: string;
316
317
  readonly verifiedAt: string;
317
318
  }
@@ -406,13 +407,13 @@ declare function serializeShaderManifest(manifest: PrecompiledManifest): string;
406
407
  declare function readShaderLocalTiming(directory: string, receipt: Uint8Array): Promise<ShaderLocalTiming | undefined>;
407
408
  /** Read exact timing twins, preferring the machine-local observation. */
408
409
  declare function readShaderTiming(directory: string, receipt: Uint8Array): Promise<ShaderTiming | undefined>;
409
- /** Read browser parity evidence for the scenes that still match the current receipt. */
410
+ /** Read native parity evidence for the scenes that still match the current receipt. */
410
411
  declare function readShaderParityEvidence(directory: string, receipt: Uint8Array): Promise<ShaderParityEvidence | undefined>;
411
412
  /** Read only the canonical, committed timing file for an exact receipt. */
412
413
  declare function readShaderCommittedTiming(directory: string, receipt: Uint8Array): Promise<ShaderCommittedTiming | undefined>;
413
414
  /** Persist successful build timing, bound to the exact current shader receipt. */
414
415
  declare function writeShaderLocalTiming(root: string, scenes: Readonly<Record<string, ShaderSceneTiming>>): Promise<ShaderLocalTiming>;
415
- /** Persist successful browser parity checkpoints for exact per-scene receipt inputs. */
416
+ /** Persist successful Node parity checkpoints for exact per-scene receipt inputs. */
416
417
  declare function writeShaderParityEvidence(root: string, scenes: readonly string[], expectedReceipt?: Uint8Array): Promise<ShaderParityEvidence>;
417
418
  /** Persist local timing and its explicitly requested committed twin. */
418
419
  declare function writeShaderTimingTwins(root: string, scenes: Readonly<Record<string, ShaderSceneTiming>>, environment: ShaderTimingEnvironment): Promise<{
@@ -445,6 +446,7 @@ interface ShaderBrowserReadiness {
445
446
  readonly firstFrame: boolean;
446
447
  }
447
448
  interface ShaderBrowserObservation {
449
+ readonly execution?: 'node';
448
450
  readonly scene: string;
449
451
  readonly mode: 'live' | 'precompiled';
450
452
  readonly compatibility: string;
@@ -489,12 +491,18 @@ interface AttachedPlaywrightShaderDriverOptions extends PlaywrightShaderDriverOp
489
491
  /** Already-running application origin or base URL. */
490
492
  readonly url: string;
491
493
  }
494
+ interface InternalPlaywrightShaderDriverOptions extends PlaywrightShaderDriverOptions {
495
+ readonly serve?: string;
496
+ readonly url?: string;
497
+ }
492
498
  declare function isRetryableShaderObservationNavigation(error: unknown): boolean;
493
499
  declare function createPlaywrightShaderDriver(options: PlaywrightShaderDriverOptions): ShaderBrowserDriver;
494
500
  /** Capture and verify an already-built app without loading Vite from the target project. */
495
501
  declare function createStaticPlaywrightShaderDriver(options: StaticPlaywrightShaderDriverOptions): ShaderBrowserDriver;
496
502
  /** Attach capture and parity transport to an already-running transformed application. */
497
503
  declare function createAttachedPlaywrightShaderDriver(options: AttachedPlaywrightShaderDriverOptions): ShaderBrowserDriver;
504
+ /** Shared Node capture/parity driver for every scene. */
505
+ declare function createShaderDriver(options: InternalPlaywrightShaderDriverOptions): ShaderBrowserDriver;
498
506
 
499
507
  interface ShaderScreenshotMetrics {
500
508
  readonly width: number;
@@ -661,6 +669,8 @@ interface TestShadersResult {
661
669
  readonly root: string;
662
670
  readonly noGpu: ShaderMatrixStatus;
663
671
  readonly browser: 'passed' | 'skipped';
672
+ /** Native raster parity is reported separately from browser release evidence. */
673
+ readonly native?: 'passed';
664
674
  readonly scenes: readonly ShaderSceneTestResult[];
665
675
  readonly timing?: ShaderLocalTiming;
666
676
  readonly committedTiming?: ShaderCommittedTiming;
@@ -939,10 +949,10 @@ declare const DOCUMENTED_BROWSER_NOISE: readonly [{
939
949
  readonly pattern: RegExp;
940
950
  }];
941
951
  declare function isDocumentedBrowserNoise(message: string): boolean;
942
- /** Chromium launch flags used by public WebGPU tools. */
943
- declare function webgpuBrowserArgs(environment?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): readonly string[];
944
- /** Lavapipe is most reliable in Chromium's headful mode under Xvfb. */
945
- declare function webgpuBrowserHeadless(headed?: boolean, environment?: NodeJS.ProcessEnv): boolean;
952
+ /** @deprecated Native Node rendering needs no browser launch arguments. */
953
+ declare function webgpuBrowserArgs(_environment?: NodeJS.ProcessEnv, _platform?: NodeJS.Platform): readonly string[];
954
+ /** @deprecated Native Node rendering is always headless. */
955
+ declare function webgpuBrowserHeadless(_headed?: boolean, _environment?: NodeJS.ProcessEnv): boolean;
946
956
 
947
957
  interface BrowserSmokeOptions {
948
958
  readonly root: string;
@@ -1024,7 +1034,7 @@ interface BrowserSmokeHmr {
1024
1034
  readonly acknowledged: boolean;
1025
1035
  readonly lifecycleStable: boolean;
1026
1036
  readonly sourceUnchanged: boolean;
1027
- readonly evidenceSource: 'public-runtime-browser-probe';
1037
+ readonly evidenceSource: 'public-runtime-node-probe';
1028
1038
  readonly evidence: BrowserSmokeHmrEvidence;
1029
1039
  readonly restart: BrowserSmokeWorkerRestart;
1030
1040
  readonly error: string | null;
@@ -1061,6 +1071,7 @@ interface BrowserSmokeBuildReceipt {
1061
1071
  interface BrowserSmokeReport {
1062
1072
  readonly schemaVersion: 1;
1063
1073
  readonly command: 'browser smoke';
1074
+ readonly execution: 'node';
1064
1075
  readonly passed: boolean;
1065
1076
  readonly scene: string;
1066
1077
  readonly lifecycle: BrowserSmokeLifecycle;
@@ -1145,6 +1156,7 @@ interface BrowserPreviewRouteReport {
1145
1156
  interface BrowserPreviewReport {
1146
1157
  readonly schemaVersion: 1;
1147
1158
  readonly command: 'browser preview';
1159
+ readonly execution: 'node';
1148
1160
  readonly passed: boolean;
1149
1161
  readonly buildMode: string | null;
1150
1162
  readonly expectShaders: 'precompiled' | 'live';
@@ -1211,7 +1223,7 @@ declare function encodeRoomEnvironmentKtx2(rawBytes: Uint8Array, options: {
1211
1223
  readonly threeRevision: string;
1212
1224
  readonly compression?: 'zstd' | 'none';
1213
1225
  }): EncodedRoomEnvironment;
1214
- /** Capture the procedural environment in a real Chromium WebGPU renderer. */
1226
+ /** Capture the procedural environment in a native Node WebGPU renderer. */
1215
1227
  declare const captureRoomEnvironment: RoomEnvironmentCapture;
1216
1228
  /** Render, encode, verify, and atomically commit the public RoomEnvironment artifact pair. */
1217
1229
  declare function bakeRoomEnvironment(options: EnvironmentBakeOptions): Promise<EnvironmentBakeReport>;
@@ -1250,7 +1262,7 @@ declare function watchShaders(options?: WatchShadersOptions): Promise<ShaderWatc
1250
1262
  /**
1251
1263
  * Asset optimization: meshopt geometry + slot-aware Basis Universal (KTX2)
1252
1264
  * textures for GLB/image/HDR inputs, with a content-hash encode cache and a
1253
- * receipt committed last. The heavy encoders (sharp, gltf-transform,
1265
+ * receipt committed last. The heavy encoders (Skia, gltf-transform,
1254
1266
  * meshoptimizer, ktx2-encoder) load lazily so importing this module stays
1255
1267
  * cheap for the Vite plugin's self-inspection path.
1256
1268
  *
@@ -1354,4 +1366,4 @@ interface AssetStatusReport {
1354
1366
  declare function inspectAssets(root: string): Promise<AssetStatusReport>;
1355
1367
  declare function formatAssetStatusReport(report: AssetStatusReport): string;
1356
1368
 
1357
- export { ASSET_OPTIMIZE_VERSION, ASSET_RECEIPT_DIRECTORY, ASSET_RECEIPT_FILE, type AdoptedProjectStatus, type ArtifactState, type AssetKind, type AssetOptimizeOptions, type AssetOptimizeReport, type AssetState, type AssetStatusEntry, type AssetStatusReport, type AttachedPlaywrightShaderDriverOptions, type BrowserPreviewOptions, type BrowserPreviewReport, type BrowserPreviewRouteReport, type BrowserSmokeBuildReceipt, type BrowserSmokeCodec, type BrowserSmokeCodecRoute, type BrowserSmokeHmr, type BrowserSmokeHmrEvidence, type BrowserSmokeLifecycle, type BrowserSmokeOptions, type BrowserSmokeReport, type BrowserSmokeWorkerRestart, type BuiltinFontMetadata, type CaptureSceneResult, type CaptureShadersOptions, type CaptureShadersResult, DOCUMENTED_BROWSER_NOISE, type DiscoveredTextContent, type EncodedRoomEnvironment, type EnsuredShaderToolConfig, type EnvironmentBakeOptions, type EnvironmentBakeReport, type FailedAssetResult, type GenerateTextResult, type GeneratedTextAtlas, type GlyphSet, type GlyphSetOptions, type InferredShaderCaptureTarget, type InstalledShaderRuntime, type OptimizedAssetResult, type PlaywrightShaderDriverOptions, type ProjectMetadataV2, type ProjectStatus, RUNTIME_STATUS_RECEIPT_MAX_BYTES, RUNTIME_STATUS_RECEIPT_PATH, RUNTIME_STATUS_RECOVERY, type RoomEnvironmentCapture, type RoomEnvironmentCaptureOptions, type RoomEnvironmentCaptureResult, type RoomEnvironmentMetadata, type RuntimeAssetsStatus, type RuntimeBackend, type RuntimeCodecObservation, type RuntimeHmrCapabilities, type RuntimeHmrOutcome, type RuntimeHmrStatus, type RuntimeObservation, type RuntimeOptimizationStatus, type RuntimeState, type RuntimeStatsStatus, type RuntimeStatusReceiptV1, type RuntimeTextStatus, type RuntimeWorkerStatus, SHADER_ARTIFACT_DIRECTORY, SHADER_COMMITTED_TIMING_FILE, SHADER_DEVTOOLS_VERSION, SHADER_LOCAL_TIMING_FILE, SHADER_PARITY_DIRECTORY, SHADER_PARITY_EVIDENCE_FILE, SHADER_PROVIDER_TRANSFORM_VERSION, SHADER_TOOL_CONFIG_FILE, type ShaderBridgeConfig, type ShaderBrowserDriver, type ShaderBrowserObservation, type ShaderBrowserReadiness, type ShaderCapturePayload, type ShaderCaptureProvenance, type ShaderCaptureStageTiming, type ShaderCaptureStats, type ShaderCommittedTiming, type ShaderCoverage, type ShaderFreshness, type ShaderLocalTiming, type ShaderMatrixState, type ShaderMatrixStatus, type ShaderParityConfig, type ShaderParityEvidence, type ShaderParityResult, type ShaderReadinessConfig, type ShaderReceiptV2, type ShaderSceneArtifactStatus, type ShaderSceneConfig, type ShaderSceneParityEvidence, type ShaderSceneReceipt, type ShaderSceneTestResult, type ShaderSceneTiming, type ShaderScreenshotMetrics, type ShaderSkippedBuild, type ShaderStartupMeasurement, type ShaderState, type ShaderStatus, type ShaderTiming, type ShaderTimingEnvironment, type ShaderToolConfig, ShaderWatchQueue, type ShaderWatchQueueOptions, type ShaderWatchSession, type StaticPlaywrightShaderDriverOptions, TEXT_ATLAS_GENERATOR_VERSION, TEXT_ATLAS_SCHEMA_VERSION, type TestShadersOptions, type TestShadersResult, type TextAtlasFileReceipt, type TextAtlasGenerationReceipt, type TextAtlasInspection, type TextAtlasRuntimeOptions, type TextAtlasStatus, type TextState, type TextStatus, type TextUnicodePreset, type TextUnicodeRange, type TextureEncodeMode, type TextureEncodeResult, type TexturePreset, type ThreeBlocksStatus, type ToolTextConfiguration, type ToolTextFontRoute, type ToolTextFontSource, type ToolTextGenerationOptions, type ValidateShaderCaptureOptions, type ValidatedShaderCapture, type WatchShadersOptions, type WriteShaderArtifactsOptions, type WrittenShaderArtifacts, bakeRoomEnvironment, buildGlyphSet, builtinFontMetadata, captureRoomEnvironment, captureShaders, compareShaderScreenshots, createAttachedPlaywrightShaderDriver, createPlaywrightShaderDriver, createStaticPlaywrightShaderDriver, discoverPublicAssets, discoverTextContent, encodeRoomEnvironmentKtx2, ensureShaderToolConfig, extractCanvasTextFromHtml, extractDefinedTextContent, findProjectRoot, findShaderProjectRoot, formatAssetOptimizeReport, formatAssetStatusReport, formatBrowserPreviewReport, formatBrowserSmokeReport, formatEnvironmentBakeReport, formatShaderMatrixStatus, formatStatus, formatThreeBlocksStatus, generateTextAtlases, inferShaderCaptureTarget, inspectAssets, inspectProject, inspectShaderMatrix, inspectTextAtlases, inspectThreeBlocksStatus, isDocumentedBrowserNoise, isRetryableShaderObservationNavigation, loadShaderCaptureRuntimeSource, loadShaderToolConfig, optimizeAssets, parseBrowserSmokeLifecycle, parseProjectMetadata, parseRuntimeStatusReceipt, parseShaderReceipt, parseShaderToolConfig, parseTextAtlasReceipt, parseTextConfiguration, presetForImageName, presetForTextureSlots, prewarmBuiltinFont, readInstalledShaderRuntime, readShaderCommittedTiming, readShaderLocalTiming, readShaderParityEvidence, readShaderTiming, readTextConfiguration, runBrowserPreview, runBrowserSmoke, screenshotLuminance, serializeShaderManifest, shaderCoverage, shaderScreenshotMetrics, snapshotShaderInputs, stableStringify, testShaders, threeBlocksStatusIsFresh, validateEnvironmentCubeSize, validateShaderCapture, watchShaders, webgpuBrowserArgs, webgpuBrowserHeadless, writeShaderArtifacts, writeShaderLocalTiming, writeShaderParityEvidence, writeShaderTimingTwins };
1369
+ export { ASSET_OPTIMIZE_VERSION, ASSET_RECEIPT_DIRECTORY, ASSET_RECEIPT_FILE, type AdoptedProjectStatus, type ArtifactState, type AssetKind, type AssetOptimizeOptions, type AssetOptimizeReport, type AssetState, type AssetStatusEntry, type AssetStatusReport, type AttachedPlaywrightShaderDriverOptions, type BrowserPreviewOptions, type BrowserPreviewReport, type BrowserPreviewRouteReport, type BrowserSmokeBuildReceipt, type BrowserSmokeCodec, type BrowserSmokeCodecRoute, type BrowserSmokeHmr, type BrowserSmokeHmrEvidence, type BrowserSmokeLifecycle, type BrowserSmokeOptions, type BrowserSmokeReport, type BrowserSmokeWorkerRestart, type BuiltinFontMetadata, type CaptureSceneResult, type CaptureShadersOptions, type CaptureShadersResult, DOCUMENTED_BROWSER_NOISE, type DiscoveredTextContent, type EncodedRoomEnvironment, type EnsuredShaderToolConfig, type EnvironmentBakeOptions, type EnvironmentBakeReport, type FailedAssetResult, type GenerateTextResult, type GeneratedTextAtlas, type GlyphSet, type GlyphSetOptions, type InferredShaderCaptureTarget, type InstalledShaderRuntime, type OptimizedAssetResult, type PlaywrightShaderDriverOptions, type ProjectMetadataV2, type ProjectStatus, RUNTIME_STATUS_RECEIPT_MAX_BYTES, RUNTIME_STATUS_RECEIPT_PATH, RUNTIME_STATUS_RECOVERY, type RoomEnvironmentCapture, type RoomEnvironmentCaptureOptions, type RoomEnvironmentCaptureResult, type RoomEnvironmentMetadata, type RuntimeAssetsStatus, type RuntimeBackend, type RuntimeCodecObservation, type RuntimeHmrCapabilities, type RuntimeHmrOutcome, type RuntimeHmrStatus, type RuntimeObservation, type RuntimeOptimizationStatus, type RuntimeState, type RuntimeStatsStatus, type RuntimeStatusReceiptV1, type RuntimeTextStatus, type RuntimeWorkerStatus, SHADER_ARTIFACT_DIRECTORY, SHADER_COMMITTED_TIMING_FILE, SHADER_DEVTOOLS_VERSION, SHADER_LOCAL_TIMING_FILE, SHADER_PARITY_DIRECTORY, SHADER_PARITY_EVIDENCE_FILE, SHADER_PROVIDER_TRANSFORM_VERSION, SHADER_TOOL_CONFIG_FILE, type ShaderBridgeConfig, type ShaderBrowserDriver, type ShaderBrowserObservation, type ShaderBrowserReadiness, type ShaderCapturePayload, type ShaderCaptureProvenance, type ShaderCaptureStageTiming, type ShaderCaptureStats, type ShaderCommittedTiming, type ShaderCoverage, type ShaderFreshness, type ShaderLocalTiming, type ShaderMatrixState, type ShaderMatrixStatus, type ShaderParityConfig, type ShaderParityEvidence, type ShaderParityResult, type ShaderReadinessConfig, type ShaderReceiptV2, type ShaderSceneArtifactStatus, type ShaderSceneConfig, type ShaderSceneParityEvidence, type ShaderSceneReceipt, type ShaderSceneTestResult, type ShaderSceneTiming, type ShaderScreenshotMetrics, type ShaderSkippedBuild, type ShaderStartupMeasurement, type ShaderState, type ShaderStatus, type ShaderTiming, type ShaderTimingEnvironment, type ShaderToolConfig, ShaderWatchQueue, type ShaderWatchQueueOptions, type ShaderWatchSession, type StaticPlaywrightShaderDriverOptions, TEXT_ATLAS_GENERATOR_VERSION, TEXT_ATLAS_SCHEMA_VERSION, type TestShadersOptions, type TestShadersResult, type TextAtlasFileReceipt, type TextAtlasGenerationReceipt, type TextAtlasInspection, type TextAtlasRuntimeOptions, type TextAtlasStatus, type TextState, type TextStatus, type TextUnicodePreset, type TextUnicodeRange, type TextureEncodeMode, type TextureEncodeResult, type TexturePreset, type ThreeBlocksStatus, type ToolTextConfiguration, type ToolTextFontRoute, type ToolTextFontSource, type ToolTextGenerationOptions, type ValidateShaderCaptureOptions, type ValidatedShaderCapture, type WatchShadersOptions, type WriteShaderArtifactsOptions, type WrittenShaderArtifacts, bakeRoomEnvironment, buildGlyphSet, builtinFontMetadata, captureRoomEnvironment, captureShaders, compareShaderScreenshots, createAttachedPlaywrightShaderDriver, createPlaywrightShaderDriver, createShaderDriver, createStaticPlaywrightShaderDriver, discoverPublicAssets, discoverTextContent, encodeRoomEnvironmentKtx2, ensureShaderToolConfig, extractCanvasTextFromHtml, extractDefinedTextContent, findProjectRoot, findShaderProjectRoot, formatAssetOptimizeReport, formatAssetStatusReport, formatBrowserPreviewReport, formatBrowserSmokeReport, formatEnvironmentBakeReport, formatShaderMatrixStatus, formatStatus, formatThreeBlocksStatus, generateTextAtlases, inferShaderCaptureTarget, inspectAssets, inspectProject, inspectShaderMatrix, inspectTextAtlases, inspectThreeBlocksStatus, isDocumentedBrowserNoise, isRetryableShaderObservationNavigation, loadShaderCaptureRuntimeSource, loadShaderToolConfig, optimizeAssets, parseBrowserSmokeLifecycle, parseProjectMetadata, parseRuntimeStatusReceipt, parseShaderReceipt, parseShaderToolConfig, parseTextAtlasReceipt, parseTextConfiguration, presetForImageName, presetForTextureSlots, prewarmBuiltinFont, readInstalledShaderRuntime, readShaderCommittedTiming, readShaderLocalTiming, readShaderParityEvidence, readShaderTiming, readTextConfiguration, runBrowserPreview, runBrowserSmoke, screenshotLuminance, serializeShaderManifest, shaderCoverage, shaderScreenshotMetrics, snapshotShaderInputs, stableStringify, testShaders, threeBlocksStatusIsFresh, validateEnvironmentCubeSize, validateShaderCapture, watchShaders, webgpuBrowserArgs, webgpuBrowserHeadless, writeShaderArtifacts, writeShaderLocalTiming, writeShaderParityEvidence, writeShaderTimingTwins };