Skip to content

wp-build-polyfills: add export-contract build check to catch version-skew - #50676

Merged
CGastrell merged 6 commits into
trunkfrom
worktree-wp-build-polyfills-safety
Jul 27, 2026
Merged

wp-build-polyfills: add export-contract build check to catch version-skew#50676
CGastrell merged 6 commits into
trunkfrom
worktree-wp-build-polyfills-safety

Conversation

@CGastrell

@CGastrell CGastrell commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

wp-build-polyfills ships a matched set of @wordpress/* packages that call each other's exports at runtime (e.g. @wordpress/boot imports ThemeProvider from @wordpress/theme, SnackbarNotices from @wordpress/notices). When those versions drift out of sync, an imported symbol resolves to undefined at runtime — a blank dashboard with no build error and no obvious console message. That is the class of failure that shipped in Jetpack 16.0 (fixed in the 16.0.1 point release via #50515 / #50465).

The existing post-build check (validate-boot-asset.js) verifies dependency handle names, which is a different failure class and did not catch 16.0. This PR adds a second, complementary build-time guard that catches the export-skew class directly:

  • New bin/validate-export-contract.js (+ -lib.js) — after webpack, for every symbol a consumer package (@wordpress/boot, …) imports from a polyfilled provider (@wordpress/theme, @wordpress/notices, @wordpress/private-apis, @wordpress/views), it asserts the provider's shipped public API actually exports it. Both sides are read from the packages' published ESM source (build-module/*.mjs), which is stable across builds/minification — not from the webpack bundle. The provider/consumer lists are derived from SCRIPT_HANDLES / MODULE_IDS in class-wp-build-polyfills.php (single source of truth). Scoped in v1 to the classic-script providers (the window.wp.<pkg> globals, where a missing export silently becomes undefined); the ESM module providers (route, a11y) are a documented follow-up.
  • Wired into the build script, so a violation fails pnpm build → fails the build and test-js CI jobs (same gate as the existing check). Run standalone with pnpm run check-contracts.
  • Regression-testedtests/js/validate-export-contract.test.js covers the exact 16.0 shape (a consumer imports a symbol the provider no longer exports), a real-installed-tree green check, a simulated-skew red check that asserts the CLI exits non-zero, import/export parsing, and a drift test keeping the derived package lists in sync with webpack.config.js.

No change to the polyfill's runtime behavior or public PHP/JS API — this is a build-time safety net only.

Related product discussion/links

Does this pull request change what data or activity we track or use?

No.

Testing instructions

From projects/packages/wp-build-polyfills:

  • Guard is green on trunk:
    pnpm install
    pnpm run build            # webpack + validate-boot-asset + validate-export-contract, all pass
    pnpm run check-contracts  # exits 0
    
  • Tests pass (incl. the 16.0 regression and the CLI red-path):
    pnpm run build && pnpm run test   # build must run first — a pre-existing test reads its output
    
  • See the guard stop a broken build (authentic end-to-end): edit package.json"@wordpress/theme": "0.15.1" (a version that only exposed ThemeProvider privately — the real 16.0 cause), then pnpm install && pnpm run build → the build fails at validate-export-contract.js. Revert the pin + pnpm install when done. (The same red path is also asserted in the test suite via the “CLI exits non-zero … on a skew” case.)

@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack or WordPress.com Site Helper), and enable the worktree-wp-build-polyfills-safety branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack worktree-wp-build-polyfills-safety
bin/jetpack-downloader test jetpack-mu-wpcom-plugin worktree-wp-build-polyfills-safety

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

@github-actions github-actions Bot added the [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. label Jul 20, 2026
@jp-launch-control

jp-launch-control Bot commented Jul 20, 2026

Copy link
Copy Markdown

Code Coverage Summary

2 files are newly checked for coverage.

File Coverage
projects/packages/wp-build-polyfills/bin/validate-export-contract-lib.js 328/359 (91.36%) 💚
projects/packages/wp-build-polyfills/bin/validate-export-contract.js 15/15 (100.00%) 💚

Full summary · PHP report · JS report

// resolved via the browser import map rather than a window global, so they
// have a different (import-map) failure mode. Verifying them is a documented
// follow-up; see README "Export-contract validation".
const PROVIDER_PACKAGES = [

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets just have one source of truth for this list. So that we don't have to keep it updated in two places.

The same goes for @wordpress/boot', '@wordpress/route', '@wordpress/a11y'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Enej here. The list comes from https://github.com/Automattic/jetpack/blob/trunk/projects/packages/wp-build-polyfills/src/class-wp-build-polyfills.php#L22. It needs some mapping to js package names.

@dhasilva dhasilva left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial review — no blockers. Additive, build-time-only guard. I ran the suite (45/45 green) and probed the parser against the installed @wordpress/* tree; it's correct for the ESM shapes it actually runs against, and the simulate-skew test genuinely proves the boot → theme pair is scanned end-to-end (not just "green because it matched nothing").

Duplicated package lists — agree with the single-source-of-truth point already raised

PROVIDER_PACKAGES / CONSUMER_PACKAGES in validate-export-contract-lib.js duplicate a list that already exists in src/class-wp-build-polyfills.php (SCRIPT_HANDLES, L22) and in webpack.config.js. The PR keeps them honest with a drift test (PROVIDER_PACKAGES matches webpack classicPolyfills / CONSUMER_PACKAGES matches webpack modulePolyfills), but that guards around the duplication rather than removing it.

This is the same concern @enejb and @dhasilva raised inline:

+1 — deriving both lists from one source (with the PHP→JS package-name mapping dhasilva mentions) is preferable, and it would also dissolve suggestion #2 below.

Robustness suggestions (all non-blocking)

  1. parsePublicExports only recognizes consolidated export { … } blocks. It misses inline export const/function/class (verified: export const ThemeProvider = …names: []). All four current providers emit consolidated blocks, so it's green today — but a future @wordpress/* bump that ships an inline-export index would make the check report a legitimately-exported symbol as missing and spuriously fail the build. Cheap to harden by also matching export\s+(?:const|function|class|let|var)\s+(\w+).

  2. Opaque (export *) and unresolved providers silently drop coverage. The lib tracks skipped/errors, but the CLI prints nothing on success and only throws on !ok. So if a provider index switches to export * from './x', its contract is silently skipped and the build stays green — the exact silent failure class this guard exists to prevent. A console.warn per skipped/opaque/unresolved entry would keep coverage regressions visible.

  3. parseNamedImports doesn't distinguish commented-out or re-export lines. It treats // import { X } from '@wordpress/theme' as a real import (false positive) and ignores export { X } from … re-exports and mixed import Default, { X } (false negatives). None of these shapes occur in the current boot/route/a11y build output, so low real-world risk — a one-line comment documenting the "clean named-import lines only" assumption would suffice.

Scope

This is a name-presence contract, not a semantic/version check: a symbol that is present but broken (wrong signature, stub implementation) passes. That's an appropriate boundary for a static build-time guard and the PR is honest about it — noting it only so the guarantee isn't over-read.

Verdict: minor issues — can merge after addressing. Also resolve the draft's P2/Slack/Linear TODO before marking ready for review.

Generated by Claude.

@CGastrell

Copy link
Copy Markdown
Contributor Author

Roadmap: making wp-build-polyfills safer

Follow-up to the Jetpack 16.0 blank-admin-dashboard incident (fixed in 16.0.1 via #50515 / #50465). Root cause was a silent version skew between two @wordpress/* packages this package ships as a matched set: @wordpress/boot expected a public ThemeProvider from @wordpress/theme, but the shipped theme version only exposed it privately → undefined at runtime → blank dashboard, with no build error. Planning the work in independently-reviewable layers.

This PR — export-contract build check ✅

For every symbol a consumer (boot/route/a11y) imports from a classic-script provider (theme/notices/private-apis/views), assert the shipped provider's public API actually exports it. Fails the build (→ red CI) when it doesn't — the direct detector of the 16.0 failure, complementing the existing handle-name check in validate-boot-asset.js. Build-only; no runtime or dependency changes. Provider/consumer lists derive from SCRIPT_HANDLES / MODULE_IDS in class-wp-build-polyfills.php (single source of truth). Includes manual-trigger tooling (check-contracts, simulate:skew) and a regression test that encodes the exact 16.0 shape.

Finding — a live (currently benign) version skew on trunk

@wordpress/boot@0.18 declares @wordpress/theme: ^1.0.0, but this package pins ^0.17.0 and builds the wp-theme global from 0.17.0. Nothing flags it today: pnpm resolves boot's own @wordpress/theme to a nested 1.0.0 (so no unmet-peer error), while webpack builds the top-level 0.17.0 — the two never meet at install. The export-contract check stays green because the only symbol boot uses from theme (ThemeProvider) exists in 0.17 — but the versions are misaligned, so green is partly luck.

I investigated whether the polyfill can simply move to @wordpress/theme@1.0.0 (now the npm latest): yes, low-risk. ThemeProvider's JS API is identical; the ESM-only change in 1.0 (dropping the CJS entry) doesn't break the webpack build; the privateApis bridge is still exported; and the generated color tokens are unchanged. Confirmed with a local build test — build succeeds and the emitted wp.theme global stays compatible. The 1.0 breaking changes are almost all static design tokens this package doesn't ship, so the monorepo blast radius is small (a handful of --wpds-elevation-* box-shadow references).

Follow-ups (separate PRs)

  1. Bump the pinned @wordpress/theme to ^1.0.0 — reconciles the skew at its source, so the guard is green because the versions match, not by coincidence. It's a runtime change to the shared wp.theme global that every wp-build dashboard boots through, so it warrants its own PR with a dashboard smoke test and a minimal lockfile diff — sequenced after this guard lands.
  2. Renovate atomic group for the co-released @wordpress/* set — prevents the two-cadence dependency drift that produced the original skew.
  3. Semver-range assertion (optional, after Use class_exists() guard for Featured_Content. #1) — flags declared-version mismatches, complementing this PR's export-level check.
  4. Extend the export-contract check to the ESM module providers (route / a11y), which resolve via the import map rather than a window global.
  5. CI smoke cell on the minimum supported WordPress + Gutenberg inactive — the exact environment that regressed.

@CGastrell

Copy link
Copy Markdown
Contributor Author

Status update on the follow-ups

Checked where the other layers from the roadmap actually stand — most are already covered:

  • Atomic Renovate grouping (prevention): already in place. The "Bundled @wordpress/* monorepo" group in .github/renovate.json5 includes every package this one polyfills — boot / theme / notices / private-apis / route / a11y / views (added in renovate: Add polyfilled packages to the "Bundled WP" group #50668) — with separateMajorMinor: false, so they bump together. No separate change needed.

  • The @wordpress/theme 0.17 → 1.0 reconciliation: already in flight as Update Bundled @wordpress/* monorepo #50509 ("Update Bundled @wordpress/* monorepo"), which bumps the whole bundled set (theme, ui, …) across the monorepo together. The version skew this PR's check makes visible — @wordpress/boot@0.18 expects @wordpress/theme@^1.0.0, but the package currently ships ^0.17.0 — is monorepo-wide (every consumer is pinned at 0.17) and resolves when Update Bundled @wordpress/* monorepo #50509 lands. A polyfill-only bump would be both redundant with Update Bundled @wordpress/* monorepo #50509 and messy: bumping theme alone (while the other consumers stay at 0.17) makes pnpm re-resolve peer suffixes tree-wide (theme 1.0 widens its React peer to ^18 || ^19), producing a large, unrelated lockfile churn.

  • This PR's guard vs theme 1.0: confirmed compatible. I built the polyfill against @wordpress/theme@1.0.0 locally — the build succeeds (1.0 is ESM-only, which the webpack build handles), the emitted wp.theme global is unchanged (ThemeProvider + privateApis + the same color tokens), and the export-contract check stays green (now for the right reason: boot ↔ theme aligned). So this check won't block Update Bundled @wordpress/* monorepo #50509.

Still open (feedback welcome):

  • Extending the export-contract check to the ESM module providers (route / a11y), which resolve via the browser import map rather than a window.wp.* global — a different failure mode than the classic-script one that caused 16.0. Lower urgency; easy to add if it's wanted.
  • A semver-range assertion (flagging declared-version mismatches like the boot ↔ theme one directly) — better added after Update Bundled @wordpress/* monorepo #50509 lands, since it would otherwise flag the current in-flight skew as a failure.

@CGastrell
CGastrell marked this pull request as ready for review July 21, 2026 13:28
@CGastrell CGastrell removed the [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. label Jul 21, 2026

@anomiex anomiex left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At a quick glance, it looks like your AI went way overboard with the comments and readme docs, and possibly over-engineered the testing too. Does it really need a CLI command run during the build and the same code run in the unit testing?

Also, one other thing in progress that your AI missed: #50621

Comment thread projects/packages/wp-build-polyfills/bin/validate-export-contract-lib.js Outdated
Comment thread projects/packages/wp-build-polyfills/package.json Outdated
@CGastrell CGastrell changed the title wp-build-polyfills: add export-contract build check to catch version-skew blank dashboards wp-build-polyfills: add export-contract build check to catch version-skew Jul 21, 2026
CGastrell and others added 4 commits July 23, 2026 11:33
…skew blank dashboards

Ship a build-time guard that fails the build when a polyfilled package imports
a symbol the shipped version of another polyfilled package does not export —
the Jetpack 16.0 blank-dashboard failure mode (boot imported ThemeProvider but
the shipped @wordpress/theme only exposed it privately → undefined at runtime).

- bin/validate-export-contract{,-lib}.js: scan consumer imports (boot/route/a11y)
  vs classic-script provider exports (theme/notices/private-apis/views) from the
  packages' published ESM source; fail on any missing symbol.
- Wire into the build script so a violation reddens the build + test-js CI jobs.
- Manual triggers: `check-contracts`, `simulate:skew` (WP_BUILD_POLYFILLS_SIMULATE_MISSING),
  plus a real-version-pin recipe in the README.
- tests/js/validate-export-contract.test.js: 19 cases incl. the 16.0 regression,
  real-tree green check, simulated-skew red check, and webpack-config drift test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…test coverage

- package.json: sort scripts lexicographically (package-json/sort-collections).
- Cover the CLI wrapper end-to-end (child_process) and defensive lib branches
  (parseSimulateEnv malformed input, formatError errors path, unresolvable
  packages), matching the existing validate-boot-asset-lib coverage bar.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e of truth

Address review (enejb, dhasilva): don't maintain the shipped-package list in a
second place. Derive the export-contract validator's provider/consumer lists
from SCRIPT_HANDLES + MODULE_IDS in class-wp-build-polyfills.php (mapping wp-*
handles → @wordpress/* names), the same constants that register them at runtime.

The drift test now guards PHP↔webpack agreement instead of comparing to a
hardcoded copy, so a polyfill added to one but not the other fails the build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address review (anomiex): trim the AI-verbose comments and README to match the
codebase, and cut the over-engineered test surface.

- Concise comments/JSDoc; README safety note reduced to a short bullet list.
- Remove the WP_BUILD_POLYFILLS_SIMULATE_MISSING env feature and the
  `simulate:skew` script (manual-trigger meta-tooling); keep the `simulateMissing`
  test hook that drives the 16.0 regression test.
- Tests: 27 → 7 (16.0 regression, import/export parsing, PHP-derivation↔webpack
  sync, real-tree green + simulated-skew, CLI green).

Same behavior: the check still runs in `build` and trips on a missing export.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@CGastrell
CGastrell force-pushed the worktree-wp-build-polyfills-safety branch from cd05eea to d9b1a61 Compare July 23, 2026 14:35
@CGastrell
CGastrell requested a review from Copilot July 23, 2026 17:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new post-build “export contract” validator to wp-build-polyfills to catch @wordpress/* version-skew where a consumer imports a symbol that the shipped provider package does not export (the Jetpack 16.0 blank-dashboard failure mode). It complements the existing .asset.php dependency-handle validation by checking the actual JS export surface area.

Changes:

  • Add bin/validate-export-contract.js + shared library to verify consumer named imports exist in provider public exports.
  • Wire the new validator into pnpm run build, and add a standalone pnpm run check-contracts script.
  • Add Node test coverage for parsing/contract checking + installed-tree validation, plus README + changelog updates.

Reviewed changes

Copilot reviewed 4 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
projects/packages/wp-build-polyfills/bin/validate-export-contract.js New CLI entrypoint that runs the export-contract validator post-build.
projects/packages/wp-build-polyfills/bin/validate-export-contract-lib.js Core implementation: reads shipped provider/consumer lists, parses imports/exports, and reports contract violations.
projects/packages/wp-build-polyfills/tests/js/validate-export-contract.test.js Regression and behavior tests covering parsing, contract failures, and installed-tree checks.
projects/packages/wp-build-polyfills/package.json Wires export-contract validation into build and adds check-contracts.
projects/packages/wp-build-polyfills/README.md Documents the new safety check and how to run it.
projects/packages/wp-build-polyfills/changelog/add-export-contract-validation Changelog entry for the new build-time guard.

Comment thread projects/packages/wp-build-polyfills/README.md
- parseNamedImports: handle mixed default+named imports (`import Def, { Bar }`),
  which the regex previously missed (silent false-negative).
- Warn (not silently skip) when a provider's index uses `export *` and can't be
  statically verified — a barrel would otherwise open a hole in the guard.
- Cover the CLI failure path end-to-end: a test-only env hook injects a skew and
  asserts the CLI exits non-zero (the actual CI gate).
- README: use full `@wordpress/*` package names in the provider list.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 6 changed files in this pull request and generated no new comments.

@dhasilva

Copy link
Copy Markdown
Contributor

Took another pass over the post-feedback state (9806dbc). This looks good — the single-source-of-truth rework that @enejb and @dhasilva asked for is properly done, and I like that the check reads the packages' build-module/*.mjs rather than the webpack output: that's what the browser actually ends up seeing via the wp.theme global, so it's the right thing to compare against.

I ran things locally to make sure the green isn't vacuous:

  • pnpm run test → 28/28 pass, eslint clean on the three new files.
  • Driving validateExportContracts() against the installed tree produces four real contracts (boot→notices, boot→private-apis, boot→theme, route→private-apis), so it's genuinely scanning the pair that caused 16.0.

No blockers from me. A few small suggestions, all optional — the first two are the items from the earlier review round that I think are still worth closing, since both protect against the check quietly misbehaving:

1. parsePublicExports only matches consolidated export { … } blocks (lib.js#L98-L101)

Verified: parsePublicExports( 'export const ThemeProvider = () => {};' ){ names: [] }. All four providers currently ship esbuild-consolidated indexes so it's green today, but the failure direction is the awkward one — a future @wordpress/* bump emitting inline exports would report every consumer symbol as missing and fail a build that's actually fine. One extra pass closes it:

for ( const m of indexSource.matchAll( /export\s+(?:const|function|class|let|var)\s+([\w$]+)/g ) ) {
	names.add( m[ 1 ] );
}

2. A few continues still drop coverage silently

The export * branch got a nice console.warn, but the provider-unresolved (L272), consumer-unresolved (L300) and no-build-module (L304) paths still exit quietly. If @wordpress/boot ever renames its output dir, the build goes green having verified nothing.

To be fair, the simulated-skew test would catch that for boot → theme (empty results ⇒ ok === true ⇒ the assertion fails), so it wouldn't reach production unnoticed — it'd just surface as a puzzling unit-test failure rather than a build-time warning, and the other three pairs have no equivalent tripwire. The same one-liner as the opaque branch would do it. A cheap complement: assert result.results.length > 0 in the "passes for the actually-shipped versions" test, so "green because nothing was scanned" can't slip through.

3. readPackageExports ignores the exports map (L188)

pkg.module || pkg.main — worth noting @wordpress/boot@0.18.0 already ships no main. I checked npm and @wordpress/theme@1.0.0 still publishes module, so #50509 won't trip this. But an exports-only publish would land in the errors array and fail the build with Could not read exports for @wordpress/x — a confusing message for something that isn't a skew. pkg.exports?.[ '.' ]?.import ?? pkg.module ?? pkg.main would match how resolution actually works.

4. Tiny docs nit — a one-line comment on parseNamedImports noting the "clean named-import lines only" assumption, as @dhasilva suggested. Confirmed both edges: // import { Ghost } from '@wordpress/theme'; yields [ 'Ghost' ], and export { Foo } from '@wordpress/theme' yields []. Neither shape occurs in the current boot/route output, so this is purely documenting the boundary.

5. The description still has the TODO (before un-drafting): add P2/Slack/Linear shortlinks line, and the label is still [Status] In Progress — probably just leftovers now that it's out of draft.

Nice piece of work — the CLI red-path test asserting a non-zero exit rather than just the library return value is a good touch, since that's the actual CI gate.

Generated by Claude.

Address dhasilva's follow-ups (all closing "silent green" holes):
- parsePublicExports also reads inline `export const/function/...` declarations,
  not just consolidated `export { … }` blocks — an inline-export bump would
  otherwise report every symbol missing and fail a valid build.
- Warn (not silently continue) when a provider/consumer is unresolvable or a
  consumer has no build-module/, and assert results.length > 0 in the real-tree
  test so a vacuous green can't slip through.
- readPackageExports honors the `exports` map (exports['.'].import ?? module ?? main).
- Document parseNamedImports' import-only boundary.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@CGastrell CGastrell added [Status] Needs Review This PR is ready for review. and removed [Status] In Progress labels Jul 27, 2026
@CGastrell
CGastrell merged commit cf0ebce into trunk Jul 27, 2026
157 of 158 checks passed
@CGastrell
CGastrell deleted the worktree-wp-build-polyfills-safety branch July 27, 2026 16:13
@github-actions github-actions Bot removed the [Status] Needs Review This PR is ready for review. label Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants