🏁 Weld the Skyweave forks, seat the structures, and land the finish - #70
Conversation
Four reported defects, all in the Claude Opus 5 Neon Horizon Racer. **The forks read as tears and pointed the wrong way.** The prompt hardcoded "steer left" and the commit test hardcoded `lateral < -1.6`, but both branches diverge to `+side` — screen right — as the file's own `sideOfMain` already computed. Both now resolve the side from the geometry, along with the fork signposts and the `takeBranch` hook. The junction itself is rebuilt: a new `weldJunction` pass blends each branch's derived bank and width into the main line's across the gore, so the abutting decks are exactly coplanar at the seam instead of meeting a few degrees rolled apart; the ring walk now starts and ends on the junction samples so no raced deck goes undrawn; rails ramp instead of switching, opening the main line across the split so there is no wall to cross and growing the branch's shared rail back out of the gore; the shared edge overlaps by 35 cm; and the gore is painted with amber hazard chevrons through a widened `aTrack.w`. **Structures floated.** `CanopyTruss` was a 50 m gantry whose legs ended 9 m below the deck, 13 m outboard of it, and `TRUSS_AT` dropped several inside junction spans; `BranchPylon` hovered 3.4 m past the deck edge over the void and was mirrored to both sides so its chevrons meant nothing. Both are re-authored in Blender to clamp the ribbon — deck-edge legs with an under-deck yoke on the truss, a bolted deck plate and under-hook on the pylon — and placement is junction-aware throughout. Every deck-mounted prop is now seated by scaling its authored deck-edge reference onto the local half-width. **The start line was invisible.** There was no start structure at all: gate 0 sat at `s = 40` and looked like the other eight, while the lap boundary was an untextured wrap at `s = 0`. A new `StartGantry` root — half again as tall as a checkpoint, with a chequered banner board — now stands on the boundary itself over a procedural chequer band that flashes on every crossing. **Finishing was silent.** `finishRacer` fired one arpeggio and one particle burst, the `else` swallowed any message, and the board waited for the whole field. Crossing now lands a chequer-topped banner, a screen flash, a fuller cadence and a hero-orbit camera, and the board arrives within a five-second outro hold, quoting a gap for any rival still out instead of a DNF that live play could never reach. Steering is gated once finished, and the final lap is called out on the HUD. Also fixed in passing: bollard cluster members re-check gate proximity for themselves, main-line anchors skip junctions as branch anchors already did, and props with no deck reference no longer scale to NaN. Blender: `StartGantry` added, `CanopyTruss` and `BranchPylon` re-authored, `skyweave-structures.glb` re-exported and the manifest recipe updated. Verification: - `npm run validate:game-assets` — 2 manifests, 4 files - `npm run test:game-assets` — 13 pass - `npm run lint` — clean - `npx playwright test tests/outrun-racer-opus-5.spec.ts` — 23 pass - `npx playwright test tests/games-load.spec.ts --grep outrun-racer` — 3 pass - `npm run build` — clean - `npm run inspect:threejs -- --game outrun-racer --model opus-5 --state active-play` — 110 calls / 290k triangles, down from 316k before this change Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a598afed6d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Fixes multiple gameplay, geometry, prop-placement, and finish-flow defects in the Claude Opus 5 “Neon Horizon Racer / Skyweave” Three.js game, and adds regression hooks/tests to prevent the fork/junction/structure/finish issues from reappearing.
Changes:
- Rebuilds junction handling (fork side resolution, welded seams, rail openings/ramps, hazard chevrons) and updates fork prompt + commit logic to match geometry.
- Reworks prop placement to be junction-aware, adds StartGantry + start-line band/flash, and improves finish flow (banner, outro hold, steering gating, hero camera).
- Expands Playwright coverage with new tests for fork prompts/commit direction, junction seam integrity, prop seating, and start/finish behavior.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| tests/outrun-racer-opus-5.spec.ts | Adds regression tests for fork prompt correctness, fork commitment, junction welding, prop seating, and start/finish flow. |
| public/games/outrun-racer/opus-5/index.html | Implements the core fixes: junction welding/rails, prop seating & reporting hooks, start-line structure/band/flash, and improved finish/outro behavior. |
| public/games/outrun-racer/opus-5/assets/manifest.json | Updates the authored-asset recipe/prompt and purpose to include StartGantry and new seating assumptions. |
| games-metadata.json | Updates LOC and asset byte counts for the opus-5 version metadata. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…amps Two review findings. **Codex, P2:** when the player crossed after all three rivals, `finishRacer` raised the banner and started the hero orbit, and then the `racers.every(...)` shortcut called `endRace()` in the very same fixed step — hiding both. The outro hold only ever protected finishes with someone still on track, which is to say it did not protect finishing last, the one place a player most needs telling that the race is over. `outroFrom` is only ever set once the player is in, so it now drives the whole end-of-race condition: `OUTRO_MIN` (2.8 s) with the field already home, `OUTRO_HOLD` (5 s) while rivals are still out. Covered by a new `crossLineLast()` hook and a regression test, confirmed failing against the previous condition. **Copilot:** `propReport()` recorded `overhang: 0` for `BranchPylon`, which was not a measurement — the pylon has no deck reference because it is not scaled onto the deck. Reporting a zero there meant a pylon could drift off the edge without the guard noticing, and the manifest's "every deck-mounted part is authored against a 9.8 m reference" was wrong about it. Deck-mounted props are now explicitly two families. Portals span the road and are reference-scaled, so they are measured by how far a footing overhangs the deck edge. Edge clamps sit beside the deck at a fixed size and bolt on with a plate reaching inboard, so they are measured by how far that plate grips the deck — `PROP_EDGE_GRIP` plus a `grip` figure in `propReport`, asserted along with the overhangs. Unmeasured families now report `null` rather than a flattering zero, and the test pins which family each prop belongs to. Manifest recipe reworded to match. Verification: - `npx playwright test tests/outrun-racer-opus-5.spec.ts` — 24 pass - `npm run validate:game-assets` — 2 manifests, 4 files - `npm run lint` — clean - `npm run update-metadata` — line count refreshed Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Four reported defects in the Claude Opus 5 Neon Horizon Racer, plus a few found alongside them.
1. The forks read as tears and pointed the wrong way
index.html:242hardcoded "steer left to commit" and the commit test hardcodedr.lateral < -1.6, but both branches diverge to+side— screen right — which the file's ownsideOfMain()already computed as+1. So the player was told to steer away from the fork and could only commit by hugging the wrong rail.The side is now resolved from the geometry once, in
buildCircuit, and read by the prompt, the commit test, the signposts and thetakeBranchhook. A newjunctionReport()hook projects a point inside each branch through the live chase camera, so a test can assert the wording against where the branch is actually drawn.The junction geometry is rebuilt:
weldJunctionblends each branch's derived bank and width into the main line's across the gore, unwrapping through the corkscrews' turn count. Bank was previously derived from each line's own curvature with its own smoothing window, so the two decks met a few degrees rolled apart — the visible tearing wedge. Residual roll at the seams is now< 1e-6.aTrack.w, weighted outboard so the racing line stays clean.2. Structures floated
CanopyTrusswas a 50 m gantry whose legs stopped 9 m below the deck plane and 13 m outboard of it — it never touched anything — andTRUSS_ATdropped several inside junction spans, where from a branch you see a detached gantry hanging in the void.BranchPylonhovered 3.4 m past the deck edge over nothing, mirrored to both sides so its chevrons pointed both ways.GateArchused fixed 0.86 / 0.68 scales, putting a 29 m span's footings ~3 m past the deck edge.RibbonAnchorslots had no junction exclusion, though branch slots did.Both offending assets are re-authored in Blender to clamp the ribbon — deck-edge legs plus an under-deck yoke on the truss, a bolted deck plate and under-hook on the pylon. Every deck-mounted prop is now seated by scaling its authored deck-edge reference onto the local half-width, and placement is junction-aware throughout. A
propReport()hook reports worst-case footing overhang per family so this cannot regress silently.3. The start line was invisible
There was no start structure at all: checkpoint gate 0 sat at
s = 40and looked identical to the other eight, while the actual lap boundary was an unmarked wrap ats = 0. A newStartGantryroot — half again as tall as a checkpoint, twin lattice columns over a lit portal, timing pods, and a 12×3 chequered banner board — now stands on the boundary itself, over a procedural chequer band with amber lips that flashes on every crossing. The nine checkpoints are re-spaced half a slot in so none crowds it.4. Finishing was silent
finishRacerfired one arpeggio and one particle burst; theelseat the lap accounting swallowed any on-screen message; andendRace()only ran once every racer had finished, so a winning player coasted to a stop under an unchanged HUD for as long as the slowest rival took. Steering also stayed live after finishing.Crossing now lands a chequer-topped
#finishBannerwith the placement and a live "waiting on" line, a screen flash, a multi-wave burst, a fuller audio cadence and a hero-orbit camera. The board arrives when the field is in or after a five-second outro hold, whichever comes first, quoting a metre gap for any rival still out instead of theDNFthat live play could never reach. Steering is gated once finished, and the final lap is called out on the HUD.Found alongside
s + k * 9offset could walk one into a gate mouth.NaN— this had made the fork signposts invisible until a visual check caught it.Assets
Blender 5.2.0 LTS via Blender Assets MCP:
StartGantryadded,CanopyTrussandBranchPylonre-authored,skyweave-structures.glbre-exported (485 KiB → 1.17 MiB, cap 6 MiB), manifest recipe updated. Bevels reduced to one segment on the new large parts so the deck-clamped truss costs about what the floating one did.Verification
npm run validate:game-assetsnpm run test:game-assetsnpm run lintnpx playwright test tests/outrun-racer-opus-5.spec.tsnpx playwright test tests/games-load.spec.ts --grep outrun-racernpm run buildnpm run inspect:threejs -- --game outrun-racer --model opus-5 --state active-playnpm run sync:three-runtime -- --checkreports the vendored runtime out of sync on this Windows checkout; the files are byte-identical tonode_modules/three@0.185.1apart from CRLF line endings, andpublic/vendoris untouched by this branch.Visual review at 1280×720 through the sandboxed play page covered all four defects: both fork approaches (prompt direction, welded seam, hazard-striped gore), inside a branch mid-junction (nothing hanging beside the other deck), the start gantry and chequer band from the grid, and the crossing in place plus the results board.
🤖 Generated with Claude Code