Read-only audit of the build/metaframework setup on main (cbda5abe6, after #547) against the Rstack agent skills (rslib-best-practices, rslib-modern-package, rspack-best-practices, rspack-split-chunks, rsbuild-best-practices, rstest-best-practices, rspress-best-practices, rsdoctor-analysis) and the current upstream docs (rslib.rs/guide/upgrade/v0-to-v1). No files were changed and no build was run; evidence comes from the configs, the installed node_modules, the last local dist/, and the published registry metadata.
Format per finding: priority · file:line · skill rule · why it matters here · concrete change · risk/notes. Findings are ordered by priority inside each area; the "already compliant" list at the end is there so nobody re-audits those points.
Installed vs latest at audit time: @rslib/core 0.23.2 → 1.0.0, @rsbuild/core 2.2.1 → 2.2.3, @rspack/core 2.1.10 (via Rslib) / 2.2.1 → 2.2.2, @rstest/* 0.11.10 → 0.11.12, @rspress/core 2.0.21 (latest), @rslint/core 0.8.2 → 0.9.1.
1. The compiler (packages/agent-bundle/src/build/*)
P1 · packages/agent-bundle/package.json:101,103, src/build/rslib.ts:5, src/build/mcp-apps.ts:1 · rslib-modern-package: keep the consumer install lean, one copy of each toolchain package; rslib-best-practices: keep Rslib and the Rsbuild plugins in sync · agent-bundle depends on both @rslib/core@0.23.2 (→ @rsbuild/core@2.1.13 → @rspack/core@2.1.10) and @rsbuild/core@2.2.1 (→ @rspack/core@2.2.1). Every consumer therefore installs two 28 MB @rspack/binding-* native packages, and the process runs two Rspack engines: the executable compiler uses the rspack re-exported by @rslib/core (2.1.10) while MCP Apps use @rsbuild/core's (2.2.1). · Bump @rslib/core to ^1.0.0 (depends on @rsbuild/core ~2.2.2) and @rsbuild/core to 2.2.3 in the same PR, then add a guard to the packed pool (already installs the tarball) asserting exactly one @rspack/binding-* directory in the consumer tree, or pnpm dedupe --check in CI. · Risk: Rslib v1 is a breaking release; the blockers specific to this repo are the next finding and must land in the same PR.
P1 · Rslib 0.23 → 1.0 migration blockers (from rslib.rs/guide/upgrade/v0-to-v1) · rslib-best-practices: read the upgrade guide, verify with rslib inspect before bumping
src/build/entry-shell.ts:43-44,128-129 — new URL('./cli-entry.js', import.meta.url) / new URL(\./${name}.js`, import.meta.url)inside agent-bundle's own ESM build. Rslib v1 processes statically analyzablenew URL()as static assets and rejects targets that exist only in the build output → build failure or a bogus asset. Rewrite withfileURLToPath+path.join(the guide's recommendation for filesystem paths) or add/* rspackIgnore: true */`.
src/build/entry-shell.ts:149,275 — generated entry strings emit new URL("../", import.meta.url) and new Worker(new URL('./<worker>.js', import.meta.url), …) into user builds compiled by the compiler's Rslib. In v1 these become an asset reference to a directory (rejected) and a Worker entry that re-bundles a file the compiler already emits as its own entry. Emit /* rspackIgnore: true */ in the generated strings now (a no-op on 0.23), or in composeEntryLibConfig set chain.module.rule('rslib:new-url').parser({ url: false }) and module.parser.javascript.worker: false.
externalsType default changes from module-import to modern-module: CommonJS require() of externalized node: builtins inside inlined dependencies is emitted as createRequire(). dist/*.js of agent-bundle is re-bundled by the compiler into user artifacts, so either enable module.parser.javascript.createRequire in the compiler's Rspack config or keep externalsType: 'module-import' in packages/agent-bundle/rslib.config.ts.
src/build/rslib.ts:603 — autoExternal: false is deprecated in v1 → output: { autoExternal: false }.
src/build/rslib.ts:760 — rslib.inspectConfig() without mode; in v1 mode is inferred from NODE_ENV, and under development it returns only format: 'mf' libs, so assertExecutableConfig at :761 would see zero bundler configs when a user runs agent-bundle build from a dev script. Pass { mode: 'production' } explicitly (safe today).
dts: true — with TypeScript 7 at the repo root, v1 auto-selects tsgo; redirect.dts.extension defaults on. Compare dist/**/*.d.ts before/after with attw --profile esm-only.
- All four packages set
syntax: 'es2022' explicitly, so the new engines.node inference does not change output; see the P3 below for aligning it deliberately.
P2 · src/build/rslib.ts:760-761, src/build/inspect-bundler.ts:51-68, src/cli.ts:1019-1039 · rslib-best-practices: use rslib inspect (dist/.rsbuild/rspack.config.*.mjs) to verify the final Rspack config, not the input · agent-bundle inspect --bundler dumps the composed Rslib/Rsbuild config with functions rendered as [function …]. The lowered Rspack config — the real externals after guardReservedExternals, the $-suffixed resolve.alias entries, the virtual-modules plugin, optimization.splitChunks, node, output.module — is computed at :760 (inspection.origin.bundlerConfigs) and consumed only by assertExecutableConfig; it is never persisted, so a plugin author debugging a tools.rspack escape hatch cannot see what the hatch produced. · Add inspect --bundler --lowered (or --write-config) that calls rslib.inspectConfig({ writeToDisk: true, outputPath: '<artifact>/.rsbuild', mode: 'production' }) or serializes origin.bundlerConfigs, and expose it in the Workbench build panel. · Risk: the dump contains absolute paths; label it a debugging artifact and keep it out of packs.
P2 · packages/agent-bundle/rslib.config.ts:111-116 vs the compiler that inlines dist/*.js (src/build/rslib.ts:603, src/build/entry-shell.ts:21-64,119-137) · rspack-split-chunks: choose the chunk strategy deliberately and verify it in the output; rslib-modern-package: validate the artifact, not the config · The 24-entry bundle-mode build emits ~47 numeric shared chunks (dist/1178.js, dist/5610.js, …); runtime-facing entries the compiler inlines into user artifacts are thin re-exports (dist/mcp-server-runtime.js is 180 bytes → ./5610.js). The comment at :111-116 documents that a shared chunk carrying Rslib's __webpack_require__ runtime shadows the artifact bundler's runtime, and the only guard is the manual mcp-tasks entry split — any future module shared between mcp-server-runtime and a sibling re-introduces the bug silently. · Build the inlined runtime entries (mcp-server-runtime, mcp-entry, cli-entry, install-entry, launch-env, terminal-capability, meta, routes, event-ipc, event-project) as a second lib with splitChunks: false so each is self-contained, and add a check:release assertion that the transitive chunk closure of those entries contains no __webpack_require__/__webpack_modules__. · Risk: some duplicated code between the two libs' outputs; acceptable for a devDependency. (The last local dist/ predates launch-env/mcp-tasks, so re-check the chunk closure after pnpm build.)
P3 · src/build/rslib.ts:628-630 · rsbuild-best-practices: legalComments — keep third-party licence text when bundling; enable source maps for Node output · legalComments: 'none' is a no-op here: Rsbuild applies legalComments only through the SWC minimizer (getSwcMinimizerOptions), and minify: false disables it, so inlined dependencies' licence headers survive by accident. If minification is ever enabled, every user artifact silently drops licences. · Set legalComments: 'inline' so the intent is explicit; keep minify: false. Separately, sourceMap: false makes stack traces inside inlined dependencies opaque — consider an opt-in --source-map flag (output.sourceMap: { js: 'source-map' }, .map excluded from packs via files, run with node --enable-source-maps). · Risk: none.
P3 · src/build/rslib.ts:623 · rslib-best-practices: align lib.syntax with the runtime floor in engines.node · The compiler hard-codes syntax: 'es2022' although the framework requires Node ≥ 22.19 (packages/agent-bundle/package.json engines) and generated artifacts only ever run there. · syntax: ['node >= 22.19'] now; after v1, omit it for user builds and let Rslib infer from the user package's engines.node (falls back to esnext). · Risk: ES2023+ syntax stays untranspiled, which is correct for the target.
P3 · src/build/mcp-apps.ts:198-210 · rsbuild-best-practices: set the browserslist for web targets explicitly · The MCP Apps web build has no output.overrideBrowserslist, so Rsbuild's default baseline (Chrome 87, Safari 14, …) lowers syntax and CSS for host webviews that are all recent Chromium. · output.overrideBrowserslist: ['chrome >= 120'] (or a documented constant beside dataUriLimit). · Risk: none; inlined HTML apps get slightly smaller.
2. Workspace package builds
P1 · packages/rsc-runtime/package.json:83, packages/rsc-runtime/src/lower-mcp.ts:3, packages/rsc-runtime/src/project-mcp.ts:1 · rslib-modern-package: dependencies hold only what shipped code and shipped declarations need · @modelcontextprotocol/sdk@1.30.0 (express 5, hono, jose, cors, ajv, zod-to-json-schema, eventsource, …) is installed by every @agent-bundle/runtime consumer for two import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js' lines. Because the emitted dist/lower-mcp.d.ts and dist/project-mcp.d.ts reference it, it must stay a runtime dependency as long as the import exists — which is exactly why AB7014 accepts it and a human has to decide. · import type { CallToolResult } from '@modelcontextprotocol/server' (already a dependency; exported at @modelcontextprotocol/server@2.0.0/dist/index.d.mts:738), then delete the 1.x dependency. · Risk: structural differences between the 1.x and 2.x CallToolResult types; pnpm typecheck and the runtime unit tests cover it. patch changeset, docs unaffected.
P2 · packages/rsc-runtime/rslib.config.ts:24-99 · rslib-best-practices: output.externals is for third-party packages; share internal modules through one multi-entry lib (shared chunks) or bundleless output with redirect · Six separate bundle-mode libs are stitched with string-keyed externals ('../state/index.js': './state.js', './index.js': '../notices.js', …) so the kernel is bundled once; the comment at :88-91 explains that a duplicated module graph forks class identity and breaks instanceof AgentStateError. String externals match the literal request: an import from one directory deeper (../../state/index.js), a new file in a nested folder, or a re-export through another path silently re-bundles the kernel, and no test asserts identity across entries. · (a) One lib with all nine entries — Rslib extracts shared modules into common chunks, so there is exactly one module instance while each entry's graph stays lean (node:sqlite still loads only via state/sqlite); or (b) bundle: false with redirect.js (v1 turns on redirect.dts.extension). Either way add a packed test that AgentStateError from @agent-bundle/runtime, /state, /state/sqlite, /mount and /lineage is the same class. · Risk: (a) changes the dist layout to numeric shared chunks; exports (package.json) and sideEffects: false (:24) are unaffected.
P2 · packages/agent-bundle/rslib.config.ts:50 + the tarball · rslib-modern-package: shipped declarations must not reference devDependencies; validate with attw/publint · dts: true in bundle mode emits one .d.ts per source file (≈0.97 MB of .d.ts in the pack, e.g. dist/events/ipc.d.ts, dist/routes/input-schema.d.ts) including internals that reference devDependencies (zod, typescript-5). Nothing under exports reaches them today, so this is latent, but the next re-export can turn it into a consumer type error under skipLibCheck: false. · Either dts: { bundle: true } per exported entry (API Extractor) so only the public surface ships, or keep per-file output and add attw --profile esm-only plus a check that no packed .d.ts imports a devDependency to check:release (package.json:52). · Risk: API Extractor adds a devDependency and build time; tsgo (automatic on Rslib v1 with TS 7) offsets it.
P3 · packages/agent-bundle/package.json:100,122 · rslib-modern-package: package.json is the authority · @modelcontextprotocol/server is declared in both dependencies and devDependencies. · Delete the devDependencies entry. · Risk: none.
P3 · packages/agent-bundle/package.json:132-134, packages/rsc-runtime/package.json:77-80 · rslib-modern-package: peers express the real compatibility contract — no *, no accidental exact pins, optional when only some entries need them · (i) "@agent-bundle/runtime": "*" while generated code imports @agent-bundle/runtime/{mount,notices,notices/inbox-route,state,state/sqlite,flight/server} (src/build/entry-shell.ts:31,211-213,571,808-809): a runtime older than those subpaths breaks at the consumer's runtime, not at install. Use ">=<first version with those subpaths> <1" and bump it in the changeset that adds a subpath; pnpm-workspace.yaml:13-15 keeps local linking. (ii) react: 19.2.8 exact peers (documented as deliberate in packages/rsc-runtime/README.md:70) are tighter than react-server-dom-rspack@0.1.0's own ^19.1.0; consider ~19.2.8 or say why the patch pin is required. (iii) @rspack/core is a required peer of @agent-bundle/runtime although no source file imports it (only react-server-dom-rspack's build side needs it) — mark it optional in peerDependenciesMeta. · Risk: (i) is a patch changeset; (ii)/(iii) loosen installs only.
P3 · packages/rsc-runtime/package.json:88, pnpm-workspace.yaml:15 · rslib-modern-package: workspace deps use the workspace protocol · "rsc-markdown-stream": "^0.1.0" is linked locally only because of the overrides entry. · workspace:^ — pnpm rewrites it to ^0.1.0 on publish, and the override becomes unnecessary (same for @agent-bundle/runtime if any package lists it by range). · Risk: none.
P3 · packages/rsc-markdown-stream/rslib.config.ts:11,21 · rslib-modern-package: declarations are generated from the source that ships · dts: false with a hand-copied src/index.d.ts (vendored in #344) can drift from dist/index.js with no compiler check. · dts: true if the source is TypeScript; otherwise add a typecheck-only test that consumes dist/index.js through the hand-written declarations (attw does not catch semantic drift). · Risk: none.
P3 · all four package.json files · rslib-modern-package: explicit exports, expose ./package.json · No package exports ./package.json, and create-agent-bundle/package.json has no exports at all (acceptable for a bin-only package, but it leaves dist/** importable). · Add "./package.json": "./package.json" everywhere and exports: { "./package.json": "./package.json" } to create-agent-bundle to close the surface. · Risk: none (publint already gates the rest).
P3 · packages/agent-bundle/rslib.config.ts:22-32,79-88 · rslib-best-practices: prefer lib.shims.esm over custom __filename/__dirname handling · A custom processAssets plugin prepends an ESM shim to chunks that mention __filename/__dirname (the bundled TypeScript 5 parser), and tools.rspack disables Rspack's Node polyfills. Rslib's shims: { esm: { __filename: true, __dirname: true } } exists for exactly this. · If shims.esm was tried and rejected for #381, say so in the comment; otherwise replace the plugin with the option. · Risk: the built-in shim rewrites per module rather than per chunk — verify with the packed pool's TypeScript-parser tests.
3. Tests (rstest.*.ts)
P2 · rstest.integration-tests.ts (108 literal test paths), rstest.unit.config.ts:19-33, package.json:13 · rstest-best-practices: use projects with directory-based include; keep the config declarative · Pools are defined by subtraction — the unit pool is packages/**/tests/**/*.test.ts minus eight hand-maintained exclusion lists — and nothing checks that a listed path exists. A renamed or moved integration test silently drops into the non-isolated, parallel unit pool, and a deleted one leaves a stale entry. · Move suites into tests/unit, tests/integration, tests/projection, tests/route-unit, tests/packed, … (or a .int.test.ts suffix) and replace the four per-leg configs with one rstest.config.ts using projects/defineProject, so pnpm test becomes rstest run and CI can --project or shard. Interim guard: a unit test asserting every listed path exists. · Risk: mechanical moves touch many imports; do it per pool.
P2 · rstest.rslib.ts:8-17 · rstest-best-practices: reuse the build config only when it is compatible; explicitly drop publish-time plugins · withRslibConfig copies plugins, tools, source, resolve and performance.buildCache from packages/agent-bundle/rslib.config.ts into every test build (adapter source: plugins: finalLibConfig.plugins, tools: {rspack, swc, bundlerChain}). So pluginPublint({ throwOn: 'warning' }), the agent-bundle:esm-node-globals asset rewrite, tools.rspack's ignoreWarnings/node.__dirname=false, and source.define.__AGENT_BUNDLE_VERSION__ run in the unit, integration, packed and evidence pools. · In modifyLibConfig filter plugins to what tests need (plugins.filter(p => p.name !== 'rsbuild:publint' && p.name !== 'agent-bundle:esm-node-globals')), drop the publish-only tools.rspack hook, and comment what is intentionally kept (define, tsconfigPath). · Risk: low; confirm with DEBUG=rstest whether publint's onAfterBuild fires against the workspace root manifest (root: workspaceRoot) inside dist/.rstest-temp.
P2 · rstest.unit.config.ts:37 (isolate: false) + packages/agent-bundle/tests/inspect-state.test.ts:44 · rstest-best-practices: restore mocks, env and globals between tests; use rs.stubGlobal and unstubGlobals · The test mutates globalThis.__AGENT_BUNDLE_VERSION__ for the whole shared worker with no restore, and no config sets restoreMocks/clearMocks/unstubEnvs/unstubGlobals. The adapter already applies source.define so the identifier at src/cli.ts:726 is replaced at compile time — the stub is likely dead and, in a non-isolated pool, order-dependent. · Remove the defineProperty (or use rs.stubGlobal with unstubGlobals: true), and set restoreMocks: true, clearMocks: true, unstubEnvs: true, unstubGlobals: true in the shared config for all pools. · Risk: reveals other order-dependent tests — that is the point.
P3 · packages/agent-bundle/tests/mcp-session-service.test.ts:272,1137,1150 · rstest-best-practices: wait on observable state, not fixed sleeps · Three fixed sleeps (25 ms, 10 ms, 10 ms) between issuing a request and cancelling/observing it, in a suite that runs on the parallel integration pool (rstest.integration.config.ts:31,61); poolTimeScale scales timeouts but not these sleeps, which is the classic contention flake. · Wait on a signal from the fixture server (request acknowledged) or expect.poll / a bounded retry loop instead of the sleep. · Risk: none.
P3 · rstest.runtime-playground.config.ts:12-17, rstest.runtime-playground.browser.config.ts · AGENTS.md: delete on sight; rstest-best-practices: install @rstest/coverage-v8, set coverage.include and thresholds · Both configs are referenced only by two docs/superpowers/plans/*.md; the first configures coverage.provider: 'v8' with thresholds, but @rstest/coverage-v8 is not installed, so no coverage runs anywhere in the repo. · Delete both files; if coverage is wanted, add @rstest/coverage-v8 to the unit leg with coverage.include: ['packages/*/src/**'] and real thresholds. · Risk: none.
P3 · .github/workflows/ci.yml:158-161, package.json:13 · rstest-best-practices: CI — --reporter=github-actions, shard long legs · pnpm test runs four legs serially inside each Node-matrix job. With projects (above) a single rstest run --reporter=github-actions gives annotations, and the integration project can shard across the matrix. · Risk: none.
4. Website (website/rspress.config.ts)
P3 · website/rspress.config.ts:122-129, website/package.json:31 · rspress-best-practices: generate API reference from what ships · TypeDoc compiles packages/agent-bundle/src with a pinned TypeScript 6.0.3 (typedoc 0.28 peers ≤ 6.0.x) while the repo is on 7.0.2 — the comment acknowledges that TS7-only syntax fails the docsite first. · Point entryPoints at the built declarations (packages/agent-bundle/dist/*.d.ts after pnpm build in docs.yml) so the reference documents exactly the published surface and the TS pin only affects doc rendering; or track typedoc's TS 7 support. · Risk: docs.yml needs the build step before docs:site:build.
P3 · plugin-api-docgen vs TypeDoc · rspress-best-practices · @rspress/plugin-api-docgen 2.0.21 generates React component prop tables (react-docgen-typescript / documentation.js); it does not cover a TypeScript API surface. Keep @rspress/plugin-typedoc + mirrorApiLocale. No change.
P3 · website/rspress.config.ts:170-191 · rspress-best-practices: llms.txt covers what agents need · Both locales' llms-full.txt exclude /api/ pages. If agents are expected to learn the public API from the site, include the generated API index or emit a third llms-api.txt. Note only.
5. Workbench (packages/workbench/rsbuild.config.ts)
P3 · packages/workbench/rsbuild.config.ts:26-31, packages/agent-bundle/src/dev/foreground-server.ts:953 · rsbuild-best-practices: hash production filenames; index.html no-cache, hashed assets immutable · filenameHash: false with fixed [name].js/[name].css, and assets are served with only content-type (no cache-control, etag or last-modified), so browsers re-download every asset on every Workbench load (correct, just wasteful on localhost). If a cache header is ever added, the unhashed names would serve stale JS across agent-bundle upgrades. · filenameHash: true for JS/CSS (keep index.html stable), serve static/** with cache-control: public, max-age=31536000, immutable and index.html with no-cache; the output.copy in packages/agent-bundle/rslib.config.ts:57-59 copies the whole directory so it needs no change. · Risk: grep for hard-coded static/js/index.js first.
P3 · packages/agent-bundle/package.json:34 · rslib-modern-package: files matches actual output · !dist/workbench/**/*.map excludes maps the production Rsbuild build never emits (0 .map files under packages/workbench/dist). · Delete the entry, or set output.sourceMap.js: 'hidden-source-map' deliberately if maps are wanted for local debugging. · Risk: none.
P3 · packages/workbench/ (no .browserslistrc / output.overrideBrowserslist) · rsbuild-best-practices: define the browser target · A desktop-only Chromium app (AGENTS.md) is built for Rsbuild's default baseline (Chrome 87, Safari 14, …). · .browserslistrc with chrome >= 120 (or overrideBrowserslist) — smaller output, fewer helpers. · Risk: none.
Rsdoctor
Worth one scoped pass, not a permanent integration: (1) packages/agent-bundle's own build, to see what the 24 entries share across the ~47 numeric chunks, confirm the typescript-5 chunk is isolated, and measure declaration time before the tsgo/API Extractor decision; (2) one generated user artifact through the compiler (tools.rsbuild → plugins: [new RsdoctorRspackPlugin({ mode: 'brief' })] via the escape hatch) to see the inlined-dependency composition — that view is what plugin authors will ask the Workbench for. Not worthwhile for MCP Apps (single inlined HTML, splitChunks: false) or the Workbench SPA (default split-by-experience already yields lib-react.js).
Already compliant (do not re-audit)
- Compiler:
bundle: true, format: 'esm', output.target: 'node', filenameHash: false, minify: false, splitChunks: false, performance.buildCache: false per lib id, pluginReact({ fastRefresh: false }) for the automatic JSX runtime, $-exact resolve.alias for reserved specifiers, reserved-externals guard, frameworkInvariantLayer forcing cleanDistPath: false, assertExecutableConfig on inspectConfig().origin, virtual generated entries served from memory, autoExternal: false + AB7014/AB7015 as the declared-vs-used gate.
- MCP Apps:
mode: 'production', legalComments: 'inline', everything inlined (inlineScripts, inlineStyles, dataUriLimit), splitChunks: false, asyncChunks: false, self-contained-view assertion.
- Package builds:
type: module, engines.node >= 22.19.0, publishConfig.provenance (+ access: public), files allowlists incl. LICENSE/NOTICE, exports with types + import per entry, pluginPublint({ throwOn: 'warning' }) in all four packages, syntax: 'es2022' explicit, cleanDistPath, tsconfigPath: './tsconfig.build.json', source.define for the version, legalComments: 'linked' → dist/*.LICENSE.txt, AGENT_BUNDLE_RSLIB_CACHE_DIRECTORY for parallel builds, sideEffects: false on @agent-bundle/runtime and rsc-markdown-stream, create-agent-bundle bundling @clack/prompts from devDependencies for zero runtime deps, typescript-5 bundled so no tsc bin ships.
- Tests:
@rstest/adapter-rslib everywhere; integration pool isolate: true, testTimeout: 30_000, maxWorkers from availableParallelism with env override and time scaling; conformance/evidence pools maxWorkers: 1; globalSetup builds prebuilt artifacts once; per-worker temp/cache isolation (rstest.worker-isolation.ts); browser tests via @rstest/browser + Playwright Chrome channel with React aliases deduped to one copy.
- Website: Rspress 2.0.21 (latest),
languageParity (exclude: ['api']), checkDeadLinks + checkAnchors + checkDeadImages, search.codeBlocks, pluginLlms per locale with mdxToMd, pluginSitemap, pluginTwoslash with paths, route.cleanUrls, editLink, llmsUI, generated hosts/events/diagnostics pages from source JSON, docs:site:build gate in docs.yml.
- Workbench:
mode pinned to the CLI command (hermetic under NODE_ENV=test), pluginReact(), default chunk split (lib-react.js), default legalComments: 'linked' + THIRD_PARTY_NOTICES copy, type checking through pnpm typecheck rather than a build-time plugin, server.proxy gated by env.
Not assessed / caveats
packages/agent-bundle/src/rslib.ts does not exist on main; the Rslib integration is src/build/rslib.ts and the public config surface is src/config/*.
- No build was run (read-only;
src/build/ is being changed on a branch). Rslib v1 items come from the upgrade guide, not a trial build. The local dist/ predates today's launch-env/mcp-tasks entries, so chunk-layout numbers are from that build; the config shape is unchanged.
rstest.rs has no published page for the Rslib adapter (/guide/basic/rslib → 404); adapter behaviour was read from @rstest/adapter-rslib@0.11.10/dist/index.js.
- Rspress MDX compiler/rehype interplay and search-index size need a docs build and were not evaluated.
Read-only audit of the build/metaframework setup on
main(cbda5abe6, after #547) against the Rstack agent skills (rslib-best-practices,rslib-modern-package,rspack-best-practices,rspack-split-chunks,rsbuild-best-practices,rstest-best-practices,rspress-best-practices,rsdoctor-analysis) and the current upstream docs (rslib.rs/guide/upgrade/v0-to-v1). No files were changed and no build was run; evidence comes from the configs, the installednode_modules, the last localdist/, and the published registry metadata.Format per finding: priority ·
file:line· skill rule · why it matters here · concrete change · risk/notes. Findings are ordered by priority inside each area; the "already compliant" list at the end is there so nobody re-audits those points.Installed vs latest at audit time:
@rslib/core0.23.2 → 1.0.0,@rsbuild/core2.2.1 → 2.2.3,@rspack/core2.1.10 (via Rslib) / 2.2.1 → 2.2.2,@rstest/*0.11.10 → 0.11.12,@rspress/core2.0.21 (latest),@rslint/core0.8.2 → 0.9.1.1. The compiler (
packages/agent-bundle/src/build/*)P1 ·
packages/agent-bundle/package.json:101,103,src/build/rslib.ts:5,src/build/mcp-apps.ts:1· rslib-modern-package: keep the consumer install lean, one copy of each toolchain package; rslib-best-practices: keep Rslib and the Rsbuild plugins in sync ·agent-bundledepends on both@rslib/core@0.23.2(→@rsbuild/core@2.1.13→@rspack/core@2.1.10) and@rsbuild/core@2.2.1(→@rspack/core@2.2.1). Every consumer therefore installs two 28 MB@rspack/binding-*native packages, and the process runs two Rspack engines: the executable compiler uses therspackre-exported by@rslib/core(2.1.10) while MCP Apps use@rsbuild/core's (2.2.1). · Bump@rslib/coreto^1.0.0(depends on@rsbuild/core ~2.2.2) and@rsbuild/coreto 2.2.3 in the same PR, then add a guard to the packed pool (already installs the tarball) asserting exactly one@rspack/binding-*directory in the consumer tree, orpnpm dedupe --checkin CI. · Risk: Rslib v1 is a breaking release; the blockers specific to this repo are the next finding and must land in the same PR.P1 · Rslib 0.23 → 1.0 migration blockers (from
rslib.rs/guide/upgrade/v0-to-v1) · rslib-best-practices: read the upgrade guide, verify withrslib inspectbefore bumpingsrc/build/entry-shell.ts:43-44,128-129—new URL('./cli-entry.js', import.meta.url)/new URL(\./${name}.js`, import.meta.url)inside agent-bundle's own ESM build. Rslib v1 processes statically analyzablenew URL()as static assets and rejects targets that exist only in the build output → build failure or a bogus asset. Rewrite withfileURLToPath+path.join(the guide's recommendation for filesystem paths) or add/* rspackIgnore: true */`.src/build/entry-shell.ts:149,275— generated entry strings emitnew URL("../", import.meta.url)andnew Worker(new URL('./<worker>.js', import.meta.url), …)into user builds compiled by the compiler's Rslib. In v1 these become an asset reference to a directory (rejected) and a Worker entry that re-bundles a file the compiler already emits as its own entry. Emit/* rspackIgnore: true */in the generated strings now (a no-op on 0.23), or incomposeEntryLibConfigsetchain.module.rule('rslib:new-url').parser({ url: false })andmodule.parser.javascript.worker: false.externalsTypedefault changes frommodule-importtomodern-module: CommonJSrequire()of externalizednode:builtins inside inlined dependencies is emitted ascreateRequire().dist/*.jsof agent-bundle is re-bundled by the compiler into user artifacts, so either enablemodule.parser.javascript.createRequirein the compiler's Rspack config or keepexternalsType: 'module-import'inpackages/agent-bundle/rslib.config.ts.src/build/rslib.ts:603—autoExternal: falseis deprecated in v1 →output: { autoExternal: false }.src/build/rslib.ts:760—rslib.inspectConfig()withoutmode; in v1modeis inferred fromNODE_ENV, and underdevelopmentit returns onlyformat: 'mf'libs, soassertExecutableConfigat:761would see zero bundler configs when a user runsagent-bundle buildfrom a dev script. Pass{ mode: 'production' }explicitly (safe today).dts: true— with TypeScript 7 at the repo root, v1 auto-selects tsgo;redirect.dts.extensiondefaults on. Comparedist/**/*.d.tsbefore/after withattw --profile esm-only.syntax: 'es2022'explicitly, so the newengines.nodeinference does not change output; see the P3 below for aligning it deliberately.P2 ·
src/build/rslib.ts:760-761,src/build/inspect-bundler.ts:51-68,src/cli.ts:1019-1039· rslib-best-practices: userslib inspect(dist/.rsbuild/rspack.config.*.mjs) to verify the final Rspack config, not the input ·agent-bundle inspect --bundlerdumps the composed Rslib/Rsbuild config with functions rendered as[function …]. The lowered Rspack config — the realexternalsafterguardReservedExternals, the$-suffixedresolve.aliasentries, the virtual-modules plugin,optimization.splitChunks,node,output.module— is computed at:760(inspection.origin.bundlerConfigs) and consumed only byassertExecutableConfig; it is never persisted, so a plugin author debugging atools.rspackescape hatch cannot see what the hatch produced. · Addinspect --bundler --lowered(or--write-config) that callsrslib.inspectConfig({ writeToDisk: true, outputPath: '<artifact>/.rsbuild', mode: 'production' })or serializesorigin.bundlerConfigs, and expose it in the Workbench build panel. · Risk: the dump contains absolute paths; label it a debugging artifact and keep it out of packs.P2 ·
packages/agent-bundle/rslib.config.ts:111-116vs the compiler that inlinesdist/*.js(src/build/rslib.ts:603,src/build/entry-shell.ts:21-64,119-137) · rspack-split-chunks: choose the chunk strategy deliberately and verify it in the output; rslib-modern-package: validate the artifact, not the config · The 24-entry bundle-mode build emits ~47 numeric shared chunks (dist/1178.js,dist/5610.js, …); runtime-facing entries the compiler inlines into user artifacts are thin re-exports (dist/mcp-server-runtime.jsis 180 bytes →./5610.js). The comment at:111-116documents that a shared chunk carrying Rslib's__webpack_require__runtime shadows the artifact bundler's runtime, and the only guard is the manualmcp-tasksentry split — any future module shared betweenmcp-server-runtimeand a sibling re-introduces the bug silently. · Build the inlined runtime entries (mcp-server-runtime,mcp-entry,cli-entry,install-entry,launch-env,terminal-capability,meta,routes,event-ipc,event-project) as a secondlibwithsplitChunks: falseso each is self-contained, and add acheck:releaseassertion that the transitive chunk closure of those entries contains no__webpack_require__/__webpack_modules__. · Risk: some duplicated code between the two libs' outputs; acceptable for a devDependency. (The last localdist/predateslaunch-env/mcp-tasks, so re-check the chunk closure afterpnpm build.)P3 ·
src/build/rslib.ts:628-630· rsbuild-best-practices:legalComments— keep third-party licence text when bundling; enable source maps for Node output ·legalComments: 'none'is a no-op here: Rsbuild applieslegalCommentsonly through the SWC minimizer (getSwcMinimizerOptions), andminify: falsedisables it, so inlined dependencies' licence headers survive by accident. If minification is ever enabled, every user artifact silently drops licences. · SetlegalComments: 'inline'so the intent is explicit; keepminify: false. Separately,sourceMap: falsemakes stack traces inside inlined dependencies opaque — consider an opt-in--source-mapflag (output.sourceMap: { js: 'source-map' },.mapexcluded from packs viafiles, run withnode --enable-source-maps). · Risk: none.P3 ·
src/build/rslib.ts:623· rslib-best-practices: alignlib.syntaxwith the runtime floor inengines.node· The compiler hard-codessyntax: 'es2022'although the framework requires Node ≥ 22.19 (packages/agent-bundle/package.jsonengines) and generated artifacts only ever run there. ·syntax: ['node >= 22.19']now; after v1, omit it for user builds and let Rslib infer from the user package'sengines.node(falls back toesnext). · Risk: ES2023+ syntax stays untranspiled, which is correct for the target.P3 ·
src/build/mcp-apps.ts:198-210· rsbuild-best-practices: set the browserslist for web targets explicitly · The MCP Apps web build has nooutput.overrideBrowserslist, so Rsbuild's default baseline (Chrome 87, Safari 14, …) lowers syntax and CSS for host webviews that are all recent Chromium. ·output.overrideBrowserslist: ['chrome >= 120'](or a documented constant besidedataUriLimit). · Risk: none; inlined HTML apps get slightly smaller.2. Workspace package builds
P1 ·
packages/rsc-runtime/package.json:83,packages/rsc-runtime/src/lower-mcp.ts:3,packages/rsc-runtime/src/project-mcp.ts:1· rslib-modern-package:dependencieshold only what shipped code and shipped declarations need ·@modelcontextprotocol/sdk@1.30.0(express 5, hono, jose, cors, ajv, zod-to-json-schema, eventsource, …) is installed by every@agent-bundle/runtimeconsumer for twoimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'lines. Because the emitteddist/lower-mcp.d.tsanddist/project-mcp.d.tsreference it, it must stay a runtime dependency as long as the import exists — which is exactly why AB7014 accepts it and a human has to decide. ·import type { CallToolResult } from '@modelcontextprotocol/server'(already a dependency; exported at@modelcontextprotocol/server@2.0.0/dist/index.d.mts:738), then delete the 1.x dependency. · Risk: structural differences between the 1.x and 2.xCallToolResulttypes;pnpm typecheckand the runtime unit tests cover it.patchchangeset, docs unaffected.P2 ·
packages/rsc-runtime/rslib.config.ts:24-99· rslib-best-practices:output.externalsis for third-party packages; share internal modules through one multi-entry lib (shared chunks) or bundleless output withredirect· Six separate bundle-mode libs are stitched with string-keyed externals ('../state/index.js': './state.js','./index.js': '../notices.js', …) so the kernel is bundled once; the comment at:88-91explains that a duplicated module graph forks class identity and breaksinstanceof AgentStateError. String externals match the literal request: an import from one directory deeper (../../state/index.js), a new file in a nested folder, or a re-export through another path silently re-bundles the kernel, and no test asserts identity across entries. · (a) Onelibwith all nine entries — Rslib extracts shared modules into common chunks, so there is exactly one module instance while each entry's graph stays lean (node:sqlitestill loads only viastate/sqlite); or (b)bundle: falsewithredirect.js(v1 turns onredirect.dts.extension). Either way add a packed test thatAgentStateErrorfrom@agent-bundle/runtime,/state,/state/sqlite,/mountand/lineageis the same class. · Risk: (a) changes the dist layout to numeric shared chunks;exports(package.json) andsideEffects: false(:24) are unaffected.P2 ·
packages/agent-bundle/rslib.config.ts:50+ the tarball · rslib-modern-package: shipped declarations must not reference devDependencies; validate with attw/publint ·dts: truein bundle mode emits one.d.tsper source file (≈0.97 MB of.d.tsin the pack, e.g.dist/events/ipc.d.ts,dist/routes/input-schema.d.ts) including internals that reference devDependencies (zod,typescript-5). Nothing underexportsreaches them today, so this is latent, but the next re-export can turn it into a consumer type error underskipLibCheck: false. · Eitherdts: { bundle: true }per exported entry (API Extractor) so only the public surface ships, or keep per-file output and addattw --profile esm-onlyplus a check that no packed.d.tsimports a devDependency tocheck:release(package.json:52). · Risk: API Extractor adds a devDependency and build time; tsgo (automatic on Rslib v1 with TS 7) offsets it.P3 ·
packages/agent-bundle/package.json:100,122· rslib-modern-package: package.json is the authority ·@modelcontextprotocol/serveris declared in bothdependenciesanddevDependencies. · Delete thedevDependenciesentry. · Risk: none.P3 ·
packages/agent-bundle/package.json:132-134,packages/rsc-runtime/package.json:77-80· rslib-modern-package: peers express the real compatibility contract — no*, no accidental exact pins, optional when only some entries need them · (i)"@agent-bundle/runtime": "*"while generated code imports@agent-bundle/runtime/{mount,notices,notices/inbox-route,state,state/sqlite,flight/server}(src/build/entry-shell.ts:31,211-213,571,808-809): a runtime older than those subpaths breaks at the consumer's runtime, not at install. Use">=<first version with those subpaths> <1"and bump it in the changeset that adds a subpath;pnpm-workspace.yaml:13-15keeps local linking. (ii)react: 19.2.8exact peers (documented as deliberate inpackages/rsc-runtime/README.md:70) are tighter thanreact-server-dom-rspack@0.1.0's own^19.1.0; consider~19.2.8or say why the patch pin is required. (iii)@rspack/coreis a required peer of@agent-bundle/runtimealthough no source file imports it (onlyreact-server-dom-rspack's build side needs it) — mark it optional inpeerDependenciesMeta. · Risk: (i) is apatchchangeset; (ii)/(iii) loosen installs only.P3 ·
packages/rsc-runtime/package.json:88,pnpm-workspace.yaml:15· rslib-modern-package: workspace deps use the workspace protocol ·"rsc-markdown-stream": "^0.1.0"is linked locally only because of theoverridesentry. ·workspace:^— pnpm rewrites it to^0.1.0on publish, and the override becomes unnecessary (same for@agent-bundle/runtimeif any package lists it by range). · Risk: none.P3 ·
packages/rsc-markdown-stream/rslib.config.ts:11,21· rslib-modern-package: declarations are generated from the source that ships ·dts: falsewith a hand-copiedsrc/index.d.ts(vendored in #344) can drift fromdist/index.jswith no compiler check. ·dts: trueif the source is TypeScript; otherwise add a typecheck-only test that consumesdist/index.jsthrough the hand-written declarations (attwdoes not catch semantic drift). · Risk: none.P3 · all four
package.jsonfiles · rslib-modern-package: explicitexports, expose./package.json· No package exports./package.json, andcreate-agent-bundle/package.jsonhas noexportsat all (acceptable for abin-only package, but it leavesdist/**importable). · Add"./package.json": "./package.json"everywhere andexports: { "./package.json": "./package.json" }tocreate-agent-bundleto close the surface. · Risk: none (publint already gates the rest).P3 ·
packages/agent-bundle/rslib.config.ts:22-32,79-88· rslib-best-practices: preferlib.shims.esmover custom__filename/__dirnamehandling · A customprocessAssetsplugin prepends an ESM shim to chunks that mention__filename/__dirname(the bundled TypeScript 5 parser), andtools.rspackdisables Rspack's Node polyfills. Rslib'sshims: { esm: { __filename: true, __dirname: true } }exists for exactly this. · Ifshims.esmwas tried and rejected for #381, say so in the comment; otherwise replace the plugin with the option. · Risk: the built-in shim rewrites per module rather than per chunk — verify with the packed pool's TypeScript-parser tests.3. Tests (
rstest.*.ts)P2 ·
rstest.integration-tests.ts(108 literal test paths),rstest.unit.config.ts:19-33,package.json:13· rstest-best-practices: useprojectswith directory-basedinclude; keep the config declarative · Pools are defined by subtraction — the unit pool ispackages/**/tests/**/*.test.tsminus eight hand-maintained exclusion lists — and nothing checks that a listed path exists. A renamed or moved integration test silently drops into the non-isolated, parallel unit pool, and a deleted one leaves a stale entry. · Move suites intotests/unit,tests/integration,tests/projection,tests/route-unit,tests/packed, … (or a.int.test.tssuffix) and replace the four per-leg configs with onerstest.config.tsusingprojects/defineProject, sopnpm testbecomesrstest runand CI can--projector shard. Interim guard: a unit test asserting every listed path exists. · Risk: mechanical moves touch many imports; do it per pool.P2 ·
rstest.rslib.ts:8-17· rstest-best-practices: reuse the build config only when it is compatible; explicitly drop publish-time plugins ·withRslibConfigcopiesplugins,tools,source,resolveandperformance.buildCachefrompackages/agent-bundle/rslib.config.tsinto every test build (adapter source:plugins: finalLibConfig.plugins,tools: {rspack, swc, bundlerChain}). SopluginPublint({ throwOn: 'warning' }), theagent-bundle:esm-node-globalsasset rewrite,tools.rspack'signoreWarnings/node.__dirname=false, andsource.define.__AGENT_BUNDLE_VERSION__run in the unit, integration, packed and evidence pools. · InmodifyLibConfigfilterpluginsto what tests need (plugins.filter(p => p.name !== 'rsbuild:publint' && p.name !== 'agent-bundle:esm-node-globals')), drop the publish-onlytools.rspackhook, and comment what is intentionally kept (define,tsconfigPath). · Risk: low; confirm withDEBUG=rstestwhether publint'sonAfterBuildfires against the workspace root manifest (root: workspaceRoot) insidedist/.rstest-temp.P2 ·
rstest.unit.config.ts:37(isolate: false) +packages/agent-bundle/tests/inspect-state.test.ts:44· rstest-best-practices: restore mocks, env and globals between tests; users.stubGlobalandunstubGlobals· The test mutatesglobalThis.__AGENT_BUNDLE_VERSION__for the whole shared worker with no restore, and no config setsrestoreMocks/clearMocks/unstubEnvs/unstubGlobals. The adapter already appliessource.defineso the identifier atsrc/cli.ts:726is replaced at compile time — the stub is likely dead and, in a non-isolated pool, order-dependent. · Remove thedefineProperty(or users.stubGlobalwithunstubGlobals: true), and setrestoreMocks: true, clearMocks: true, unstubEnvs: true, unstubGlobals: truein the shared config for all pools. · Risk: reveals other order-dependent tests — that is the point.P3 ·
packages/agent-bundle/tests/mcp-session-service.test.ts:272,1137,1150· rstest-best-practices: wait on observable state, not fixed sleeps · Three fixed sleeps (25 ms, 10 ms, 10 ms) between issuing a request and cancelling/observing it, in a suite that runs on the parallel integration pool (rstest.integration.config.ts:31,61);poolTimeScalescales timeouts but not these sleeps, which is the classic contention flake. · Wait on a signal from the fixture server (request acknowledged) orexpect.poll/ a bounded retry loop instead of the sleep. · Risk: none.P3 ·
rstest.runtime-playground.config.ts:12-17,rstest.runtime-playground.browser.config.ts· AGENTS.md: delete on sight; rstest-best-practices: install@rstest/coverage-v8, setcoverage.includeand thresholds · Both configs are referenced only by twodocs/superpowers/plans/*.md; the first configurescoverage.provider: 'v8'with thresholds, but@rstest/coverage-v8is not installed, so no coverage runs anywhere in the repo. · Delete both files; if coverage is wanted, add@rstest/coverage-v8to the unit leg withcoverage.include: ['packages/*/src/**']and real thresholds. · Risk: none.P3 ·
.github/workflows/ci.yml:158-161,package.json:13· rstest-best-practices: CI —--reporter=github-actions, shard long legs ·pnpm testruns four legs serially inside each Node-matrix job. Withprojects(above) a singlerstest run --reporter=github-actionsgives annotations, and the integration project can shard across the matrix. · Risk: none.4. Website (
website/rspress.config.ts)P3 ·
website/rspress.config.ts:122-129,website/package.json:31· rspress-best-practices: generate API reference from what ships · TypeDoc compilespackages/agent-bundle/srcwith a pinned TypeScript 6.0.3 (typedoc 0.28 peers≤ 6.0.x) while the repo is on 7.0.2 — the comment acknowledges that TS7-only syntax fails the docsite first. · PointentryPointsat the built declarations (packages/agent-bundle/dist/*.d.tsafterpnpm buildindocs.yml) so the reference documents exactly the published surface and the TS pin only affects doc rendering; or track typedoc's TS 7 support. · Risk:docs.ymlneeds the build step beforedocs:site:build.P3 ·
plugin-api-docgenvs TypeDoc · rspress-best-practices ·@rspress/plugin-api-docgen2.0.21 generates React component prop tables (react-docgen-typescript / documentation.js); it does not cover a TypeScript API surface. Keep@rspress/plugin-typedoc+mirrorApiLocale. No change.P3 ·
website/rspress.config.ts:170-191· rspress-best-practices:llms.txtcovers what agents need · Both locales'llms-full.txtexclude/api/pages. If agents are expected to learn the public API from the site, include the generated API index or emit a thirdllms-api.txt. Note only.5. Workbench (
packages/workbench/rsbuild.config.ts)P3 ·
packages/workbench/rsbuild.config.ts:26-31,packages/agent-bundle/src/dev/foreground-server.ts:953· rsbuild-best-practices: hash production filenames;index.htmlno-cache, hashed assets immutable ·filenameHash: falsewith fixed[name].js/[name].css, and assets are served with onlycontent-type(nocache-control,etagorlast-modified), so browsers re-download every asset on every Workbench load (correct, just wasteful on localhost). If a cache header is ever added, the unhashed names would serve stale JS acrossagent-bundleupgrades. ·filenameHash: truefor JS/CSS (keepindex.htmlstable), servestatic/**withcache-control: public, max-age=31536000, immutableandindex.htmlwithno-cache; theoutput.copyinpackages/agent-bundle/rslib.config.ts:57-59copies the whole directory so it needs no change. · Risk: grep for hard-codedstatic/js/index.jsfirst.P3 ·
packages/agent-bundle/package.json:34· rslib-modern-package:filesmatches actual output ·!dist/workbench/**/*.mapexcludes maps the production Rsbuild build never emits (0.mapfiles underpackages/workbench/dist). · Delete the entry, or setoutput.sourceMap.js: 'hidden-source-map'deliberately if maps are wanted for local debugging. · Risk: none.P3 ·
packages/workbench/(no.browserslistrc/output.overrideBrowserslist) · rsbuild-best-practices: define the browser target · A desktop-only Chromium app (AGENTS.md) is built for Rsbuild's default baseline (Chrome 87, Safari 14, …). ·.browserslistrcwithchrome >= 120(oroverrideBrowserslist) — smaller output, fewer helpers. · Risk: none.Rsdoctor
Worth one scoped pass, not a permanent integration: (1)
packages/agent-bundle's own build, to see what the 24 entries share across the ~47 numeric chunks, confirm thetypescript-5chunk is isolated, and measure declaration time before the tsgo/API Extractor decision; (2) one generated user artifact through the compiler (tools.rsbuild→plugins: [new RsdoctorRspackPlugin({ mode: 'brief' })]via the escape hatch) to see the inlined-dependency composition — that view is what plugin authors will ask the Workbench for. Not worthwhile for MCP Apps (single inlined HTML,splitChunks: false) or the Workbench SPA (defaultsplit-by-experiencealready yieldslib-react.js).Already compliant (do not re-audit)
bundle: true,format: 'esm',output.target: 'node',filenameHash: false,minify: false,splitChunks: false,performance.buildCache: falseper lib id,pluginReact({ fastRefresh: false })for the automatic JSX runtime,$-exactresolve.aliasfor reserved specifiers, reserved-externals guard,frameworkInvariantLayerforcingcleanDistPath: false,assertExecutableConfigoninspectConfig().origin, virtual generated entries served from memory,autoExternal: false+ AB7014/AB7015 as the declared-vs-used gate.mode: 'production',legalComments: 'inline', everything inlined (inlineScripts,inlineStyles,dataUriLimit),splitChunks: false,asyncChunks: false, self-contained-view assertion.type: module,engines.node >= 22.19.0,publishConfig.provenance(+access: public),filesallowlists incl.LICENSE/NOTICE,exportswithtypes+importper entry,pluginPublint({ throwOn: 'warning' })in all four packages,syntax: 'es2022'explicit,cleanDistPath,tsconfigPath: './tsconfig.build.json',source.definefor the version,legalComments: 'linked'→dist/*.LICENSE.txt,AGENT_BUNDLE_RSLIB_CACHE_DIRECTORYfor parallel builds,sideEffects: falseon@agent-bundle/runtimeandrsc-markdown-stream,create-agent-bundlebundling@clack/promptsfrom devDependencies for zero runtime deps,typescript-5bundled so notscbin ships.@rstest/adapter-rslibeverywhere; integration poolisolate: true,testTimeout: 30_000,maxWorkersfromavailableParallelismwith env override and time scaling; conformance/evidence poolsmaxWorkers: 1;globalSetupbuilds prebuilt artifacts once; per-worker temp/cache isolation (rstest.worker-isolation.ts); browser tests via@rstest/browser+ Playwright Chrome channel with React aliases deduped to one copy.languageParity(exclude: ['api']),checkDeadLinks+checkAnchors+checkDeadImages,search.codeBlocks,pluginLlmsper locale withmdxToMd,pluginSitemap,pluginTwoslashwithpaths,route.cleanUrls,editLink,llmsUI, generated hosts/events/diagnostics pages from source JSON,docs:site:buildgate indocs.yml.modepinned to the CLI command (hermetic underNODE_ENV=test),pluginReact(), default chunk split (lib-react.js), defaultlegalComments: 'linked'+THIRD_PARTY_NOTICEScopy, type checking throughpnpm typecheckrather than a build-time plugin,server.proxygated by env.Not assessed / caveats
packages/agent-bundle/src/rslib.tsdoes not exist onmain; the Rslib integration issrc/build/rslib.tsand the public config surface issrc/config/*.src/build/is being changed on a branch). Rslib v1 items come from the upgrade guide, not a trial build. The localdist/predates today'slaunch-env/mcp-tasksentries, so chunk-layout numbers are from that build; the config shape is unchanged.rstest.rshas no published page for the Rslib adapter (/guide/basic/rslib→ 404); adapter behaviour was read from@rstest/adapter-rslib@0.11.10/dist/index.js.