Skip to content

redesign(1.0): single-branch 1.0 rewrite#278

Open
jbdevprimary wants to merge 6 commits into
mainfrom
redesign/1.0
Open

redesign(1.0): single-branch 1.0 rewrite#278
jbdevprimary wants to merge 6 commits into
mainfrom
redesign/1.0

Conversation

@jbdevprimary
Copy link
Copy Markdown
Collaborator

@jbdevprimary jbdevprimary commented Apr 24, 2026

Overview

Draft — single-branch 1.0 rewrite. Replaces the phase-by-phase approach: the phase PRs would have forced every affected file to be rewritten multiple times (each phase inherited the previous phase's still-wrong shape), burning review cycles on intermediate wrongness.

Instead: logical commits land directly on this branch. Each push triggers a fresh review round. Integration happens once, when the whole thing's coherent. One squash-merge to main.

Follows:

  • docs/DESIGN.md — canonical game spec (identity, dual sanity meters, popup choreography, maze guarantees, cockpit layout, landing unification, ECS boundary, config package layout).
  • docs/assets/ASSET_GENERATION.md — asset-by-asset audit + generation plan.
  • docs/plans/2026-04-24-beppo-1.0-redesign.prq.md — full PRD (sequenced as phases there; this PR executes them as logical commits instead of PRs).

Commits (running log, appended as work lands)

  • refactor(landing): replace 3D landing with 2D tent backdrop + Beppo poster — deletes public/assets/3d/ tree (~28 MB), src/assets/catalog.ts, scripts/{build-catalog,salvage-glbs}.sh. Reworks HeroCanvas.tsx + Villains.tsx to pure-CSS 2D using a new src/lib/assetPath helper. 535 tests still green.

Remaining scope

Executed as additional commits on this branch. Reviewers can start eyeing commit 1 while these are in flight:

  • Asset reorg into public/assets/images/{floors,walls,ceilings,items,drops,slides,popups,ui}/ with final names (strip item_, paper_mache_, vintage_circus_tent_canvas_texture; reclassify velvet_drape + ringmaster_banners + tent_canvas as ceilings).
  • config/raw/ + config/compiled/ package with every tunable (sanity rates, popup scripts, item effects, asset manifest, palette, strings).
  • Koota ECS (src/ecs/) replaces Zustand. Jester, Tubeman, Clown entities — no "Villains" abstraction anywhere in game code.
  • Maze generator rewrite with 8 guarantees + headless golden-path sim.
  • Ceiling geometry + OSB-boarded drops/slides with corner pinheads + drop/slide animation.
  • Scripted popup choreography (jester follow system, tubeman x2, final clown + ticket branch).
  • Item effects wired through ECS actions per DESIGN.md table.
  • Single-route landing (/ landing, /play scene — no MainMenu overlay), Help button replaces forced tutorial.
  • Bottom-anchor cockpit at 20-25% viewport height.
  • Balance sim in nightly CI.
  • Rename landing/Villains.tsxBeppoReveal.tsx and HeroCanvas.tsxHeroBackdrop.tsx as part of the final integration pass.

Test plan

  • pnpm typecheck, pnpm lint, pnpm test (535 pass), pnpm build — all green
  • CI green on this PR
  • Visual QA on deployed preview after each commit
  • Golden-path sim green across 1000 seeds
  • Deployed build remains playable on GitHub Pages after each commit

Kept as draft until the game is fully playable end-to-end on this branch. Converted to ready-for-review for the final integration pass.

Summary by CodeRabbit

  • Documentation

    • Updated project layout documentation to reflect reorganized assets and components structure.
  • Chores

    • Removed 3D asset catalog system and related build scripts.
    • Simplified landing page hero visuals to use CSS-based effects instead of 3D rendering.
    • Added asset path utilities for improved resource handling.

…oster

Redesign 1.0 opening commit. The 3D asset experiment was never
finished — 28 MB of preview GLBs in public/assets/3d/ that no
playable path consumed. docs/DESIGN.md commits the game to the
2D paper-pinned identity, so both the 3D tree and the r3f-based
landing components go.

Removed:
- public/assets/3d/ entire tree (~28 MB, 86 files)
- src/assets/catalog.ts + catalog.test.ts (the 3D manifest + tests)
- src/assets/ directory (empty after catalog removal)
- scripts/build-catalog.sh + scripts/salvage-glbs.sh (rebuilders for
  the deleted manifest)

Rewritten to 2D:
- src/components/landing/HeroCanvas.tsx — was an r3f <Canvas> with
  useGLTF('clown_car'), headlights, and fog. Now a pure-CSS
  tent-canvas backdrop over an animated amber headlight-glow pool.
  Preserves the `{ active }` prop so Hero.tsx's lazy import works
  unchanged. HeroCanvas chunk drops to ~1.17 kB; r3f bundle shrinks
  by ~86 kB as a side effect because useGLTF is no longer imported
  on the landing path.
- src/components/landing/Villains.tsx — was a second r3f <Canvas>
  rotating beppo_clown.glb next to pull-quotes. Now a static <img>
  poster of popup_clown.png with halftone-style amber vignette and
  an optional CSS idle sway that honors prefers-reduced-motion.
  Naming note: still called "Villains" for continuity with the
  current landing composition, flagged in the file for the later
  rename to BeppoReveal (docs/DESIGN.md: the game has no "villains"
  concept, Beppo is a scripted three-act boss).

Added:
- src/lib/assetPath.ts — normalizedBaseUrl() + assetPath(relative)
  helpers that resolve public-asset URLs against the Vite/Astro
  configured base path. Used by both landing components so the
  base-join logic isn't duplicated.
- src/lib/assetPath.test.ts — 6 unit tests covering root base,
  subpath base, subpath-without-trailing-slash, and
  leading-slash-on-relative-path cases.

New CSS keyframes in src/index.css:
- beppo-sway (Villains poster idle drift)
- hero-headlight-sweep (headlight glow pool drift)
Both collapse to 0.01ms under the existing
@media (prefers-reduced-motion: reduce) block.

README.md project-layout block updated to reflect the new shape
(no more src/assets/, no more public/assets/3d/).

pnpm typecheck + lint + test (535 pass) + build all green. No
gameplay code touched. Part of redesign/1.0 single-branch rewrite
per docs/plans/2026-04-24-beppo-1.0-redesign.prq.md.
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 2026

Warning

Rate limit exceeded

@jbdevprimary has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 2 minutes and 42 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 2 minutes and 42 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 42725a6c-78c2-4024-9581-b90dce0ef801

📥 Commits

Reviewing files that changed from the base of the PR and between 7d6ea59 and b91e933.

⛔ Files ignored due to path filters (36)
  • public/assets/generated_images/slide_spiked_door.png is excluded by !**/*.png
  • public/assets/images/ceilings/circus_tent.png is excluded by !**/*.png
  • public/assets/images/ceilings/ringmaster_banners.png is excluded by !**/*.png
  • public/assets/images/ceilings/velvet_drape.png is excluded by !**/*.png
  • public/assets/images/drops/cage.png is excluded by !**/*.png
  • public/assets/images/drops/chain.png is excluded by !**/*.png
  • public/assets/images/drops/net.png is excluded by !**/*.png
  • public/assets/images/floors/blood_stained_concrete.png is excluded by !**/*.png
  • public/assets/images/floors/circus_sawdust.png is excluded by !**/*.png
  • public/assets/images/floors/creaky_boardwalk.png is excluded by !**/*.png
  • public/assets/images/floors/dark_muddy_grass.png is excluded by !**/*.png
  • public/assets/images/floors/greasepaint_smear.png is excluded by !**/*.png
  • public/assets/images/floors/muddy_straw.png is excluded by !**/*.png
  • public/assets/images/floors/ticket_litter.png is excluded by !**/*.png
  • public/assets/images/floors/worn_carnival_tile.png is excluded by !**/*.png
  • public/assets/images/items/boxing_glove.png is excluded by !**/*.png
  • public/assets/images/items/circus_ticket.png is excluded by !**/*.png
  • public/assets/images/items/exit_key.png is excluded by !**/*.png
  • public/assets/images/items/hook.png is excluded by !**/*.png
  • public/assets/images/items/key.png is excluded by !**/*.png
  • public/assets/images/items/lamp.png is excluded by !**/*.png
  • public/assets/images/items/mallet.png is excluded by !**/*.png
  • public/assets/images/items/net.png is excluded by !**/*.png
  • public/assets/images/items/pitcher.png is excluded by !**/*.png
  • public/assets/images/items/scissors.png is excluded by !**/*.png
  • public/assets/images/items/souvenir_pin.png is excluded by !**/*.png
  • public/assets/images/popups/clown.png is excluded by !**/*.png
  • public/assets/images/popups/jester.png is excluded by !**/*.png
  • public/assets/images/popups/tubeman.png is excluded by !**/*.png
  • public/assets/images/slides/carousel.png is excluded by !**/*.png
  • public/assets/images/slides/guillotine.png is excluded by !**/*.png
  • public/assets/images/walls/backstage_canvas.png is excluded by !**/*.png
  • public/assets/images/walls/dark_hedge.png is excluded by !**/*.png
  • public/assets/images/walls/rusted_metal_grid.png is excluded by !**/*.png
  • public/assets/images/walls/tattered_fabric.png is excluded by !**/*.png
  • public/assets/images/walls/weathered_wood_planks.png is excluded by !**/*.png
📒 Files selected for processing (20)
  • .claude/settings.json
  • README.md
  • public/assets/asset-catalog.json
  • scripts/redesign/rewrite-catalog.mjs
  • src/components/game/Collectibles.test.tsx
  • src/components/game/Collectibles.tsx
  • src/components/game/Maze.test.tsx
  • src/components/game/Maze.tsx
  • src/components/landing/BeppoReveal.tsx
  • src/components/landing/HeroCanvas.tsx
  • src/components/landing/Landing.tsx
  • src/components/landing/Mechanics.tsx
  • src/game/assetCatalog.test.ts
  • src/game/assetCatalog.ts
  • src/game/spawnPlan.test.ts
  • src/game/spawnPlan.ts
  • src/game/textures.test.ts
  • src/game/textures.ts
  • src/lib/assetPath.test.ts
  • src/lib/assetPath.ts
📝 Walkthrough

Walkthrough

This PR removes the 3D asset catalog generation pipeline (build scripts, JSON manifests, TypeScript catalog) and replaces three.js/r3f-based 3D rendering with simpler 2D CSS and image-based assets. New runtime asset path utilities replace the static catalog approach.

Changes

Cohort / File(s) Summary
README & Configuration
README.md
Updated project layout documentation to reflect asset structure reorganization; added references to landing/ directory and generated_images//textures/ subdirectories.
Asset Catalog & Metadata (Removed)
public/assets/3d/asset-catalog.json, public/assets/3d/.../{manifest,metadata}.json
Deleted the top-level asset catalog and all per-asset metadata/manifest JSON files across collectible, obstacle, performer, vehicle, and villain categories (42 JSON files total).
Build Scripts (Removed)
scripts/build-catalog.sh, scripts/salvage-glbs.sh
Deleted TypeScript catalog generator and asset extraction scripts that previously regenerated src/assets/catalog.ts and managed 3D asset publishing.
Generated Asset Catalog (Removed)
src/assets/catalog.ts, src/assets/catalog.test.ts
Removed static asset catalog module, exported type definitions (AssetCategory, AssetEntry), URL resolver (assetUrl), and test coverage for catalog integrity.
Asset Path Utilities (New)
src/lib/assetPath.ts, src/lib/assetPath.test.ts
Added runtime asset path resolution using Vite's BASE_URL, with normalizedBaseUrl() and assetPath() functions and test coverage.
Component Updates
src/components/landing/HeroCanvas.tsx, src/components/landing/Villains.tsx
Converted 3D rendered canvases to 2D CSS/image-based backdrops; removed three.js/r3f dependencies and GLTF preloading; added CSS animation support for reduced-motion users.
CSS Animations (New)
src/index.css
Added two keyframe animations: beppo-sway (side-to-side translate with scale) and hero-headlight-sweep (animated background-position for headlight effect).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested labels

game/rendering, synthesis

Poem

🎪 Away with catalogs and GLB files vast,
Two dimensions rise where three.js held fast—
CSS swaying, headlights sweep and glow,
Runtime paths now guide where assets go.
Build scripts vanish; the stage stays the same! ✨

🚥 Pre-merge checks | ✅ 5 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title uses 'redesign(1.0)' prefix which does not conform to the conventional commit format requirement of feat:, fix:, docs:, chore:, refactor:, or test: prefix. Update the title to follow conventional commit format, e.g., 'refactor: single-branch 1.0 rewrite' or 'refactor(1.0): single-branch 1.0 rewrite' where the scope is optional.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 60.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Security Check ✅ Passed The PR contains no hardcoded secrets, API keys, or credentials. Only build-time configuration and standard React practices are used without dangerous patterns.
R3f Performance Check ✅ Passed PR eliminates R3F entirely by converting HeroCanvas and Villains to pure CSS/DOM implementations with no render-loop object creation or three.js dependencies remaining.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch redesign/1.0

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added game/rendering Rendering/graphics changes synthesis labels Apr 24, 2026
coderabbitai[bot]
coderabbitai Bot previously requested changes Apr 24, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Around line 87-90: The README's public/assets tree omits the runtime asset
manifest; add an entry for public/assets/asset-catalog.json and a short note
that this JSON is the runtime asset manifest used by the game. Update the assets
tree under the public/assets section to include "asset-catalog.json" and note
its purpose/location so it isn’t removed; reference that it is consumed by
src/game/assetCatalog.ts and relied upon by src/components/game/Scene.tsx and
src/game/spawnPlan.ts so maintainers know it’s required at runtime.

In `@src/lib/assetPath.ts`:
- Around line 18-19: The code that builds the asset URL only strips a single
leading slash from relative (variable name "relative") so inputs like
"//assets/foo.png" yield double slashes; update the cleaning step in
src/lib/assetPath.ts to remove all leading slashes (e.g., trim leading '/'
characters using a regex or loop) before concatenating with normalizedBaseUrl(),
keeping the same return construction that uses normalizedBaseUrl() and the
cleaned variable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: c73bfc00-e3ea-45b5-bb99-eee75a4f21c6

📥 Commits

Reviewing files that changed from the base of the PR and between 409ecff and 7d6ea59.

📒 Files selected for processing (92)
  • README.md
  • public/assets/3d/asset-catalog.json
  • public/assets/3d/collectible/broken_pocket_watch/manifest.json
  • public/assets/3d/collectible/broken_pocket_watch/metadata.json
  • public/assets/3d/collectible/broken_pocket_watch/preview.glb
  • public/assets/3d/collectible/crumpled_playbill/manifest.json
  • public/assets/3d/collectible/crumpled_playbill/metadata.json
  • public/assets/3d/collectible/crumpled_playbill/preview.glb
  • public/assets/3d/collectible/faded_photograph/manifest.json
  • public/assets/3d/collectible/faded_photograph/metadata.json
  • public/assets/3d/collectible/faded_photograph/preview.glb
  • public/assets/3d/collectible/paper_mache_elephant/manifest.json
  • public/assets/3d/collectible/paper_mache_elephant/preview.glb
  • public/assets/3d/collectible/paper_mache_lion/manifest.json
  • public/assets/3d/collectible/paper_mache_lion/metadata.json
  • public/assets/3d/collectible/paper_mache_lion/preview.glb
  • public/assets/3d/collectible/paper_mache_seal/manifest.json
  • public/assets/3d/collectible/paper_mache_seal/metadata.json
  • public/assets/3d/collectible/paper_mache_seal/preview.glb
  • public/assets/3d/collectible/rusty_key/manifest.json
  • public/assets/3d/collectible/rusty_key/metadata.json
  • public/assets/3d/collectible/rusty_key/preview.glb
  • public/assets/3d/collectible/torn_ticket/manifest.json
  • public/assets/3d/collectible/torn_ticket/metadata.json
  • public/assets/3d/collectible/torn_ticket/preview.glb
  • public/assets/3d/obstacle/broken_carousel_horse/manifest.json
  • public/assets/3d/obstacle/broken_carousel_horse/metadata.json
  • public/assets/3d/obstacle/broken_carousel_horse/preview.glb
  • public/assets/3d/obstacle/broken_mirror_maze/manifest.json
  • public/assets/3d/obstacle/broken_mirror_maze/metadata.json
  • public/assets/3d/obstacle/broken_mirror_maze/preview.glb
  • public/assets/3d/obstacle/burning_hoop/manifest.json
  • public/assets/3d/obstacle/burning_hoop/metadata.json
  • public/assets/3d/obstacle/burning_hoop/preview.glb
  • public/assets/3d/obstacle/collapsed_bleachers/manifest.json
  • public/assets/3d/obstacle/collapsed_bleachers/metadata.json
  • public/assets/3d/obstacle/collapsed_bleachers/preview.glb
  • public/assets/3d/obstacle/falling_tent_pole/manifest.json
  • public/assets/3d/obstacle/falling_tent_pole/metadata.json
  • public/assets/3d/obstacle/falling_tent_pole/preview.glb
  • public/assets/3d/obstacle/overturned_popcorn_cart/manifest.json
  • public/assets/3d/obstacle/overturned_popcorn_cart/metadata.json
  • public/assets/3d/obstacle/overturned_popcorn_cart/preview.glb
  • public/assets/3d/obstacle/scattered_hay_bales/manifest.json
  • public/assets/3d/obstacle/scattered_hay_bales/metadata.json
  • public/assets/3d/obstacle/scattered_hay_bales/preview.glb
  • public/assets/3d/performer/carnival_barker/manifest.json
  • public/assets/3d/performer/carnival_barker/metadata.json
  • public/assets/3d/performer/carnival_barker/preview.glb
  • public/assets/3d/performer/fire_breather/manifest.json
  • public/assets/3d/performer/fire_breather/metadata.json
  • public/assets/3d/performer/fire_breather/preview.glb
  • public/assets/3d/performer/juggler/manifest.json
  • public/assets/3d/performer/juggler/preview.glb
  • public/assets/3d/performer/lion_tamer/manifest.json
  • public/assets/3d/performer/lion_tamer/metadata.json
  • public/assets/3d/performer/lion_tamer/preview.glb
  • public/assets/3d/performer/magician/manifest.json
  • public/assets/3d/performer/magician/metadata.json
  • public/assets/3d/performer/magician/preview.glb
  • public/assets/3d/performer/sword_swallower/manifest.json
  • public/assets/3d/performer/sword_swallower/metadata.json
  • public/assets/3d/performer/sword_swallower/preview.glb
  • public/assets/3d/performer/tightrope_walker/manifest.json
  • public/assets/3d/performer/tightrope_walker/metadata.json
  • public/assets/3d/performer/tightrope_walker/preview.glb
  • public/assets/3d/performer/trapeze_artist/manifest.json
  • public/assets/3d/performer/trapeze_artist/metadata.json
  • public/assets/3d/performer/trapeze_artist/preview.glb
  • public/assets/3d/vehicle/circus_wagon/manifest.json
  • public/assets/3d/vehicle/circus_wagon/preview.glb
  • public/assets/3d/vehicle/clown_car/manifest.json
  • public/assets/3d/vehicle/clown_car/metadata.json
  • public/assets/3d/vehicle/clown_car/preview.glb
  • public/assets/3d/vehicle/unicycle/manifest.json
  • public/assets/3d/vehicle/unicycle/preview.glb
  • public/assets/3d/villain/beppo_clown/manifest.json
  • public/assets/3d/villain/beppo_clown/metadata.json
  • public/assets/3d/villain/beppo_clown/preview.glb
  • public/assets/3d/villain/mime/manifest.json
  • public/assets/3d/villain/mime/preview.glb
  • public/assets/3d/villain/ringmaster/manifest.json
  • public/assets/3d/villain/ringmaster/preview.glb
  • scripts/build-catalog.sh
  • scripts/salvage-glbs.sh
  • src/assets/catalog.test.ts
  • src/assets/catalog.ts
  • src/components/landing/HeroCanvas.tsx
  • src/components/landing/Villains.tsx
  • src/index.css
  • src/lib/assetPath.test.ts
  • src/lib/assetPath.ts
💤 Files with no reviewable changes (57)
  • public/assets/3d/collectible/paper_mache_lion/metadata.json
  • public/assets/3d/performer/carnival_barker/metadata.json
  • public/assets/3d/collectible/broken_pocket_watch/metadata.json
  • public/assets/3d/performer/lion_tamer/metadata.json
  • public/assets/3d/collectible/paper_mache_seal/manifest.json
  • public/assets/3d/obstacle/broken_mirror_maze/manifest.json
  • public/assets/3d/obstacle/scattered_hay_bales/manifest.json
  • public/assets/3d/collectible/paper_mache_lion/manifest.json
  • public/assets/3d/collectible/broken_pocket_watch/manifest.json
  • public/assets/3d/collectible/torn_ticket/manifest.json
  • public/assets/3d/obstacle/broken_mirror_maze/metadata.json
  • public/assets/3d/performer/tightrope_walker/metadata.json
  • public/assets/3d/collectible/paper_mache_elephant/manifest.json
  • public/assets/3d/collectible/torn_ticket/metadata.json
  • public/assets/3d/vehicle/clown_car/manifest.json
  • public/assets/3d/vehicle/unicycle/manifest.json
  • public/assets/3d/collectible/faded_photograph/metadata.json
  • public/assets/3d/collectible/rusty_key/metadata.json
  • public/assets/3d/obstacle/burning_hoop/manifest.json
  • public/assets/3d/asset-catalog.json
  • public/assets/3d/obstacle/falling_tent_pole/manifest.json
  • public/assets/3d/performer/trapeze_artist/metadata.json
  • public/assets/3d/vehicle/clown_car/metadata.json
  • public/assets/3d/performer/fire_breather/metadata.json
  • public/assets/3d/collectible/crumpled_playbill/manifest.json
  • public/assets/3d/collectible/paper_mache_seal/metadata.json
  • public/assets/3d/performer/fire_breather/manifest.json
  • public/assets/3d/obstacle/collapsed_bleachers/metadata.json
  • public/assets/3d/obstacle/overturned_popcorn_cart/manifest.json
  • public/assets/3d/obstacle/collapsed_bleachers/manifest.json
  • public/assets/3d/obstacle/scattered_hay_bales/metadata.json
  • public/assets/3d/performer/trapeze_artist/manifest.json
  • public/assets/3d/obstacle/broken_carousel_horse/manifest.json
  • src/assets/catalog.test.ts
  • public/assets/3d/performer/carnival_barker/manifest.json
  • public/assets/3d/obstacle/falling_tent_pole/metadata.json
  • public/assets/3d/performer/lion_tamer/manifest.json
  • public/assets/3d/collectible/rusty_key/manifest.json
  • public/assets/3d/performer/magician/metadata.json
  • public/assets/3d/villain/beppo_clown/metadata.json
  • public/assets/3d/villain/ringmaster/manifest.json
  • scripts/build-catalog.sh
  • public/assets/3d/obstacle/overturned_popcorn_cart/metadata.json
  • public/assets/3d/performer/sword_swallower/metadata.json
  • public/assets/3d/performer/sword_swallower/manifest.json
  • public/assets/3d/performer/juggler/manifest.json
  • public/assets/3d/performer/tightrope_walker/manifest.json
  • scripts/salvage-glbs.sh
  • public/assets/3d/vehicle/circus_wagon/manifest.json
  • public/assets/3d/villain/mime/manifest.json
  • public/assets/3d/performer/magician/manifest.json
  • public/assets/3d/collectible/faded_photograph/manifest.json
  • src/assets/catalog.ts
  • public/assets/3d/obstacle/burning_hoop/metadata.json
  • public/assets/3d/collectible/crumpled_playbill/metadata.json
  • public/assets/3d/obstacle/broken_carousel_horse/metadata.json
  • public/assets/3d/villain/beppo_clown/manifest.json

Comment thread README.md
Comment thread src/lib/assetPath.ts Outdated
Your Name added 2 commits April 24, 2026 12:31
Reshapes the asset tree and asset-catalog.json to the redesign/1.0
taxonomy documented in docs/DESIGN.md + docs/assets/ASSET_GENERATION.md.
The catalog here is *provisional* — the canonical source of truth for
gameplay behavior and placement rules will land in a proper
archetype/definition config package in the Turboplan work. This
commit keeps the engine compilable against the new taxonomy while
that larger refactor is in flight.

File moves (35 renames + 1 deletion):
- public/assets/generated_images/ (flat) →
  public/assets/images/{floors,walls,ceilings,items,drops,slides,popups}/
- `slide_spiked_door.png` deleted (cut during design review —
  `items/souvenir_pin.png` didn't have a clean mechanical
  resolver fit for the guillotine, so we trimmed to 5 blockade arts
  aligned 1-to-1 with 5 resolver items)
- Three files reclassified from walls to ceilings:
  `wall_velvet_drape`, `wall_ringmaster_banners`,
  `vintage_circus_tent_canvas` (the last being both the outer-ring
  ceiling AND the landing-page background — no duplicated file,
  consumers share the same path)
- Items renamed to drop legacy prefixes: `item_*` → bare name,
  `paper_mache_*_item` → `exit_key` / `circus_ticket`, `item_pin` →
  `souvenir_pin`

Catalog schema rewrite (public/assets/asset-catalog.json):
- Buckets: floors[], walls[], ceilings[], items[], drops[],
  slides[], popups[]
- Each asset carries `id`, `fileName`, `path` (category-relative),
  `prompt`, `aspectRatio`
- Floors/walls/ceilings add `zoneBias: 'outer' | 'outer-mid' |
  'inner-mid' | 'inner'`
- Items add `role: 'resolver' | 'sanity' | 'mitigator' | 'special'`
  plus `resolverOf` / `restores` / `mitigates` / `effect`
- Drops/slides add `resolverItem: string` — the id of the item that
  opens this blockade
- Popups add `script: 'jester' | 'tubeman' | 'clown'`
- `ui: { landingBackground }` points at the shared tent image
- Regenerated via scripts/redesign/rewrite-catalog.mjs (committed
  as provenance of the one-shot migration; safe to delete once the
  archetype/definition package lands)

Type rewrites (src/game/assetCatalog.ts):
- New discriminated types: FloorAsset, WallAsset, CeilingAsset,
  ItemAsset, DropAsset, SlideAsset, PopupAsset — each extends a
  shared CatalogImageAsset
- ASSET_IMAGE_BASE now points at /assets/images/ (via assetPath
  helper)
- New imageUrl() helper joins category-relative path to the base

Consumer updates:
- src/game/spawnPlan.ts: blockades sourced from drops+slides;
  resolvers sourced from items.filter(role='resolver'); pairings
  matched via resolverItem <-> resolverOf instead of the old
  "unlock-<nodeId>" placeholder
- src/game/textures.ts: thin surface kept for non-migrated
  consumers; paths updated to assets/images/<category>/<id>.png
- src/components/game/Maze.tsx: reads wall/ceiling/floor pools from
  new schema buckets
- src/components/game/Collectibles.tsx: reads items pool from new
  schema; asset.path replaces asset.fileName + manual concat
- src/components/landing/{HeroCanvas,Villains}.tsx: updated to
  new paths

Test rewrites:
- src/game/assetCatalog.test.ts: rewritten for new schema; tests
  constants, imageUrl, loadAssetCatalog lifecycle, pickSeededAsset
- src/game/spawnPlan.test.ts: rewritten with new mock factories for
  the drops/slides/resolvers shape; covers null-catalog,
  empty-blockade, empty-resolver, pairing, collectible/blockade
  correspondence, and determinism
- src/game/textures.test.ts: path assertions updated
  (generated_images → images)
- src/components/game/{Maze,Collectibles}.test.tsx: mocks updated
  to new schema

Typecheck + lint + build all green.
Two minor findings from the first CodeRabbit review pass on PR #278:

- src/lib/assetPath.ts: assetPath() only stripped a single leading
  slash, so "//assets/foo.png" still produced a double-slash URL
  after joining. Switched to `replace(/^\/+/, '')` so runs of
  leading slashes collapse. Added a regression test covering "//"
  and "///" prefixes.
- README.md: the Project Layout block described public/assets/ but
  omitted asset-catalog.json, which is still fetched at runtime by
  src/game/assetCatalog.ts and src/game/spawnPlan.ts. Added it
  explicitly with a one-line description; also renamed the tree
  entry from generated_images/ to images/ to reflect the taxonomy
  rewrite that landed in the previous commit.
@jbdevprimary jbdevprimary dismissed coderabbitai[bot]’s stale review April 24, 2026 17:34

Both findings addressed in commit 6c9d71a: assetPath multi-slash strip + regression test, README project-layout includes asset-catalog.json.

@jbdevprimary jbdevprimary marked this pull request as ready for review April 24, 2026 17:34
Copilot AI review requested due to automatic review settings April 24, 2026 17:34
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

Your Name added 3 commits April 24, 2026 12:52
CI on PR #278 surfaced two real issues from the taxonomy rewrite plus
a long-running infrastructure nuisance:

1. **textures.test.ts** — 7 tests still asserted on the OLD filenames
   (paper_mache_circus_ticket_item.png, etc.) and on the old
   "paper mâché" description copy. The rename in the asset reorg
   broke these. Updated to assert new category-scoped paths
   (items/circus_ticket.png, items/exit_key.png, floors/...,
   ceilings/..., walls/...) and dropped the now-obsolete "paper
   mâché" description substring check.

2. **Playwright smoke — React duplicate-key warning fails the
   console-errors assertion.** spawnPlan.buildSpawnPlan was using the
   resolver item id (e.g. "mallet") as the collectible.id. Two
   blockades needing the same resolver produced two collectibles
   with the same id, and React rendering them via
   `<Collectible key={item.id} />` emitted "Encountered two children
   with the same key" to the console, which e2e treats as a failure.
   Collectibles now use a per-placement id (`item-<nodeId>`); the
   resolver-item id is still carried as `name` and the blockade
   pairing still works via `unlocksBlockadeId`. Test updated to
   assert collectible-id uniqueness + name/unlocks pairing.

3. **.claude/settings.json: removed the Stop hook.** The old
   polish-batch Stop guard was firing ASSESS.play-and-improve on
   every turn against a stale state file from an earlier batch
   (.claude/state/task-batch/batch-20260423-beppo-1.0.json). Archived
   the stale state file and removed the hook entirely — the redesign
   PRD is the governing driver now, not a per-turn batch loop.
The landing component was carrying forward the legacy 'Villains'
name from pre-redesign. The game has no 'villains' concept in
redesign/1.0 — Beppo is a scripted three-act boss (jester →
tubeman → clown, see docs/DESIGN.md popup choreography). The
landing section is a single Beppo reveal, not a gallery of
antagonists.

- src/components/landing/Villains.tsx → BeppoReveal.tsx (git mv)
- Internal export Villains → BeppoReveal, doc comment updated
- src/components/landing/Landing.tsx import/usage updated

No behavior change. The in-game src/components/game/Villains.tsx is
a separate file and stays named Villains for now — it manages the
SDF-shader encounter entities that'll be refactored into proper
per-popup scripts (jester/tubeman/clown) in the Turboplan ECS work.
…aphy

The Mechanics section on the landing page still described the game
in pre-redesign terms: 'Villains drift the maze' (wrong — popups are
scripted boss moments, not drifting entities) and 'Two doors open at
the edge. Only one leads out' (wrong — docs/DESIGN.md commits to one
specific exit_key that must be collected to leave, no door decoys).

Card 03: 'Stay ahead of the laughter' → 'Meet Beppo on his terms'.
Copy rewritten around the three-act popup structure (jester →
tubeman → clown) matching DESIGN.md popup choreography.

Card 04: 'Find the real exit' → 'Find the key that lets you leave'.
Copy rewritten around exit_key as the gating mechanic. Kept the
'still laughing' sting from the original.

Part of redesign/1.0. No behavior change — copy only.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

game/rendering Rendering/graphics changes synthesis

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants