@jgengine/editor 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +12 -0
  3. package/dist/AssetBrowser.d.ts +26 -1
  4. package/dist/AssetBrowser.js +54 -1
  5. package/dist/AssetDropZone.d.ts +9 -0
  6. package/dist/AssetDropZone.js +65 -0
  7. package/dist/CatalogsPanel.d.ts +4 -2
  8. package/dist/CatalogsPanel.js +162 -9
  9. package/dist/CityPreview.d.ts +11 -0
  10. package/dist/CityPreview.js +45 -0
  11. package/dist/CollectionsPanel.js +5 -5
  12. package/dist/DebugDraw.d.ts +3 -1
  13. package/dist/DebugDraw.js +37 -19
  14. package/dist/EditorApp.d.ts +9 -1
  15. package/dist/EditorApp.js +147 -35
  16. package/dist/EditorChrome.d.ts +25 -6
  17. package/dist/EditorChrome.js +310 -130
  18. package/dist/InspectorPanel.d.ts +17 -7
  19. package/dist/InspectorPanel.js +173 -27
  20. package/dist/LightingPanel.d.ts +11 -0
  21. package/dist/LightingPanel.js +99 -0
  22. package/dist/MaterialsWorkspacePanel.d.ts +12 -0
  23. package/dist/MaterialsWorkspacePanel.js +86 -0
  24. package/dist/ParentPickerMenu.d.ts +13 -0
  25. package/dist/ParentPickerMenu.js +33 -0
  26. package/dist/PerfProbe.js +33 -0
  27. package/dist/PrefabsPanel.js +5 -5
  28. package/dist/RuntimePlayBridge.d.ts +5 -3
  29. package/dist/RuntimePlayBridge.js +6 -13
  30. package/dist/ScatterPreview.d.ts +3 -1
  31. package/dist/ScatterPreview.js +10 -7
  32. package/dist/SchemaInspector.js +21 -8
  33. package/dist/ScriptingPanel.d.ts +15 -0
  34. package/dist/ScriptingPanel.js +46 -0
  35. package/dist/SelectionGizmo.js +114 -30
  36. package/dist/StandaloneEditor.d.ts +16 -9
  37. package/dist/StandaloneEditor.js +19 -20
  38. package/dist/TerrainPanel.d.ts +3 -2
  39. package/dist/TerrainPanel.js +16 -5
  40. package/dist/TerrainSculpt.js +98 -59
  41. package/dist/agent/AgentPanel.d.ts +5 -2
  42. package/dist/agent/AgentPanel.js +11 -6
  43. package/dist/agent/toolBridge.js +5 -0
  44. package/dist/assetImport.d.ts +36 -0
  45. package/dist/assetImport.js +66 -0
  46. package/dist/authoredComponentMeta.d.ts +25 -0
  47. package/dist/authoredComponentMeta.js +65 -0
  48. package/dist/gizmoPivot.d.ts +4 -0
  49. package/dist/gizmoPivot.js +34 -0
  50. package/dist/handlers/catalogs.d.ts +3 -0
  51. package/dist/handlers/catalogs.js +137 -0
  52. package/dist/handlers/collections.d.ts +3 -0
  53. package/dist/handlers/collections.js +57 -0
  54. package/dist/handlers/context.d.ts +36 -0
  55. package/dist/handlers/context.js +1 -0
  56. package/dist/handlers/document.d.ts +3 -0
  57. package/dist/handlers/document.js +350 -0
  58. package/dist/handlers/grids.d.ts +3 -0
  59. package/dist/handlers/grids.js +142 -0
  60. package/dist/handlers/hierarchy.d.ts +3 -0
  61. package/dist/handlers/hierarchy.js +55 -0
  62. package/dist/handlers/index.d.ts +8 -0
  63. package/dist/handlers/index.js +23 -0
  64. package/dist/handlers/minimap.d.ts +9 -0
  65. package/dist/handlers/minimap.js +32 -0
  66. package/dist/handlers/runtime.d.ts +3 -0
  67. package/dist/handlers/runtime.js +191 -0
  68. package/dist/handlers/terrain.d.ts +3 -0
  69. package/dist/handlers/terrain.js +204 -0
  70. package/dist/index.d.ts +3 -2
  71. package/dist/index.js +3 -2
  72. package/dist/listDocumentTriggers.d.ts +42 -0
  73. package/dist/listDocumentTriggers.js +49 -0
  74. package/dist/materialAssignments.d.ts +63 -0
  75. package/dist/materialAssignments.js +84 -0
  76. package/dist/mcp/fieldSpec.d.ts +32 -0
  77. package/dist/mcp/fieldSpec.js +173 -0
  78. package/dist/mcp/rpcRequest.d.ts +8 -5
  79. package/dist/mcp/rpcRequest.js +72 -93
  80. package/dist/mcp/tools.js +104 -912
  81. package/dist/networkSnapshot.d.ts +82 -0
  82. package/dist/networkSnapshot.js +73 -0
  83. package/dist/parentCandidates.d.ts +12 -0
  84. package/dist/parentCandidates.js +25 -0
  85. package/dist/session.d.ts +77 -4
  86. package/dist/session.js +36 -1017
  87. package/dist/shell/AnimationPanel.d.ts +17 -0
  88. package/dist/shell/AnimationPanel.js +134 -0
  89. package/dist/shell/AssetThumbnail.d.ts +12 -0
  90. package/dist/shell/AssetThumbnail.js +23 -0
  91. package/dist/shell/BottomDock.d.ts +25 -0
  92. package/dist/shell/BottomDock.js +40 -0
  93. package/dist/shell/CommandPalette.d.ts +12 -0
  94. package/dist/shell/CommandPalette.js +56 -0
  95. package/dist/shell/ConsolePanel.d.ts +8 -0
  96. package/dist/shell/ConsolePanel.js +45 -0
  97. package/dist/shell/ContentBrowser.d.ts +21 -0
  98. package/dist/shell/ContentBrowser.js +130 -0
  99. package/dist/shell/HierarchyPanel.d.ts +26 -0
  100. package/dist/shell/HierarchyPanel.js +387 -0
  101. package/dist/shell/NetworkWorkspacePanel.d.ts +11 -0
  102. package/dist/shell/NetworkWorkspacePanel.js +49 -0
  103. package/dist/shell/PlayModeBar.d.ts +12 -0
  104. package/dist/shell/PlayModeBar.js +27 -0
  105. package/dist/shell/ProfilerPanel.d.ts +10 -0
  106. package/dist/shell/ProfilerPanel.js +41 -0
  107. package/dist/shell/SceneToolbar.d.ts +43 -0
  108. package/dist/shell/SceneToolbar.js +122 -0
  109. package/dist/shell/StatusBar.d.ts +18 -0
  110. package/dist/shell/StatusBar.js +41 -0
  111. package/dist/shell/TopAppBar.d.ts +33 -0
  112. package/dist/shell/TopAppBar.js +64 -0
  113. package/dist/shell/ViewportOverlays.d.ts +23 -0
  114. package/dist/shell/ViewportOverlays.js +136 -0
  115. package/dist/shell/WorkspaceRail.d.ts +20 -0
  116. package/dist/shell/WorkspaceRail.js +31 -0
  117. package/dist/shell/cameraTelemetry.d.ts +27 -0
  118. package/dist/shell/cameraTelemetry.js +24 -0
  119. package/dist/shell/commandRegistry.d.ts +58 -0
  120. package/dist/shell/commandRegistry.js +133 -0
  121. package/dist/shell/consoleSink.d.ts +11 -0
  122. package/dist/shell/consoleSink.js +17 -0
  123. package/dist/shell/consoleStore.d.ts +27 -0
  124. package/dist/shell/consoleStore.js +43 -0
  125. package/dist/shell/fields.d.ts +39 -0
  126. package/dist/shell/fields.js +104 -0
  127. package/dist/shell/formatSavedRelative.d.ts +2 -0
  128. package/dist/shell/formatSavedRelative.js +14 -0
  129. package/dist/shell/glbThumbnailCache.d.ts +45 -0
  130. package/dist/shell/glbThumbnailCache.js +241 -0
  131. package/dist/shell/hierarchyA11y.d.ts +21 -0
  132. package/dist/shell/hierarchyA11y.js +35 -0
  133. package/dist/shell/icons.d.ts +13 -0
  134. package/dist/shell/icons.js +85 -0
  135. package/dist/shell/layoutStore.d.ts +68 -0
  136. package/dist/shell/layoutStore.js +156 -0
  137. package/dist/shell/pathFlythrough.d.ts +37 -0
  138. package/dist/shell/pathFlythrough.js +54 -0
  139. package/dist/shell/perfHistory.d.ts +70 -0
  140. package/dist/shell/perfHistory.js +130 -0
  141. package/dist/shell/renameObject.d.ts +3 -0
  142. package/dist/shell/renameObject.js +25 -0
  143. package/dist/shell/theme.d.ts +36 -0
  144. package/dist/shell/theme.js +37 -0
  145. package/dist/shell/ui.d.ts +84 -0
  146. package/dist/shell/ui.js +90 -0
  147. package/dist/shell/useGlbThumbnail.d.ts +8 -0
  148. package/dist/shell/useGlbThumbnail.js +19 -0
  149. package/dist/uiStore.d.ts +27 -0
  150. package/dist/uiStore.js +10 -0
  151. package/dist/viewportContextMenu.d.ts +4 -2
  152. package/dist/viewportContextMenu.js +5 -1
  153. package/package.json +4 -4
  154. package/skills/jgengine/SKILL.md +7 -4
  155. package/skills/jgengine/api.md +172 -79
  156. package/skills/jgengine/capabilities.md +104 -2
  157. package/skills/jgengine/recipes/minimal-game.md +88 -0
  158. package/skills/jgengine-editor/SKILL.md +18 -3
  159. package/skills/jgengine-editor/api.md +397 -18
  160. package/skills/jgengine-editor/capabilities.md +46 -0
  161. package/skills/jgengine-editor/reference.md +87 -0
  162. package/skills/level-design/SKILL.md +54 -0
  163. package/skills/level-design/agents/openai.yaml +4 -0
  164. package/skills/level-design/references/application-playbook.md +192 -0
  165. package/skills/level-design/references/field-guide.md +337 -0
  166. package/skills/level-design/references/live-editor-loop.md +179 -0
  167. package/dist/OutlinerPanel.d.ts +0 -14
  168. package/dist/OutlinerPanel.js +0 -84
  169. package/skills/jgengine/reference-cartridge.md +0 -72
@@ -11,8 +11,19 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
11
11
  - `EditorCatalogEntry` (interface) · `import { EditorCatalogEntry } from "@jgengine/core/editor"`
12
12
  - `findEditorCatalog` (function) · `import { findEditorCatalog } from "@jgengine/core/editor"`
13
13
  - `findEditorCatalogEntry` (function) · `import { findEditorCatalogEntry } from "@jgengine/core/editor"`
14
+ - `resolveCatalogDefinitions` (function) · `import { resolveCatalogDefinitions } from "@jgengine/core/editor"`
14
15
  - `seedEditorCatalogs` (function) · `import { seedEditorCatalogs } from "@jgengine/core/editor"`
15
16
 
17
+ ## editor-entities — Author entity stats/movement per catalog row instead of hardcoding TS.
18
+
19
+ - `entityDefinitionSchema` (const) · `import { entityDefinitionSchema } from "@jgengine/core/editor"`
20
+ - `entityEntryFromCatalog` (function) · `import { entityEntryFromCatalog } from "@jgengine/core/editor"`
21
+
22
+ ## editor-environment — persist sky/fog/lighting knobs on the scene document
23
+
24
+ - `EditorEnvironment` (interface) · `import { EditorEnvironment } from "@jgengine/core/editor"`
25
+ - `skyFromDocument` (function) · `import { skyFromDocument } from "@jgengine/core/editor"`
26
+
16
27
  ## editor-grid-import — Configure an ASCII/glyph → grid-layer import.
17
28
 
18
29
  - `AsciiGridImportOptions` (interface) · `import { AsciiGridImportOptions } from "@jgengine/core/editor"`
@@ -65,6 +76,12 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
65
76
  - `runtimeEntityMetaWriteBackCommand` (function) · `import { runtimeEntityMetaWriteBackCommand } from "@jgengine/core/editor"`
66
77
  - `summarizeRuntimeInspector` (function) · `import { summarizeRuntimeInspector } from "@jgengine/core/editor"`
67
78
 
79
+ ## minimap-bake — persist a baked minimap PNG + bounds on the scene document
80
+
81
+ - `EditorMinimapBake` (interface) · `import { EditorMinimapBake } from "@jgengine/core/editor"`
82
+ - `bakeMinimapFromDocument` (function) · `import { bakeMinimapFromDocument } from "@jgengine/core/editor"`
83
+ - `documentBakeZones` (function) · `import { documentBakeZones } from "@jgengine/core/editor"`
84
+
68
85
  ## scene-ownership — audit a whole ownership manifest for boundary violations
69
86
 
70
87
  - `auditManifest` (function) · `import { auditManifest } from "@jgengine/core/scene/sceneOwnership"`
@@ -72,3 +89,32 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
72
89
  - `collectOwnershipDiagnostics` (function) · `import { collectOwnershipDiagnostics } from "@jgengine/core/scene/sceneOwnership"`
73
90
  - `isSceneOwnershipManifest` (function) · `import { isSceneOwnershipManifest } from "@jgengine/core/scene/sceneOwnership"`
74
91
  - `ownershipKey` (function) · `import { ownershipKey } from "@jgengine/core/scene/sceneOwnership"`
92
+
93
+ ## world-convergence — derive environment coordinate content from the scene document
94
+
95
+ - `environmentContentFromDocument` (function) · `import { environmentContentFromDocument } from "@jgengine/core/editor"`
96
+ - `lakebedFromWaterVolumes` (function) · `import { lakebedFromWaterVolumes } from "@jgengine/core/editor/environment"`
97
+ - `terrainBoundsFromDocument` (function) · `import { terrainBoundsFromDocument } from "@jgengine/core/editor"`
98
+
99
+ ## world-directives — apply a sparse overlay over materialized directive instances
100
+
101
+ - `applyDirectiveOverlay` (function) · `import { applyDirectiveOverlay } from "@jgengine/core/editor"`
102
+ - `materializeDirective` (function) · `import { materializeDirective } from "@jgengine/core/editor"`
103
+ - `materializeDirectives` (function) · `import { materializeDirectives } from "@jgengine/core/editor"`
104
+ - `materializePopulationDirective` (function) · `import { materializePopulationDirective } from "@jgengine/core/editor"`
105
+ - `materializeScatterDirective` (function) · `import { materializeScatterDirective } from "@jgengine/core/editor"`
106
+ - `resolveDirectiveFootprint` (function) · `import { resolveDirectiveFootprint } from "@jgengine/core/editor"`
107
+
108
+ ## world-shards — decode an untrusted world manifest with per-field diagnostics
109
+
110
+ - `decodeWorldManifest` (function) · `import { decodeWorldManifest } from "@jgengine/core/editor"`
111
+ - `loadWorldDocument` (function) · `import { loadWorldDocument } from "@jgengine/core/editor"`
112
+ - `selectWorldShards` (function) · `import { selectWorldShards } from "@jgengine/core/editor"`
113
+ - `shardMatchesQuery` (function) · `import { shardMatchesQuery } from "@jgengine/core/editor"`
114
+ - `singleShardWorldManifest` (function) · `import { singleShardWorldManifest } from "@jgengine/core/editor"`
115
+ - `splitEditorDocumentIntoShards` (function) · `import { splitEditorDocumentIntoShards } from "@jgengine/core/editor"`
116
+
117
+ ## world-streaming — schedule shard load/unload by camera proximity
118
+
119
+ - `createWorldStreamer` (function) · `import { createWorldStreamer } from "@jgengine/core/editor"`
120
+ - `shardDistance` (function) · `import { shardDistance } from "@jgengine/core/editor"`
@@ -1,3 +1,13 @@
1
+ # Editor RPC/CLI and agent panel
2
+
3
+ ## Headless CLI persistence
4
+
5
+ `bun packages/editor/src/mcp/cli.ts --game <id> --rpc '<json>' … --save` runs the RPC batch on one
6
+ in-memory session and, when every RPC succeeds, writes the session document to
7
+ `Games/<id>/src/editor.scene.json` (dev-save format: 2-space JSON + trailing newline, identical to
8
+ the GUI's Ctrl+S through `devSavePlugin`). Without `--save`, `--rpc` mutations are discarded on
9
+ exit — use it for read-only inspection only, or capture `export_document` yourself.
10
+
1
11
  # Editor agent panel (embedded)
2
12
 
3
13
  Toolbar **Agent** opens a dockable chat panel in `EditorChrome`. Tool calls use the same editor RPC verbs as the MCP/CLI bridge and the GUI — one session undo stack, interleaved with human edits.
@@ -30,6 +40,15 @@ Content-Type: application/json
30
40
 
31
41
  Each `toolCalls[].name` is an editor RPC method (`set_transform`, `select`, …). The panel runs them via `routeToolCall` → `EditorHostApi.handle`.
32
42
 
43
+ ## Bridge reliability
44
+
45
+ The bridge is trustworthy so agents author instead of hardcoding — every path is honest about failure:
46
+
47
+ - **Rejected mutations return `ok:false` with a reason.** A locked/cyclic `set_transform`, a `set_parent` that would form a cycle, a collection/prefab verb targeting a missing id, and a batch verb that matches nothing all fail loudly — never a phantom `{ok:true}`.
48
+ - **One decode/migrate boundary.** `decodeEditorDocument` (`@jgengine/core/editor`) validates every field with a path-specific diagnostic (`$.markers[2].position`) and migrates forward; `import_document` and a `push_document_patch` **snapshot** both clear it, so a malformed or old document fails or migrates loudly rather than corrupting a live session.
49
+ - **Document-global id uniqueness.** Placeable ids (markers/volumes/paths/notes) are one namespace: adds re-id on collision, and a single imported document that reuses an id is rejected with its path — a duplicate-id import is impossible. Combine paths (`mergeEditorDocuments`, duplicate, overlay) re-id instead.
50
+ - **Schema-validated input.** `decodeEditorBridgeRequest` type-checks each field a method understands against the per-method schema before it reaches `handle` — a fuzzed value (string where a number belongs, scalar where an object belongs) is rejected at the `--rpc`/HTTP/stdio/agent-tool boundary, never cast in blind. Missing/unknown fields are left to `handle`'s guards so the boundary stays forward-compatible.
51
+
33
52
  ## Pure API (`@jgengine/editor`)
34
53
 
35
54
  ```ts
@@ -63,6 +82,53 @@ routeToolCall(api, { id: "1", name: "set_transform", arguments: { id: "boss", x:
63
82
 
64
83
  Commands: `/help`, `/status`, `/summary`, `/selection`, `/frame`, `/undo`, `/redo`, `/clear`, `/select <id…>`, `/goto <id>`, `move <id> <x> <y> <z>`.
65
84
 
85
+ ## Data catalogs & entity definitions
86
+
87
+ The **Data** tab (`CatalogsPanel`) edits gameplay tuning rows that persist on the scene document
88
+ (`EditorDocument.catalogs`). Two kinds of catalog feed the tab, merged by
89
+ `resolveCatalogDefinitions(document, gameDefinitions)`: **game-exported** catalogs whose schema lives
90
+ in code (a game's `editorCatalogs` export, `EditorCatalogDefinition[]`: `{ id, label, schema:
91
+ ParamSchema, entries }`, wired via a `defineGame`-sibling module export passed as the `catalogs` prop —
92
+ the scaffold's `main.tsx` passes `catalogs={editorCatalogs}`), and **editor-authored** catalogs created
93
+ entirely in the editor. A game def always wins on id collision; a document catalog is surfaced only when
94
+ it carries its own `schema`.
95
+
96
+ Beyond tuning existing rows the tab **authors catalogs and schemas**:
97
+ - **Create a catalog** — the `+ New catalog` form takes an id (+ optional label) and dispatches
98
+ `addCatalog` with an empty `schema: { fields: [] }`. The document now *carries the schema*
99
+ (`EditorCatalogData.schema`/`label`), so an editor-only catalog round-trips through save/reload and
100
+ drives the default `content.ts` path with no game code.
101
+ - **Author schema fields** — for document-authored catalogs (`data.schema !== undefined`; game-exported
102
+ catalogs stay read-only since their schema is in code) the field editor adds/renames/removes fields
103
+ (key, type over `ParamField["type"]`, default, min/max). Every field mutation rebuilds the whole
104
+ `fields` array and dispatches one `setCatalogSchema`, whose reducer **re-parses every row's `meta`
105
+ against the new schema** via `parseParams`: removed keys drop, added keys default in, range/number
106
+ values clamp. One undoable step.
107
+ - **Author rows** — `+ Row` adds a schema-defaulted entry; each row has a remove (`×`).
108
+
109
+ Agents/CLI drive the same edits: `add_catalog` / `remove_catalog` / `set_catalog_schema` for the
110
+ catalog + schema, and `add_catalog_entry` / `remove_catalog_entry` / `set_catalog_entry` for rows
111
+ (alongside `list_catalogs`, `get_catalog_entry`). A catalog added via `add_catalog` is RPC-addressable
112
+ immediately (the host recomputes merged defs per request). New-row meta is seeded from the catalog
113
+ `ParamSchema` defaults and validated before it lands. Values and document-carried schemas save into
114
+ `editor.scene.json` → `catalogs`.
115
+
116
+ **Entity definitions** are a data catalog: the well-known `ENTITY_CATALOG_ID` (`"entities"`) catalog,
117
+ whose rows carry role/health/speed/scale per `entityDefinitionSchema`. `entityEntryFromCatalog(document,
118
+ catalogId, definitions?)` (`@jgengine/core/editor`) turns a row into the runtime
119
+ `GameContextEntityEntry` the default `content.ts#entityById` returns — so a `mob`/`boss` marker whose
120
+ `catalogId` names an entities row spawns with the stats/speed tuned in the editor, no game TS. It
121
+ prefers a document-carried `entities` schema over `entityDefinitionSchema` when the document authored
122
+ one, so a re-authored entity field set drives the parse.
123
+ `authoredEntitySpawns(document)` (`@jgengine/core/world/authoredEntities`) yields the spawn plan
124
+ (`{ markerId, catalogId, position, rotationY }`) the scaffold `loop.ts` feeds to
125
+ `ctx.scene.entity.spawn`. Author entities in the editor (place a marker → Data tab → tune the row →
126
+ save); never hardcode entity stats where the document should own them.
127
+
128
+ ## Asset import
129
+
130
+ Dropping a `.glb`/`.gltf` into the editor persists it durably, but where depends on the project shape (`editorHostPlugin`, `@jgengine/node`). A **standalone folder workspace** copies the bytes into the scanned asset folder and re-lists them under a scan-stable id (`importEditorAsset`); the id comes from the file's workspace-relative path, so a placement referencing it resolves after reload. A **promoted game** (one with a typed `src/game/assets.ts` catalog — `isPromotedProject`) instead copies the bytes into `public/<basePath>/imported/` and rewrites `assets.ts` to add a durable `extras` entry to its `buildCatalog({ extras })` call (`importPromotedAsset` → `upsertCatalogExtra`), so the **shipped** game serves and resolves the asset through its own typed catalog rather than a dev-only route. The id matches what a folder rescan would produce, the rewrite is idempotent (re-import of the same id collapses to a single entry), and an unparseable or multi-`buildCatalog` source throws so the host falls back to the folder-scan import rather than corrupt the file.
131
+
66
132
  ## Grid / tile layers
67
133
 
68
134
  Grid-addressed content (rooms, tactics maps, farms, nav/rule layers) lives on the scene document as
@@ -88,3 +154,24 @@ author the grid and read it at runtime.
88
154
  `importCsvGrid`/`exportCsvGrid` (value id per cell). ASCII/CSV are import paths **into** the grid
89
155
  document, never the canonical representation — `migrateGridLayer` normalizes and version-migrates
90
156
  any layer from disk or an adapter.
157
+
158
+ ## Minimap bake (#1036)
159
+
160
+ `bake_minimap` rasterizes the authored terrain into a top-down PNG stored on the document as
161
+ `EditorDocument.minimap: EditorMinimapBake` (`{ background: "data:image/png;…", bounds }`). The pure,
162
+ deterministic core rasterizer is `bakeMinimapFromDocument` (`@jgengine/core/editor/index`); the RPC
163
+ handler composes the live viewport's base ground field with `document.terrain` and dispatches the
164
+ undoable `setMinimapBake` command. Runtime feeds the stored `background`/`bounds` straight into the
165
+ `Minimap`/`WorldMap` props — **no re-rasterization at runtime** (see `jgengine-ui`).
166
+
167
+ - **Live-viewport only.** The bake needs the mounted editor world's composed height/normal sampler
168
+ (`EditorHostApi.getTerrainSampler`, registered by `EditorWorldOverlay` while the viewport is
169
+ mounted). It is **not** a headless CLI/MCP verb: with no viewport the sampler is null and
170
+ `bake_minimap` returns `{ ok:false, error:"bake_minimap needs the live editor viewport" }`. To bake
171
+ a committed scene offline, run a deterministic node script that rebuilds the base field with
172
+ `groundFieldFor(world)` and calls `bakeMinimapFromDocument` (see
173
+ `scripts/bake-claudecraft-minimap.ts`).
174
+ - GUI: the Terrain panel's **Bake minimap** button calls `bake_minimap` and surfaces any `ok:false`
175
+ error inline.
176
+ - RPC/CLI verb: `bake_minimap` (optional `padding`, `resolution`, `waterLevel`). The bake path uses
177
+ no `Date`/`Math.random`, so the same scene + sampler always bakes byte-identical output.
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: level-design
3
+ description: Design, audit, author, implement, and validate readable levels, worlds, encounters, navigation, and pacing.
4
+ ---
5
+
6
+ # Level design
7
+
8
+ ## Ownership
9
+
10
+ Own the spatial realization of game design: player metrics, topology, routes, landmarks, gates, encounter geometry, challenge sequencing, exploration, pacing, recovery, and spatial storytelling. Use `game-design` for the player promise and loops, `jgengine-editor` to author space, and `jgengine-world` to consume it.
11
+
12
+ All authorable world content belongs in `editor.scene.json`, changed through the editor GUI or RPC/CLI. Never hand-edit the document or keep geometry, paths, spawns, zones, objectives, terrain, foliage, encounters, or coordinate arrays in code. File an editor `[FEATURE]` issue before any fallback.
13
+
14
+ Read [references/application-playbook.md](references/application-playbook.md) only when the task explicitly calls for spatial design depth — a level/world design brief, an audit or redesign, or "make this fun/better" work; it is not a mandatory step of creating a game. Read [references/live-editor-loop.md](references/live-editor-loop.md) whenever live captures, an editor-agent handoff, or iterative scene improvement is involved. Read [references/field-guide.md](references/field-guide.md) for metric families, topology, pacing, genre lenses, accessibility, and research.
15
+
16
+ ## Choose the mode
17
+
18
+ ### Greenfield
19
+
20
+ Measure the real controller, camera, interaction, combat, AI, and network constraints in an authored metric gym. Produce a topology graph, critical/optional route model, beat sheet, learning sequence, encounter cards, authoring plan, and falsifiable completion scenario before art production.
21
+
22
+ ### Existing game
23
+
24
+ Start with a spatial-truth audit. Inventory every source of coordinates and semantics; report any gameplay placement outside `editor.scene.json` as a blocking ownership defect. Reconstruct the critical path and representative optional path from scene data and live play. Measure travel, decision, encounter, retry, and recovery time. Inspect first-look orientation, reverse navigation, affordances, spawn safety, combat positions, pacing contrast, and visual hierarchy.
25
+
26
+ “Improve with level design” is an authoring and implementation request. Do not stop at a map critique: select the highest-leverage route/zone/encounter slice, author the change through editor operations, connect runtime semantics, and prove it in play.
27
+
28
+ For a live editor handoff, send evidence and an executable authoring contract—not an aesthetic request. Require the editor agent to inspect authority, document revision, ids, layers, assets, runtime state, and tool support before mutation; apply one coherent hypothesis through undoable operations; then return the exact revision/change log for replay and comparison. Stop when the live editor is not connected to the runtime's authoritative scene or the required operation is unsupported.
29
+
30
+ ## Required output contract
31
+
32
+ Make every level-design pass yield:
33
+
34
+ 1. **Spatial truth audit:** scene counts and semantic kinds plus every code-owned coordinate table, generated placement, or duplicated position that must migrate.
35
+ 2. **Metric sheet:** measured movement, camera, interaction, weapon/AI, readability, density, performance, multiplayer, and retry constraints with units.
36
+ 3. **Topology and journey:** nodes/edges, critical and optional routes, gates, returns, landmarks, expected traversal times, and first-minute/mission/campaign beats.
37
+ 4. **Zone/encounter diagnosis:** purpose, entry knowledge/state, choices, geometry, actors, escalation, resources, exits, failure/reset, reward, and downstream change.
38
+ 5. **Bottleneck ranking:** observed symptom, player consequence, root cause, evidence, reach, confidence, effort, dependencies, and ownership.
39
+ 6. **Editor change set:** exact semantic ids/kinds and operations to add/move/remove for paths, markers, zones, spawns, objectives, checkpoints, props, and terrain—without putting coordinates in code.
40
+ 7. **Acceptance evidence:** document assertions, route/encounter tests, fresh-player play scenario, pacing/wayfinding thresholds, inspected screenshots, and before/after comparison.
41
+
42
+ ## Execution rules
43
+
44
+ - Graph before geometry; graybox before art; gameplay and wayfinding before decoration.
45
+ - Present decision-relevant information before commitment. Make alternate routes differ in risk, cost, verbs, information, reward, or experience.
46
+ - Sequence teaching through cue, safe use, feedback, independent test, combination, transformation, and mastery as the audience requires.
47
+ - Align composition, landmark, value/color, motion, audio, affordance, path shape, and optional UI guidance. No marker can repair contradictory space.
48
+ - Design pacing across separate threat, motor, cognitive, navigation, emotional, resource, and social axes. Constant pressure or empty traversal is not pacing.
49
+ - Make every encounter support intended verbs, counterplay, retreat, fair spawns, recovery, and bounded performance.
50
+ - Populate only after the graybox survives play. Preserve silhouettes, safe footing, goals, threats, interactables, teams, and traversal boundaries through art passes.
51
+
52
+ ## Completion
53
+
54
+ An audit or prettier screenshot is not completion for a build/improve request. Finish when the scene document owns spatial truth; a fresh target player can orient, choose, act, recover, and complete the scenario without coaching; the route has intentional decisions and pacing; encounter exploits and alternate states are tested; and `jgengine-verify` records document, gameplay, and inspected visual evidence.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Level Design"
3
+ short_description: "Design readable, paced, playable spaces"
4
+ default_prompt: "Use $level-design to observe this world live, brief and drive the editor agent through an authoritative scene change, then replay the same journey and prove the result."
@@ -0,0 +1,192 @@
1
+ # Applying level design
2
+
3
+ Use this playbook to turn spatial intent or an existing world into editor-authored, playable change. Its purpose is to force concrete topology, authoring operations, and evidence rather than aesthetic commentary.
4
+
5
+ ## Contents
6
+
7
+ 1. Greenfield procedure
8
+ 2. Existing-world audit
9
+ 3. Spatial truth and metrics
10
+ 4. Journey, topology, and beats
11
+ 5. Zone and encounter diagnosis
12
+ 6. Ranking interventions
13
+ 7. Editor change set
14
+ 8. Implementation and proof
15
+ 9. Failure modes
16
+
17
+ ## 1. Greenfield procedure
18
+
19
+ Before production art:
20
+
21
+ 1. Import the game-design contract: promise, verbs, repeated decision, loops, target player, and completion proof.
22
+ 2. Author a metric gym and measure the actual controller, camera, interaction, combat, AI, and network behavior.
23
+ 3. Draw the topology graph with starts, goals, critical/optional routes, gates, returns, checkpoints, encounters, safe spaces, and rewards.
24
+ 4. Write a beat sheet across threat, motor, cognitive, navigation, emotional, resource, and social intensity.
25
+ 5. Map where each mechanic is cued, tried safely, tested, combined, transformed, and mastered.
26
+ 6. Specify encounter cards and the semantic scene ids they require.
27
+ 7. Graybox one route/zone slice in `editor.scene.json` through GUI or RPC/CLI.
28
+ 8. Playtest orientation, decisions, traversal, encounter flow, failure, and retry before population and art.
29
+
30
+ ## 2. Existing-world audit
31
+
32
+ ### Inventory spatial truth
33
+
34
+ Inspect the editor document and source tree. Report separately:
35
+
36
+ - authored paths and point counts
37
+ - authored markers grouped by semantic kind and catalog id
38
+ - authored zones/volumes, terrain, foliage, annotations, prefabs, and collections
39
+ - gameplay spawns, objectives, NPCs, vendors, loot, checkpoints, gates, and encounters
40
+ - coordinate arrays, centers, offsets, radii, procedural placement, and duplicated positions in code
41
+ - runtime queries that consume stable scene ids/kinds
42
+
43
+ If gameplay placement exists in code but not the document, mark the spatial-truth audit failed before discussing polish. The repair is an editor-authored migration with stable semantics, not another adapter around coordinate tables.
44
+
45
+ ### Observe live play
46
+
47
+ Capture and inspect:
48
+
49
+ - spawn/first frame and the first ten seconds
50
+ - first decision and first objective
51
+ - one critical-path transition
52
+ - one representative encounter and retry
53
+ - one optional route/POI
54
+ - reverse travel or return after state change
55
+ - a dense/peak gameplay frame
56
+
57
+ Record what dominates the frame, what the player can infer, where they look, where they move, what they miss, and whether UI/world cues agree. Pixel metrics only reject technical blanks; human inspection judges composition and gameplay readability.
58
+
59
+ ## 3. Spatial truth and metrics
60
+
61
+ ### Metric sheet
62
+
63
+ | Family | Measured values | Source/build | Design consequence | Extreme/accessibility case |
64
+ | --- | --- | --- | --- | --- |
65
+ | movement | speed, acceleration, stop, turn, jump, slope, radius | | | |
66
+ | camera | perspective, FOV, offset, obstruction, sensitivity | | | |
67
+ | interaction | range, use time, target clarity | | | |
68
+ | combat/AI | weapon bands, projectile time, sensing, attack, group size | | | |
69
+ | navigation | path width, sightline, branch/rejoin, landmark range | | | |
70
+ | pacing | time to action, encounter, rest, reward, retry | | | |
71
+ | multiplayer | spawn, regroup, revive, latency, count | | | |
72
+ | performance | actor/object density, nav, draw, simulation | | | |
73
+
74
+ Derive dimensions from the measured game. Never paste corridor, cover, jump, or arena numbers from another title.
75
+
76
+ ### Travel-time audit
77
+
78
+ Measure each route at the actual movement speed, including turns, hazards, encounters, and interaction delay. For every interval, classify the intended value: decision, mastery, anticipation, story, resource planning, combat, exploration, recovery, or deliberate atmosphere. Empty time with no purpose is a pacing defect even when the scenery is attractive.
79
+
80
+ ## 4. Journey, topology, and beats
81
+
82
+ ### Topology table
83
+
84
+ | Node/edge | Purpose | Entry information | Choice/tradeoff | Gate/return | Expected time | Downstream change |
85
+ | --- | --- | --- | --- | --- | --- | --- |
86
+
87
+ Validate reachability for relevant quest/world states and the reverse direction. Branches must differ in risk, cost, verb, information, reward, story, or experience.
88
+
89
+ ### Beat sheet
90
+
91
+ | Time/distance | Beat | Threat | Motor | Cognitive | Navigation | Emotion/resource | Evidence/failure signal |
92
+ | --- | --- | --- | --- | --- | --- | --- | --- |
93
+
94
+ Look for long flats, constant peaks, unseen goals, repeated rhythms, rewards without anticipation, combat without aftermath, and failure without fast useful retry.
95
+
96
+ ### First-minute contract
97
+
98
+ The first minute must deliberately answer:
99
+
100
+ - Where am I and what fantasy am I inhabiting?
101
+ - What can I do now?
102
+ - What should I notice first?
103
+ - What is my immediate goal and why?
104
+ - Where is the first safe experiment?
105
+ - What consequence teaches the rule?
106
+ - What next decision promises depth?
107
+
108
+ Do not answer all seven with text. Use space, action, feedback, and only the necessary UI.
109
+
110
+ ## 5. Zone and encounter diagnosis
111
+
112
+ ### Zone card
113
+
114
+ - role in the game/session loop
115
+ - visual/spatial identity and landmark hierarchy
116
+ - entry/exit states and critical/optional routes
117
+ - mechanics introduced, tested, combined, and mastered
118
+ - decision types and exploration rewards
119
+ - pacing arc, safe spaces, checkpoints, and return value
120
+ - content budget and performance peak
121
+ - spatial story and world-state change
122
+
123
+ Zones that differ only by palette, enemy level, or kill quota do not provide meaningful progression.
124
+
125
+ ### Encounter card
126
+
127
+ - purpose and target player behavior
128
+ - entry sightline, knowledge, position, resources, and condition
129
+ - initial decision and viable approaches
130
+ - geometry for every intended verb and counterplay
131
+ - actors/hazards, escalation, reinforcement, peak, and resolution
132
+ - cover/refuge, retreat, flank, exits, and exploit risks
133
+ - reward, failure/reset, retry time, and downstream state change
134
+ - semantic scene ids and performance budget
135
+
136
+ ## 6. Ranking interventions
137
+
138
+ Rank candidate changes with evidence:
139
+
140
+ | Candidate | Player behavior changed | Reach | Evidence/confidence | Effort/risk | Dependencies | Editor/runtime owner |
141
+ | --- | --- | --- | --- | --- | --- | --- |
142
+
143
+ Use three horizons:
144
+
145
+ - **Minimum correction:** migrate invalid spatial ownership or repair a blocking orientation/flow failure.
146
+ - **Strong target:** make one representative route/zone/encounter deliver the intended promise end to end.
147
+ - **Multiplier:** propagate the proven spatial grammar, semantic kinds, encounter kit, and tests across the world.
148
+
149
+ Prioritize upstream seams and reusable authoring kinds. Do not spend the first pass scattering props across a structurally unchanged map.
150
+
151
+ ## 7. Editor change set
152
+
153
+ Specify operations semantically, not as code coordinates:
154
+
155
+ | Operation | Stable id/kind | Purpose/meta | Runtime consumer | Acceptance |
156
+ | --- | --- | --- | --- | --- |
157
+ | add/move/remove path | | from/to, route role | | |
158
+ | add/move/remove marker | | spawn/objective/NPC/checkpoint/landmark | | |
159
+ | add/move/remove zone | | encounter/settlement/safe/gate/resource | | |
160
+ | terrain/foliage/material pass | | traversal/readability/identity | | |
161
+ | prop/asset pass | | cover/affordance/story/landmark | | |
162
+
163
+ Execute through `jgengine-editor`. Gameplay code queries ids, kinds, layers, and metadata; it does not receive copied positions. File an editor feature issue if a required semantic kind or operation does not exist.
164
+
165
+ ## 8. Implementation and proof
166
+
167
+ When the user asks to build or improve:
168
+
169
+ 1. Establish before evidence and the acceptance scenario.
170
+ 2. Author the chosen graybox and semantics through the editor.
171
+ 3. Connect shared runtime/gameplay primitives to the authored ids.
172
+ 4. Migrate superseded coordinate tables without changing unrelated content.
173
+ 5. Add document assertions for required paths, zones, markers, and ids.
174
+ 6. Add deterministic route, encounter, reset, and state-transition tests.
175
+ 7. Run a fresh-player or representative play scenario.
176
+ 8. Capture and inspect the same views before/after.
177
+ 9. Evaluate timing, choice, comprehension, exploit, accessibility, and performance falsifiers.
178
+
179
+ Evidence should answer the design claim. Scene counts prove ownership, headless tests prove state, a driven playtest proves progress, and inspected screenshots prove visible composition. No one rung proves all four.
180
+
181
+ ## 9. Failure modes
182
+
183
+ - praising asset count while gameplay semantics remain in code
184
+ - drawing a map without measuring the real controller/camera
185
+ - calling multiple corridors meaningful choice
186
+ - filling empty travel with collectibles instead of decisions or pacing
187
+ - changing color/lighting while topology and encounter flow remain unchanged
188
+ - using objective markers to compensate for contradictory geometry
189
+ - designing only the critical path or only the plan view
190
+ - making every zone the same objective with new enemies and palette
191
+ - reporting an audit after the user asked for improvement
192
+ - claiming success from scene counts, tests, telemetry, or screenshots alone