@forgeax/engine-pack 0.1.28 → 0.1.30

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 (63) hide show
  1. package/README.md +33 -5
  2. package/dist/build.mjs +99 -60
  3. package/dist/build.mjs.map +1 -1
  4. package/dist/catalog-projection.d.ts +3 -3
  5. package/dist/cli-asset.mjs +22 -13
  6. package/dist/cli-asset.mjs.map +1 -1
  7. package/dist/evidence/material-cook.d.ts +7 -1
  8. package/dist/evidence/material-cook.d.ts.map +1 -1
  9. package/dist/index.mjs +61 -5
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/inventory/declaration.d.ts +1 -1
  12. package/dist/inventory/declaration.d.ts.map +1 -1
  13. package/dist/inventory/sync.d.ts.map +1 -1
  14. package/dist/material-cook.mjs +61 -5
  15. package/dist/material-cook.mjs.map +1 -1
  16. package/dist/native-cooker-registry.d.ts +1 -0
  17. package/dist/native-cooker-registry.d.ts.map +1 -1
  18. package/dist/native-cooker.mjs.map +1 -1
  19. package/dist/pack-authoring-node.mjs +22 -13
  20. package/dist/pack-authoring-node.mjs.map +1 -1
  21. package/dist/pack-authoring.d.ts +8 -2
  22. package/dist/pack-authoring.d.ts.map +1 -1
  23. package/dist/pack-authoring.mjs.map +1 -1
  24. package/dist/runtime-publication.d.ts +2 -0
  25. package/dist/runtime-publication.d.ts.map +1 -1
  26. package/dist/runtime.mjs.map +1 -1
  27. package/dist/scanner.mjs +22 -13
  28. package/dist/scanner.mjs.map +1 -1
  29. package/dist/schema-compiled.d.ts.map +1 -1
  30. package/dist/schema.mjs +40 -62
  31. package/dist/schema.mjs.map +1 -1
  32. package/dist/scriptable-pack-node.d.ts.map +1 -1
  33. package/dist/scriptable-pack-node.mjs +12 -4
  34. package/dist/scriptable-pack-node.mjs.map +1 -1
  35. package/dist/scriptable-pack-worker.mjs +12 -5
  36. package/dist/scriptable-pack-worker.mjs.map +1 -1
  37. package/dist/scriptable-pack.d.ts +2 -1
  38. package/dist/scriptable-pack.d.ts.map +1 -1
  39. package/dist/scriptable-pack.mjs.map +1 -1
  40. package/package.json +2 -2
  41. package/src/__tests__/inventory-schema.test.ts +10 -10
  42. package/src/__tests__/material-cook-schema.unit.test.ts +92 -1
  43. package/src/__tests__/pack-authoring.unit.test.ts +2 -4
  44. package/src/__tests__/pack.unit.test.ts +86 -124
  45. package/src/__tests__/runtime-publication.unit.test.ts +36 -0
  46. package/src/__tests__/scanner-instance-cycle.test.ts +92 -0
  47. package/src/__tests__/scanner-inventory.contract.test.ts +2 -2
  48. package/src/__tests__/scriptable-pack-cli.integration.test.ts +35 -1
  49. package/src/__tests__/scriptable-pack-diagnostic.integration.test.ts +45 -0
  50. package/src/evidence/material-cook.ts +79 -5
  51. package/src/inventory/binding.ts +3 -3
  52. package/src/inventory/declaration.ts +10 -48
  53. package/src/inventory/sync.ts +3 -2
  54. package/src/native-cooker-registry.ts +1 -0
  55. package/src/pack-authoring.ts +11 -2
  56. package/src/runtime-publication.ts +7 -3
  57. package/src/scanner.ts +28 -28
  58. package/src/schema/material-cook.schema.json +107 -0
  59. package/src/schema-compiled.ts +40 -79
  60. package/src/scriptable-pack-node.ts +16 -4
  61. package/src/scriptable-pack-worker.ts +23 -5
  62. package/src/scriptable-pack.ts +2 -1
  63. package/src/__tests__/scanner-mount-cycle.test.ts +0 -232
@@ -5,7 +5,7 @@ export interface AuthorInventoryRow {
5
5
  readonly kind: string;
6
6
  readonly payload: Readonly<Record<string, unknown>>;
7
7
  readonly refs: readonly string[];
8
- readonly sceneBindings?: readonly string[];
8
+ readonly sceneEntityKeys?: readonly string[];
9
9
  }
10
10
  export interface AuthorInventory {
11
11
  readonly declarations: readonly AuthorInventoryRow[];
@@ -1 +1 @@
1
- {"version":3,"file":"declaration.d.ts","sourceRoot":"","sources":["../../src/inventory/declaration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,YAAY,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACtD;AAED,MAAM,MAAM,kBAAkB,GAC1B,8BAA8B,GAC9B,gCAAgC,GAChC,0BAA0B,GAC1B,iCAAiC,GACjC,mCAAmC,CAAC;AAExC,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;KAC7B,CAAC;CACH,CAAC;AAWF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,eAAe,EAAE,cAAc,CAAC,CA8H/F"}
1
+ {"version":3,"file":"declaration.d.ts","sourceRoot":"","sources":["../../src/inventory/declaration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,YAAY,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACtD;AAED,MAAM,MAAM,kBAAkB,GAC1B,8BAA8B,GAC9B,gCAAgC,GAChC,0BAA0B,GAC1B,iCAAiC,GACjC,mCAAmC,CAAC;AAExC,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;KAC7B,CAAC;CACH,CAAC;AAWF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,eAAe,EAAE,cAAc,CAAC,CAwF/F"}
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/inventory/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAErC,wBAAgB,eAAe,CAAC,SAAS,EAAE,eAAe,GAAG,eAAe,CAO3E;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,eAAe,GAAG,eAAe,CAQ/E"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/inventory/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAErC,wBAAgB,eAAe,CAAC,SAAS,EAAE,eAAe,GAAG,eAAe,CAQ3E;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,eAAe,GAAG,eAAe,CAQ/E"}
@@ -1,4 +1,4 @@
1
- import { deriveStandardLayerPlan, MATERIAL_TEXTURE_SLOTS, ok, err } from '@forgeax/engine-types';
1
+ import { deriveStandardLayerPlan, MATERIAL_TEXTURE_SLOTS, isMaterialProgramAbi, ok, err } from '@forgeax/engine-types';
2
2
  import { sha256 } from '@noble/hashes/sha2.js';
3
3
  import { bytesToHex } from '@noble/hashes/utils.js';
4
4
 
@@ -266,6 +266,9 @@ function validateCookedMaterialRecord(value) {
266
266
  const programs = [];
267
267
  const programKeys = /* @__PURE__ */ new Set();
268
268
  const selections = /* @__PURE__ */ new Set();
269
+ const submissionSelections = /* @__PURE__ */ new Map();
270
+ let modernPublication = false;
271
+ let legacySelectionField;
269
272
  const selectedPasses = /* @__PURE__ */ new Set();
270
273
  for (const [index, entry] of candidate.programs.entries()) {
271
274
  const field = `programs[${index}]`;
@@ -283,9 +286,11 @@ function validateCookedMaterialRecord(value) {
283
286
  if (!Array.isArray(program.selections) || program.selections.length === 0)
284
287
  return invalid(`${field}.selections`);
285
288
  const programSelections = [];
286
- for (const [selectionIndex, selection] of program.selections.entries()) {
289
+ for (const [selectionIndex, rawSelection] of program.selections.entries()) {
287
290
  const selectionField = `${field}.selections[${selectionIndex}]`;
288
- if (selection === null || typeof selection !== "object" || !passNames.has(selection.pass))
291
+ if (rawSelection === null || typeof rawSelection !== "object") return invalid(selectionField);
292
+ const selection = rawSelection;
293
+ if (typeof selection.pass !== "string" || !passNames.has(selection.pass))
289
294
  return invalid(selectionField);
290
295
  const context = validateMaterialCookProgramContext(selection.context);
291
296
  if (!context.ok)
@@ -293,11 +298,51 @@ function validateCookedMaterialRecord(value) {
293
298
  `${selectionField}.${context.error.detail.field}`,
294
299
  context.error.detail.actual
295
300
  );
296
- const key = JSON.stringify([selection.pass, materialProgramContextKey(context.value)]);
301
+ const address = selection.address === void 0 ? "direct" : selection.address;
302
+ if (address !== "direct" && address !== "scene-index")
303
+ return invalid(`${selectionField}.address`, selection.address);
304
+ const hasAddressFacts = selection.address !== void 0 || selection.entry !== void 0 || selection.abi !== void 0;
305
+ modernPublication ||= hasAddressFacts;
306
+ if (!hasAddressFacts) legacySelectionField ??= selectionField;
307
+ const rawEntry = selection.entry;
308
+ const entry2 = typeof rawEntry === "string" ? rawEntry : void 0;
309
+ if (hasAddressFacts && selection.address === void 0)
310
+ return invalid(
311
+ `${selectionField}.address`,
312
+ "modern ABI selections require an explicit address"
313
+ );
314
+ if (hasAddressFacts && (entry2 === void 0 || entry2.length === 0))
315
+ return invalid(`${selectionField}.entry`, rawEntry);
316
+ if (hasAddressFacts && !isMaterialProgramAbi(selection.abi))
317
+ return invalid(`${selectionField}.abi`, selection.abi);
318
+ if (hasAddressFacts) {
319
+ const abi = selection.abi;
320
+ const expectedEntry = address === "direct" ? abi.directEntry : abi.sceneIndexEntry;
321
+ if (entry2 !== expectedEntry)
322
+ return invalid(`${selectionField}.entry`, "entry does not match published ABI");
323
+ const submissionKey = JSON.stringify([
324
+ selection.pass,
325
+ materialProgramContextKey(context.value)
326
+ ]);
327
+ const addresses = submissionSelections.get(submissionKey) ?? /* @__PURE__ */ new Set();
328
+ addresses.add(address);
329
+ submissionSelections.set(submissionKey, addresses);
330
+ }
331
+ const key = JSON.stringify([
332
+ selection.pass,
333
+ materialProgramContextKey(context.value),
334
+ address
335
+ ]);
297
336
  if (selections.has(key)) return invalid(selectionField, "ambiguous Pass/context selection");
298
337
  selections.add(key);
299
338
  selectedPasses.add(selection.pass);
300
- programSelections.push({ pass: selection.pass, context: context.value });
339
+ programSelections.push({
340
+ pass: selection.pass,
341
+ context: context.value,
342
+ ...selection.address === void 0 ? {} : { address },
343
+ ...entry2 === void 0 ? {} : { entry: entry2 },
344
+ ...selection.abi === void 0 ? {} : { abi: selection.abi }
345
+ });
301
346
  }
302
347
  programs.push({
303
348
  specializationKey: program.specializationKey,
@@ -305,6 +350,17 @@ function validateCookedMaterialRecord(value) {
305
350
  selections: programSelections
306
351
  });
307
352
  }
353
+ if (modernPublication && legacySelectionField !== void 0) {
354
+ return invalid(
355
+ legacySelectionField,
356
+ "modern material publications require address, entry, and ABI facts on every selection"
357
+ );
358
+ }
359
+ for (const [selectionKey, addresses] of submissionSelections) {
360
+ if (addresses.size !== 2) {
361
+ return invalid("programs.selections", `incomplete submission address pair: ${selectionKey}`);
362
+ }
363
+ }
308
364
  if ([...passNames].some((pass) => !selectedPasses.has(pass)))
309
365
  return invalid("programs.selections", "unpublished Pass");
310
366
  const manifestDigest = createMaterialProgramSetDigest(programs, passes);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/evidence/material-cook.ts"],"names":[],"mappings":";;;;;AAkIA,IAAM,qBAAA,uBAA4B,GAAA,CAAI;AAAA,EACpC,+BAAA;AAAA,EACA,mBAAA;AAAA,EACA,4BAAA;AAAA,EACA;AACF,CAAC,CAAA;AAGM,SAAS,qBAAqB,MAAA,EAAyB;AAC5D,EAAA,OAAO,qBAAA,CAAsB,IAAI,MAAM,CAAA;AACzC;AAEO,SAAS,yBAAyB,MAAA,EAAyD;AAChG,EAAA,OAAO,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,CAAC,SAAS,oBAAA,CAAqB,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAC,CAAA;AACxF;AAOO,SAAS,0BACd,MAAA,EACoB;AACpB,EAAA,IAAI,CAAC,wBAAA,CAAyB,MAAM,CAAA,EAAG;AACrC,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,wBAAwB,MAAA,CAAO,QAAA,CAAS,YAAY,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,CAAE,QAAA;AACrF;AAEA,SAAS,OAAO,MAAA,EAA8C;AAC5D,EAAA,OAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,EAAE,IAAA,EAAK;AACnC;AAEA,SAAS,SAAS,KAAA,EAAoC;AACpD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GACpB,QACA,KAAA,CAAM,IAAA,CAAK,OAAO,CAAC,IAAA,KAAS,KAAK,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AAC7E;AAEA,SAAS,aAAa,KAAA,EAAqD;AACzE,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GAAW,MAAA,GAAY,SAAS,KAAK,CAAA;AAC/D;AAEA,SAAS,aAAA,CACP,QACA,aAAA,EACiC;AACjC,EAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,MAAA,IAAU,EAAE,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,IAAA,EAAM,KAAK,CAAA,KAAM;AAC7D,IAAA,IAAI,KAAA,KAAU,IAAA,EAAM,OAAO,EAAC;AAC5B,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,OAAO,aAAA,CAAc,GAAA,CAAI,IAAI,CAAA,GAAI,CAAC,EAAE,OAAA,EAAS,KAAA,EAAO,CAAA,GAAI,EAAC;AAAA,IAC3D;AACA,IAAA,OAAO,KAAA,KAAU,IAAA,IACf,OAAO,KAAA,KAAU,YACjB,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,KACpB,SAAA,IAAa,KAAA,GACX,CAAC,KAA6B,IAC9B,EAAC;AAAA,EACP,CAAC,CAAA;AACH;AAEO,SAAS,wBAAwB,QAAA,EAAoD;AAC1F,EAAA,MAAM,aAAA,GACJ,SAAS,UAAA,KAAe,MAAA,GACpB,IAAI,GAAA,CAAY,sBAAsB,IACtC,IAAI,GAAA;AAAA,IACF,SAAS,UAAA,CACN,MAAA;AAAA,MACC,CAAC,SAAA,KAAc,SAAA,CAAU,IAAA,KAAS,SAAA,IAAa,UAAU,IAAA,KAAS;AAAA,KACpE,CACC,GAAA,CAAI,CAAC,SAAA,KAAc,UAAU,IAAI;AAAA,GACtC;AACN,EAAA,MAAM,QAAA,GAAW,aAAA,CAAc,QAAA,CAAS,MAAA,EAAQ,aAAa,CAAA;AAC7D,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,SAAS,MAAA,GAAS,CAAC,SAAS,QAAA,CAAS,MAAM,CAAC,CAAA,GAAI,EAAC;AAAA,IACzD,QAAA,EAAU,MAAA;AAAA,MACR,QAAA,CAAS,OAAA,CAAQ,CAAC,KAAA,KAAU;AAC1B,QAAA,MAAM,IAAA,GAAO,YAAA,CAAa,KAAA,CAAM,OAAO,CAAA;AACvC,QAAA,OAAO,IAAA,KAAS,MAAA,GAAY,EAAC,GAAI,CAAC,IAAI,CAAA;AAAA,MACxC,CAAC;AAAA,KACH;AAAA,IACA,QAAA,EAAU,MAAA;AAAA,MACR,QAAA,CAAS,OAAA,CAAQ,CAAC,KAAA,KAAU;AAC1B,QAAA,IAAI,KAAA,CAAM,OAAA,KAAY,MAAA,EAAW,OAAO,EAAC;AACzC,QAAA,MAAM,IAAA,GAAO,YAAA,CAAa,KAAA,CAAM,OAAO,CAAA;AACvC,QAAA,OAAO,IAAA,KAAS,MAAA,GAAY,EAAC,GAAI,CAAC,IAAI,CAAA;AAAA,MACxC,CAAC;AAAA,KACH;AAAA,IACA,OAAA,EAAS,MAAA,CAAA,CAAQ,QAAA,CAAS,MAAA,IAAU,EAAC,EAAG,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAC;AAAA,GAC5E;AACF;AAEO,SAAS,6BAA6B,KAAA,EAA2B;AACtE,EAAA,OAAO,CAAA,OAAA,EAAU,UAAA,CAAW,MAAA,CAAO,KAAK,CAAC,CAAC,CAAA,CAAA;AAC5C;AAEA,SAAS,UAAU,KAAA,EAAyB;AAC1C,EAAA,IAAI,KAAA,YAAiB,UAAA,EAAY,OAAO,CAAC,GAAG,KAAK,CAAA;AACjD,EAAA,IAAI,MAAM,OAAA,CAAQ,KAAK,GAAG,OAAO,KAAA,CAAM,IAAI,SAAS,CAAA;AACpD,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,OAAO,KAAA,KAAU,QAAA,EAAU;AAC/C,IAAA,OAAO,MAAA,CAAO,WAAA;AAAA,MACZ,OAAO,OAAA,CAAQ,KAAK,CAAA,CACjB,MAAA,CAAO,CAAC,GAAG,KAAK,CAAA,KAAM,UAAU,MAAS,CAAA,CACzC,IAAA,CAAK,CAAC,CAAC,CAAC,CAAA,EAAG,CAAC,CAAC,MAAM,CAAA,CAAE,aAAA,CAAc,CAAC,CAAC,EACrC,GAAA,CAAI,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM,CAAC,KAAK,SAAA,CAAU,KAAK,CAAC,CAAC;AAAA,KAClD;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,2BAA2B,KAAA,EAAwD;AACjG,EAAA,MAAM,YAAA,GAAe,4BAAA;AAAA,IACnB,IAAI,aAAY,CAAE,MAAA;AAAA,MAChB,IAAA,CAAK,SAAA;AAAA,QACH,SAAA,CAAU;AAAA,UACR,wBAAwB,KAAA,CAAM,sBAAA;AAAA,UAC9B,gBAAgB,KAAA,CAAM,cAAA;AAAA,UACtB,qBAAqB,KAAA,CAAM,mBAAA;AAAA,UAC3B,gBAAgB,KAAA,CAAM,cAAA;AAAA,UACtB,iBAAiB,KAAA,CAAM,eAAA;AAAA,UACvB,kBAAkB,KAAA,CAAM,gBAAA;AAAA,UACxB,qBAAqB,KAAA,CAAM,mBAAA;AAAA,UAC3B,MAAM,KAAA,CAAM,IAAA;AAAA,UACZ,gBAAgB,KAAA,CAAM;AAAA,SACvB;AAAA;AACH;AACF,GACF;AACA,EAAA,OAAO,EAAE,GAAG,KAAA,EAAO,YAAA,EAAa;AAClC;AAEO,SAAS,8BAA8B,MAAA,EAAsC;AAClF,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,MAAM,CAAC,CAAA;AACzC;AAEO,SAAS,6BAA6B,OAAA,EAAsC;AACjF,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,EAAE,GAAG,OAAA,EAAS,aAAA,EAAe,MAAA,CAAO,OAAA,CAAQ,aAAa,CAAA,EAAG,CAAC,CAAA;AAC/F;AAEA,SAAS,OAAA,CAAQ,OAAe,MAAA,EAA0D;AACxF,EAAA,OAAO,GAAA,CAAI;AAAA,IACT,IAAA,EAAM,8BAAA;AAAA,IACN,QAAA,EAAU,wEAAA;AAAA,IACV,IAAA,EAAM,yFAAA;AAAA,IACN,MAAA,EAAQ;AAAA,MACN,KAAA;AAAA,MACA,GAAI,MAAA,KAAW,MAAA,GAAY,EAAC,GAAI,EAAE,MAAA,EAAO;AAAA,MACzC,MAAA,EAAQ;AAAA;AACV,GACD,CAAA;AACH;AAEA,SAAS,uBAAuB,KAAA,EAAwC;AACtE,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,IAAA,OAAO,MAAM,KAAA,CAAM,CAAC,IAAA,KAAS,MAAA,CAAO,UAAU,IAAI,CAAA,IAAK,IAAA,IAAQ,CAAA,IAAK,QAAQ,GAAG,CAAA,GAC3E,UAAA,CAAW,IAAA,CAAK,KAAK,CAAA,GACrB,MAAA;AAAA,EACN;AACA,EAAA,IAAI,CAAC,WAAA,CAAY,MAAA,CAAO,KAAK,GAAG,OAAO,MAAA;AACvC,EAAA,MAAM,IAAA,GAAO,KAAA;AACb,EAAA,OAAO,IAAI,WAAW,IAAA,CAAK,MAAA,EAAQ,KAAK,UAAA,EAAY,IAAA,CAAK,UAAU,CAAA,CAAE,KAAA,EAAM;AAC7E;AAEA,IAAM,eAAA,GAAkB;AAAA,EACtB,wBAAA;AAAA,EACA,gBAAA;AAAA,EACA,qBAAA;AAAA,EACA,gBAAA;AAAA,EACA,iBAAA;AAAA,EACA,kBAAA;AAAA,EACA,6BAAA;AAAA,EACA,cAAA;AAAA,EACA,qBAAA;AAAA,EACA;AACF,CAAA;AAEA,SAAS,aAAa,KAAA,EAAiC;AACrD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,aAAA,CAAc,KAAK,KAAK,KAAA,IAAS,CAAA;AAC9E;AAEA,SAAS,iBAAiB,KAAA,EAAuE;AAC/F,EAAA,IAAI,KAAA,KAAU,QAAQ,OAAO,KAAA,KAAU,UAAU,OAAO,OAAA,CAAQ,oBAAoB,KAAK,CAAA;AACzF,EAAA,MAAM,SAAA,GAAY,KAAA;AAClB,EAAA,KAAA,MAAW,SAAS,eAAA,EAAiB;AACnC,IAAA,IAAI,OAAO,UAAU,KAAK,CAAA,KAAM,YAAY,SAAA,CAAU,KAAK,CAAA,CAAE,MAAA,KAAW,CAAA,EAAG;AACzE,MAAA,OAAO,QAAQ,CAAA,iBAAA,EAAoB,KAAK,CAAA,CAAA,EAAI,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,IAC9D;AAAA,EACF;AACA,EAAA,IAAI,UAAU,IAAA,KAAS,IAAA,IAAQ,OAAO,SAAA,CAAU,SAAS,QAAA,EAAU;AACjE,IAAA,OAAO,OAAA,CAAQ,uBAAA,EAAyB,SAAA,CAAU,IAAI,CAAA;AAAA,EACxD;AACA,EAAA,MAAM,OAAO,SAAA,CAAU,IAAA;AACvB,EAAA,KAAA,MAAW,KAAA,IAAS,CAAC,kBAAA,EAAoB,gBAAA,EAAkB,YAAY,CAAA,EAAG;AACxE,IAAA,IAAI,OAAO,KAAK,KAAK,CAAA,KAAM,YAAY,IAAA,CAAK,KAAK,CAAA,CAAE,MAAA,KAAW,CAAA,EAAG;AAC/D,MAAA,OAAO,QAAQ,CAAA,sBAAA,EAAyB,KAAK,CAAA,CAAA,EAAI,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,IAC9D;AAAA,EACF;AACA,EAAA,KAAA,MAAW,KAAA,IAAS,CAAC,iBAAA,EAAmB,sBAAA,EAAwB,gBAAgB,CAAA,EAAG;AACjF,IAAA,IAAI,CAAC,YAAA,CAAa,SAAA,CAAU,KAAK,CAAC,CAAA;AAChC,MAAA,OAAO,QAAQ,CAAA,iBAAA,EAAoB,KAAK,CAAA,CAAA,EAAI,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,EAChE;AACA,EAAA,OAAO,EAAA,CAAG;AAAA,IACR,GAAG,SAAA;AAAA,IACH;AAAA,GACuB,CAAA;AAC3B;AAEO,SAAS,2BAAA,CACd,KAAA,EACA,QAAA,GAA4C,EAAC,EACS;AACtD,EAAA,IAAI,UAAU,IAAA,IAAQ,OAAO,UAAU,QAAA,EAAU,OAAO,QAAQ,SAAS,CAAA;AACzE,EAAA,MAAM,SAAA,GAAY,KAAA;AAClB,EAAA,IAAI,UAAU,aAAA,KAAkB,iBAAA;AAC9B,IAAA,OAAO,OAAA,CAAQ,uBAAA,EAAyB,SAAA,CAAU,aAAa,CAAA;AACjE,EAAA,MAAM,cAAA,GAAiB,gBAAA,CAAiB,SAAA,CAAU,QAAQ,CAAA;AAC1D,EAAA,IAAI,CAAC,cAAA,CAAe,EAAA,EAAI,OAAO,cAAA;AAC/B,EAAA,MAAM,WAAW,cAAA,CAAe,KAAA;AAChC,EAAA,IAAI,UAAU,gBAAA,KAAqB,IAAA,IAAQ,OAAO,SAAA,CAAU,qBAAqB,QAAA,EAAU;AACzF,IAAA,OAAO,OAAA,CAAQ,0BAAA,EAA4B,SAAA,CAAU,gBAAgB,CAAA;AAAA,EACvE;AACA,EAAA,MAAM,mBAAmB,SAAA,CAAU,gBAAA;AACnC,EAAA,IAAI,gBAAA,CAAiB,cAAA,KAAmB,QAAA,CAAS,cAAA,EAAgB;AAC/D,IAAA,OAAO,OAAA,CAAQ,yCAAA,EAA2C,gBAAA,CAAiB,cAAc,CAAA;AAAA,EAC3F;AACA,EAAA,IACE,gBAAA,CAAiB,iBAAA,KAAsB,MAAA,KACtC,OAAO,gBAAA,CAAiB,sBAAsB,QAAA,IAC7C,gBAAA,CAAiB,iBAAA,CAAkB,MAAA,KAAW,CAAA,CAAA,EAChD;AACA,IAAA,OAAO,OAAA;AAAA,MACL,4CAAA;AAAA,MACA,gBAAA,CAAiB;AAAA,KACnB;AAAA,EACF;AACA,EAAA,KAAA,MAAW,KAAA,IAAS,CAAC,eAAA,EAAiB,SAAA,EAAW,iBAAiB,CAAA,EAAG;AACnE,IAAA,MAAM,UAAA,GAAa,UAAU,KAAK,CAAA;AAClC,IAAA,IACG,KAAA,KAAU,eAAA,IAAmB,CAAC,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,IACtD,KAAA,KAAU,eAAA,IAAmB,OAAO,UAAA,KAAe,QAAA,EACpD;AACA,MAAA,OAAO,OAAA,CAAQ,CAAA,QAAA,EAAW,KAAK,CAAA,CAAA,EAAI,UAAU,CAAA;AAAA,IAC/C;AAAA,EACF;AACA,EAAA,MAAM,gBAAgB,SAAA,CAAU,aAAA;AAChC,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,aAAa,CAAA,IAAK,aAAA,CAAc,IAAA,CAAK,CAAC,IAAA,KAAS,OAAO,IAAA,KAAS,QAAQ,CAAA,EAAG;AAC1F,IAAA,OAAO,OAAA,CAAQ,yBAAyB,aAAa,CAAA;AAAA,EACvD;AACA,EAAA,IACE,SAAS,cAAA,KAAmB,MAAA,IAC5B,QAAA,CAAS,cAAA,KAAmB,SAAS,cAAA,EACrC;AACA,IAAA,OAAO,OAAA,CAAQ,iCAAA,EAAmC,QAAA,CAAS,cAAc,CAAA;AAAA,EAC3E;AACA,EAAA,IACE,SAAS,cAAA,KAAmB,MAAA,IAC5B,QAAA,CAAS,cAAA,KAAmB,SAAS,cAAA,EACrC;AACA,IAAA,OAAO,OAAA,CAAQ,iCAAA,EAAmC,QAAA,CAAS,cAAc,CAAA;AAAA,EAC3E;AACA,EAAA,IAAI,SAAS,WAAA,KAAgB,MAAA,IAAa,QAAA,CAAS,YAAA,KAAiB,SAAS,WAAA,EAAa;AACxF,IAAA,OAAO,OAAA,CAAQ,+BAAA,EAAiC,QAAA,CAAS,YAAY,CAAA;AAAA,EACvE;AACA,EAAA,OAAO,EAAA,CAAG;AAAA,IACR,aAAA,EAAe,iBAAA;AAAA,IACf,eAAe,SAAA,CAAU,aAAA;AAAA,IACzB,SAAS,SAAA,CAAU,OAAA;AAAA,IACnB,iBAAiB,SAAA,CAAU,eAAA;AAAA,IAC3B,QAAA;AAAA,IACA,gBAAA,EAAkB;AAAA,MAChB,gBAAgB,gBAAA,CAAiB,cAAA;AAAA,MACjC,GAAI,iBAAiB,iBAAA,KAAsB,MAAA,GACvC,EAAC,GACD,EAAE,iBAAA,EAAmB,gBAAA,CAAiB,iBAAA;AAA4B;AACxE,GACD,CAAA;AACH;AAEO,SAAS,6BACd,KAAA,EACuD;AACvD,EAAA,IAAI,UAAU,IAAA,IAAQ,OAAO,UAAU,QAAA,EAAU,OAAO,QAAQ,QAAQ,CAAA;AACxE,EAAA,MAAM,SAAA,GAAY,KAAA;AAClB,EAAA,IAAI,UAAU,aAAA,KAAkB,iBAAA;AAC9B,IAAA,OAAO,OAAA,CAAQ,eAAA,EAAiB,SAAA,CAAU,aAAa,CAAA;AACzD,EAAA,IAAI,OAAO,UAAU,IAAA,KAAS,QAAA,IAAY,CAAC,SAAA,CAAU,IAAA,EAAM,OAAO,OAAA,CAAQ,MAAM,CAAA;AAChF,EAAA,IAAI,SAAA,CAAU,YAAA,KAAiB,MAAA,IAAa,OAAO,UAAU,YAAA,KAAiB,QAAA;AAC5E,IAAA,OAAO,QAAQ,cAAc,CAAA;AAC/B,EAAA,IACE,UAAU,qBAAA,KAA0B,MAAA,IACpC,CAAC,YAAA,CAAa,UAAU,qBAAqB,CAAA;AAE7C,IAAA,OAAO,OAAA,CAAQ,uBAAA,EAAyB,SAAA,CAAU,qBAAqB,CAAA;AACzE,EAAA,IAAI,SAAA,CAAU,iBAAA,KAAsB,MAAA,IAAa,OAAO,UAAU,iBAAA,KAAsB,QAAA;AACtF,IAAA,OAAO,QAAQ,mBAAmB,CAAA;AACpC,EAAA,IAAI,UAAA,IAAc,SAAA,IAAa,UAAA,IAAc,SAAA,IAAa,gBAAA,IAAoB,SAAA;AAC5E,IAAA,OAAO,OAAA,CAAQ,YAAY,oCAAoC,CAAA;AACjE,EAAA,IAAI,SAAA,CAAU,cAAA,KAAmB,MAAA,IAAa,OAAO,UAAU,cAAA,KAAmB,QAAA;AAChF,IAAA,OAAO,QAAQ,gBAAgB,CAAA;AACjC,EAAA,IACE,UAAU,aAAA,KAAkB,MAAA,KAC3B,CAAC,KAAA,CAAM,QAAQ,SAAA,CAAU,aAAa,CAAA,IACrC,SAAA,CAAU,cAAc,IAAA,CAAK,CAAC,IAAA,KAAS,OAAO,SAAS,QAAQ,CAAA,CAAA;AAEjE,IAAA,OAAO,QAAQ,eAAe,CAAA;AAChC,EAAA,IAAI,SAAA,CAAU,sBAAsB,MAAA,EAAW;AAC7C,IAAA,IAAI,SAAA,CAAU,iBAAA,KAAsB,IAAA,IAAQ,OAAO,UAAU,iBAAA,KAAsB,QAAA;AACjF,MAAA,OAAO,QAAQ,mBAAmB,CAAA;AACpC,IAAA,MAAM,oBAAoB,SAAA,CAAU,iBAAA;AACpC,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,iBAAA,CAAkB,UAAU,CAAA;AAC7C,MAAA,OAAO,QAAQ,8BAA8B,CAAA;AAC/C,IAAA,IACE,iBAAA,CAAkB,MAAA,KAAW,IAAA,IAC7B,OAAO,iBAAA,CAAkB,WAAW,QAAA,IACpC,KAAA,CAAM,OAAA,CAAQ,iBAAA,CAAkB,MAAM,CAAA;AAEtC,MAAA,OAAO,QAAQ,0BAA0B,CAAA;AAAA,EAC7C;AACA,EAAA,IAAI,SAAA,CAAU,QAAA,KAAa,IAAA,IAAQ,OAAO,UAAU,QAAA,KAAa,QAAA;AAC/D,IAAA,OAAO,QAAQ,UAAU,CAAA;AAC3B,EAAA,IAAI,SAAA,CAAU,SAAS,IAAA,IAAQ,OAAO,UAAU,IAAA,KAAS,QAAA,EAAU,OAAO,OAAA,CAAQ,MAAM,CAAA;AACxF,EAAA,IAAI,SAAA,CAAU,OAAA,KAAY,IAAA,IAAQ,OAAO,UAAU,OAAA,KAAY,QAAA;AAC7D,IAAA,OAAO,QAAQ,SAAS,CAAA;AAC1B,EAAA,MAAM,WAAW,SAAA,CAAU,QAAA;AAC3B,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,MAAM,GAAG,OAAO,OAAA,CAAQ,iBAAA,EAAmB,QAAA,CAAS,MAAM,CAAA;AACtF,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA;AACpC,IAAA,OAAO,OAAA,CAAQ,qBAAA,EAAuB,QAAA,CAAS,UAAU,CAAA;AAC3D,EAAA,IACE,QAAA,CAAS,MAAA,KAAW,IAAA,IACpB,OAAO,QAAA,CAAS,WAAW,QAAA,IAC3B,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA;AAE7B,IAAA,OAAO,OAAA,CAAQ,iBAAA,EAAmB,QAAA,CAAS,MAAM,CAAA;AACnD,EAAA,MAAM,SAAS,QAAA,CAAS,MAAA;AACxB,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,IAAI,CAAA,IAAK,MAAA,CAAO,SAAQ,EAAG;AAC5C,IAAA,IACE,IAAA,KAAS,IAAA,IACT,OAAO,IAAA,KAAS,QAAA,IAChB,OAAO,IAAA,CAAK,IAAA,KAAS,QAAA,IACrB,CAAC,IAAA,CAAK,IAAA,IACN,SAAA,CAAU,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,IACvB,IAAA,CAAK,OAAA,KAAY,IAAA,IACjB,OAAO,IAAA,CAAK,OAAA,KAAY,QAAA,IACxB,OAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,KAAW,QAAA;AAE/B,MAAA,OAAO,OAAA,CAAQ,CAAA,gBAAA,EAAmB,KAAK,CAAA,CAAA,CAAG,CAAA;AAC5C,IAAA,SAAA,CAAU,GAAA,CAAI,KAAK,IAAI,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,CAAC,MAAM,OAAA,CAAQ,SAAA,CAAU,QAAQ,CAAA,IAAK,SAAA,CAAU,SAAS,MAAA,KAAW,CAAA;AACtE,IAAA,OAAO,QAAQ,UAAU,CAAA;AAC3B,EAAA,MAAM,WAAkC,EAAC;AACzC,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAY;AACpC,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAY;AACnC,EAAA,MAAM,cAAA,uBAAqB,GAAA,EAAY;AACvC,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,KAAK,KAAK,SAAA,CAAU,QAAA,CAAS,SAAQ,EAAG;AACzD,IAAA,MAAM,KAAA,GAAQ,YAAY,KAAK,CAAA,CAAA,CAAA;AAC/B,IAAA,IAAI,UAAU,IAAA,IAAQ,OAAO,UAAU,QAAA,EAAU,OAAO,QAAQ,KAAK,CAAA;AACrE,IAAA,MAAM,OAAA,GAAU,KAAA;AAChB,IAAA,IACE,OAAO,OAAA,CAAQ,iBAAA,KAAsB,QAAA,IACrC,CAAC,QAAQ,iBAAA,IACT,WAAA,CAAY,GAAA,CAAI,OAAA,CAAQ,iBAAiB,CAAA;AAEzC,MAAA,OAAO,OAAA,CAAQ,CAAA,EAAG,KAAK,CAAA,kBAAA,CAAoB,CAAA;AAC7C,IAAA,WAAA,CAAY,GAAA,CAAI,QAAQ,iBAAiB,CAAA;AACzC,IAAA,IAAI,OAAA,CAAQ,QAAA,KAAa,IAAA,IAAQ,OAAO,QAAQ,QAAA,KAAa,QAAA;AAC3D,MAAA,OAAO,OAAA,CAAQ,CAAA,EAAG,KAAK,CAAA,SAAA,CAAW,CAAA;AACpC,IAAA,MAAM,WAAW,OAAA,CAAQ,QAAA;AACzB,IAAA,MAAM,KAAA,GAAQ,sBAAA,CAAuB,QAAA,CAAS,KAAK,CAAA;AACnD,IAAA,IACE,SAAS,SAAA,KAAc,WAAA,IACvB,OAAO,QAAA,CAAS,SAAS,QAAA,IACzB,CAAC,QAAA,CAAS,IAAA,IACV,OAAO,QAAA,CAAS,MAAA,KAAW,YAC3B,CAAC,QAAA,CAAS,UACV,KAAA,KAAU,MAAA;AAEV,MAAA,OAAO,OAAA,CAAQ,CAAA,EAAG,KAAK,CAAA,SAAA,CAAW,CAAA;AACpC,IAAA,IAAI,CAAC,MAAM,OAAA,CAAQ,OAAA,CAAQ,UAAU,CAAA,IAAK,OAAA,CAAQ,WAAW,MAAA,KAAW,CAAA;AACtE,MAAA,OAAO,OAAA,CAAQ,CAAA,EAAG,KAAK,CAAA,WAAA,CAAa,CAAA;AACtC,IAAA,MAAM,oBAAiE,EAAC;AACxE,IAAA,KAAA,MAAW,CAAC,cAAA,EAAgB,SAAS,KAAK,OAAA,CAAQ,UAAA,CAAW,SAAQ,EAAG;AACtE,MAAA,MAAM,cAAA,GAAiB,CAAA,EAAG,KAAK,CAAA,YAAA,EAAe,cAAc,CAAA,CAAA,CAAA;AAC5D,MAAA,IAAI,SAAA,KAAc,QAAQ,OAAO,SAAA,KAAc,YAAY,CAAC,SAAA,CAAU,GAAA,CAAI,SAAA,CAAU,IAAI,CAAA;AACtF,QAAA,OAAO,QAAQ,cAAc,CAAA;AAC/B,MAAA,MAAM,OAAA,GAAU,kCAAA,CAAmC,SAAA,CAAU,OAAO,CAAA;AACpE,MAAA,IAAI,CAAC,OAAA,CAAQ,EAAA;AACX,QAAA,OAAO,OAAA;AAAA,UACL,GAAG,cAAc,CAAA,CAAA,EAAI,OAAA,CAAQ,KAAA,CAAM,OAAO,KAAK,CAAA,CAAA;AAAA,UAC/C,OAAA,CAAQ,MAAM,MAAA,CAAO;AAAA,SACvB;AACF,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,CAAC,SAAA,CAAU,MAAM,yBAAA,CAA0B,OAAA,CAAQ,KAAK,CAAC,CAAC,CAAA;AACrF,MAAA,IAAI,WAAW,GAAA,CAAI,GAAG,GAAG,OAAO,OAAA,CAAQ,gBAAgB,kCAAkC,CAAA;AAC1F,MAAA,UAAA,CAAW,IAAI,GAAG,CAAA;AAClB,MAAA,cAAA,CAAe,GAAA,CAAI,UAAU,IAAI,CAAA;AACjC,MAAA,iBAAA,CAAkB,IAAA,CAAK,EAAE,IAAA,EAAM,SAAA,CAAU,MAAM,OAAA,EAAS,OAAA,CAAQ,OAAO,CAAA;AAAA,IACzE;AACA,IAAA,QAAA,CAAS,IAAA,CAAK;AAAA,MACZ,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,MAC3B,QAAA,EAAU,EAAE,SAAA,EAAW,WAAA,EAAa,IAAA,EAAM,SAAS,IAAA,EAAM,MAAA,EAAQ,QAAA,CAAS,MAAA,EAAQ,KAAA,EAAM;AAAA,MACxF,UAAA,EAAY;AAAA,KACb,CAAA;AAAA,EACH;AACA,EAAA,IAAI,CAAC,GAAG,SAAS,CAAA,CAAE,IAAA,CAAK,CAAC,IAAA,KAAS,CAAC,cAAA,CAAe,GAAA,CAAI,IAAI,CAAC,CAAA;AACzD,IAAA,OAAO,OAAA,CAAQ,uBAAuB,kBAAkB,CAAA;AAC1D,EAAA,MAAM,cAAA,GAAiB,8BAAA,CAA+B,QAAA,EAAU,MAAM,CAAA;AACtE,EAAA,MAAM,aAAA,GAAgB,2BAAA,CAA4B,SAAA,CAAU,OAAA,EAAS;AAAA,IACnE,cAAA,EAAgB;AAAA,GACjB,CAAA;AACD,EAAA,IAAI,CAAC,aAAA,CAAc,EAAA,EAAI,OAAO,aAAA;AAC9B,EAAA,IAAI,yBAAA;AACJ,EAAA,IAAI;AACF,IAAA,yBAAA,GAA4B,yBAAA,CAA0B;AAAA,MACpD;AAAA,KACD,CAAA;AAAA,EACH,SAAS,KAAA,EAAO;AACd,IAAA,OAAO,QAAQ,4BAAA,EAA8B,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,KAAK,CAAA;AAAA,EAC7F;AACA,EAAA,IACE,8BAA8B,MAAA,IAC9B,aAAA,CAAc,KAAA,CAAM,gBAAA,CAAiB,sBAAsB,yBAAA,EAC3D;AACA,IAAA,OAAO,OAAA;AAAA,MACL,4CAAA;AAAA,MACA,aAAA,CAAc,MAAM,gBAAA,CAAiB;AAAA,KACvC;AAAA,EACF;AACA,EAAA,IAAI,SAAA,CAAU,cAAA,KAAmB,MAAA,IAAa,SAAA,CAAU,cAAA,KAAmB,cAAA;AACzE,IAAA,OAAO,OAAA,CAAQ,gBAAA,EAAkB,SAAA,CAAU,cAAc,CAAA;AAC3D,EAAA,IACE,UAAU,qBAAA,KAA0B,MAAA,IACpC,cAAc,KAAA,CAAM,QAAA,CAAS,mBAAmB,SAAA,CAAU,qBAAA;AAE1D,IAAA,OAAO,OAAA,CAAQ,iCAAA,EAAmC,aAAA,CAAc,KAAA,CAAM,SAAS,cAAc,CAAA;AAC/F,EAAA,OAAO,EAAA,CAAG;AAAA,IACR,GAAG,SAAA;AAAA,IACH,QAAA;AAAA,IACA,SAAS,aAAA,CAAc;AAAA,GACW,CAAA;AACtC;AAEO,SAAS,4BACd,MAAA,EACiD;AACjD,EAAA,OAAO;AAAA,IACL,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,eAAe,MAAA,CAAO;AAAA,GACxB;AACF;AAGO,SAAS,0BAA0B,OAAA,EAA6C;AACrF,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,OAAO,CAAC,CAAA;AAC1C;AAEO,SAAS,mCACd,KAAA,EAC6D;AAC7D,EAAA,IAAI,UAAU,IAAA,IAAQ,OAAO,UAAU,QAAA,IAAY,KAAA,CAAM,QAAQ,KAAK,CAAA;AACpE,IAAA,OAAO,OAAA,CAAQ,WAAW,KAAK,CAAA;AACjC,EAAA,MAAM,OAAA,GAAU,KAAA;AAChB,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,OAAA,EAAS,CAAC,QAAA,EAAU,QAAA,EAAU,aAAa,CAAA;AAAA,IAC3C,UAAA,EAAY,CAAC,gBAAA,EAAkB,kBAAkB,CAAA;AAAA,IACjD,QAAA,EAAU,CAAC,SAAA,EAAW,UAAU,CAAA;AAAA,IAChC,QAAA,EAAU,CAAC,MAAA,EAAQ,SAAA,EAAW,QAAQ,CAAA;AAAA,IACtC,IAAA,EAAM,CAAC,SAAA,EAAW,QAAA,EAAU,OAAO,CAAA;AAAA,IACnC,OAAA,EAAS,CAAC,0BAA0B,CAAA;AAAA,IACpC,SAAA,EAAW,CAAC,UAAU,CAAA;AAAA,IACtB,eAAA,EAAiB,CAAC,MAAA,EAAQ,YAAY;AAAA,GACxC;AACA,EAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,EAAG;AACxC,IAAA,IAAI,EAAE,KAAA,IAAS,MAAA,CAAA,EAAS,OAAO,OAAA,CAAQ,WAAW,KAAK,CAAA,CAAA,EAAI,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAC3E;AACA,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACrD,IAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,OAAA,CAAQ,KAAK,CAAW,CAAA;AAC5C,MAAA,OAAO,QAAQ,CAAA,QAAA,EAAW,KAAK,CAAA,CAAA,EAAI,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EACrD;AACA,EAAA,OAAO,EAAA,CAAG,EAAE,GAAG,OAAA,EAAkD,CAAA;AACnE;AAGO,SAAS,8BAAA,CACd,UACA,MAAA,EACQ;AACR,EAAA,MAAM,QAAA,GAAW;AAAA,IACf,MAAA;AAAA,IACA,QAAA,EAAU,QAAA,CACP,GAAA,CAAI,CAAC,OAAA,MAAa;AAAA,MACjB,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,MAC3B,QAAA,EAAU;AAAA,QACR,IAAA,EAAM,QAAQ,QAAA,CAAS,IAAA;AAAA,QACvB,SAAA,EAAW,QAAQ,QAAA,CAAS,SAAA;AAAA,QAC5B,MAAA,EAAQ,QAAQ,QAAA,CAAS;AAAA,OAC3B;AAAA,MACA,UAAA,EAAY,CAAC,GAAG,OAAA,CAAQ,UAAU,CAAA,CAAE,IAAA;AAAA,QAAK,CAAC,CAAA,EAAG,CAAA,KAC3C,IAAA,CAAK,UAAU,SAAA,CAAU,CAAC,CAAC,CAAA,CAAE,cAAc,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,CAAC,CAAC,CAAC;AAAA;AACzE,KACF,CAAE,CAAA,CACD,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,iBAAA,CAAkB,aAAA,CAAc,CAAA,CAAE,iBAAiB,CAAC;AAAA,GAC1E;AACA,EAAA,OAAO,4BAAA;AAAA,IACL,IAAI,aAAY,CAAE,MAAA,CAAO,KAAK,SAAA,CAAU,SAAA,CAAU,QAAQ,CAAC,CAAC;AAAA,GAC9D;AACF","file":"material-cook.mjs","sourcesContent":["import type {\n MaterialAsset,\n MaterialParameter,\n MaterialPass,\n MaterialTextureReference,\n MaterialTextureValue,\n MaterialValue,\n Result,\n} from '@forgeax/engine-types';\nimport { deriveStandardLayerPlan, err, MATERIAL_TEXTURE_SLOTS, ok } from '@forgeax/engine-types';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { bytesToHex } from '@noble/hashes/utils.js';\n\nexport interface MaterialCookRefs {\n readonly parent: readonly string[];\n readonly textures: readonly string[];\n readonly samplers: readonly string[];\n readonly modules: readonly string[];\n}\n\nexport interface MaterialCookArtifact {\n readonly mediaType: string;\n readonly path: string;\n readonly digest: string;\n readonly bytes: Uint8Array;\n}\n\n/** Domain-owned inputs used to compile and select a material program. */\nexport interface MaterialCookProgramContext {\n readonly backend: 'webgpu' | 'webgl2' | 'wgpu-native';\n readonly capability: 'storage-buffer' | 'uniform-fallback';\n readonly pipeline: 'forward' | 'deferred';\n readonly geometry: 'mesh' | 'skinned' | 'sprite';\n readonly pass: 'forward' | 'shadow' | 'depth';\n readonly profile: 'forgeax-material-wgsl-v1';\n readonly toolchain: 'naga-oil';\n readonly instrumentation: 'none' | 'validation';\n}\n\n/** Programs are derived artifacts, never independently authored assets. */\nexport interface MaterialCookProgram {\n readonly specializationKey: string;\n readonly artifact: MaterialCookArtifact;\n readonly selections: readonly {\n readonly pass: string;\n readonly context: MaterialCookProgramContext;\n }[];\n}\n\nexport interface MaterialCookWasmProvenance {\n readonly sourceContentKey: string;\n readonly artifactSha256: string;\n readonly glueSha256: string;\n}\n\nexport interface MaterialCookIdentity {\n readonly materialContractDigest: string;\n readonly sourceRevision: string;\n readonly sourceClosureDigest: string;\n readonly layoutIdentity: string;\n readonly programIdentity: string;\n readonly pipelineIdentity: string;\n readonly materialPublicationIdentity: string;\n readonly cookIdentity: string;\n readonly compilerFingerprint: string;\n readonly wasm: MaterialCookWasmProvenance;\n readonly artifactDigest: string;\n readonly valueGeneration: number;\n readonly dependencyGeneration: number;\n readonly cookGeneration: number;\n}\n\nexport type MaterialCookIdentityInput = Omit<MaterialCookIdentity, 'cookIdentity'>;\n\nexport interface MaterialCookReceipt {\n readonly schemaVersion: 'material-cook/4';\n readonly sourceClosure: readonly string[];\n readonly profile: string;\n readonly compilerVersion: string;\n readonly identity: MaterialCookIdentity;\n readonly derivedInterface: {\n readonly layoutIdentity: string;\n /** Build-time Standard physical lowering identity, when the root is Standard. */\n readonly layerPlanIdentity?: string;\n };\n}\n\nexport interface MaterialParameterContract {\n readonly parameters: readonly MaterialParameter[];\n readonly values: Readonly<Record<string, MaterialValue | null>>;\n}\n\nexport interface CookedMaterialRecord {\n readonly schemaVersion: 'material-cook/4';\n readonly guid: string;\n readonly authored?: MaterialAsset;\n readonly materialGuid?: string;\n readonly publicationGeneration?: number;\n readonly specializationKey?: string;\n readonly programs: readonly MaterialCookProgram[];\n /** Digest of the complete program/Pass/context manifest. */\n readonly artifactDigest?: string;\n readonly sourceClosure?: readonly string[];\n readonly parameterContract?: MaterialParameterContract;\n readonly resolved: {\n readonly passes: readonly MaterialPass[];\n readonly parameters: readonly MaterialParameter[];\n readonly values: Readonly<Record<string, MaterialValue | null>>;\n };\n readonly refs: MaterialCookRefs;\n readonly receipt: MaterialCookReceipt;\n}\n\nexport interface MaterialCookRecordError {\n readonly code: 'material-cook-record-invalid';\n readonly expected: string;\n readonly hint: string;\n readonly detail: {\n readonly field: string;\n readonly actual?: unknown;\n readonly action: string;\n };\n}\n\nexport interface MaterialCookIdentityExpectation {\n readonly layoutIdentity?: string;\n readonly artifactDigest?: string;\n readonly inputDigest?: string;\n}\n\nconst STANDARD_ROOT_MODULES = new Set([\n 'forgeax::default-standard-pbr',\n 'forgeax::pbr-skin',\n 'forgeax_material::standard',\n 'forgeax_material::pbr-skin',\n]);\n\n/** Shared ownership predicate for the built-in Standard material root. */\nexport function isStandardRootModule(module: string): boolean {\n return STANDARD_ROOT_MODULES.has(module);\n}\n\nexport function isStandardMaterialRecord(record: Pick<CookedMaterialRecord, 'resolved'>): boolean {\n return record.resolved.passes.some((pass) => isStandardRootModule(pass.program.module));\n}\n\n/**\n * Recompute the Standard layer identity from the admitted resolved root.\n * Material admission and runtime loading share this owner so a stale receipt\n * cannot select a different physical layer plan after cooking.\n */\nexport function materialLayerPlanIdentity(\n record: Pick<CookedMaterialRecord, 'resolved'>,\n): string | undefined {\n if (!isStandardMaterialRecord(record)) {\n return undefined;\n }\n return deriveStandardLayerPlan(record.resolved.parameters, record.resolved.passes).identity;\n}\n\nfunction unique(values: readonly string[]): readonly string[] {\n return [...new Set(values)].sort();\n}\n\nfunction guidText(value: string | Uint8Array): string {\n return typeof value === 'string'\n ? value\n : Array.from(value, (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\nfunction cookGuidText(value: MaterialTextureReference): string | undefined {\n return typeof value === 'number' ? undefined : guidText(value);\n}\n\nfunction textureValues(\n values: Readonly<Record<string, MaterialValue | null>> | undefined,\n textureFields: ReadonlySet<string>,\n): readonly MaterialTextureValue[] {\n return Object.entries(values ?? {}).flatMap(([name, value]) => {\n if (value === null) return [];\n if (typeof value === 'string') {\n return textureFields.has(name) ? [{ texture: value }] : [];\n }\n return value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n 'texture' in value\n ? [value as MaterialTextureValue]\n : [];\n });\n}\n\nexport function collectMaterialCookRefs(material: Partial<MaterialAsset>): MaterialCookRefs {\n const textureFields =\n material.parameters === undefined\n ? new Set<string>(MATERIAL_TEXTURE_SLOTS)\n : new Set(\n material.parameters\n .filter(\n (parameter) => parameter.type === 'texture' || parameter.type === 'texture_cube',\n )\n .map((parameter) => parameter.name),\n );\n const textures = textureValues(material.values, textureFields);\n return {\n parent: material.parent ? [guidText(material.parent)] : [],\n textures: unique(\n textures.flatMap((value) => {\n const guid = cookGuidText(value.texture);\n return guid === undefined ? [] : [guid];\n }),\n ),\n samplers: unique(\n textures.flatMap((value) => {\n if (value.sampler === undefined) return [];\n const guid = cookGuidText(value.sampler);\n return guid === undefined ? [] : [guid];\n }),\n ),\n modules: unique((material.passes ?? []).map((pass) => pass.program.module)),\n };\n}\n\nexport function createMaterialArtifactDigest(bytes: Uint8Array): string {\n return `sha256:${bytesToHex(sha256(bytes))}`;\n}\n\nfunction jsonValue(value: unknown): unknown {\n if (value instanceof Uint8Array) return [...value];\n if (Array.isArray(value)) return value.map(jsonValue);\n if (value !== null && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value)\n .filter(([, entry]) => entry !== undefined)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, entry]) => [key, jsonValue(entry)]),\n );\n }\n return value;\n}\n\nexport function createMaterialCookIdentity(input: MaterialCookIdentityInput): MaterialCookIdentity {\n const cookIdentity = createMaterialArtifactDigest(\n new TextEncoder().encode(\n JSON.stringify(\n jsonValue({\n materialContractDigest: input.materialContractDigest,\n sourceRevision: input.sourceRevision,\n sourceClosureDigest: input.sourceClosureDigest,\n layoutIdentity: input.layoutIdentity,\n programIdentity: input.programIdentity,\n pipelineIdentity: input.pipelineIdentity,\n compilerFingerprint: input.compilerFingerprint,\n wasm: input.wasm,\n artifactDigest: input.artifactDigest,\n }),\n ),\n ),\n );\n return { ...input, cookIdentity };\n}\n\nexport function serializeCookedMaterialRecord(record: CookedMaterialRecord): string {\n return JSON.stringify(jsonValue(record));\n}\n\nexport function serializeMaterialCookReceipt(receipt: MaterialCookReceipt): string {\n return JSON.stringify(jsonValue({ ...receipt, sourceClosure: unique(receipt.sourceClosure) }));\n}\n\nfunction invalid(field: string, actual?: unknown): Result<never, MaterialCookRecordError> {\n return err({\n code: 'material-cook-record-invalid',\n expected: 'a complete material-cook/4 record with layered identity and provenance',\n hint: 're-cook the material and publish its record, artifact, references, and receipt together',\n detail: {\n field,\n ...(actual === undefined ? {} : { actual }),\n action: 'inspect the named field and recook the material generation',\n },\n });\n}\n\nfunction normalizeArtifactBytes(value: unknown): Uint8Array | undefined {\n if (Array.isArray(value)) {\n return value.every((byte) => Number.isInteger(byte) && byte >= 0 && byte <= 255)\n ? Uint8Array.from(value)\n : undefined;\n }\n if (!ArrayBuffer.isView(value)) return undefined;\n const view = value as ArrayBufferView;\n return new Uint8Array(view.buffer, view.byteOffset, view.byteLength).slice();\n}\n\nconst IDENTITY_FIELDS = [\n 'materialContractDigest',\n 'sourceRevision',\n 'sourceClosureDigest',\n 'layoutIdentity',\n 'programIdentity',\n 'pipelineIdentity',\n 'materialPublicationIdentity',\n 'cookIdentity',\n 'compilerFingerprint',\n 'artifactDigest',\n] as const;\n\nfunction isGeneration(value: unknown): value is number {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 1;\n}\n\nfunction validateIdentity(value: unknown): Result<MaterialCookIdentity, MaterialCookRecordError> {\n if (value === null || typeof value !== 'object') return invalid('receipt.identity', value);\n const candidate = value as Record<string, unknown>;\n for (const field of IDENTITY_FIELDS) {\n if (typeof candidate[field] !== 'string' || candidate[field].length === 0) {\n return invalid(`receipt.identity.${field}`, candidate[field]);\n }\n }\n if (candidate.wasm === null || typeof candidate.wasm !== 'object') {\n return invalid('receipt.identity.wasm', candidate.wasm);\n }\n const wasm = candidate.wasm as Record<string, unknown>;\n for (const field of ['sourceContentKey', 'artifactSha256', 'glueSha256']) {\n if (typeof wasm[field] !== 'string' || wasm[field].length === 0) {\n return invalid(`receipt.identity.wasm.${field}`, wasm[field]);\n }\n }\n for (const field of ['valueGeneration', 'dependencyGeneration', 'cookGeneration']) {\n if (!isGeneration(candidate[field]))\n return invalid(`receipt.identity.${field}`, candidate[field]);\n }\n return ok({\n ...candidate,\n wasm: wasm as unknown as MaterialCookWasmProvenance,\n } as MaterialCookIdentity);\n}\n\nexport function validateMaterialCookReceipt(\n value: unknown,\n expected: MaterialCookIdentityExpectation = {},\n): Result<MaterialCookReceipt, MaterialCookRecordError> {\n if (value === null || typeof value !== 'object') return invalid('receipt');\n const candidate = value as Record<string, unknown>;\n if (candidate.schemaVersion !== 'material-cook/4')\n return invalid('receipt.schemaVersion', candidate.schemaVersion);\n const identityResult = validateIdentity(candidate.identity);\n if (!identityResult.ok) return identityResult;\n const identity = identityResult.value;\n if (candidate.derivedInterface === null || typeof candidate.derivedInterface !== 'object') {\n return invalid('receipt.derivedInterface', candidate.derivedInterface);\n }\n const derivedInterface = candidate.derivedInterface as Record<string, unknown>;\n if (derivedInterface.layoutIdentity !== identity.layoutIdentity) {\n return invalid('receipt.derivedInterface.layoutIdentity', derivedInterface.layoutIdentity);\n }\n if (\n derivedInterface.layerPlanIdentity !== undefined &&\n (typeof derivedInterface.layerPlanIdentity !== 'string' ||\n derivedInterface.layerPlanIdentity.length === 0)\n ) {\n return invalid(\n 'receipt.derivedInterface.layerPlanIdentity',\n derivedInterface.layerPlanIdentity,\n );\n }\n for (const field of ['sourceClosure', 'profile', 'compilerVersion']) {\n const fieldValue = candidate[field];\n if (\n (field === 'sourceClosure' && !Array.isArray(fieldValue)) ||\n (field !== 'sourceClosure' && typeof fieldValue !== 'string')\n ) {\n return invalid(`receipt.${field}`, fieldValue);\n }\n }\n const sourceClosure = candidate.sourceClosure;\n if (Array.isArray(sourceClosure) && sourceClosure.some((path) => typeof path !== 'string')) {\n return invalid('receipt.sourceClosure', sourceClosure);\n }\n if (\n expected.layoutIdentity !== undefined &&\n identity.layoutIdentity !== expected.layoutIdentity\n ) {\n return invalid('receipt.identity.layoutIdentity', identity.layoutIdentity);\n }\n if (\n expected.artifactDigest !== undefined &&\n identity.artifactDigest !== expected.artifactDigest\n ) {\n return invalid('receipt.identity.artifactDigest', identity.artifactDigest);\n }\n if (expected.inputDigest !== undefined && identity.cookIdentity !== expected.inputDigest) {\n return invalid('receipt.identity.cookIdentity', identity.cookIdentity);\n }\n return ok({\n schemaVersion: 'material-cook/4',\n sourceClosure: candidate.sourceClosure as string[],\n profile: candidate.profile as string,\n compilerVersion: candidate.compilerVersion as string,\n identity,\n derivedInterface: {\n layoutIdentity: derivedInterface.layoutIdentity as string,\n ...(derivedInterface.layerPlanIdentity === undefined\n ? {}\n : { layerPlanIdentity: derivedInterface.layerPlanIdentity as string }),\n },\n });\n}\n\nexport function validateCookedMaterialRecord(\n value: unknown,\n): Result<CookedMaterialRecord, MaterialCookRecordError> {\n if (value === null || typeof value !== 'object') return invalid('record');\n const candidate = value as Record<string, unknown>;\n if (candidate.schemaVersion !== 'material-cook/4')\n return invalid('schemaVersion', candidate.schemaVersion);\n if (typeof candidate.guid !== 'string' || !candidate.guid) return invalid('guid');\n if (candidate.materialGuid !== undefined && typeof candidate.materialGuid !== 'string')\n return invalid('materialGuid');\n if (\n candidate.publicationGeneration !== undefined &&\n !isGeneration(candidate.publicationGeneration)\n )\n return invalid('publicationGeneration', candidate.publicationGeneration);\n if (candidate.specializationKey !== undefined && typeof candidate.specializationKey !== 'string')\n return invalid('specializationKey');\n if ('artifact' in candidate || 'variants' in candidate || 'variantContext' in candidate)\n return invalid('programs', 'legacy single-artifact publication');\n if (candidate.artifactDigest !== undefined && typeof candidate.artifactDigest !== 'string')\n return invalid('artifactDigest');\n if (\n candidate.sourceClosure !== undefined &&\n (!Array.isArray(candidate.sourceClosure) ||\n candidate.sourceClosure.some((path) => typeof path !== 'string'))\n )\n return invalid('sourceClosure');\n if (candidate.parameterContract !== undefined) {\n if (candidate.parameterContract === null || typeof candidate.parameterContract !== 'object')\n return invalid('parameterContract');\n const parameterContract = candidate.parameterContract as Record<string, unknown>;\n if (!Array.isArray(parameterContract.parameters))\n return invalid('parameterContract.parameters');\n if (\n parameterContract.values === null ||\n typeof parameterContract.values !== 'object' ||\n Array.isArray(parameterContract.values)\n )\n return invalid('parameterContract.values');\n }\n if (candidate.resolved === null || typeof candidate.resolved !== 'object')\n return invalid('resolved');\n if (candidate.refs === null || typeof candidate.refs !== 'object') return invalid('refs');\n if (candidate.receipt === null || typeof candidate.receipt !== 'object')\n return invalid('receipt');\n const resolved = candidate.resolved as Record<string, unknown>;\n if (!Array.isArray(resolved.passes)) return invalid('resolved.passes', resolved.passes);\n if (!Array.isArray(resolved.parameters))\n return invalid('resolved.parameters', resolved.parameters);\n if (\n resolved.values === null ||\n typeof resolved.values !== 'object' ||\n Array.isArray(resolved.values)\n )\n return invalid('resolved.values', resolved.values);\n const passes = resolved.passes as MaterialPass[];\n const passNames = new Set<string>();\n for (const [index, pass] of passes.entries()) {\n if (\n pass === null ||\n typeof pass !== 'object' ||\n typeof pass.name !== 'string' ||\n !pass.name ||\n passNames.has(pass.name) ||\n pass.program === null ||\n typeof pass.program !== 'object' ||\n typeof pass.program.module !== 'string'\n )\n return invalid(`resolved.passes[${index}]`);\n passNames.add(pass.name);\n }\n if (!Array.isArray(candidate.programs) || candidate.programs.length === 0)\n return invalid('programs');\n const programs: MaterialCookProgram[] = [];\n const programKeys = new Set<string>();\n const selections = new Set<string>();\n const selectedPasses = new Set<string>();\n for (const [index, entry] of candidate.programs.entries()) {\n const field = `programs[${index}]`;\n if (entry === null || typeof entry !== 'object') return invalid(field);\n const program = entry as Record<string, unknown>;\n if (\n typeof program.specializationKey !== 'string' ||\n !program.specializationKey ||\n programKeys.has(program.specializationKey)\n )\n return invalid(`${field}.specializationKey`);\n programKeys.add(program.specializationKey);\n if (program.artifact === null || typeof program.artifact !== 'object')\n return invalid(`${field}.artifact`);\n const artifact = program.artifact as Record<string, unknown>;\n const bytes = normalizeArtifactBytes(artifact.bytes);\n if (\n artifact.mediaType !== 'text/wgsl' ||\n typeof artifact.path !== 'string' ||\n !artifact.path ||\n typeof artifact.digest !== 'string' ||\n !artifact.digest ||\n bytes === undefined\n )\n return invalid(`${field}.artifact`);\n if (!Array.isArray(program.selections) || program.selections.length === 0)\n return invalid(`${field}.selections`);\n const programSelections: MaterialCookProgram['selections'][number][] = [];\n for (const [selectionIndex, selection] of program.selections.entries()) {\n const selectionField = `${field}.selections[${selectionIndex}]`;\n if (selection === null || typeof selection !== 'object' || !passNames.has(selection.pass))\n return invalid(selectionField);\n const context = validateMaterialCookProgramContext(selection.context);\n if (!context.ok)\n return invalid(\n `${selectionField}.${context.error.detail.field}`,\n context.error.detail.actual,\n );\n const key = JSON.stringify([selection.pass, materialProgramContextKey(context.value)]);\n if (selections.has(key)) return invalid(selectionField, 'ambiguous Pass/context selection');\n selections.add(key);\n selectedPasses.add(selection.pass);\n programSelections.push({ pass: selection.pass, context: context.value });\n }\n programs.push({\n specializationKey: program.specializationKey,\n artifact: { mediaType: 'text/wgsl', path: artifact.path, digest: artifact.digest, bytes },\n selections: programSelections,\n });\n }\n if ([...passNames].some((pass) => !selectedPasses.has(pass)))\n return invalid('programs.selections', 'unpublished Pass');\n const manifestDigest = createMaterialProgramSetDigest(programs, passes);\n const receiptResult = validateMaterialCookReceipt(candidate.receipt, {\n artifactDigest: manifestDigest,\n });\n if (!receiptResult.ok) return receiptResult;\n let expectedLayerPlanIdentity: string | undefined;\n try {\n expectedLayerPlanIdentity = materialLayerPlanIdentity({\n resolved: resolved as unknown as CookedMaterialRecord['resolved'],\n });\n } catch (error) {\n return invalid('resolved.layerPlanIdentity', error instanceof Error ? error.message : error);\n }\n if (\n expectedLayerPlanIdentity !== undefined &&\n receiptResult.value.derivedInterface.layerPlanIdentity !== expectedLayerPlanIdentity\n ) {\n return invalid(\n 'receipt.derivedInterface.layerPlanIdentity',\n receiptResult.value.derivedInterface.layerPlanIdentity,\n );\n }\n if (candidate.artifactDigest !== undefined && candidate.artifactDigest !== manifestDigest)\n return invalid('artifactDigest', candidate.artifactDigest);\n if (\n candidate.publicationGeneration !== undefined &&\n receiptResult.value.identity.cookGeneration !== candidate.publicationGeneration\n )\n return invalid('receipt.identity.cookGeneration', receiptResult.value.identity.cookGeneration);\n return ok({\n ...candidate,\n programs,\n receipt: receiptResult.value,\n } as unknown as CookedMaterialRecord);\n}\n\nexport function projectCookedMaterialRecord(\n record: CookedMaterialRecord,\n): Omit<CookedMaterialRecord, 'guid' | 'authored'> {\n return {\n resolved: record.resolved,\n refs: record.refs,\n programs: record.programs,\n receipt: record.receipt,\n schemaVersion: record.schemaVersion,\n };\n}\n\n/** Canonical context key shared by publication validation and runtime selection. */\nexport function materialProgramContextKey(context: MaterialCookProgramContext): string {\n return JSON.stringify(jsonValue(context));\n}\n\nexport function validateMaterialCookProgramContext(\n value: unknown,\n): Result<MaterialCookProgramContext, MaterialCookRecordError> {\n if (value === null || typeof value !== 'object' || Array.isArray(value))\n return invalid('context', value);\n const context = value as Record<string, unknown>;\n const fields = {\n backend: ['webgpu', 'webgl2', 'wgpu-native'],\n capability: ['storage-buffer', 'uniform-fallback'],\n pipeline: ['forward', 'deferred'],\n geometry: ['mesh', 'skinned', 'sprite'],\n pass: ['forward', 'shadow', 'depth'],\n profile: ['forgeax-material-wgsl-v1'],\n toolchain: ['naga-oil'],\n instrumentation: ['none', 'validation'],\n };\n for (const field of Object.keys(context)) {\n if (!(field in fields)) return invalid(`context.${field}`, context[field]);\n }\n for (const [field, allowed] of Object.entries(fields)) {\n if (!allowed.includes(context[field] as string))\n return invalid(`context.${field}`, context[field]);\n }\n return ok({ ...context } as unknown as MaterialCookProgramContext);\n}\n\n/** Covers every selection and artifact while excluding transport copies of the bytes. */\nexport function createMaterialProgramSetDigest(\n programs: readonly MaterialCookProgram[],\n passes: readonly MaterialPass[],\n): string {\n const manifest = {\n passes,\n programs: programs\n .map((program) => ({\n specializationKey: program.specializationKey,\n artifact: {\n path: program.artifact.path,\n mediaType: program.artifact.mediaType,\n digest: program.artifact.digest,\n },\n selections: [...program.selections].sort((a, b) =>\n JSON.stringify(jsonValue(a)).localeCompare(JSON.stringify(jsonValue(b))),\n ),\n }))\n .sort((a, b) => a.specializationKey.localeCompare(b.specializationKey)),\n };\n return createMaterialArtifactDigest(\n new TextEncoder().encode(JSON.stringify(jsonValue(manifest))),\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/evidence/material-cook.ts"],"names":["entry"],"mappings":"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","file":"material-cook.mjs","sourcesContent":["import type {\n MaterialAsset,\n MaterialParameter,\n MaterialPass,\n MaterialProgramAbi,\n MaterialProgramAddress,\n MaterialTextureReference,\n MaterialTextureValue,\n MaterialValue,\n Result,\n} from '@forgeax/engine-types';\nimport {\n deriveStandardLayerPlan,\n err,\n isMaterialProgramAbi,\n MATERIAL_TEXTURE_SLOTS,\n ok,\n} from '@forgeax/engine-types';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { bytesToHex } from '@noble/hashes/utils.js';\n\nexport interface MaterialCookRefs {\n readonly parent: readonly string[];\n readonly textures: readonly string[];\n readonly samplers: readonly string[];\n readonly modules: readonly string[];\n}\n\nexport interface MaterialCookArtifact {\n readonly mediaType: string;\n readonly path: string;\n readonly digest: string;\n readonly bytes: Uint8Array;\n}\n\n/** Domain-owned inputs used to compile and select a material program. */\nexport interface MaterialCookProgramContext {\n readonly backend: 'webgpu' | 'webgl2' | 'wgpu-native';\n readonly capability: 'storage-buffer' | 'uniform-fallback';\n readonly pipeline: 'forward' | 'deferred';\n readonly geometry: 'mesh' | 'skinned' | 'sprite';\n readonly pass: 'forward' | 'shadow' | 'depth';\n readonly profile: 'forgeax-material-wgsl-v1';\n readonly toolchain: 'naga-oil';\n readonly instrumentation: 'none' | 'validation';\n}\n\n/** Programs are derived artifacts, never independently authored assets. */\nexport interface MaterialCookProgram {\n readonly specializationKey: string;\n readonly artifact: MaterialCookArtifact;\n readonly selections: readonly {\n readonly pass: string;\n readonly context: MaterialCookProgramContext;\n /** Renderer submission address selected by this publication. */\n readonly address?: MaterialProgramAddress;\n /** Actual entry point paired with the selected address. */\n readonly entry?: string;\n /** Producer-reflected ABI facts for the selected artifact/entry. */\n readonly abi?: MaterialProgramAbi;\n }[];\n}\n\nexport interface MaterialCookWasmProvenance {\n readonly sourceContentKey: string;\n readonly artifactSha256: string;\n readonly glueSha256: string;\n}\n\nexport interface MaterialCookIdentity {\n readonly materialContractDigest: string;\n readonly sourceRevision: string;\n readonly sourceClosureDigest: string;\n readonly layoutIdentity: string;\n readonly programIdentity: string;\n readonly pipelineIdentity: string;\n readonly materialPublicationIdentity: string;\n readonly cookIdentity: string;\n readonly compilerFingerprint: string;\n readonly wasm: MaterialCookWasmProvenance;\n readonly artifactDigest: string;\n readonly valueGeneration: number;\n readonly dependencyGeneration: number;\n readonly cookGeneration: number;\n}\n\nexport type MaterialCookIdentityInput = Omit<MaterialCookIdentity, 'cookIdentity'>;\n\nexport interface MaterialCookReceipt {\n readonly schemaVersion: 'material-cook/4';\n readonly sourceClosure: readonly string[];\n readonly profile: string;\n readonly compilerVersion: string;\n readonly identity: MaterialCookIdentity;\n readonly derivedInterface: {\n readonly layoutIdentity: string;\n /** Build-time Standard physical lowering identity, when the root is Standard. */\n readonly layerPlanIdentity?: string;\n };\n}\n\nexport interface MaterialParameterContract {\n readonly parameters: readonly MaterialParameter[];\n readonly values: Readonly<Record<string, MaterialValue | null>>;\n}\n\nexport interface CookedMaterialRecord {\n readonly schemaVersion: 'material-cook/4';\n readonly guid: string;\n readonly authored?: MaterialAsset;\n readonly materialGuid?: string;\n readonly publicationGeneration?: number;\n readonly specializationKey?: string;\n readonly programs: readonly MaterialCookProgram[];\n /** Digest of the complete program/Pass/context manifest. */\n readonly artifactDigest?: string;\n readonly sourceClosure?: readonly string[];\n readonly parameterContract?: MaterialParameterContract;\n readonly resolved: {\n readonly passes: readonly MaterialPass[];\n readonly parameters: readonly MaterialParameter[];\n readonly values: Readonly<Record<string, MaterialValue | null>>;\n };\n readonly refs: MaterialCookRefs;\n readonly receipt: MaterialCookReceipt;\n}\n\nexport interface MaterialCookRecordError {\n readonly code: 'material-cook-record-invalid';\n readonly expected: string;\n readonly hint: string;\n readonly detail: {\n readonly field: string;\n readonly actual?: unknown;\n readonly action: string;\n };\n}\n\nexport interface MaterialCookIdentityExpectation {\n readonly layoutIdentity?: string;\n readonly artifactDigest?: string;\n readonly inputDigest?: string;\n}\n\nconst STANDARD_ROOT_MODULES = new Set([\n 'forgeax::default-standard-pbr',\n 'forgeax::pbr-skin',\n 'forgeax_material::standard',\n 'forgeax_material::pbr-skin',\n]);\n\n/** Shared ownership predicate for the built-in Standard material root. */\nexport function isStandardRootModule(module: string): boolean {\n return STANDARD_ROOT_MODULES.has(module);\n}\n\nexport function isStandardMaterialRecord(record: Pick<CookedMaterialRecord, 'resolved'>): boolean {\n return record.resolved.passes.some((pass) => isStandardRootModule(pass.program.module));\n}\n\n/**\n * Recompute the Standard layer identity from the admitted resolved root.\n * Material admission and runtime loading share this owner so a stale receipt\n * cannot select a different physical layer plan after cooking.\n */\nexport function materialLayerPlanIdentity(\n record: Pick<CookedMaterialRecord, 'resolved'>,\n): string | undefined {\n if (!isStandardMaterialRecord(record)) {\n return undefined;\n }\n return deriveStandardLayerPlan(record.resolved.parameters, record.resolved.passes).identity;\n}\n\nfunction unique(values: readonly string[]): readonly string[] {\n return [...new Set(values)].sort();\n}\n\nfunction guidText(value: string | Uint8Array): string {\n return typeof value === 'string'\n ? value\n : Array.from(value, (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\nfunction cookGuidText(value: MaterialTextureReference): string | undefined {\n return typeof value === 'number' ? undefined : guidText(value);\n}\n\nfunction textureValues(\n values: Readonly<Record<string, MaterialValue | null>> | undefined,\n textureFields: ReadonlySet<string>,\n): readonly MaterialTextureValue[] {\n return Object.entries(values ?? {}).flatMap(([name, value]) => {\n if (value === null) return [];\n if (typeof value === 'string') {\n return textureFields.has(name) ? [{ texture: value }] : [];\n }\n return value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n 'texture' in value\n ? [value as MaterialTextureValue]\n : [];\n });\n}\n\nexport function collectMaterialCookRefs(material: Partial<MaterialAsset>): MaterialCookRefs {\n const textureFields =\n material.parameters === undefined\n ? new Set<string>(MATERIAL_TEXTURE_SLOTS)\n : new Set(\n material.parameters\n .filter(\n (parameter) => parameter.type === 'texture' || parameter.type === 'texture_cube',\n )\n .map((parameter) => parameter.name),\n );\n const textures = textureValues(material.values, textureFields);\n return {\n parent: material.parent ? [guidText(material.parent)] : [],\n textures: unique(\n textures.flatMap((value) => {\n const guid = cookGuidText(value.texture);\n return guid === undefined ? [] : [guid];\n }),\n ),\n samplers: unique(\n textures.flatMap((value) => {\n if (value.sampler === undefined) return [];\n const guid = cookGuidText(value.sampler);\n return guid === undefined ? [] : [guid];\n }),\n ),\n modules: unique((material.passes ?? []).map((pass) => pass.program.module)),\n };\n}\n\nexport function createMaterialArtifactDigest(bytes: Uint8Array): string {\n return `sha256:${bytesToHex(sha256(bytes))}`;\n}\n\nfunction jsonValue(value: unknown): unknown {\n if (value instanceof Uint8Array) return [...value];\n if (Array.isArray(value)) return value.map(jsonValue);\n if (value !== null && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value)\n .filter(([, entry]) => entry !== undefined)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, entry]) => [key, jsonValue(entry)]),\n );\n }\n return value;\n}\n\nexport function createMaterialCookIdentity(input: MaterialCookIdentityInput): MaterialCookIdentity {\n const cookIdentity = createMaterialArtifactDigest(\n new TextEncoder().encode(\n JSON.stringify(\n jsonValue({\n materialContractDigest: input.materialContractDigest,\n sourceRevision: input.sourceRevision,\n sourceClosureDigest: input.sourceClosureDigest,\n layoutIdentity: input.layoutIdentity,\n programIdentity: input.programIdentity,\n pipelineIdentity: input.pipelineIdentity,\n compilerFingerprint: input.compilerFingerprint,\n wasm: input.wasm,\n artifactDigest: input.artifactDigest,\n }),\n ),\n ),\n );\n return { ...input, cookIdentity };\n}\n\nexport function serializeCookedMaterialRecord(record: CookedMaterialRecord): string {\n return JSON.stringify(jsonValue(record));\n}\n\nexport function serializeMaterialCookReceipt(receipt: MaterialCookReceipt): string {\n return JSON.stringify(jsonValue({ ...receipt, sourceClosure: unique(receipt.sourceClosure) }));\n}\n\nfunction invalid(field: string, actual?: unknown): Result<never, MaterialCookRecordError> {\n return err({\n code: 'material-cook-record-invalid',\n expected: 'a complete material-cook/4 record with layered identity and provenance',\n hint: 're-cook the material and publish its record, artifact, references, and receipt together',\n detail: {\n field,\n ...(actual === undefined ? {} : { actual }),\n action: 'inspect the named field and recook the material generation',\n },\n });\n}\n\nfunction normalizeArtifactBytes(value: unknown): Uint8Array | undefined {\n if (Array.isArray(value)) {\n return value.every((byte) => Number.isInteger(byte) && byte >= 0 && byte <= 255)\n ? Uint8Array.from(value)\n : undefined;\n }\n if (!ArrayBuffer.isView(value)) return undefined;\n const view = value as ArrayBufferView;\n return new Uint8Array(view.buffer, view.byteOffset, view.byteLength).slice();\n}\n\nconst IDENTITY_FIELDS = [\n 'materialContractDigest',\n 'sourceRevision',\n 'sourceClosureDigest',\n 'layoutIdentity',\n 'programIdentity',\n 'pipelineIdentity',\n 'materialPublicationIdentity',\n 'cookIdentity',\n 'compilerFingerprint',\n 'artifactDigest',\n] as const;\n\nfunction isGeneration(value: unknown): value is number {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 1;\n}\n\nfunction validateIdentity(value: unknown): Result<MaterialCookIdentity, MaterialCookRecordError> {\n if (value === null || typeof value !== 'object') return invalid('receipt.identity', value);\n const candidate = value as Record<string, unknown>;\n for (const field of IDENTITY_FIELDS) {\n if (typeof candidate[field] !== 'string' || candidate[field].length === 0) {\n return invalid(`receipt.identity.${field}`, candidate[field]);\n }\n }\n if (candidate.wasm === null || typeof candidate.wasm !== 'object') {\n return invalid('receipt.identity.wasm', candidate.wasm);\n }\n const wasm = candidate.wasm as Record<string, unknown>;\n for (const field of ['sourceContentKey', 'artifactSha256', 'glueSha256']) {\n if (typeof wasm[field] !== 'string' || wasm[field].length === 0) {\n return invalid(`receipt.identity.wasm.${field}`, wasm[field]);\n }\n }\n for (const field of ['valueGeneration', 'dependencyGeneration', 'cookGeneration']) {\n if (!isGeneration(candidate[field]))\n return invalid(`receipt.identity.${field}`, candidate[field]);\n }\n return ok({\n ...candidate,\n wasm: wasm as unknown as MaterialCookWasmProvenance,\n } as MaterialCookIdentity);\n}\n\nexport function validateMaterialCookReceipt(\n value: unknown,\n expected: MaterialCookIdentityExpectation = {},\n): Result<MaterialCookReceipt, MaterialCookRecordError> {\n if (value === null || typeof value !== 'object') return invalid('receipt');\n const candidate = value as Record<string, unknown>;\n if (candidate.schemaVersion !== 'material-cook/4')\n return invalid('receipt.schemaVersion', candidate.schemaVersion);\n const identityResult = validateIdentity(candidate.identity);\n if (!identityResult.ok) return identityResult;\n const identity = identityResult.value;\n if (candidate.derivedInterface === null || typeof candidate.derivedInterface !== 'object') {\n return invalid('receipt.derivedInterface', candidate.derivedInterface);\n }\n const derivedInterface = candidate.derivedInterface as Record<string, unknown>;\n if (derivedInterface.layoutIdentity !== identity.layoutIdentity) {\n return invalid('receipt.derivedInterface.layoutIdentity', derivedInterface.layoutIdentity);\n }\n if (\n derivedInterface.layerPlanIdentity !== undefined &&\n (typeof derivedInterface.layerPlanIdentity !== 'string' ||\n derivedInterface.layerPlanIdentity.length === 0)\n ) {\n return invalid(\n 'receipt.derivedInterface.layerPlanIdentity',\n derivedInterface.layerPlanIdentity,\n );\n }\n for (const field of ['sourceClosure', 'profile', 'compilerVersion']) {\n const fieldValue = candidate[field];\n if (\n (field === 'sourceClosure' && !Array.isArray(fieldValue)) ||\n (field !== 'sourceClosure' && typeof fieldValue !== 'string')\n ) {\n return invalid(`receipt.${field}`, fieldValue);\n }\n }\n const sourceClosure = candidate.sourceClosure;\n if (Array.isArray(sourceClosure) && sourceClosure.some((path) => typeof path !== 'string')) {\n return invalid('receipt.sourceClosure', sourceClosure);\n }\n if (\n expected.layoutIdentity !== undefined &&\n identity.layoutIdentity !== expected.layoutIdentity\n ) {\n return invalid('receipt.identity.layoutIdentity', identity.layoutIdentity);\n }\n if (\n expected.artifactDigest !== undefined &&\n identity.artifactDigest !== expected.artifactDigest\n ) {\n return invalid('receipt.identity.artifactDigest', identity.artifactDigest);\n }\n if (expected.inputDigest !== undefined && identity.cookIdentity !== expected.inputDigest) {\n return invalid('receipt.identity.cookIdentity', identity.cookIdentity);\n }\n return ok({\n schemaVersion: 'material-cook/4',\n sourceClosure: candidate.sourceClosure as string[],\n profile: candidate.profile as string,\n compilerVersion: candidate.compilerVersion as string,\n identity,\n derivedInterface: {\n layoutIdentity: derivedInterface.layoutIdentity as string,\n ...(derivedInterface.layerPlanIdentity === undefined\n ? {}\n : { layerPlanIdentity: derivedInterface.layerPlanIdentity as string }),\n },\n });\n}\n\nexport function validateCookedMaterialRecord(\n value: unknown,\n): Result<CookedMaterialRecord, MaterialCookRecordError> {\n if (value === null || typeof value !== 'object') return invalid('record');\n const candidate = value as Record<string, unknown>;\n if (candidate.schemaVersion !== 'material-cook/4')\n return invalid('schemaVersion', candidate.schemaVersion);\n if (typeof candidate.guid !== 'string' || !candidate.guid) return invalid('guid');\n if (candidate.materialGuid !== undefined && typeof candidate.materialGuid !== 'string')\n return invalid('materialGuid');\n if (\n candidate.publicationGeneration !== undefined &&\n !isGeneration(candidate.publicationGeneration)\n )\n return invalid('publicationGeneration', candidate.publicationGeneration);\n if (candidate.specializationKey !== undefined && typeof candidate.specializationKey !== 'string')\n return invalid('specializationKey');\n if ('artifact' in candidate || 'variants' in candidate || 'variantContext' in candidate)\n return invalid('programs', 'legacy single-artifact publication');\n if (candidate.artifactDigest !== undefined && typeof candidate.artifactDigest !== 'string')\n return invalid('artifactDigest');\n if (\n candidate.sourceClosure !== undefined &&\n (!Array.isArray(candidate.sourceClosure) ||\n candidate.sourceClosure.some((path) => typeof path !== 'string'))\n )\n return invalid('sourceClosure');\n if (candidate.parameterContract !== undefined) {\n if (candidate.parameterContract === null || typeof candidate.parameterContract !== 'object')\n return invalid('parameterContract');\n const parameterContract = candidate.parameterContract as Record<string, unknown>;\n if (!Array.isArray(parameterContract.parameters))\n return invalid('parameterContract.parameters');\n if (\n parameterContract.values === null ||\n typeof parameterContract.values !== 'object' ||\n Array.isArray(parameterContract.values)\n )\n return invalid('parameterContract.values');\n }\n if (candidate.resolved === null || typeof candidate.resolved !== 'object')\n return invalid('resolved');\n if (candidate.refs === null || typeof candidate.refs !== 'object') return invalid('refs');\n if (candidate.receipt === null || typeof candidate.receipt !== 'object')\n return invalid('receipt');\n const resolved = candidate.resolved as Record<string, unknown>;\n if (!Array.isArray(resolved.passes)) return invalid('resolved.passes', resolved.passes);\n if (!Array.isArray(resolved.parameters))\n return invalid('resolved.parameters', resolved.parameters);\n if (\n resolved.values === null ||\n typeof resolved.values !== 'object' ||\n Array.isArray(resolved.values)\n )\n return invalid('resolved.values', resolved.values);\n const passes = resolved.passes as MaterialPass[];\n const passNames = new Set<string>();\n for (const [index, pass] of passes.entries()) {\n if (\n pass === null ||\n typeof pass !== 'object' ||\n typeof pass.name !== 'string' ||\n !pass.name ||\n passNames.has(pass.name) ||\n pass.program === null ||\n typeof pass.program !== 'object' ||\n typeof pass.program.module !== 'string'\n )\n return invalid(`resolved.passes[${index}]`);\n passNames.add(pass.name);\n }\n if (!Array.isArray(candidate.programs) || candidate.programs.length === 0)\n return invalid('programs');\n const programs: MaterialCookProgram[] = [];\n const programKeys = new Set<string>();\n const selections = new Set<string>();\n const submissionSelections = new Map<string, Set<MaterialProgramAddress>>();\n let modernPublication = false;\n let legacySelectionField: string | undefined;\n const selectedPasses = new Set<string>();\n for (const [index, entry] of candidate.programs.entries()) {\n const field = `programs[${index}]`;\n if (entry === null || typeof entry !== 'object') return invalid(field);\n const program = entry as Record<string, unknown>;\n if (\n typeof program.specializationKey !== 'string' ||\n !program.specializationKey ||\n programKeys.has(program.specializationKey)\n )\n return invalid(`${field}.specializationKey`);\n programKeys.add(program.specializationKey);\n if (program.artifact === null || typeof program.artifact !== 'object')\n return invalid(`${field}.artifact`);\n const artifact = program.artifact as Record<string, unknown>;\n const bytes = normalizeArtifactBytes(artifact.bytes);\n if (\n artifact.mediaType !== 'text/wgsl' ||\n typeof artifact.path !== 'string' ||\n !artifact.path ||\n typeof artifact.digest !== 'string' ||\n !artifact.digest ||\n bytes === undefined\n )\n return invalid(`${field}.artifact`);\n if (!Array.isArray(program.selections) || program.selections.length === 0)\n return invalid(`${field}.selections`);\n const programSelections: MaterialCookProgram['selections'][number][] = [];\n for (const [selectionIndex, rawSelection] of program.selections.entries()) {\n const selectionField = `${field}.selections[${selectionIndex}]`;\n if (rawSelection === null || typeof rawSelection !== 'object') return invalid(selectionField);\n const selection = rawSelection as Record<string, unknown>;\n if (typeof selection.pass !== 'string' || !passNames.has(selection.pass))\n return invalid(selectionField);\n const context = validateMaterialCookProgramContext(selection.context);\n if (!context.ok)\n return invalid(\n `${selectionField}.${context.error.detail.field}`,\n context.error.detail.actual,\n );\n const address = selection.address === undefined ? 'direct' : selection.address;\n if (address !== 'direct' && address !== 'scene-index')\n return invalid(`${selectionField}.address`, selection.address);\n const hasAddressFacts =\n selection.address !== undefined ||\n selection.entry !== undefined ||\n selection.abi !== undefined;\n modernPublication ||= hasAddressFacts;\n if (!hasAddressFacts) legacySelectionField ??= selectionField;\n const rawEntry = selection.entry;\n const entry = typeof rawEntry === 'string' ? rawEntry : undefined;\n if (hasAddressFacts && selection.address === undefined)\n return invalid(\n `${selectionField}.address`,\n 'modern ABI selections require an explicit address',\n );\n if (hasAddressFacts && (entry === undefined || entry.length === 0))\n return invalid(`${selectionField}.entry`, rawEntry);\n if (hasAddressFacts && !isMaterialProgramAbi(selection.abi))\n return invalid(`${selectionField}.abi`, selection.abi);\n if (hasAddressFacts) {\n const abi = selection.abi as MaterialProgramAbi;\n const expectedEntry = address === 'direct' ? abi.directEntry : abi.sceneIndexEntry;\n if (entry !== expectedEntry)\n return invalid(`${selectionField}.entry`, 'entry does not match published ABI');\n const submissionKey = JSON.stringify([\n selection.pass,\n materialProgramContextKey(context.value),\n ]);\n const addresses =\n submissionSelections.get(submissionKey) ?? new Set<MaterialProgramAddress>();\n addresses.add(address);\n submissionSelections.set(submissionKey, addresses);\n }\n const key = JSON.stringify([\n selection.pass,\n materialProgramContextKey(context.value),\n address,\n ]);\n if (selections.has(key)) return invalid(selectionField, 'ambiguous Pass/context selection');\n selections.add(key);\n selectedPasses.add(selection.pass);\n programSelections.push({\n pass: selection.pass,\n context: context.value,\n ...(selection.address === undefined ? {} : { address }),\n ...(entry === undefined ? {} : { entry }),\n ...(selection.abi === undefined ? {} : { abi: selection.abi as MaterialProgramAbi }),\n });\n }\n programs.push({\n specializationKey: program.specializationKey,\n artifact: { mediaType: 'text/wgsl', path: artifact.path, digest: artifact.digest, bytes },\n selections: programSelections,\n });\n }\n if (modernPublication && legacySelectionField !== undefined) {\n return invalid(\n legacySelectionField,\n 'modern material publications require address, entry, and ABI facts on every selection',\n );\n }\n for (const [selectionKey, addresses] of submissionSelections) {\n if (addresses.size !== 2) {\n return invalid('programs.selections', `incomplete submission address pair: ${selectionKey}`);\n }\n }\n if ([...passNames].some((pass) => !selectedPasses.has(pass)))\n return invalid('programs.selections', 'unpublished Pass');\n const manifestDigest = createMaterialProgramSetDigest(programs, passes);\n const receiptResult = validateMaterialCookReceipt(candidate.receipt, {\n artifactDigest: manifestDigest,\n });\n if (!receiptResult.ok) return receiptResult;\n let expectedLayerPlanIdentity: string | undefined;\n try {\n expectedLayerPlanIdentity = materialLayerPlanIdentity({\n resolved: resolved as unknown as CookedMaterialRecord['resolved'],\n });\n } catch (error) {\n return invalid('resolved.layerPlanIdentity', error instanceof Error ? error.message : error);\n }\n if (\n expectedLayerPlanIdentity !== undefined &&\n receiptResult.value.derivedInterface.layerPlanIdentity !== expectedLayerPlanIdentity\n ) {\n return invalid(\n 'receipt.derivedInterface.layerPlanIdentity',\n receiptResult.value.derivedInterface.layerPlanIdentity,\n );\n }\n if (candidate.artifactDigest !== undefined && candidate.artifactDigest !== manifestDigest)\n return invalid('artifactDigest', candidate.artifactDigest);\n if (\n candidate.publicationGeneration !== undefined &&\n receiptResult.value.identity.cookGeneration !== candidate.publicationGeneration\n )\n return invalid('receipt.identity.cookGeneration', receiptResult.value.identity.cookGeneration);\n return ok({\n ...candidate,\n programs,\n receipt: receiptResult.value,\n } as unknown as CookedMaterialRecord);\n}\n\nexport function projectCookedMaterialRecord(\n record: CookedMaterialRecord,\n): Omit<CookedMaterialRecord, 'guid' | 'authored'> {\n return {\n resolved: record.resolved,\n refs: record.refs,\n programs: record.programs,\n receipt: record.receipt,\n schemaVersion: record.schemaVersion,\n };\n}\n\n/** Canonical context key shared by publication validation and runtime selection. */\nexport function materialProgramContextKey(context: MaterialCookProgramContext): string {\n return JSON.stringify(jsonValue(context));\n}\n\nexport function validateMaterialCookProgramContext(\n value: unknown,\n): Result<MaterialCookProgramContext, MaterialCookRecordError> {\n if (value === null || typeof value !== 'object' || Array.isArray(value))\n return invalid('context', value);\n const context = value as Record<string, unknown>;\n const fields = {\n backend: ['webgpu', 'webgl2', 'wgpu-native'],\n capability: ['storage-buffer', 'uniform-fallback'],\n pipeline: ['forward', 'deferred'],\n geometry: ['mesh', 'skinned', 'sprite'],\n pass: ['forward', 'shadow', 'depth'],\n profile: ['forgeax-material-wgsl-v1'],\n toolchain: ['naga-oil'],\n instrumentation: ['none', 'validation'],\n };\n for (const field of Object.keys(context)) {\n if (!(field in fields)) return invalid(`context.${field}`, context[field]);\n }\n for (const [field, allowed] of Object.entries(fields)) {\n if (!allowed.includes(context[field] as string))\n return invalid(`context.${field}`, context[field]);\n }\n return ok({ ...context } as unknown as MaterialCookProgramContext);\n}\n\n/** Covers every selection and artifact while excluding transport copies of the bytes. */\nexport function createMaterialProgramSetDigest(\n programs: readonly MaterialCookProgram[],\n passes: readonly MaterialPass[],\n): string {\n const manifest = {\n passes,\n programs: programs\n .map((program) => ({\n specializationKey: program.specializationKey,\n artifact: {\n path: program.artifact.path,\n mediaType: program.artifact.mediaType,\n digest: program.artifact.digest,\n },\n selections: [...program.selections].sort((a, b) =>\n JSON.stringify(jsonValue(a)).localeCompare(JSON.stringify(jsonValue(b))),\n ),\n }))\n .sort((a, b) => a.specializationKey.localeCompare(b.specializationKey)),\n };\n return createMaterialArtifactDigest(\n new TextEncoder().encode(JSON.stringify(jsonValue(manifest))),\n );\n}\n"]}
@@ -10,6 +10,7 @@ export interface NativeCookDraft<P = unknown> {
10
10
  readonly refs: readonly string[];
11
11
  readonly artifacts: Readonly<Record<string, NativeCookArtifact>>;
12
12
  readonly inputFingerprint: string;
13
+ readonly sourceDependencies?: readonly string[];
13
14
  }
14
15
  export interface NativeCooker<P = unknown, I = unknown> {
15
16
  readonly key: string;
@@ -1 +1 @@
1
- {"version":3,"file":"native-cooker-registry.d.ts","sourceRoot":"","sources":["../src/native-cooker-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"native-cooker-registry.d.ts","sourceRoot":"","sources":["../src/native-cooker-registry.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/native-cooker-registry.ts"],"names":[],"mappings":"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","file":"native-cooker.mjs","sourcesContent":["import { createHash } from 'node:crypto';\nimport type {\n ArtifactDescriptor,\n AssetCodec,\n AssetStageError,\n CookProduct,\n Result,\n} from '@forgeax/engine-types';\nimport { err, ok } from '@forgeax/engine-types';\n\nexport interface NativeCookArtifact {\n readonly mediaType: string;\n readonly assetCodec?: AssetCodec;\n readonly bytes: Uint8Array;\n}\n\nexport interface NativeCookDraft<P = unknown> {\n readonly guid: string;\n readonly payload: P;\n readonly refs: readonly string[];\n readonly artifacts: Readonly<Record<string, NativeCookArtifact>>;\n readonly inputFingerprint: string;\n}\n\nexport interface NativeCooker<P = unknown, I = unknown> {\n readonly key: string;\n readonly discover?: (input: unknown) => I | Promise<I>;\n cook(input: I): NativeCookDraft<P> | Promise<NativeCookDraft<P>>;\n}\n\nexport interface NativeCookTransactionSnapshot<P = unknown> {\n readonly draft: NativeCookDraft<P>;\n readonly generation: number;\n}\n\nexport interface NativeCookTransactionOptions<P = unknown, I = unknown> {\n readonly key: string;\n readonly input: I;\n readonly previous?: NativeCookTransactionSnapshot<P>;\n readonly validate?: (draft: NativeCookDraft<P>) => string | undefined;\n readonly publish?: (draft: NativeCookDraft<P>, generation: number) => void | Promise<void>;\n}\n\nexport interface NativeCookTransactionResult<P = unknown> extends NativeCookTransactionSnapshot<P> {\n readonly status: 'committed' | 'recovered';\n readonly lastKnownGood: NativeCookDraft<P>;\n readonly candidateGeneration: number;\n readonly lastKnownGoodGeneration: number;\n readonly recoveryHint?: string;\n}\n\nfunction canonicalize(value: unknown): unknown {\n if (value instanceof Uint8Array) return Buffer.from(value).toString('base64');\n if (Array.isArray(value)) return value.map(canonicalize);\n if (typeof value !== 'object' || value === null) return value;\n return Object.fromEntries(\n Object.entries(value)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, nested]) => [key, canonicalize(nested)]),\n );\n}\n\nfunction digestDraft<P>(draft: NativeCookDraft<P>): string {\n const bytes = JSON.stringify(\n canonicalize({\n guid: draft.guid,\n payload: draft.payload,\n refs: draft.refs,\n artifacts: draft.artifacts,\n }),\n );\n return `sha256:${createHash('sha256').update(bytes).digest('hex')}`;\n}\n\ntype NativeCookErrorDetail = Extract<\n AssetStageError['detail'],\n { readonly guid: string; readonly producer: string }\n>;\n\nfunction failure(key: string, detail: NativeCookErrorDetail): Result<never, AssetStageError> {\n return err({\n stage: 'native-cook',\n code: 'native-cook-failed',\n expected: 'a registered native cooker to produce a complete draft',\n hint: 'register the cooker or repair its draft, then rerun recovery',\n detail,\n recovery: { action: `rerun native cooker ${key}`, retryable: true },\n });\n}\n\nfunction transactionFailure(key: string, reason: string): Result<never, AssetStageError> {\n return failure(key, { guid: 'unknown', producer: reason });\n}\n\nfunction recovered<P>(\n key: string,\n previous: NativeCookTransactionSnapshot<P>,\n): NativeCookTransactionResult<P> {\n return {\n ...previous,\n status: 'recovered',\n lastKnownGood: previous.draft,\n candidateGeneration: previous.generation + 1,\n lastKnownGoodGeneration: previous.generation,\n recoveryHint: `repair ${key} and submit a new candidate generation`,\n };\n}\n\n/** Injectable build-time table for native authored Pack producers. */\nexport class NativeCookerRegistry {\n private readonly cookers = new Map<string, NativeCooker>();\n\n register(cooker: NativeCooker): void {\n if (typeof cooker.key !== 'string' || cooker.key.length === 0) {\n throw new TypeError('NativeCookerRegistry.register: key must be a non-empty string');\n }\n if (typeof cooker.cook !== 'function') {\n throw new TypeError(`NativeCookerRegistry.register: cooker ${cooker.key} must expose cook`);\n }\n this.cookers.set(cooker.key, cooker);\n }\n\n get(key: string): NativeCooker | undefined {\n return this.cookers.get(key);\n }\n\n registeredCookers(): readonly string[] {\n return [...this.cookers.keys()];\n }\n\n async runDraft<P = unknown, I = unknown>(\n key: string,\n input: I,\n ): Promise<Result<NativeCookDraft<P>, AssetStageError>> {\n const cooker = this.cookers.get(key) as NativeCooker<P, I> | undefined;\n if (cooker === undefined) {\n return failure(key, { guid: 'unknown', producer: key });\n }\n let draft: NativeCookDraft<P>;\n try {\n const typedInput = cooker.discover === undefined ? input : await cooker.discover(input);\n draft = await cooker.cook(typedInput);\n } catch (error) {\n return failure(key, { guid: 'unknown', producer: String(error) });\n }\n if (\n draft.guid.length === 0 ||\n draft.inputFingerprint.length === 0 ||\n !Array.isArray(draft.refs) ||\n typeof draft.payload !== 'object' ||\n draft.payload === null ||\n typeof draft.artifacts !== 'object' ||\n draft.artifacts === null ||\n Object.entries(draft.artifacts).some(\n ([, artifact]) =>\n artifact === null ||\n typeof artifact !== 'object' ||\n typeof artifact.mediaType !== 'string' ||\n artifact.mediaType.length === 0 ||\n !(artifact.bytes instanceof Uint8Array),\n )\n ) {\n return failure(key, { guid: draft.guid || 'unknown', producer: key });\n }\n return ok(draft);\n }\n\n async run<P = unknown, I = unknown>(\n key: string,\n input: I,\n ): Promise<Result<CookProduct<P>, AssetStageError>> {\n const draftResult = await this.runDraft<P, I>(key, input);\n if (!draftResult.ok) return draftResult;\n const draft = draftResult.value;\n const digest = digestDraft(draft);\n const artifacts: Record<string, ArtifactDescriptor> = {};\n for (const [path, artifact] of Object.entries(draft.artifacts)) {\n artifacts[path] = {\n path,\n mediaType: artifact.mediaType,\n ...(artifact.assetCodec === undefined ? {} : { assetCodec: artifact.assetCodec }),\n byteLength: artifact.bytes.byteLength,\n };\n }\n const receipt = {\n guid: draft.guid,\n origin: 'authoredPack' as const,\n status: 'succeeded' as const,\n inputFingerprint: draft.inputFingerprint,\n outputDigest: digest,\n };\n const product: CookProduct<P> = {\n guid: draft.guid,\n payload: draft.payload,\n refs: draft.refs,\n artifacts,\n digest,\n receipt,\n };\n return ok(product);\n }\n\n async runTransaction<P = unknown, I = unknown>(\n options: NativeCookTransactionOptions<P, I>,\n ): Promise<Result<NativeCookTransactionResult<P>, AssetStageError>> {\n const candidate = await this.runDraft<P, I>(options.key, options.input);\n if (!candidate.ok) {\n return options.previous === undefined\n ? candidate\n : ok(recovered(options.key, options.previous));\n }\n const invalidReason = options.validate?.(candidate.value);\n if (invalidReason !== undefined) {\n return options.previous === undefined\n ? transactionFailure(options.key, invalidReason)\n : ok(recovered(options.key, options.previous));\n }\n const generation = (options.previous?.generation ?? 0) + 1;\n try {\n await options.publish?.(candidate.value, generation);\n } catch {\n return options.previous === undefined\n ? transactionFailure(options.key, 'atomic producer publication failed')\n : ok(recovered(options.key, options.previous));\n }\n return ok({\n draft: candidate.value,\n generation,\n status: 'committed',\n lastKnownGood: candidate.value,\n candidateGeneration: generation,\n lastKnownGoodGeneration: generation,\n });\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/native-cooker-registry.ts"],"names":[],"mappings":"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","file":"native-cooker.mjs","sourcesContent":["import { createHash } from 'node:crypto';\nimport type {\n ArtifactDescriptor,\n AssetCodec,\n AssetStageError,\n CookProduct,\n Result,\n} from '@forgeax/engine-types';\nimport { err, ok } from '@forgeax/engine-types';\n\nexport interface NativeCookArtifact {\n readonly mediaType: string;\n readonly assetCodec?: AssetCodec;\n readonly bytes: Uint8Array;\n}\n\nexport interface NativeCookDraft<P = unknown> {\n readonly guid: string;\n readonly payload: P;\n readonly refs: readonly string[];\n readonly artifacts: Readonly<Record<string, NativeCookArtifact>>;\n readonly inputFingerprint: string;\n readonly sourceDependencies?: readonly string[];\n}\n\nexport interface NativeCooker<P = unknown, I = unknown> {\n readonly key: string;\n readonly discover?: (input: unknown) => I | Promise<I>;\n cook(input: I): NativeCookDraft<P> | Promise<NativeCookDraft<P>>;\n}\n\nexport interface NativeCookTransactionSnapshot<P = unknown> {\n readonly draft: NativeCookDraft<P>;\n readonly generation: number;\n}\n\nexport interface NativeCookTransactionOptions<P = unknown, I = unknown> {\n readonly key: string;\n readonly input: I;\n readonly previous?: NativeCookTransactionSnapshot<P>;\n readonly validate?: (draft: NativeCookDraft<P>) => string | undefined;\n readonly publish?: (draft: NativeCookDraft<P>, generation: number) => void | Promise<void>;\n}\n\nexport interface NativeCookTransactionResult<P = unknown> extends NativeCookTransactionSnapshot<P> {\n readonly status: 'committed' | 'recovered';\n readonly lastKnownGood: NativeCookDraft<P>;\n readonly candidateGeneration: number;\n readonly lastKnownGoodGeneration: number;\n readonly recoveryHint?: string;\n}\n\nfunction canonicalize(value: unknown): unknown {\n if (value instanceof Uint8Array) return Buffer.from(value).toString('base64');\n if (Array.isArray(value)) return value.map(canonicalize);\n if (typeof value !== 'object' || value === null) return value;\n return Object.fromEntries(\n Object.entries(value)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, nested]) => [key, canonicalize(nested)]),\n );\n}\n\nfunction digestDraft<P>(draft: NativeCookDraft<P>): string {\n const bytes = JSON.stringify(\n canonicalize({\n guid: draft.guid,\n payload: draft.payload,\n refs: draft.refs,\n artifacts: draft.artifacts,\n }),\n );\n return `sha256:${createHash('sha256').update(bytes).digest('hex')}`;\n}\n\ntype NativeCookErrorDetail = Extract<\n AssetStageError['detail'],\n { readonly guid: string; readonly producer: string }\n>;\n\nfunction failure(key: string, detail: NativeCookErrorDetail): Result<never, AssetStageError> {\n return err({\n stage: 'native-cook',\n code: 'native-cook-failed',\n expected: 'a registered native cooker to produce a complete draft',\n hint: 'register the cooker or repair its draft, then rerun recovery',\n detail,\n recovery: { action: `rerun native cooker ${key}`, retryable: true },\n });\n}\n\nfunction transactionFailure(key: string, reason: string): Result<never, AssetStageError> {\n return failure(key, { guid: 'unknown', producer: reason });\n}\n\nfunction recovered<P>(\n key: string,\n previous: NativeCookTransactionSnapshot<P>,\n): NativeCookTransactionResult<P> {\n return {\n ...previous,\n status: 'recovered',\n lastKnownGood: previous.draft,\n candidateGeneration: previous.generation + 1,\n lastKnownGoodGeneration: previous.generation,\n recoveryHint: `repair ${key} and submit a new candidate generation`,\n };\n}\n\n/** Injectable build-time table for native authored Pack producers. */\nexport class NativeCookerRegistry {\n private readonly cookers = new Map<string, NativeCooker>();\n\n register(cooker: NativeCooker): void {\n if (typeof cooker.key !== 'string' || cooker.key.length === 0) {\n throw new TypeError('NativeCookerRegistry.register: key must be a non-empty string');\n }\n if (typeof cooker.cook !== 'function') {\n throw new TypeError(`NativeCookerRegistry.register: cooker ${cooker.key} must expose cook`);\n }\n this.cookers.set(cooker.key, cooker);\n }\n\n get(key: string): NativeCooker | undefined {\n return this.cookers.get(key);\n }\n\n registeredCookers(): readonly string[] {\n return [...this.cookers.keys()];\n }\n\n async runDraft<P = unknown, I = unknown>(\n key: string,\n input: I,\n ): Promise<Result<NativeCookDraft<P>, AssetStageError>> {\n const cooker = this.cookers.get(key) as NativeCooker<P, I> | undefined;\n if (cooker === undefined) {\n return failure(key, { guid: 'unknown', producer: key });\n }\n let draft: NativeCookDraft<P>;\n try {\n const typedInput = cooker.discover === undefined ? input : await cooker.discover(input);\n draft = await cooker.cook(typedInput);\n } catch (error) {\n return failure(key, { guid: 'unknown', producer: String(error) });\n }\n if (\n draft.guid.length === 0 ||\n draft.inputFingerprint.length === 0 ||\n !Array.isArray(draft.refs) ||\n typeof draft.payload !== 'object' ||\n draft.payload === null ||\n typeof draft.artifacts !== 'object' ||\n draft.artifacts === null ||\n Object.entries(draft.artifacts).some(\n ([, artifact]) =>\n artifact === null ||\n typeof artifact !== 'object' ||\n typeof artifact.mediaType !== 'string' ||\n artifact.mediaType.length === 0 ||\n !(artifact.bytes instanceof Uint8Array),\n )\n ) {\n return failure(key, { guid: draft.guid || 'unknown', producer: key });\n }\n return ok(draft);\n }\n\n async run<P = unknown, I = unknown>(\n key: string,\n input: I,\n ): Promise<Result<CookProduct<P>, AssetStageError>> {\n const draftResult = await this.runDraft<P, I>(key, input);\n if (!draftResult.ok) return draftResult;\n const draft = draftResult.value;\n const digest = digestDraft(draft);\n const artifacts: Record<string, ArtifactDescriptor> = {};\n for (const [path, artifact] of Object.entries(draft.artifacts)) {\n artifacts[path] = {\n path,\n mediaType: artifact.mediaType,\n ...(artifact.assetCodec === undefined ? {} : { assetCodec: artifact.assetCodec }),\n byteLength: artifact.bytes.byteLength,\n };\n }\n const receipt = {\n guid: draft.guid,\n origin: 'authoredPack' as const,\n status: 'succeeded' as const,\n inputFingerprint: draft.inputFingerprint,\n outputDigest: digest,\n };\n const product: CookProduct<P> = {\n guid: draft.guid,\n payload: draft.payload,\n refs: draft.refs,\n artifacts,\n digest,\n receipt,\n };\n return ok(product);\n }\n\n async runTransaction<P = unknown, I = unknown>(\n options: NativeCookTransactionOptions<P, I>,\n ): Promise<Result<NativeCookTransactionResult<P>, AssetStageError>> {\n const candidate = await this.runDraft<P, I>(options.key, options.input);\n if (!candidate.ok) {\n return options.previous === undefined\n ? candidate\n : ok(recovered(options.key, options.previous));\n }\n const invalidReason = options.validate?.(candidate.value);\n if (invalidReason !== undefined) {\n return options.previous === undefined\n ? transactionFailure(options.key, invalidReason)\n : ok(recovered(options.key, options.previous));\n }\n const generation = (options.previous?.generation ?? 0) + 1;\n try {\n await options.publish?.(candidate.value, generation);\n } catch {\n return options.previous === undefined\n ? transactionFailure(options.key, 'atomic producer publication failed')\n : ok(recovered(options.key, options.previous));\n }\n return ok({\n draft: candidate.value,\n generation,\n status: 'committed',\n lastKnownGood: candidate.value,\n candidateGeneration: generation,\n lastKnownGoodGeneration: generation,\n });\n }\n}\n"]}
@@ -8748,9 +8748,17 @@ var WorkerScriptablePackExecutor = class {
8748
8748
  }
8749
8749
  };
8750
8750
  worker.on("message", onMessage);
8751
- worker.once("error", rejectLoad);
8751
+ const fail = (error) => {
8752
+ rejectLoad(error);
8753
+ const active = this.build;
8754
+ this.build = void 0;
8755
+ active?.reject(error);
8756
+ void this.dispose("failure");
8757
+ };
8758
+ worker.once("error", fail);
8752
8759
  worker.once("exit", (code) => {
8753
- if (code !== 0) rejectLoad(new Error(`ScriptablePack worker exited with code ${code}`));
8760
+ if (this.disposal !== void 0) return;
8761
+ fail(new Error(`ScriptablePack worker exited with code ${code}`));
8754
8762
  });
8755
8763
  });
8756
8764
  }
@@ -8828,7 +8836,7 @@ function scriptablePackLoadFailure(sourcePath, reason, phase, diagnostic, timeou
8828
8836
  }
8829
8837
  async function loadScriptablePack(sourcePath, options = {}) {
8830
8838
  const timeoutMs = options.timeoutMs ?? 15e3;
8831
- const buildTimeoutMs = options.buildTimeoutMs ?? 5e3;
8839
+ const buildTimeoutMs = options.buildTimeoutMs ?? 15e3;
8832
8840
  const executor = options.executor ?? new WorkerScriptablePackExecutor();
8833
8841
  let disposeReason;
8834
8842
  let timeout;
@@ -8978,16 +8986,17 @@ function makePackError(code, detail) {
8978
8986
  detail
8979
8987
  });
8980
8988
  }
8981
- function* extractMountSourceGuids(asset) {
8989
+ function* extractInstanceSourceGuids(asset) {
8982
8990
  if (asset.kind !== "scene") return;
8983
8991
  const payload = asset.payload;
8984
- if (!payload || !Array.isArray(payload.mounts)) return;
8985
- for (const rawMount of payload.mounts) {
8986
- const mount = rawMount;
8987
- const idx = mount.source;
8988
- if (typeof idx !== "number" || !Number.isInteger(idx)) continue;
8989
- if (idx < 0 || idx >= asset.refs.length) continue;
8990
- const resolved = asset.refs[idx];
8992
+ if (!payload || payload.entities === null || typeof payload.entities !== "object" || Array.isArray(payload.entities))
8993
+ return;
8994
+ for (const rawEntity of Object.values(payload.entities)) {
8995
+ if (rawEntity === null || typeof rawEntity !== "object" || Array.isArray(rawEntity)) continue;
8996
+ const instance = rawEntity.instance;
8997
+ if (instance === null || typeof instance !== "object" || Array.isArray(instance)) continue;
8998
+ const source = instance.source;
8999
+ const resolved = typeof source === "number" && Number.isInteger(source) ? asset.refs[source] : typeof source === "string" ? source : void 0;
8991
9000
  if (typeof resolved !== "string") continue;
8992
9001
  yield resolved.toLowerCase();
8993
9002
  }
@@ -9105,7 +9114,7 @@ async function scanValidated(roots, opts = {}, capture) {
9105
9114
  guidToPath.set(normalizedGuid, packPath);
9106
9115
  packRefs.set(normalizedGuid, [
9107
9116
  ...asset.refs.map((ref) => ref.toLowerCase()),
9108
- ...extractMountSourceGuids(asset)
9117
+ ...extractInstanceSourceGuids(asset)
9109
9118
  ]);
9110
9119
  }
9111
9120
  }
@@ -9209,7 +9218,7 @@ async function scanValidated(roots, opts = {}, capture) {
9209
9218
  guidToPath.set(normalizedGuid, packPath);
9210
9219
  packRefs.set(normalizedGuid, [
9211
9220
  ...asset.refs.map((ref) => ref.toLowerCase()),
9212
- ...extractMountSourceGuids(asset)
9221
+ ...extractInstanceSourceGuids(asset)
9213
9222
  ]);
9214
9223
  }
9215
9224
  capture?.declarations.set(packPath, {