[GH-ISSUE #2626] fix(browser): retain optional WebMCP declaration sites #940

Closed
opened 2026-10-15 18:29:45 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @coygeek on GitHub (Oct 13, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/2626

Summary

Static bundle analysis omits literal WebMCP declarations written with optional chaining. A captured script containing two optional registration forms and a plain form returns only the plain declaration, even though the script parses successfully.

Steps to reproduce

  1. At the source baseline below, use the single-script page-inspection fixture in src/domain/webBundleAnalyzer.test.ts with this source.
document.modelContext?.registerTool({name: "optional-object"});
document.modelContext.registerTool?.({name: "optional-call"});
document.modelContext.registerTool({name: "plain"});
  1. Call analyzeCapturedWebBundle and read observations.webmcp_declarations and completeness.
  2. As a syntax control, add window.fetch?.('/optional-fetch'); and inspect endpoint candidates.

Expected behavior

The static declaration inventory should include all three named declaration sites. Optional chaining changes whether a call executes at runtime, but this analysis reports source declarations without execution. The entries should retain the existing untrusted page-declaration designation.

Actual behavior

The observed declaration names were ["plain"]. Both optional declaration sites were missing. The result reported complete with zero parse failures and retained /optional-fetch from the optional-call syntax control.

Evidence

  • Expected source: docs/browser-observation.md:19 advertises static WebMCP declarations; AGENTS.md, Architecture and Cleanup, requires preserving source evidence; src/domain/webBundleAnalyzerInspection.ts:131-146 accepts optional calls for static inspection.
  • Failure source: src/domain/webBundleAnalyzerInspection.ts:198-203 excludes optional call nodes from declaration collection, although src/domain/javascript/javascriptStaticAnalysisHelpers.ts:574-591 resolves their literal callee names.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

One focused domain observation test passed while asserting the faulty inventory and syntax control. The same test confirmed that document.modelContext[registerTool]({name: "dynamic"}) remained unrecorded. This was source-analyzer verification with a validated inspection, without live registration, CLI capture, or tool execution.

Restoration check

Return the three names from the reproduction in source order with untrusted declaration metadata, while retaining the optional fetch endpoint. Keep dynamic computed registration names unrecorded and the existing computed-name control passing. The result must remain evidence of source declarations, without implying successful live registration.

Runtime or environment

Source revision: 8b181716ac. Node.js v26.10.0, npm 11.19.1, and lockfile-installed dependencies.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: The inventory silently omits declaration evidence for two valid optional-call forms while reporting complete parse coverage. Live registration failures or broader frequency were not established.
  • Workaround status: unverified
  • Workaround basis: Captured source remains available, but no alternate workflow was tested that returns the omitted static declarations with equivalent provenance.
Originally created by @coygeek on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2626 ## Summary Static bundle analysis omits literal WebMCP declarations written with optional chaining. A captured script containing two optional registration forms and a plain form returns only the plain declaration, even though the script parses successfully. ## Steps to reproduce 1. At the source baseline below, use the single-script page-inspection fixture in `src/domain/webBundleAnalyzer.test.ts` with this source. ```js document.modelContext?.registerTool({name: "optional-object"}); document.modelContext.registerTool?.({name: "optional-call"}); document.modelContext.registerTool({name: "plain"}); ``` 2. Call `analyzeCapturedWebBundle` and read `observations.webmcp_declarations` and `completeness`. 3. As a syntax control, add `window.fetch?.('/optional-fetch');` and inspect endpoint candidates. ## Expected behavior The static declaration inventory should include all three named declaration sites. Optional chaining changes whether a call executes at runtime, but this analysis reports source declarations without execution. The entries should retain the existing untrusted page-declaration designation. ## Actual behavior The observed declaration names were `["plain"]`. Both optional declaration sites were missing. The result reported `complete` with zero parse failures and retained `/optional-fetch` from the optional-call syntax control. ## Evidence - Expected source: `docs/browser-observation.md:19` advertises static WebMCP declarations; `AGENTS.md`, Architecture and Cleanup, requires preserving source evidence; `src/domain/webBundleAnalyzerInspection.ts:131-146` accepts optional calls for static inspection. - Failure source: `src/domain/webBundleAnalyzerInspection.ts:198-203` excludes optional call nodes from declaration collection, although `src/domain/javascript/javascriptStaticAnalysisHelpers.ts:574-591` resolves their literal callee names. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete One focused domain observation test passed while asserting the faulty inventory and syntax control. The same test confirmed that `document.modelContext[registerTool]({name: "dynamic"})` remained unrecorded. This was source-analyzer verification with a validated inspection, without live registration, CLI capture, or tool execution. ## Restoration check Return the three names from the reproduction in source order with untrusted declaration metadata, while retaining the optional fetch endpoint. Keep dynamic computed registration names unrecorded and the existing computed-name control passing. The result must remain evidence of source declarations, without implying successful live registration. ## Runtime or environment Source revision: 8b181716aca2cb467be499cba226abfb5ae19141. Node.js v26.10.0, npm 11.19.1, and lockfile-installed dependencies. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: The inventory silently omits declaration evidence for two valid optional-call forms while reporting complete parse coverage. Live registration failures or broader frequency were not established. - Workaround status: unverified - Workaround basis: Captured source remains available, but no alternate workflow was tested that returns the omitted static declarations with equivalent provenance.
bsakaguchi 2026-10-15 18:29:45 +00:00
Author
Owner

@morluto commented on GitHub (Oct 14, 2026):

Static web-bundle analysis now retains literal WebMCP declaration names written through optional chaining and marks them as untrusted page declarations. The regression passes on current main.

Root cause: Declaration inspection excluded optional member/call AST nodes despite resolving their literal callee names.

Validation: src/domain/webBundleAnalyzer.test.ts: 'retains WebMCP declarations through optional member and call chaining' checks both optional declaration names and page-declared-untrusted metadata; a separate test keeps dynamic computed identifiers unrecorded. These assertions passed in CI at 500e32399; the reviewed implementation is present on current main. Fix: b58adafa4f.

Verification scope: This reports static source declarations only, not runtime registration or execution.

<!-- gh-comment-id:6161950754 --> @morluto commented on GitHub (Oct 14, 2026): Static web-bundle analysis now retains literal WebMCP declaration names written through optional chaining and marks them as untrusted page declarations. The regression passes on current main. Root cause: Declaration inspection excluded optional member/call AST nodes despite resolving their literal callee names. Validation: src/domain/webBundleAnalyzer.test.ts: 'retains WebMCP declarations through optional member and call chaining' checks both optional declaration names and page-declared-untrusted metadata; a separate test keeps dynamic computed identifiers unrecorded. These assertions passed in [CI at 500e32399](https://github.com/morluto/rea/actions/runs/38514789942); the reviewed implementation is present on current main. Fix: [b58adafa4f](https://github.com/morluto/rea/commit/b58adafa4f). Verification scope: This reports static source declarations only, not runtime registration or execution.
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#940
No description provided.