[PR #2856] [CLOSED] fix(browser): retain optional WebMCP declaration sites #5444

Closed
opened 2026-10-31 01:06:40 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2856
Author: @zhangguiping-xydt
Created: 10/13/2026
Status: ❌ Closed

Base: main ← Head: fix/browser-optional-webmcp-declarations


📝 Commits (5)

  • 92d6714 fix(browser): retain optional WebMCP declaration sites
  • e03cef6 chore(browser): merge main and preserve bundle regression cases
  • ea15199 test(ci): restore complete reconstruction fixture coverage
  • 9404953 chore(ci): merge main repairs for PR 2856
  • b74b689 Merge branch 'main' into fix/browser-optional-webmcp-declarations

📊 Changes

2 files changed (+29 additions, -4 deletions)

View changed files

📝 src/domain/webBundleAnalyzer.test.ts (+26 -0)
📝 src/domain/webBundleAnalyzerInspection.ts (+3 -4)

📄 Description

Summary

Fixes #2626. Include statically declared WebMCP tools written with optional chaining in captured bundle analysis.

Problem and expected behavior

What Problem This Solves

document.modelContext?.registerTool(...) and document.modelContext.registerTool?.(...) silently disappear from the declaration inventory, although the parser accepts both and reports complete analysis. Plain calls are retained. Optional calls should retain their literal declarations, without asserting that the calls ran or registered a tool.

User Impact

The CLI and MCP bundle analyzer can report progressively enhanced page declarations that guard access to WebMCP.

Change and scope

Why This Change Was Made

The shared call inspector already accepts optional calls, but the declaration collector's extra node-kind guard excludes them. Remove the redundant guard and allow OptionalCallExpression in the existing collector. Dynamic computed callees stay unrecognized; literal computed property names remain supported.

Contract and boundary impact

  • Owner: static declaration extraction in webBundleAnalyzerInspection.ts.
  • Scope decision: not applicable; routine fix within existing passive analysis.
  • CLI/MCP/catalog: no schema, tool, or metadata changes.
  • Evidence: same source locations and page-declared-untrusted classification; no runtime-registration claim.
  • Provider, authority, cleanup: no added provider behavior, target execution, mutation, or network destination. Verification uses an owned localhost page and temporary Chrome profile.
  • Package, installation, migration: none.

Expected effects: read captured scripts and attach to the selected loopback CDP endpoint. REA does not execute the declarations.

Evidence and regression coverage

Evidence

Real Linux x64 / Chrome 138.0.7204.157, Node 24.18.0 / npm 11.16.0. Serve /app.js containing:

function declarations() {
  document.modelContext?.registerTool({name:'optional-object'});
  document.modelContext.registerTool?.({name:'optional-call'});
  document.modelContext.registerTool({name:'plain'});
  document.modelContext[registerTool]({name:'dynamic'});
  window.fetch?.('/optional-fetch');
}

Load it with <script src="/app.js"></script> in Chrome and run node scripts/rea.mjs analyze-web-bundle <loopback-cdp-endpoint> <target-id> --observation-ms 0 --format json. The real stdio MCP client calls analyze_web_bundle with the same endpoint, target, page origin, include_script_sources: true, and observation_ms: 0.

Result in both public adapters Before cbe769b Final e03cef6
Declaration names plain optional-object, optional-call, plain
Dynamic computed declaration absent absent
Optional fetch endpoint /optional-fetch /optional-fetch

The producer is unchanged between the live-before revision and original branch base 6e25cc3. The regression fails on the unmodified base (1 failed / 23 passed) and passes after the fix. It additionally exercises optional literal-computed registration and verifies retained source locations and untrusted classification. The real page never invokes the declaration function; this proves source inventory, not live registration.

Validation performed

Current revision 9404953b9eb9bc311227fced4afdc16e43db528f (Linux, pinned Node.js 24.18.0/npm 11.16.0):

  • npm run check — passed, including repository-wide formatting, typecheck, lint/module boundaries, knip, metadata and architecture guards.
  • Build and focused regression suites — Tests 27 passed (27). The compiled runtime was used for the live proof below.
  • Exact-revision live proof — Real Chrome, built CLI and stdio MCP: both optional-chain declarations and the plain declaration are retained, along with /optional-fetch; both adapters return identical selected analysis facts.

The earlier shared CI failures were repaired by integrating main through f1045001f, including #2895 (static checks) and #2910 (portable DEX regex and isolated Linux process inventory). The remaining complete-facet reconstruction fixture correction is reused from #2853; the pinned formatter was applied to the process inventory code introduced by #2910. No assertions or CI gates were removed, and process-observation permission behavior remains unchanged.

Before these repairs, the three affected suites failed 7 tests on unmodified main 1b6c899b0. The shared repairs passed 120 tests across reconstruction, function comparison, advertised schema patterns and the live Linux process fixture. Each PR's own workflow was then checked separately on its final revision above. The locked duplicate scanner was also run directly using its same-version jscpd-linux-x64-musl 5.0.12 binary because the GNU binary requires newer glibc: all five revisions are below 2.94% duplicated lines, within the unchanged 3.5% threshold. npm run scan:todos also passed. Remote CI continues to use its normal GNU binary.

Remote CI for this revision is being checked separately; passing local verification is not a claim that queued GitHub checks have passed.

Compatibility, safety, and release

No public contract, dependency, or release changes. What was not tested: other operating systems/browser versions, live WebMCP registration/invocation, the published package, and the complete real-browser verifier. No private application data or credentials used.

Before merge

  • Concrete issue, focused title, and resolved scope.
  • Failing regression, passing focused suite, and real CLI/MCP evidence.
  • Unknowns and untrusted declarations retain their meaning.
  • No generated contract or documentation change required.
  • Final diff reviewed for unrelated changes, secrets, and unsupported claims.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/2856 **Author:** [@zhangguiping-xydt](https://github.com/zhangguiping-xydt) **Created:** 10/13/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/browser-optional-webmcp-declarations` --- ### 📝 Commits (5) - [`92d6714`](https://github.com/morluto/rea/commit/92d6714fdb14244c0e361e5118dba479224cf5e2) fix(browser): retain optional WebMCP declaration sites - [`e03cef6`](https://github.com/morluto/rea/commit/e03cef6f3202ff15edc3e218cc414773cdd42002) chore(browser): merge main and preserve bundle regression cases - [`ea15199`](https://github.com/morluto/rea/commit/ea15199facca3dbac88779ab81c9aee7243044c8) test(ci): restore complete reconstruction fixture coverage - [`9404953`](https://github.com/morluto/rea/commit/9404953b9eb9bc311227fced4afdc16e43db528f) chore(ci): merge main repairs for PR 2856 - [`b74b689`](https://github.com/morluto/rea/commit/b74b689629356f3ce2979f57fc23e7efbc5f651d) Merge branch 'main' into fix/browser-optional-webmcp-declarations ### 📊 Changes **2 files changed** (+29 additions, -4 deletions) <details> <summary>View changed files</summary> 📝 `src/domain/webBundleAnalyzer.test.ts` (+26 -0) 📝 `src/domain/webBundleAnalyzerInspection.ts` (+3 -4) </details> ### 📄 Description ## Summary Fixes #2626. Include statically declared WebMCP tools written with optional chaining in captured bundle analysis. ## Problem and expected behavior ### What Problem This Solves `document.modelContext?.registerTool(...)` and `document.modelContext.registerTool?.(...)` silently disappear from the declaration inventory, although the parser accepts both and reports complete analysis. Plain calls are retained. Optional calls should retain their literal declarations, without asserting that the calls ran or registered a tool. ### User Impact The CLI and MCP bundle analyzer can report progressively enhanced page declarations that guard access to WebMCP. ## Change and scope ### Why This Change Was Made The shared call inspector already accepts optional calls, but the declaration collector's extra node-kind guard excludes them. Remove the redundant guard and allow `OptionalCallExpression` in the existing collector. Dynamic computed callees stay unrecognized; literal computed property names remain supported. ## Contract and boundary impact - Owner: static declaration extraction in `webBundleAnalyzerInspection.ts`. - Scope decision: not applicable; routine fix within existing passive analysis. - CLI/MCP/catalog: no schema, tool, or metadata changes. - Evidence: same source locations and `page-declared-untrusted` classification; no runtime-registration claim. - Provider, authority, cleanup: no added provider behavior, target execution, mutation, or network destination. Verification uses an owned localhost page and temporary Chrome profile. - Package, installation, migration: none. Expected effects: read captured scripts and attach to the selected loopback CDP endpoint. REA does not execute the declarations. ## Evidence and regression coverage ### Evidence Real Linux x64 / Chrome 138.0.7204.157, Node 24.18.0 / npm 11.16.0. Serve `/app.js` containing: ```js function declarations() { document.modelContext?.registerTool({name:'optional-object'}); document.modelContext.registerTool?.({name:'optional-call'}); document.modelContext.registerTool({name:'plain'}); document.modelContext[registerTool]({name:'dynamic'}); window.fetch?.('/optional-fetch'); } ``` Load it with `<script src="/app.js"></script>` in Chrome and run `node scripts/rea.mjs analyze-web-bundle <loopback-cdp-endpoint> <target-id> --observation-ms 0 --format json`. The real stdio MCP client calls `analyze_web_bundle` with the same endpoint, target, page origin, `include_script_sources: true`, and `observation_ms: 0`. | Result in both public adapters | Before `cbe769b` | Final `e03cef6` | | --- | --- | --- | | Declaration names | `plain` | `optional-object`, `optional-call`, `plain` | | Dynamic computed declaration | absent | absent | | Optional fetch endpoint | `/optional-fetch` | `/optional-fetch` | The producer is unchanged between the live-before revision and original branch base `6e25cc3`. The regression fails on the unmodified base (1 failed / 23 passed) and passes after the fix. It additionally exercises optional literal-computed registration and verifies retained source locations and untrusted classification. The real page never invokes the declaration function; this proves source inventory, not live registration. ## Validation performed Current revision `9404953b9eb9bc311227fced4afdc16e43db528f` (Linux, pinned Node.js 24.18.0/npm 11.16.0): - `npm run check` — **passed**, including repository-wide formatting, typecheck, lint/module boundaries, knip, metadata and architecture guards. - Build and focused regression suites — **Tests 27 passed (27)**. The compiled runtime was used for the live proof below. - Exact-revision live proof — Real Chrome, built CLI and stdio MCP: both optional-chain declarations and the plain declaration are retained, along with /optional-fetch; both adapters return identical selected analysis facts. The earlier shared CI failures were repaired by integrating main through `f1045001f`, including [#2895](https://github.com/morluto/rea/pull/2895) (static checks) and [#2910](https://github.com/morluto/rea/pull/2910) (portable DEX regex and isolated Linux process inventory). The remaining complete-facet reconstruction fixture correction is reused from [#2853](https://github.com/morluto/rea/pull/2853); the pinned formatter was applied to the process inventory code introduced by #2910. No assertions or CI gates were removed, and process-observation permission behavior remains unchanged. Before these repairs, the three affected suites failed **7 tests** on unmodified main `1b6c899b0`. The shared repairs passed **120 tests** across reconstruction, function comparison, advertised schema patterns and the live Linux process fixture. Each PR's own workflow was then checked separately on its final revision above. The locked duplicate scanner was also run directly using its same-version `jscpd-linux-x64-musl` 5.0.12 binary because the GNU binary requires newer glibc: all five revisions are below 2.94% duplicated lines, within the unchanged 3.5% threshold. `npm run scan:todos` also passed. Remote CI continues to use its normal GNU binary. Remote CI for this revision is being checked separately; passing local verification is not a claim that queued GitHub checks have passed. ## Compatibility, safety, and release No public contract, dependency, or release changes. **What was not tested:** other operating systems/browser versions, live WebMCP registration/invocation, the published package, and the complete real-browser verifier. No private application data or credentials used. ## Before merge - [x] Concrete issue, focused title, and resolved scope. - [x] Failing regression, passing focused suite, and real CLI/MCP evidence. - [x] Unknowns and untrusted declarations retain their meaning. - [x] No generated contract or documentation change required. - [x] Final diff reviewed for unrelated changes, secrets, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:06:40 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#5444
No description provided.