Summary
The macOS WKWebView can show a blank OpenWorlds surface when Swift navigates to
/openworlds without a trailing slash. The OpenWorlds bundle uses relative asset
URLs like styles.css, app.jsx, and vendor/react-18.3.1.development.js.
When the browser treats /openworlds as a file path, those assets resolve from
/ instead of /openworlds/.
Release Impact
This makes the new native app look broken even though the same URL may appear to
work when manually corrected in Safari. It directly blocks the OpenWorlds-as-app
rollout because the main window can render blank while Safari renders the design.
Architecture Invariant Violated
OpenWorlds must be the normal in-app play surface. The native app must not rely on
manual Safari correction or a user knowing to add a slash.
Evidence
Relevant code paths:
macos/ClawDnDApp/Sources/ClawDnDApp/Models/LocalEndpoint.swift
viewer/server.py
viewer/tests/test_openworlds_static.py
Current behavior to guard:
Swift URL: http://127.0.0.1:<port>/openworlds
Expected canonical URL: http://127.0.0.1:<port>/openworlds/
Repro
- Launch the app.
- Navigate the embedded WKWebView to
/openworlds.
- Observe a blank surface or missing styling/scripts.
- Manually open
/openworlds/ and observe the designed UI.
Suspected Root Cause
LocalEndpoint.openWorldsURL appends openworlds without preserving directory
semantics, and the viewer did not canonicalize /openworlds to /openworlds/.
Fix Options
Minimal patch:
- Make Swift construct
/openworlds/.
- Redirect
/openworlds to /openworlds/ in viewer/server.py.
- Add a route regression.
Broader hardening:
- Add endpoint readiness and canonical-route tests for every app surface.
- Make the app wait for
/openworlds/ before navigation.
Recommended Solution
Take the minimal patch now, then include readiness waiting in the OpenWorlds host
PR.
Acceptance Criteria
GET /openworlds returns 301 or 302 to /openworlds/.
LocalEndpoint.openWorldsURL includes the trailing slash.
- WKWebView loads OpenWorlds assets correctly.
Focused Validation
python3 -m unittest viewer.tests.test_openworlds_static -q
python3 -m py_compile viewer/server.py
swift build --package-path macos/ClawDnDApp
git diff --check
Original-Agent Handoff
Inspect first:
LocalEndpoint.openWorldsURL
_Handler.do_GET OpenWorlds route handling in viewer/server.py
OpenWorldsStaticRouteTests
Summary
The macOS WKWebView can show a blank OpenWorlds surface when Swift navigates to
/openworldswithout a trailing slash. The OpenWorlds bundle uses relative assetURLs like
styles.css,app.jsx, andvendor/react-18.3.1.development.js.When the browser treats
/openworldsas a file path, those assets resolve from/instead of/openworlds/.Release Impact
This makes the new native app look broken even though the same URL may appear to
work when manually corrected in Safari. It directly blocks the OpenWorlds-as-app
rollout because the main window can render blank while Safari renders the design.
Architecture Invariant Violated
OpenWorlds must be the normal in-app play surface. The native app must not rely on
manual Safari correction or a user knowing to add a slash.
Evidence
Relevant code paths:
macos/ClawDnDApp/Sources/ClawDnDApp/Models/LocalEndpoint.swiftviewer/server.pyviewer/tests/test_openworlds_static.pyCurrent behavior to guard:
Repro
/openworlds./openworlds/and observe the designed UI.Suspected Root Cause
LocalEndpoint.openWorldsURLappendsopenworldswithout preserving directorysemantics, and the viewer did not canonicalize
/openworldsto/openworlds/.Fix Options
Minimal patch:
/openworlds/./openworldsto/openworlds/inviewer/server.py.Broader hardening:
/openworlds/before navigation.Recommended Solution
Take the minimal patch now, then include readiness waiting in the OpenWorlds host
PR.
Acceptance Criteria
GET /openworldsreturns 301 or 302 to/openworlds/.LocalEndpoint.openWorldsURLincludes the trailing slash.Focused Validation
Original-Agent Handoff
Inspect first:
LocalEndpoint.openWorldsURL_Handler.do_GETOpenWorlds route handling inviewer/server.pyOpenWorldsStaticRouteTests