auto-git:
[add] AGENTS.md [add] Action [add] architecture.md [add] prompts.txt [add] roadmap.md [add] testing.md
This commit is contained in:
506
AGENTS.md
Normal file
506
AGENTS.md
Normal file
@@ -0,0 +1,506 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Project identity
|
||||
|
||||
This repository contains a browser-based brush/solid editor for creating lightweight interactive 3D scenes, plus a built-in browser runner for playing those scenes.
|
||||
|
||||
The product goal is:
|
||||
|
||||
- Hammer / TrenchBroom style spatial authoring
|
||||
- modern browser delivery
|
||||
- glTF asset import/export
|
||||
- fast edit -> run iteration
|
||||
- lightweight interactive runtime with spatial audio, navigation modes, and simple entity-driven logic
|
||||
|
||||
This is not a general-purpose DCC.
|
||||
This is not a full game engine.
|
||||
This is a focused authoring + runtime tool for browser-delivered 3D spaces.
|
||||
|
||||
---
|
||||
|
||||
## Product pillars
|
||||
|
||||
1. **Brushes are sacred**
|
||||
- Layout authoring must remain faster than Blender.
|
||||
- Brush editing is a first-class workflow, not a legacy compatibility mode.
|
||||
- The editor must feel immediate, precise, and grid-friendly.
|
||||
|
||||
2. **Imported assets are first-class**
|
||||
- glTF / GLB import must feel native.
|
||||
- Imported meshes, materials, textures, and animations must coexist cleanly with brush-authored worlds.
|
||||
- Imported assets complement brushes; they do not replace them.
|
||||
|
||||
3. **The runner is built in**
|
||||
- Every meaningful authoring step should be testable in-browser.
|
||||
- Switching from edit mode to play mode should be nearly instant.
|
||||
- The runner is part of the product, not a demo app.
|
||||
|
||||
4. **Web-native sharing matters**
|
||||
- Scenes should be easy to load, embed, preview, and eventually share by URL.
|
||||
- The browser is a target platform, not a secondary export target.
|
||||
|
||||
---
|
||||
|
||||
## Architectural stance
|
||||
|
||||
When making design decisions, prefer:
|
||||
|
||||
- plain three.js over unnecessary abstraction
|
||||
- explicit data models over implicit scene graph state
|
||||
- deterministic rebuilds over hidden mutations
|
||||
- command-based editing over ad hoc state changes
|
||||
- typed scene entities over free-form JSON blobs
|
||||
- vertical slices over speculative infrastructure
|
||||
- boring, maintainable code over cleverness
|
||||
|
||||
The project uses:
|
||||
|
||||
- React for application shell and editor UI
|
||||
- three.js for viewport and runtime rendering
|
||||
- a canonical editor document model independent of three.js
|
||||
- command pattern for undo/redo
|
||||
- runtime entity systems for navigation, triggers, audio, and interaction
|
||||
- glTF / GLB as the main interchange asset format
|
||||
- JSON as the canonical authoring format
|
||||
|
||||
Do not collapse editor state into raw three.js objects.
|
||||
Do not make the three.js scene the source of truth.
|
||||
Do not make glTF the canonical editor save format.
|
||||
|
||||
---
|
||||
|
||||
## Early binding decisions
|
||||
|
||||
These defaults are intentionally fixed for the early slices unless a later slice explicitly changes them.
|
||||
|
||||
### Coordinate system
|
||||
|
||||
- world space is right-handed and **Y-up**
|
||||
- `+X` is right, `+Y` is up
|
||||
- scene units are meter-like and should be used consistently for movement, collision, and audio distances
|
||||
|
||||
### Early repo shape
|
||||
|
||||
- start as a single Vite app
|
||||
- keep domain folders under `src/`
|
||||
- do not introduce `/apps` + `/packages` or a monorepo split until the current code actually needs it
|
||||
|
||||
### State ownership
|
||||
|
||||
- do not use the React tree as the canonical state container
|
||||
- keep canonical editor state in a thin external editor store/service
|
||||
- React renders and dispatches commands; it does not own the document
|
||||
|
||||
### Persistence
|
||||
|
||||
- the canonical scene document is versioned from day one
|
||||
- M0-M2 may use local draft persistence plus explicit JSON import/export
|
||||
- when binary assets arrive, they must survive reloads via embedded data or project-scoped packaged storage
|
||||
- never rely on ephemeral Blob URLs as the only persisted asset reference
|
||||
|
||||
### Early brush defaults
|
||||
|
||||
- Slice 1.1 box brushes are axis-aligned only
|
||||
- arbitrary brush rotation is explicitly deferred
|
||||
- canonical box face IDs are fixed and stable:
|
||||
- `posX`
|
||||
- `negX`
|
||||
- `posY`
|
||||
- `negY`
|
||||
- `posZ`
|
||||
- `negZ`
|
||||
- `posY` is the top face and `negY` is the bottom face
|
||||
|
||||
### Model placement
|
||||
|
||||
- placed imported models are **model instances**, not typed entities
|
||||
- keep model instances in a document collection separate from `entities`
|
||||
|
||||
### Runtime interaction scope
|
||||
|
||||
- keep trigger/action/target links explicit and typed
|
||||
- do not activate actions for systems that do not exist yet
|
||||
- add sound and animation actions only when those runtime systems are implemented
|
||||
|
||||
### Early clipping scope
|
||||
|
||||
- until a dedicated convex-brush slice exists, clipping must be constrained to results representable by currently supported brush kinds
|
||||
- unsupported clip cases must fail clearly instead of inventing new hidden geometry rules
|
||||
|
||||
---
|
||||
|
||||
## Non-goals
|
||||
|
||||
Unless explicitly added to the roadmap, do not turn this project into:
|
||||
|
||||
- a general CAD package
|
||||
- a Blender replacement
|
||||
- a multiplayer MMO editor
|
||||
- a full node-based visual scripting environment
|
||||
- a full physics sandbox
|
||||
- a photoreal AAA renderer
|
||||
- a React Three Fiber showcase
|
||||
- an ECS research project
|
||||
|
||||
We may add optional scripting, plugins, collaboration, or advanced baking later.
|
||||
They are not v1 priorities.
|
||||
|
||||
---
|
||||
|
||||
## Core product vocabulary
|
||||
|
||||
Use these terms consistently:
|
||||
|
||||
- **Document**: canonical editor state
|
||||
- **Brush**: author-authored solid/primitive in canonical brush form
|
||||
- **Face**: one editable surface of a brush
|
||||
- **Material**: logical authoring material definition
|
||||
- **Texture**: image resource backing material channels
|
||||
- **Asset**: imported external resource, usually GLB/GLTF or audio and related media
|
||||
- **Model Instance**: placed scene instance of an imported asset
|
||||
- **Prefab**: reusable asset/entity package placeable in scenes
|
||||
- **Entity**: typed scene object with runtime/editor semantics
|
||||
- **Runner**: browser runtime that loads and plays scenes
|
||||
- **Viewport**: editor rendering surface
|
||||
- **Command**: undoable state transition
|
||||
- **Tool**: editor interaction mode such as select, move, box-create, face-edit
|
||||
- **Build**: deterministic transformation from document -> runtime scene data
|
||||
- **Export**: transformation to external deliverables such as GLB
|
||||
|
||||
Avoid vague terms like “object”, “thing”, “item”, or “component” when a more precise domain term exists.
|
||||
|
||||
---
|
||||
|
||||
## Repo expectations for agents
|
||||
|
||||
When working in this repo:
|
||||
|
||||
1. Read:
|
||||
- `AGENTS.md`
|
||||
- `architecture.md`
|
||||
- `roadmap.md`
|
||||
- `testing.md`
|
||||
|
||||
2. Respect the current vertical slice.
|
||||
- Do not “prepare for future flexibility” by adding unnecessary systems.
|
||||
- Implement the smallest coherent version that preserves the architecture.
|
||||
|
||||
3. Preserve layering.
|
||||
- `document` owns canonical state.
|
||||
- `commands` apply valid state changes.
|
||||
- `geometry` owns derived brush and collider generation.
|
||||
- `viewport-three` renders editor state.
|
||||
- `runtime-three` plays runtime state.
|
||||
- `entities` owns typed non-brush scene objects.
|
||||
- `assets` adapts external asset/audio/media formats.
|
||||
- `serialization` persists canonical state.
|
||||
|
||||
4. Do not bypass command infrastructure for editor mutations.
|
||||
- If the user can do it in the editor, it should usually be represented as a command.
|
||||
|
||||
5. If persisted schema changes, update compatibility explicitly.
|
||||
- bump the document schema version when required
|
||||
- add or update migrations
|
||||
- add at least one migration or compatibility test
|
||||
|
||||
6. Prefer explicit typing and explicit invariants.
|
||||
- Avoid permissive `any`, loose maps, or magic strings when a discriminated union or typed schema is appropriate.
|
||||
|
||||
7. Keep systems testable.
|
||||
- Geometry generation should be testable outside the browser UI.
|
||||
- Serialization should be round-trip tested.
|
||||
- Runtime interactions should be testable through deterministic fixtures where possible.
|
||||
|
||||
8. Keep browser concerns in mind.
|
||||
- Gracefully handle pointer lock failure, audio unlock requirements, missing gamepads, and asset load failures.
|
||||
- Avoid architecture that assumes native desktop privileges.
|
||||
|
||||
---
|
||||
|
||||
## Code quality rules
|
||||
|
||||
### General
|
||||
|
||||
- TypeScript only
|
||||
- strict typing enabled
|
||||
- prefer pure functions for transforms/build steps
|
||||
- isolate impure browser/three.js side effects
|
||||
- no silent catch-and-ignore
|
||||
- no dead feature flags without roadmap justification
|
||||
- no hidden singleton globals unless explicitly part of infrastructure
|
||||
|
||||
### Naming
|
||||
|
||||
- use descriptive names
|
||||
- prefer domain names over generic utility names
|
||||
- avoid abbreviations unless they are standard and obvious
|
||||
- function names should describe intent, not implementation detail
|
||||
|
||||
Good:
|
||||
- `buildRuntimeSceneFromDocument`
|
||||
- `applyMaterialToSelectedFaces`
|
||||
- `createBoxBrushCommand`
|
||||
|
||||
Bad:
|
||||
- `handleThing`
|
||||
- `updateData`
|
||||
- `doBuild`
|
||||
|
||||
### File organization
|
||||
|
||||
- small files where it helps clarity
|
||||
- split by domain, not by arbitrary technical categories
|
||||
- avoid giant “misc” or “utils” dumping grounds
|
||||
- every folder should have a clear reason to exist
|
||||
|
||||
### Comments
|
||||
|
||||
- explain *why*, not what the code obviously does
|
||||
- use comments to document invariants, constraints, and tricky browser behavior
|
||||
- remove stale comments promptly
|
||||
|
||||
### Error handling
|
||||
|
||||
- fail loudly in development
|
||||
- surface usable diagnostics in the editor UI
|
||||
- never corrupt the document silently
|
||||
- preserve previous valid state on failed builds where possible
|
||||
|
||||
---
|
||||
|
||||
## Data model rules
|
||||
|
||||
The canonical authoring state must remain independent from three.js scene graph objects.
|
||||
|
||||
### Required separation
|
||||
|
||||
Maintain these layers:
|
||||
|
||||
1. **Authoring model**
|
||||
- JSON-serializable
|
||||
- versioned
|
||||
- typed
|
||||
- stable across runtime/editor rebuilds
|
||||
|
||||
2. **Editor view model**
|
||||
- three.js meshes, helpers, overlays, gizmos
|
||||
- disposable and rebuildable
|
||||
|
||||
3. **Runtime model**
|
||||
- play-mode scene graph
|
||||
- controllers, triggers, emitters, colliders, animation mixers
|
||||
|
||||
Do not let editor-only helpers leak into the canonical document.
|
||||
Do not store raw three.js objects inside canonical document state.
|
||||
|
||||
### Brush rules
|
||||
|
||||
- brushes are not stored as triangle soup
|
||||
- face material assignments are per-face
|
||||
- UV transforms are canonical editor data
|
||||
- runtime mesh generation is derived data
|
||||
- collision generation is derived data
|
||||
- early boxes are axis-aligned and use fixed face IDs
|
||||
|
||||
### Entity rules
|
||||
|
||||
- entities must be typed
|
||||
- entity schemas must be explicit
|
||||
- entity defaults must be centralized
|
||||
- entity validation must happen at document/build boundaries
|
||||
- model instances remain separate from entities
|
||||
|
||||
---
|
||||
|
||||
## Performance rules
|
||||
|
||||
Performance matters, but premature micro-optimization does not.
|
||||
|
||||
Priorities:
|
||||
|
||||
1. editor responsiveness during common operations
|
||||
2. deterministic rebuild behavior
|
||||
3. predictable memory usage
|
||||
4. runtime smoothness for modest scenes
|
||||
5. export/build correctness
|
||||
|
||||
When optimizing:
|
||||
|
||||
- measure first
|
||||
- optimize hotspots, not aesthetics
|
||||
- document assumptions
|
||||
- prefer algorithmic improvements over clever hacks
|
||||
|
||||
Expected hotspots:
|
||||
|
||||
- picking/raycasting
|
||||
- brush rebuilds / CSG
|
||||
- face highlighting
|
||||
- large texture browser lists
|
||||
- imported asset previews
|
||||
- runtime trigger scanning if implemented naively
|
||||
|
||||
---
|
||||
|
||||
## UX rules
|
||||
|
||||
The editor should feel like a real authoring tool, not a tech demo.
|
||||
|
||||
Prioritize:
|
||||
|
||||
- fast selection
|
||||
- robust snapping
|
||||
- visible grid and transform feedback
|
||||
- obvious active tool state
|
||||
- low-friction material application
|
||||
- quick play testing
|
||||
- understandable errors
|
||||
|
||||
Every new feature should answer:
|
||||
- What does the user see?
|
||||
- What does the user click/drag/type?
|
||||
- How is failure communicated?
|
||||
- How is the action undone?
|
||||
- How is the result tested?
|
||||
|
||||
---
|
||||
|
||||
## Vertical slice policy
|
||||
|
||||
We build in vertical slices.
|
||||
Each slice must deliver a complete, usable capability across all relevant layers.
|
||||
|
||||
A good slice includes:
|
||||
- document changes
|
||||
- commands
|
||||
- viewport behavior
|
||||
- UI panel updates
|
||||
- runner behavior if relevant
|
||||
- persistence
|
||||
- tests
|
||||
- manual QA notes
|
||||
|
||||
A bad slice is “just backend structure” or “just a partial UI”.
|
||||
|
||||
Do not land architectural scaffolding that has no immediate use in the current slice.
|
||||
|
||||
If a roadmap item is too large for one pass, split it into smaller end-to-end sub-slices instead of landing half-systems.
|
||||
|
||||
---
|
||||
|
||||
## Typical slice shape
|
||||
|
||||
For each slice, agents should aim to deliver:
|
||||
|
||||
1. domain model changes
|
||||
2. command(s)
|
||||
3. viewport interaction/tooling
|
||||
4. UI affordance
|
||||
5. serialization support
|
||||
6. runtime/build support if needed
|
||||
7. tests
|
||||
8. docs update if behavior changed materially
|
||||
|
||||
---
|
||||
|
||||
## Decision heuristics
|
||||
|
||||
When uncertain:
|
||||
|
||||
### Prefer plain three.js over extra abstraction
|
||||
Unless abstraction clearly simplifies repeated patterns.
|
||||
|
||||
### Prefer canonical JSON over reusing runtime/export data structures
|
||||
The editor’s needs are different from export/runtime needs.
|
||||
|
||||
### Prefer typed entity schemas over generic script bags
|
||||
Especially in early versions.
|
||||
|
||||
### Prefer constrained capabilities that feel good over flexible capabilities that feel vague
|
||||
Example:
|
||||
- better to have one excellent box-brush tool than five half-working primitive tools
|
||||
|
||||
### Prefer immediate usability over speculative extensibility
|
||||
But preserve clean seams for future extensions.
|
||||
|
||||
---
|
||||
|
||||
## What agents must not do
|
||||
|
||||
Do not:
|
||||
|
||||
- rewrite broad project structure without a strong reason
|
||||
- introduce new framework dependencies casually
|
||||
- add R3F because “we might want it later”
|
||||
- introduce ECS because “games use ECS”
|
||||
- over-generalize the entity system
|
||||
- replace canonical brush data with raw mesh editing
|
||||
- implement hidden magic behaviors without schema support
|
||||
- remove tests to get green CI
|
||||
- make visual changes without noting them in the slice summary
|
||||
- ignore browser restrictions around input/audio
|
||||
|
||||
---
|
||||
|
||||
## Required deliverables in implementation responses
|
||||
|
||||
When making meaningful changes, include:
|
||||
|
||||
1. what changed
|
||||
2. why it changed
|
||||
3. which files were added/updated
|
||||
4. how to run/test it
|
||||
5. known limitations
|
||||
6. follow-up suggestions only if directly relevant
|
||||
|
||||
If the environment prevents verification, state exactly what was and was not verified.
|
||||
|
||||
---
|
||||
|
||||
## Definition of done for a slice
|
||||
|
||||
A slice is done when:
|
||||
|
||||
- the feature can be used end-to-end
|
||||
- the feature is represented in canonical document data
|
||||
- the feature can be saved and loaded
|
||||
- the feature is test-covered appropriately
|
||||
- the feature has manual verification notes
|
||||
- the feature does not violate the architecture
|
||||
- obvious failures produce usable diagnostics
|
||||
- undo/redo works if the feature is editor-authored
|
||||
|
||||
---
|
||||
|
||||
## Preferred stack unless changed deliberately
|
||||
|
||||
- TypeScript
|
||||
- React
|
||||
- Vite
|
||||
- three.js
|
||||
- Vitest
|
||||
- Playwright
|
||||
- ESLint
|
||||
- Prettier
|
||||
- a small state store if needed
|
||||
- minimal dependencies overall
|
||||
|
||||
Add dependencies only when they clearly save time and complexity over building in-house.
|
||||
|
||||
---
|
||||
|
||||
## Final instruction to agents
|
||||
|
||||
Build the smallest coherent thing that feels real.
|
||||
|
||||
The product should always trend toward:
|
||||
- spatial immediacy
|
||||
- authoring clarity
|
||||
- browser-native practicality
|
||||
- fast iteration
|
||||
- strong foundations for brushes, assets, entities, and runner behavior
|
||||
|
||||
If forced to choose, preserve the integrity of:
|
||||
1. the canonical document model
|
||||
2. the brush workflow
|
||||
3. the edit -> run loop
|
||||
1101
architecture.md
Normal file
1101
architecture.md
Normal file
File diff suppressed because it is too large
Load Diff
1113
prompts.txt
Normal file
1113
prompts.txt
Normal file
File diff suppressed because it is too large
Load Diff
606
roadmap.md
Normal file
606
roadmap.md
Normal file
@@ -0,0 +1,606 @@
|
||||
# roadmap.md
|
||||
|
||||
## Overview
|
||||
|
||||
This roadmap is organized as vertical slices.
|
||||
Each slice must deliver an end-to-end usable capability across:
|
||||
|
||||
- document model
|
||||
- commands
|
||||
- viewport/editor behavior
|
||||
- UI
|
||||
- persistence
|
||||
- runner behavior where relevant
|
||||
- tests
|
||||
- manual QA notes
|
||||
|
||||
We optimize for:
|
||||
|
||||
- proving the product loop early
|
||||
- preserving architecture
|
||||
- shipping coherent slices
|
||||
- avoiding speculative complexity
|
||||
|
||||
If a roadmap item is too large for one implementation pass, split it into smaller end-to-end sub-slices rather than landing half-systems.
|
||||
|
||||
---
|
||||
|
||||
## Product north star
|
||||
|
||||
A browser-based brush editor with a built-in runner, enabling users to quickly create and share lightweight interactive 3D spaces with:
|
||||
|
||||
- brush-authored layout
|
||||
- material/texture workflows
|
||||
- imported GLB/GLTF assets
|
||||
- spatial audio
|
||||
- typed entities and simple interactions
|
||||
- optional navigation modes
|
||||
|
||||
---
|
||||
|
||||
## Early project decisions
|
||||
|
||||
These are locked for the early milestones:
|
||||
|
||||
- world space is **Y-up**
|
||||
- early repo shape is a single Vite app with domain folders under `src/`
|
||||
- canonical document state lives outside the React tree
|
||||
- the document is versioned from day one
|
||||
- early box brushes are axis-aligned only with fixed face IDs
|
||||
- placed imported models are `modelInstances`, not `entities`
|
||||
- local draft persistence plus explicit JSON import/export is acceptable early
|
||||
- broad roadmap items may be split into smaller implementation chats as long as each chat still lands a coherent vertical slice
|
||||
|
||||
---
|
||||
|
||||
## Milestone structure
|
||||
|
||||
### Milestone 0
|
||||
Foundation and repo discipline
|
||||
|
||||
### Milestone 1
|
||||
First real room: brush layout + materials + play mode
|
||||
|
||||
### Milestone 2
|
||||
Entities and runtime interaction
|
||||
|
||||
### Milestone 3
|
||||
Imported models, animation, and audio
|
||||
|
||||
### Milestone 4
|
||||
Better brush editing and authoring ergonomics
|
||||
|
||||
### Milestone 5
|
||||
Scene packaging, sharing, and quality improvements
|
||||
|
||||
### Milestone 6
|
||||
Power-user systems and ecosystem growth
|
||||
|
||||
---
|
||||
|
||||
## Milestone 0 — Foundation
|
||||
|
||||
### Goals
|
||||
|
||||
Create the minimum project skeleton that supports fast vertical slicing without overbuilding.
|
||||
|
||||
### Deliverables
|
||||
|
||||
- repo structure established under a single app
|
||||
- TypeScript + Vite + React app booting
|
||||
- three.js viewport shell visible
|
||||
- thin external editor store/document skeleton
|
||||
- versioned scene document and migration entry point
|
||||
- command history scaffold
|
||||
- local draft save/load scaffold plus JSON import/export scaffold
|
||||
- test runner setup
|
||||
- Playwright basic smoke setup
|
||||
- docs established and aligned
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- app boots locally
|
||||
- empty viewport renders
|
||||
- empty document loads
|
||||
- command stack can push a dummy command and undo/redo
|
||||
- one smoke test passes
|
||||
- docs exist and are consistent
|
||||
|
||||
### Out of scope
|
||||
|
||||
- real geometry tools
|
||||
- real runtime
|
||||
- real asset import
|
||||
- full inspector
|
||||
|
||||
---
|
||||
|
||||
## Milestone 1 — First playable slice
|
||||
|
||||
### Vision
|
||||
|
||||
The user can create a box brush, assign materials to faces, save the scene, reload it, and run around it.
|
||||
|
||||
This is the first proof that the product is real.
|
||||
|
||||
### Slice 1.1 — Box brush authoring
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- axis-aligned box brush schema
|
||||
- stable box face IDs
|
||||
- create box brush command
|
||||
- select box brush
|
||||
- move/resize box brush
|
||||
- grid snapping
|
||||
- viewport render of box brushes
|
||||
- basic outliner presence
|
||||
- save/load support
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- user can create at least one box brush
|
||||
- box persists through save/load
|
||||
- selection works reliably
|
||||
- transform edits are undoable
|
||||
- no arbitrary brush rotation is introduced yet
|
||||
|
||||
---
|
||||
|
||||
### Slice 1.2 — Face materials and UV basics
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- material registry
|
||||
- small local starter material library
|
||||
- face selection
|
||||
- apply material to a single face
|
||||
- basic UV controls:
|
||||
- offset
|
||||
- scale
|
||||
- rotate 90-degree steps
|
||||
- flip U/V
|
||||
- fit to face by rewriting explicit UV values
|
||||
- inspector integration
|
||||
- material browser panel
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- user can texture a simple room quickly
|
||||
- per-face assignments persist through save/load
|
||||
- UV edits persist
|
||||
- editor rendering reflects those changes immediately
|
||||
|
||||
---
|
||||
|
||||
### Slice 1.3 — Runner v1
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- runtime build from document
|
||||
- first-person navigation
|
||||
- orbit visitor mode
|
||||
- mode switch
|
||||
- minimal typed `PlayerStart` support
|
||||
- basic collision against axis-aligned box brush geometry
|
||||
- play-from-editor action
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- user can press Run and navigate the scene
|
||||
- first-person works with keyboard/mouse
|
||||
- orbit visitor works
|
||||
- leaving run mode returns to editor state safely
|
||||
- `PlayerStart` does not need to be rebuilt later as a separate foundation
|
||||
|
||||
---
|
||||
|
||||
### Slice 1.4 — End-to-end polish for “first room”
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- status/errors panel
|
||||
- document validation basics
|
||||
- improved snapping feedback
|
||||
- basic toolbar
|
||||
- coherent save/load UX for the current persistence path
|
||||
- basic scene settings if needed
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- creating a tiny room feels coherent
|
||||
- failures are visible
|
||||
- no obvious corruption issues
|
||||
- smoke tests cover the loop
|
||||
|
||||
---
|
||||
|
||||
## Milestone 2 — Entity-driven interactions
|
||||
|
||||
### Vision
|
||||
|
||||
The user can place non-brush entities and author simple interactive scenes without scripting.
|
||||
|
||||
### Slice 2.1 — Entity system foundation
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- typed entity base
|
||||
- entity registry
|
||||
- entity icons/helpers in viewport
|
||||
- entity placement workflow
|
||||
- entity inspector
|
||||
- save/load support
|
||||
- extension of the existing `PlayerStart` path rather than a parallel rewrite
|
||||
|
||||
#### Initial entity types
|
||||
|
||||
- PlayerStart
|
||||
- SoundEmitter
|
||||
- TriggerVolume
|
||||
- TeleportTarget
|
||||
- Interactable
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- entities can be placed, selected, edited, saved, and loaded
|
||||
- runtime build can consume them
|
||||
- model instances remain separate from entities
|
||||
|
||||
---
|
||||
|
||||
### Slice 2.2 — Trigger -> Action -> Target foundation
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- typed trigger/action/target schema
|
||||
- action dispatch pipeline
|
||||
- editor UI for linking
|
||||
- runtime evaluation
|
||||
|
||||
#### Initial trigger sources
|
||||
|
||||
- TriggerVolume enter
|
||||
- TriggerVolume exit
|
||||
|
||||
#### Initial actions
|
||||
|
||||
- teleport player
|
||||
- toggle visibility
|
||||
|
||||
Sound and animation actions are intentionally deferred until their runtime systems exist.
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- user can build a basic non-scripted interaction without code
|
||||
- links survive save/load
|
||||
- runtime behavior is deterministic
|
||||
|
||||
---
|
||||
|
||||
### Slice 2.3 — Click interactions and runner prompts
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- click target support
|
||||
- prompt UI
|
||||
- action-on-click behavior
|
||||
- interaction distance settings
|
||||
- compatibility with the existing trigger/action/target system
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- user can click an entity to trigger something
|
||||
- prompts are understandable
|
||||
- keyboard/controller fallback rules are documented
|
||||
|
||||
---
|
||||
|
||||
## Milestone 3 — Assets, animation, audio
|
||||
|
||||
### Vision
|
||||
|
||||
The tool becomes more than brush-only by supporting imported GLB/GLTF assets and native spatial audio.
|
||||
|
||||
### Slice 3.1 — GLB/GLTF import
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- import workflow
|
||||
- asset registry
|
||||
- persistent project storage for imported binary data
|
||||
- place imported model instance
|
||||
- transform model instance
|
||||
- save/load support for asset refs and model instances
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- user can import a GLB/GLTF and place it in scene
|
||||
- asset metadata is preserved
|
||||
- imported assets survive reload
|
||||
- runtime renders imported model instances correctly
|
||||
|
||||
---
|
||||
|
||||
### Slice 3.2 — Animation playback
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- detect imported animations
|
||||
- animation config on model instances or equivalent explicit target config
|
||||
- play/stop animation actions
|
||||
- animation trigger binding
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- imported animated asset can be triggered in runner
|
||||
- editor exposes basic animation controls/settings
|
||||
|
||||
---
|
||||
|
||||
### Slice 3.3 — Spatial audio
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- audio asset import/reference
|
||||
- positional emitter runtime support
|
||||
- distance settings
|
||||
- loop/one-shot settings
|
||||
- triggerable playback
|
||||
- browser audio unlock UX
|
||||
- play/stop sound actions integrated into the trigger system
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- sound emits from authored world positions
|
||||
- playback is spatial in runner
|
||||
- author can test it locally with clear UX
|
||||
|
||||
---
|
||||
|
||||
## Milestone 4 — Better brush ergonomics
|
||||
|
||||
### Vision
|
||||
|
||||
The editor starts feeling closer to the old-school map-editor joy.
|
||||
|
||||
These roadmap items may be delivered as multiple smaller implementation chats if that produces cleaner vertical slices.
|
||||
|
||||
### Slice 4.1 — More brush primitives
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- wedge/ramp
|
||||
- cylinder prism
|
||||
- stairs
|
||||
- arch
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- each new primitive is:
|
||||
- creatable
|
||||
- editable
|
||||
- save/load safe
|
||||
- renderable in runner
|
||||
- covered by geometry tests
|
||||
|
||||
---
|
||||
|
||||
### Slice 4.2 — Brush clipping
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- clip tool
|
||||
- split/keep side options
|
||||
- preview visualization
|
||||
- undo/redo support
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- clip operations are predictable and reversible
|
||||
- resulting brushes remain valid
|
||||
- unsupported clip cases fail clearly instead of silently producing ad hoc geometry
|
||||
|
||||
---
|
||||
|
||||
### Slice 4.3 — Better viewport layouts
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- top/front/side orthographic views
|
||||
- optional split layout
|
||||
- improved transform workflows
|
||||
- configurable snapping
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- level-authoring speed materially improves
|
||||
- camera controls are documented and stable
|
||||
|
||||
---
|
||||
|
||||
## Milestone 5 — Material and ecosystem maturity
|
||||
|
||||
### Vision
|
||||
|
||||
The editor becomes attractive for repeated use, not just demos.
|
||||
|
||||
These items are also likely candidates for sub-slices if needed.
|
||||
|
||||
### Slice 5.1 — Better material library
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- categories
|
||||
- tags
|
||||
- search
|
||||
- favorites
|
||||
- recent materials
|
||||
- starter library expansion
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- material assignment feels fast
|
||||
- modestly larger libraries remain usable
|
||||
|
||||
---
|
||||
|
||||
### Slice 5.2 — Prefabs and reusable assets
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- prefab definition support
|
||||
- prefab placement
|
||||
- prefab instance updating rules
|
||||
- prefab browser
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- user can create or import reusable building blocks
|
||||
- instances remain manageable
|
||||
- update behavior is explicit and documented
|
||||
|
||||
---
|
||||
|
||||
### Slice 5.3 — Export and packaging improvements
|
||||
|
||||
#### Deliverables
|
||||
|
||||
- GLB export improvements
|
||||
- scene packaging options
|
||||
- embeddable runner route or bundle
|
||||
- production asset optimization hooks where easy and justified
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
- user can reasonably share or deploy scenes
|
||||
- runner package loads reliably in target browsers
|
||||
|
||||
---
|
||||
|
||||
## Milestone 6 — Power-user growth
|
||||
|
||||
### Vision
|
||||
|
||||
Expand capability without compromising the core.
|
||||
|
||||
### Candidate slices
|
||||
|
||||
- advanced UV tools
|
||||
- nav waypoints authoring
|
||||
- camera zones / guided tours
|
||||
- ambient zones and audio buses
|
||||
- lightweight scripting
|
||||
- plugin/tool API
|
||||
- collaborative editing groundwork
|
||||
- remote asset libraries
|
||||
- scene templates/starter kits
|
||||
|
||||
These are only pursued after the earlier core loop feels solid.
|
||||
|
||||
---
|
||||
|
||||
## Priority order inside the roadmap
|
||||
|
||||
When schedule pressure forces tradeoffs, prefer work that strengthens:
|
||||
|
||||
1. edit -> save/load -> run loop
|
||||
2. brush ergonomics
|
||||
3. material/texture speed
|
||||
4. typed entities and interactions
|
||||
5. imported asset support
|
||||
6. runner stability and input/audio quality
|
||||
7. ecosystem niceties
|
||||
|
||||
---
|
||||
|
||||
## Definition of “vertical slice complete”
|
||||
|
||||
A slice is complete only when:
|
||||
|
||||
- the feature is usable by a human end-to-end
|
||||
- it is represented in the canonical document
|
||||
- it supports save/load
|
||||
- it is visible and usable in the UI
|
||||
- it is test-covered appropriately
|
||||
- obvious failure modes are handled
|
||||
- it does not violate architecture boundaries
|
||||
|
||||
---
|
||||
|
||||
## Known risk areas
|
||||
|
||||
### High-risk technical areas
|
||||
|
||||
- brush geometry robustness
|
||||
- per-face UV persistence
|
||||
- picking accuracy
|
||||
- collision generation from brush data
|
||||
- imported asset/material compatibility
|
||||
- browser audio unlock behavior
|
||||
- input edge cases across browsers
|
||||
- export correctness
|
||||
|
||||
### Process risks
|
||||
|
||||
- overbuilding infrastructure before a slice needs it
|
||||
- letting the three.js scene graph become canonical state
|
||||
- adding too many entity types too early
|
||||
- under-testing geometry/serialization boundaries
|
||||
- chasing polish before proving workflow
|
||||
|
||||
---
|
||||
|
||||
## Quality gates by milestone
|
||||
|
||||
### M0 quality gate
|
||||
- app boots
|
||||
- empty document loads
|
||||
- docs stable
|
||||
- tests run
|
||||
|
||||
### M1 quality gate
|
||||
- user can make a textured room, save/reload it, and walk it
|
||||
|
||||
### M2 quality gate
|
||||
- user can place interactive entities without code
|
||||
|
||||
### M3 quality gate
|
||||
- user can import a GLB and combine it with brush scenes, animation, and audio
|
||||
|
||||
### M4 quality gate
|
||||
- editor starts feeling genuinely ergonomic
|
||||
|
||||
### M5 quality gate
|
||||
- project becomes reusable for real experiments / small productions
|
||||
|
||||
---
|
||||
|
||||
## Deferred items list
|
||||
|
||||
These are explicitly deferred unless reprioritized:
|
||||
|
||||
- full multiplayer collaboration
|
||||
- advanced physics gameplay
|
||||
- procedural generation systems
|
||||
- full scripting VM
|
||||
- lightmapping pipeline
|
||||
- node-based materials
|
||||
- native desktop packaging as a priority
|
||||
- R3F integration as a core dependency
|
||||
- custom rendering backend beyond three.js
|
||||
|
||||
---
|
||||
|
||||
## Expected first public “wow” moment
|
||||
|
||||
The first moment that will make the product feel truly exciting is likely this:
|
||||
|
||||
1. create a brutalist room with box brushes
|
||||
2. texture faces quickly from the library
|
||||
3. import an animated GLB sculpture or door
|
||||
4. place a positional sound source
|
||||
5. hit Run
|
||||
6. walk through it in-browser with sound and interaction
|
||||
|
||||
The roadmap should always move toward making that loop feel better.
|
||||
649
testing.md
Normal file
649
testing.md
Normal file
@@ -0,0 +1,649 @@
|
||||
# testing.md
|
||||
|
||||
## Philosophy
|
||||
|
||||
This project is a tool and a runtime.
|
||||
|
||||
That means we must test both:
|
||||
|
||||
- **correctness of authored data and transformations**
|
||||
- **actual browser behavior experienced by the user**
|
||||
|
||||
We do not rely on a single testing style.
|
||||
We use a layered strategy:
|
||||
|
||||
1. unit tests
|
||||
2. domain/model tests
|
||||
3. geometry and serialization tests
|
||||
4. browser-level integration tests
|
||||
5. end-to-end tests
|
||||
6. manual QA for spatial/editor ergonomics
|
||||
|
||||
The goal is not maximal test count.
|
||||
The goal is confidence in the edit -> save/load -> run loop.
|
||||
|
||||
---
|
||||
|
||||
## Testing priorities
|
||||
|
||||
Highest-priority confidence areas:
|
||||
|
||||
1. document validity and migrations
|
||||
2. undo/redo correctness
|
||||
3. brush generation correctness
|
||||
4. per-face material/UV persistence
|
||||
5. runtime build correctness
|
||||
6. asset import survival
|
||||
7. runner navigation/input reliability
|
||||
8. spatial audio and interaction basics
|
||||
9. critical regressions caught in CI
|
||||
|
||||
---
|
||||
|
||||
## Test stack
|
||||
|
||||
Recommended baseline:
|
||||
|
||||
- **Vitest** for unit and integration tests
|
||||
- **Vitest Browser Mode** where real browser behavior is needed at component/integration level
|
||||
- **Playwright** for end-to-end testing
|
||||
- optional lightweight golden fixtures for serialized documents and runtime builds
|
||||
|
||||
No snapshot-heavy strategy by default.
|
||||
Prefer explicit assertions over giant snapshots.
|
||||
|
||||
---
|
||||
|
||||
## Global testing rules
|
||||
|
||||
### Schema changes
|
||||
|
||||
Whenever the persisted `SceneDocument` schema changes:
|
||||
|
||||
- make the compatibility decision explicit
|
||||
- bump the version when needed
|
||||
- add at least one migration or compatibility test
|
||||
|
||||
### Persistence coverage
|
||||
|
||||
For every author-authored feature that persists:
|
||||
|
||||
- add a round-trip save/load test
|
||||
- cover the current persistence path used by the product at that milestone
|
||||
- avoid assuming that runtime-only state is persisted
|
||||
|
||||
### Small fixtures
|
||||
|
||||
Prefer tiny, explicit fixtures over large assets or giant snapshots.
|
||||
|
||||
---
|
||||
|
||||
## Test categories
|
||||
|
||||
## 1. Pure unit tests
|
||||
|
||||
Purpose:
|
||||
|
||||
- fast confidence on isolated logic
|
||||
|
||||
Scope:
|
||||
|
||||
- math helpers
|
||||
- grid snapping
|
||||
- ID utilities
|
||||
- small schema defaults
|
||||
- validation helpers
|
||||
- transform calculations
|
||||
- UV helper logic
|
||||
- entity defaulting logic
|
||||
|
||||
Characteristics:
|
||||
|
||||
- no DOM
|
||||
- no WebGL
|
||||
- no three.js renderer boot if avoidable
|
||||
- deterministic
|
||||
- extremely fast
|
||||
|
||||
Examples:
|
||||
|
||||
- `snapValue(1.23, 0.5) -> 1.0`
|
||||
- UV rotate/flip calculations
|
||||
- entity schema default application
|
||||
- command label generation if logic matters
|
||||
|
||||
---
|
||||
|
||||
## 2. Domain/model tests
|
||||
|
||||
Purpose:
|
||||
|
||||
- validate the canonical document model and command behavior
|
||||
|
||||
Scope:
|
||||
|
||||
- document factories
|
||||
- migrations
|
||||
- command execution
|
||||
- command undo/redo
|
||||
- selection semantics where model-driven
|
||||
- validation rules
|
||||
|
||||
Examples:
|
||||
|
||||
- create brush command adds valid brush
|
||||
- undo removes it cleanly
|
||||
- redo restores the same result
|
||||
- invalid entity reference is detected
|
||||
- old scene version migrates correctly
|
||||
|
||||
These tests should not need a browser renderer.
|
||||
|
||||
---
|
||||
|
||||
## 3. Geometry tests
|
||||
|
||||
Purpose:
|
||||
|
||||
- verify brush/kernel correctness
|
||||
|
||||
Scope:
|
||||
|
||||
- primitive generation
|
||||
- face generation
|
||||
- topology expectations
|
||||
- collision mesh generation
|
||||
- UV projection generation
|
||||
- clipping results
|
||||
- derived mesh determinism
|
||||
|
||||
Examples:
|
||||
|
||||
- box brush creates expected face count
|
||||
- stairs generator creates expected step count
|
||||
- fit-to-face UV produces finite values
|
||||
- clipping yields valid child brushes
|
||||
- generated geometry contains no NaNs
|
||||
- rebuild is deterministic for the same input
|
||||
|
||||
### Geometry test principles
|
||||
|
||||
- assert invariants, not fragile exact arrays unless necessary
|
||||
- prefer bounded numeric comparisons
|
||||
- verify no degenerate triangles where required
|
||||
- test edge cases: tiny sizes, rejected zero-like values, unsupported cases failing clearly
|
||||
|
||||
Geometry is a high-risk area and deserves dense testing.
|
||||
|
||||
---
|
||||
|
||||
## 4. Serialization tests
|
||||
|
||||
Purpose:
|
||||
|
||||
- ensure document persistence is trustworthy
|
||||
|
||||
Scope:
|
||||
|
||||
- save/load round trips
|
||||
- migration paths
|
||||
- invalid file handling
|
||||
- missing refs behavior
|
||||
- canonical normalization if any
|
||||
|
||||
Examples:
|
||||
|
||||
- scene round-trips without losing face materials
|
||||
- UV state survives save/load
|
||||
- imported asset refs survive save/load
|
||||
- unsupported version throws an understandable error
|
||||
- migration from v1 to v2 preserves semantics
|
||||
|
||||
### Required pattern
|
||||
|
||||
For every substantial document feature, add at least:
|
||||
|
||||
- one round-trip save/load test
|
||||
- one migration or backward-compatibility consideration if schema changed
|
||||
|
||||
---
|
||||
|
||||
## 5. Browser integration tests
|
||||
|
||||
Purpose:
|
||||
|
||||
- verify real browser behavior that pure tests cannot cover
|
||||
|
||||
Use for:
|
||||
|
||||
- pointer interactions
|
||||
- keyboard shortcut handling
|
||||
- focus issues
|
||||
- canvas/UI interaction boundaries
|
||||
- panel interactions
|
||||
- browser API edge behavior
|
||||
- audio unlock flows where practical
|
||||
- pointer lock flows where practical
|
||||
|
||||
Examples:
|
||||
|
||||
- clicking viewport selects a brush
|
||||
- dragging a gizmo updates inspector values
|
||||
- applying material through UI changes a selected face
|
||||
- entering play mode mounts the runtime canvas
|
||||
- pointer lock request path is handled correctly
|
||||
|
||||
---
|
||||
|
||||
## 6. End-to-end tests
|
||||
|
||||
Purpose:
|
||||
|
||||
- verify the actual user flows across the product
|
||||
|
||||
Playwright covers:
|
||||
|
||||
- page loading
|
||||
- cross-browser execution
|
||||
- real input simulation
|
||||
- visible UI assertions
|
||||
- route/deployment behavior
|
||||
- screenshot and trace capture on failures
|
||||
|
||||
### Required e2e flows for early milestones
|
||||
|
||||
#### E2E-01 Empty app boots
|
||||
- app loads
|
||||
- viewport visible
|
||||
- no fatal console errors
|
||||
|
||||
#### E2E-02 Create box brush
|
||||
- create box brush
|
||||
- select it
|
||||
- persist through the current save path
|
||||
- reload
|
||||
- brush still exists
|
||||
|
||||
#### E2E-03 Apply material
|
||||
- create room or brush
|
||||
- assign material to a face
|
||||
- persist through the current save path
|
||||
- reload
|
||||
- material persists
|
||||
|
||||
#### E2E-04 Run scene
|
||||
- place `PlayerStart`
|
||||
- enter run mode
|
||||
- runtime loads
|
||||
- first-person or orbit mode active
|
||||
|
||||
#### E2E-05 Import asset
|
||||
- import test GLB
|
||||
- place a model instance
|
||||
- reload
|
||||
- instance remains visible
|
||||
|
||||
#### E2E-06 Trigger action
|
||||
- create trigger and target
|
||||
- run scene
|
||||
- activate trigger
|
||||
- target effect occurs
|
||||
|
||||
These flows should expand with milestones.
|
||||
|
||||
---
|
||||
|
||||
## 7. Manual QA
|
||||
|
||||
Some qualities are hard to fully automate, especially in spatial tools.
|
||||
|
||||
Manual QA is required for:
|
||||
|
||||
- authoring feel
|
||||
- camera comfort
|
||||
- snapping quality
|
||||
- transform ergonomics
|
||||
- texture workflow speed
|
||||
- runtime movement feel
|
||||
- browser UX polish
|
||||
- spatial audio perception
|
||||
|
||||
### Manual QA checklist style
|
||||
|
||||
Every slice should include:
|
||||
|
||||
- setup
|
||||
- expected steps
|
||||
- expected result
|
||||
- known limitations
|
||||
- browser(s) tested
|
||||
- screenshots or short recordings if helpful
|
||||
|
||||
---
|
||||
|
||||
## Test directory guidance
|
||||
|
||||
Suggested structure:
|
||||
|
||||
```txt
|
||||
src/
|
||||
...
|
||||
tests/
|
||||
unit/
|
||||
domain/
|
||||
geometry/
|
||||
serialization/
|
||||
browser/
|
||||
e2e/
|
||||
fixtures/
|
||||
documents/
|
||||
assets/
|
||||
exports/
|
||||
```
|
||||
|
||||
Alternative layouts are fine if the categories remain conceptually clear.
|
||||
|
||||
---
|
||||
|
||||
## Naming conventions
|
||||
|
||||
Use descriptive names.
|
||||
|
||||
Good:
|
||||
|
||||
- `create-box-brush.command.test.ts`
|
||||
- `scene-roundtrip.materials.test.ts`
|
||||
- `runtime-trigger-teleport.e2e.ts`
|
||||
|
||||
Bad:
|
||||
|
||||
- `misc.test.ts`
|
||||
- `editor2.test.ts`
|
||||
- `utils.spec.ts`
|
||||
|
||||
Test names should tell a future reader:
|
||||
|
||||
- what behavior is being protected
|
||||
- what broke if it fails
|
||||
|
||||
---
|
||||
|
||||
## Core invariants to protect
|
||||
|
||||
The following invariants are important enough to deserve repeated coverage:
|
||||
|
||||
### Document invariants
|
||||
|
||||
- IDs are unique
|
||||
- references resolve or fail clearly
|
||||
- version is known/migratable
|
||||
- entity payload matches type schema
|
||||
- model instances are not mixed into entity collections
|
||||
|
||||
### Command invariants
|
||||
|
||||
- execute changes state correctly
|
||||
- undo restores previous state
|
||||
- redo reproduces execute result
|
||||
- command history remains coherent
|
||||
|
||||
### Geometry invariants
|
||||
|
||||
- generated meshes contain finite numeric values
|
||||
- expected face counts/topology rules hold
|
||||
- collision/output is deterministic
|
||||
- invalid inputs fail safely
|
||||
|
||||
### Serialization invariants
|
||||
|
||||
- save/load preserves semantics
|
||||
- unsupported versions do not silently corrupt
|
||||
- migrations are explicit and tested
|
||||
- binary asset persistence survives the current project-storage strategy
|
||||
|
||||
### Runtime invariants
|
||||
|
||||
- runner loads valid scenes
|
||||
- missing optional systems fail gracefully
|
||||
- navigation controller activation is exclusive and consistent
|
||||
- interactions target the correct entities or model instances
|
||||
|
||||
---
|
||||
|
||||
## What to unit test vs what to e2e test
|
||||
|
||||
### Unit test
|
||||
|
||||
When logic is:
|
||||
|
||||
- deterministic
|
||||
- isolated
|
||||
- data-heavy
|
||||
- performance-sensitive
|
||||
- easier to debug outside the browser
|
||||
|
||||
Examples:
|
||||
|
||||
- brush face generation
|
||||
- UV transforms
|
||||
- validation
|
||||
- migrations
|
||||
- command sequencing
|
||||
|
||||
### E2E test
|
||||
|
||||
When behavior depends on:
|
||||
|
||||
- actual browser input behavior
|
||||
- canvas and DOM interaction
|
||||
- route/app boot
|
||||
- browser APIs
|
||||
- focus/pointer lock/input timing
|
||||
- asset load flows
|
||||
|
||||
Examples:
|
||||
|
||||
- selecting and moving things via UI
|
||||
- entering play mode
|
||||
- first-person input behavior
|
||||
- import workflow if browser-exposed
|
||||
- prompt/click interactions
|
||||
|
||||
---
|
||||
|
||||
## Fixture strategy
|
||||
|
||||
Use small, explicit fixtures.
|
||||
|
||||
### Document fixtures
|
||||
|
||||
- minimal empty doc
|
||||
- one-box-room
|
||||
- textured-room
|
||||
- trigger-scene
|
||||
- imported-asset-scene
|
||||
- migration-old-version scene
|
||||
|
||||
### Asset fixtures
|
||||
|
||||
- tiny GLB static mesh
|
||||
- tiny GLB animated mesh
|
||||
- simple audio file
|
||||
- placeholder textures
|
||||
|
||||
Keep fixtures:
|
||||
|
||||
- tiny
|
||||
- deterministic
|
||||
- checked into the repo when legally safe
|
||||
- documented
|
||||
|
||||
Do not use giant random assets in core CI.
|
||||
|
||||
---
|
||||
|
||||
## Browser support testing
|
||||
|
||||
At minimum, regularly test in:
|
||||
|
||||
- Chromium
|
||||
- Firefox
|
||||
- WebKit where relevant
|
||||
|
||||
Not every test must run in every browser in every iteration, but critical e2e coverage should include cross-browser confidence at appropriate cadence.
|
||||
|
||||
Early CI suggestion:
|
||||
|
||||
- smoke in Chromium on every push
|
||||
- broader cross-browser on main branch / PR gate / nightly depending on cost
|
||||
|
||||
---
|
||||
|
||||
## CI expectations
|
||||
|
||||
Baseline CI pipeline should include:
|
||||
|
||||
1. install
|
||||
2. typecheck
|
||||
3. lint
|
||||
4. unit/domain/geometry/serialization tests
|
||||
5. browser integration tests where stable
|
||||
6. Playwright smoke/e2e subset
|
||||
7. test artifact upload on failure
|
||||
|
||||
### Required artifacts on e2e failure
|
||||
|
||||
Capture where possible:
|
||||
|
||||
- screenshots
|
||||
- traces
|
||||
- video if worth the storage cost
|
||||
- console logs
|
||||
- failed document/export fixture if relevant
|
||||
|
||||
These artifacts materially reduce debugging time.
|
||||
|
||||
---
|
||||
|
||||
## Performance testing
|
||||
|
||||
Do not overcomplicate early performance testing, but do track basic regressions.
|
||||
|
||||
Recommended early checks:
|
||||
|
||||
- app boot time smoke metric
|
||||
- scene build time for a representative small scene
|
||||
- brush rebuild time for representative test cases
|
||||
- asset import of a small reference GLB
|
||||
- runtime frame stability in a standard test scene
|
||||
|
||||
This can begin as manual/dev benchmarking and later become more formal if needed.
|
||||
|
||||
---
|
||||
|
||||
## Audio testing notes
|
||||
|
||||
Spatial audio is important, but automated audio verification is limited.
|
||||
|
||||
### Automate what we can
|
||||
|
||||
- sound entities load
|
||||
- trigger paths call correct audio system methods
|
||||
- invalid audio refs surface errors
|
||||
- autoplay rules behave as expected in app state
|
||||
|
||||
### Manually verify
|
||||
|
||||
- perceived spatial positioning
|
||||
- distance attenuation feel
|
||||
- loop transition quality
|
||||
- browser-specific unlock friction
|
||||
|
||||
Include manual audio QA notes in slices touching audio.
|
||||
|
||||
---
|
||||
|
||||
## Input testing notes
|
||||
|
||||
Input in browser apps is full of edge cases.
|
||||
|
||||
Explicitly test:
|
||||
|
||||
- keyboard focus transitions
|
||||
- pointer lock enter/exit
|
||||
- escape handling
|
||||
- canvas vs panel focus
|
||||
- gamepad absent/present behavior
|
||||
- drag cancellation when pointer leaves element/window
|
||||
|
||||
Where automating is hard, document the manual verification steps.
|
||||
|
||||
---
|
||||
|
||||
## Regression policy
|
||||
|
||||
Every bug fix should add one of:
|
||||
|
||||
- a unit/domain/geometry test
|
||||
- a browser integration test
|
||||
- an e2e test
|
||||
- a documented manual regression step if automation is genuinely not feasible yet
|
||||
|
||||
Do not accept “fixed” without protecting against recurrence.
|
||||
|
||||
---
|
||||
|
||||
## Done criteria from a testing perspective
|
||||
|
||||
A slice is not done until:
|
||||
|
||||
- happy path is covered
|
||||
- one obvious failure path is covered
|
||||
- save/load or persistence path is covered if the feature is author-authored
|
||||
- manual QA notes are written
|
||||
- test commands are documented if new setup is needed
|
||||
|
||||
---
|
||||
|
||||
## Minimum test commands to maintain
|
||||
|
||||
Keep the project easy to verify.
|
||||
|
||||
Recommended scripts:
|
||||
|
||||
```json
|
||||
{
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"test:browser": "vitest --browser --run",
|
||||
"test:e2e": "playwright test",
|
||||
"test:e2e:ui": "playwright test --ui",
|
||||
"test:typecheck": "tsc --noEmit"
|
||||
}
|
||||
```
|
||||
|
||||
Exact commands may evolve, but the repo should always expose a simple path for:
|
||||
|
||||
- fast local checks
|
||||
- browser checks
|
||||
- e2e checks
|
||||
- CI checks
|
||||
|
||||
---
|
||||
|
||||
## What we do not test aggressively yet
|
||||
|
||||
Initially, avoid over-investing in:
|
||||
|
||||
- screenshot snapshot forests
|
||||
- fragile pixel-perfect rendering tests
|
||||
- massive browser matrix on every commit
|
||||
- giant scene stress tests before the core workflow is stable
|
||||
- plugin systems we do not yet have
|
||||
|
||||
Test the heart of the product first:
|
||||
|
||||
- data integrity
|
||||
- brush correctness
|
||||
- interaction correctness
|
||||
- runtime usability
|
||||
Reference in New Issue
Block a user