Spike now runs real input (90 Hz sample-and-hold tracking + jitter under 144 Hz
physics), which reproduced the playtest. Root causes fixed:
- PoseFilter/RagdollDriver: timestamped extrapolation of tracking, one tick
pipeline shared by PlayerRig and the spike
- low-pass all feed-forwards (ground control amplified jitter by body mass)
- arm muscles back to local targets (physical-frame aim fed chest rotation back)
- structural hand strength only when braced or holding
- no free-path view chasing while grounded (8 m crouch slide); stick hold-back
- explicit inertia for the Legs body (shape-less tuck tumbled the pelvis)
- world grab: Box3D shape queries return a null collider, use collider_id
- new crouch-hold phases; world-grab detection asserted
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WorldPanel is now the project's one SubViewport screen: MainMenu (tabs Player /
World / System; Return to spawn, Recalibrate body, Reset props, Ping, click
volume slider, scrollable log, FPS, Close) rendered by MenuScreen into a
960x640 SubViewport on a thin 0.36x0.24 m panel.
Input = touch-first hybrid cursor injected as mouse events: both controller
rays are projected analytically onto the panel plane, converted to viewport
pixels and pushed via Viewport.PushInput (MouseMotion/MouseButton, wheel from
thumbstick). Stylus tip within 6 cm = touch cursor (press crossing 0.6 cm from
the front, release past 1.8 cm); farther = laser cursor with trigger edge. One
owning hand per viewport. Haptic tick + synthesized click on press.
Kept: ax_button summon/dismiss, XROrigin3D parenting, grip drag (direct/laser)
with head re-orient, IsBlocking/IsPanelCollider. Locomotion's beam now takes
its length from WorldPanel.TryGetLaserDistance (no beam while touching) and
starts at the stylus tip. Recalibrate calls Recalibrate() on the first node in
group "calibration" (disabled when absent).
New headless regression scenes/menu_spike.tscn ("MENU: overall PASS").
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Elbow stored as an angle around the arm axis vs a torso-frame reference: 85% hand-suggested,
from the controller pose (not the physics palm), clamped +-110 deg, 6 rad/s rate limit
(flip spike: 1.8 cm/tick max vs 13.8 unclamped)
- PhysicsArms.ConstrainHand: while an arm segment is in contact the hand may lead the
forearm end by 3 cm; PhysicsHands applies it and suspends stuck-snap while active
- ArmSpike: forearm-rest-over-anvil (owner pose: collider fine, drawn forearm 3.9 cm -> 0),
flip sweep, bar test now asserts the hand is held back; all six spikes PASS x3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Lean computed from PhysicsTorso.NominalTarget/TargetBasis, not the body's own shoulders:
the closed loop made the chest hunt (spike: |v| 1.1 -> 0.019 m/s, lean range 2.7 cm -> 0.9 mm)
- Elbow on its IK circle, 75% hand-axis (forearm continues behind the wrist), bounded-rate
rotation smoothing (no flips), capped at max(shoulder, wrist) + 5 cm
- PhysicsArms.SetHeld: held prop ignores that side's arm segments (PropGrabber calls it)
- ArmSpike: stretch settle, hug elbows out (0.17 m vs 0.02 m old pole), held-anvil stability;
all six spikes PASS x3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- PhysicsArms: per side 2.0 kg upper arm + 1.2 kg forearm RigidBody3D PD-chasing their
analytic 2-bone IK pose, solved per physics tick from the physical chest shoulders to the
physical hands; no joints (Box3D has no usable shoulder/wrist joint; AGENTS forbids joints
between tracked bodies). Budgets from a 60 kg mass stat: hand 90 < forearm 180 < upper
arm 360 < chest 2400 N. Owns calibration + reach budget (moved from BodyRig); 1 m snap,
non-finite reset, BodyMath.RotationError servo.
- Layer 5 = player arms (mask 1); props/table/floor masks include it; no self-collision.
- BodyRig: visuals only, arms drawn shoulder -> physical elbow -> wrist.
- ArmSpike: track gap 0, swing lag <= 6 cm, arm pushes prop with hand clear, forearm blocked
by bar without tunneling and quiet when pinned, teleport snap, NaN reset — PASS x3.
- CollapseSpike now runs the full body (49/49 x3); all six spikes PASS x3.
- HANDOFF/AGENTS: Stage 2 entry (item 10), layers, tuning table, Stage 2b next steps.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- BodyMath.RotationError: atan2-based shortest-arc error (no NaN, no GetAxis gain collapse
inside 0.16 deg); used by PhysicsTorso orientation servo and PhysicsHands rotation lock
- BodyMath.ResetIfNonFinite escape hatch on torso + hands
- PhysicsHands.Drive extracted (static) so spikes run the real hand chase
- CollapseSpike: deterministic repro (slow yaw drift across a parked chest, 7/40 NaN on old
code) + solver-stacking scenarios (seated chest in table, two-hand-welded 50 kg anvil,
real PropShop) — 49/49 clean after fix, x3; all other spikes PASS x3
- Failure brief RESOLUTION section; HANDOFF/AGENTS updated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>