Skip to content

chore(build): official Rsbuild plugin adoption — drop the standalone publint gate, register the framework-owned plugin set - #509

Merged
ScriptedAlchemy merged 3 commits into
mainfrom
chore/official-rsbuild-plugins
Sep 4, 2026
Merged

chore(build): official Rsbuild plugin adoption — drop the standalone publint gate, register the framework-owned plugin set#509
ScriptedAlchemy merged 3 commits into
mainfrom
chore/official-rsbuild-plugins

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Adopt official Rsbuild/Rslib plugins where one covers a hand-rolled build/release step, and publish the framework-owned plugin set the tools.rsbuild collision diagnostic (#497) reads. Rspack/Rsbuild/Rslib only; nothing upgraded (@rslib/core 0.23.2, workspace @rsbuild/core 2.2.1, Rslib-nested 2.1.13).

Adoption table

Hand-rolled step Official plugin Decision Why
lint:package = publint <dir> ×3 (script + "Package lint (publint)" CI step + local-ci leg) rsbuild-plugin-publint Adopted — script and CI step removed. Each of the three package rslib.config.ts already registers pluginPublint({ throwOn: 'warning' }), which is stricter than the CLI (publint <dir> exits non-zero only on errors; the plugin also fails on warnings, onAfterBuild, order: 'post'). The standalone step was a second, weaker run of the same check. lint:release is now only the attw step; the publint root devDependency goes (the plugin carries its own).
attw --pack --profile esm-only packages/agent-bundle (lint:release, release-gates job) rsbuild-plugin-arethetypeswrong@0.3.1 Kept as a script. The plugin expresses the options exactly (areTheTypesWrongOptions: { ignoreResolutions: ['node10', 'node16-cjs'] } is what --profile esm-only maps to; it runs pnpm pack on api.context.rootPath in onAfterBuild). It is unusable in this workspace: its bundled @arethetypeswrong/core loads the TypeScript compiler API through the plugin's typescript peer, which pnpm resolves to the workspace root's typescript@7.0.2 — the native compiler, no JS API — and the build crashes (TypeError: Cannot read properties of undefined (reading 'Latest') in core.js). The CLI works because @arethetypeswrong/core pins its own typescript dependency. pnpm cannot re-target a peer to a different version than the dependent's: overrides parent>child with a range re-ranges the peer but still resolves the root's copy; an npm: alias moves it to dependencies at the same 7.0.2; '-' plus a packageExtensions dependency removes both. Revisit when the repo's root TypeScript regains a JS API or the plugin takes a typescript module option.
pnpm typecheck (root tsc --noEmit, project references over src + tests + workbench + create-agent-bundle) @rsbuild/plugin-type-check Not adopted. The plugin runs ts-checker-rspack-plugin over the environment's tsconfigPath only (packages/agent-bundle/tsconfig.build.json, i.e. package source), which rslib build already type-checks while emitting declarations (rsbuild-plugin-dts, tsgo). Adding it would be a third pass over a subset of what pnpm typecheck covers (7–8 s in CI), so it can only add time.
— (no hand-rolled syntax/target check exists) @rsbuild/plugin-check-syntax Not adopted. The Rsbuild plugin is inert for the artifacts in question: pluginCheckSyntax returns early unless target === 'web', and every generated bin/*.mjs, hook wrapper, and MCP shell builds with target: 'node'. Only its raw CheckSyntaxRspackPlugin with an explicit ecmaVersion could check node output, and that would be a new gate (there is nothing to replace; validate-artifact-modules.ts parses artifacts with acorn ecmaVersion: 'latest' for import-graph integrity, not target compatibility). The emitted syntax is bounded by the profile's syntax: 'es2022', which the documented Node floor (engines: >=22.19.0) covers. Documented as an MCP-App-view-only plugin in the reference.
JSX/React setup in src/build/rslib.ts and src/build/mcp-apps.ts @rsbuild/plugin-react Already the official plugin. composeEntryLibConfig registers pluginReact({ fastRefresh: false }) on every entry; composeMcpAppsRsbuildConfig registers pluginReact() per .jsx/.tsx view. Nothing hand-rolled remained.
Monorepo source resolution rsbuild-plugin-source-build Not applicable. The framework does not resolve workspace siblings to source anywhere; declaredDependencyRoots in rslib.ts is evidence classification (which modules count as authored source), not resolution. Examples consume the built agent-bundle package by design (AGENTS.md: public exports only).

Community plugins from awesome-rstack were also evaluated and none replace a framework path: rsbuild-plugin-virtual-module writes scratch files (the framework's experiments.VirtualModulesPlugin design decision explicitly avoids that), rsbuild-plugin-dts/rsbuild-plugin-rsc/rsbuild-plugin-mcp/@module-federation/rsbuild-plugin/rspack-manifest-plugin target other problems.

Exported plugin set

The registry is packages/agent-bundle/src/build/framework-plugins.tsframeworkOwnedRsbuildPlugins: ReadonlyMap<string, string> = { 'rsbuild:react' → '@rsbuild/plugin-react' }, plus frameworkOwnedPluginCollisions(plugins) for the diagnostic. It landed in #497 (fc4d6b6c7) and this PR is rebased onto it; the file dropped out of this diff (it was byte-identical). #497 wires the AB4724 diagnostic into validateTools; this PR adds the test that derives the set from the synthesized configs and the docs table. Nothing else is registered by the framework-generated builds (publint/attw/type-check/check-syntax/source-build were all not adopted for them, see the table above), so the map stays a single entry — the registration test would fail if a build path registered a plugin outside it.

New test tests/framework-plugin-registration.test.ts (unit pool) derives the set from what the framework actually registers: composeEntryLibConfig(...).plugins and composeMcpAppsRsbuildConfig(...).environments[view].plugins for a React view must equal the map's keys exactly, a plain .ts view registers nothing, no name is registered twice, and no plugin sits at the root the consumer's tools.rsbuild.plugins merges into.

Docs (website/docs/{en,zh}/reference/configuration.mdxtools → new Plugins subsection): the framework-owned set, pointing at #497's AB4724 paragraph for why it must not be re-added, and a table of official plugins a project may add via tools.rsbuild.plugins with the surface each is relevant to (artifact entries vs MCP App views; check-syntax marked views-only per its source), plus the not-applicable list (other-framework JSX plugins, umd, the publishing checks).

CI proof that a publint failure fails the job

tests/publint-gate.test.ts (integration pool): (1) all three package rslib.config.ts register plugin-publint; (2) a real createRslib build of a temp package with a warning-level finding (EXPORTS_MISSING_ROOT_ENTRYPOINT) under the same pluginPublint({ throwOn: 'warning' }) rejects with Publint failed!; (3) the clean manifest builds. This is the gate the removed CI step relied on.

Artifact diff

No profile in src/build/** changes in this PR (the new module is not wired anywhere yet), so artifact/** for examples/audiobook-curator and examples/host-test is unchanged by construction. The package dist/** is unaffected too (rslib.config.ts untouched here).

CI timings (Verify job)

Job / step Before (main run 33769764920) After (this PR, run 33830518283)
Verify → pnpm build 15–16 s 13 s
Verify → Package lint (publint) 3–4 s step removed
Verify → pnpm typecheck 7–8 s 5 s
Release gates → pnpm check:release:ci 222 s 319 s (sibling PR #510 on the same day: 193 s — the step is dominated by test:packed; the removed publint call was ~1–3 s of it)

Net: the Verify job loses the 3–4 s publint step and nothing is added, because rsbuild-plugin-publint was already running inside pnpm build.

Other

  • docs/local-ci.md, scripts/local-ci.mjs, docs/effect-conventions.md and two dated plan docs: lint:package references updated.
  • website/docs/{en,zh}/guide/distribution/preview-packages.mdx: lint:release described as attw-only, publint as in-build.
  • Rebased over docs(site): drop the duplicate lineage Detail header key (#502 + #504 collision) #507 (the duplicate detail key that broke Docs site on main); pnpm docs:site:build green here.

Review status

Codex reviewed 7f92ac1 (PR opened). One thread, answered here rather than by reply (this PR posts no comments):

Last Codex-reviewed head: 7f92ac1. Unreviewed heads (no re-review arrived after the pushes; this PR posts no comments): the changeset-number commit, the rebases over #507, #510 and #497, and the docs sentence pointing at AB4724 — current head de25c1e87. Merged on green CI per the AGENTS.md fallback; any thread opened afterwards is answered in a follow-up PR.

@changeset-bot

changeset-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: de25c1e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-bundle Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-04T02:26:30.501661Z 7f92ac1 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@pkg-pr-new

pkg-pr-new Bot commented Sep 4, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle@509
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/create-agent-bundle@509
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@509

commit: de25c1e

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7f92ac1d36

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

* holes and plugins supplied as Promises (which Rsbuild also accepts) carry
* no name to compare until the build awaits them.
*/
export const frameworkOwnedPluginCollisions = (plugins: unknown): readonly string[] => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Wire the collision helper into validation

When a project supplies pluginReact() through tools.rsbuild.plugins, validateTools in src/config/validate.ts still only validates that rsbuild is an object and never calls this helper, so AB4724 is not emitted and the duplicate rsbuild:react plugins continue into the synthesized config. Repository-wide search shows this new production module is imported only by its test, so wire it into validateTools in this commit rather than leaving the advertised collision diagnostic for a follow-up.

AGENTS.md reference: AGENTS.md:L11-L16

Useful? React with 👍 / 👎.

@ScriptedAlchemy
ScriptedAlchemy force-pushed the chore/official-rsbuild-plugins branch 2 times, most recently from a71dff9 to 3966048 Compare September 4, 2026 03:05
@ScriptedAlchemy
ScriptedAlchemy force-pushed the chore/official-rsbuild-plugins branch from 3966048 to de25c1e Compare September 4, 2026 03:35
@ScriptedAlchemy
ScriptedAlchemy merged commit 61ff1f1 into main Sep 4, 2026
13 checks passed
@ScriptedAlchemy
ScriptedAlchemy deleted the chore/official-rsbuild-plugins branch September 4, 2026 04:03
ScriptedAlchemy added a commit that referenced this pull request Sep 4, 2026
…istry test

#518 made cwd required on composeEntryLibConfig and
composeMcpAppsRsbuildConfig; #509's framework-plugin-registration test
landed beside it without the argument, so main no longer typechecks.
ScriptedAlchemy added a commit that referenced this pull request Sep 4, 2026
…istry test (#523)

#518 made cwd required on composeEntryLibConfig and
composeMcpAppsRsbuildConfig; #509's framework-plugin-registration test
landed beside it without the argument, so main no longer typechecks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant