| name | monica-ui-bridge-debug |
| description | Orchestrate Monica UI inspection, debugging, and refinement through a bridge ASP.NET Core project. Use when Monica has no standalone entry point and Codex must launch a bridge service on a user-provided or discovered URL/port, choose between a simple single-agent bridge workflow and a delegated sub-agent workflow, capture browser artifacts with Playwright, and implement Monica UI fixes under $monica-ui-development. Use simple mode for narrow tasks or when the user requests simple mode. |
Monica UI Bridge Debug
Use this skill when Monica UI work must be verified through a separate runnable application.
Required UI and browser skills
- Use
$monica-ui-development for every Monica Blazor UI implementation or style change.
- Use
$monica-ui-localization for any UI text, localization resource, navigation/AppBar key, or i18n validation change.
- Use
$playwright-cli for browser inspection, snapshots, and screenshots.
Inputs to collect or resolve
Collect or derive these inputs before bridge-based UI testing starts:
- Bridge implementation project directory, for example
..\SomeApp\src\Services\Sample\SampleService.API
- Bridge service base URL when the user already knows it, for example
http://localhost:5092
- Target page route or enough module context to discover the page route from the ModuleUI page
- The actual UI task to inspect, fix, or implement
- Bridge artifact directory when the user already has a preferred location
The bridge service base URL is optional user input. If it is missing, derive it from project launch configuration, an existing project-owned listener, or a newly selected unused local port. Do not stop to ask for a base URL unless no reasonable URL can be discovered or selected.
Do not hardcode any bridge project path, service URL, or artifact directory inside the workflow.
DOM-first bridge diagnosis
When debugging Monica UI through a bridge app, prioritize runtime DOM and CSS evidence over screenshots.
- Always inspect the live page HTML for the target elements before changing code.
- Always inspect computed styles for the target elements when the issue is spacing, sizing, alignment, overflow, or visibility.
- Always inspect the loaded stylesheet rules or emitted Blazor
*.bundle.scp.css when a class appears in HTML but the expected style does not apply.
- Validate actual runtime MudBlazor DOM class names before writing selectors. Do not guess internal names.
- Use screenshots only to confirm the visible impact after the root cause is understood. Do not diagnose layout issues from screenshots alone.
Select execution mode first
Choose the workflow before launching the bridge service.
Simple mode
Use simple mode when the task is narrow, the expected fix is localized, or the user explicitly asks for simple mode.
Rules:
- Use the user-provided bridge artifact directory or create a task-specific directory under
.tmp/monica-ui-bridge-debug/.
- Do not use sub-agents.
- Store bridge logs, screenshots, snapshots, and readiness artifacts in the bridge artifact directory.
Delegated sub-agent mode
Use delegated sub-agent mode when the task is complex, spans multiple debug or verification loops, benefits from parallel long-running work, or the user explicitly asks for sub-agent mode.
Rules:
- Act only as the orchestrator. Collect inputs, decide the workflow, ask the user for design confirmation, coordinate sub-agents, and summarize results.
- Delegate concrete bridge testing, Playwright capture, debugging, implementation, and verification to sub-agents through the runtime's SubAgent features.
- Keep all bridge artifacts in the selected bridge artifact directory.
- Do not silently downgrade to simple mode when the user asked for sub-agent mode.
Mandatory Monica UI rule handoff
Before editing Monica UI files, also apply $monica-ui-development:
python scripts/check_mudblazor_source.py
If the source check fails, stop implementation and ask the user to provide the required MudBlazor source.
Ask for design confirmation early
If a meaningful design choice needs user confirmation, ask as soon as the decision becomes clear.
- Provide a small set of concrete options and the main tradeoff for each option.
- Pause before implementation if the choice changes architecture, UX, component structure, or shared patterns in a non-obvious way.
Quick start
Simple mode
- Collect the required inputs.
- Select the user-provided bridge artifact directory or create a task-specific directory under
.tmp/monica-ui-bridge-debug/.
- Resolve the bridge service URL from user input, launch settings, an existing project-owned listener, or an unused local port.
- Place screenshots, snapshots, bridge logs, and readiness files in that artifact directory.
- Launch the bridge service with
scripts/bridge_service.py run.
- Wait for readiness with
scripts/bridge_service.py wait-ready.
- Open the full page URL with
$playwright-cli and capture artifacts.
- Implement Monica UI changes under
$monica-ui-development rules.
- Restart the bridge service with the same script when verification requires a rebuild.
- Leave the bridge service running after success so the user can inspect it.
Delegated sub-agent mode
- Collect the required inputs and ask for any blocking design decision immediately.
- Select or create the bridge artifact directory.
- Spawn sub-agents with explicit ownership for bridge testing, debugging, implementation, or verification.
- Observe native lifecycle, respond promptly to blockers, and collect each completed result before integration.
- Keep the bridge service running after successful verification unless the user asks otherwise.
Workflow
Cleanup safety note
The helper must never kill unrelated system listeners just because they share the target port. Before trusting bridge_service.py cleanup/run, verify cleanup only terminates:
- PIDs recorded in the artifact directory state file, or
- project-owned bridge processes whose command line clearly references the selected bridge project.
If the target port is occupied by an unrelated listener, the helper should report that conflict instead of force-killing it.
1. Bridge artifact directory
Select the artifact directory before launching the bridge. Use a user-provided directory when available; otherwise create a task-specific path under .tmp/monica-ui-bridge-debug/<timestamp>-<short-slug>/. The bridge helper creates the selected directory when necessary.
Save these artifacts in the bridge artifact directory:
app-run.log
bridge-ready.json
bridge-ready-report.json
bridge-process.json
- Playwright screenshots and snapshots
- Any additional debug notes
2. Default execution model
Prefer simple mode by default for narrow bridge tasks:
- Run
bridge_service.py run
- Run
bridge_service.py wait-ready
- Use
$playwright-cli
- Implement or verify the Monica UI change
run now starts the bridge service in the background by default and returns immediately, so the same agent can continue with wait-ready.
Switch to delegated sub-agent mode when the task is complex or the user requests it. In that mode, the main agent only coordinates and the sub-agents perform the concrete bridge, debug, and implementation work.
3. Delegated sub-agent orchestration
When delegated sub-agent mode is selected:
- Give each sub-agent a stable ownership boundary and a concrete deliverable.
- Assign bridge-process ownership to one sub-agent at a time so concurrent workers do not restart or clean up the same service.
- Use native runtime lifecycle inspection and bounded waits while work continues.
- Respond immediately to explicit blockers or input requests.
- Collect terminal results and verify the integrated outcome in the main task before delivery.
4. Bridge service startup script
Use the bundled Python script instead of ad-hoc shell snippets.
Resolve <bridge-service-url> before launch:
- If the user supplied a base URL, use it.
- Otherwise inspect
Properties/launchSettings.json in the bridge project and use the first HTTP URL with an explicit port from applicationUrl.
- Otherwise look for an existing listener whose process command line clearly references the selected bridge project and use that listener's port.
- Otherwise choose an unused localhost port and construct
http://localhost:<port>.
The helper still requires --service-url, but that value may be agent-discovered. A selected localhost URL is passed through to dotnet run -- --urls, so the bridge starts on the discovered port instead of silently using its default launch profile port.
Launch:
python scripts/bridge_service.py run \
--project-dir "<bridge-project-dir>" \
--service-url "<bridge-service-url>" \
--task-dir "<artifact-directory>"
This is the default and recommended mode. It returns after the detached runner starts.
Readiness wait:
python scripts/bridge_service.py wait-ready \
--service-url "<bridge-service-url>" \
--task-dir "<artifact-directory>" \
--timeout 120
Optional explicit project selection when the directory contains more than one .csproj:
python scripts/bridge_service.py run \
--project-dir "<bridge-project-dir>" \
--project-file "<project-file>.csproj" \
--service-url "<bridge-service-url>" \
--task-dir "<artifact-directory>"
In delegated sub-agent mode, the sub-agent that owns bridge execution should run these commands.
5. WSL NAT handling
If the user provides a specific non-loopback IP such as http://172.31.96.1:5092, treat it as a WSL NAT-style access URL.
The bundled script automatically converts the runtime bind address to:
http://0.0.0.0:<port>
and passes it to dotnet run as an application argument. The external URL used for browser access remains the user-provided service URL.
If the user provides localhost or 127.0.0.1 and the agent is running inside WSL, always consider a fallback:
- if shell probes such as
curl work
- but Playwright gets
net::ERR_CONNECTION_REFUSED
then retry with the WSL gateway IP instead of localhost.
Example:
ip route | awk '/default/ { print $3; exit }'
If that returns 172.31.96.1, switch from http://localhost:5092 to http://172.31.96.1:5092, restart the bridge with that URL, and use that URL for Playwright.
6. What the startup script guarantees
bridge_service.py provides these behaviors:
- Cross-platform Python implementation for Windows, WSL, and Linux workflows
- Residual process cleanup before launch
- Extra Windows-side cleanup when running inside WSL
- Task-folder artifact reset before each new detached launch
- Background
run mode for the normal single-agent workflow
- Internal state tracking in
bridge-process.json
- Internal worker that runs
dotnet run and mirrors output into app-run.log
- Automatic retry when MSBuild reports file-lock markers such as
MSB3026
bridge-ready.json creation when a listening marker is observed
bridge-ready-report.json creation when readiness checks finish
- Safer readiness semantics: if the probe URL becomes reachable three times but the log marker is still missing,
wait-ready returns success with a warning by default instead of incorrectly treating the run as blocked
If strict log-marker enforcement is required, add --strict-marker to wait-ready.
7. Playwright capture workflow
After readiness succeeds, build the page URL from:
- resolved service base URL
- target page route from the relevant ModuleUI page
Then use $playwright-cli to inspect and capture the page.
For UI debugging, the default workflow is:
- Open the page and save a snapshot.
- Inspect the target element HTML with
eval, for example:
playwright-cli eval "() => document.querySelector('<selector>')?.outerHTML"
- Inspect computed styles for the same element, for example:
playwright-cli eval "() => JSON.stringify((() => { const el = document.querySelector('<selector>'); if (!el) return null; const cs = getComputedStyle(el); const r = el.getBoundingClientRect(); return { width: r.width, height: r.height, padding: cs.padding, margin: cs.margin, display: cs.display, borderRadius: cs.borderRadius }; })(), null, 2)"
- If the class is present but styling is missing, inspect loaded stylesheet rules or fetch the emitted Blazor CSS bundle and compare the selector shape against the runtime DOM.
- Only after the DOM/CSS root cause is clear, capture screenshots to confirm the visible result.
Use explicit paths inside the bridge artifact directory, for example:
playwright-cli open "<service-url><page-route>"
playwright-cli snapshot --filename="<artifact-directory>/page.yaml"
playwright-cli screenshot --filename="<artifact-directory>/page.png"
If the global playwright-cli binary is unavailable, fall back to npx playwright-cli.
If open is unavailable but an existing browser session is already running, prefer reusing that session with playwright-cli list, -s=<session> goto, snapshot, and eval instead of switching to screenshot-only debugging.
8. Debug logging and log markers
For difficult problems, let the delegated sub-agent add focused debug output and log search markers.
- Use a unique marker string for each investigation attempt, for example
[bridge-marker:<short-id>].
- Report the marker, approximate timestamp, page route, and investigation goal as a factual progress checkpoint before reproducing the issue.
- Search
app-run.log by marker first, then narrow by timestamp if needed.
- Keep debug logging scoped to the suspected path and remove temporary logs after verification unless the user asks to keep them.
- Assume service logs can become very large. Use markers to make retrieval practical instead of scanning the whole log repeatedly.
9. Reporting UI errors
Do not claim a runtime UI error unless one of these is true:
- the error text is visible in the saved screenshot, or
- the same error text is searchable in the saved Playwright snapshot
For layout and styling bugs, do not claim a root cause unless one of these is true:
- the target HTML and computed styles confirm the cause, or
- the emitted stylesheet rules and runtime DOM mismatch confirm the cause
Otherwise report it as unconfirmed instead of as a verified UI error.
References
references/bridge-service-script.md
Scripts
scripts/bridge_service.py - cross-platform bridge cleanup, detached launch, and readiness checks
Quick checklist