Skip to content

feat(build): MCP App views judged from compile evidence (#619 step 5) - #627

Merged
ScriptedAlchemy merged 5 commits into
mainfrom
feat/619-mcp-app-evidence
Sep 5, 2026
Merged

feat(build): MCP App views judged from compile evidence (#619 step 5)#627
ScriptedAlchemy merged 5 commits into
mainfrom
feat/619-mcp-app-evidence

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 5, 2026

Copy link
Copy Markdown
Owner

The MCP App slice of #619 step 5, split out because the manifest half of steps 4–5 (compile provenance rows, definePrebuilt) waits on #604 and this piece does not. Raised as a Codex P2 on #623: compileMcpApps is a separate Rsbuild compiler, so a function-form or mutator externals in a view build escaped both AB4725 and the evidence path.

What changes

  • src/build/mcp-apps.ts: composeMcpAppsRsbuildConfig composes ArtifactDependencyAuditPlugin in its framework invariant layer (after the consumer's tools hatch, beside the meta-module and app-runtime replacements), always — so inspect --bundler shows what runs — with an optional onCompilationEvidence recorder. compileMcpApps collects one CompilationEvidence per view (each App is its own Rsbuild environment, so compilation.compiler.name is the App name) and assertViewsSelfContained fails the build with AB6005 for every external any view kept. A browser document has no allowable external: no Node built-ins, no sibling module.
  • src/build/external-policy.ts: viewSelfContainmentDiagnostics — the view form of AB6005: Compiled MCP App view "mcp-apps/<name>.html" keeps "<request>" external (<type>)[, imported as "<specifier>",] from <issuer>; a view inlines every module it loads.
  • src/build/dependency-audit-plugin.ts: module classes come from compilation.compiler.rspack instead of the @rslib/core import, so the instanceof checks hold whichever Rspack instance (Rslib's or Rsbuild's) created the compilation.
  • src/core/paths.ts: posixRelativeWhenInside (project-relative issuer names) replaces rslib.ts's private projectIssuer; both compilers use it.
  • Docs: docs/diagnostics.md (AB60xx summary row, AB6005 row, AB7014 preamble), website/docs/{en,zh}/guide/distribution/validation.mdx. One minor changeset.

assertSelfContainedViews (emitted-file inventory, external script/link URLs in the HTML) stays: it judges the document, not the module graph.

Tests

tests/mcp-apps-compile.test.ts:

  • "fails a view with AB6005 when a tools.rspack mutator keeps a dependency external" — config.externals = { 'react-dom/client': 'ReactDOMClient' } (Rsbuild web target, default externalsType: 'var') → exactly one AB6005 on mcp-apps/status.html, message names ReactDOMClient, react-dom/client, views/status.ts.
  • "records no external for a self-contained view" — composes the config with a recorder, builds through createRsbuild, asserts one record named status with externals: [] and views/StatusPanel.tsx among its modules.
    Existing 17 compileMcpApps tests unchanged and green (fallback path, templates, favicon, source maps, size advisories).

Verification

Run on the merged tree (origin/main merged before each gate):

  • pnpm build && pnpm typecheck && pnpm lint && pnpm test:unit — pass.
  • pnpm docs:site:build — pass (dead-link, anchor, image, language-parity checks).
  • pnpm test:integration:run — pass.

Deslop: cursor-grok-4.6-high-fast, 5 edits (two JSDoc blocks cut to one "why" sentence each, one restating sentence dropped, records[0]! → typed [record] guard, one test assertion that could pass vacuously tightened).

Self-review

gpt-5.6-sol-medium on the deslopped diff:

  1. Should-fix — the plugin's instanceof rspack.ExternalModule / NormalModule used the @rslib/core Rspack instance, while MCP Apps compile through @rsbuild/core; a second Rspack instance would make both checks reject every module and let externals through silently (pins currently dedupe, so the test passed). Fixed: classes read from compilation.compiler.rspack.
  2. Nit — the AB60xx summary row in docs/diagnostics.md still limited AB6005 to host-pack/package-build entries. Fixed.

Checked and found fine by the reviewer: the development-mode fallback (the production recompile is a fresh compileMcpApps call with its own evidence array); a thrown rsbuild.build() (compileFailure rethrows before assertViewsSelfContained); afterOptimizeModules firing per environment and compiler.name being the environment name; renderConfigValue on the plugin instance in inspect --bundler; readable mode leaving externals unchanged; export reachability and helper de-duplication; the var default behind the message; en/zh parity; the changeset.

Pass 2 — claude-fable-5-1-thinking-high on the fixed diff: no blocker.

  1. Should-fix — the view-form sentence had been spliced into the middle of the AB6005 row's primary-form description in docs/diagnostics.md, attaching the Node-built-in rationale to views. Fixed: moved after the expression-request sentence; notes the , imported as clause applies to both forms.
  2. Nit — the assertViewsSelfContained comment credited the invariant layer with naming the compiler; Rsbuild does, and nothing pinned bundler.name, so a hatch setting config.name would surface as the opaque "found 0 records" error. Fixed: comment reworded; assertResolvedViewConfig now requires the resolved bundler names to be exactly the App names (the existing "invalid self-contained MCP App configuration" path).
  3. Nit — the keeps … external (…)[, imported as …,][ from …]; fragment was written twice in external-policy.ts. Fixed: keptExternalClause shared by both message forms.
  4. Nit — a 176-column line in the AB7014 preamble. Fixed: rewrapped.

Verified by the reviewer and unchanged: compilation.compiler.rspack is typed and populated from the creating module for Rsbuild, Rslib, and child compilers (which thisCompilation never records anyway); neither new test can pass vacuously (compileFailure rethrows non-DiagnosticErrors; toEqual pins type, imported as, issuer, generatedPath, recovery); docs and changeset consistent with viewSelfContainmentDiagnostics; minor is right (a hatch-externalized view that passed now fails).

@changeset-bot

changeset-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5e07ff0

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 Minor

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

@pkg-pr-new

pkg-pr-new Bot commented Sep 5, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle@627
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/create-agent-bundle@627
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/rsc-markdown-stream@627
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@627

commit: 5e07ff0

@ScriptedAlchemy
ScriptedAlchemy marked this pull request as ready for review September 5, 2026 11:12
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

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