From dc0df9122e7684c1f963d49e083a500da8941ee1 Mon Sep 17 00:00:00 2001 From: "R3AL.CH1CK3N" Date: Thu, 6 Aug 2026 08:45:27 -0400 Subject: [PATCH] docs: project CLAUDE.md for native-Windows Claude Code handoff Pure ASCII (PS 5.1 reads non-ASCII as ANSI and desyncs the parser). Records the aux-lane suppression invariant, the verified 6e50f97 baseline, the read/write channel split, and the probe scripts that check each metric. --- CLAUDE.md | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f4e46e4 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,139 @@ +# CLAUDE.md -- Tokyo Wangan Racing + +Guidance for Claude Code running **natively on `windows-gpu`**, the same machine +as Roblox Studio. Pure ASCII on purpose (PowerShell 5.1 reads non-ASCII as ANSI +and desyncs the parser). + +--- + +## 1. Read this before touching MapBuilder + +`src/server/MapBuilder.luau` generates the map procedurally. The user also edits +geometry **by hand in Studio**. Those two facts collide, and that collision is +the single most important thing about this repo: + +> **A rebuild regenerates anything the source still describes.** +> If the user deleted geometry by hand and you rebuild without teaching the +> source about that deletion, you silently put it back. + +The user WILL notice, immediately, and will say so ("you just added back the X +that I deleted"). When that happens: **stop editing, run a read-only probe, +report exact numbers.** Do not "fix" it with another rebuild. + +### The live invariant: aux-lane suppression + +```lua +local AUX_SUPPRESS_FROM = 525 -- samples 525..550 have NO aux lane +local AUX_SUPPRESS_TO = 550 -- because the user deleted that run by hand +local AUX_BLEND = 5 -- smoothstep width ramp, do not hard-cut +``` + +- **Do not remove or widen this range.** Re-enabling it resurrects deleted geometry. +- `AUX_BLEND = 5` is not cosmetic. A hard cut produced a **26-stud lateral fence + jog**. The smoothstep removes it. +- The parapet is force-closed across the same range (~line 1031). Normally the + parapet OPENS along a speed-change lane because the aux lane re-fences the + outer edge -- with no aux lane there is nothing to re-fence with, leaving the + deck edge bare. That was the measured barrier gap at samples 527..548. + +Any change touching aux lanes, parapets, or barriers must re-run +`tools/probe_regression.luau` and match the baseline below. + +--- + +## 2. Verified baseline (commit 6e50f97) + +Measured in the live datamodel, not inferred from source: + +| Metric | Value | +|---|---| +| total parts | 16788 | +| PAWestSlip | 60 segs, 34.4 deg total bend, worst 1.4, 0 kinks >5 | +| PAEastSlip | 60 segs, 30.7 deg total bend, worst 1.3, 0 kinks >5 | +| AuxLane parts | 30 (samples 525-550 deliberately absent) | +| barrier coverage | 823 samples, 0 unguarded | +| fence jogs >10 studs | 0 | + +`AuxLane = 30` is the **user's hand-edited count**, not the source's original 52. +If a probe reports 52, a rebuild has undone the suppression -- that is a +regression, not progress. + +--- + +## 3. Two channels, different jobs + +``` +[A] MCP bridge (roblox_studio) -> READ run Luau in Studio, measure, screenshot +[B] Rojo -> WRITE push .luau source into Studio (~1 s) +``` + +**Use [A] to verify what [B] did. Never assume a sync landed.** + +Rojo syncs **scripts, not built geometry**. Editing MapBuilder replaces the +ModuleScript instantly, but `workspace.Map` still holds parts from a PREVIOUS +`build()` run. The map looks stale until you re-run the build. Do not tell the +user "you'll see it live" about map geometry. + +**Rojo version must match the Studio plugin.** The plugin auto-updates from the +Marketplace without asking. Server older than plugin fails the handshake with a +cryptic `attempt to index number with 'protocolVersion'`. Both are pinned at +**7.7.0** (`rokit.toml`). If the user reports a connect error, check this first. + +--- + +## 4. Workflow + +```bash +make check # stylua --check + selene + rojo build +make build # rojo build --output build.rbxl +make serve # rojo serve (Studio: Rojo -> Connect) +make fmt # stylua src/ +``` + +Probe scripts in `tools/` are **read-only** -- they measure the live datamodel +and never build. Run them through the MCP bridge. + +| Script | Answers | +|---|---| +| `probe_regression.luau` | full baseline check vs the table above | +| `verify_auxlane.luau` | is the 525-550 suppression intact? | +| `verify_slips.luau` | slip-road bend angles / kink count | +| `probe_barriergap.luau` | any unguarded deck edge? | +| `probe_jog.luau` | lateral fence jogs | + +--- + +## 5. Hard-won rules + +- **Measure, then fix.** Do not infer a bug from symptoms. One inverted + convention can produce three unrelated-looking symptoms; fixing each symptom + leaves the root cause intact. +- **A metric derived from a constant cannot fail.** Ask: would this number + differ between the broken and fixed build? If not, it is not a test. +- **An empty result set must FAIL, never pass.** Count what you actually + exercised; `if tested == 0 then return "NOTHING TESTED -- FAILURE" end`. +- **Verification in Play mode proves nothing.** Play is a disposable sandbox + discarded on stop. Verify in Edit mode. +- **require() caches stale bytecode after a Rojo edit.** The cache still holds + old bytecode even though `.Source` is new -- no error, no warning. Clone the + module and require the clone. +- **Enumerate part names, don't just count.** A raw total hides partial removals + (deleted the tall barrier, missed the kerb). Tally what should be gone vs + what should remain, and report both. +- **AutoRecovery places are silently stale.** After a crash Studio reopens + `*_AutoRecovery_1.rbxl` holding pre-crash state. Check the title bar. +- **Creator Store assets: 50+ scripts or 1M+ tris is zero-tolerance.** Get exact + counts before inserting anything. + +--- + +## 6. Shell + +Git Bash (`C:\Program Files\Git\bin\bash.exe`) is present -- prefer it. +PowerShell over a non-interactive pipe mangles quoting. `&` is not a statement +separator in PowerShell. When PowerShell is unavoidable non-interactively, use +`-EncodedCommand` with UTF-16LE base64. + +`StudioMCP.exe` lives inside the versioned Studio install and **moves on every +update**. Never hardcode it; `~/claude-tools/studio-mcp.bat` resolves it +dynamically.