Purpose

Use this runbook when a new chat needs to render the actual Nex runtime locally in Chromium for visual QA. The goal is to avoid re-discovering the same Chromium policy, Xvfb, ANGLE and SwiftShader setup every time.

This procedure must test the actual full-root checkpoint. Do not reconstruct a checkpoint from unrelated old roots + patches unless the handover explicitly requires it.

1. Verify the exact checkpoint first

Before doing anything else:

1. Locate the requested locked full-root ZIP in the Library.
2. Materialize the ZIP into /mnt/data.
3. Verify its .sha256 if supplied.
4. Unpack that exact root.
5. Read its current START_HERE, handover/current-step files and stop boundary.

If the requested full root is not actually available, STOP and say exactly what is missing.

2. Chromium is present but localhost may be centrally blocked

The sandbox Chromium policy can contain:

```json
"URLBlocklist": ["*"]
```

That blocks the local Nex HTTP server with ERR_BLOCKED_BY_ADMINISTRATOR, even though Chromium and WebGL themselves are working.

For local QA only, temporarily add a localhost allow-list entry:

```json
"URLAllowlist": ["127.0.0.1"]
```

The working policy file in this sandbox was:

```text
/etc/chromium/policies/managed/000_policy_merge.json
```

Mandatory policy handling

• Back up the policy file before editing it.
• Change only the local allow-list needed for the QA server.
• Do not modify the Nex checkpoint to solve a browser-policy problem.
• Restore the original policy file after QA.

A previous attempt using path wildcards was too restrictive for this Chromium policy parser. The verified working value was simply 127.0.0.1.

3. Start Xvfb

SwiftShader/ANGLE can fail its EGL/XCB initialization if Chromium is launched without a display. Use Xvfb even when Chromium itself is headless.

Known working pattern:

```bash
Xvfb :99 -screen 0 1280x960x24 -nolisten tcp &
export DISPLAY=:99
```

If Chromium logs EGL_NOT_INITIALIZED or XCB/display errors, verify Xvfb is running and that Chromium inherits DISPLAY=:99.

4. Known-working Chromium flags

Use the system Chromium binary:

```text
/usr/bin/chromium
```

Known-working flags:

```text
--headless=new
--no-sandbox
--disable-dev-shm-usage
--ignore-gpu-blocklist
--enable-webgl
--enable-webgl2
--enable-unsafe-swiftshader
--use-gl=angle
--use-angle=swiftshader-webgl
--remote-debugging-port=0
--remote-allow-origins=*
--user-data-dir=<fresh temp directory>
about:blank
```

Use a fresh temporary Chromium profile for each QA run.

5. Serve the full root over local HTTP

Do not use file:// for the production QA path. Start a tiny HTTP server bound to:

```text
127.0.0.1
```

Serve files from the unpacked checkpoint root only, with path traversal protection and Cache-Control: no-store.

The player is normally:

```text
/assets/nexprod/nexprod01-player.html
```

6. Connect through CDP

Wait for Chromium stderr to emit:

```text
DevTools listening on ws://127.0.0.1:...
```

Then connect to the page target through Chrome DevTools Protocol and enable at least:

```text
Page.enable
Runtime.enable
```

Set a deterministic viewport, for example:

```text
1200 × 900, deviceScaleFactor 1
```

7. Verify the graphics stack before judging Nex

Once the actual Nex scene is ready, inspect the renderer context.

Expected successful renderer from the V384E128 QA:

```text
WebGL 2.0 (OpenGL ES 3.0 Chromium)
ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero)), SwiftShader driver)
```

A WebGL probe on about:blank is useful for debugging the graphics stack, but it is NOT a substitute for loading the actual Nex player.

8. Actual-scene readiness gate

Do not take a screenshot just because the HTML page loaded. Wait until the real Nex renderer exists, for example:

```js
!!globalThis.__NEXPROD01_DEBUG_SCENE?.renderer
```

For grip QA, also wait for the relevant grip solver to be active/applied and verify its pass/status fields before rendering evidence.

9. Critical exercise-selection rule

Do not trust only the exercise= URL parameter. Verify the exact exercise/profile/case being rendered.

For Dynamic Warm Up · Figure fours in V384E128, the correct identity is:

```text
exerciseId: figure-fours
profileId: warmup_figure_four_walk_ik_v1
```

Correct V93 peak cases:

```text
RIGHT Figure 4 peak
caseId=v93_warmup_figure_four_walk_1
phase=0.25
expectedKeypose=right_figure_four_peak

LEFT Figure 4 peak
caseId=v93_warmup_figure_four_walk_2
phase=0.75
expectedKeypose=left_figure_four_peak
```

Important failure discovered 2026-08-23

Old/stale v340_figure_four_* case IDs were used in one QA attempt. The URL still said exercise=figure-fours, but the resulting screenshots showed a quad-stretch-like pose rather than the requested Figure 4. Therefore:

A valid QA must visually confirm that the rendered pose is actually the requested exercise.

For Figure 4, the lifted leg must cross in front of the body in the figure-four position. If the heel is simply pulled behind the body, STOP: it is the wrong pose/exercise state.

10. Recommended player URL for Figure 4

Right peak example:

```text
http://127.0.0.1:<PORT>/assets/nexprod/nexprod01-player.html?exercise=figure-fours&caseId=v93_warmup_figure_four_walk_1&phase=0.25&play=0&safeBoot=0&debug=0&visualMode=nex&nativeRuntimeParity=1&idleSleepAfterReady=0
```

Left peak uses:

```text
caseId=v93_warmup_figure_four_walk_2&phase=0.75
```

11. Multi-view visual QA

Never approve biomechanics from one camera angle.

Capture at least:

• front
• rear
• left or right side
• opposite side if joint direction is ambiguous
• rear/three-quarter view when grip or elbow branch is being assessed

For a deterministic camera, calculate the model bounding box, use its center as the look-at target and place the camera on ±X / ±Z around the model at a distance based on model size.

Hide only QA HUD/loading overlays before screenshots. Do not change the pose, solver or model to make the screenshot look better.

12. Figure 4 runtime checks used in V384E128

For the Figure 4 peaks, the generic multi-grip state should be present:

```text
NEXPROD01_GENERIC_MULTI_GRIP_SOLVER_V1
```

Expected characteristics in V384E128:

• active = true
• applied = true
• gripCount = 2
• grip pass = true for both hands
• arm relock stage = v384e_arm_explicit_snap_outward_elbow_branch

The renderer must still report SwiftShader/WebGL2 during the same actual-scene run.

13. Cleanup

At the end of the QA run:

1. Kill Chromium.
2. Stop Xvfb.
3. Stop the local HTTP server.
4. Restore the original Chromium managed-policy JSON.
5. Confirm no changes were made to the locked checkpoint unless the task explicitly requested a patch.

14. Fast diagnostic interpretation

• ERR_BLOCKED_BY_ADMINISTRATOR → Chromium localhost policy, not Nex.
• EGL_NOT_INITIALIZED / XCB display error → Xvfb/DISPLAY problem.
• WebGL2 works on about:blank but Nex never gets a renderer → investigate player/runtime boot.
• Nex renderer exists but grip-ready gate times out → investigate runtime/grip state, not Chromium.
• URL says correct exercise but image is visibly another movement → wrong/stale case/profile state; STOP and verify canonical case IDs and expected keypose.

15. Reusable V384E128 Figure 4 QA script

The tested CDP multiview harness for this checkpoint is saved as:

```text
tools/nexprod/run_v384e128_figure4_chromium_opengl_qa.mjs
```

It uses the correct V93 Figure 4 case IDs, captures multiple camera views and records the WebGL/SwiftShader renderer plus grip evidence.