TURNCRAFT/docs/progress-cutoff/turncraft-b-progress.txt
jing 9c668d340c Headshell Workshop + Glow-Up phase: assembly minigame, art pass, review fixes
- Workshop (WORKSHOP_CARTRIDGE): five-stage cartridge assembly at Deck A —
  seat/square, crimp four tag-wires, torque screws, ride-the-arm counterweight
  balance, needle-drop diagnostic with per-fault audio + scope. Relay-synced
  (per-field co-op merge: held screw + carried wire survive remote state).
- Glow-Up (G1-G5): 32px atlas with per-voxel variants, selective LED bloom
  (quality-gated), screen-print decal system + party flyers, mixer/PCB worldgen
  density pass, record groove-sheen side texture.
- 10 confirmed multi-agent review fixes, incl. co-op screw-stomp soft-lock,
  ride-snap collider-identity (magnet feet / eaten record-fling), workshop SFX
  exact-match map (rca_seated hijack), beam ride colliders to the head,
  double-crimp guard, WIRING INCOMPLETE diagnosis mode, skate-abort timer,
  completedState wiring, per-tick material churn, trackingHeavy platter drag.
- Crossfader playtest fix: slew-limited sled (3.4 v/s) + ribbed grip caps with
  amber index — the sled reads as a heavy handle, not a teleporting wall.
- Demo harnesses: machinesDemo hold-key wiring, playerDemo seesaw phase
  continuity, audioDemo incomplete fault button.
- Workshop sync: exact 1.0 screw endpoint gets its own emit signature.

Verified: typecheck + vite build clean, live solo quest smoke, two-client
co-op relay smoke (simultaneous torque, no rewind, exact convergence).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:32:07 +10:00

113 lines
13 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Let me look at the current repo state and read both new briefs before deciding what's Lane B's to build.
The game fully integrated since my last turn (all five lanes + multiplayer + art pass), and my `src/player` is committed. Two new briefs landed. Let me read them to find what's Lane B's.
This is clarifying. The Workshop is a single-session feature (mostly machines/interaction/audio), but it **explicitly leans on my lane** for one thing: Stage 4, standing on the tonearm while it seesaws under you in real time — *"Lane B's min-penetration cylinder/aabb resolution handles the ride ... verify no slingshot on tilt."* That — riding a **tilting / vertically-moving kinematic platform** — is exactly the limitation I flagged in my last review ("vertical platform carry is dropped; matters if Lane D ships a vertically-moving rideable collider"). So the Lane B slice is: make riding a tilting arm provably safe, verify it, and write the physics section the Workshop brief tells its dev to read.
Let me read the current state of my code (integration may have touched it), the integration notes, and the tonearm it'll reuse.
Integration extended my controller (added `setSensitivity`, defaulted view-bob off, added terraced-record auto-step) — core structure intact, my fixes present. Note `setCarry` still zeroes `carryVel[1]` and `applyCarry` sweeps only X/Z: vertical is handled purely by snap-to-top. Let me read the tonearm it'll become a seesaw, and the integration notes.
Now I have the full picture. The current tonearm sweeps **horizontally** (constant Y, `headVel[1]=0`). The Workshop's Stage 4 turns it into a **vertical seesaw** you stand on — a chain of aabb segments whose Y and vertical velocity change per tick. That's precisely the "vertically-moving rideable collider" I flagged. Two things to verify/harden in my lane:
1. My aabb resolution uses pure min-penetration — at a segment **edge** during a tilt, a horizontal overlap can momentarily be smaller than the vertical one and shove the player sideways off the arm (the "slingshot").
2. Confirm vertical motion is handled (it is, via snap-to-top — not carry) with no tunneling.
Let me check whether my demo file changed under integration, then build the exact seesaw scenario and test it empirically.
My demo is untouched by integration. Let me read it to add the seesaw test mock cleanly.
Now I'll add a faithful **seesaw** mock to the demo — a chain of aabb segments that tilt about a pivot exactly like the Workshop's arm will, with a debug hook to drive the tilt headlessly. Then I'll test the current physics against it before deciding on a fix.
Now wire the seesaw into the loop, the debug handle, and add controls.
Now typecheck, then start my own dev server (the hook warns another chat's server is running — I need my own for verification).
I need my own server without clashing with the other chat's (which likely holds port 5173). Let me add a separate launch config on a distinct port rather than disturb the shared one.
Now the empirical test against the **current** physics — driving the seesaw tilt deterministically while the player rides it, measuring for any slingshot (horizontal shove off the arm, velocity spike, or launch).
No lateral slingshot (`maxZoff:0` — my resolution keeps the player centered on the arm width), but a clear failure: the player **separates from the arm**. Gentle tilt → grounded only 52% of the time, floating up to 0.69 above the surface. Fast tilt → flung (maxSpeed 48, off-arm 567/600 ticks, falls to the floor). Root cause is exactly the limitation I documented: **vertical motion is handled only by gravity chasing the surface via snap-to-top**, and a tilting arm moves faster than gravity can chase — so the player bounces on descents and gets punted on the rebound.
The fix: **glue the player to the ridden platform's vertical motion** (a pre-gravity vertical carry from the collider you're standing on). Disc/platform (vertical velocity = 0) are unaffected. Let me implement it.
Typecheck, then re-run the seesaw test plus the disc/platform/fling regressions to confirm the fix works and nothing broke.
A typecheck error appeared — but it's in `src/audio/testSignal.ts`, the parallel Workshop session's in-progress Stage-5 file (we share this working directory), not mine. Let me confirm my files are clean and that's the only error.
Confirmed: the only error is `testSignal.ts`, an untracked WIP file owned by the parallel Workshop session (`src/audio` is theirs). My code is clean, and my demo doesn't import it, so Vite (transpile-only) still runs it. Let me reload and re-test the seesaw ride plus regressions.
The vertical glue helped the fast case (no longer flung off — offArm 0, minY 4.33 vs 0.5 before) but standing isn't glued yet (gentle still floats 1.2), and "walking" here actually walked *along* the arm and off the end (test artifact, not a bug). Let me trace a steady tilt to see exactly where the player separates.
During a steady descent the player is grounded every tick (`seesaw3` throughout) — the growing `dy` (0.29 max) is just the **staircase artifact**: the player stands on a segment's flat slab (midpoint height), which my continuous `topAt` reference under-measures. That's not separation. Let me trace an **ascent** and the oscillation reversal, where the 36% ungrounded must occur.
Now I understand the real failure. Trace shows: a **steady ascent is glued** (grounded `seesaw4` throughout), but a **fast ascent floats** (grounded `—`, player rises to 12). The bug is in my own pre-carry: the arm's collider updates once per tick, but the player substeps N times, so the per-substep pre-carry *overshoots* the static arm and lifts the player off it.
The clean fix is different and simpler: **drop the velocity pre-carry; a rising arm already grounds the player by penetration (it rises into them), and a descending arm just needs a gated "ride-snap" that pulls the player back down onto the platform they were riding** — the textbook moving-platform solution, with no velocity extrapolation. Let me revert the pre-carry and implement ride-snap.
Now add the `RIDE_SNAP` constant and the ride-snap logic in the aabb branch:
Typecheck my files, then re-run the seesaw tests plus regressions.
Excellent — the **realistic tonearm-balancing pace (0.4 Hz) is now perfectly glued** (grounded 100%, yErr 0, maxSpeed 3.4), and gentle is glued too (grounded 100%, yErr = staircase artifact only). The fast/veryFast cases (3745 v/s surface speed — physically unreachable by shoving a counterweight sled) degrade *gracefully* (player slides off onto the floor, no explosion). Let me trace the fast case to confirm the failure mode is graceful and find the safe envelope, then decide if a small `RIDE_SNAP` bump is worth it.
That clarifies it — at omegaPeak 1.02.0 the player is **grounded 100%** of the time; my `offArm` flag was falsely tripping because the *arm itself* legitimately tilts below y=3 at steep angles and the player correctly rides it down. So the glued envelope extends to ~2 rad/s (~24 v/s surface) — far beyond any counterweight-driven tonearm (realistic was 0.25 rad/s). Only absurd mousetrap-speed tilts (3+ rad/s) separate, and gracefully.
Let me run the full regression suite (disc, fling, platform, auto-step, wall, tunneling, footsteps) to confirm the ride-snap changes broke nothing, plus a clean seesaw-glued confirmation.
All green: seesaw **glued at realistic pace (100%, yErr 0)** and even at 24 v/s stress (100% grounded), and every prior mechanic intact — disc circle (20.01), fling (10.2), platform, auto-step (6), no wall tunneling (29.7). Let me grab a visual of the tilted arm to confirm it renders, then finalize.
The seesaw renders — a chrome beam on a pivot, tilted head-up, with the new "Seesaw" and "Teleport to arm" controls. Let me check console, then look at the integration notes the Workshop brief points its dev to read.
INTEGRATION_NOTES.md already has a "Player physics" section from the terraced-record integration. Let me read it to augment it correctly with the seesaw/ride-snap contract.
INTEGRATION_NOTES.md has the physics section the Workshop brief references. I'll add a dedicated subsection documenting the ride-snap guarantee for the seesaw — this is exactly what the Workshop dev is told to read. Inserting it surgically before the deploy section to avoid clobbering the parallel session's edits.
Now update my HANDOFF to reflect the new ride-snap capability (which resolves the vertical-carry limitation I'd flagged). Let me read the current friction section.
Now the main deliverable Fable asked for — updating UPDATE_B.md. Let me read its current state to append this round cleanly.
Let me prepend this round's summary to UPDATE_B.md so it's the first thing Fable reads.
Let me get the diff of this round's changes and run a focused adversarial review of the ride-snap logic (proportionate to a ~15-line change), while I do a final typecheck.
The focused review found a **real false-stick bug** (and a minor fly-mode gap):
1. **Ride-snap re-grabs a platform after stepping onto flush voxel ground** — the gate checks `rideCollider !== null` (a "was I riding anything" flag) but not whether the player is now on voxel ground. So walking off the oscillating platform onto the pit rim (both flush at y=1) lets ride-snap re-grab the platform and drag the player sideways on solid ground, suppressing footsteps.
2. **`rideCollider` not cleared on `setFlying`** — could briefly ground a hovering flyer.
Both are one-line gate fixes. The reviewer also cleared 5 other classes (head-bonk short-circuit, upward teleport, jump lifecycle, double-carry, NaN) as safe. Let me fix the gate and `setFlying`.
Typecheck, reload, and verify the false-stick is fixed while the seesaw ride and regressions still pass.
All fixes verified and no regressions:
- **flushFloor:** `groundedOn: null`, x stays 60 — the false-stick is fixed (player on flush voxel ground is no longer carried).
- **overPit:** `groundedOn: platform` — legitimate riding where there's no floor beneath still works (fix didn't over-correct).
- **seesawGlued:** 100% grounded, yErr 0 — seesaw still perfect.
- **disc** (20.01) and **flyClearsRide** intact.
Let me add a note about the self-review to UPDATE_B, check console, and confirm final typecheck.
No console errors. Final confirmation of what changed this round:
Done. Here's the summary.
## Lane B this round — physics for the Headshell Workshop seesaw
I read both new briefs. **Glow-Up** is a Lane A/E art pass — not mine. The **Workshop** brief leans on Lane B for exactly one thing: Stage 4 has you *standing on the tonearm as it seesaws under your feet*, and it says *"Lane B's resolution handles the ride — verify no slingshot on tilt."* That's riding a **vertically-moving** platform — the limitation I'd flagged last round. So I built and verified that slice.
**I tested before assuming.** I added a faithful seesaw mock (a tilting aabb-segment chain like `tonearm.ts` uses) to my demo and drove it headlessly. The *old* physics **failed** — a gentle tilt left the player grounded only ~52% of the time (bouncing up to 0.7 above the arm); a fast tilt **flung them off** onto the floor. Root cause: vertical motion was left to gravity chasing the surface, and a tilting arm outruns gravity.
**The fix — ride-snap.** A rising arm grounds the player by penetration; a descending/tilting arm snaps them back onto its top across a ≤0.75-voxel per-tick gap, gated so it never fights a jump. (I first tried a velocity-based vertical carry — it *overshot*, because the arm's collider is static within a tick while the player substeps. Ride-snap sidesteps that entirely.)
**Verified live** (measured, not eyeballed):
- Seesaw **glued at realistic tonearm pace** (grounded 100%, feet on the slab) and holds to ~2 rad/s / ~24 v/s surface — ~8× past anything a counterweight can drive; graceful slide-off beyond, no explosion. No lateral slingshot at any rate.
- Every prior mechanic intact: disc circle (20.01), fling (10.2), platform, auto-step (6), no wall tunneling.
**Self-review caught 2 more, both fixed:** an adversarial pass on the diff found a false-stick (a platform flush with the voxel floor kept carrying you after you stepped off onto solid ground) and a fly-mode lifecycle gap. Fixed and re-verified — flush-floor now reads `groundedOn=null`; riding over a real gap still reads `platform`.
**Changed (6 files, all in-lane or the doc the Workshop brief points to):** [PlayerController.ts](src/player/PlayerController.ts) (ride-snap), [playerDemo.ts](src/demo/playerDemo.ts) (seesaw mock + controls), [INTEGRATION_NOTES.md](docs/INTEGRATION_NOTES.md) (new *"Physics — riding tilting platforms"* section — the one the Workshop dev is told to read), [HANDOFF.md](src/player/HANDOFF.md), [UPDATE_B.md](docs/UPDATE_B.md), and a `.claude/launch.json` port so my demo server didn't collide with the parallel session's. I did **not** touch `tonearm.ts`/`interaction.ts`/audio — those are the Workshop session's edits.
**Two heads-up for you, Fable:**
- The working tree has many files modified by the **parallel Workshop + Glow-Up sessions** (they share this directory) — `src/machines/workshop/`, `src/audio/*`, `tonearm.ts`, `main.ts`, etc. Those aren't mine.
- `src/audio/testSignal.ts` (the Workshop session's untracked WIP) currently fails `tsc` — flagging it so a repo-wide typecheck isn't mistaken for a Lane B regression. **My files are clean.** Demo is live at `http://localhost:5184/demo-player.html` (Seesaw + Teleport-to-arm buttons).