# V306 ENTRY FRAME STATE MACHINE REPORT

## Purpose
Fix the V304/V305 false positive on the left grip-entry path. V297 `NEEDS_NEUTRALIZE_BEFORE_SOLVE_GRIP` is now a hard state transition: the solver must rotate/neutralize the active handframe before point snap and before finger release.

## Runtime changes
- Runtime version: `NEXPROD01_RUNTIME_V306_ENTRY_FRAME_STATE_MACHINE_2026_08_19`
- Added `NEXPROD01_V306_ENTRY_FRAME_NEUTRALIZE_ROTATION`.
- Added `NEXPROD01_V306_ACTUAL_SURFACE_PREFINGER_GATE`.
- Finger child-layer remains blocked unless solver side-surface gate and post-commit actual-surface gate both pass.
- Finger layer remains z+ only; thumb writer remains off.

## Browser audit
- Browser/WebGL runtime: `True`
- Entry-frame state machine present: `True`
- No false finger release when actual gate fails: `True`

### Right summary
```json
{
  "hasModel": true,
  "boneCount": 165,
  "skinnedMeshCount": 12,
  "runtimeVersion": "V306_ENTRY_FRAME_STATE_MACHINE_ACTUAL_GATE",
  "side": "R",
  "gripApplied": true,
  "gripPass": true,
  "gripStatus": "GRIP_ENTRY_CONTRACT_PREFINGER_READY",
  "gripReason": null,
  "nextPhase": "finger_child_layer_ready_but_deferred_to_v302_integration",
  "entryPass": true,
  "entryGate": "GRIP_ENTRY_FRAME_USABLE",
  "entryRequiredOutwardShiftM": 0,
  "entrySignedOutsideM": 0.12338,
  "repairSchema": "NEXPROD01_V306_ENTRY_FRAME_NEUTRALIZE_ROTATION",
  "repairApplied": false,
  "repairPass": true,
  "repairReason": "initial_entry_frame_pass",
  "repairRollDeg": null,
  "repairAfterGate": {
    "schema": "NEXPROD01_V297_V286_ENTRY_FRAME_GATE",
    "source": "V286_NEUTRALIZE_HAND_FOR_GRIP",
    "active": true,
    "mutatesTargets": false,
    "side": "R",
    "pass": true,
    "gate": "GRIP_ENTRY_FRAME_USABLE",
    "desiredOutsideDistanceM": 0.055,
    "signedOutsideM": 0.12338,
    "palmBaseOutsideM": 0.11954,
    "requiredOutwardShiftM": 0,
    "palmAcrossOutsideDot": -0.82552,
    "limbAxisA": "R_Foot",
    "limbAxisB": "R_Calf",
    "policy": "V297 ports V286 as a non-mutating pre-contact entry-frame gate inside the V267 clean solver. It measures whether the hand MCP/palm frame approaches from the outside shell before point snap, palm roll, or finger child-layer."
  },
  "sideSurfacePass": true,
  "sideSurfaceStatus": "GRIP_ENTRY_CONTRACT_PREFINGER_READY",
  "actualGatePass": false,
  "actualEntryOk": true,
  "actualSolverOk": true,
  "actualMeshPass": false,
  "actualPalmGapOk": false,
  "actualPalmGapM": -0.007666,
  "v153Pass": false,
  "fingerSchema": "NEXPROD01_V306_ZPLUS_SEQUENTIAL_FINGER_CONTACT_CHILD_LAYER",
  "fingerActive": false,
  "fingerBlocked": true,
  "fingerReason": "v306_actual_surface_or_entry_frame_gate_not_passed",
  "fingerReady": false,
  "fingerReleaseEnabled": false,
  "probeSide": "R",
  "meshTruthSide": null,
  "palmSourceGapM": -0.007665873643823113
}
```

### Left summary
```json
{
  "hasModel": true,
  "boneCount": 165,
  "skinnedMeshCount": 12,
  "runtimeVersion": "V306_ENTRY_FRAME_STATE_MACHINE_ACTUAL_GATE",
  "side": "L",
  "gripApplied": true,
  "gripPass": true,
  "gripStatus": "GRIP_ENTRY_CONTRACT_PREFINGER_READY",
  "gripReason": null,
  "nextPhase": "finger_child_layer_ready_but_deferred_to_v302_integration",
  "entryPass": false,
  "entryGate": "NEEDS_NEUTRALIZE_BEFORE_SOLVE_GRIP",
  "entryRequiredOutwardShiftM": 0.0136,
  "entrySignedOutsideM": 0.0414,
  "repairSchema": "NEXPROD01_V306_ENTRY_FRAME_NEUTRALIZE_ROTATION",
  "repairApplied": true,
  "repairPass": true,
  "repairReason": "rotated_entry_frame_repaired_orientation_continue_to_point_snap",
  "repairRollDeg": -180,
  "repairAfterGate": {
    "schema": "NEXPROD01_V297_V286_ENTRY_FRAME_GATE",
    "source": "V286_NEUTRALIZE_HAND_FOR_GRIP",
    "active": true,
    "mutatesTargets": false,
    "side": "L",
    "pass": false,
    "gate": "NEEDS_NEUTRALIZE_BEFORE_SOLVE_GRIP",
    "desiredOutsideDistanceM": 0.055,
    "signedOutsideM": 0.0414,
    "palmBaseOutsideM": 0.04588,
    "requiredOutwardShiftM": 0.0136,
    "palmAcrossOutsideDot": 0.76411,
    "limbAxisA": "L_Foot",
    "limbAxisB": "L_Calf",
    "policy": "V297 ports V286 as a non-mutating pre-contact entry-frame gate inside the V267 clean solver. It measures whether the hand MCP/palm frame approaches from the outside shell before point snap, palm roll, or finger child-layer."
  },
  "sideSurfacePass": true,
  "sideSurfaceStatus": "GRIP_ENTRY_CONTRACT_PREFINGER_READY",
  "actualGatePass": false,
  "actualEntryOk": true,
  "actualSolverOk": true,
  "actualMeshPass": false,
  "actualPalmGapOk": false,
  "actualPalmGapM": 0.02355,
  "v153Pass": false,
  "fingerSchema": "NEXPROD01_V306_ZPLUS_SEQUENTIAL_FINGER_CONTACT_CHILD_LAYER",
  "fingerActive": false,
  "fingerBlocked": true,
  "fingerReason": "v306_actual_surface_or_entry_frame_gate_not_passed",
  "fingerReady": false,
  "fingerReleaseEnabled": false,
  "probeSide": "L",
  "meshTruthSide": null,
  "palmSourceGapM": 0.023550332758627113
}
```

## Interpretation
V306 fixes the control-flow bug: left is no longer allowed to pass from a failed V297 entry-frame gate directly into fake `PREFINGER_READY` and finger closure.

Left now performs the neutralizing rotation step. The best repair rotates the handframe around the active forearm/wrist axis and changes the entry frame from the original bad side state to a repaired orientation state, then continues into point snap/object-meet. The final solver-side gate passes, but the new post-commit actual-surface gate still fails because actual skinned contact is not yet close enough (`palmSourceGapM` remains too large). Therefore fingers remain blocked.

This means the next root cause is not finger axis and not the thumb rule. It is the mapping between solver palm targets/shifted surface and actual skinned palm/leg contact after the one-writer commit. V307 should make the actual palm bones/skin (`Mid1/Index1/Pinky1`) the surface gate authority, rather than letting phantom pre-commit pointA/pointB approve the grip.
