{"owner":"gpujs","repo":"gpu.js","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md"],"skills":{"CLAUDE.md":"# Working on gpu.js\n\n## Build environment\n\nNode 22. Node 23 breaks headless-gl, and early 22.x hits a vinyl-fs bug, so\npin something recent within 22.\n\n`npm run make` runs build → beautify → minify → build-tests, from plain Node\nscripts in `scripts/`. It rewrites `dist/` and regenerates `test/all.html`, so\nrun it before anything that loads the browser bundle, and commit `dist/` with\nthe change. Individual steps are available as `npm run build`, `minify`,\n`beautify`, `build-tests`; `npm run dev` serves the repo for test/all.html.\n\nBundling is rolldown, minifying is terser. Two things there are load-bearing:\n\n- `gl` and (for the core build) `acorn` are aliased to `scripts/empty-module.js`.\n  That is browserify's old `.ignore()`. They must be aliased, not `external` —\n  external leaves a live `require()` that throws in a browser.\n- both the bundle and the minified bundle are run through terser with\n  `ascii_only`. acorn ships its unicode tables already escaped, but rolldown\n  decodes string literals and prints the characters, which puts ~68k raw UTF-8\n  bytes in the bundle. Serving that without a matching charset is #743/#744.\n\nThe banner interpolates `new Date()`, so two builds are never byte-identical —\ncompare `dist/` with the `@date` lines normalized. All four bundles of one run\nshare a timestamp: the minify step passes the banner through (terser keeps it\nvia `output.comments`, since it carries `@license`) rather than prepending its\nown. Prepending is what used to put the banner in the minified files twice,\nseconds apart.\n\nNote `beautify` reformats `src/`, so `npm run make` can produce unrelated\nwhitespace churn in files you did not touch. That is expected.\n\n## Tests\n\n`npm test` runs qunit over `test/issues test/internal test/features`.\n\nThe suite has platform-dependent failures that are **not** regressions:\n\n- **Linux/Mesa**: a set of failures baselined in\n  `.github/known-test-failures.txt`. CI compares against it with\n  `.github/compare-test-failures.js` and fails only on *new* failures, so the\n  raw exit code is not the signal.\n- `test/internal/math.random.js` \"unique every time\" is flaky (seed\n  collisions, related to #850). A single failure there is not meaningful.\n\nConfirm any new regression test actually catches the bug by reverting the fix\nand watching it fail — a test that passes both ways is worse than none.\n\n## Real devices\n\nBugs that only reproduce on real GPU drivers are a recurring theme here; three\nwere found this way in 2.19.8 alone, none of which any CI runner could have\ncaught. See the Testing section of README.md for how to run it.\n\n```bash\nnpm run make                     # devices load dist/, so build first\nnpm run test:browserstack        # real iOS/Android\nnode test/browserstack/run.js --dry-run --browsers=desktop   # inspect caps, no session\n```\n\nCredentials live in gitignored `test/browserstack/.credentials.json`, and as\n`BROWSERSTACK_USERNAME` / `BROWSERSTACK_ACCESS_KEY` repo secrets for CI.\n\nBrowserStack groups runs into one build by `buildName`, distinguishing them by\n`buildIdentifier`. Keep `buildName` stable — a name that varies per run creates\na separate build every time and there is no single `gpu.js` entry to find in\nthe dashboard.\n\n## Releasing\n\nEvery step below is required; skipping the npm publish is the usual mistake —\n2.19.5 and 2.19.7 have tags and GitHub releases but were never published, so\ntheir release notes tell people to install a version that does not exist.\n\n```bash\nnpm version <version> --no-git-tag-version   # package.json only\nnpm run make                                 # dist/ carries the version header\nnpm test                                     # expect the known baseline\n\ngit add -A && git commit -m \"chore: Release <version>\"\ngit tag <version>\ngit push origin develop && git push origin <version>\n\ngh release create <version> --title \"<version>\" --notes-file <notes>\n```\n\n### Publishing\n\n`npm publish` requires 2FA and prompts for a one-time code. Two things that\notherwise waste time:\n\n- `npm view gpu.js version` lags a publish by up to a minute. `curl -s\n  https://registry.npmjs.org/gpu.js` is authoritative.\n- `E404 PUT ... not found` on publish means the npm token expired, not that\n  anything is wrong with the package. Run `npm login`.\n\n### Pushing workflow files\n\nChanges under `.github/workflows/` are rejected unless the credential pushing\nthem carries the `workflow` scope. Push with one that does, or add the file\nthrough the GitHub API.\n"},"files":{"CLAUDE.md":"# Working on gpu.js\n\n## Build environment\n\nNode 22. Node 23 breaks headless-gl, and early 22.x hits a vinyl-fs bug, so\npin something recent within 22.\n\n`npm run make` runs build → beautify → minify → build-tests, from plain Node\nscripts in `scripts/`. It rewrites `dist/` and regenerates `test/all.html`, so\nrun it before anything that loads the browser bundle, and commit `dist/` with\nthe change. Individual steps are available as `npm run build`, `minify`,\n`beautify`, `build-tests`; `npm run dev` serves the repo for test/all.html.\n\nBundling is rolldown, minifying is terser. Two things there are load-bearing:\n\n- `gl` and (for the core build) `acorn` are aliased to `scripts/empty-module.js`.\n  That is browserify's old `.ignore()`. They must be aliased, not `external` —\n  external leaves a live `require()` that throws in a browser.\n- both the bundle and the minified bundle are run through terser with\n  `ascii_only`. acorn ships its unicode tables already escaped, but rolldown\n  decodes string literals and prints the characters, which puts ~68k raw UTF-8\n  bytes in the bundle. Serving that without a matching charset is #743/#744.\n\nThe banner interpolates `new Date()`, so two builds are never byte-identical —\ncompare `dist/` with the `@date` lines normalized. All four bundles of one run\nshare a timestamp: the minify step passes the banner through (terser keeps it\nvia `output.comments`, since it carries `@license`) rather than prepending its\nown. Prepending is what used to put the banner in the minified files twice,\nseconds apart.\n\nNote `beautify` reformats `src/`, so `npm run make` can produce unrelated\nwhitespace churn in files you did not touch. That is expected.\n\n## Tests\n\n`npm test` runs qunit over `test/issues test/internal test/features`.\n\nThe suite has platform-dependent failures that are **not** regressions:\n\n- **Linux/Mesa**: a set of failures baselined in\n  `.github/known-test-failures.txt`. CI compares against it with\n  `.github/compare-test-failures.js` and fails only on *new* failures, so the\n  raw exit code is not the signal.\n- `test/internal/math.random.js` \"unique every time\" is flaky (seed\n  collisions, related to #850). A single failure there is not meaningful.\n\nConfirm any new regression test actually catches the bug by reverting the fix\nand watching it fail — a test that passes both ways is worse than none.\n\n## Real devices\n\nBugs that only reproduce on real GPU drivers are a recurring theme here; three\nwere found this way in 2.19.8 alone, none of which any CI runner could have\ncaught. See the Testing section of README.md for how to run it.\n\n```bash\nnpm run make                     # devices load dist/, so build first\nnpm run test:browserstack        # real iOS/Android\nnode test/browserstack/run.js --dry-run --browsers=desktop   # inspect caps, no session\n```\n\nCredentials live in gitignored `test/browserstack/.credentials.json`, and as\n`BROWSERSTACK_USERNAME` / `BROWSERSTACK_ACCESS_KEY` repo secrets for CI.\n\nBrowserStack groups runs into one build by `buildName`, distinguishing them by\n`buildIdentifier`. Keep `buildName` stable — a name that varies per run creates\na separate build every time and there is no single `gpu.js` entry to find in\nthe dashboard.\n\n## Releasing\n\nEvery step below is required; skipping the npm publish is the usual mistake —\n2.19.5 and 2.19.7 have tags and GitHub releases but were never published, so\ntheir release notes tell people to install a version that does not exist.\n\n```bash\nnpm version <version> --no-git-tag-version   # package.json only\nnpm run make                                 # dist/ carries the version header\nnpm test                                     # expect the known baseline\n\ngit add -A && git commit -m \"chore: Release <version>\"\ngit tag <version>\ngit push origin develop && git push origin <version>\n\ngh release create <version> --title \"<version>\" --notes-file <notes>\n```\n\n### Publishing\n\n`npm publish` requires 2FA and prompts for a one-time code. Two things that\notherwise waste time:\n\n- `npm view gpu.js version` lags a publish by up to a minute. `curl -s\n  https://registry.npmjs.org/gpu.js` is authoritative.\n- `E404 PUT ... not found` on publish means the npm token expired, not that\n  anything is wrong with the package. Run `npm login`.\n\n### Pushing workflow files\n\nChanges under `.github/workflows/` are rejected unless the credential pushing\nthem carries the `workflow` scope. Push with one that does, or add the file\nthrough the GitHub API.\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# Working on gpu.js\n\n## Build environment\n\nNode 22. Node 23 breaks headless-gl, and early 22.x hits a vinyl-fs bug, so\npin something recent within 22.\n\n`npm run make` runs build → beautify → minify → build-tests, from plain Node\nscripts in `scripts/`. It rewrites `dist/` and regenerates `test/all.html`, so\nrun it before anything that loads the browser bundle, and commit `dist/` with\nthe change. Individual steps are available as `npm run build`, `minify`,\n`beautify`, `build-tests`; `npm run dev` serves the repo for test/all.html.\n\nBundling is rolldown, minifying is terser. Two things there are load-bearing:\n\n- `gl` and (for the core build) `acorn` are aliased to `scripts/empty-module.js`.\n  That is browserify's old `.ignore()`. They must be aliased, not `external` —\n  external leaves a live `require()` that throws in a browser.\n- both the bundle and the minified bundle are run through terser with\n  `ascii_only`. acorn ships its unicode tables already escaped, but rolldown\n  decodes string literals and prints the characters, which puts ~68k raw UTF-8\n  bytes in the bundle. Serving that without a matching charset is #743/#744.\n\nThe banner interpolates `new Date()`, so two builds are never byte-identical —\ncompare `dist/` with the `@date` lines normalized. All four bundles of one run\nshare a timestamp: the minify step passes the banner through (terser keeps it\nvia `output.comments`, since it carries `@license`) rather than prepending its\nown. Prepending is what used to put the banner in the minified files twice,\nseconds apart.\n\nNote `beautify` reformats `src/`, so `npm run make` can produce unrelated\nwhitespace churn in files you did not touch. That is expected.\n\n## Tests\n\n`npm test` runs qunit over `test/issues test/internal test/features`.\n\nThe suite has platform-dependent failures that are **not** regressions:\n\n- **Linux/Mesa**: a set of failures baselined in\n  `.github/known-test-failures.txt`. CI compares against it with\n  `.github/compare-test-failures.js` and fails only on *new* failures, so the\n  raw exit code is not the signal.\n- `test/internal/math.random.js` \"unique every time\" is flaky (seed\n  collisions, related to #850). A single failure there is not meaningful.\n\nConfirm any new regression test actually catches the bug by reverting the fix\nand watching it fail — a test that passes both ways is worse than none.\n\n## Real devices\n\nBugs that only reproduce on real GPU drivers are a recurring theme here; three\nwere found this way in 2.19.8 alone, none of which any CI runner could have\ncaught. See the Testing section of README.md for how to run it.\n\n```bash\nnpm run make                     # devices load dist/, so build first\nnpm run test:browserstack        # real iOS/Android\nnode test/browserstack/run.js --dry-run --browsers=desktop   # inspect caps, no session\n```\n\nCredentials live in gitignored `test/browserstack/.credentials.json`, and as\n`BROWSERSTACK_USERNAME` / `BROWSERSTACK_ACCESS_KEY` repo secrets for CI.\n\nBrowserStack groups runs into one build by `buildName`, distinguishing them by\n`buildIdentifier`. Keep `buildName` stable — a name that varies per run creates\na separate build every time and there is no single `gpu.js` entry to find in\nthe dashboard.\n\n## Releasing\n\nEvery step below is required; skipping the npm publish is the usual mistake —\n2.19.5 and 2.19.7 have tags and GitHub releases but were never published, so\ntheir release notes tell people to install a version that does not exist.\n\n```bash\nnpm version <version> --no-git-tag-version   # package.json only\nnpm run make                                 # dist/ carries the version header\nnpm test                                     # expect the known baseline\n\ngit add -A && git commit -m \"chore: Release <version>\"\ngit tag <version>\ngit push origin develop && git push origin <version>\n\ngh release create <version> --title \"<version>\" --notes-file <notes>\n```\n\n### Publishing\n\n`npm publish` requires 2FA and prompts for a one-time code. Two things that\notherwise waste time:\n\n- `npm view gpu.js version` lags a publish by up to a minute. `curl -s\n  https://registry.npmjs.org/gpu.js` is authoritative.\n- `E404 PUT ... not found` on publish means the npm token expired, not that\n  anything is wrong with the package. Run `npm login`.\n\n### Pushing workflow files\n\nChanges under `.github/workflows/` are rejected unless the credential pushing\nthem carries the `workflow` scope. Push with one that does, or add the file\nthrough the GitHub API.\n","category":"root","tokens":1120}]}