7.0 KiB
AGENTS.md
Purpose
This is the mandatory high-signal brief for agents working in this repo.
Read this file first.
Then read CHAT_CONTEXT.md.
After that, inspect the code and open only the relevant sections of architecture.md, roadmap.md, and testing.md.
Do not read the large docs end-to-end by default.
When docs and code disagree:
- trust the code for current behavior
- trust
AGENTS.md+CHAT_CONTEXT.mdfor current intent - use the larger docs as selective reference
- update stale docs if your slice materially changes behavior
Product
This repo is a browser-based engine/editor for interactive 3D environments with a built-in runner.
Core loop:
- author
- save/load
- run immediately in-browser
Primary product priorities:
- intuitive whiteboxing / level blocking
- imported assets as first-class content
- typed entities and simple interactions
- very fast edit -> run iteration
- web-native delivery and sharing
This is not:
- a Blender replacement
- a general CAD tool
- an unlimited engine platform
- a full physics sandbox unless the roadmap explicitly says so
Hard Rules
Canonical state
- The canonical
SceneDocument/ project state is the source of truth. - Do not store three.js objects in canonical document state.
- Do not make the three.js scene graph the source of truth.
- Editor-authored mutations should go through commands.
Layering
documentowns canonical statecommandsown undoable mutationsgeometryowns derived solid/mesh/collider generationviewport-threeowns editor rendering and interaction helpersruntime-threeowns play-mode runtime behaviorentitiesown typed non-model scene objectsassetsown imported external resources and adaptersserializationowns save/load/versioning/migrations
Persistence
- The document is versioned from day one.
- If persisted schema changes, update version/migration/validation and add at least one compatibility test.
- Canonical save format is project JSON.
- Once binary assets matter, user-facing save/load must be a portable project package containing canonical JSON plus referenced assets.
- Runner/deployment output is separate from editable save/load.
- Never rely on Blob URLs as the only persisted asset reference.
Models, entities, world
- Imported assets live in the asset registry.
- Placed imported models live in
modelInstances. modelInstancesare notentities.- Typed runtime/editor objects such as
PlayerStart,TriggerVolume, and lights live inentities. - Global ambient/sun/background/fog belong in
worldsettings. - Local authored lights belong in typed entity schemas.
Imported model collision
- Collision authoring for imported models belongs on
modelInstances, not assets. - Supported imported-model collision modes must stay explicit and typed.
- Generated collision data is derived data, not canonical source data.
- If broad-phase/narrow-phase pruning or non-box collider support is needed, prefer Rapier over custom collision math.
- Collision mode meanings are fixed unless deliberately changed:
none= no colliderterrain= heightfield collider, static onlystatic= triangle mesh collider, fixed onlydynamic= convex decomposition into compound collider, dynamic/kinematic capablesimple= one cheap primitive or one convex hull
Whiteboxing direction
- The product is moving away from grid-bound brush thinking toward whitebox solids.
- Floating point position/rotation/scale are allowed.
- The grid is a snap/reference helper, not a hard law.
- Whiteboxing should converge on one coherent transform-driven interaction model.
- Object / face / edge / vertex editing are valid goals.
- Non-planar quads are acceptable if derived triangulation is deterministic.
- Whitebox solids do not have to remain convex.
- Collision should come from the solid collider path, not old axis-aligned assumptions.
Implementation Strategy
Default workflow
- Inspect the current repo first.
- Extend the existing implementation.
- Keep the slice as small and vertical as possible.
- Reuse existing paths instead of adding parallel architecture.
- Verify with the narrowest relevant checks.
Vertical slices
Good slice:
- document changes
- commands
- viewport/editor behavior
- UI
- persistence
- runner behavior if relevant
- tests
- brief manual QA notes
Bad slice:
- scaffolding with no user-facing payoff
- duplicate systems
- speculative abstractions
Read selectively
Only open full reference sections when needed:
architecture.mdfor non-trivial runtime/editor/data-model boundariesroadmap.mdfor future direction and accepted scopetesting.mdfor which test layers to add
If the slice is local and obvious, do not reload half the repo’s docs.
Code Rules
Do
- use TypeScript only
- keep types explicit
- prefer pure functions for transforms/build steps
- isolate browser/three.js side effects
- fail loudly in development
- surface useful diagnostics instead of silently ignoring errors
- keep geometry/collision generation testable outside the browser where practical
Don’t
- add R3F casually
- add ECS casually
- over-generalize the entity system
- replace canonical whitebox data with hidden renderer-only mutations
- invent hidden magic behavior without schema support
- remove tests to get green CI
- silently corrupt state on failure
UX Rules
Prioritize:
- fast selection
- direct transforms
- understandable tool state
- visible feedback
- quick play testing
- clear failure modes
Every meaningful feature should answer:
- what the user sees
- what the user clicks/drags/types
- how it is undone
- how failure is shown
- how it is tested
Testing Rules
At minimum, match the slice:
- pure/domain tests for deterministic logic
- serialization tests for persisted features
- runtime/build tests where runtime behavior changes
- browser/e2e only when real browser behavior matters
If schema changes:
- add round-trip coverage
- add migration/compatibility coverage
Prefer small explicit fixtures over giant snapshots.
Vocabulary
Use precise terms:
Document: canonical editor stateWhitebox Solid: author-authored blockout / gameplay-space solidBox Solid: the first whitebox solid shape; old code may still say “box brush”Face/Edge/Vertex: editable parts of a whitebox solidAsset: imported external resourceModel Instance: placed instance of an imported assetEntity: typed scene object with editor/runtime semanticsCollider: derived runtime collision representationProject Package: portable editable bundleRunner Package: deployable playable outputBuild: deterministic document -> runtime transformation
Avoid vague terms like “thing” or “object” when a domain term exists.
Required Closeout
For meaningful changes, report briefly:
- what changed
- why
- files touched
- how you verified it
- known limitations
If you could not verify something, say so plainly.