diff --git a/AGENTS.md b/AGENTS.md
index d2ddad09f0..959f2f806b 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -46,7 +46,7 @@ One source, two runtimes: browser WebGPU and an owned C++ host for desktop/Andro
2. **Kill switch.** An abstraction costing more code than plain Three.js is deleted; `scripts/count-loc.ts` scores every repetition.
3. **Never own the look.** Geometry, material, colour, texture, curve and timing come from the game; it must be able to change the appearance completely without editing package code. `GPUParticles3D` is the shape.
4. **Borrow vocabulary**: Godot for nodes (the only node source), Three.js for rendering, Rapier for physics, Tailwind for UI, in camelCase. **A package exists only when it carries a dependency the others must not inherit.**
-5. **Closed, outranking rule 1**: an IR, a scene format, an editor, a preset/genre system, a code-first ECS, a bespoke CLI vocabulary. **Web-only is unfinished**: a helper admitted for being unportable ships native proof (a conformance case or a `--target` playtest) in the same commit, and no result claims a platform it did not run on. Contract: `packages/runtime-native/AGENTS.md`.
+5. **Closed, outranking rule 1**: an authored IR, a second renderer, a scene format, an editor, a preset/genre system, a code-first ECS, a bespoke CLI vocabulary. **Web-only is unfinished**: a helper admitted for being unportable ships native proof (a conformance case or a `--target` playtest) in the same commit, and no result claims a platform it did not run on. Contract: `packages/runtime-native/AGENTS.md`. **One exception, opt-in**: the owned C++ engine (renderer plus internal shader IR) behind the Three.js API; legacy stays the default until it proves itself (`docs/architecture/NATIVE-ENGINE-DECISION.md`).
## Commands
diff --git a/CLAUDE.md b/CLAUDE.md
index 7afe3b15ba..237b2733cc 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -48,7 +48,7 @@ One source, two runtimes: browser WebGPU and an owned C++ host for desktop/Andro
2. **Kill switch.** An abstraction costing more code than plain Three.js is deleted; `scripts/count-loc.ts` scores every repetition.
3. **Never own the look.** Geometry, material, colour, texture, curve and timing come from the game; it must be able to change the appearance completely without editing package code. `GPUParticles3D` is the shape.
4. **Borrow vocabulary**: Godot for nodes (the only node source), Three.js for rendering, Rapier for physics, Tailwind for UI, in camelCase. **A package exists only when it carries a dependency the others must not inherit.**
-5. **Closed, outranking rule 1**: an IR, a scene format, an editor, a preset/genre system, a code-first ECS, a bespoke CLI vocabulary. **Web-only is unfinished**: a helper admitted for being unportable ships native proof (a conformance case or a `--target` playtest) in the same commit, and no result claims a platform it did not run on. Contract: `packages/runtime-native/AGENTS.md`.
+5. **Closed, outranking rule 1**: an authored IR, a second renderer, a scene format, an editor, a preset/genre system, a code-first ECS, a bespoke CLI vocabulary. **Web-only is unfinished**: a helper admitted for being unportable ships native proof (a conformance case or a `--target` playtest) in the same commit, and no result claims a platform it did not run on. Contract: `packages/runtime-native/AGENTS.md`. **One exception, opt-in**: the owned C++ engine (renderer plus internal shader IR) behind the Three.js API; legacy stays the default until it proves itself (`docs/architecture/NATIVE-ENGINE-DECISION.md`).
## Commands
diff --git a/docs/architecture/CHARTER-HISTORY.md b/docs/architecture/CHARTER-HISTORY.md
index ae93935977..8d11d34e59 100644
--- a/docs/architecture/CHARTER-HISTORY.md
+++ b/docs/architecture/CHARTER-HISTORY.md
@@ -14,3 +14,4 @@ Charter itself can state the current rule without carrying its own diff history.
| 2026-09-02 | all | Condensed. Rationale that had been restated across sections is stated once; open work and known limitations move to [`CURRENT-CHALLENGES.md`](../CURRENT-CHALLENGES.md). No rule changed. |
| 2026-09-05 | §1 | Added the out-of-the-box principle: ordinary games work without configuration pain, and configuration remains an escape hatch rather than a prerequisite. |
| 2026-09-30 (PRDs 466–468) | §2, §9a, §11.5 | Owner-approved optional Strata terrain-authoring addon, editable terrain documents and terrain-only authoring companions; baked runtime data and game-owned appearance, with no general game editor or runtime recipe/scene format. |
+| 2026-10-12 (N00) | §2, §6b, §7, §11.1 | Owner-accepted native engine: one owned C++ engine (renderer plus internal shader IR) behind the Three.js API, opt-in per game, with the legacy host as the default until it proves itself. The closed list now bans an *authored* IR; any other renderer stays closed. Record: [`NATIVE-ENGINE-DECISION.md`](NATIVE-ENGINE-DECISION.md). |
diff --git a/docs/architecture/CHARTER.md b/docs/architecture/CHARTER.md
index 3843b09f81..06766b4128 100644
--- a/docs/architecture/CHARTER.md
+++ b/docs/architecture/CHARTER.md
@@ -96,8 +96,8 @@ thesis: each spends the training-data advantage to buy a surface the model then
| Not building | Why |
|---|---|
-| An IR, a compiler, a serialized scene format | Your game is TypeScript. The compiler was 25,898 LOC and bought nothing a model can't do with a `.ts` file. |
-| A second *renderer* | 32% of v1's commits went to a runtime no benchmark ever measured. §7's host is the bounded exception: it runs Three.js, it does not replace it. The moment the host starts drawing, it has become v1. |
+| An authored IR, a compiler of game code, a serialized scene format | Your game is TypeScript. The compiler was 25,898 LOC and bought nothing a model can't do with a `.ts` file. The opt-in native engine's shader IR is internal: no game or author writes it. |
+| A second *renderer* | 32% of v1's commits went to a runtime no benchmark ever measured. §7's host runs Three.js, it does not replace it. **One exception (owner, 2026-10-12):** ThreeNative owns one C++ engine, renderer plus internal shader IR, behind the Three.js API. A game opts in; the legacy host stays the default until measured benchmarks prove the engine ([`NATIVE-ENGINE-DECISION.md`](NATIVE-ENGINE-DECISION.md)). Any renderer beyond that one engine has become v1. |
| A JSON/structured-source ECS | Measured at **14x vanilla Three.js** on greenfield work, and scored lower on playability and visuals. |
| An editor | Not in v1. The paid editor is a separate product in a separate repository. |
| A bespoke CLI vocabulary | 178 command forms, a 2,477-word root help. Models are worst at discovering novel API surfaces. |
@@ -395,7 +395,7 @@ and a bitmap font against the browser's whole CSS, SVG and font stack.
the same Tailwind or plain CSS run with no WebView: the game's own JS realm reconciles React into
an element tree held by an in-process, third-party CSS engine (Stylo, Taffy and Parley through
Blitz), and the result is painted into a CPU surface that the compositor draws over the frame. This
-is the one exception to "no second renderer": the engine owns a UI-only element tree and a UI-only
+is also an exception to "no second renderer": the engine owns a UI-only element tree and a UI-only
surface. It never renders the 3D game, exposes no scene or style IR to game code, does not replace
Three.js, and imposes no look — the stylesheet is the game's own, from the same Vite and Tailwind
build the web renderer uses. It claims only what its fixtures prove; unsupported CSS is not
@@ -461,8 +461,11 @@ Mystral is absorbed as the owned `packages/runtime-native/` fork. Its C++ and pl
in one workspace package; Dawn, V8, QuickJS, SDL3, wgpu-native and other dependency trees stay
downloaded into an untracked `third_party/`.
-**The runtime is a host, not a renderer.** It must not own Three's renderer, fork Three.js, or
-replace the JavaScript `GLTFLoader`. Three.js compatibility must equal the workspace catalog.
+**The default runtime is a host, not a renderer.** It must not own Three's renderer, fork Three.js, or
+replace the JavaScript `GLTFLoader`. Three.js compatibility must equal the workspace catalog. The
+opt-in native engine of [`NATIVE-ENGINE-DECISION.md`](NATIVE-ENGINE-DECISION.md) is the one
+exception: it implements the Three.js API in C++, a game selects it, and it changes nothing for a
+game that does not.
Native physics is compiled into the runtime and exposed through a coarse, host-neutral typed-array
ABI, with bulk `step`/`readVisibleTransforms` crossings rather than per-object frame calls. The
@@ -690,7 +693,7 @@ fifteen lines.
**Four things this does not loosen:**
-1. **§2's closed list outranks both questions.** An IR, a scene format, an editor, a
+1. **§2's closed list outranks both questions.** An authored IR, a scene format, an editor, a
preset/genre/recipe system, a code-first ECS and a bespoke CLI vocabulary stay closed however
cleanly they pass.
2. **§11.2 applies retroactively to everything admitted here.** Generous on the way in is only safe
diff --git a/docs/architecture/NATIVE-ENGINE-DECISION.md b/docs/architecture/NATIVE-ENGINE-DECISION.md
new file mode 100644
index 0000000000..06b3962097
--- /dev/null
+++ b/docs/architecture/NATIVE-ENGINE-DECISION.md
@@ -0,0 +1,176 @@
+# Native engine — architecture decision record (N00)
+
+**Status:** binding. The owner took the decision on 2026-10-04 (interview) and accepted the agent
+calls below the same day. On 2026-10-12 the owner accepted the charter amendment: ThreeNative owns
+one C++ engine (renderer plus internal shader IR) behind the Three.js API, **opt-in per game**, and
+the legacy host stays the default until the engine proves itself.
+
+**What it changes today:** the rule text of [`CHARTER.md`](CHARTER.md) §2, §7 and §11.1 and of root
+`AGENTS.md` rule 5 admits the engine. [`NATIVE-RUNTIME.md`](NATIVE-RUNTIME.md) and
+[`packages/runtime-native/AGENTS.md`](../../packages/runtime-native/AGENTS.md) keep describing the
+shipped host. They change in the commit that ships the first native-engine artifact, because primary
+docs name only shipped things.
+
+**Work package:** N00 of the native-engine batch (source PRD-497). The engine reaches `develop` in
+small slices. Each slice is inert or opt-in until the next one lands.
+
+---
+
+## 1. What is decided
+
+ThreeNative adds an owned engine underneath the Three.js API, in C++. Every engine system of that
+engine runs in native code on every target; game code keeps its JavaScript VM. A game selects the
+engine; a game that does not select it runs on the legacy host exactly as before. The compatibility
+denominator is measured from what games actually import, not asserted as a percentage.
+
+```mermaid
+flowchart LR
+ api["Three.js API
what games write"] --> legacy["Legacy host + upstream three
default"]
+ api --> engine["One C++ engine
opt-in per game"]
+ engine --> v8["V8 game runtime
desktop and Android"]
+ engine --> wasm["Browser Wasm port
browser JS game runtime"]
+```
+
+## 2. The charter rules this amends, in plain words
+
+The charter outranks every `AGENTS.md`, so the reversal is quoted here rather than paraphrased.
+
+- **"A second *renderer*."** The charter's closed list of things that killed v1 names a second
+ renderer: the moment the host starts drawing instead of running Three.js, it has become v1.
+ **Amended:** ThreeNative owns one C++ engine behind the Three.js API, opt-in per game. The row's
+ objection — 32% of v1's commits went to a runtime no benchmark ever measured — is answered by
+ measurement instead of by a ban: the CP1 checkpoint (PRD-534) can stop the program, and the
+ engine becomes the default only on measured evidence. Any renderer beyond that one engine stays
+ closed.
+- **"The runtime is a host, not a renderer."** The charter's platform section says the runtime must
+ not own Three's renderer, fork Three.js, or replace the JavaScript `GLTFLoader`. **Amended:** the
+ rule stays for the default host. The opt-in engine *is* the renderer, and native glTF replaces the
+ JavaScript loader inside it.
+- **"An IR, a compiler, a serialized scene format."** The ban is kept exactly where it was aimed: no
+ authored IR, no scene format, and no compiler of game code as a **required authoring step**. The
+ engine's shader IR is internal and never authored.
+
+Everything else in the charter stands, including the kill switch, "never own the look", and the
+rule that the supported API is the measured denominator.
+
+## 3. The decisions
+
+Owner decisions, João, 2026-10-04 (interview):
+
+1. **The engine runs in C++.** Every system of the native engine runs in C++: traversal,
+ transforms, animation, batching, materials and TSL, visibility, streaming and rendering. No JS
+ implementation of an engine system ships inside the native engine on any target. Gate E is
+ mandatory.
+2. **Speed first; game code stays on a JS VM.** Game code runs on a JS VM (V8 on desktop and
+ Android, the browser's own engine on web) through generated bindings. The V8 game runtime
+ adapter (PRD-531, N18) is the shipping game runtime. Compiling game code to native is not part
+ of this decision.
+3. **An early perf checkpoint can stop the program.** CP1 (PRD-534) measures the native engine
+ against current ThreeNative after N06 + N09. With no CPU win in the engine hot paths, N11–N15 do
+ not start until the owner re-plans.
+4. **One engine everywhere.** The web runs the same C++ core in Wasm (PRD-532, N19, is mandatory).
+ The core is Wasm-safe from day one: single-thread fallback, retained views that survive memory
+ growth, no blocking waits.
+
+Calls made from the code by the agent, accepted by the owner ("go with what you think will be
+best"), 2026-10-04:
+
+5. **Charter amendment, in plain words:** "a second renderer" and "the runtime is a host, not a
+ renderer" admit one owned C++ engine behind the Three.js API. The closed list keeps banning an
+ authored IR, a scene format and a compiler of game code *as a required authoring step*. The
+ shader IR is internal and never authored.
+6. **The game API stays vanilla Three.js.** The charter's training-data thesis is the reason. The
+ supported surface is the measured denominator (§7), published in
+ `packages/create-threenative/capabilities.json`. An unsupported symbol fails at build, or at
+ scene preparation, with a named diagnostic. A game that selected the engine gets no silent
+ fallback to the legacy host.
+7. **`ctx.renderer.raw` survives as the compatible `WebGPURenderer`.** Templates read only public
+ renderer fields through it (`toneMapping`, `toneMappingExposure`, `shadowMap`, and setup passed
+ to `setupLighting`), so it returns the engine's Three-compatible renderer object.
+ Renderer-private fields and the raw GPU device are unsupported and named as such.
+8. **Bindings are generated from one catalog for several VMs:** V8 first (N18), browser JS over
+ Wasm next (N19), JSC when iOS returns. iOS is out of the first program but not designed out.
+9. **Binding crossing cost:** the per-object API stays Three-compatible. Bulk typed-array paths,
+ shaped like the existing physics ABI, are added only where CP1 shows that crossings cost real
+ frame time.
+10. **The legacy JS-owned engine stays the default until the native engine proves itself.**
+ Promotion to default (PRD-533, N20) needs the owner's call on measured evidence. The legacy
+ engine is deleted (PRD-535, N21) only one release after that promotion.
+
+Fixed by the proposal: C++20 for the engine, Dawn and wgpu-native retained, no upstream Three.js
+bundle inside the native engine.
+
+11. **The web build: Wasm engine, JavaScript game code (owner decision, 2026-10-05).** On the web
+ the C++ engine compiles to WebAssembly with Emscripten and renders through the browser's WebGPU
+ (PRD-532, N19); the game's TypeScript stays ordinary JavaScript run by the browser's JIT. A page
+ starts from JavaScript, and Wasm reaches WebGPU, input and the DOM through JS glue, so the
+ engine replaces only the three.js engine code in JS. Rules:
+ - **The GPU-side design comes first:** the engine owns scene state in Wasm memory; static draws
+ are recorded once as render bundles; culled instances draw indirectly; uniforms share one
+ buffer with dynamic offsets; the renderer runs in a Web Worker on an `OffscreenCanvas`;
+ animation, culling and decode use Wasm threads over `SharedArrayBuffer` where the host serves
+ cross-origin isolation (COOP/COEP).
+ - **The game-to-engine API is bulk by default:** typed-array views into Wasm memory and dirty
+ flags, not per-property calls every frame. Per-object calls stay available for authoring and
+ tooling.
+
+## 4. The gate
+
+**E — native engine.** A native application creates a scene, runs engine systems and renders with
+no dependency on V8, QuickJS, JavaScriptCore, Hermes, an engine JavaScript bundle or a WebView. A
+C++ test driver can establish it. **Mandatory**, per decision 1.
+
+Gate E is proved from the build dependency graph, linker and symbol inspection, the packaged
+resource inventory and runtime module inspection together — a filename scan for `.js` proves
+nothing, since a binary can embed a VM.
+
+## 5. Definitions
+
+| Term | Means |
+| --- | --- |
+| **Native engine** | The C++ implementation of scene state, traversal, transforms, animation, materials and TSL, visibility, streaming and rendering, behind the Three.js API. One engine, every platform, including web in Wasm. |
+| **Legacy host** | The shipped default: the game and upstream Three.js run on a JS VM, and the host maps WebGPU calls onto Dawn or wgpu. |
+| **Game runtime** | Whatever executes the game's own code: V8 on desktop and Android, the browser's own engine on web, JSC when iOS returns. |
+| **Native-engine artifact** | A game build that selected the engine: the engine runs in C++ and the game code runs on a VM. |
+| **WebView-UI labelling** | A WebView UI carries its own browser runtime, so a native-engine artifact shipping one is labelled as such. |
+
+Gate E's "no JavaScript engine" is scoped to the engine: no JavaScript engine executes an engine
+system. Build tools, binding generation, asset cooking and test drivers may use Node.js or
+TypeScript.
+
+**Non-goals.** No new Vulkan/Metal/D3D12 backend, no universal ECMAScript compiler, no mandatory ECS
+programming model, no replacement physics engine, no complete browser/DOM implementation, no editor
+rewrite. No iOS qualification in the first program. No Unreal-level visuals from changing the
+implementation language.
+
+## 6. Configuration dimensions and rejected combinations
+
+Three dimensions are configured separately: **engine implementation** × **game runtime** × **UI**.
+Contradictory combinations are rejected at packaging time, not tolerated at runtime.
+
+| Engine | Game runtime | UI | Artifact |
+| --- | --- | --- | --- |
+| Legacy host | VM | WebView or native | the default |
+| Native C++ | VM (V8, browser JS, JSC) | WebView or native | **native-engine artifact**, opt-in |
+| Native C++ | VM | WebView | allowed, labelled per §5 |
+
+Two rules follow. **There is no automatic fallback** from a native-engine artifact to the legacy
+host; the legacy host is a separately selected build, preserved until N21. And a target that claims
+native-engine independence must be inspected and proved as one, not assumed from a build flag.
+
+## 7. The pinned reference
+
+**`three@0.185.1` plus the ThreeNative patch
+[`packages/core/patches/three@0.185.1.patch`](../../packages/core/patches/three@0.185.1.patch) is
+the behavioural oracle.** Every compatibility claim — object semantics, numerics, animation,
+materials, shader packages — is measured against that exact pair, resolved through the workspace
+`catalog:` in [`pnpm-workspace.yaml`](../../pnpm-workspace.yaml).
+
+**Upgrading it is a deliberate batch, never drift.** TSL's API changes between three releases with no
+deprecation cycle, so a bump re-opens the measured denominator, the reference outputs and the
+baseline it was measured against; it is its own change with its own evidence, and never rides along
+with engine work.
+
+The compatibility denominator lands with the API catalog slice: every module reachable from
+`packages/core/src` is classified, and every `three*` symbol that templates and examples import
+becomes a row of the catalog.