Add AGENTS.md and update CHAT_CONTEXT.md, architecture.md

This commit is contained in:
2026-04-11 03:14:45 +02:00
parent 3d66f7ec5c
commit a6cff8b3b1
3 changed files with 352 additions and 157 deletions

247
AGENTS.md Normal file
View File

@@ -0,0 +1,247 @@
# 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:
1. trust the code for current behavior
2. trust `AGENTS.md` + `CHAT_CONTEXT.md` for current intent
3. use the larger docs as selective reference
4. 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:
1. author
2. save/load
3. 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
- `document` owns canonical state
- `commands` own undoable mutations
- `geometry` owns derived solid/mesh/collider generation
- `viewport-three` owns editor rendering and interaction helpers
- `runtime-three` owns play-mode runtime behavior
- `entities` own typed non-model scene objects
- `assets` own imported external resources and adapters
- `serialization` owns 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`.
- `modelInstances` are not `entities`.
- Typed runtime/editor objects such as `PlayerStart`, `TriggerVolume`, and lights live in `entities`.
- Global ambient/sun/background/fog belong in `world` settings.
- 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 collider
- `terrain` = heightfield collider, static only
- `static` = triangle mesh collider, fixed only
- `dynamic` = convex decomposition into compound collider, dynamic/kinematic capable
- `simple` = 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
1. Inspect the current repo first.
2. Extend the existing implementation.
3. Keep the slice as small and vertical as possible.
4. Reuse existing paths instead of adding parallel architecture.
5. 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.md` for non-trivial runtime/editor/data-model boundaries
- `roadmap.md` for future direction and accepted scope
- `testing.md` for which test layers to add
If the slice is local and obvious, do not reload half the repos 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
### Dont
- 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 state
- `Whitebox Solid`: author-authored blockout / gameplay-space solid
- `Box Solid`: the first whitebox solid shape; old code may still say “box brush”
- `Face` / `Edge` / `Vertex`: editable parts of a whitebox solid
- `Asset`: imported external resource
- `Model Instance`: placed instance of an imported asset
- `Entity`: typed scene object with editor/runtime semantics
- `Collider`: derived runtime collision representation
- `Project Package`: portable editable bundle
- `Runner Package`: deployable playable output
- `Build`: deterministic document -> runtime transformation
Avoid vague terms like “thing” or “object” when a domain term exists.
---
## Required Closeout
For meaningful changes, report briefly:
1. what changed
2. why
3. files touched
4. how you verified it
5. known limitations
If you could not verify something, say so plainly.

View File

@@ -1,198 +1,139 @@
# CHAT_CONTEXT.md
This file is the lightweight startup context for new Codex chats.
This file is the small startup brief for new implementation chats.
Read this after `AGENTS.md`.
Then inspect only the relevant sections of `architecture.md`, `roadmap.md`, and `testing.md` for the active slice.
Then inspect the code.
Then open only the relevant sections of `architecture.md`, `roadmap.md`, and `testing.md`.
This file does not replace the full docs.
It exists to keep new chats focused and to reduce repeated context load.
The large docs are reference docs, not mandatory full reads.
---
## Product summary
## Current Status
This repo is a browser-based 3D scene authoring tool with a built-in runner.
As of now, the repo is no longer in the very early “empty skeleton” phase.
Core loop:
Broadly implemented already:
1. author a scene
2. save/load it reliably
3. run it in-browser immediately
- foundational document/command/persistence/test setup
- box-based room authoring and per-face materials / UVs
- built-in runner with edit -> run loop
- world settings / lighting / environment basics
- typed entities and trigger/action/target interaction flow
- GLB/GLTF model import and model instances
- local lights, animation playback, spatial audio
- advanced rendering
- better material-library workflow
- runner package / embeddable runner work
- multi-viewport editor foundations
- unified creation/placement foundations
- transform foundations
The product prioritizes:
Important consequence:
- intuitive whiteboxing / level blocking for interactive 3D environments
- imported assets as first-class additions
- typed entities and simple interactions
- browser-native delivery
- many roadmap sections are now historical context, not literal todo items
- do not assume Milestone 0-3 are untouched just because they are still documented
It is not:
- an unlimited general-purpose engine platform
- a Blender replacement
- a general CAD tool
- an R3F showcase
When in doubt, inspect the current code before trusting old milestone wording.
---
## Hard architectural rules
## Current Product Direction
- The canonical `SceneDocument` is the source of truth.
- The document must stay independent from three.js objects.
- Editor-authored mutations should flow through commands.
- The editor viewport is derived from the document.
- The runner is a sibling system, not an editor hack.
- Canonical document format is project JSON, not glTF/GLB.
- Portable save/load for asset-bearing scenes should use a project package built around that JSON.
- Runner/deployment output is downstream from the document/runtime build and is separate from editable project save/load.
- Model instances are separate from typed entities.
The product is a browser-native engine/editor for interactive 3D environments.
Key direction:
- intuitive whiteboxing / level blocking
- imported assets as first-class content
- typed entities and runtime interactions
- fast built-in runner workflow
The geometry direction is shifting from old grid-bound “brush” thinking toward whitebox solids:
- floating point transforms allowed
- free object rotation allowed
- grid is optional snap/reference help
- object / face / edge / vertex editing should converge on one transform-driven model
- non-planar quads are acceptable if triangulated deterministically
- non-convex whitebox solids are acceptable if the solid mesh/collider path supports them
Old code and docs may still say “brush” in places.
Treat current box-brush structures as the starting point for whitebox solids unless the slice deliberately changes that.
---
## Early binding decisions
## Hard Current Assumptions
These are fixed for the early milestones unless a later slice explicitly changes them.
- world is right-handed and Y-up
- canonical state lives outside the React tree
- document/project state remains source of truth
- editor changes should flow through commands
- model instances remain separate from entities
- world settings own global background / ambient / sun / fog
- local authored lights stay in typed entities
- project save/load and runner export are separate concerns
### Coordinates and units
Imported model collision:
- world is right-handed and **Y-up**
- `+X` is right
- `+Y` is up
- units are meter-like
### Repo shape
- keep the repo as a single Vite app
- keep domain folders under `src/`
- do not split into a monorepo early
### State ownership
- do not use the React tree as the canonical state container
- keep canonical state in a thin external editor store/service
### Persistence
- version the document from day one
- keep migrations explicit
- early project persistence can be local draft storage plus JSON import/export
- once binary assets exist, portable save/load should use a project package such as `scene.json` plus bundled assets
- canonical JSON stays the source document format underneath that project package
- runner package output is a separate deployable artifact
- binary assets must survive reload via embedded or project-scoped persistent storage
- never rely on Blob URLs as the only persisted asset reference
### Current box-solid foundation
- early slices began with an axis-aligned box shape and stable face IDs
- stable box face IDs are:
- `posX`
- `negX`
- `posY`
- `negY`
- `posZ`
- `negZ`
- `posY` is top and `negY` is bottom
### Whitebox direction
- move away from grid-bound brush thinking toward whitebox solids
- allow floating point transforms
- allow free object rotation
- use the grid as optional snap/reference help, not as a hard restriction
- unify object / face / edge / vertex editing around one transform-driven interaction model
- non-planar quads are acceptable if triangulated deterministically in derived geometry
- non-convex whitebox solids are acceptable if the solid mesh/collider pipeline can support them
### Early UV data
Per face, keep explicit UV transform values such as:
- `offset`
- `scale`
- `rotationQuarterTurns`
- `flipU`
- `flipV`
“Fit to face” should rewrite explicit values, not add a magical persistent flag.
### Model placement
- imported assets live in the asset registry
- placed imported models live in `modelInstances`
- typed scene objects like `PlayerStart`, `TriggerVolume`, or lights live in `entities`
- collision authoring for imported models belongs on `modelInstances`, not asset records
- generated imported-model collider data should be derived from asset geometry + instance transform + authored settings
- for imported-model collider types beyond simple boxes, prefer a Rapier-backed collision/query layer over extending the handcrafted collision code indefinitely
- broad-phase and narrow-phase pruning should come from that collision/query layer, not custom app code
### Interaction scope
- keep `Trigger -> Action -> Target` typed and explicit
- do not add actions for systems that do not exist yet
### World environment vs local lights
- global background / ambient / sun / fog belong in `world` settings
- local authored lights belong in typed entity schemas
- true skyboxes or environment textures belong after persistent asset storage exists
- authored collision settings belong on `modelInstances`
- generated collider data is derived, not canonical
- if non-box collider support needs broad-phase/narrow-phase pruning, prefer Rapier over custom app-side collision math
---
## What a good slice looks like
## Reading Strategy
Each slice should land the smallest coherent end-to-end version of the feature across the layers it touches:
Default:
- document data
- commands
- viewport behavior
- runner behavior if relevant
- persistence
- UI
- tests
1. read `AGENTS.md`
2. read this file
3. inspect the code paths touched by the slice
4. open only the relevant sections of:
- `architecture.md`
- `roadmap.md`
- `testing.md`
Do not land speculative scaffolding with no immediate slice use.
Open the larger docs only when needed:
If a roadmap item is too large, split it into smaller vertical slices.
- `architecture.md`
- data-model boundaries
- runtime/editor integration
- geometry/collision semantics
- persistence/export/package architecture
- `roadmap.md`
- whether a direction is already chosen
- whether something is intentionally deferred
- how a large topic should be split into slices
- `testing.md`
- what test layers to add
- schema/migration expectations
- browser/e2e guidance
If the slice is small and local, do not reread unrelated doc sections.
---
## Required habits for implementation
## What To Be Careful About
- Inspect the current repo first.
- Extend the current implementation instead of restarting architecture.
- If persisted schema changes, update versioning/migrations and add a compatibility test.
- Run the narrowest relevant checks you can.
- Report what was actually verified.
- do not restart architecture just because the original docs were written earlier
- extend existing paths instead of introducing parallel systems
- if docs and code disagree on current behavior, trust the code and update docs if your slice changes direction materially
- keep responses brief and verification scoped to the actual slice
---
## Early slice ordering to keep in mind
## Likely Near-Term Themes
- M0: foundation, document, commands, persistence, test setup
- M1: axis-aligned box brushes, face materials/UVs, runner, first-room polish, world lighting basics
- M2: typed entities, simple trigger/action/target interactions, click interactions
- M3: GLB/GLTF import, local lights + skyboxes, animation, spatial audio
- M4+: whitebox-solid interaction model, component editing, derived solid triangulation/collision
The next large topics are more likely to be things like:
That ordering matters because:
- whitebox-solid editing model
- multi-scene / project structure
- richer runtime systems
- remaining packaging / portability work
- future primitives and topology tools after the whitebox direction is coherent
- world settings do not need entity or asset pipelines
- local lights need the entity system
- skyboxes need persistent asset storage
- animation and audio actions should land only with those runtime systems
---
## When to open the full docs
Open the relevant full sections when:
- persistence schema changes
- runtime/editor boundaries are being touched
- a slice adds new tests or new failure modes
- geometry semantics are non-trivial
- import/export behavior changes
Otherwise, stay focused on the active slice and keep the implementation small.
Do not assume the old prompt list is still the whole plan.

View File

@@ -1,5 +1,12 @@
# architecture.md
Use this as a selective reference doc.
Do not read this file end-to-end by default.
Read only the headings relevant to the active slice after reading `AGENTS.md`, `CHAT_CONTEXT.md`, and inspecting the current code.
If examples in this file lag behind the code, trust the code for current behavior and update the docs when your slice materially changes direction.
## Overview
This project is a browser-based 3D scene authoring tool with a built-in runtime runner.