@yali-engine/core 0.0.0-stage → 0.4.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 (118) hide show
  1. package/dist/abi.gen.d.ts +76 -0
  2. package/dist/abi.gen.js +49 -0
  3. package/dist/abi.gen.js.map +1 -0
  4. package/dist/app/app.d.ts +194 -0
  5. package/dist/app/app.js +562 -0
  6. package/dist/app/app.js.map +1 -0
  7. package/dist/app/headless.d.ts +78 -0
  8. package/dist/app/headless.js +81 -0
  9. package/dist/app/headless.js.map +1 -0
  10. package/dist/app/lifecycle.d.ts +139 -0
  11. package/dist/app/lifecycle.js +100 -0
  12. package/dist/app/lifecycle.js.map +1 -0
  13. package/dist/app/plugins.d.ts +40 -0
  14. package/dist/app/plugins.js +92 -0
  15. package/dist/app/plugins.js.map +1 -0
  16. package/dist/app/profiler.d.ts +118 -0
  17. package/dist/app/profiler.js +312 -0
  18. package/dist/app/profiler.js.map +1 -0
  19. package/dist/app/quality.d.ts +114 -0
  20. package/dist/app/quality.js +222 -0
  21. package/dist/app/quality.js.map +1 -0
  22. package/dist/app/rng.d.ts +26 -0
  23. package/dist/app/rng.js +61 -0
  24. package/dist/app/rng.js.map +1 -0
  25. package/dist/app/time.d.ts +62 -0
  26. package/dist/app/time.js +92 -0
  27. package/dist/app/time.js.map +1 -0
  28. package/dist/app/tools.d.ts +40 -0
  29. package/dist/app/tools.js +57 -0
  30. package/dist/app/tools.js.map +1 -0
  31. package/dist/assets/decode-pool.d.ts +85 -0
  32. package/dist/assets/decode-pool.js +169 -0
  33. package/dist/assets/decode-pool.js.map +1 -0
  34. package/dist/assets/decode-worker.d.ts +10 -0
  35. package/dist/assets/decode-worker.js +11 -0
  36. package/dist/assets/decode-worker.js.map +1 -0
  37. package/dist/assets/handle.d.ts +44 -0
  38. package/dist/assets/handle.js +81 -0
  39. package/dist/assets/handle.js.map +1 -0
  40. package/dist/assets/loaders.d.ts +7 -0
  41. package/dist/assets/loaders.js +25 -0
  42. package/dist/assets/loaders.js.map +1 -0
  43. package/dist/assets/plugin.d.ts +19 -0
  44. package/dist/assets/plugin.js +42 -0
  45. package/dist/assets/plugin.js.map +1 -0
  46. package/dist/assets/server.d.ts +104 -0
  47. package/dist/assets/server.js +407 -0
  48. package/dist/assets/server.js.map +1 -0
  49. package/dist/assets/types.d.ts +83 -0
  50. package/dist/assets/types.js +2 -0
  51. package/dist/assets/types.js.map +1 -0
  52. package/dist/core.d.ts +75 -0
  53. package/dist/core.js +139 -0
  54. package/dist/core.js.map +1 -0
  55. package/dist/errors.d.ts +15 -0
  56. package/dist/errors.js +22 -0
  57. package/dist/errors.js.map +1 -0
  58. package/dist/index.d.ts +45 -0
  59. package/dist/index.js +43 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/pool-worker.d.ts +3 -0
  62. package/dist/pool-worker.js +61 -0
  63. package/dist/pool-worker.js.map +1 -0
  64. package/dist/query.d.ts +118 -0
  65. package/dist/query.js +244 -0
  66. package/dist/query.js.map +1 -0
  67. package/dist/schema.d.ts +41 -0
  68. package/dist/schema.js +58 -0
  69. package/dist/schema.js.map +1 -0
  70. package/dist/script/dispatch.d.ts +23 -0
  71. package/dist/script/dispatch.js +105 -0
  72. package/dist/script/dispatch.js.map +1 -0
  73. package/dist/script/pool.d.ts +60 -0
  74. package/dist/script/pool.js +81 -0
  75. package/dist/script/pool.js.map +1 -0
  76. package/dist/script/protocol.d.ts +39 -0
  77. package/dist/script/protocol.js +40 -0
  78. package/dist/script/protocol.js.map +1 -0
  79. package/dist/script/runner.d.ts +40 -0
  80. package/dist/script/runner.js +89 -0
  81. package/dist/script/runner.js.map +1 -0
  82. package/dist/script/worker.d.ts +24 -0
  83. package/dist/script/worker.js +49 -0
  84. package/dist/script/worker.js.map +1 -0
  85. package/dist/thread-worker.d.ts +13 -0
  86. package/dist/thread-worker.js +27 -0
  87. package/dist/thread-worker.js.map +1 -0
  88. package/dist/threads.d.ts +58 -0
  89. package/dist/threads.js +56 -0
  90. package/dist/threads.js.map +1 -0
  91. package/dist/transforms.d.ts +34 -0
  92. package/dist/transforms.js +39 -0
  93. package/dist/transforms.js.map +1 -0
  94. package/dist/wasi.d.ts +6 -0
  95. package/dist/wasi.js +68 -0
  96. package/dist/wasi.js.map +1 -0
  97. package/dist/worker-pool.d.ts +85 -0
  98. package/dist/worker-pool.js +115 -0
  99. package/dist/worker-pool.js.map +1 -0
  100. package/dist/world-hash.d.ts +15 -0
  101. package/dist/world-hash.js +51 -0
  102. package/dist/world-hash.js.map +1 -0
  103. package/dist/world-tools.d.ts +14 -0
  104. package/dist/world-tools.js +113 -0
  105. package/dist/world-tools.js.map +1 -0
  106. package/dist/world.d.ts +107 -0
  107. package/dist/world.js +288 -0
  108. package/dist/world.js.map +1 -0
  109. package/package.json +53 -3
  110. package/wasm/yali_core.anim.physics.threads.wasm +0 -0
  111. package/wasm/yali_core.anim.physics.wasm +0 -0
  112. package/wasm/yali_core.anim.threads.wasm +0 -0
  113. package/wasm/yali_core.anim.wasm +0 -0
  114. package/wasm/yali_core.physics.threads.wasm +0 -0
  115. package/wasm/yali_core.physics.wasm +0 -0
  116. package/wasm/yali_core.threads.wasm +0 -0
  117. package/wasm/yali_core.wasm +0 -0
  118. package/README.md +0 -3
@@ -0,0 +1,76 @@
1
+ /** The ABI version these declarations describe. */
2
+ export declare const ABI_VERSION = 20;
3
+ /** The core module's exports. Optional members exist only in bench builds or core variants. */
4
+ export interface CoreExports {
5
+ readonly memory: WebAssembly.Memory;
6
+ yali_abi_version(): number;
7
+ yali_alloc(size: number): number;
8
+ yali_dealloc(ptr: number, size: number): void;
9
+ yali_world_new(): number;
10
+ yali_features(): number;
11
+ yali_features_install(w: number): number;
12
+ yali_anim_add_skeleton?(w: number, parents: number, n: number, rest: number): number;
13
+ yali_anim_add_clip?(w: number, skeleton: number, data: number, words: number): number;
14
+ yali_anim_add_graph?(w: number, skeleton: number, data: number, words: number): number;
15
+ yali_anim_add_mask?(w: number, skeleton: number, weights: number, n: number): number;
16
+ yali_anim_add_skin?(w: number, skeleton: number, n: number, joints: number, ibm: number, rest_error: number): number;
17
+ yali_anim_joint_model?(w: number, e: number, joint: number, out: number): number;
18
+ yali_anim_update?(w: number, dt: number): number;
19
+ yali_anim_palette?(w: number, out: number): number;
20
+ yali_anim_clip_duration?(w: number, clip: number): number;
21
+ yali_physics_settings?(w: number, fixed_dt: number, gx: number, gy: number, gz: number, substeps: number): number;
22
+ yali_physics_debug?(w: number, flags: number, max_segments: number, out: number): number;
23
+ yali_physics_ray_casts?(w: number, input: number, n: number, output: number): number;
24
+ yali_physics_add_hull?(w: number, points: number, n: number): number;
25
+ yali_physics_add_mesh?(w: number, verts: number, nv: number, indices: number, ni: number, double_sided: number): number;
26
+ yali_physics_add_heightfield?(w: number, rows: number, cols: number, heights: number, sx: number, sy: number, sz: number): number;
27
+ yali_physics_snapshot?(w: number): number;
28
+ yali_physics_restore?(w: number, id: number): number;
29
+ yali_physics_snapshot_free?(w: number, id: number): number;
30
+ yali_physics_stats?(w: number, out: number): number;
31
+ yali_cloth_step?(w: number, params: number, cloths: number, ncloths: number, st: number, st_len: number, particles: number, vertices: number, colliders: number, ncolliders: number, torn: number, torn_len: number): number;
32
+ yali_cloth_write?(w: number, params: number, cloths: number, ncloths: number, st: number, st_len: number, particles: number, vertices: number, out: number, out_len: number): number;
33
+ yali_world_free(w: number): void;
34
+ yali_error_text(w: number): number;
35
+ yali_error_text_len(w: number): number;
36
+ yali_register_component(w: number, ptr: number, len: number): number;
37
+ yali_field_id(w: number, c: number, ptr: number, len: number): number;
38
+ yali_spawn(w: number, comps: number, n: number, count: number, out: number): number;
39
+ yali_despawn(w: number, e: number): number;
40
+ yali_insert(w: number, e: number, c: number, data: number, len: number): number;
41
+ yali_remove(w: number, e: number, c: number): number;
42
+ yali_set_parent(w: number, child: number, parent: number): number;
43
+ yali_is_alive(w: number, e: number): number;
44
+ yali_entity_count(w: number): number;
45
+ yali_end_frame(w: number): number;
46
+ yali_schedule_add_external(w: number, stage: number, ext: number, desc: number, len: number): number;
47
+ yali_schedule_remove(w: number, name: number, len: number): number;
48
+ yali_schedule_plan(w: number, stage: number, out: number, cap: number): number;
49
+ yali_schedule_run_batch(w: number, stage: number, batch: number): number;
50
+ yali_schedule_finish_stage(w: number, stage: number): number;
51
+ yali_transforms_install(w: number): number;
52
+ yali_frame_begin(w: number, alpha: number): number;
53
+ yali_query_new(w: number, desc: number, desc_len: number, cols: number, ncols: number): number;
54
+ yali_query_run(w: number, q: number): number;
55
+ yali_query_header(w: number, q: number): number;
56
+ yali_extract_transforms(w: number, q: number, cx: number, cy: number, cz: number, out: number, cap: number): number;
57
+ yali_extract_instances(w: number, q: number, ax: number, ay: number, az: number, out: number, cap: number, counts: number, meshes: number, changed: number, dirty: number, dirty_cap: number): number;
58
+ yali_bench_cull_selftest?(n: number): number;
59
+ yali_extract_culled(w: number, q: number, cx: number, cy: number, cz: number, cull: number, mesh_info: number, meshes: number, out: number, cap: number, slot_counts: number): number;
60
+ yali_query_write(w: number, q: number, col: number, src: number, kind: number, rows: number, lanes: number): number;
61
+ yali_jobs_new(w: number, workers: number): number;
62
+ yali_jobs_worker(pool: number): void;
63
+ yali_jobs_shutdown(pool: number): void;
64
+ yali_jobs_help(pool: number): number;
65
+ yali_jobs_park(pool: number, seen: number): void;
66
+ yali_jobs_wake_all(pool: number): void;
67
+ yali_jobs_wake(pool: number): number;
68
+ yali_jobs_running(pool: number): number;
69
+ yali_bench_integrate_par?(w: number, q: number, dt: number): number;
70
+ yali_bench_integrate?(w: number, q: number, dt: number): number;
71
+ yali_bench_integrate_simd?(w: number, q: number, dt: number): number;
72
+ yali_bench_math_selftest?(n: number): number;
73
+ yali_bench_raw?(pos: number, vel: number, n: number, dt: number): void;
74
+ }
75
+ /** Every required export, for the load-time check. */
76
+ export declare const REQUIRED_EXPORTS: readonly ["yali_abi_version", "yali_alloc", "yali_dealloc", "yali_world_new", "yali_features", "yali_features_install", "yali_world_free", "yali_error_text", "yali_error_text_len", "yali_register_component", "yali_field_id", "yali_spawn", "yali_despawn", "yali_insert", "yali_remove", "yali_set_parent", "yali_is_alive", "yali_entity_count", "yali_end_frame", "yali_schedule_add_external", "yali_schedule_remove", "yali_schedule_plan", "yali_schedule_run_batch", "yali_schedule_finish_stage", "yali_transforms_install", "yali_frame_begin", "yali_query_new", "yali_query_run", "yali_query_header", "yali_extract_transforms", "yali_extract_instances", "yali_extract_culled", "yali_query_write", "yali_jobs_new", "yali_jobs_worker", "yali_jobs_shutdown", "yali_jobs_help", "yali_jobs_park", "yali_jobs_wake_all", "yali_jobs_wake", "yali_jobs_running"];
@@ -0,0 +1,49 @@
1
+ // GENERATED by tools/abi-gen.mjs from crates/yali-core-wasm/src/lib.rs. Do not edit.
2
+ // Regenerate with `node tools/abi-gen.mjs`; CI runs it with --check.
3
+ /** The ABI version these declarations describe. */
4
+ export const ABI_VERSION = 20;
5
+ /** Every required export, for the load-time check. */
6
+ export const REQUIRED_EXPORTS = [
7
+ 'yali_abi_version',
8
+ 'yali_alloc',
9
+ 'yali_dealloc',
10
+ 'yali_world_new',
11
+ 'yali_features',
12
+ 'yali_features_install',
13
+ 'yali_world_free',
14
+ 'yali_error_text',
15
+ 'yali_error_text_len',
16
+ 'yali_register_component',
17
+ 'yali_field_id',
18
+ 'yali_spawn',
19
+ 'yali_despawn',
20
+ 'yali_insert',
21
+ 'yali_remove',
22
+ 'yali_set_parent',
23
+ 'yali_is_alive',
24
+ 'yali_entity_count',
25
+ 'yali_end_frame',
26
+ 'yali_schedule_add_external',
27
+ 'yali_schedule_remove',
28
+ 'yali_schedule_plan',
29
+ 'yali_schedule_run_batch',
30
+ 'yali_schedule_finish_stage',
31
+ 'yali_transforms_install',
32
+ 'yali_frame_begin',
33
+ 'yali_query_new',
34
+ 'yali_query_run',
35
+ 'yali_query_header',
36
+ 'yali_extract_transforms',
37
+ 'yali_extract_instances',
38
+ 'yali_extract_culled',
39
+ 'yali_query_write',
40
+ 'yali_jobs_new',
41
+ 'yali_jobs_worker',
42
+ 'yali_jobs_shutdown',
43
+ 'yali_jobs_help',
44
+ 'yali_jobs_park',
45
+ 'yali_jobs_wake_all',
46
+ 'yali_jobs_wake',
47
+ 'yali_jobs_running',
48
+ ];
49
+ //# sourceMappingURL=abi.gen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abi.gen.js","sourceRoot":"","sources":["../src/abi.gen.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,qEAAqE;AAErE,mDAAmD;AACnD,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AA2E9B,sDAAsD;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,kBAAkB;IAClB,YAAY;IACZ,cAAc;IACd,gBAAgB;IAChB,eAAe;IACf,uBAAuB;IACvB,iBAAiB;IACjB,iBAAiB;IACjB,qBAAqB;IACrB,yBAAyB;IACzB,eAAe;IACf,YAAY;IACZ,cAAc;IACd,aAAa;IACb,aAAa;IACb,iBAAiB;IACjB,eAAe;IACf,mBAAmB;IACnB,gBAAgB;IAChB,4BAA4B;IAC5B,sBAAsB;IACtB,oBAAoB;IACpB,yBAAyB;IACzB,4BAA4B;IAC5B,yBAAyB;IACzB,kBAAkB;IAClB,gBAAgB;IAChB,gBAAgB;IAChB,mBAAmB;IACnB,yBAAyB;IACzB,wBAAwB;IACxB,qBAAqB;IACrB,kBAAkB;IAClB,eAAe;IACf,kBAAkB;IAClB,oBAAoB;IACpB,gBAAgB;IAChB,gBAAgB;IAChB,oBAAoB;IACpB,gBAAgB;IAChB,mBAAmB;CACX,CAAC"}
@@ -0,0 +1,194 @@
1
+ import type { Core } from '../core.ts';
2
+ import type { ThreadsOptions } from '../threads.ts';
3
+ import { WorkerPool } from '../worker-pool.ts';
4
+ import type { Component, World } from '../world.ts';
5
+ import { type DeviceLossInfo, type LeakReport, Lifecycle, type LifecycleEvent, type PauseReason } from './lifecycle.ts';
6
+ import { type YaliPlugin } from './plugins.ts';
7
+ import { Profiler } from './profiler.ts';
8
+ import { type GovernorOptions, QualityGovernor, type QualityKnob } from './quality.ts';
9
+ import { Rng } from './rng.ts';
10
+ import { type ToolDef, ToolRegistry } from './tools.ts';
11
+ import { Time } from './time.ts';
12
+ /** The fixed frame stages, in order (DESIGN.md §4; the same names as the Rust scheduler). */
13
+ export declare const STAGES: readonly ["Input", "PreUpdate", "FixedUpdate", "Update", "PostUpdate", "Extract", "RenderPrep", "Submit", "NetworkSend", "EndFrame"];
14
+ /** One stage. */
15
+ export type StageName = (typeof STAGES)[number];
16
+ /** What a frame callback sees. One object, reused every frame (no allocation). */
17
+ export interface FrameInfo {
18
+ readonly time: Time;
19
+ /** Frames run since start. */
20
+ readonly frame: number;
21
+ /** Fixed steps this frame (FixedUpdate runs this many times). */
22
+ readonly fixedSteps: number;
23
+ }
24
+ /**
25
+ * A TS system. With a core (`App.create({ core })`) it is an external system of the Rust
26
+ * schedule (ADR-0031): ordered with Rust systems by `before`/`after`/`sets`, and run alone
27
+ * in its batch unless it declares `access` (ADR-0044). Without a core, systems run in
28
+ * registration order and ordering is refused.
29
+ */
30
+ export interface AppSystem {
31
+ /** Unique, conventionally `plugin.what`. */
32
+ readonly name: string;
33
+ readonly stage: StageName;
34
+ /** Runs before these systems or sets (same stage). Needs a core. */
35
+ readonly before?: readonly string[];
36
+ /** Runs after these systems or sets (same stage). Needs a core. */
37
+ readonly after?: readonly string[];
38
+ /** Named sets other systems can order against. Needs a core. */
39
+ readonly sets?: readonly string[];
40
+ /**
41
+ * The components this system reads and writes (ADR-0044). Declared, it shares a batch
42
+ * with Rust systems it does not conflict with, so those run in parallel instead of being
43
+ * split around it; it runs after them, on the main thread. Leave it out (exclusive) if
44
+ * the system touches resources, events, or components it cannot list.
45
+ */
46
+ readonly access?: {
47
+ readonly read?: readonly Component[];
48
+ readonly write?: readonly Component[];
49
+ };
50
+ run(frame: FrameInfo): void;
51
+ }
52
+ /** Rebuilds a plugin's GPU state after device loss. Resolves to counts of what it rebuilt. */
53
+ export type RecoverFn = () => Promise<Readonly<Record<string, number>>>;
54
+ /** Drives frames. `requestAnimationFrame` in a browser; a manual source in headless runs. */
55
+ export interface FrameSource {
56
+ request(cb: (now: number) => void): number;
57
+ cancel(id: number): void;
58
+ }
59
+ /** App options. */
60
+ export interface AppOptions {
61
+ readonly plugins: readonly YaliPlugin[];
62
+ /** The loaded core. The App then owns `app.world` and runs one Rust schedule for every
63
+ * system, TS and Rust (ADR-0031). Without it the App runs TS systems on its own. */
64
+ readonly core?: Core;
65
+ /** Fixed simulation rate (default 60). */
66
+ readonly fixedHz?: number;
67
+ /** Most fixed steps per frame before time is dropped (default 4). */
68
+ readonly maxSubsteps?: number;
69
+ /**
70
+ * Let the governor lower the fixed steps per frame (`sim.substeps`: max, then 1) when frames
71
+ * are CPU-bound over budget (default true). A slow device then runs the simulation
72
+ * slower than real time instead of halving its frame rate: past 16.6 ms a frame needs two
73
+ * steps, which doubles the simulation's cost (measured on a Galaxy F04, ADR-0046).
74
+ */
75
+ readonly adaptiveSubsteps?: boolean;
76
+ /** Frame driver (default: requestAnimationFrame). */
77
+ readonly frames?: FrameSource;
78
+ /** Pause automatically when the page is hidden or frozen (default true in a browser). */
79
+ readonly pauseWhenHidden?: boolean;
80
+ /** Record frames into `app.profiler` (default true; ADR-0025). */
81
+ readonly profile?: boolean;
82
+ /** The profiler's clock in ms (default `performance.now`; tests and headless runs inject one). */
83
+ readonly clock?: () => number;
84
+ /** Seed of `app.rng` (default: random). Pass one for runs that must repeat exactly. */
85
+ readonly seed?: number;
86
+ /** The frame-budget governor (DESIGN.md §4). It reads the profiler, so it needs `profile`. */
87
+ readonly governor?: GovernorOptions;
88
+ /**
89
+ * The app's worker threads (ADR-0076): `app.pool`, one pool for the world's Rust jobs and
90
+ * the TS worker systems listed here (ADR-0037). Needs `core`. Take the count from
91
+ * `loadCore` (threads where the page can run them); `@yali-engine/vite`'s `virtual:yali/threads`
92
+ * builds the whole object. Without it the app has no pool.
93
+ */
94
+ readonly threads?: ThreadsOptions;
95
+ }
96
+ /**
97
+ * The registration surface plugins get (DESIGN.md §2). Everything registered here is
98
+ * recorded against the plugin and unwound automatically when the app is disposed.
99
+ */
100
+ export interface AppBuilder {
101
+ readonly app: App;
102
+ /** Adds a TS system to a stage. Names are unique. */
103
+ system(system: AppSystem): void;
104
+ /** Listens for a lifecycle event while the plugin is alive. */
105
+ on<T extends LifecycleEvent['type']>(type: T, fn: (e: Extract<LifecycleEvent, {
106
+ type: T;
107
+ }>) => void): void;
108
+ /** Registers how to rebuild this plugin's GPU state after device loss. */
109
+ recover(fn: RecoverFn): void;
110
+ /** Reports live resources for the dispose leak check (GPU buffers, workers, handles…). */
111
+ leaks(fn: () => Partial<LeakReport>): void;
112
+ /** Runs on dispose, in reverse registration order. */
113
+ onDispose(fn: () => void | Promise<void>): void;
114
+ /** Shares a value with other plugins under a key (a TS-side resource). */
115
+ provide<T>(key: string, value: T): void;
116
+ /** Adds a profiler counter while the plugin is alive (`read` must be cheap, no allocation). */
117
+ counter(name: string, read: () => number, unit?: string): void;
118
+ /** Adds a quality knob for the governor while the plugin is alive (restored on dispose). */
119
+ quality(knob: QualityKnob): void;
120
+ /** Adds a tool agents can call on the running app (DESIGN.md §19), while the plugin is alive. */
121
+ tool(def: ToolDef): void;
122
+ }
123
+ /**
124
+ * One Yali application: a lifecycle (DESIGN.md §3), plugins built in dependency order, and
125
+ * a frame loop with a fixed-timestep simulation (§4). No global state: several apps can
126
+ * share a page.
127
+ *
128
+ * @example
129
+ * const app = App.create({ plugins: [renderPlugin({ canvas })] });
130
+ * await app.init();
131
+ * app.start();
132
+ */
133
+ export declare class App {
134
+ #private;
135
+ readonly lifecycle: Lifecycle;
136
+ readonly time: Time;
137
+ /** Per-frame CPU, GPU and counter timings (ADR-0025). */
138
+ readonly profiler: Profiler;
139
+ /** The frame-budget governor and its quality knobs (DESIGN.md §4). */
140
+ readonly quality: QualityGovernor;
141
+ /** Tools agents call on the running app (`@yali-engine/mcp`); `app.*` tools are built in. */
142
+ readonly tools: ToolRegistry;
143
+ /** The app's seeded random numbers: gameplay draws from this, so a seed replays a run. */
144
+ readonly rng: Rng;
145
+ readonly options: AppOptions;
146
+ /** Errors thrown by systems this session (name → count), so a broken system is visible. */
147
+ readonly systemErrors: Map<string, number>;
148
+ private constructor();
149
+ /**
150
+ * The app's worker pool (ADR-0076; needs `App.create({ threads })`): `pool.run(system,
151
+ * query, args)` runs a TS worker system over a query's chunks in parallel, and the world's
152
+ * Rust systems split across the same workers. With 0 workers it all runs on this thread.
153
+ */
154
+ get pool(): WorkerPool;
155
+ /** The app's world (needs `App.create({ core })`). Plugins register components on it. */
156
+ get world(): World;
157
+ /** Creates and configures an app (state Configured): plugins are ordered and validated. */
158
+ static create(options: AppOptions): App;
159
+ /** A value a plugin provided. Throws `MISSING_RESOURCE` with the plugin to add. */
160
+ resource<T>(key: string): T;
161
+ /** Whether a plugin provided `key`. */
162
+ hasResource(key: string): boolean;
163
+ /**
164
+ * Initializing: builds every plugin in dependency order (each emits `init:plugin`), then
165
+ * moves to Running (not yet ticking; call `start`). A plugin that throws moves the app
166
+ * to Failed, and the error is rethrown.
167
+ */
168
+ init(): Promise<void>;
169
+ /** Starts driving frames from the frame source. */
170
+ start(): void;
171
+ /**
172
+ * Runs one frame of `seconds` synchronously: every stage in order, FixedUpdate once per
173
+ * fixed step. Headless tests drive the app with this. A system that throws is counted
174
+ * and logged; the frame continues.
175
+ */
176
+ step(seconds: number): void;
177
+ /** Pauses (DESIGN.md §3): frames keep arriving but no stage runs. */
178
+ pause(reason?: PauseReason): void;
179
+ /** Resumes. Accumulated time is reset, so a long pause causes no catch-up steps. */
180
+ resume(): void;
181
+ /**
182
+ * Reports GPU device loss (the render plugin calls this). Unless the app is disposing,
183
+ * it moves to Recovering and runs every plugin's recover function in build order. On
184
+ * success it returns to Running and emits `recovered`; on failure it moves to Failed.
185
+ * The simulation keeps its state; the game is not restarted.
186
+ */
187
+ deviceLost(info: DeviceLossInfo): Promise<void>;
188
+ /**
189
+ * Disposes: plugins in reverse build order (their registrations first, then their own
190
+ * `dispose`), then the leak check. `disposed.leaks` must be all zeros on a clean dispose;
191
+ * tests assert it.
192
+ */
193
+ dispose(): Promise<LeakReport>;
194
+ }