@forgeax/engine-pack 0.1.21 → 0.1.23

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 (124) hide show
  1. package/README.md +159 -46
  2. package/dist/__tests__/inventory-schema.test.d.ts +2 -0
  3. package/dist/__tests__/inventory-schema.test.d.ts.map +1 -0
  4. package/dist/__tests__/parameterized-pack-authoring-gateway.unit.test.d.ts +2 -0
  5. package/dist/__tests__/parameterized-pack-authoring-gateway.unit.test.d.ts.map +1 -0
  6. package/dist/__tests__/parameterized-pack-scanner.unit.test.d.ts +2 -0
  7. package/dist/__tests__/parameterized-pack-scanner.unit.test.d.ts.map +1 -0
  8. package/dist/__tests__/parameterized-pack.unit.test.d.ts +2 -0
  9. package/dist/__tests__/parameterized-pack.unit.test.d.ts.map +1 -0
  10. package/dist/__tests__/scanner-blacklist.test.d.ts +2 -0
  11. package/dist/__tests__/scanner-blacklist.test.d.ts.map +1 -0
  12. package/dist/build.d.ts +9 -4
  13. package/dist/build.d.ts.map +1 -1
  14. package/dist/build.mjs +3314 -803
  15. package/dist/build.mjs.map +1 -1
  16. package/dist/builtin.mjs +37 -4
  17. package/dist/builtin.mjs.map +1 -1
  18. package/dist/catalog-builder.d.ts.map +1 -1
  19. package/dist/cli-asset.d.ts.map +1 -1
  20. package/dist/cli-asset.mjs +1368 -850
  21. package/dist/cli-asset.mjs.map +1 -1
  22. package/dist/deriveAssetName.d.ts +11 -7
  23. package/dist/deriveAssetName.d.ts.map +1 -1
  24. package/dist/evidence/source-inventory.d.ts.map +1 -1
  25. package/dist/guid.d.ts +15 -0
  26. package/dist/guid.d.ts.map +1 -1
  27. package/dist/guid.mjs +53 -5
  28. package/dist/guid.mjs.map +1 -1
  29. package/dist/index.d.ts +3 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.mjs +1252 -560
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/inventory/binding.d.ts +6 -0
  34. package/dist/inventory/binding.d.ts.map +1 -0
  35. package/dist/inventory/declaration.d.ts +24 -0
  36. package/dist/inventory/declaration.d.ts.map +1 -0
  37. package/dist/inventory/index.d.ts +3 -0
  38. package/dist/inventory/index.d.ts.map +1 -0
  39. package/dist/inventory/sync.d.ts +5 -0
  40. package/dist/inventory/sync.d.ts.map +1 -0
  41. package/dist/name.mjs +4 -7
  42. package/dist/name.mjs.map +1 -1
  43. package/dist/package-finalizer.d.ts +2 -20
  44. package/dist/package-finalizer.d.ts.map +1 -1
  45. package/dist/parameterized-pack-node.d.ts +26 -0
  46. package/dist/parameterized-pack-node.d.ts.map +1 -0
  47. package/dist/parameterized-pack-node.mjs +11093 -0
  48. package/dist/parameterized-pack-node.mjs.map +1 -0
  49. package/dist/parameterized-pack.d.ts +233 -0
  50. package/dist/parameterized-pack.d.ts.map +1 -0
  51. package/dist/resolve-asset-source.d.ts +1 -3
  52. package/dist/resolve-asset-source.d.ts.map +1 -1
  53. package/dist/resolve-asset-source.mjs +6 -81
  54. package/dist/resolve-asset-source.mjs.map +1 -1
  55. package/dist/runtime.mjs +77 -7
  56. package/dist/runtime.mjs.map +1 -1
  57. package/dist/scanner.d.ts +19 -8
  58. package/dist/scanner.d.ts.map +1 -1
  59. package/dist/scanner.mjs +1169 -690
  60. package/dist/scanner.mjs.map +1 -1
  61. package/dist/schema-compiled.d.ts.map +1 -1
  62. package/dist/schema.mjs +79 -7
  63. package/dist/schema.mjs.map +1 -1
  64. package/dist/scriptable-pack-node.d.ts +8 -32
  65. package/dist/scriptable-pack-node.d.ts.map +1 -1
  66. package/dist/scriptable-pack-node.mjs +576 -1021
  67. package/dist/scriptable-pack-node.mjs.map +1 -1
  68. package/dist/scriptable-pack-worker.mjs +29 -11
  69. package/dist/scriptable-pack-worker.mjs.map +1 -1
  70. package/dist/scriptable-pack.d.ts +19 -532
  71. package/dist/scriptable-pack.d.ts.map +1 -1
  72. package/dist/scriptable-pack.mjs +1042 -527
  73. package/dist/scriptable-pack.mjs.map +1 -1
  74. package/package.json +7 -7
  75. package/schema/meta.schema.json +1 -1
  76. package/schema/pack.schema.json +76 -6
  77. package/src/__tests__/guid-collision.unit.test.ts +18 -9
  78. package/src/__tests__/inventory-schema.test.ts +109 -0
  79. package/src/__tests__/pack.unit.test.ts +1 -238
  80. package/src/__tests__/package-finalizer.contract.test.ts +55 -0
  81. package/src/__tests__/parameterized-pack-authoring-gateway.unit.test.ts +249 -0
  82. package/src/__tests__/parameterized-pack-scanner.unit.test.ts +123 -0
  83. package/src/__tests__/parameterized-pack.unit.test.ts +266 -0
  84. package/src/__tests__/resolve-asset-source.test.ts +15 -98
  85. package/src/__tests__/scanner-blacklist.test.ts +55 -0
  86. package/src/__tests__/scanner-inventory.contract.test.ts +14 -15
  87. package/src/__tests__/scanner-inventory.test.ts +24 -12
  88. package/src/__tests__/scriptable-pack-cli.integration.test.ts +4 -9
  89. package/src/__tests__/topology.unit.test.ts +23 -0
  90. package/src/build.ts +28 -18
  91. package/src/catalog-builder.ts +61 -34
  92. package/src/cli-asset.ts +70 -85
  93. package/src/deriveAssetName.ts +14 -13
  94. package/src/evidence/source-inventory.ts +34 -21
  95. package/src/guid.ts +65 -4
  96. package/src/index.ts +12 -11
  97. package/src/inventory/binding.ts +25 -0
  98. package/src/inventory/declaration.ts +168 -0
  99. package/src/inventory/index.ts +18 -0
  100. package/src/inventory/sync.ts +22 -0
  101. package/src/package-finalizer.ts +2 -42
  102. package/src/parameterized-pack-node.ts +1968 -0
  103. package/src/parameterized-pack.ts +1493 -0
  104. package/src/resolve-asset-source.ts +4 -76
  105. package/src/scanner.ts +241 -59
  106. package/src/schema-compiled.ts +2 -0
  107. package/src/scriptable-pack-node.ts +111 -722
  108. package/src/scriptable-pack-worker.ts +48 -16
  109. package/src/scriptable-pack.ts +27 -939
  110. package/dist/.tsbuildinfo +0 -1
  111. package/dist/__tests__/load-asset-config.test.d.ts +0 -2
  112. package/dist/__tests__/load-asset-config.test.d.ts.map +0 -1
  113. package/dist/__tests__/scriptable-pack.test-d.d.ts +0 -2
  114. package/dist/__tests__/scriptable-pack.test-d.d.ts.map +0 -1
  115. package/dist/__tests__/scriptable-pack.unit.test.d.ts +0 -2
  116. package/dist/__tests__/scriptable-pack.unit.test.d.ts.map +0 -1
  117. package/dist/config.d.ts +0 -6
  118. package/dist/config.d.ts.map +0 -1
  119. package/dist/config.mjs +0 -29
  120. package/dist/config.mjs.map +0 -1
  121. package/src/__tests__/load-asset-config.test.ts +0 -121
  122. package/src/__tests__/scriptable-pack.test-d.ts +0 -131
  123. package/src/__tests__/scriptable-pack.unit.test.ts +0 -789
  124. package/src/config.ts +0 -36
package/dist/scanner.mjs CHANGED
@@ -1,9 +1,10 @@
1
1
  import { createHash } from 'crypto';
2
2
  import { stat, readFile, readdir, realpath, mkdtemp, rm } from 'fs/promises';
3
- import { join, basename, dirname, resolve, posix, extname } from 'path';
4
- import { PACK_ERROR_HINTS, ok, err, validateSourceOverrideMap, AssetError, ImportError } from '@forgeax/engine-types';
5
- import { readFileSync, existsSync } from 'fs';
3
+ import { join, basename, dirname, resolve, extname } from 'path';
4
+ import { ok, PACK_ERROR_HINTS, err, validateSourceOverrideMap, AssetError, ImportError } from '@forgeax/engine-types';
5
+ import { sha1 } from '@noble/hashes/legacy.js';
6
6
  import { uuidv7obj } from 'uuidv7';
7
+ import { existsSync } from 'fs';
7
8
  import { tmpdir } from 'os';
8
9
  import { fileURLToPath } from 'url';
9
10
  import { Worker } from 'worker_threads';
@@ -3625,49 +3626,49 @@ var require_fast_uri = __commonJS({
3625
3626
  schemelessOptions.skipEscape = true;
3626
3627
  return serialize(resolved, schemelessOptions);
3627
3628
  }
3628
- function resolveComponent(base, relative2, options, skipNormalization) {
3629
+ function resolveComponent(base, relative, options, skipNormalization) {
3629
3630
  const target = {};
3630
3631
  if (!skipNormalization) {
3631
3632
  base = parse(serialize(base, options), options);
3632
- relative2 = parse(serialize(relative2, options), options);
3633
+ relative = parse(serialize(relative, options), options);
3633
3634
  }
3634
3635
  options = options || {};
3635
- if (!options.tolerant && relative2.scheme) {
3636
- target.scheme = relative2.scheme;
3637
- target.userinfo = relative2.userinfo;
3638
- target.host = relative2.host;
3639
- target.port = relative2.port;
3640
- target.path = removeDotSegments(relative2.path || "");
3641
- target.query = relative2.query;
3636
+ if (!options.tolerant && relative.scheme) {
3637
+ target.scheme = relative.scheme;
3638
+ target.userinfo = relative.userinfo;
3639
+ target.host = relative.host;
3640
+ target.port = relative.port;
3641
+ target.path = removeDotSegments(relative.path || "");
3642
+ target.query = relative.query;
3642
3643
  } else {
3643
- if (relative2.userinfo !== void 0 || relative2.host !== void 0 || relative2.port !== void 0) {
3644
- target.userinfo = relative2.userinfo;
3645
- target.host = relative2.host;
3646
- target.port = relative2.port;
3647
- target.path = removeDotSegments(relative2.path || "");
3648
- target.query = relative2.query;
3644
+ if (relative.userinfo !== void 0 || relative.host !== void 0 || relative.port !== void 0) {
3645
+ target.userinfo = relative.userinfo;
3646
+ target.host = relative.host;
3647
+ target.port = relative.port;
3648
+ target.path = removeDotSegments(relative.path || "");
3649
+ target.query = relative.query;
3649
3650
  } else {
3650
- if (!relative2.path) {
3651
+ if (!relative.path) {
3651
3652
  target.path = base.path;
3652
- if (relative2.query !== void 0) {
3653
- target.query = relative2.query;
3653
+ if (relative.query !== void 0) {
3654
+ target.query = relative.query;
3654
3655
  } else {
3655
3656
  target.query = base.query;
3656
3657
  }
3657
3658
  } else {
3658
- if (relative2.path[0] === "/") {
3659
- target.path = removeDotSegments(relative2.path);
3659
+ if (relative.path[0] === "/") {
3660
+ target.path = removeDotSegments(relative.path);
3660
3661
  } else {
3661
3662
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
3662
- target.path = "/" + relative2.path;
3663
+ target.path = "/" + relative.path;
3663
3664
  } else if (!base.path) {
3664
- target.path = relative2.path;
3665
+ target.path = relative.path;
3665
3666
  } else {
3666
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
3667
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
3667
3668
  }
3668
3669
  target.path = removeDotSegments(target.path);
3669
3670
  }
3670
- target.query = relative2.query;
3671
+ target.query = relative.query;
3671
3672
  }
3672
3673
  target.userinfo = base.userinfo;
3673
3674
  target.host = base.host;
@@ -3675,7 +3676,7 @@ var require_fast_uri = __commonJS({
3675
3676
  }
3676
3677
  target.scheme = base.scheme;
3677
3678
  }
3678
- target.fragment = relative2.fragment;
3679
+ target.fragment = relative.fragment;
3679
3680
  return target;
3680
3681
  }
3681
3682
  function equal(uriA, uriB, options) {
@@ -4714,8 +4715,8 @@ var require_multipleOf = __commonJS({
4714
4715
  const { gen, data, schemaCode, it } = cxt;
4715
4716
  const prec = it.opts.multipleOfPrecision;
4716
4717
  const res = gen.let("res");
4717
- const invalid2 = prec ? (0, codegen_1._)`Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}` : (0, codegen_1._)`${res} !== parseInt(${res})`;
4718
- cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid2}))`);
4718
+ const invalid = prec ? (0, codegen_1._)`Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}` : (0, codegen_1._)`${res} !== parseInt(${res})`;
4719
+ cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid}))`);
4719
4720
  }
4720
4721
  };
4721
4722
  exports.default = def;
@@ -6820,27 +6821,6 @@ var require_dist = __commonJS({
6820
6821
  exports.default = formatsPlugin;
6821
6822
  }
6822
6823
  });
6823
- function loadAssetConfig(cwd) {
6824
- let pkg;
6825
- try {
6826
- pkg = JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"));
6827
- } catch {
6828
- return { roots: [join(cwd, "assets")], paths: {} };
6829
- }
6830
- const assets = pkg.forgeax?.assets;
6831
- const rawRoots = assets?.roots;
6832
- const roots = Array.isArray(rawRoots) && rawRoots.length > 0 ? rawRoots.map((r) => join(cwd, r)) : [join(cwd, "assets")];
6833
- const rawPaths = assets?.paths;
6834
- const paths = {};
6835
- if (rawPaths !== void 0 && rawPaths !== null && typeof rawPaths === "object") {
6836
- for (const [name, dir] of Object.entries(rawPaths)) {
6837
- if (typeof dir === "string") {
6838
- paths[name] = join(cwd, dir);
6839
- }
6840
- }
6841
- }
6842
- return { roots, paths };
6843
- }
6844
6824
 
6845
6825
  // src/errors.ts
6846
6826
  var PackError = class extends Error {
@@ -6866,6 +6846,10 @@ function bytesToDashForm(bytes) {
6866
6846
  return `${h[bytes[0]]}${h[bytes[1]]}${h[bytes[2]]}${h[bytes[3]]}-${h[bytes[4]]}${h[bytes[5]]}-${h[bytes[6]]}${h[bytes[7]]}-${h[bytes[8]]}${h[bytes[9]]}-${h[bytes[10]]}${h[bytes[11]]}${h[bytes[12]]}${h[bytes[13]]}${h[bytes[14]]}${h[bytes[15]]}`;
6867
6847
  }
6868
6848
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
6849
+ var PACK_SOURCE_KEY_RE = /^[a-z0-9][a-z0-9._-]*(\/[a-z0-9][a-z0-9._-]*)*$/;
6850
+ function isValidPackSourceKey(value) {
6851
+ return typeof value === "string" && PACK_SOURCE_KEY_RE.test(value);
6852
+ }
6869
6853
  function isValidAssetGuidString(value) {
6870
6854
  return typeof value === "string" && UUID_RE.test(value);
6871
6855
  }
@@ -6877,6 +6861,48 @@ function dashFormToBytes(dashForm) {
6877
6861
  }
6878
6862
  return bytes;
6879
6863
  }
6864
+ function randomUuidBytes() {
6865
+ const uuid = uuidv7obj();
6866
+ const bytes = new Uint8Array(16);
6867
+ bytes.set(uuid.bytes);
6868
+ return bytes;
6869
+ }
6870
+ function packageId(value) {
6871
+ return value;
6872
+ }
6873
+ var PackageId = {
6874
+ parse(dashForm) {
6875
+ const parsed = AssetGuid.parse(dashForm);
6876
+ return parsed.ok ? { ok: true, value: packageId(parsed.value) } : parsed;
6877
+ },
6878
+ format(value) {
6879
+ return bytesToDashForm(value);
6880
+ },
6881
+ random() {
6882
+ return packageId(randomUuidBytes());
6883
+ }
6884
+ };
6885
+ function derivedGuid(namespace, sourceKey) {
6886
+ if (!(namespace instanceof Uint8Array) || namespace.byteLength !== 16) {
6887
+ throw new TypeError("AssetGuid.derive requires a 16-byte PackageId");
6888
+ }
6889
+ if (!isValidPackSourceKey(sourceKey)) {
6890
+ const error = new TypeError(
6891
+ `AssetGuid.derive received invalid sourceKey ${JSON.stringify(sourceKey)}`
6892
+ );
6893
+ Object.defineProperty(error, "code", { value: "pack-source-key-invalid" });
6894
+ throw error;
6895
+ }
6896
+ const name = new TextEncoder().encode(sourceKey);
6897
+ const input = new Uint8Array(namespace.byteLength + name.byteLength);
6898
+ input.set(namespace, 0);
6899
+ input.set(name, namespace.byteLength);
6900
+ const digest = sha1(input);
6901
+ const result = digest.slice(0, 16);
6902
+ result[6] = (result[6] ?? 0) & 15 | 80;
6903
+ result[8] = (result[8] ?? 0) & 63 | 128;
6904
+ return brand(result);
6905
+ }
6880
6906
  var AssetGuid = {
6881
6907
  /**
6882
6908
  * Parse a 36-char RFC 4122 dash-form UUID string into an AssetGuid.
@@ -6920,19 +6946,760 @@ var AssetGuid = {
6920
6946
  * Works in both Node.js and browser environments.
6921
6947
  */
6922
6948
  random() {
6923
- const uuid = uuidv7obj();
6924
- const bytes = new Uint8Array(16);
6925
- bytes.set(uuid.bytes);
6926
- return brand(bytes);
6949
+ return brand(randomUuidBytes());
6950
+ },
6951
+ /** Derive the stable UUIDv5 projection for one Pack subject and sourceKey. */
6952
+ derive(namespace, sourceKey) {
6953
+ return derivedGuid(namespace, sourceKey);
6927
6954
  }
6928
6955
  };
6956
+ var PACK_PARAMETER_TYPES = [
6957
+ "bool",
6958
+ "u32",
6959
+ "i32",
6960
+ "f32",
6961
+ "f64",
6962
+ "string",
6963
+ "enum",
6964
+ "vec2",
6965
+ "vec3",
6966
+ "vec4",
6967
+ "color",
6968
+ "asset-guid"
6969
+ ];
6970
+ function authoringError(code, expected, hint, detail = {}, actual) {
6971
+ return {
6972
+ code,
6973
+ expected,
6974
+ hint,
6975
+ ...actual === void 0 ? {} : { actual },
6976
+ detail
6977
+ };
6978
+ }
6979
+ function failure(error) {
6980
+ return err(error);
6981
+ }
6929
6982
  function isRecord(value) {
6983
+ return value !== null && typeof value === "object" && !Array.isArray(value);
6984
+ }
6985
+ function validateSceneComponents(value) {
6986
+ if (value === void 0) return ok(void 0);
6987
+ if (!Array.isArray(value)) {
6988
+ return failure(
6989
+ parameterFailure(
6990
+ "$.sceneComponents",
6991
+ "an array of component schema records",
6992
+ value,
6993
+ "sceneComponents is not an array"
6994
+ )
6995
+ );
6996
+ }
6997
+ const components = [];
6998
+ const names = /* @__PURE__ */ new Set();
6999
+ for (const [componentIndex, candidate] of value.entries()) {
7000
+ if (!isRecord(candidate) || typeof candidate.name !== "string" || !isRecord(candidate.fields)) {
7001
+ return failure(
7002
+ parameterFailure(
7003
+ `$.sceneComponents[${componentIndex}]`,
7004
+ "a component record with name and fields",
7005
+ candidate,
7006
+ "scene component schema is malformed"
7007
+ )
7008
+ );
7009
+ }
7010
+ if (candidate.name.length === 0 || names.has(candidate.name)) {
7011
+ return failure(
7012
+ parameterFailure(
7013
+ `$.sceneComponents[${componentIndex}].name`,
7014
+ "a non-empty unique component name",
7015
+ candidate.name,
7016
+ "scene component names must be unique"
7017
+ )
7018
+ );
7019
+ }
7020
+ names.add(candidate.name);
7021
+ const fields = {};
7022
+ for (const [fieldName, field] of Object.entries(candidate.fields)) {
7023
+ if (typeof field === "string" && field.length === 0 || typeof field !== "string" && (!isRecord(field) || typeof field.type !== "string" || field.type.length === 0)) {
7024
+ return failure(
7025
+ parameterFailure(
7026
+ `$.sceneComponents[${componentIndex}].fields.${fieldName}`,
7027
+ "a field type string or { type: string }",
7028
+ field,
7029
+ "scene component field schema is malformed"
7030
+ )
7031
+ );
7032
+ }
7033
+ fields[fieldName] = field;
7034
+ }
7035
+ components.push({ name: candidate.name, fields });
7036
+ }
7037
+ return ok(components);
7038
+ }
7039
+ function isPackageId(value) {
7040
+ return value instanceof Uint8Array && value.byteLength === 16;
7041
+ }
7042
+ function cloneValue(value) {
7043
+ if (value instanceof Uint8Array) return value.slice();
7044
+ if (Array.isArray(value)) return value.map((item) => cloneValue(item));
7045
+ return value;
7046
+ }
7047
+ function sourceKeyFailure(sourceKey, propertyPath = "$.sourceKey") {
7048
+ return authoringError(
7049
+ "pack-source-key-invalid",
7050
+ "a sourceKey matching ^[a-z0-9][a-z0-9._-]*(/[a-z0-9][a-z0-9._-]*)*$",
7051
+ "use a stable lower-case semantic key; do not derive it from file paths or output order",
7052
+ { propertyPath, sourceKey },
7053
+ typeof sourceKey === "string" ? sourceKey : void 0
7054
+ );
7055
+ }
7056
+ function parameterFailure(propertyPath, expected, actual, reason) {
7057
+ return authoringError(
7058
+ "pack-parameter-invalid",
7059
+ expected,
7060
+ "repair the parameter declaration or the instance values, then inspect and rebuild",
7061
+ { propertyPath, reason, actual: typeof actual === "string" ? actual : JSON.stringify(actual) }
7062
+ );
7063
+ }
7064
+ function numericType(type) {
7065
+ return type === "u32" || type === "i32" || type === "f32" || type === "f64";
7066
+ }
7067
+ function vectorLength(type) {
7068
+ switch (type) {
7069
+ case "vec2":
7070
+ return 2;
7071
+ case "vec3":
7072
+ return 3;
7073
+ case "vec4":
7074
+ case "color":
7075
+ return 4;
7076
+ default:
7077
+ return void 0;
7078
+ }
7079
+ }
7080
+ function parameterValueError(parameter, value, propertyPath) {
7081
+ const { type } = parameter;
7082
+ if (type === "bool" && typeof value !== "boolean") {
7083
+ return parameterFailure(propertyPath, "a boolean", value, "bool value has the wrong type");
7084
+ }
7085
+ if (numericType(type)) {
7086
+ if (typeof value !== "number" || !Number.isFinite(value)) {
7087
+ return parameterFailure(
7088
+ propertyPath,
7089
+ "a finite number",
7090
+ value,
7091
+ "numeric value is not finite"
7092
+ );
7093
+ }
7094
+ if ((type === "u32" || type === "i32") && !Number.isInteger(value)) {
7095
+ return parameterFailure(
7096
+ propertyPath,
7097
+ "an integer",
7098
+ value,
7099
+ "integer parameter received a fraction"
7100
+ );
7101
+ }
7102
+ if (type === "u32" && (value < 0 || value > 4294967295)) {
7103
+ return parameterFailure(
7104
+ propertyPath,
7105
+ "an unsigned 32-bit integer",
7106
+ value,
7107
+ "u32 value is outside [0, 2^32 - 1]"
7108
+ );
7109
+ }
7110
+ if (type === "i32" && (value < -2147483648 || value > 2147483647)) {
7111
+ return parameterFailure(
7112
+ propertyPath,
7113
+ "a signed 32-bit integer",
7114
+ value,
7115
+ "i32 value is outside [-2^31, 2^31 - 1]"
7116
+ );
7117
+ }
7118
+ if (type === "f32" && !Number.isFinite(Math.fround(value))) {
7119
+ return parameterFailure(
7120
+ propertyPath,
7121
+ "a finite IEEE-754 32-bit float",
7122
+ value,
7123
+ "f32 value overflows binary32"
7124
+ );
7125
+ }
7126
+ if (parameter.minimum !== void 0 && value < parameter.minimum) {
7127
+ return parameterFailure(
7128
+ propertyPath,
7129
+ `a number >= ${parameter.minimum}`,
7130
+ value,
7131
+ "value is below minimum"
7132
+ );
7133
+ }
7134
+ if (parameter.maximum !== void 0 && value > parameter.maximum) {
7135
+ return parameterFailure(
7136
+ propertyPath,
7137
+ `a number <= ${parameter.maximum}`,
7138
+ value,
7139
+ "value is above maximum"
7140
+ );
7141
+ }
7142
+ return void 0;
7143
+ }
7144
+ if (type === "string" && typeof value !== "string") {
7145
+ return parameterFailure(propertyPath, "a string", value, "string parameter has the wrong type");
7146
+ }
7147
+ if (type === "enum") {
7148
+ if (typeof value !== "string") {
7149
+ return parameterFailure(
7150
+ propertyPath,
7151
+ "one of the declared enum strings",
7152
+ value,
7153
+ "enum value has the wrong type"
7154
+ );
7155
+ }
7156
+ if (parameter.values === void 0 || !parameter.values.includes(value)) {
7157
+ return parameterFailure(
7158
+ propertyPath,
7159
+ "one of the declared enum values",
7160
+ value,
7161
+ "enum value is not declared"
7162
+ );
7163
+ }
7164
+ return void 0;
7165
+ }
7166
+ const length = vectorLength(type);
7167
+ if (length !== void 0) {
7168
+ if (!Array.isArray(value) || value.length !== length || value.some((component) => typeof component !== "number" || !Number.isFinite(component))) {
7169
+ return parameterFailure(
7170
+ propertyPath,
7171
+ `a finite numeric vector with ${length} components`,
7172
+ value,
7173
+ "vector value has the wrong shape"
7174
+ );
7175
+ }
7176
+ if (type === "color" && value.some((component) => component < 0 || component > 1)) {
7177
+ return parameterFailure(
7178
+ propertyPath,
7179
+ "an RGBA color with components in [0, 1]",
7180
+ value,
7181
+ "color component is outside [0, 1]"
7182
+ );
7183
+ }
7184
+ return void 0;
7185
+ }
7186
+ if (type === "asset-guid") {
7187
+ const validString = typeof value === "string" && isValidAssetGuidString(value);
7188
+ if (!(value instanceof Uint8Array && value.byteLength === 16) && !validString) {
7189
+ return parameterFailure(
7190
+ propertyPath,
7191
+ "a 16-byte AssetGuid or UUID string",
7192
+ value,
7193
+ "asset GUID value is malformed"
7194
+ );
7195
+ }
7196
+ return void 0;
7197
+ }
7198
+ return parameterFailure(
7199
+ propertyPath,
7200
+ "a supported Pack parameter type",
7201
+ value,
7202
+ "unknown parameter type"
7203
+ );
7204
+ }
7205
+ function normalizeParameterValue(parameter, value, propertyPath) {
7206
+ const error = parameterValueError(parameter, value, propertyPath);
7207
+ if (error !== void 0) return failure(error);
7208
+ if (parameter.type === "asset-guid" && typeof value === "string") {
7209
+ const parsed = AssetGuid.parse(value);
7210
+ if (!parsed.ok) {
7211
+ return failure(
7212
+ parameterFailure(
7213
+ propertyPath,
7214
+ "a valid AssetGuid UUID string",
7215
+ value,
7216
+ "asset GUID parser rejected the value"
7217
+ )
7218
+ );
7219
+ }
7220
+ return ok(parsed.value);
7221
+ }
7222
+ return ok(cloneValue(value));
7223
+ }
7224
+ function validateParameterDefinitions(parameters, propertyPath = "$.parameters") {
7225
+ if (!Array.isArray(parameters) || parameters.length === 0) {
7226
+ return failure(
7227
+ parameterFailure(
7228
+ propertyPath,
7229
+ "a non-empty parameter descriptor array",
7230
+ parameters,
7231
+ "parameters must be explicit and non-empty"
7232
+ )
7233
+ );
7234
+ }
7235
+ const names = /* @__PURE__ */ new Set();
7236
+ const normalized = [];
7237
+ for (const [index, candidate] of parameters.entries()) {
7238
+ const path = `${propertyPath}[${index}]`;
7239
+ if (!isRecord(candidate))
7240
+ return failure(
7241
+ parameterFailure(
7242
+ path,
7243
+ "a parameter descriptor object",
7244
+ candidate,
7245
+ "descriptor is not an object"
7246
+ )
7247
+ );
7248
+ const name = candidate.name;
7249
+ if (typeof name !== "string" || !/^[A-Za-z][A-Za-z0-9_.-]*$/.test(name)) {
7250
+ return failure(
7251
+ parameterFailure(
7252
+ `${path}.name`,
7253
+ "a unique identifier-like parameter name",
7254
+ name,
7255
+ "parameter name is invalid"
7256
+ )
7257
+ );
7258
+ }
7259
+ if (names.has(name))
7260
+ return failure(
7261
+ parameterFailure(
7262
+ `${path}.name`,
7263
+ "a unique parameter name",
7264
+ name,
7265
+ "parameter name is duplicated"
7266
+ )
7267
+ );
7268
+ names.add(name);
7269
+ const unknown = Object.keys(candidate).find(
7270
+ (key) => !["name", "type", "default", "minimum", "maximum", "values", "kind"].includes(key)
7271
+ );
7272
+ if (unknown !== void 0) {
7273
+ return failure(
7274
+ parameterFailure(
7275
+ `${path}.${unknown}`,
7276
+ "only name, type, default, minimum, maximum, values, and kind fields",
7277
+ candidate[unknown],
7278
+ "parameter descriptors are a closed authoring schema"
7279
+ )
7280
+ );
7281
+ }
7282
+ const type = candidate.type;
7283
+ if (typeof type !== "string" || !PACK_PARAMETER_TYPES.includes(type)) {
7284
+ return failure(
7285
+ parameterFailure(
7286
+ `${path}.type`,
7287
+ PACK_PARAMETER_TYPES.join(" | "),
7288
+ type,
7289
+ "parameter type is not supported"
7290
+ )
7291
+ );
7292
+ }
7293
+ const typed = {
7294
+ ...candidate,
7295
+ name,
7296
+ type
7297
+ };
7298
+ if (typed.values !== void 0) {
7299
+ if (typed.type !== "enum" || !Array.isArray(typed.values) || typed.values.length === 0 || typed.values.some((item) => typeof item !== "string") || new Set(typed.values).size !== typed.values.length) {
7300
+ return failure(
7301
+ parameterFailure(
7302
+ `${path}.values`,
7303
+ "unique non-empty strings for enum",
7304
+ typed.values,
7305
+ "enum values are malformed"
7306
+ )
7307
+ );
7308
+ }
7309
+ } else if (typed.type === "enum") {
7310
+ return failure(
7311
+ parameterFailure(
7312
+ `${path}.values`,
7313
+ "a non-empty enum choices array",
7314
+ typed.values,
7315
+ "enum has no choices"
7316
+ )
7317
+ );
7318
+ }
7319
+ if (typed.kind !== void 0 && (typed.type !== "asset-guid" || typeof typed.kind !== "string")) {
7320
+ return failure(
7321
+ parameterFailure(
7322
+ `${path}.kind`,
7323
+ "a kind constraint only on asset-guid parameters",
7324
+ typed.kind,
7325
+ "kind is misplaced"
7326
+ )
7327
+ );
7328
+ }
7329
+ for (const field of ["minimum", "maximum"]) {
7330
+ const bound = typed[field];
7331
+ if (bound !== void 0 && (typeof bound !== "number" || !Number.isFinite(bound))) {
7332
+ return failure(
7333
+ parameterFailure(
7334
+ `${path}.${field}`,
7335
+ "a finite numeric bound",
7336
+ bound,
7337
+ "numeric bound is invalid"
7338
+ )
7339
+ );
7340
+ }
7341
+ }
7342
+ if (!numericType(typed.type) && (typed.minimum !== void 0 || typed.maximum !== void 0)) {
7343
+ return failure(
7344
+ parameterFailure(
7345
+ path,
7346
+ "minimum/maximum only on numeric parameters",
7347
+ typed,
7348
+ "numeric bounds are not meaningful for this parameter type"
7349
+ )
7350
+ );
7351
+ }
7352
+ if (typed.minimum !== void 0 && typed.maximum !== void 0 && typed.minimum > typed.maximum) {
7353
+ return failure(
7354
+ parameterFailure(path, "minimum <= maximum", typed, "numeric bounds are reversed")
7355
+ );
7356
+ }
7357
+ const defaultResult = normalizeParameterValue(typed, typed.default, `${path}.default`);
7358
+ if (!defaultResult.ok) return defaultResult;
7359
+ normalized.push({
7360
+ ...typed,
7361
+ default: defaultResult.value,
7362
+ ...typed.values === void 0 ? {} : { values: Object.freeze([...typed.values]) }
7363
+ });
7364
+ }
7365
+ return ok(Object.freeze(normalized));
7366
+ }
7367
+ function projectParameterizedPackMeta(definition, sourcePath) {
7368
+ return {
7369
+ schemaVersion: "2.0.0",
7370
+ kind: "parameterized-pack-source",
7371
+ packageId: PackageId.format(definition.packageId),
7372
+ source: sourcePath,
7373
+ ..."parameters" in definition ? {
7374
+ parameters: definition.parameters.map((parameter) => ({
7375
+ name: parameter.name,
7376
+ type: parameter.type,
7377
+ default: jsonParameterValue(parameter.default),
7378
+ ...parameter.minimum === void 0 ? {} : { minimum: parameter.minimum },
7379
+ ...parameter.maximum === void 0 ? {} : { maximum: parameter.maximum },
7380
+ ...parameter.values === void 0 ? {} : { values: parameter.values },
7381
+ ...parameter.kind === void 0 ? {} : { kind: parameter.kind }
7382
+ }))
7383
+ } : {}
7384
+ };
7385
+ }
7386
+ function jsonParameterValue(value) {
7387
+ return value instanceof Uint8Array ? AssetGuid.format(value) : value;
7388
+ }
7389
+ function validatePackDefinition(value, sourcePath) {
7390
+ if (!isRecord(value))
7391
+ return failure(
7392
+ parameterFailure("$", "a Pack definition object", value, "definition is not an object")
7393
+ );
7394
+ const unknown = Object.keys(value).find(
7395
+ (key) => !["schemaVersion", "packageId", "name", "parameters", "sceneComponents", "build"].includes(
7396
+ key
7397
+ )
7398
+ );
7399
+ if (unknown !== void 0) {
7400
+ return failure(
7401
+ parameterFailure(
7402
+ `$.${unknown}`,
7403
+ "only schemaVersion, packageId, name, parameters, sceneComponents, and build fields",
7404
+ value[unknown],
7405
+ "legacy static output declarations and external asset tables are not part of v2 authoring"
7406
+ )
7407
+ );
7408
+ }
7409
+ if (value.schemaVersion !== "2.0.0") {
7410
+ return failure(
7411
+ parameterFailure(
7412
+ "$.schemaVersion",
7413
+ "the literal '2.0.0'",
7414
+ value.schemaVersion,
7415
+ "authoring source schema is unsupported"
7416
+ )
7417
+ );
7418
+ }
7419
+ if (!isPackageId(value.packageId)) {
7420
+ return failure(
7421
+ authoringError(
7422
+ "pack-package-id-invalid",
7423
+ "a 16-byte PackageId",
7424
+ "use definePackageId() for the stable source identity",
7425
+ { sourcePath, propertyPath: "$.packageId" },
7426
+ typeof value.packageId === "string" ? value.packageId : void 0
7427
+ )
7428
+ );
7429
+ }
7430
+ if (value.name !== void 0 && typeof value.name !== "string") {
7431
+ return failure(
7432
+ parameterFailure("$.name", "a string when present", value.name, "display name is malformed")
7433
+ );
7434
+ }
7435
+ if (typeof value.build !== "function") {
7436
+ return failure(
7437
+ parameterFailure("$.build", "a build function", value.build, "build is not callable")
7438
+ );
7439
+ }
7440
+ const sceneComponents = validateSceneComponents(value.sceneComponents);
7441
+ if (!sceneComponents.ok) return sceneComponents;
7442
+ const hasParameters = Object.hasOwn(value, "parameters");
7443
+ if (!hasParameters) {
7444
+ return ok(
7445
+ Object.freeze({
7446
+ schemaVersion: "2.0.0",
7447
+ packageId: value.packageId,
7448
+ ...value.name === void 0 ? {} : { name: value.name },
7449
+ ...sceneComponents.value === void 0 ? {} : { sceneComponents: sceneComponents.value },
7450
+ build: value.build
7451
+ })
7452
+ );
7453
+ }
7454
+ const parameters = validateParameterDefinitions(value.parameters);
7455
+ if (!parameters.ok) return parameters;
7456
+ return ok(
7457
+ Object.freeze({
7458
+ schemaVersion: "2.0.0",
7459
+ packageId: value.packageId,
7460
+ ...value.name === void 0 ? {} : { name: value.name },
7461
+ ...sceneComponents.value === void 0 ? {} : { sceneComponents: sceneComponents.value },
7462
+ parameters: parameters.value,
7463
+ build: value.build
7464
+ })
7465
+ );
7466
+ }
7467
+ function jsonError(propertyPath, expected, actual, reason) {
7468
+ return failure(
7469
+ authoringError(
7470
+ "pack-parameter-invalid",
7471
+ expected,
7472
+ "repair the v3 pack.json authoring data, then rerun scan or rebuild",
7473
+ {
7474
+ propertyPath,
7475
+ reason,
7476
+ actual: typeof actual === "string" ? actual : JSON.stringify(actual)
7477
+ }
7478
+ )
7479
+ );
7480
+ }
7481
+ function parsePackageId(value, propertyPath) {
7482
+ if (typeof value !== "string") {
7483
+ return failure(
7484
+ authoringError(
7485
+ "pack-package-id-invalid",
7486
+ "a UUID string",
7487
+ "repair packageId in the authoring file",
7488
+ { propertyPath, value }
7489
+ )
7490
+ );
7491
+ }
7492
+ const parsed = PackageId.parse(value);
7493
+ if (!parsed.ok) {
7494
+ return failure(
7495
+ authoringError(
7496
+ "pack-package-id-invalid",
7497
+ "a 36-character RFC 4122 UUID",
7498
+ "repair packageId or use the authoring gateway to mint one",
7499
+ { propertyPath, value },
7500
+ value
7501
+ )
7502
+ );
7503
+ }
7504
+ return ok(parsed.value);
7505
+ }
7506
+ function parsePackJsonAsset(value, sourceKey) {
7507
+ if (!isRecord(value))
7508
+ return jsonError(
7509
+ `$.assets.${sourceKey}`,
7510
+ "an asset entry object",
7511
+ value,
7512
+ "asset entry is not an object"
7513
+ );
7514
+ const allowed = /* @__PURE__ */ new Set(["kind", "payload", "refs", "name", "artifacts"]);
7515
+ const unknown = Object.keys(value).find((key) => !allowed.has(key));
7516
+ if (unknown !== void 0)
7517
+ return jsonError(
7518
+ `$.assets.${sourceKey}.${unknown}`,
7519
+ "no GUID or extra authoring field",
7520
+ value[unknown],
7521
+ "direct v3 entries derive identity from their object key"
7522
+ );
7523
+ if (typeof value.kind !== "string" || value.kind.length === 0)
7524
+ return jsonError(
7525
+ `$.assets.${sourceKey}.kind`,
7526
+ "a non-empty asset kind",
7527
+ value.kind,
7528
+ "asset kind is missing"
7529
+ );
7530
+ if (!isRecord(value.payload))
7531
+ return jsonError(
7532
+ `$.assets.${sourceKey}.payload`,
7533
+ "a JSON object payload",
7534
+ value.payload,
7535
+ "payload must be a plain object"
7536
+ );
7537
+ if (!Array.isArray(value.refs) || value.refs.some((ref) => typeof ref !== "string" || !isValidAssetGuidString(ref))) {
7538
+ return jsonError(
7539
+ `$.assets.${sourceKey}.refs`,
7540
+ "an array of UUID references",
7541
+ value.refs,
7542
+ "references must already be real AssetGuids"
7543
+ );
7544
+ }
7545
+ if (value.name !== void 0 && (typeof value.name !== "string" || value.name.length === 0))
7546
+ return jsonError(
7547
+ `$.assets.${sourceKey}.name`,
7548
+ "a non-empty display name when present",
7549
+ value.name,
7550
+ "asset name is malformed"
7551
+ );
7552
+ if (value.artifacts !== void 0 && !isRecord(value.artifacts))
7553
+ return jsonError(
7554
+ `$.assets.${sourceKey}.artifacts`,
7555
+ "an artifact descriptor object when present",
7556
+ value.artifacts,
7557
+ "artifacts are not an object"
7558
+ );
7559
+ const base = {
7560
+ kind: value.kind,
7561
+ payload: value.payload,
7562
+ refs: Object.freeze([...value.refs]),
7563
+ ...value.name === void 0 ? {} : { name: value.name }
7564
+ };
7565
+ if (value.artifacts === void 0) return ok(base);
7566
+ const withArtifacts = {
7567
+ ...base,
7568
+ artifacts: value.artifacts
7569
+ };
7570
+ return ok(withArtifacts);
7571
+ }
7572
+ function parseParameterizedPackJson(value) {
7573
+ if (!isRecord(value))
7574
+ return jsonError("$", "a v3 pack.json object", value, "document is not an object");
7575
+ if (value.schemaVersion !== "3.0.0")
7576
+ return jsonError(
7577
+ "$.schemaVersion",
7578
+ "the literal '3.0.0'",
7579
+ value.schemaVersion,
7580
+ "document schema is not v3"
7581
+ );
7582
+ const unknown = Object.keys(value).find(
7583
+ (key) => !["schemaVersion", "packageId", "assets", "parent", "values"].includes(key)
7584
+ );
7585
+ if (unknown !== void 0)
7586
+ return jsonError(
7587
+ `$.${unknown}`,
7588
+ "no extra top-level authoring fields",
7589
+ value[unknown],
7590
+ "keep the v3 document to packageId+assets or packageId+parent+values"
7591
+ );
7592
+ const packageResult = parsePackageId(value.packageId, "$.packageId");
7593
+ if (!packageResult.ok) return packageResult;
7594
+ const hasAssets = Object.hasOwn(value, "assets");
7595
+ const hasParent = Object.hasOwn(value, "parent");
7596
+ const hasValues = Object.hasOwn(value, "values");
7597
+ if (hasAssets && (hasParent || hasValues))
7598
+ return jsonError(
7599
+ "$",
7600
+ "assets or parent+values, never both",
7601
+ value,
7602
+ "direct and instance branches are mutually exclusive"
7603
+ );
7604
+ if (hasAssets) {
7605
+ if (!isRecord(value.assets))
7606
+ return jsonError(
7607
+ "$.assets",
7608
+ "a sourceKey to asset object",
7609
+ value.assets,
7610
+ "direct assets are not an object"
7611
+ );
7612
+ const assets = {};
7613
+ for (const [sourceKey, entry] of Object.entries(value.assets)) {
7614
+ if (!isValidPackSourceKey(sourceKey))
7615
+ return failure(sourceKeyFailure(sourceKey, `$.assets.${sourceKey}`));
7616
+ const parsed = parsePackJsonAsset(entry, sourceKey);
7617
+ if (!parsed.ok) return parsed;
7618
+ assets[sourceKey] = parsed.value;
7619
+ }
7620
+ return ok({
7621
+ format: "direct",
7622
+ schemaVersion: "3.0.0",
7623
+ packageId: packageResult.value,
7624
+ assets: Object.freeze(assets)
7625
+ });
7626
+ }
7627
+ if (!hasParent || !hasValues || hasAssets)
7628
+ return jsonError(
7629
+ "$",
7630
+ "parent and values for an instance document",
7631
+ value,
7632
+ "instance branch is incomplete"
7633
+ );
7634
+ const parentResult = parsePackageId(value.parent, "$.parent");
7635
+ if (!parentResult.ok) return parentResult;
7636
+ if (!isRecord(value.values))
7637
+ return jsonError(
7638
+ "$.values",
7639
+ "a sparse parameter object",
7640
+ value.values,
7641
+ "instance values are not an object"
7642
+ );
7643
+ return ok({
7644
+ format: "instance",
7645
+ schemaVersion: "3.0.0",
7646
+ packageId: packageResult.value,
7647
+ parent: parentResult.value,
7648
+ values: Object.freeze({ ...value.values })
7649
+ });
7650
+ }
7651
+ function projectDirectPackJson(value) {
7652
+ const parsed = "format" in value ? ok(value) : parseParameterizedPackJson(value);
7653
+ if (!parsed.ok) return parsed;
7654
+ if (parsed.value.format !== "direct") {
7655
+ return failure(
7656
+ authoringError(
7657
+ "pack-parameter-invalid",
7658
+ "a direct v3 pack.json",
7659
+ "projectDirectPackJson accepts the direct branch only",
7660
+ { observed: parsed.value.format }
7661
+ )
7662
+ );
7663
+ }
7664
+ const assets = [];
7665
+ for (const [sourceKey, entry] of Object.entries(parsed.value.assets).sort(
7666
+ ([left], [right]) => left.localeCompare(right)
7667
+ )) {
7668
+ assets.push({
7669
+ ...entry,
7670
+ guid: AssetGuid.format(AssetGuid.derive(parsed.value.packageId, sourceKey)),
7671
+ sourceKey
7672
+ });
7673
+ }
7674
+ return ok({ packageId: PackageId.format(parsed.value.packageId), assets: Object.freeze(assets) });
7675
+ }
7676
+ var PARAMETERIZED_PACK_OPERATION_IDS = [
7677
+ "asset.list",
7678
+ "asset.inspect",
7679
+ "asset.resolve",
7680
+ "asset.verify",
7681
+ "asset-source.create",
7682
+ "asset-source.clone",
7683
+ "asset-source.create-instance",
7684
+ "asset-source.apply-values",
7685
+ "asset-source.rebuild",
7686
+ "asset-source.cold-cook"
7687
+ ];
7688
+ PARAMETERIZED_PACK_OPERATION_IDS.map(
7689
+ (id) => ({
7690
+ id,
7691
+ domain: id.startsWith("asset-source.") ? "session" : "asset",
7692
+ readOnly: id.startsWith("asset."),
7693
+ requiresRevision: !id.startsWith("asset.") && id !== "asset-source.create"
7694
+ })
7695
+ );
7696
+ function isRecord2(value) {
6930
7697
  return typeof value === "object" && value !== null && !Array.isArray(value);
6931
7698
  }
6932
7699
  function hasText(value) {
6933
7700
  return typeof value === "string" && value.length > 0;
6934
7701
  }
6935
- function issue(code, subjectId, expected, hint, actual2, authority = "producer") {
7702
+ function issue(code, subjectId, expected, hint, actual, authority = "producer") {
6936
7703
  const subject = { type: "asset", id: subjectId };
6937
7704
  return {
6938
7705
  ok: false,
@@ -6940,7 +7707,7 @@ function issue(code, subjectId, expected, hint, actual2, authority = "producer")
6940
7707
  code,
6941
7708
  subject,
6942
7709
  expected,
6943
- ...actual2 === void 0 ? {} : { actual: actual2 },
7710
+ ...actual === void 0 ? {} : { actual },
6944
7711
  hint,
6945
7712
  authority
6946
7713
  }
@@ -6957,7 +7724,7 @@ function validateFacts(value, subjectId) {
6957
7724
  }
6958
7725
  if ("provenance" in value) {
6959
7726
  const provenance = value.provenance;
6960
- if (!isRecord(provenance) || !hasText(provenance.provider) || !hasText(provenance.version)) {
7727
+ if (!isRecord2(provenance) || !hasText(provenance.provider) || !hasText(provenance.version)) {
6961
7728
  return issue(
6962
7729
  "invalid-producer-fact",
6963
7730
  subjectId,
@@ -6968,7 +7735,7 @@ function validateFacts(value, subjectId) {
6968
7735
  }
6969
7736
  if ("revision" in value) {
6970
7737
  const revision = value.revision;
6971
- if (!isRecord(revision) || !hasText(revision.digest) || !hasText(revision.rootId) || typeof revision.observedAt !== "number" || !Number.isFinite(revision.observedAt)) {
7738
+ if (!isRecord2(revision) || !hasText(revision.digest) || !hasText(revision.rootId) || typeof revision.observedAt !== "number" || !Number.isFinite(revision.observedAt)) {
6972
7739
  return issue(
6973
7740
  "invalid-producer-fact",
6974
7741
  subjectId,
@@ -6987,7 +7754,7 @@ function validateFacts(value, subjectId) {
6987
7754
  );
6988
7755
  }
6989
7756
  for (const diagnostic of value.diagnostics) {
6990
- if (!isRecord(diagnostic) || !hasText(diagnostic.code)) {
7757
+ if (!isRecord2(diagnostic) || !hasText(diagnostic.code)) {
6991
7758
  return issue(
6992
7759
  "invalid-producer-fact",
6993
7760
  subjectId,
@@ -6996,7 +7763,7 @@ function validateFacts(value, subjectId) {
6996
7763
  );
6997
7764
  }
6998
7765
  if (diagnostic.severity === "blocking") {
6999
- if (!isRecord(diagnostic.subject) || !hasText(diagnostic.subject.id)) {
7766
+ if (!isRecord2(diagnostic.subject) || !hasText(diagnostic.subject.id)) {
7000
7767
  return issue(
7001
7768
  "invalid-producer-fact",
7002
7769
  subjectId,
@@ -7020,7 +7787,7 @@ function validateFacts(value, subjectId) {
7020
7787
  function validateMetaSourceOverrides(value, subjectId) {
7021
7788
  if (!("sourceOverrides" in value)) return { ok: true, value };
7022
7789
  const declaredSourceKeys = Array.isArray(value.subAssets) ? value.subAssets.flatMap(
7023
- (subAsset) => isRecord(subAsset) && hasText(subAsset.sourceKey) ? [subAsset.sourceKey] : []
7790
+ (subAsset) => isRecord2(subAsset) && hasText(subAsset.sourceKey) ? [subAsset.sourceKey] : []
7024
7791
  ) : [];
7025
7792
  const result = validateSourceOverrideMap(value.sourceOverrides, declaredSourceKeys);
7026
7793
  if (!result.ok) {
@@ -7039,7 +7806,7 @@ function validateMetaSourceOverrides(value, subjectId) {
7039
7806
  };
7040
7807
  }
7041
7808
  function validateProducerContract(value) {
7042
- if (!isRecord(value)) {
7809
+ if (!isRecord2(value)) {
7043
7810
  return issue(
7044
7811
  "invalid-producer-fact",
7045
7812
  "unknown",
@@ -7141,83 +7908,25 @@ function baseName(p) {
7141
7908
  const idx = Math.max(trimmed.lastIndexOf("/"), trimmed.lastIndexOf("\\"));
7142
7909
  return idx === -1 ? trimmed : trimmed.slice(idx + 1);
7143
7910
  }
7144
- function deriveAssetName(packagePath, assetCount, storedName) {
7911
+ function deriveAssetName(packagePath, _assetCount, storedName) {
7145
7912
  if (packagePath === null) {
7146
7913
  return "";
7147
7914
  }
7148
- {
7149
- return baseName(packagePath);
7150
- }
7915
+ return baseName(packagePath);
7151
7916
  }
7152
7917
 
7153
7918
  // src/resolve-asset-source.ts
7154
7919
  function deriveSourceName(metaFileName) {
7155
7920
  return metaFileName.replace(/\.meta\.json$/, "");
7156
7921
  }
7157
- var PATH_REF_RE = /^@([^/]+)\/(.+)$/;
7158
- function isPathEscape(pathDir, resolved) {
7159
- const rel = posix.relative(pathDir, resolved);
7160
- return rel.startsWith("..") || posix.isAbsolute(rel);
7161
- }
7162
- function resolveAssetSource(metaPath, source, paths) {
7922
+ function resolveAssetSource(metaPath, source) {
7163
7923
  if (source === void 0) {
7164
7924
  const metaDir = dirname(metaPath);
7165
7925
  const metaName = deriveAssetName(metaPath);
7166
7926
  const derived = deriveSourceName(metaName);
7167
- return ok(resolve(metaDir, derived));
7927
+ return resolve(metaDir, derived);
7168
7928
  }
7169
- if (source.startsWith("@")) {
7170
- const match = source.match(PATH_REF_RE);
7171
- if (!match) {
7172
- return err(
7173
- new PackError({
7174
- code: "pack-malformed-path-ref",
7175
- expected: "source in format @<name>/<rest>",
7176
- hint: PACK_ERROR_HINTS["pack-malformed-path-ref"],
7177
- detail: {
7178
- code: "pack-malformed-path-ref",
7179
- reason: "format",
7180
- rawSource: source,
7181
- expectedFormat: "@<name>/<rest>"
7182
- }
7183
- })
7184
- );
7185
- }
7186
- const [, name, rest] = match;
7187
- const pathDir = paths[name];
7188
- if (pathDir === void 0) {
7189
- return err(
7190
- new PackError({
7191
- code: "pack-unknown-path",
7192
- expected: "path name found in package.json#forgeax.assets.paths",
7193
- hint: PACK_ERROR_HINTS["pack-unknown-path"],
7194
- detail: {
7195
- code: "pack-unknown-path",
7196
- pathName: name,
7197
- knownNames: Object.keys(paths)
7198
- }
7199
- })
7200
- );
7201
- }
7202
- const resolved = resolve(pathDir, rest);
7203
- if (isPathEscape(pathDir, resolved)) {
7204
- return err(
7205
- new PackError({
7206
- code: "pack-malformed-path-ref",
7207
- expected: "rest path must not escape the declared path directory",
7208
- hint: PACK_ERROR_HINTS["pack-malformed-path-ref"],
7209
- detail: {
7210
- code: "pack-malformed-path-ref",
7211
- reason: "escape",
7212
- rawSource: source,
7213
- expectedFormat: "@<name>/<rest>"
7214
- }
7215
- })
7216
- );
7217
- }
7218
- return ok(resolved);
7219
- }
7220
- return ok(resolve(dirname(metaPath), source));
7929
+ return resolve(dirname(metaPath), source);
7221
7930
  }
7222
7931
 
7223
7932
  // src/schema-compiled.ts
@@ -7267,7 +7976,7 @@ var meta_schema_default = {
7267
7976
  source: {
7268
7977
  type: "string",
7269
7978
  minLength: 1,
7270
- description: "Optional. Omit to derive the companion file in the same directory (strip .meta.json suffix from the meta filename). Or write @<name>/<rest> to reference a declared path table entry (see package.json#forgeax.assets.paths). Existing relative paths remain unchanged."
7979
+ description: "Optional. Omit to derive the companion file in the same directory (strip .meta.json suffix from the meta filename). An explicit source is resolved relative to this sidecar."
7271
7980
  },
7272
7981
  importSettings: {
7273
7982
  type: "object",
@@ -7408,11 +8117,11 @@ var pack_schema_default = {
7408
8117
  $comment: "The ordinary durable consumer matrix is SCRIPTABLE_PACK_ASSET_KINDS in @forgeax/engine-pack/source. Pack kind fields remain open for registered producer extensions.",
7409
8118
  type: "object",
7410
8119
  additionalProperties: false,
7411
- required: ["schemaVersion", "kind", "assets"],
8120
+ required: ["schemaVersion"],
7412
8121
  properties: {
7413
8122
  schemaVersion: {
7414
8123
  type: "string",
7415
- enum: ["1.0.0", "2.0.0"]
8124
+ enum: ["1.0.0", "2.0.0", "3.0.0"]
7416
8125
  },
7417
8126
  kind: {
7418
8127
  type: "string",
@@ -7434,12 +8143,58 @@ var pack_schema_default = {
7434
8143
  items: { $ref: "#/$defs/diagnostic" }
7435
8144
  },
7436
8145
  assets: {
7437
- type: "array",
7438
- items: {
7439
- $ref: "#/$defs/asset"
7440
- }
8146
+ oneOf: [
8147
+ {
8148
+ type: "array",
8149
+ items: { $ref: "#/$defs/asset" }
8150
+ },
8151
+ { $ref: "#/$defs/authoringAssets" }
8152
+ ]
8153
+ },
8154
+ parent: {
8155
+ $ref: "#/$defs/guid36",
8156
+ description: "Parent parameterized Pack packageId for one v3 instance."
8157
+ },
8158
+ values: {
8159
+ type: "object",
8160
+ additionalProperties: true,
8161
+ description: "Sparse shallow parameter overrides for one v3 instance."
7441
8162
  }
7442
8163
  },
8164
+ oneOf: [
8165
+ {
8166
+ required: ["kind", "assets"],
8167
+ properties: {
8168
+ schemaVersion: { enum: ["1.0.0", "2.0.0"] },
8169
+ kind: { const: "internal-text-package" },
8170
+ assets: { type: "array" },
8171
+ parent: false,
8172
+ values: false
8173
+ }
8174
+ },
8175
+ {
8176
+ required: ["packageId", "assets"],
8177
+ properties: {
8178
+ schemaVersion: { const: "3.0.0" },
8179
+ kind: false,
8180
+ packageId: { $ref: "#/$defs/guid36" },
8181
+ assets: { $ref: "#/$defs/authoringAssets" },
8182
+ parent: false,
8183
+ values: false
8184
+ }
8185
+ },
8186
+ {
8187
+ required: ["packageId", "parent", "values"],
8188
+ properties: {
8189
+ schemaVersion: { const: "3.0.0" },
8190
+ kind: false,
8191
+ packageId: { $ref: "#/$defs/guid36" },
8192
+ parent: { $ref: "#/$defs/guid36" },
8193
+ values: { type: "object" },
8194
+ assets: false
8195
+ }
8196
+ }
8197
+ ],
7443
8198
  allOf: [
7444
8199
  {
7445
8200
  if: {
@@ -7531,6 +8286,30 @@ var pack_schema_default = {
7531
8286
  }
7532
8287
  ]
7533
8288
  },
8289
+ authoringAssets: {
8290
+ type: "object",
8291
+ additionalProperties: false,
8292
+ patternProperties: {
8293
+ "^[a-z0-9][a-z0-9._-]*(/[a-z0-9][a-z0-9._-]*)*$": {
8294
+ $ref: "#/$defs/authoringAsset"
8295
+ }
8296
+ }
8297
+ },
8298
+ authoringAsset: {
8299
+ type: "object",
8300
+ additionalProperties: false,
8301
+ required: ["kind", "payload", "refs"],
8302
+ properties: {
8303
+ kind: { type: "string", minLength: 1 },
8304
+ name: { type: "string", minLength: 1 },
8305
+ payload: { type: "object" },
8306
+ refs: {
8307
+ type: "array",
8308
+ items: { $ref: "#/$defs/guid36" }
8309
+ },
8310
+ artifacts: { $ref: "#/$defs/artifacts" }
8311
+ }
8312
+ },
7534
8313
  artifacts: {
7535
8314
  type: "object",
7536
8315
  additionalProperties: false,
@@ -7638,467 +8417,6 @@ var ajv = new import_ajv.default({ strict: true, allErrors: false });
7638
8417
  (0, import_ajv_formats.default)(ajv, ["uuid"]);
7639
8418
  var validateMeta = ajv.compile(meta_schema_default);
7640
8419
  var validatePack = ajv.compile(pack_schema_default);
7641
- var SCRIPTABLE_PACK_ASSET_KINDS = [
7642
- "mesh",
7643
- "material",
7644
- "scene",
7645
- "texture",
7646
- "equirect",
7647
- "sampler",
7648
- "font",
7649
- "render-pipeline",
7650
- "tileset",
7651
- "video",
7652
- "skeleton",
7653
- "skin",
7654
- "animation-clip",
7655
- "animation-graph",
7656
- "audio",
7657
- "particle-effect"
7658
- ];
7659
- function isScriptablePackAssetKind(value) {
7660
- return SCRIPTABLE_PACK_ASSET_KINDS.includes(value);
7661
- }
7662
- function sceneComponentFieldType(value) {
7663
- if (typeof value === "string") return value;
7664
- if (isRecord2(value) && typeof value.type === "string") return value.type;
7665
- return void 0;
7666
- }
7667
- function projectScriptablePackSceneComponents(components) {
7668
- return (components ?? []).map((component) => ({
7669
- name: component.name,
7670
- fields: Object.fromEntries(
7671
- Object.entries(component.fields).map(([fieldName, field]) => [
7672
- fieldName,
7673
- sceneComponentFieldType(field)
7674
- ])
7675
- )
7676
- }));
7677
- }
7678
- var SCRIPTABLE_PACK_REQUEST_ID_SCHEMA = {
7679
- type: "string",
7680
- minLength: 1,
7681
- maxLength: 128,
7682
- pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$",
7683
- description: "Caller-minted identity for one idempotent ScriptablePack operation."
7684
- };
7685
- var SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA = {
7686
- type: "string",
7687
- minLength: 8,
7688
- pattern: "^[^/].*\\.pack\\.ts$",
7689
- description: "Game-root-relative ScriptablePack source path."
7690
- };
7691
- var SCRIPTABLE_PACK_OWNER_GUID_SCHEMA = {
7692
- type: "string",
7693
- format: "uuid",
7694
- description: "Catalog GUID used to resolve the producer-owned source subject."
7695
- };
7696
- var SCRIPTABLE_PACK_REVISION_SCHEMA = {
7697
- type: "string",
7698
- minLength: 64,
7699
- maxLength: 64,
7700
- pattern: "^[a-f0-9]{64}$",
7701
- description: "SHA-256 source revision returned by preflight."
7702
- };
7703
- var SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA = { type: "string", minLength: 1 };
7704
- var SCRIPTABLE_PACK_ASSET_KIND_SCHEMA = {
7705
- enum: SCRIPTABLE_PACK_ASSET_KINDS,
7706
- description: "Ordinary Asset kind supported by the ScriptablePack producer/loader matrix."
7707
- };
7708
- var SCRIPTABLE_PACK_NAME_SCHEMA = { type: "string", minLength: 1 };
7709
- function scriptablePackArgsSchema(properties, required, options = {}) {
7710
- const subjectRequired = ["requestId", ...required];
7711
- return {
7712
- type: "object",
7713
- properties: {
7714
- sourcePath: SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA,
7715
- ownerGuid: SCRIPTABLE_PACK_OWNER_GUID_SCHEMA,
7716
- requestId: SCRIPTABLE_PACK_REQUEST_ID_SCHEMA,
7717
- ...properties
7718
- },
7719
- required: subjectRequired,
7720
- ...options.subject === false ? {} : {
7721
- anyOf: [
7722
- { required: [...subjectRequired, "sourcePath"] },
7723
- { required: [...subjectRequired, "ownerGuid"] },
7724
- ...options.guidSubject === false ? [] : [{ required: [...subjectRequired, "guid"] }]
7725
- ]
7726
- },
7727
- additionalProperties: false
7728
- };
7729
- }
7730
- [
7731
- {
7732
- id: "asset-source.create",
7733
- kind: "create",
7734
- domain: "session",
7735
- title: "Create Asset Source",
7736
- argsSchema: scriptablePackArgsSchema(
7737
- {
7738
- name: SCRIPTABLE_PACK_NAME_SCHEMA,
7739
- initialOutput: {
7740
- type: "object",
7741
- properties: {
7742
- sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
7743
- kind: SCRIPTABLE_PACK_ASSET_KIND_SCHEMA,
7744
- name: SCRIPTABLE_PACK_NAME_SCHEMA
7745
- },
7746
- required: ["sourceKey", "kind"],
7747
- additionalProperties: false
7748
- }
7749
- },
7750
- ["sourcePath", "initialOutput"],
7751
- { subject: false }
7752
- )
7753
- },
7754
- {
7755
- id: "asset-source.add-output",
7756
- kind: "add-output",
7757
- domain: "session",
7758
- title: "Add Asset Source Output",
7759
- argsSchema: scriptablePackArgsSchema(
7760
- {
7761
- sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
7762
- assetKind: SCRIPTABLE_PACK_ASSET_KIND_SCHEMA,
7763
- name: SCRIPTABLE_PACK_NAME_SCHEMA,
7764
- expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
7765
- },
7766
- ["sourceKey", "assetKind", "expectedRevision"]
7767
- )
7768
- },
7769
- {
7770
- id: "asset-source.add-external-asset",
7771
- kind: "add-external-asset",
7772
- domain: "session",
7773
- title: "Add Asset Source External Asset",
7774
- argsSchema: scriptablePackArgsSchema(
7775
- {
7776
- alias: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
7777
- guid: { type: "string", format: "uuid" },
7778
- expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
7779
- },
7780
- ["alias", "guid", "expectedRevision"],
7781
- { guidSubject: false }
7782
- )
7783
- },
7784
- {
7785
- id: "asset-source.rename",
7786
- kind: "rename",
7787
- domain: "session",
7788
- title: "Rename Asset Source Display Name",
7789
- argsSchema: scriptablePackArgsSchema(
7790
- {
7791
- target: {
7792
- oneOf: [
7793
- {
7794
- type: "object",
7795
- properties: { kind: { const: "package" } },
7796
- required: ["kind"],
7797
- additionalProperties: false
7798
- },
7799
- {
7800
- type: "object",
7801
- properties: {
7802
- kind: { const: "output" },
7803
- sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA
7804
- },
7805
- required: ["kind", "sourceKey"],
7806
- additionalProperties: false
7807
- }
7808
- ]
7809
- },
7810
- name: SCRIPTABLE_PACK_NAME_SCHEMA,
7811
- expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
7812
- },
7813
- ["target", "name", "expectedRevision"]
7814
- )
7815
- },
7816
- {
7817
- id: "asset-source.remove-output",
7818
- kind: "remove-output",
7819
- domain: "session",
7820
- title: "Remove Asset Source Output",
7821
- destructive: true,
7822
- argsSchema: scriptablePackArgsSchema(
7823
- {
7824
- sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
7825
- confirmIncomingRefs: { type: "array", items: { type: "string" } },
7826
- expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
7827
- },
7828
- ["sourceKey", "expectedRevision"]
7829
- )
7830
- },
7831
- {
7832
- id: "asset-source.clone",
7833
- kind: "clone",
7834
- domain: "session",
7835
- title: "Clone Asset Source",
7836
- argsSchema: scriptablePackArgsSchema(
7837
- {
7838
- targetPath: SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA,
7839
- expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
7840
- },
7841
- ["targetPath", "expectedRevision"]
7842
- )
7843
- },
7844
- {
7845
- id: "asset-source.rebuild",
7846
- kind: "rebuild",
7847
- domain: "session",
7848
- title: "Rebuild Asset Source",
7849
- argsSchema: scriptablePackArgsSchema({ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA }, [
7850
- "expectedRevision"
7851
- ])
7852
- },
7853
- {
7854
- id: "asset-source.cold-cook",
7855
- kind: "cold-cook",
7856
- domain: "session",
7857
- title: "Cold Cook Asset Source",
7858
- argsSchema: scriptablePackArgsSchema({ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA }, [
7859
- "expectedRevision"
7860
- ])
7861
- }
7862
- ];
7863
- function actual(value) {
7864
- if (value === null) return "null";
7865
- if (Array.isArray(value)) return "array";
7866
- if (ArrayBuffer.isView(value)) return value.constructor.name;
7867
- return typeof value;
7868
- }
7869
- function invalid(propertyPath, expected, value, sourcePath) {
7870
- return err({
7871
- code: "pack-source-definition-invalid",
7872
- expected,
7873
- hint: "repair the default exported ScriptablePack definition, then inspect Meta again",
7874
- detail: {
7875
- ...sourcePath === void 0 ? {} : { sourcePath },
7876
- propertyPath,
7877
- actual: actual(value)
7878
- }
7879
- });
7880
- }
7881
- function isRecord2(value) {
7882
- return value !== null && typeof value === "object" && !Array.isArray(value);
7883
- }
7884
- function isAssetGuid(value) {
7885
- return value instanceof Uint8Array && value.byteLength === 16;
7886
- }
7887
- function guidKey(guid) {
7888
- return AssetGuid.format(guid);
7889
- }
7890
- function freezeDefinition(definition) {
7891
- const assets = Object.fromEntries(
7892
- Object.entries(definition.assets).map(([sourceKey, descriptor]) => [
7893
- sourceKey,
7894
- Object.freeze({ ...descriptor, guid: descriptor.guid.slice() })
7895
- ])
7896
- );
7897
- const externalAssets = Object.fromEntries(
7898
- Object.entries(definition.externalAssets).map(([alias, guid]) => [
7899
- alias,
7900
- guid.slice()
7901
- ])
7902
- );
7903
- const sceneComponents = definition.sceneComponents === void 0 ? void 0 : Object.freeze(
7904
- projectScriptablePackSceneComponents(definition.sceneComponents).map(
7905
- (component) => Object.freeze({
7906
- ...component,
7907
- fields: Object.freeze({ ...component.fields })
7908
- })
7909
- )
7910
- );
7911
- return Object.freeze({
7912
- ...definition,
7913
- packageId: definition.packageId.slice(),
7914
- assets: Object.freeze(assets),
7915
- externalAssets: Object.freeze(externalAssets),
7916
- ...sceneComponents === void 0 ? {} : { sceneComponents }
7917
- });
7918
- }
7919
- function validateScriptablePackDefinition(value, sourcePath) {
7920
- if (!isRecord2(value))
7921
- return invalid("$", "a ScriptablePack definition object", value, sourcePath);
7922
- if (value.schemaVersion !== "1.0.0") {
7923
- return invalid("$.schemaVersion", "the literal '1.0.0'", value.schemaVersion, sourcePath);
7924
- }
7925
- if (!isAssetGuid(value.packageId)) {
7926
- return invalid("$.packageId", "a 16-byte AssetGuid", value.packageId, sourcePath);
7927
- }
7928
- if (value.name !== void 0 && typeof value.name !== "string") {
7929
- return invalid("$.name", "a string when present", value.name, sourcePath);
7930
- }
7931
- if (!isRecord2(value.assets) || Object.keys(value.assets).length === 0) {
7932
- return invalid(
7933
- "$.assets",
7934
- "a non-empty sourceKey to descriptor object",
7935
- value.assets,
7936
- sourcePath
7937
- );
7938
- }
7939
- if (!isRecord2(value.externalAssets)) {
7940
- return invalid(
7941
- "$.externalAssets",
7942
- "an alias to AssetGuid object",
7943
- value.externalAssets,
7944
- sourcePath
7945
- );
7946
- }
7947
- if (value.sceneComponents !== void 0) {
7948
- if (!Array.isArray(value.sceneComponents)) {
7949
- return invalid(
7950
- "$.sceneComponents",
7951
- "an array of component tokens or neutral schema rows when present",
7952
- value.sceneComponents,
7953
- sourcePath
7954
- );
7955
- }
7956
- const componentNames = /* @__PURE__ */ new Set();
7957
- for (const [componentIndex, component] of value.sceneComponents.entries()) {
7958
- if (!isRecord2(component)) {
7959
- return invalid(
7960
- `$.sceneComponents[${componentIndex}]`,
7961
- "a component token or neutral schema row",
7962
- component,
7963
- sourcePath
7964
- );
7965
- }
7966
- if (typeof component.name !== "string" || component.name.trim().length === 0) {
7967
- return invalid(
7968
- `$.sceneComponents[${componentIndex}].name`,
7969
- "a non-empty component name",
7970
- component.name,
7971
- sourcePath
7972
- );
7973
- }
7974
- if (componentNames.has(component.name)) {
7975
- return invalid(
7976
- `$.sceneComponents[${componentIndex}].name`,
7977
- "component names to be unique within one ScriptablePack",
7978
- component.name,
7979
- sourcePath
7980
- );
7981
- }
7982
- componentNames.add(component.name);
7983
- if (!isRecord2(component.fields)) {
7984
- return invalid(
7985
- `$.sceneComponents[${componentIndex}].fields`,
7986
- "a field-name to schema-type object",
7987
- component.fields,
7988
- sourcePath
7989
- );
7990
- }
7991
- for (const [fieldName, field] of Object.entries(component.fields)) {
7992
- const type = sceneComponentFieldType(field);
7993
- if (fieldName.trim().length === 0 || type === void 0 || type.trim().length === 0) {
7994
- return invalid(
7995
- `$.sceneComponents[${componentIndex}].fields`,
7996
- "field names with non-empty string schema types",
7997
- field,
7998
- sourcePath
7999
- );
8000
- }
8001
- }
8002
- }
8003
- }
8004
- if (typeof value.build !== "function") {
8005
- return invalid("$.build", "a build(assetReader) function", value.build, sourcePath);
8006
- }
8007
- const packageGuid = guidKey(value.packageId);
8008
- const localGuids = /* @__PURE__ */ new Set();
8009
- for (const [sourceKey, descriptor] of Object.entries(value.assets)) {
8010
- if (sourceKey.trim().length === 0) {
8011
- return invalid("$.assets", "non-empty sourceKey object keys", sourceKey, sourcePath);
8012
- }
8013
- if (!isRecord2(descriptor)) {
8014
- return invalid(
8015
- `$.assets[${JSON.stringify(sourceKey)}]`,
8016
- "an asset descriptor",
8017
- descriptor,
8018
- sourcePath
8019
- );
8020
- }
8021
- if (!isAssetGuid(descriptor.guid)) {
8022
- return invalid(
8023
- `$.assets[${JSON.stringify(sourceKey)}].guid`,
8024
- "a 16-byte AssetGuid",
8025
- descriptor.guid,
8026
- sourcePath
8027
- );
8028
- }
8029
- if (typeof descriptor.kind !== "string" || !isScriptablePackAssetKind(descriptor.kind)) {
8030
- return invalid(
8031
- `$.assets[${JSON.stringify(sourceKey)}].kind`,
8032
- "one of SCRIPTABLE_PACK_ASSET_KINDS",
8033
- descriptor.kind,
8034
- sourcePath
8035
- );
8036
- }
8037
- if (descriptor.name !== void 0 && typeof descriptor.name !== "string") {
8038
- return invalid(
8039
- `$.assets[${JSON.stringify(sourceKey)}].name`,
8040
- "a string when present",
8041
- descriptor.name,
8042
- sourcePath
8043
- );
8044
- }
8045
- const guid = guidKey(descriptor.guid);
8046
- if (guid === packageGuid || localGuids.has(guid)) {
8047
- return invalid(
8048
- `$.assets[${JSON.stringify(sourceKey)}].guid`,
8049
- "a GUID unique within the package and distinct from packageId",
8050
- descriptor.guid,
8051
- sourcePath
8052
- );
8053
- }
8054
- localGuids.add(guid);
8055
- }
8056
- const externalGuids = /* @__PURE__ */ new Set();
8057
- for (const [alias, guidValue] of Object.entries(value.externalAssets)) {
8058
- if (alias.trim().length === 0) {
8059
- return invalid("$.externalAssets", "non-empty alias object keys", alias, sourcePath);
8060
- }
8061
- if (!isAssetGuid(guidValue)) {
8062
- return invalid(
8063
- `$.externalAssets[${JSON.stringify(alias)}]`,
8064
- "a 16-byte AssetGuid",
8065
- guidValue,
8066
- sourcePath
8067
- );
8068
- }
8069
- const guid = guidKey(guidValue);
8070
- if (guid === packageGuid || localGuids.has(guid) || externalGuids.has(guid)) {
8071
- return invalid(
8072
- `$.externalAssets[${JSON.stringify(alias)}]`,
8073
- "a unique foreign GUID not owned by this package",
8074
- guidValue,
8075
- sourcePath
8076
- );
8077
- }
8078
- externalGuids.add(guid);
8079
- }
8080
- return ok(freezeDefinition(value));
8081
- }
8082
- function projectScriptablePackMeta(definition, source) {
8083
- const subAssets = Object.entries(definition.assets).sort(([left], [right]) => left.localeCompare(right)).map(([sourceKey, descriptor], sourceIndex) => ({
8084
- guid: guidKey(descriptor.guid),
8085
- sourceIndex,
8086
- sourceKey,
8087
- kind: descriptor.kind,
8088
- ...descriptor.name === void 0 ? {} : { name: descriptor.name }
8089
- }));
8090
- const externalAssets = Object.entries(definition.externalAssets).sort(([left], [right]) => left.localeCompare(right)).map(([alias, guid]) => ({ alias, guid: guidKey(guid) }));
8091
- return {
8092
- schemaVersion: "1.0.0",
8093
- kind: "external-asset-package",
8094
- packageId: guidKey(definition.packageId),
8095
- ...definition.name === void 0 ? {} : { name: definition.name },
8096
- importer: "pack-ts",
8097
- source,
8098
- importSettings: { contractVersion: "1.0.0", externalAssets },
8099
- subAssets
8100
- };
8101
- }
8102
8420
  var IMPORT_META_RESOLVE_FLAG = "--experimental-import-meta-resolve";
8103
8421
  function scriptablePackWorkerExecArgv() {
8104
8422
  const inherited = process.execArgv.filter((arg) => !arg.startsWith("--input-type"));
@@ -8146,50 +8464,51 @@ async function inventoryScriptablePackSource(sourcePath, initialSourceText) {
8146
8464
  }
8147
8465
  function serializeFailure(value) {
8148
8466
  if (value !== null && typeof value === "object") {
8149
- const failure = value;
8467
+ const failure2 = value;
8150
8468
  return {
8151
- name: failure.name,
8152
- code: failure.code,
8153
- expected: failure.expected,
8154
- actual: failure.actual,
8155
- hint: failure.hint,
8156
- detail: failure.detail,
8157
- message: failure.message
8469
+ name: failure2.name,
8470
+ code: failure2.code,
8471
+ expected: failure2.expected,
8472
+ actual: failure2.actual,
8473
+ hint: failure2.hint,
8474
+ detail: failure2.detail,
8475
+ message: failure2.message
8158
8476
  };
8159
8477
  }
8160
8478
  return { message: String(value) };
8161
8479
  }
8162
8480
  function hydrateFailure(value) {
8163
8481
  if (value === null || typeof value !== "object") return value;
8164
- const failure = value;
8165
- if (failure.name === "AssetError" && typeof failure.code === "string" && typeof failure.expected === "string" && typeof failure.hint === "string") {
8482
+ const failure2 = value;
8483
+ if (failure2.name === "AssetError" && typeof failure2.code === "string" && typeof failure2.expected === "string" && typeof failure2.hint === "string") {
8166
8484
  const args = {
8167
- code: failure.code,
8168
- expected: failure.expected,
8169
- hint: failure.hint
8485
+ code: failure2.code,
8486
+ expected: failure2.expected,
8487
+ hint: failure2.hint
8170
8488
  };
8171
- return failure.detail === void 0 ? new AssetError(args) : new AssetError({
8489
+ return failure2.detail === void 0 ? new AssetError(args) : new AssetError({
8172
8490
  ...args,
8173
- detail: failure.detail
8491
+ detail: failure2.detail
8174
8492
  });
8175
8493
  }
8176
- if (failure.name === "ImportError" && typeof failure.code === "string" && typeof failure.expected === "string" && typeof failure.hint === "string" && failure.detail !== void 0) {
8494
+ if (failure2.name === "ImportError" && typeof failure2.code === "string" && typeof failure2.expected === "string" && typeof failure2.hint === "string" && failure2.detail !== void 0) {
8177
8495
  return new ImportError({
8178
- code: failure.code,
8179
- expected: failure.expected,
8180
- hint: failure.hint,
8181
- detail: failure.detail,
8182
- ...typeof failure.actual === "string" ? { actual: failure.actual } : {}
8496
+ code: failure2.code,
8497
+ expected: failure2.expected,
8498
+ hint: failure2.hint,
8499
+ detail: failure2.detail,
8500
+ ...typeof failure2.actual === "string" ? { actual: failure2.actual } : {}
8183
8501
  });
8184
8502
  }
8185
- if (typeof failure.message === "string") {
8186
- const error = new Error(failure.message);
8187
- if (typeof failure.name === "string") error.name = failure.name;
8503
+ if (typeof failure2.message === "string") {
8504
+ const error = new Error(failure2.message);
8505
+ if (typeof failure2.name === "string") error.name = failure2.name;
8188
8506
  return error;
8189
8507
  }
8190
8508
  return value;
8191
8509
  }
8192
8510
  var WorkerScriptablePackExecutor = class {
8511
+ supportsParameterizedContext = true;
8193
8512
  worker;
8194
8513
  compileRoot;
8195
8514
  nextBuildId = 0;
@@ -8217,7 +8536,7 @@ var WorkerScriptablePackExecutor = class {
8217
8536
  resolveLoad({
8218
8537
  default: value.definition === void 0 ? void 0 : {
8219
8538
  ...value.definition,
8220
- build: (reader) => this.runBuild(reader)
8539
+ build: (readByGuid, context) => this.runBuild({ readByGuid }, context)
8221
8540
  }
8222
8541
  });
8223
8542
  } else if (value.kind === "load-threw") {
@@ -8249,7 +8568,7 @@ var WorkerScriptablePackExecutor = class {
8249
8568
  })();
8250
8569
  return this.disposal;
8251
8570
  }
8252
- runBuild(reader) {
8571
+ runBuild(reader, context) {
8253
8572
  const worker = this.worker;
8254
8573
  if (worker === void 0) return Promise.reject(new Error("ScriptablePack worker is closed"));
8255
8574
  if (this.build !== void 0)
@@ -8257,7 +8576,7 @@ var WorkerScriptablePackExecutor = class {
8257
8576
  const id = this.nextBuildId++;
8258
8577
  return new Promise((resolveBuild, rejectBuild) => {
8259
8578
  this.build = { id, reader, resolve: resolveBuild, reject: rejectBuild };
8260
- worker.postMessage({ kind: "build", buildId: id });
8579
+ worker.postMessage({ kind: "build", buildId: id, context });
8261
8580
  });
8262
8581
  }
8263
8582
  onMessage(message) {
@@ -8290,11 +8609,11 @@ function scriptablePackWorkerUrl() {
8290
8609
  const bundledWorker = new URL("./scriptable-pack-worker.mjs", import.meta.url);
8291
8610
  return existsSync(fileURLToPath(bundledWorker)) ? bundledWorker : new URL("../dist/scriptable-pack-worker.mjs", import.meta.url);
8292
8611
  }
8293
- function loadFailure(sourcePath, reason, phase, diagnostic, timeoutMs) {
8294
- return err({
8295
- code: "pack-source-load-failed",
8296
- expected: "a trusted synchronous module with a valid default ScriptablePack export",
8297
- hint: "repair the module load or initialization failure, then inspect Meta again",
8612
+ function parameterizedLoadFailure(sourcePath, reason, phase, diagnostic, timeoutMs) {
8613
+ return {
8614
+ code: "pack-parameter-invalid",
8615
+ expected: "a trusted Pack v2 authoring module with a valid default export",
8616
+ hint: "repair the source module or its build timeout, then inspect the Pack again",
8298
8617
  detail: {
8299
8618
  sourcePath,
8300
8619
  reason,
@@ -8302,30 +8621,16 @@ function loadFailure(sourcePath, reason, phase, diagnostic, timeoutMs) {
8302
8621
  diagnostic,
8303
8622
  ...timeoutMs === void 0 ? {} : { timeoutMs }
8304
8623
  }
8305
- });
8306
- }
8307
- function buildTimeoutFailure(sourcePath, timeoutMs) {
8308
- return {
8309
- code: "pack-source-load-failed",
8310
- expected: "a ScriptablePack build to settle within the configured build timeout",
8311
- hint: "repair the authored build, then retry through a fresh ScriptablePack generation",
8312
- detail: {
8313
- sourcePath,
8314
- reason: "timeout",
8315
- phase: "build",
8316
- timeoutMs,
8317
- diagnostic: `ScriptablePack build exceeded ${timeoutMs}ms`
8318
- }
8319
8624
  };
8320
8625
  }
8321
- async function loadScriptablePack(sourcePath, options = {}) {
8626
+ async function loadParameterizedScriptablePack(sourcePath, options = {}) {
8322
8627
  const timeoutMs = options.timeoutMs ?? 15e3;
8323
8628
  const buildTimeoutMs = options.buildTimeoutMs ?? 5e3;
8324
8629
  const executor = options.executor ?? new WorkerScriptablePackExecutor();
8325
8630
  let disposeReason;
8326
8631
  let timeout;
8327
8632
  try {
8328
- const timeoutSignal = /* @__PURE__ */ Symbol("scriptable-pack-module-timeout");
8633
+ const timeoutSignal = /* @__PURE__ */ Symbol("parameterized-pack-module-timeout");
8329
8634
  const loaded = await Promise.race([
8330
8635
  executor.load(sourcePath),
8331
8636
  new Promise((resolve3) => {
@@ -8334,34 +8639,49 @@ async function loadScriptablePack(sourcePath, options = {}) {
8334
8639
  ]);
8335
8640
  if (loaded === timeoutSignal) {
8336
8641
  disposeReason = "timeout";
8337
- return loadFailure(
8338
- sourcePath,
8339
- "timeout",
8340
- "module-load",
8341
- `ScriptablePack module initialization exceeded ${timeoutMs}ms`,
8342
- timeoutMs
8642
+ return err(
8643
+ parameterizedLoadFailure(
8644
+ sourcePath,
8645
+ "timeout",
8646
+ "module-load",
8647
+ `Pack module initialization exceeded ${timeoutMs}ms`,
8648
+ timeoutMs
8649
+ )
8343
8650
  );
8344
8651
  }
8345
8652
  const moduleValue = loaded !== null && typeof loaded === "object" && "default" in loaded ? loaded.default : void 0;
8346
- const validated = validateScriptablePackDefinition(moduleValue, sourcePath);
8653
+ const validated = validatePackDefinition(moduleValue, sourcePath);
8347
8654
  if (!validated.ok) {
8348
8655
  disposeReason = "failure";
8349
8656
  return validated;
8350
8657
  }
8351
8658
  if (options.metadataOnly === true) {
8352
8659
  disposeReason = "complete";
8353
- return validated;
8660
+ return ok(validated.value);
8354
8661
  }
8355
8662
  const definition = validated.value;
8663
+ const build = definition.build;
8356
8664
  return ok({
8357
8665
  ...definition,
8358
- build: async (reader) => {
8666
+ build: async (context) => {
8359
8667
  let buildTimedOut = false;
8360
8668
  let buildTimeout;
8361
- const timeoutResult = err(buildTimeoutFailure(sourcePath, buildTimeoutMs));
8669
+ const timeoutResult = err(
8670
+ parameterizedLoadFailure(
8671
+ sourcePath,
8672
+ "timeout",
8673
+ "build",
8674
+ `ScriptablePack build exceeded ${buildTimeoutMs}ms`,
8675
+ buildTimeoutMs
8676
+ )
8677
+ );
8362
8678
  try {
8679
+ const invocation = "supportsParameterizedContext" in executor && executor.supportsParameterizedContext === true ? build(context.readByGuid, {
8680
+ packageId: [...context.packageId],
8681
+ ..."values" in context && context.values !== void 0 ? { values: context.values } : {}
8682
+ }) : definition.build(context);
8363
8683
  const built = await Promise.race([
8364
- Promise.resolve(definition.build(reader)),
8684
+ Promise.resolve(invocation),
8365
8685
  new Promise((resolve3) => {
8366
8686
  buildTimeout = setTimeout(() => {
8367
8687
  buildTimedOut = true;
@@ -8384,9 +8704,15 @@ async function loadScriptablePack(sourcePath, options = {}) {
8384
8704
  }
8385
8705
  });
8386
8706
  } catch (error) {
8387
- const diagnostic = error instanceof Error ? error.message : String(error);
8388
8707
  disposeReason = "failure";
8389
- return loadFailure(sourcePath, "module-load", "module-load", diagnostic);
8708
+ return err(
8709
+ parameterizedLoadFailure(
8710
+ sourcePath,
8711
+ "module-load",
8712
+ "module-load",
8713
+ error instanceof Error ? error.message : String(error)
8714
+ )
8715
+ );
8390
8716
  } finally {
8391
8717
  if (timeout !== void 0) clearTimeout(timeout);
8392
8718
  if (disposeReason !== void 0) await executor.dispose?.(disposeReason);
@@ -8400,11 +8726,15 @@ function ok3(value) {
8400
8726
  function packErr(error) {
8401
8727
  return { ok: false, error };
8402
8728
  }
8729
+ function record(value) {
8730
+ return value !== null && typeof value === "object" && !Array.isArray(value);
8731
+ }
8403
8732
  var STANDARD_SCRIPTABLE_PACK_SCAN_OPTIONS = Object.freeze(
8404
8733
  {}
8405
8734
  );
8406
8735
  var BLACKLIST = /* @__PURE__ */ new Set([
8407
8736
  "node_modules",
8737
+ "__tests__",
8408
8738
  ".forgeax-harness",
8409
8739
  ".forgeax",
8410
8740
  ".git",
@@ -8508,10 +8838,87 @@ async function scanValidated(roots, opts = {}, capture) {
8508
8838
  const scriptablePaths = rawPaths.filter((p) => p.endsWith(".pack.ts"));
8509
8839
  const guidToPath = /* @__PURE__ */ new Map();
8510
8840
  const packRefs = /* @__PURE__ */ new Map();
8841
+ const packageIdToPath = /* @__PURE__ */ new Map();
8842
+ const packageKind = /* @__PURE__ */ new Map();
8843
+ const instanceParents = [];
8844
+ function registerPackage(packageId2, path, kind) {
8845
+ if (packageId2 === void 0) return void 0;
8846
+ const normalized = packageId2.toLowerCase();
8847
+ const existing = packageIdToPath.get(normalized);
8848
+ if (existing !== void 0) {
8849
+ return makePackError("pack-guid-collision", {
8850
+ paths: [existing, path],
8851
+ guid: normalized
8852
+ });
8853
+ }
8854
+ packageIdToPath.set(normalized, path);
8855
+ packageKind.set(normalized, kind);
8856
+ return void 0;
8857
+ }
8511
8858
  for (const packPath of packPaths) {
8512
8859
  const loaded = await readValidatedJson(packPath, "pack-malformed-pack", validatePack);
8513
8860
  if (!loaded.ok) return loaded;
8514
8861
  const { raw, parsed } = loaded.value;
8862
+ if (record(parsed) && parsed.schemaVersion === "3.0.0") {
8863
+ const authoring = parseParameterizedPackJson(parsed);
8864
+ if (!authoring.ok) {
8865
+ return packErr(
8866
+ makePackError("pack-malformed-pack", {
8867
+ path: packPath,
8868
+ ajvErrors: [{ instancePath: "", message: authoring.error.code }]
8869
+ })
8870
+ );
8871
+ }
8872
+ const packageId2 = authoring.value.packageId;
8873
+ const packageCollision2 = registerPackage(
8874
+ PackageId.format(packageId2),
8875
+ packPath,
8876
+ authoring.value.format
8877
+ );
8878
+ if (packageCollision2 !== void 0) return packErr(packageCollision2);
8879
+ if (authoring.value.format === "instance") {
8880
+ instanceParents.push({
8881
+ path: packPath,
8882
+ packageId: PackageId.format(authoring.value.packageId),
8883
+ parent: PackageId.format(authoring.value.parent)
8884
+ });
8885
+ } else {
8886
+ const projected = projectDirectPackJson(authoring.value);
8887
+ if (!projected.ok) {
8888
+ return packErr(
8889
+ makePackError("pack-malformed-pack", {
8890
+ path: packPath,
8891
+ ajvErrors: [{ instancePath: "/assets", message: projected.error.code }]
8892
+ })
8893
+ );
8894
+ }
8895
+ for (const asset of projected.value.assets) {
8896
+ const normalizedGuid = asset.guid.toLowerCase();
8897
+ const existing = guidToPath.get(normalizedGuid);
8898
+ if (existing !== void 0) {
8899
+ return packErr(
8900
+ makePackError("pack-guid-collision", {
8901
+ paths: [existing, packPath],
8902
+ guid: normalizedGuid
8903
+ })
8904
+ );
8905
+ }
8906
+ guidToPath.set(normalizedGuid, packPath);
8907
+ packRefs.set(normalizedGuid, [
8908
+ ...asset.refs.map((ref) => ref.toLowerCase()),
8909
+ ...extractMountSourceGuids(asset)
8910
+ ]);
8911
+ }
8912
+ }
8913
+ capture?.declarations.set(packPath, {
8914
+ format: "pack.json",
8915
+ sourcePath: packPath,
8916
+ sourceRevision: `sha256:${createHash("sha256").update(raw).digest("hex")}`,
8917
+ sourceText: raw,
8918
+ value: parsed
8919
+ });
8920
+ continue;
8921
+ }
8515
8922
  const packageContract = validateProducerContract(parsed);
8516
8923
  if (!packageContract.ok) {
8517
8924
  return packErr(
@@ -8522,6 +8929,8 @@ async function scanValidated(roots, opts = {}, capture) {
8522
8929
  );
8523
8930
  }
8524
8931
  const packObj = parsed;
8932
+ const packageCollision = registerPackage(packObj.packageId, packPath, "legacy");
8933
+ if (packageCollision !== void 0) return packErr(packageCollision);
8525
8934
  for (const asset of packObj.assets) {
8526
8935
  if (asset.kind === "particle-effect" && asset.execution === "direct" && (asset.refs.length > 0 || Object.keys(asset.artifacts ?? {}).length > 0)) {
8527
8936
  return packErr(
@@ -8612,7 +9021,6 @@ async function scanValidated(roots, opts = {}, capture) {
8612
9021
  value: packObj
8613
9022
  });
8614
9023
  }
8615
- const { paths: assetPaths } = loadAssetConfig(process.cwd());
8616
9024
  for (const metaPath of metaPaths) {
8617
9025
  const loaded = await readValidatedJson(metaPath, "pack-malformed-meta", validateMeta);
8618
9026
  if (!loaded.ok) return loaded;
@@ -8627,6 +9035,8 @@ async function scanValidated(roots, opts = {}, capture) {
8627
9035
  );
8628
9036
  }
8629
9037
  const metaObj = parsed;
9038
+ const packageCollision = registerPackage(metaObj.packageId, metaPath, "legacy");
9039
+ if (packageCollision !== void 0) return packErr(packageCollision);
8630
9040
  capture?.declarations.set(metaPath, {
8631
9041
  format: "meta.json",
8632
9042
  sourcePath: metaPath,
@@ -8666,11 +9076,7 @@ async function scanValidated(roots, opts = {}, capture) {
8666
9076
  );
8667
9077
  }
8668
9078
  }
8669
- const sourceResolved = resolveAssetSource(metaPath, metaObj.source, assetPaths);
8670
- if (!sourceResolved.ok) {
8671
- return packErr(sourceResolved.error);
8672
- }
8673
- const expectedSourcePath = sourceResolved.value;
9079
+ const expectedSourcePath = resolveAssetSource(metaPath, metaObj.source);
8674
9080
  try {
8675
9081
  await stat(expectedSourcePath);
8676
9082
  } catch {
@@ -8690,23 +9096,24 @@ async function scanValidated(roots, opts = {}, capture) {
8690
9096
  return packErr(
8691
9097
  makePackError("pack-malformed-meta", {
8692
9098
  path: sourcePath,
8693
- ajvErrors: [{ instancePath: "", message: "ScriptablePack source read failed" }]
9099
+ ajvErrors: [{ instancePath: "", message: "Pack source read failed" }]
8694
9100
  })
8695
9101
  );
8696
9102
  }
8697
- const loaded = await loadScriptablePack(sourcePath, {
9103
+ const loaderOptions = {
8698
9104
  ...opts.scriptablePack ?? {},
8699
9105
  ...capture === void 0 ? { metadataOnly: true } : {}
8700
- });
9106
+ };
9107
+ const loaded = await loadParameterizedScriptablePack(sourcePath, loaderOptions);
8701
9108
  if (!loaded.ok) {
8702
- const diagnostic = "diagnostic" in loaded.error.detail ? loaded.error.detail.diagnostic : void 0;
9109
+ const diagnostic = loaded.error.detail.diagnostic;
8703
9110
  return packErr(
8704
9111
  makePackError("pack-malformed-meta", {
8705
9112
  path: sourcePath,
8706
9113
  ajvErrors: [
8707
9114
  {
8708
9115
  instancePath: "",
8709
- message: diagnostic === void 0 ? loaded.error.code : `${loaded.error.code}: ${diagnostic}`
9116
+ message: typeof diagnostic === "string" ? `${loaded.error.code}: ${diagnostic}` : loaded.error.code
8710
9117
  }
8711
9118
  ]
8712
9119
  })
@@ -8719,41 +9126,81 @@ async function scanValidated(roots, opts = {}, capture) {
8719
9126
  return packErr(
8720
9127
  makePackError("pack-malformed-meta", {
8721
9128
  path: sourcePath,
8722
- ajvErrors: [{ instancePath: "", message: "ScriptablePack source closure read failed" }]
9129
+ ajvErrors: [{ instancePath: "", message: "Pack source closure read failed" }]
8723
9130
  })
8724
9131
  );
8725
9132
  }
8726
- const meta = projectScriptablePackMeta(loaded.value, sourcePath);
8727
- const topology = validateProducerOutputs(meta.subAssets);
8728
- if (!topology.ok) {
8729
- return packErr(
8730
- makePackError("pack-malformed-meta", {
8731
- path: sourcePath,
8732
- ajvErrors: [{ instancePath: "/subAssets", message: topology.error.code }]
8733
- })
8734
- );
8735
- }
8736
- const declaration = {
9133
+ const packageCollision = registerPackage(
9134
+ PackageId.format(loaded.value.packageId),
9135
+ sourcePath,
9136
+ "parameterized"
9137
+ );
9138
+ if (packageCollision !== void 0) return packErr(packageCollision);
9139
+ const meta = projectParameterizedPackMeta(loaded.value, sourcePath);
9140
+ capture?.declarations.set(sourcePath, {
9141
+ format: "pack.ts-parameterized",
8737
9142
  sourcePath,
8738
9143
  sourceRevision: `sha256:${createHash("sha256").update(source).digest("hex")}`,
8739
- meta,
9144
+ value: meta,
8740
9145
  definition: loaded.value,
8741
9146
  sourceClosure
8742
- };
8743
- capture?.declarations.set(sourcePath, {
8744
- format: "pack.ts",
8745
- ...declaration,
8746
- value: meta
8747
9147
  });
8748
- for (const sub of meta.subAssets) {
8749
- const guid = sub.guid.toLowerCase();
8750
- const existing = guidToPath.get(guid);
8751
- if (existing !== void 0) {
9148
+ }
9149
+ const parentByPackageId = new Map(
9150
+ instanceParents.map((instance) => [instance.packageId.toLowerCase(), instance])
9151
+ );
9152
+ for (const instance of instanceParents) {
9153
+ const parentId = instance.parent.toLowerCase();
9154
+ const parentPath = packageIdToPath.get(parentId);
9155
+ if (parentPath === void 0) {
9156
+ return packErr(
9157
+ makePackError("pack-malformed-pack", {
9158
+ path: instance.path,
9159
+ reason: "pack-parent-not-found",
9160
+ ajvErrors: [
9161
+ {
9162
+ instancePath: "/parent",
9163
+ message: `parent packageId ${instance.parent} was not found`
9164
+ }
9165
+ ]
9166
+ })
9167
+ );
9168
+ }
9169
+ const kind = packageKind.get(parentId);
9170
+ if (kind !== "parameterized" && kind !== "instance") {
9171
+ return packErr(
9172
+ makePackError("pack-malformed-pack", {
9173
+ path: instance.path,
9174
+ reason: "pack-parent-not-parameterized",
9175
+ ajvErrors: [
9176
+ {
9177
+ instancePath: "/parent",
9178
+ message: `parent ${instance.parent} is not a parameterized Pack`
9179
+ }
9180
+ ]
9181
+ })
9182
+ );
9183
+ }
9184
+ }
9185
+ for (const instance of instanceParents) {
9186
+ const chain = /* @__PURE__ */ new Set();
9187
+ let current = instance.packageId.toLowerCase();
9188
+ while (true) {
9189
+ if (chain.has(current)) {
8752
9190
  return packErr(
8753
- makePackError("pack-guid-collision", { paths: [existing, sourcePath], guid })
9191
+ makePackError("pack-malformed-pack", {
9192
+ path: instance.path,
9193
+ reason: "pack-parent-cycle",
9194
+ ajvErrors: [
9195
+ { instancePath: "/parent", message: `parent chain repeats packageId ${current}` }
9196
+ ]
9197
+ })
8754
9198
  );
8755
9199
  }
8756
- guidToPath.set(guid, sourcePath);
9200
+ chain.add(current);
9201
+ const next = parentByPackageId.get(current);
9202
+ if (next === void 0) break;
9203
+ current = next.parent.toLowerCase();
8757
9204
  }
8758
9205
  }
8759
9206
  const visited = /* @__PURE__ */ new Set();
@@ -8800,6 +9247,38 @@ async function scanInventory(roots, opts = {}) {
8800
9247
  for (const sourcePath of scanned.value) {
8801
9248
  const declaration = declarations.get(sourcePath);
8802
9249
  if (declaration?.format !== "pack.json") continue;
9250
+ if (declaration.value.schemaVersion === "3.0.0") {
9251
+ const parsed = parseParameterizedPackJson(declaration.value);
9252
+ if (!parsed.ok) {
9253
+ return packErr(
9254
+ makePackError("pack-malformed-pack", {
9255
+ path: sourcePath,
9256
+ ajvErrors: [{ instancePath: "", message: parsed.error.code }]
9257
+ })
9258
+ );
9259
+ }
9260
+ if (parsed.value.format !== "direct") continue;
9261
+ const projected = projectDirectPackJson(parsed.value);
9262
+ if (!projected.ok) {
9263
+ return packErr(
9264
+ makePackError("pack-malformed-pack", {
9265
+ path: sourcePath,
9266
+ ajvErrors: [{ instancePath: "/assets", message: projected.error.code }]
9267
+ })
9268
+ );
9269
+ }
9270
+ for (const [index, asset] of projected.value.assets.entries()) {
9271
+ inventory.push({
9272
+ guid: asset.guid,
9273
+ kind: asset.kind,
9274
+ sourcePath,
9275
+ sourceRevision: declaration.sourceRevision,
9276
+ sourceKey: asset.sourceKey,
9277
+ sourceIndex: index
9278
+ });
9279
+ }
9280
+ continue;
9281
+ }
8803
9282
  for (const [index, asset] of declaration.value.assets.entries()) {
8804
9283
  inventory.push({
8805
9284
  guid: asset.guid,