Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ jobs:
version: 2026.7.13
cache: true

- name: Install HarfBuzz CLI prerequisite
- name: Install HarfBuzz workload toolchain
run: mise -C apps/benchmarks install

- name: Install HarfBuzz native prerequisite
run: |
sudo apt-get update
sudo apt-get install --yes --no-install-recommends libglib2.0-dev
Expand All @@ -40,6 +43,9 @@ jobs:
- name: Install locked dependencies
run: pnpm install --frozen-lockfile

- name: Provision authenticated HarfBuzz utilities
run: mise exec -C apps/benchmarks -- pnpm provision:harfbuzz

- name: Select rolling runner Chromium
shell: bash
run: |
Expand All @@ -58,7 +64,9 @@ jobs:
printf 'PMNDRS_TEXT_CHROMIUM_EXECUTABLE_PATH=%s\n' "$chromium_executable" >> "$GITHUB_ENV"

- name: Run deterministic repository checks
run: pnpm check
run: |
pnpm check
pnpm --filter @pmndrs/text-benchmarks check:japanese-showcase-subset

- name: Retain Wasm failure evidence
if: failure()
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.DS_Store
node_modules/
.pnpm-store/
dist/
target/
*.tsbuildinfo
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Use these canonical sources instead of creating shadow plans or duplicate status

Update affected canonical documentation in the same change as source. Package source or configuration changes require reviewing the matching package concept, regenerating its `source_digest`, and running `pnpm docs:check`.

Use the exact root toolchain pins through mise. The dated nightly under `packages/font-baker/fuzz` is isolated to cargo-fuzz. Verify narrowly first, then run the relevant package and repository checks. Keep tests deterministic; do not use sleeps, timer cushions, arbitrary retries, or regenerated goldens as correctness mechanisms.
Use the exact root toolchain pins through mise. Agent commands must enter that environment explicitly with `mise exec -- pnpm ...` or `mise exec -- <tool> ...`; do not depend on `mise activate` surviving across non-interactive commands. Mise owns tool selection, while pnpm remains the only repository workflow surface. Install workload-scoped mise tools only when their documented pnpm workflow requires them. The dated nightly under `packages/font-baker/fuzz` is isolated to cargo-fuzz. Verify narrowly first, then run the relevant package and repository checks. Keep tests deterministic; do not use sleeps, timer cushions, arbitrary retries, or regenerated goldens as correctness mechanisms.

Exercise repository workflows through named `pnpm` scripts from the workspace root. Prefer a short root alias for a maintainer-facing application workflow. When a repeatable build, test, profile, capture, generation, or development command is missing, add the package-owned script and root alias before running it; do not leave the working procedure as an agent-only shell recipe or temporary probe.

Expand Down
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,17 @@ pnpm install
pnpm check
```

Use mise to install the exact root Node.js, pnpm, stable Rust, Meson, and Ninja pins. Meson and Ninja build the authenticated HarfBuzz oracle utilities used by the clean-checkout fixture gates. HarfBuzz gates those command-line utilities on GLib development metadata, so the build host must also provide `glib-2.0` through `pkg-config` (`libglib2.0-dev` on Ubuntu or `glib` on macOS with Homebrew). CI declares that native prerequisite and prints the selected GLib version before checks run. The canonical mise versions are required; do not substitute merely compatible local toolchains. The optional coverage-guided font-baker fuzzer is isolated
under `packages/font-baker/fuzz`; its nested mise configuration provisions the exact dated nightly and
`cargo-fuzz` release required by that workspace when `fuzz:rust` runs.
The root path requires only the exact Node.js, pnpm, and stable Rust versions declared by the repository. Mise is the convenient reproducible installer, not a required task runner: contributors who already have matching versions may run the same pnpm commands directly. Non-interactive agents should use `mise exec -- pnpm ...` instead of relying on shell activation. The optional coverage-guided font-baker fuzzer is isolated under `packages/font-baker/fuzz`; its nested mise configuration provisions the exact dated nightly and `cargo-fuzz` release required by that workspace when `fuzz:rust` runs.

The authenticated HarfBuzz fixture gate is a benchmark-specific workload, not a root prerequisite. It additionally needs Meson 1.11.1, Ninja 1.13.2, and `glib-2.0` development metadata through `pkg-config` (`libglib2.0-dev` on Ubuntu or `glib` plus `pkgconf` on macOS with Homebrew). Supply matching tools directly, or install the scoped pins and provision the utilities with:

```sh
mise -C apps/benchmarks install
mise exec -C apps/benchmarks -- pnpm provision:harfbuzz
pnpm --filter @pmndrs/text-benchmarks check:japanese-showcase-subset
```

The ordinary `pnpm check` path validates committed fixtures without provisioning specialized native tooling. CI installs the scoped benchmark tools explicitly and runs the HarfBuzz freshness gate separately.

Run the Figma-backed benchmark product from the monorepo app tree:

Expand Down
16 changes: 16 additions & 0 deletions apps/benchmarks/doctor.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://react.doctor/schema/config.json",
"noScore": true,
"supplyChain": {
"enabled": false
},
"ignore": {
"files": ["vitexec/**", "src/benchmark/bake-host-baseline.ts", "src/benchmark/worker-queue-evidence.ts"],
"overrides": [
{
"files": ["src/benchmark/paragraph-layout-digest.ts"],
"rules": ["deslop/unused-export"]
}
]
}
}
4 changes: 4 additions & 0 deletions apps/benchmarks/mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[tools]
pipx = "1.16.5"
"pipx:meson" = "1.11.1"
"aqua:ninja-build/ninja" = "1.13.2"
6 changes: 3 additions & 3 deletions apps/benchmarks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"check:paragraph-cjk-contract": "pnpm --filter @pmndrs/text build && pnpm --filter @pmndrs/text-font-baker build && node ./scripts/generate-paragraph-cjk-contract.mts --check",
"check:mtsdf-render-fixture": "pnpm --filter @pmndrs/text build && pnpm --filter @pmndrs/text-font-baker build && node ./scripts/generate-mtsdf-render-fixture.mts --check",
"check:slug-render-fixture": "pnpm --filter @pmndrs/text build && pnpm --filter @pmndrs/text-font-baker build && node ./scripts/generate-slug-render-fixture.mts --check",
"check:japanese-showcase-subset": "node ./scripts/provision-harfbuzz.mts && node ./scripts/generate-japanese-showcase-subset.mts --check",
"check:japanese-showcase-subset": "node ./scripts/provision-harfbuzz.mts --check && node ./scripts/generate-japanese-showcase-subset.mts --check",
"check:showcase-rasters": "pnpm --filter @pmndrs/text build && pnpm --filter @pmndrs/text-font-baker build && node ./scripts/generate-showcase-raster-fixtures.mts --check",
"dev": "pnpm --filter @pmndrs/text-font-baker build && vite",
"format": "oxfmt .",
Expand Down Expand Up @@ -59,7 +59,7 @@
"profile:inspect:paragraph-font-size:bitmap": "node ./scripts/summarize-cpu-profile.mts ./.cache/paragraph-font-size-bitmap.cpuprofile",
"profile:icon-grid:gc": "vitexec --gpu --cpu-profile ./.cache/icon-grid.cpuprofile --performance-trace ./.cache/icon-grid-performance.json --heap-snapshot ./.cache/icon-grid-heap.txt --path '/presentation?mode=benchmark&technique=bitmap&backend=webgpu&delivery=baked&dpr=2&font=inter&workload=icon-grid' ./vitexec/icon-grid-gc.probe.ts",
"profile:presentation-sweep": "vitexec --gpu --path '/presentation?mode=benchmark&technique=bitmap&backend=webgpu&delivery=baked&dpr=2&font=inter&workload=benchmark-ipsum' ./vitexec/presentation-framerate-sweep.probe.ts",
"test": "pnpm check:size && pnpm check:autoresearch-baseline && pnpm check:japanese-showcase-subset && pnpm check:paragraph-bidi-contract && pnpm check:paragraph-cjk-contract && pnpm test:unit && pnpm test:headless && pnpm test:packed",
"test": "pnpm check:size && pnpm check:autoresearch-baseline && pnpm check:paragraph-bidi-contract && pnpm check:paragraph-cjk-contract && pnpm test:unit && pnpm test:headless && pnpm test:packed",
"test:headless": "pnpm --filter @pmndrs/text build && pnpm --filter @pmndrs/text-font-baker build && node ./scripts/run-headless.mts --suite conformance --dpr 1 --samples 3 --warmup 1 --port 5181",
"test:packed": "pnpm --filter @pmndrs/text build && pnpm --filter @pmndrs/text-font-baker build && node ./scripts/run-packed-consumer.mts",
"test:live": "node ./scripts/run-live-probe.mts",
Expand All @@ -70,7 +70,7 @@
"test:raster-technique-compare:webgl": "vitexec --gpu --path '/?mode=conformance&technique=mtsdf&backend=webgl2&delivery=baked&dpr=1&font=inter&workload=mtsdf-slug-compare' ./vitexec/raster-technique-compare.probe.ts",
"test:raster-technique-compare:webgpu": "vitexec --gpu --path '/?mode=conformance&technique=mtsdf&backend=webgpu&delivery=baked&dpr=1&font=inter&workload=mtsdf-slug-compare' ./vitexec/raster-technique-compare.probe.ts",
"test:unit": "vitest run && pnpm test:scripts",
"test:scripts": "node --test ./scripts/support/project-chromium.test.mts",
"test:scripts": "node --test ./scripts/support/*.test.mts",
"test:watch": "vitest",
"typecheck": "pnpm --filter @pmndrs/text-font-baker build && tsc -p tsconfig.json --noEmit && tsc -p tsconfig.scripts.json --noEmit"
},
Expand Down
24 changes: 24 additions & 0 deletions apps/benchmarks/scripts/support/toolchain-scope.test.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import test from 'node:test';

const workspaceRoot = new URL('../../../../', import.meta.url);

test('keeps optional HarfBuzz tools outside the root contributor toolchain', async () => {
const [rootMise, benchmarkMise, manifest, workflow] = await Promise.all([
readFile(new URL('mise.toml', workspaceRoot), 'utf8'),
readFile(new URL('apps/benchmarks/mise.toml', workspaceRoot), 'utf8'),
readFile(new URL('apps/benchmarks/package.json', workspaceRoot), 'utf8').then(JSON.parse),
readFile(new URL('.github/workflows/ci.yml', workspaceRoot), 'utf8'),
]);

assert.equal(rootMise.includes('[tools]'), false, 'root mise must derive only Node, pnpm, and Rust pins');
assert.match(benchmarkMise, /pipx = "1\.16\.5"/);
assert.match(benchmarkMise, /"pipx:meson" = "1\.11\.1"/);
assert.match(benchmarkMise, /"aqua:ninja-build\/ninja" = "1\.13\.2"/);

assert.doesNotMatch(manifest.scripts.test, /japanese-showcase-subset/);
assert.match(manifest.scripts['check:japanese-showcase-subset'], /provision-harfbuzz\.mts --check/);
assert.match(workflow, /mise -C apps\/benchmarks install/);
assert.match(workflow, /pnpm --filter @pmndrs\/text-benchmarks check:japanese-showcase-subset/);
});
2 changes: 1 addition & 1 deletion apps/benchmarks/src/benchmark/package-size-budgets.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const packageSizeBudgets = {
'browser-core': {
rawBytes: 330_000,
rawBytes: 331_000,
minifiedBytes: 252_000,
gzipBytes: 74_000,
brotliBytes: 57_000,
Expand Down
22 changes: 11 additions & 11 deletions apps/benchmarks/src/benchmark/package-sizes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ describe('independent package-size report', () => {
it('bounds the accepted coverage-capability growth from its pre-coverage baseline', () => {
const coverageGrowth = {
'browser-core': {
rawBytes: { baseline: 324_269, maximumGrowth: 5_400 },
minifiedBytes: { baseline: 247_205, maximumGrowth: 4_000 },
gzipBytes: { baseline: 72_108, maximumGrowth: 1_000 },
brotliBytes: { baseline: 55_251, maximumGrowth: 825 },
rawBytes: { baseline: 324_269, maximumGrowth: 6_100 },
minifiedBytes: { baseline: 247_205, maximumGrowth: 4_400 },
gzipBytes: { baseline: 72_108, maximumGrowth: 1_100 },
brotliBytes: { baseline: 55_251, maximumGrowth: 1_000 },
},
'bitmap-baker-js': {
rawBytes: { baseline: 17_478, maximumGrowth: 5_700 },
Expand All @@ -86,9 +86,9 @@ describe('independent package-size report', () => {
brotliBytes: { baseline: 173_552, maximumGrowth: 7_000 },
},
'bitmap-runtime-js': {
rawBytes: { baseline: 361_809, maximumGrowth: 9_500 },
minifiedBytes: { baseline: 271_005, maximumGrowth: 6_400 },
gzipBytes: { baseline: 78_673, maximumGrowth: 1_400 },
rawBytes: { baseline: 361_809, maximumGrowth: 10_100 },
minifiedBytes: { baseline: 271_005, maximumGrowth: 6_700 },
gzipBytes: { baseline: 78_673, maximumGrowth: 1_500 },
brotliBytes: { baseline: 60_857, maximumGrowth: 1_300 },
},
'mtsdf-baker-wasm': {
Expand All @@ -104,10 +104,10 @@ describe('independent package-size report', () => {
brotliBytes: { baseline: 4_176, maximumGrowth: 800 },
},
'mtsdf-runtime-js': {
rawBytes: { baseline: 370_255, maximumGrowth: 8_050 },
minifiedBytes: { baseline: 275_271, maximumGrowth: 5_500 },
gzipBytes: { baseline: 79_993, maximumGrowth: 1_300 },
brotliBytes: { baseline: 62_081, maximumGrowth: 1_075 },
rawBytes: { baseline: 370_255, maximumGrowth: 8_700 },
minifiedBytes: { baseline: 275_271, maximumGrowth: 5_900 },
gzipBytes: { baseline: 79_993, maximumGrowth: 1_400 },
brotliBytes: { baseline: 62_081, maximumGrowth: 1_200 },
},
} as const;
const fields = ['rawBytes', 'minifiedBytes', 'gzipBytes', 'brotliBytes'] as const;
Expand Down
5 changes: 0 additions & 5 deletions apps/benchmarks/src/benchmark/runtime-world.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,3 @@ export function useRuntimeTelemetry() {
const world = useRuntimeWorld();
return useRequiredWorldTrait(world, RuntimeTelemetry);
}

export function useRuntimeCanvasSettings() {
const world = useRuntimeWorld();
return useRequiredWorldTrait(world, RuntimeCanvasSettings);
}
147 changes: 0 additions & 147 deletions apps/benchmarks/src/components/interactive-canvas.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
{
"id": "package-sizes",
"path": "apps/benchmarks/src/generated/package-sizes.json",
"sha256": "04594bffa1d47344ac585929eb7a996caf4363958961ffcd488062994fec6333",
"sha256": "39dbcab2192df1acbc8c46c801fff1134b4bff2a17598b23c034e20c89a10fa3",
"bytes": 6825
},
{
Expand Down
Loading