@series-inc/rundot-kinetix 0.0.0-bootstrap.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 (58) hide show
  1. package/README.md +77 -0
  2. package/authoring.d.ts +30 -0
  3. package/index.d.ts +221 -0
  4. package/native/component_runtime.cpp +341 -0
  5. package/native/component_runtime.hpp +112 -0
  6. package/native/deterministic_math.cpp +594 -0
  7. package/native/deterministic_math.hpp +21 -0
  8. package/native/kinetix-f64-native-profile.cpp +406 -0
  9. package/native/kinetix-f64-native-profile.hpp +5 -0
  10. package/native/kinetix-fixed1000-native-profile.cpp +777 -0
  11. package/native/kinetix-fixed1000-native-profile.hpp +58 -0
  12. package/native/kinetix-fixed1000-physics.cpp +887 -0
  13. package/native/kinetix-fixed1000-physics.hpp +28 -0
  14. package/native/kinetix-installed-f64-renderer.cpp +344 -0
  15. package/native/kinetix-installed-f64-renderer.hpp +35 -0
  16. package/native/kinetix-installed-f64-runtime.cpp +1085 -0
  17. package/native/kinetix-installed-f64-runtime.hpp +141 -0
  18. package/native/kinetix-installed-fixed1000-data.hpp +77 -0
  19. package/native/kinetix-native-main.cpp +37 -0
  20. package/native/kinetix-native-runtime.cpp +20 -0
  21. package/native/kinetix-native-runtime.hpp +25 -0
  22. package/native/kinetix-render-projection.cpp +20 -0
  23. package/native/kinetix-render-projection.hpp +14 -0
  24. package/package.json +65 -0
  25. package/runtime.d.ts +76 -0
  26. package/scripts/build-native.mjs +67 -0
  27. package/scripts/emit-product-digests.mjs +33 -0
  28. package/scripts/preflight.mjs +76 -0
  29. package/src/index.mjs +57 -0
  30. package/src/kinetix-authoring.mjs +69 -0
  31. package/src/kinetix-baker.mjs +587 -0
  32. package/src/kinetix-deterministic-math.mjs +1044 -0
  33. package/src/kinetix-fixed1000-runtime-adapter.mjs +33 -0
  34. package/src/kinetix-fixed1000-runtime.mjs +954 -0
  35. package/src/kinetix-installed-f64-reference.mjs +157 -0
  36. package/src/kinetix-installed-f64-render-frames.mjs +53 -0
  37. package/src/kinetix-installed-f64-renderer.mjs +240 -0
  38. package/src/kinetix-installed-f64-runtime-adapter.mjs +68 -0
  39. package/src/kinetix-installed-f64-runtime.mjs +607 -0
  40. package/src/kinetix-installed-mechanics.mjs +377 -0
  41. package/src/kinetix-installed-systems.mjs +181 -0
  42. package/src/kinetix-native-product.mjs +72 -0
  43. package/src/kinetix-product-contract.mjs +121 -0
  44. package/src/kinetix-project-compiler.mjs +1017 -0
  45. package/src/kinetix-render-projection.mjs +28 -0
  46. package/src/kinetix-runtime-adapter-utils.mjs +168 -0
  47. package/src/kinetix-runtime-contract.mjs +54 -0
  48. package/src/kinetix-session-config.mjs +170 -0
  49. package/src/kinetix-source-snapshot.mjs +24 -0
  50. package/src/kinetix-survival-runtime-adapter.mjs +305 -0
  51. package/src/kinetix-survival-runtime.generated.mjs +1 -0
  52. package/src/kinetix-world-kernel.mjs +580 -0
  53. package/src/kinetix-world-runtime.mjs +171 -0
  54. package/src/runtime.mjs +14 -0
  55. package/src/shared/f64-bits.mjs +14 -0
  56. package/src/shared/kinetix-envelope-v1.mjs +589 -0
  57. package/src/shared/render-records-v1.mjs +168 -0
  58. package/src/shared/sha256.mjs +73 -0
@@ -0,0 +1,121 @@
1
+ import { createHash } from 'node:crypto';
2
+
3
+ import {
4
+ assertKinetixRuntimeIdentity,
5
+ kinetixRuntimeAbiVersion,
6
+ } from './kinetix-runtime-contract.mjs';
7
+
8
+ export const kinetixProductKinds = Object.freeze(['simulation', 'presentation', 'binding']);
9
+
10
+ export function stableKinetixContractBytes(value) {
11
+ return Buffer.from(JSON.stringify(canonicalize(value)));
12
+ }
13
+
14
+ export function digestKinetixBytes(bytes) {
15
+ return createHash('sha256').update(bytes).digest('hex');
16
+ }
17
+
18
+ export function assertKinetixProductContract(products) {
19
+ if (!isPlainObject(products)
20
+ || !/^[0-9a-f]{64}$/u.test(products.sourceDigest)
21
+ || !isPlainObject(products.manifest)
22
+ || !Array.isArray(products.manifest.payloads)) {
23
+ throw new Error('KINETIX_PRODUCTS_INVALID');
24
+ }
25
+
26
+ const payloadKinds = products.manifest.payloads.map((entry) => entry?.name);
27
+ if (payloadKinds.some((kind) => !kinetixProductKinds.includes(kind))) {
28
+ throw new Error('KINETIX_PRODUCT_KIND_UNKNOWN');
29
+ }
30
+ if (new Set(payloadKinds).size !== payloadKinds.length) {
31
+ throw new Error('KINETIX_PRODUCT_KIND_DUPLICATE');
32
+ }
33
+ if (payloadKinds.length !== kinetixProductKinds.length
34
+ || kinetixProductKinds.some((kind) => !payloadKinds.includes(kind))) {
35
+ throw new Error('KINETIX_PRODUCT_KIND_MISSING');
36
+ }
37
+
38
+ for (const kind of kinetixProductKinds) {
39
+ if (!Object.hasOwn(products, kind)) {
40
+ throw new Error('KINETIX_PRODUCT_PAYLOAD_MISSING');
41
+ }
42
+ const declaration = products.manifest.payloads.find((entry) => entry.name === kind);
43
+ if (!/^[0-9a-f]{64}$/u.test(declaration.digest)) {
44
+ throw new Error('KINETIX_PRODUCT_DIGEST_MISSING');
45
+ }
46
+ const bytes = stableKinetixContractBytes(products[kind]);
47
+ if (declaration.byteLength !== bytes.length) {
48
+ throw new Error('KINETIX_PRODUCT_BYTE_LENGTH_MISMATCH');
49
+ }
50
+ if (declaration.digest !== digestKinetixBytes(bytes)) {
51
+ throw new Error('KINETIX_PRODUCT_DIGEST_MISMATCH');
52
+ }
53
+ }
54
+ return products;
55
+ }
56
+
57
+ export function deriveKinetixRuntimeIdentity(products, runtimeContract = products?.manifest?.runtime) {
58
+ assertKinetixProductContract(products);
59
+ assertKinetixRuntimeContract(runtimeContract);
60
+ const simulation = products.manifest.payloads.find((entry) => entry.name === 'simulation');
61
+ return assertKinetixRuntimeIdentity({
62
+ abiVersion: kinetixRuntimeAbiVersion,
63
+ tickRate: runtimeContract.tickRate,
64
+ inputSchemaId: digestKinetixBytes(stableKinetixContractBytes({
65
+ domain: 'rundot.kinetix-input-schema.v1',
66
+ schema: runtimeContract.inputSchema,
67
+ })),
68
+ stateSchemaId: digestKinetixBytes(stableKinetixContractBytes({
69
+ domain: 'rundot.kinetix-state-schema.v1',
70
+ schema: runtimeContract.stateSchema,
71
+ })),
72
+ deterministicVersion: runtimeContract.deterministicVersion,
73
+ engineIdentityHash: digestKinetixBytes(stableKinetixContractBytes({
74
+ domain: 'rundot.kinetix-engine-identity.v1',
75
+ sourceDigest: products.sourceDigest,
76
+ targetProfile: runtimeContract.targetProfile,
77
+ numericProfile: runtimeContract.numericProfile,
78
+ deterministicAbi: runtimeContract.deterministicAbi,
79
+ simulationPayloadDigest: simulation.digest,
80
+ })),
81
+ });
82
+ }
83
+
84
+ export function assertKinetixRuntimeIdentityMatchesProducts(products, identity) {
85
+ assertKinetixRuntimeIdentity(identity);
86
+ const expected = deriveKinetixRuntimeIdentity(products);
87
+ if (stableKinetixContractBytes(expected).equals(stableKinetixContractBytes(identity)) === false) {
88
+ throw new Error('KINETIX_RUNTIME_IDENTITY_PRODUCT_MISMATCH');
89
+ }
90
+ return identity;
91
+ }
92
+
93
+ export function assertKinetixRuntimeContract(runtimeContract) {
94
+ if (!isPlainObject(runtimeContract)
95
+ || ![10, 20, 30, 60].includes(runtimeContract.tickRate)
96
+ || typeof runtimeContract.targetProfile !== 'string'
97
+ || runtimeContract.targetProfile.length === 0
98
+ || typeof runtimeContract.numericProfile !== 'string'
99
+ || runtimeContract.numericProfile.length === 0
100
+ || typeof runtimeContract.deterministicAbi !== 'string'
101
+ || runtimeContract.deterministicAbi.length === 0
102
+ || typeof runtimeContract.deterministicVersion !== 'string'
103
+ || runtimeContract.deterministicVersion.length === 0
104
+ || !isPlainObject(runtimeContract.inputSchema)
105
+ || !isPlainObject(runtimeContract.stateSchema)) {
106
+ throw new Error('KINETIX_RUNTIME_CONTRACT_INVALID');
107
+ }
108
+ return runtimeContract;
109
+ }
110
+
111
+ function canonicalize(value) {
112
+ if (Array.isArray(value)) return value.map(canonicalize);
113
+ if (isPlainObject(value)) {
114
+ return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalize(value[key])]));
115
+ }
116
+ return value;
117
+ }
118
+
119
+ function isPlainObject(value) {
120
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
121
+ }