@forgeax/engine-pack 0.1.21 → 0.1.24

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 (139) hide show
  1. package/README.md +167 -48
  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__/material-cook-receipt-layer-plan.unit.test.d.ts +2 -0
  5. package/dist/__tests__/material-cook-receipt-layer-plan.unit.test.d.ts.map +1 -0
  6. package/dist/__tests__/pack-authoring-gateway.unit.test.d.ts +2 -0
  7. package/dist/__tests__/pack-authoring-gateway.unit.test.d.ts.map +1 -0
  8. package/dist/__tests__/pack-authoring.unit.test.d.ts +2 -0
  9. package/dist/__tests__/pack-authoring.unit.test.d.ts.map +1 -0
  10. package/dist/__tests__/pack-scanner.unit.test.d.ts +2 -0
  11. package/dist/__tests__/pack-scanner.unit.test.d.ts.map +1 -0
  12. package/dist/__tests__/scanner-blacklist.test.d.ts +2 -0
  13. package/dist/__tests__/scanner-blacklist.test.d.ts.map +1 -0
  14. package/dist/build.d.ts +9 -4
  15. package/dist/build.d.ts.map +1 -1
  16. package/dist/build.mjs +3449 -897
  17. package/dist/build.mjs.map +1 -1
  18. package/dist/builtin.mjs +37 -4
  19. package/dist/builtin.mjs.map +1 -1
  20. package/dist/catalog-builder.d.ts.map +1 -1
  21. package/dist/cli-asset.d.ts.map +1 -1
  22. package/dist/cli-asset.mjs +1361 -845
  23. package/dist/cli-asset.mjs.map +1 -1
  24. package/dist/deriveAssetName.d.ts +11 -7
  25. package/dist/deriveAssetName.d.ts.map +1 -1
  26. package/dist/evidence/material-cook.d.ts +11 -0
  27. package/dist/evidence/material-cook.d.ts.map +1 -1
  28. package/dist/evidence/source-inventory.d.ts.map +1 -1
  29. package/dist/guid.d.ts +15 -0
  30. package/dist/guid.d.ts.map +1 -1
  31. package/dist/guid.mjs +53 -5
  32. package/dist/guid.mjs.map +1 -1
  33. package/dist/index.d.ts +4 -2
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.mjs +1297 -562
  36. package/dist/index.mjs.map +1 -1
  37. package/dist/inventory/binding.d.ts +6 -0
  38. package/dist/inventory/binding.d.ts.map +1 -0
  39. package/dist/inventory/declaration.d.ts +24 -0
  40. package/dist/inventory/declaration.d.ts.map +1 -0
  41. package/dist/inventory/index.d.ts +3 -0
  42. package/dist/inventory/index.d.ts.map +1 -0
  43. package/dist/inventory/sync.d.ts +5 -0
  44. package/dist/inventory/sync.d.ts.map +1 -0
  45. package/dist/material-cook.d.ts +1 -1
  46. package/dist/material-cook.d.ts.map +1 -1
  47. package/dist/material-cook.mjs +50 -3
  48. package/dist/material-cook.mjs.map +1 -1
  49. package/dist/name.mjs +4 -7
  50. package/dist/name.mjs.map +1 -1
  51. package/dist/pack-authoring-node.d.ts +26 -0
  52. package/dist/pack-authoring-node.d.ts.map +1 -0
  53. package/dist/pack-authoring-node.mjs +11089 -0
  54. package/dist/pack-authoring-node.mjs.map +1 -0
  55. package/dist/pack-authoring.d.ts +230 -0
  56. package/dist/pack-authoring.d.ts.map +1 -0
  57. package/dist/pack-authoring.mjs +1137 -0
  58. package/dist/pack-authoring.mjs.map +1 -0
  59. package/dist/package-finalizer.d.ts +2 -20
  60. package/dist/package-finalizer.d.ts.map +1 -1
  61. package/dist/resolve-asset-source.d.ts +1 -3
  62. package/dist/resolve-asset-source.d.ts.map +1 -1
  63. package/dist/resolve-asset-source.mjs +6 -81
  64. package/dist/resolve-asset-source.mjs.map +1 -1
  65. package/dist/runtime.mjs +77 -7
  66. package/dist/runtime.mjs.map +1 -1
  67. package/dist/scanner.d.ts +18 -7
  68. package/dist/scanner.d.ts.map +1 -1
  69. package/dist/scanner.mjs +1164 -687
  70. package/dist/scanner.mjs.map +1 -1
  71. package/dist/schema-compiled.d.ts.map +1 -1
  72. package/dist/schema.mjs +79 -7
  73. package/dist/schema.mjs.map +1 -1
  74. package/dist/scriptable-pack-node.d.ts +7 -31
  75. package/dist/scriptable-pack-node.d.ts.map +1 -1
  76. package/dist/scriptable-pack-node.mjs +572 -1019
  77. package/dist/scriptable-pack-node.mjs.map +1 -1
  78. package/dist/scriptable-pack-worker.mjs +29 -11
  79. package/dist/scriptable-pack-worker.mjs.map +1 -1
  80. package/dist/scriptable-pack.d.ts +20 -532
  81. package/dist/scriptable-pack.d.ts.map +1 -1
  82. package/dist/scriptable-pack.mjs +1038 -527
  83. package/dist/scriptable-pack.mjs.map +1 -1
  84. package/package.json +2 -7
  85. package/schema/meta.schema.json +1 -1
  86. package/schema/pack.schema.json +76 -6
  87. package/src/__tests__/guid-collision.unit.test.ts +18 -9
  88. package/src/__tests__/inventory-schema.test.ts +109 -0
  89. package/src/__tests__/material-cook-receipt-layer-plan.unit.test.ts +16 -0
  90. package/src/__tests__/material-cook-schema.unit.test.ts +62 -0
  91. package/src/__tests__/pack-authoring-gateway.unit.test.ts +249 -0
  92. package/src/__tests__/pack-authoring.unit.test.ts +266 -0
  93. package/src/__tests__/pack-scanner.unit.test.ts +123 -0
  94. package/src/__tests__/pack.unit.test.ts +1 -238
  95. package/src/__tests__/package-finalizer.contract.test.ts +55 -0
  96. package/src/__tests__/resolve-asset-source.test.ts +15 -98
  97. package/src/__tests__/scanner-blacklist.test.ts +55 -0
  98. package/src/__tests__/scanner-inventory.contract.test.ts +11 -14
  99. package/src/__tests__/scanner-inventory.test.ts +23 -10
  100. package/src/__tests__/scriptable-pack-cli.integration.test.ts +4 -9
  101. package/src/__tests__/topology.unit.test.ts +23 -0
  102. package/src/build.ts +28 -18
  103. package/src/catalog-builder.ts +60 -33
  104. package/src/cli-asset.ts +68 -83
  105. package/src/deriveAssetName.ts +14 -13
  106. package/src/evidence/material-cook.ts +79 -3
  107. package/src/evidence/source-inventory.ts +34 -21
  108. package/src/guid.ts +65 -4
  109. package/src/index.ts +15 -11
  110. package/src/inventory/binding.ts +25 -0
  111. package/src/inventory/declaration.ts +168 -0
  112. package/src/inventory/index.ts +18 -0
  113. package/src/inventory/sync.ts +22 -0
  114. package/src/material-cook.ts +1 -0
  115. package/src/pack-authoring-node.ts +1966 -0
  116. package/src/pack-authoring.ts +1478 -0
  117. package/src/package-finalizer.ts +2 -42
  118. package/src/resolve-asset-source.ts +4 -76
  119. package/src/scanner.ts +236 -56
  120. package/src/schema/material-cook.schema.json +4 -1
  121. package/src/schema-compiled.ts +2 -0
  122. package/src/scriptable-pack-node.ts +108 -719
  123. package/src/scriptable-pack-worker.ts +48 -16
  124. package/src/scriptable-pack.ts +28 -939
  125. package/dist/.tsbuildinfo +0 -1
  126. package/dist/__tests__/load-asset-config.test.d.ts +0 -2
  127. package/dist/__tests__/load-asset-config.test.d.ts.map +0 -1
  128. package/dist/__tests__/scriptable-pack.test-d.d.ts +0 -2
  129. package/dist/__tests__/scriptable-pack.test-d.d.ts.map +0 -1
  130. package/dist/__tests__/scriptable-pack.unit.test.d.ts +0 -2
  131. package/dist/__tests__/scriptable-pack.unit.test.d.ts.map +0 -1
  132. package/dist/config.d.ts +0 -6
  133. package/dist/config.d.ts.map +0 -1
  134. package/dist/config.mjs +0 -29
  135. package/dist/config.mjs.map +0 -1
  136. package/src/__tests__/load-asset-config.test.ts +0 -121
  137. package/src/__tests__/scriptable-pack.test-d.ts +0 -131
  138. package/src/__tests__/scriptable-pack.unit.test.ts +0 -789
  139. package/src/config.ts +0 -36
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { createHash } from 'crypto';
3
3
  import { realpath, readFile, mkdir, writeFile, mkdtemp, rm, stat, readdir } from 'fs/promises';
4
- import { isAbsolute, resolve, sep, basename, extname, dirname, join, posix } from 'path';
4
+ import { isAbsolute, resolve, sep, basename, extname, dirname, join } from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { parseArgs } from 'util';
7
- import { ok, err, IMAGE_ERROR_HINTS, projectCookProductEvidence, projectAssetEvidence, AssetError, ImportError, PACK_ERROR_HINTS, validateSourceOverrideMap } from '@forgeax/engine-types';
8
- import { existsSync, readFileSync } from 'fs';
7
+ import { err, ok, IMAGE_ERROR_HINTS, projectCookProductEvidence, projectAssetEvidence, AssetError, ImportError, PACK_ERROR_HINTS, validateSourceOverrideMap } from '@forgeax/engine-types';
8
+ import { sha1 } from '@noble/hashes/legacy.js';
9
9
  import { uuidv7obj } from 'uuidv7';
10
+ import { existsSync } from 'fs';
10
11
  import { tmpdir } from 'os';
11
12
  import { Worker } from 'worker_threads';
12
13
  import ts from 'typescript';
@@ -3627,49 +3628,49 @@ var require_fast_uri = __commonJS({
3627
3628
  schemelessOptions.skipEscape = true;
3628
3629
  return serialize(resolved, schemelessOptions);
3629
3630
  }
3630
- function resolveComponent(base, relative3, options, skipNormalization) {
3631
+ function resolveComponent(base, relative2, options, skipNormalization) {
3631
3632
  const target = {};
3632
3633
  if (!skipNormalization) {
3633
3634
  base = parse(serialize(base, options), options);
3634
- relative3 = parse(serialize(relative3, options), options);
3635
+ relative2 = parse(serialize(relative2, options), options);
3635
3636
  }
3636
3637
  options = options || {};
3637
- if (!options.tolerant && relative3.scheme) {
3638
- target.scheme = relative3.scheme;
3639
- target.userinfo = relative3.userinfo;
3640
- target.host = relative3.host;
3641
- target.port = relative3.port;
3642
- target.path = removeDotSegments(relative3.path || "");
3643
- target.query = relative3.query;
3638
+ if (!options.tolerant && relative2.scheme) {
3639
+ target.scheme = relative2.scheme;
3640
+ target.userinfo = relative2.userinfo;
3641
+ target.host = relative2.host;
3642
+ target.port = relative2.port;
3643
+ target.path = removeDotSegments(relative2.path || "");
3644
+ target.query = relative2.query;
3644
3645
  } else {
3645
- if (relative3.userinfo !== void 0 || relative3.host !== void 0 || relative3.port !== void 0) {
3646
- target.userinfo = relative3.userinfo;
3647
- target.host = relative3.host;
3648
- target.port = relative3.port;
3649
- target.path = removeDotSegments(relative3.path || "");
3650
- target.query = relative3.query;
3646
+ if (relative2.userinfo !== void 0 || relative2.host !== void 0 || relative2.port !== void 0) {
3647
+ target.userinfo = relative2.userinfo;
3648
+ target.host = relative2.host;
3649
+ target.port = relative2.port;
3650
+ target.path = removeDotSegments(relative2.path || "");
3651
+ target.query = relative2.query;
3651
3652
  } else {
3652
- if (!relative3.path) {
3653
+ if (!relative2.path) {
3653
3654
  target.path = base.path;
3654
- if (relative3.query !== void 0) {
3655
- target.query = relative3.query;
3655
+ if (relative2.query !== void 0) {
3656
+ target.query = relative2.query;
3656
3657
  } else {
3657
3658
  target.query = base.query;
3658
3659
  }
3659
3660
  } else {
3660
- if (relative3.path[0] === "/") {
3661
- target.path = removeDotSegments(relative3.path);
3661
+ if (relative2.path[0] === "/") {
3662
+ target.path = removeDotSegments(relative2.path);
3662
3663
  } else {
3663
3664
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
3664
- target.path = "/" + relative3.path;
3665
+ target.path = "/" + relative2.path;
3665
3666
  } else if (!base.path) {
3666
- target.path = relative3.path;
3667
+ target.path = relative2.path;
3667
3668
  } else {
3668
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative3.path;
3669
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
3669
3670
  }
3670
3671
  target.path = removeDotSegments(target.path);
3671
3672
  }
3672
- target.query = relative3.query;
3673
+ target.query = relative2.query;
3673
3674
  }
3674
3675
  target.userinfo = base.userinfo;
3675
3676
  target.host = base.host;
@@ -3677,7 +3678,7 @@ var require_fast_uri = __commonJS({
3677
3678
  }
3678
3679
  target.scheme = base.scheme;
3679
3680
  }
3680
- target.fragment = relative3.fragment;
3681
+ target.fragment = relative2.fragment;
3681
3682
  return target;
3682
3683
  }
3683
3684
  function equal(uriA, uriB, options) {
@@ -4716,8 +4717,8 @@ var require_multipleOf = __commonJS({
4716
4717
  const { gen, data, schemaCode, it } = cxt;
4717
4718
  const prec = it.opts.multipleOfPrecision;
4718
4719
  const res = gen.let("res");
4719
- const invalid2 = prec ? (0, codegen_1._)`Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}` : (0, codegen_1._)`${res} !== parseInt(${res})`;
4720
- cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid2}))`);
4720
+ const invalid = prec ? (0, codegen_1._)`Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}` : (0, codegen_1._)`${res} !== parseInt(${res})`;
4721
+ cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid}))`);
4721
4722
  }
4722
4723
  };
4723
4724
  exports.default = def;
@@ -7180,27 +7181,6 @@ function buildOfflineAssetEvidence(input) {
7180
7181
  };
7181
7182
  return Promise.resolve(projectAssetEvidence(evidenceInput));
7182
7183
  }
7183
- function loadAssetConfig(cwd) {
7184
- let pkg;
7185
- try {
7186
- pkg = JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"));
7187
- } catch {
7188
- return { roots: [join(cwd, "assets")], paths: {} };
7189
- }
7190
- const assets = pkg.forgeax?.assets;
7191
- const rawRoots = assets?.roots;
7192
- const roots = Array.isArray(rawRoots) && rawRoots.length > 0 ? rawRoots.map((r) => join(cwd, r)) : [join(cwd, "assets")];
7193
- const rawPaths = assets?.paths;
7194
- const paths = {};
7195
- if (rawPaths !== void 0 && rawPaths !== null && typeof rawPaths === "object") {
7196
- for (const [name, dir] of Object.entries(rawPaths)) {
7197
- if (typeof dir === "string") {
7198
- paths[name] = join(cwd, dir);
7199
- }
7200
- }
7201
- }
7202
- return { roots, paths };
7203
- }
7204
7184
 
7205
7185
  // src/errors.ts
7206
7186
  var PackError = class extends Error {
@@ -7217,6 +7197,8 @@ var PackError = class extends Error {
7217
7197
  this.detail = args.detail;
7218
7198
  }
7219
7199
  };
7200
+
7201
+ // src/guid.ts
7220
7202
  function brand(bytes) {
7221
7203
  return bytes;
7222
7204
  }
@@ -7226,6 +7208,10 @@ function bytesToDashForm(bytes) {
7226
7208
  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]]}`;
7227
7209
  }
7228
7210
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
7211
+ var PACK_SOURCE_KEY_RE = /^[a-z0-9][a-z0-9._-]*(\/[a-z0-9][a-z0-9._-]*)*$/;
7212
+ function isValidPackSourceKey(value) {
7213
+ return typeof value === "string" && PACK_SOURCE_KEY_RE.test(value);
7214
+ }
7229
7215
  function isValidAssetGuidString(value) {
7230
7216
  return typeof value === "string" && UUID_RE.test(value);
7231
7217
  }
@@ -7237,6 +7223,48 @@ function dashFormToBytes(dashForm) {
7237
7223
  }
7238
7224
  return bytes;
7239
7225
  }
7226
+ function randomUuidBytes() {
7227
+ const uuid = uuidv7obj();
7228
+ const bytes = new Uint8Array(16);
7229
+ bytes.set(uuid.bytes);
7230
+ return bytes;
7231
+ }
7232
+ function packageId(value) {
7233
+ return value;
7234
+ }
7235
+ var PackageId = {
7236
+ parse(dashForm) {
7237
+ const parsed = AssetGuid.parse(dashForm);
7238
+ return parsed.ok ? { ok: true, value: packageId(parsed.value) } : parsed;
7239
+ },
7240
+ format(value) {
7241
+ return bytesToDashForm(value);
7242
+ },
7243
+ random() {
7244
+ return packageId(randomUuidBytes());
7245
+ }
7246
+ };
7247
+ function derivedGuid(namespace, sourceKey) {
7248
+ if (!(namespace instanceof Uint8Array) || namespace.byteLength !== 16) {
7249
+ throw new TypeError("AssetGuid.derive requires a 16-byte PackageId");
7250
+ }
7251
+ if (!isValidPackSourceKey(sourceKey)) {
7252
+ const error = new TypeError(
7253
+ `AssetGuid.derive received invalid sourceKey ${JSON.stringify(sourceKey)}`
7254
+ );
7255
+ Object.defineProperty(error, "code", { value: "pack-source-key-invalid" });
7256
+ throw error;
7257
+ }
7258
+ const name = new TextEncoder().encode(sourceKey);
7259
+ const input = new Uint8Array(namespace.byteLength + name.byteLength);
7260
+ input.set(namespace, 0);
7261
+ input.set(name, namespace.byteLength);
7262
+ const digest = sha1(input);
7263
+ const result = digest.slice(0, 16);
7264
+ result[6] = (result[6] ?? 0) & 15 | 80;
7265
+ result[8] = (result[8] ?? 0) & 63 | 128;
7266
+ return brand(result);
7267
+ }
7240
7268
  var AssetGuid = {
7241
7269
  /**
7242
7270
  * Parse a 36-char RFC 4122 dash-form UUID string into an AssetGuid.
@@ -7280,19 +7308,760 @@ var AssetGuid = {
7280
7308
  * Works in both Node.js and browser environments.
7281
7309
  */
7282
7310
  random() {
7283
- const uuid = uuidv7obj();
7284
- const bytes = new Uint8Array(16);
7285
- bytes.set(uuid.bytes);
7286
- return brand(bytes);
7311
+ return brand(randomUuidBytes());
7312
+ },
7313
+ /** Derive the stable UUIDv5 projection for one Pack subject and sourceKey. */
7314
+ derive(namespace, sourceKey) {
7315
+ return derivedGuid(namespace, sourceKey);
7287
7316
  }
7288
7317
  };
7318
+
7319
+ // src/pack-authoring.ts
7320
+ var PACK_PARAMETER_TYPES = [
7321
+ "bool",
7322
+ "u32",
7323
+ "i32",
7324
+ "f32",
7325
+ "f64",
7326
+ "string",
7327
+ "enum",
7328
+ "vec2",
7329
+ "vec3",
7330
+ "vec4",
7331
+ "color",
7332
+ "asset-guid"
7333
+ ];
7334
+ function authoringError(code, expected, hint, detail = {}, actual) {
7335
+ return {
7336
+ code,
7337
+ expected,
7338
+ hint,
7339
+ ...actual === void 0 ? {} : { actual },
7340
+ detail
7341
+ };
7342
+ }
7343
+ function failure(error) {
7344
+ return err(error);
7345
+ }
7289
7346
  function isRecord(value) {
7347
+ return value !== null && typeof value === "object" && !Array.isArray(value);
7348
+ }
7349
+ function validateSceneComponents(value) {
7350
+ if (value === void 0) return ok(void 0);
7351
+ if (!Array.isArray(value)) {
7352
+ return failure(
7353
+ parameterFailure(
7354
+ "$.sceneComponents",
7355
+ "an array of component schema records",
7356
+ value,
7357
+ "sceneComponents is not an array"
7358
+ )
7359
+ );
7360
+ }
7361
+ const components = [];
7362
+ const names = /* @__PURE__ */ new Set();
7363
+ for (const [componentIndex, candidate] of value.entries()) {
7364
+ if (!isRecord(candidate) || typeof candidate.name !== "string" || !isRecord(candidate.fields)) {
7365
+ return failure(
7366
+ parameterFailure(
7367
+ `$.sceneComponents[${componentIndex}]`,
7368
+ "a component record with name and fields",
7369
+ candidate,
7370
+ "scene component schema is malformed"
7371
+ )
7372
+ );
7373
+ }
7374
+ if (candidate.name.length === 0 || names.has(candidate.name)) {
7375
+ return failure(
7376
+ parameterFailure(
7377
+ `$.sceneComponents[${componentIndex}].name`,
7378
+ "a non-empty unique component name",
7379
+ candidate.name,
7380
+ "scene component names must be unique"
7381
+ )
7382
+ );
7383
+ }
7384
+ names.add(candidate.name);
7385
+ const fields = {};
7386
+ for (const [fieldName, field] of Object.entries(candidate.fields)) {
7387
+ if (typeof field === "string" && field.length === 0 || typeof field !== "string" && (!isRecord(field) || typeof field.type !== "string" || field.type.length === 0)) {
7388
+ return failure(
7389
+ parameterFailure(
7390
+ `$.sceneComponents[${componentIndex}].fields.${fieldName}`,
7391
+ "a field type string or { type: string }",
7392
+ field,
7393
+ "scene component field schema is malformed"
7394
+ )
7395
+ );
7396
+ }
7397
+ fields[fieldName] = field;
7398
+ }
7399
+ components.push({ name: candidate.name, fields });
7400
+ }
7401
+ return ok(components);
7402
+ }
7403
+ function isPackageId(value) {
7404
+ return value instanceof Uint8Array && value.byteLength === 16;
7405
+ }
7406
+ function cloneValue(value) {
7407
+ if (value instanceof Uint8Array) return value.slice();
7408
+ if (Array.isArray(value)) return value.map((item) => cloneValue(item));
7409
+ return value;
7410
+ }
7411
+ function sourceKeyFailure(sourceKey, propertyPath = "$.sourceKey") {
7412
+ return authoringError(
7413
+ "pack-source-key-invalid",
7414
+ "a sourceKey matching ^[a-z0-9][a-z0-9._-]*(/[a-z0-9][a-z0-9._-]*)*$",
7415
+ "use a stable lower-case semantic key; do not derive it from file paths or output order",
7416
+ { propertyPath, sourceKey },
7417
+ typeof sourceKey === "string" ? sourceKey : void 0
7418
+ );
7419
+ }
7420
+ function parameterFailure(propertyPath, expected, actual, reason) {
7421
+ return authoringError(
7422
+ "pack-parameter-invalid",
7423
+ expected,
7424
+ "repair the parameter declaration or the instance values, then inspect and rebuild",
7425
+ { propertyPath, reason, actual: typeof actual === "string" ? actual : JSON.stringify(actual) }
7426
+ );
7427
+ }
7428
+ function numericType(type) {
7429
+ return type === "u32" || type === "i32" || type === "f32" || type === "f64";
7430
+ }
7431
+ function vectorLength(type) {
7432
+ switch (type) {
7433
+ case "vec2":
7434
+ return 2;
7435
+ case "vec3":
7436
+ return 3;
7437
+ case "vec4":
7438
+ case "color":
7439
+ return 4;
7440
+ default:
7441
+ return void 0;
7442
+ }
7443
+ }
7444
+ function parameterValueError(parameter, value, propertyPath) {
7445
+ const { type } = parameter;
7446
+ if (type === "bool" && typeof value !== "boolean") {
7447
+ return parameterFailure(propertyPath, "a boolean", value, "bool value has the wrong type");
7448
+ }
7449
+ if (numericType(type)) {
7450
+ if (typeof value !== "number" || !Number.isFinite(value)) {
7451
+ return parameterFailure(
7452
+ propertyPath,
7453
+ "a finite number",
7454
+ value,
7455
+ "numeric value is not finite"
7456
+ );
7457
+ }
7458
+ if ((type === "u32" || type === "i32") && !Number.isInteger(value)) {
7459
+ return parameterFailure(
7460
+ propertyPath,
7461
+ "an integer",
7462
+ value,
7463
+ "integer parameter received a fraction"
7464
+ );
7465
+ }
7466
+ if (type === "u32" && (value < 0 || value > 4294967295)) {
7467
+ return parameterFailure(
7468
+ propertyPath,
7469
+ "an unsigned 32-bit integer",
7470
+ value,
7471
+ "u32 value is outside [0, 2^32 - 1]"
7472
+ );
7473
+ }
7474
+ if (type === "i32" && (value < -2147483648 || value > 2147483647)) {
7475
+ return parameterFailure(
7476
+ propertyPath,
7477
+ "a signed 32-bit integer",
7478
+ value,
7479
+ "i32 value is outside [-2^31, 2^31 - 1]"
7480
+ );
7481
+ }
7482
+ if (type === "f32" && !Number.isFinite(Math.fround(value))) {
7483
+ return parameterFailure(
7484
+ propertyPath,
7485
+ "a finite IEEE-754 32-bit float",
7486
+ value,
7487
+ "f32 value overflows binary32"
7488
+ );
7489
+ }
7490
+ if (parameter.minimum !== void 0 && value < parameter.minimum) {
7491
+ return parameterFailure(
7492
+ propertyPath,
7493
+ `a number >= ${parameter.minimum}`,
7494
+ value,
7495
+ "value is below minimum"
7496
+ );
7497
+ }
7498
+ if (parameter.maximum !== void 0 && value > parameter.maximum) {
7499
+ return parameterFailure(
7500
+ propertyPath,
7501
+ `a number <= ${parameter.maximum}`,
7502
+ value,
7503
+ "value is above maximum"
7504
+ );
7505
+ }
7506
+ return void 0;
7507
+ }
7508
+ if (type === "string" && typeof value !== "string") {
7509
+ return parameterFailure(propertyPath, "a string", value, "string parameter has the wrong type");
7510
+ }
7511
+ if (type === "enum") {
7512
+ if (typeof value !== "string") {
7513
+ return parameterFailure(
7514
+ propertyPath,
7515
+ "one of the declared enum strings",
7516
+ value,
7517
+ "enum value has the wrong type"
7518
+ );
7519
+ }
7520
+ if (parameter.values === void 0 || !parameter.values.includes(value)) {
7521
+ return parameterFailure(
7522
+ propertyPath,
7523
+ "one of the declared enum values",
7524
+ value,
7525
+ "enum value is not declared"
7526
+ );
7527
+ }
7528
+ return void 0;
7529
+ }
7530
+ const length = vectorLength(type);
7531
+ if (length !== void 0) {
7532
+ if (!Array.isArray(value) || value.length !== length || value.some((component) => typeof component !== "number" || !Number.isFinite(component))) {
7533
+ return parameterFailure(
7534
+ propertyPath,
7535
+ `a finite numeric vector with ${length} components`,
7536
+ value,
7537
+ "vector value has the wrong shape"
7538
+ );
7539
+ }
7540
+ if (type === "color" && value.some((component) => component < 0 || component > 1)) {
7541
+ return parameterFailure(
7542
+ propertyPath,
7543
+ "an RGBA color with components in [0, 1]",
7544
+ value,
7545
+ "color component is outside [0, 1]"
7546
+ );
7547
+ }
7548
+ return void 0;
7549
+ }
7550
+ if (type === "asset-guid") {
7551
+ const validString = typeof value === "string" && isValidAssetGuidString(value);
7552
+ if (!(value instanceof Uint8Array && value.byteLength === 16) && !validString) {
7553
+ return parameterFailure(
7554
+ propertyPath,
7555
+ "a 16-byte AssetGuid or UUID string",
7556
+ value,
7557
+ "asset GUID value is malformed"
7558
+ );
7559
+ }
7560
+ return void 0;
7561
+ }
7562
+ return parameterFailure(
7563
+ propertyPath,
7564
+ "a supported Pack parameter type",
7565
+ value,
7566
+ "unknown parameter type"
7567
+ );
7568
+ }
7569
+ function normalizeParameterValue(parameter, value, propertyPath) {
7570
+ const error = parameterValueError(parameter, value, propertyPath);
7571
+ if (error !== void 0) return failure(error);
7572
+ if (parameter.type === "asset-guid" && typeof value === "string") {
7573
+ const parsed = AssetGuid.parse(value);
7574
+ if (!parsed.ok) {
7575
+ return failure(
7576
+ parameterFailure(
7577
+ propertyPath,
7578
+ "a valid AssetGuid UUID string",
7579
+ value,
7580
+ "asset GUID parser rejected the value"
7581
+ )
7582
+ );
7583
+ }
7584
+ return ok(parsed.value);
7585
+ }
7586
+ return ok(cloneValue(value));
7587
+ }
7588
+ function validateParameterDefinitions(parameters, propertyPath = "$.parameters") {
7589
+ if (!Array.isArray(parameters) || parameters.length === 0) {
7590
+ return failure(
7591
+ parameterFailure(
7592
+ propertyPath,
7593
+ "a non-empty parameter descriptor array",
7594
+ parameters,
7595
+ "parameters must be explicit and non-empty"
7596
+ )
7597
+ );
7598
+ }
7599
+ const names = /* @__PURE__ */ new Set();
7600
+ const normalized = [];
7601
+ for (const [index, candidate] of parameters.entries()) {
7602
+ const path = `${propertyPath}[${index}]`;
7603
+ if (!isRecord(candidate))
7604
+ return failure(
7605
+ parameterFailure(
7606
+ path,
7607
+ "a parameter descriptor object",
7608
+ candidate,
7609
+ "descriptor is not an object"
7610
+ )
7611
+ );
7612
+ const name = candidate.name;
7613
+ if (typeof name !== "string" || !/^[A-Za-z][A-Za-z0-9_.-]*$/.test(name)) {
7614
+ return failure(
7615
+ parameterFailure(
7616
+ `${path}.name`,
7617
+ "a unique identifier-like parameter name",
7618
+ name,
7619
+ "parameter name is invalid"
7620
+ )
7621
+ );
7622
+ }
7623
+ if (names.has(name))
7624
+ return failure(
7625
+ parameterFailure(
7626
+ `${path}.name`,
7627
+ "a unique parameter name",
7628
+ name,
7629
+ "parameter name is duplicated"
7630
+ )
7631
+ );
7632
+ names.add(name);
7633
+ const unknown = Object.keys(candidate).find(
7634
+ (key) => !["name", "type", "default", "minimum", "maximum", "values", "kind"].includes(key)
7635
+ );
7636
+ if (unknown !== void 0) {
7637
+ return failure(
7638
+ parameterFailure(
7639
+ `${path}.${unknown}`,
7640
+ "only name, type, default, minimum, maximum, values, and kind fields",
7641
+ candidate[unknown],
7642
+ "parameter descriptors are a closed authoring schema"
7643
+ )
7644
+ );
7645
+ }
7646
+ const type = candidate.type;
7647
+ if (typeof type !== "string" || !PACK_PARAMETER_TYPES.includes(type)) {
7648
+ return failure(
7649
+ parameterFailure(
7650
+ `${path}.type`,
7651
+ PACK_PARAMETER_TYPES.join(" | "),
7652
+ type,
7653
+ "parameter type is not supported"
7654
+ )
7655
+ );
7656
+ }
7657
+ const typed = {
7658
+ ...candidate,
7659
+ name,
7660
+ type
7661
+ };
7662
+ if (typed.values !== void 0) {
7663
+ 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) {
7664
+ return failure(
7665
+ parameterFailure(
7666
+ `${path}.values`,
7667
+ "unique non-empty strings for enum",
7668
+ typed.values,
7669
+ "enum values are malformed"
7670
+ )
7671
+ );
7672
+ }
7673
+ } else if (typed.type === "enum") {
7674
+ return failure(
7675
+ parameterFailure(
7676
+ `${path}.values`,
7677
+ "a non-empty enum choices array",
7678
+ typed.values,
7679
+ "enum has no choices"
7680
+ )
7681
+ );
7682
+ }
7683
+ if (typed.kind !== void 0 && (typed.type !== "asset-guid" || typeof typed.kind !== "string")) {
7684
+ return failure(
7685
+ parameterFailure(
7686
+ `${path}.kind`,
7687
+ "a kind constraint only on asset-guid parameters",
7688
+ typed.kind,
7689
+ "kind is misplaced"
7690
+ )
7691
+ );
7692
+ }
7693
+ for (const field of ["minimum", "maximum"]) {
7694
+ const bound = typed[field];
7695
+ if (bound !== void 0 && (typeof bound !== "number" || !Number.isFinite(bound))) {
7696
+ return failure(
7697
+ parameterFailure(
7698
+ `${path}.${field}`,
7699
+ "a finite numeric bound",
7700
+ bound,
7701
+ "numeric bound is invalid"
7702
+ )
7703
+ );
7704
+ }
7705
+ }
7706
+ if (!numericType(typed.type) && (typed.minimum !== void 0 || typed.maximum !== void 0)) {
7707
+ return failure(
7708
+ parameterFailure(
7709
+ path,
7710
+ "minimum/maximum only on numeric parameters",
7711
+ typed,
7712
+ "numeric bounds are not meaningful for this parameter type"
7713
+ )
7714
+ );
7715
+ }
7716
+ if (typed.minimum !== void 0 && typed.maximum !== void 0 && typed.minimum > typed.maximum) {
7717
+ return failure(
7718
+ parameterFailure(path, "minimum <= maximum", typed, "numeric bounds are reversed")
7719
+ );
7720
+ }
7721
+ const defaultResult = normalizeParameterValue(typed, typed.default, `${path}.default`);
7722
+ if (!defaultResult.ok) return defaultResult;
7723
+ normalized.push({
7724
+ ...typed,
7725
+ default: defaultResult.value,
7726
+ ...typed.values === void 0 ? {} : { values: Object.freeze([...typed.values]) }
7727
+ });
7728
+ }
7729
+ return ok(Object.freeze(normalized));
7730
+ }
7731
+ function projectScriptablePackMeta(definition, sourcePath) {
7732
+ return {
7733
+ schemaVersion: "2.0.0",
7734
+ kind: "scriptable-pack-source",
7735
+ packageId: PackageId.format(definition.packageId),
7736
+ source: sourcePath,
7737
+ ..."parameters" in definition ? {
7738
+ parameters: definition.parameters.map((parameter) => ({
7739
+ name: parameter.name,
7740
+ type: parameter.type,
7741
+ default: jsonParameterValue(parameter.default),
7742
+ ...parameter.minimum === void 0 ? {} : { minimum: parameter.minimum },
7743
+ ...parameter.maximum === void 0 ? {} : { maximum: parameter.maximum },
7744
+ ...parameter.values === void 0 ? {} : { values: parameter.values },
7745
+ ...parameter.kind === void 0 ? {} : { kind: parameter.kind }
7746
+ }))
7747
+ } : {}
7748
+ };
7749
+ }
7750
+ function jsonParameterValue(value) {
7751
+ return value instanceof Uint8Array ? AssetGuid.format(value) : value;
7752
+ }
7753
+ function validatePackDefinition(value, sourcePath) {
7754
+ if (!isRecord(value))
7755
+ return failure(
7756
+ parameterFailure("$", "a Pack definition object", value, "definition is not an object")
7757
+ );
7758
+ const unknown = Object.keys(value).find(
7759
+ (key) => !["schemaVersion", "packageId", "name", "parameters", "sceneComponents", "build"].includes(
7760
+ key
7761
+ )
7762
+ );
7763
+ if (unknown !== void 0) {
7764
+ return failure(
7765
+ parameterFailure(
7766
+ `$.${unknown}`,
7767
+ "only schemaVersion, packageId, name, parameters, sceneComponents, and build fields",
7768
+ value[unknown],
7769
+ "legacy static output declarations and external asset tables are not part of v2 authoring"
7770
+ )
7771
+ );
7772
+ }
7773
+ if (value.schemaVersion !== "2.0.0") {
7774
+ return failure(
7775
+ parameterFailure(
7776
+ "$.schemaVersion",
7777
+ "the literal '2.0.0'",
7778
+ value.schemaVersion,
7779
+ "authoring source schema is unsupported"
7780
+ )
7781
+ );
7782
+ }
7783
+ if (!isPackageId(value.packageId)) {
7784
+ return failure(
7785
+ authoringError(
7786
+ "pack-package-id-invalid",
7787
+ "a 16-byte PackageId",
7788
+ "use definePackageId() for the stable source identity",
7789
+ { sourcePath, propertyPath: "$.packageId" },
7790
+ typeof value.packageId === "string" ? value.packageId : void 0
7791
+ )
7792
+ );
7793
+ }
7794
+ if (value.name !== void 0 && typeof value.name !== "string") {
7795
+ return failure(
7796
+ parameterFailure("$.name", "a string when present", value.name, "display name is malformed")
7797
+ );
7798
+ }
7799
+ if (typeof value.build !== "function") {
7800
+ return failure(
7801
+ parameterFailure("$.build", "a build function", value.build, "build is not callable")
7802
+ );
7803
+ }
7804
+ const sceneComponents = validateSceneComponents(value.sceneComponents);
7805
+ if (!sceneComponents.ok) return sceneComponents;
7806
+ const hasParameters = Object.hasOwn(value, "parameters");
7807
+ if (!hasParameters) {
7808
+ return ok(
7809
+ Object.freeze({
7810
+ schemaVersion: "2.0.0",
7811
+ packageId: value.packageId,
7812
+ ...value.name === void 0 ? {} : { name: value.name },
7813
+ ...sceneComponents.value === void 0 ? {} : { sceneComponents: sceneComponents.value },
7814
+ build: value.build
7815
+ })
7816
+ );
7817
+ }
7818
+ const parameters = validateParameterDefinitions(value.parameters);
7819
+ if (!parameters.ok) return parameters;
7820
+ return ok(
7821
+ Object.freeze({
7822
+ schemaVersion: "2.0.0",
7823
+ packageId: value.packageId,
7824
+ ...value.name === void 0 ? {} : { name: value.name },
7825
+ ...sceneComponents.value === void 0 ? {} : { sceneComponents: sceneComponents.value },
7826
+ parameters: parameters.value,
7827
+ build: value.build
7828
+ })
7829
+ );
7830
+ }
7831
+ function jsonError(propertyPath, expected, actual, reason) {
7832
+ return failure(
7833
+ authoringError(
7834
+ "pack-parameter-invalid",
7835
+ expected,
7836
+ "repair the v3 pack.json authoring data, then rerun scan or rebuild",
7837
+ {
7838
+ propertyPath,
7839
+ reason,
7840
+ actual: typeof actual === "string" ? actual : JSON.stringify(actual)
7841
+ }
7842
+ )
7843
+ );
7844
+ }
7845
+ function parsePackageId(value, propertyPath) {
7846
+ if (typeof value !== "string") {
7847
+ return failure(
7848
+ authoringError(
7849
+ "pack-package-id-invalid",
7850
+ "a UUID string",
7851
+ "repair packageId in the authoring file",
7852
+ { propertyPath, value }
7853
+ )
7854
+ );
7855
+ }
7856
+ const parsed = PackageId.parse(value);
7857
+ if (!parsed.ok) {
7858
+ return failure(
7859
+ authoringError(
7860
+ "pack-package-id-invalid",
7861
+ "a 36-character RFC 4122 UUID",
7862
+ "repair packageId or use the authoring gateway to mint one",
7863
+ { propertyPath, value },
7864
+ value
7865
+ )
7866
+ );
7867
+ }
7868
+ return ok(parsed.value);
7869
+ }
7870
+ function parsePackJsonAsset(value, sourceKey) {
7871
+ if (!isRecord(value))
7872
+ return jsonError(
7873
+ `$.assets.${sourceKey}`,
7874
+ "an asset entry object",
7875
+ value,
7876
+ "asset entry is not an object"
7877
+ );
7878
+ const allowed = /* @__PURE__ */ new Set(["kind", "payload", "refs", "name", "artifacts"]);
7879
+ const unknown = Object.keys(value).find((key) => !allowed.has(key));
7880
+ if (unknown !== void 0)
7881
+ return jsonError(
7882
+ `$.assets.${sourceKey}.${unknown}`,
7883
+ "no GUID or extra authoring field",
7884
+ value[unknown],
7885
+ "direct v3 entries derive identity from their object key"
7886
+ );
7887
+ if (typeof value.kind !== "string" || value.kind.length === 0)
7888
+ return jsonError(
7889
+ `$.assets.${sourceKey}.kind`,
7890
+ "a non-empty asset kind",
7891
+ value.kind,
7892
+ "asset kind is missing"
7893
+ );
7894
+ if (!isRecord(value.payload))
7895
+ return jsonError(
7896
+ `$.assets.${sourceKey}.payload`,
7897
+ "a JSON object payload",
7898
+ value.payload,
7899
+ "payload must be a plain object"
7900
+ );
7901
+ if (!Array.isArray(value.refs) || value.refs.some((ref) => typeof ref !== "string" || !isValidAssetGuidString(ref))) {
7902
+ return jsonError(
7903
+ `$.assets.${sourceKey}.refs`,
7904
+ "an array of UUID references",
7905
+ value.refs,
7906
+ "references must already be real AssetGuids"
7907
+ );
7908
+ }
7909
+ if (value.name !== void 0 && (typeof value.name !== "string" || value.name.length === 0))
7910
+ return jsonError(
7911
+ `$.assets.${sourceKey}.name`,
7912
+ "a non-empty display name when present",
7913
+ value.name,
7914
+ "asset name is malformed"
7915
+ );
7916
+ if (value.artifacts !== void 0 && !isRecord(value.artifacts))
7917
+ return jsonError(
7918
+ `$.assets.${sourceKey}.artifacts`,
7919
+ "an artifact descriptor object when present",
7920
+ value.artifacts,
7921
+ "artifacts are not an object"
7922
+ );
7923
+ const base = {
7924
+ kind: value.kind,
7925
+ payload: value.payload,
7926
+ refs: Object.freeze([...value.refs]),
7927
+ ...value.name === void 0 ? {} : { name: value.name }
7928
+ };
7929
+ if (value.artifacts === void 0) return ok(base);
7930
+ const withArtifacts = {
7931
+ ...base,
7932
+ artifacts: value.artifacts
7933
+ };
7934
+ return ok(withArtifacts);
7935
+ }
7936
+ function parsePackSourceJson(value) {
7937
+ if (!isRecord(value))
7938
+ return jsonError("$", "a v3 pack.json object", value, "document is not an object");
7939
+ if (value.schemaVersion !== "3.0.0")
7940
+ return jsonError(
7941
+ "$.schemaVersion",
7942
+ "the literal '3.0.0'",
7943
+ value.schemaVersion,
7944
+ "document schema is not v3"
7945
+ );
7946
+ const unknown = Object.keys(value).find(
7947
+ (key) => !["schemaVersion", "packageId", "assets", "parent", "values"].includes(key)
7948
+ );
7949
+ if (unknown !== void 0)
7950
+ return jsonError(
7951
+ `$.${unknown}`,
7952
+ "no extra top-level authoring fields",
7953
+ value[unknown],
7954
+ "keep the v3 document to packageId+assets or packageId+parent+values"
7955
+ );
7956
+ const packageResult = parsePackageId(value.packageId, "$.packageId");
7957
+ if (!packageResult.ok) return packageResult;
7958
+ const hasAssets = Object.hasOwn(value, "assets");
7959
+ const hasParent = Object.hasOwn(value, "parent");
7960
+ const hasValues = Object.hasOwn(value, "values");
7961
+ if (hasAssets && (hasParent || hasValues))
7962
+ return jsonError(
7963
+ "$",
7964
+ "assets or parent+values, never both",
7965
+ value,
7966
+ "direct and instance branches are mutually exclusive"
7967
+ );
7968
+ if (hasAssets) {
7969
+ if (!isRecord(value.assets))
7970
+ return jsonError(
7971
+ "$.assets",
7972
+ "a sourceKey to asset object",
7973
+ value.assets,
7974
+ "direct assets are not an object"
7975
+ );
7976
+ const assets = {};
7977
+ for (const [sourceKey, entry] of Object.entries(value.assets)) {
7978
+ if (!isValidPackSourceKey(sourceKey))
7979
+ return failure(sourceKeyFailure(sourceKey, `$.assets.${sourceKey}`));
7980
+ const parsed = parsePackJsonAsset(entry, sourceKey);
7981
+ if (!parsed.ok) return parsed;
7982
+ assets[sourceKey] = parsed.value;
7983
+ }
7984
+ return ok({
7985
+ format: "direct",
7986
+ schemaVersion: "3.0.0",
7987
+ packageId: packageResult.value,
7988
+ assets: Object.freeze(assets)
7989
+ });
7990
+ }
7991
+ if (!hasParent || !hasValues || hasAssets)
7992
+ return jsonError(
7993
+ "$",
7994
+ "parent and values for an instance document",
7995
+ value,
7996
+ "instance branch is incomplete"
7997
+ );
7998
+ const parentResult = parsePackageId(value.parent, "$.parent");
7999
+ if (!parentResult.ok) return parentResult;
8000
+ if (!isRecord(value.values))
8001
+ return jsonError(
8002
+ "$.values",
8003
+ "a sparse parameter object",
8004
+ value.values,
8005
+ "instance values are not an object"
8006
+ );
8007
+ return ok({
8008
+ format: "instance",
8009
+ schemaVersion: "3.0.0",
8010
+ packageId: packageResult.value,
8011
+ parent: parentResult.value,
8012
+ values: Object.freeze({ ...value.values })
8013
+ });
8014
+ }
8015
+ function projectDirectPackJson(value) {
8016
+ const parsed = "format" in value ? ok(value) : parsePackSourceJson(value);
8017
+ if (!parsed.ok) return parsed;
8018
+ if (parsed.value.format !== "direct") {
8019
+ return failure(
8020
+ authoringError(
8021
+ "pack-parameter-invalid",
8022
+ "a direct v3 pack.json",
8023
+ "projectDirectPackJson accepts the direct branch only",
8024
+ { observed: parsed.value.format }
8025
+ )
8026
+ );
8027
+ }
8028
+ const assets = [];
8029
+ for (const [sourceKey, entry] of Object.entries(parsed.value.assets).sort(
8030
+ ([left], [right]) => left.localeCompare(right)
8031
+ )) {
8032
+ assets.push({
8033
+ ...entry,
8034
+ guid: AssetGuid.format(AssetGuid.derive(parsed.value.packageId, sourceKey)),
8035
+ sourceKey
8036
+ });
8037
+ }
8038
+ return ok({ packageId: PackageId.format(parsed.value.packageId), assets: Object.freeze(assets) });
8039
+ }
8040
+ var PACK_AUTHORING_OPERATION_IDS = [
8041
+ "asset.list",
8042
+ "asset.inspect",
8043
+ "asset.resolve",
8044
+ "asset.verify",
8045
+ "asset-source.create",
8046
+ "asset-source.clone",
8047
+ "asset-source.create-instance",
8048
+ "asset-source.apply-values",
8049
+ "asset-source.rebuild",
8050
+ "asset-source.cold-cook"
8051
+ ];
8052
+ PACK_AUTHORING_OPERATION_IDS.map((id) => ({
8053
+ id,
8054
+ domain: id.startsWith("asset-source.") ? "session" : "asset",
8055
+ readOnly: id.startsWith("asset."),
8056
+ requiresRevision: !id.startsWith("asset.") && id !== "asset-source.create"
8057
+ }));
8058
+ function isRecord2(value) {
7290
8059
  return typeof value === "object" && value !== null && !Array.isArray(value);
7291
8060
  }
7292
8061
  function hasText(value) {
7293
8062
  return typeof value === "string" && value.length > 0;
7294
8063
  }
7295
- function issue(code, subjectId, expected, hint, actual2, authority = "producer") {
8064
+ function issue(code, subjectId, expected, hint, actual, authority = "producer") {
7296
8065
  const subject = { type: "asset", id: subjectId };
7297
8066
  return {
7298
8067
  ok: false,
@@ -7300,7 +8069,7 @@ function issue(code, subjectId, expected, hint, actual2, authority = "producer")
7300
8069
  code,
7301
8070
  subject,
7302
8071
  expected,
7303
- ...actual2 === void 0 ? {} : { actual: actual2 },
8072
+ ...actual === void 0 ? {} : { actual },
7304
8073
  hint,
7305
8074
  authority
7306
8075
  }
@@ -7317,7 +8086,7 @@ function validateFacts(value, subjectId) {
7317
8086
  }
7318
8087
  if ("provenance" in value) {
7319
8088
  const provenance = value.provenance;
7320
- if (!isRecord(provenance) || !hasText(provenance.provider) || !hasText(provenance.version)) {
8089
+ if (!isRecord2(provenance) || !hasText(provenance.provider) || !hasText(provenance.version)) {
7321
8090
  return issue(
7322
8091
  "invalid-producer-fact",
7323
8092
  subjectId,
@@ -7328,7 +8097,7 @@ function validateFacts(value, subjectId) {
7328
8097
  }
7329
8098
  if ("revision" in value) {
7330
8099
  const revision = value.revision;
7331
- if (!isRecord(revision) || !hasText(revision.digest) || !hasText(revision.rootId) || typeof revision.observedAt !== "number" || !Number.isFinite(revision.observedAt)) {
8100
+ if (!isRecord2(revision) || !hasText(revision.digest) || !hasText(revision.rootId) || typeof revision.observedAt !== "number" || !Number.isFinite(revision.observedAt)) {
7332
8101
  return issue(
7333
8102
  "invalid-producer-fact",
7334
8103
  subjectId,
@@ -7347,7 +8116,7 @@ function validateFacts(value, subjectId) {
7347
8116
  );
7348
8117
  }
7349
8118
  for (const diagnostic of value.diagnostics) {
7350
- if (!isRecord(diagnostic) || !hasText(diagnostic.code)) {
8119
+ if (!isRecord2(diagnostic) || !hasText(diagnostic.code)) {
7351
8120
  return issue(
7352
8121
  "invalid-producer-fact",
7353
8122
  subjectId,
@@ -7356,7 +8125,7 @@ function validateFacts(value, subjectId) {
7356
8125
  );
7357
8126
  }
7358
8127
  if (diagnostic.severity === "blocking") {
7359
- if (!isRecord(diagnostic.subject) || !hasText(diagnostic.subject.id)) {
8128
+ if (!isRecord2(diagnostic.subject) || !hasText(diagnostic.subject.id)) {
7360
8129
  return issue(
7361
8130
  "invalid-producer-fact",
7362
8131
  subjectId,
@@ -7380,7 +8149,7 @@ function validateFacts(value, subjectId) {
7380
8149
  function validateMetaSourceOverrides(value, subjectId) {
7381
8150
  if (!("sourceOverrides" in value)) return { ok: true, value };
7382
8151
  const declaredSourceKeys = Array.isArray(value.subAssets) ? value.subAssets.flatMap(
7383
- (subAsset) => isRecord(subAsset) && hasText(subAsset.sourceKey) ? [subAsset.sourceKey] : []
8152
+ (subAsset) => isRecord2(subAsset) && hasText(subAsset.sourceKey) ? [subAsset.sourceKey] : []
7384
8153
  ) : [];
7385
8154
  const result = validateSourceOverrideMap(value.sourceOverrides, declaredSourceKeys);
7386
8155
  if (!result.ok) {
@@ -7399,7 +8168,7 @@ function validateMetaSourceOverrides(value, subjectId) {
7399
8168
  };
7400
8169
  }
7401
8170
  function validateProducerContract(value) {
7402
- if (!isRecord(value)) {
8171
+ if (!isRecord2(value)) {
7403
8172
  return issue(
7404
8173
  "invalid-producer-fact",
7405
8174
  "unknown",
@@ -7501,83 +8270,25 @@ function baseName(p) {
7501
8270
  const idx = Math.max(trimmed.lastIndexOf("/"), trimmed.lastIndexOf("\\"));
7502
8271
  return idx === -1 ? trimmed : trimmed.slice(idx + 1);
7503
8272
  }
7504
- function deriveAssetName(packagePath2, assetCount, storedName) {
8273
+ function deriveAssetName(packagePath2, _assetCount, storedName) {
7505
8274
  if (packagePath2 === null) {
7506
8275
  return "";
7507
8276
  }
7508
- {
7509
- return baseName(packagePath2);
7510
- }
8277
+ return baseName(packagePath2);
7511
8278
  }
7512
8279
 
7513
8280
  // src/resolve-asset-source.ts
7514
8281
  function deriveSourceName(metaFileName) {
7515
8282
  return metaFileName.replace(/\.meta\.json$/, "");
7516
8283
  }
7517
- var PATH_REF_RE = /^@([^/]+)\/(.+)$/;
7518
- function isPathEscape(pathDir, resolved) {
7519
- const rel = posix.relative(pathDir, resolved);
7520
- return rel.startsWith("..") || posix.isAbsolute(rel);
7521
- }
7522
- function resolveAssetSource(metaPath, source, paths) {
8284
+ function resolveAssetSource(metaPath, source) {
7523
8285
  if (source === void 0) {
7524
8286
  const metaDir = dirname(metaPath);
7525
8287
  const metaName = deriveAssetName(metaPath);
7526
8288
  const derived = deriveSourceName(metaName);
7527
- return ok(resolve(metaDir, derived));
8289
+ return resolve(metaDir, derived);
7528
8290
  }
7529
- if (source.startsWith("@")) {
7530
- const match = source.match(PATH_REF_RE);
7531
- if (!match) {
7532
- return err(
7533
- new PackError({
7534
- code: "pack-malformed-path-ref",
7535
- expected: "source in format @<name>/<rest>",
7536
- hint: PACK_ERROR_HINTS["pack-malformed-path-ref"],
7537
- detail: {
7538
- code: "pack-malformed-path-ref",
7539
- reason: "format",
7540
- rawSource: source,
7541
- expectedFormat: "@<name>/<rest>"
7542
- }
7543
- })
7544
- );
7545
- }
7546
- const [, name, rest] = match;
7547
- const pathDir = paths[name];
7548
- if (pathDir === void 0) {
7549
- return err(
7550
- new PackError({
7551
- code: "pack-unknown-path",
7552
- expected: "path name found in package.json#forgeax.assets.paths",
7553
- hint: PACK_ERROR_HINTS["pack-unknown-path"],
7554
- detail: {
7555
- code: "pack-unknown-path",
7556
- pathName: name,
7557
- knownNames: Object.keys(paths)
7558
- }
7559
- })
7560
- );
7561
- }
7562
- const resolved = resolve(pathDir, rest);
7563
- if (isPathEscape(pathDir, resolved)) {
7564
- return err(
7565
- new PackError({
7566
- code: "pack-malformed-path-ref",
7567
- expected: "rest path must not escape the declared path directory",
7568
- hint: PACK_ERROR_HINTS["pack-malformed-path-ref"],
7569
- detail: {
7570
- code: "pack-malformed-path-ref",
7571
- reason: "escape",
7572
- rawSource: source,
7573
- expectedFormat: "@<name>/<rest>"
7574
- }
7575
- })
7576
- );
7577
- }
7578
- return ok(resolved);
7579
- }
7580
- return ok(resolve(dirname(metaPath), source));
8291
+ return resolve(dirname(metaPath), source);
7581
8292
  }
7582
8293
 
7583
8294
  // src/schema-compiled.ts
@@ -7627,7 +8338,7 @@ var meta_schema_default = {
7627
8338
  source: {
7628
8339
  type: "string",
7629
8340
  minLength: 1,
7630
- 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."
8341
+ 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."
7631
8342
  },
7632
8343
  importSettings: {
7633
8344
  type: "object",
@@ -7768,11 +8479,11 @@ var pack_schema_default = {
7768
8479
  $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.",
7769
8480
  type: "object",
7770
8481
  additionalProperties: false,
7771
- required: ["schemaVersion", "kind", "assets"],
8482
+ required: ["schemaVersion"],
7772
8483
  properties: {
7773
8484
  schemaVersion: {
7774
8485
  type: "string",
7775
- enum: ["1.0.0", "2.0.0"]
8486
+ enum: ["1.0.0", "2.0.0", "3.0.0"]
7776
8487
  },
7777
8488
  kind: {
7778
8489
  type: "string",
@@ -7794,12 +8505,58 @@ var pack_schema_default = {
7794
8505
  items: { $ref: "#/$defs/diagnostic" }
7795
8506
  },
7796
8507
  assets: {
7797
- type: "array",
7798
- items: {
7799
- $ref: "#/$defs/asset"
7800
- }
8508
+ oneOf: [
8509
+ {
8510
+ type: "array",
8511
+ items: { $ref: "#/$defs/asset" }
8512
+ },
8513
+ { $ref: "#/$defs/authoringAssets" }
8514
+ ]
8515
+ },
8516
+ parent: {
8517
+ $ref: "#/$defs/guid36",
8518
+ description: "Parent ScriptablePack packageId for one v3 instance; the source may declare Pack parameters."
8519
+ },
8520
+ values: {
8521
+ type: "object",
8522
+ additionalProperties: true,
8523
+ description: "Sparse shallow parameter overrides for one v3 instance."
7801
8524
  }
7802
8525
  },
8526
+ oneOf: [
8527
+ {
8528
+ required: ["kind", "assets"],
8529
+ properties: {
8530
+ schemaVersion: { enum: ["1.0.0", "2.0.0"] },
8531
+ kind: { const: "internal-text-package" },
8532
+ assets: { type: "array" },
8533
+ parent: false,
8534
+ values: false
8535
+ }
8536
+ },
8537
+ {
8538
+ required: ["packageId", "assets"],
8539
+ properties: {
8540
+ schemaVersion: { const: "3.0.0" },
8541
+ kind: false,
8542
+ packageId: { $ref: "#/$defs/guid36" },
8543
+ assets: { $ref: "#/$defs/authoringAssets" },
8544
+ parent: false,
8545
+ values: false
8546
+ }
8547
+ },
8548
+ {
8549
+ required: ["packageId", "parent", "values"],
8550
+ properties: {
8551
+ schemaVersion: { const: "3.0.0" },
8552
+ kind: false,
8553
+ packageId: { $ref: "#/$defs/guid36" },
8554
+ parent: { $ref: "#/$defs/guid36" },
8555
+ values: { type: "object" },
8556
+ assets: false
8557
+ }
8558
+ }
8559
+ ],
7803
8560
  allOf: [
7804
8561
  {
7805
8562
  if: {
@@ -7891,6 +8648,30 @@ var pack_schema_default = {
7891
8648
  }
7892
8649
  ]
7893
8650
  },
8651
+ authoringAssets: {
8652
+ type: "object",
8653
+ additionalProperties: false,
8654
+ patternProperties: {
8655
+ "^[a-z0-9][a-z0-9._-]*(/[a-z0-9][a-z0-9._-]*)*$": {
8656
+ $ref: "#/$defs/authoringAsset"
8657
+ }
8658
+ }
8659
+ },
8660
+ authoringAsset: {
8661
+ type: "object",
8662
+ additionalProperties: false,
8663
+ required: ["kind", "payload", "refs"],
8664
+ properties: {
8665
+ kind: { type: "string", minLength: 1 },
8666
+ name: { type: "string", minLength: 1 },
8667
+ payload: { type: "object" },
8668
+ refs: {
8669
+ type: "array",
8670
+ items: { $ref: "#/$defs/guid36" }
8671
+ },
8672
+ artifacts: { $ref: "#/$defs/artifacts" }
8673
+ }
8674
+ },
7894
8675
  artifacts: {
7895
8676
  type: "object",
7896
8677
  additionalProperties: false,
@@ -7914,562 +8695,101 @@ var pack_schema_default = {
7914
8695
  }
7915
8696
  },
7916
8697
  assetCodec: {
7917
- type: "object",
7918
- additionalProperties: false,
7919
- required: ["name"],
7920
- properties: {
7921
- name: { type: "string", minLength: 1 },
7922
- profile: { type: "string", minLength: 1 },
7923
- version: { type: "string", minLength: 1 }
7924
- }
7925
- },
7926
- integrity: {
7927
- type: "object",
7928
- additionalProperties: false,
7929
- required: ["algorithm", "digest"],
7930
- properties: {
7931
- algorithm: { const: "sha256" },
7932
- digest: { type: "string", minLength: 1 }
7933
- }
7934
- },
7935
- provenance: {
7936
- type: "object",
7937
- additionalProperties: false,
7938
- required: ["provider", "version"],
7939
- properties: {
7940
- provider: { type: "string", minLength: 1 },
7941
- version: { type: "string", minLength: 1 },
7942
- source: { type: "string", minLength: 1 }
7943
- }
7944
- },
7945
- revision: {
7946
- type: "object",
7947
- additionalProperties: false,
7948
- required: ["digest", "observedAt", "rootId"],
7949
- properties: {
7950
- digest: { type: "string", minLength: 1 },
7951
- observedAt: { type: "number" },
7952
- rootId: { type: "string", minLength: 1 }
7953
- }
7954
- },
7955
- diagnostic: {
7956
- type: "object",
7957
- additionalProperties: false,
7958
- required: ["code", "severity"],
7959
- properties: {
7960
- code: { type: "string", minLength: 1 },
7961
- severity: { type: "string", enum: ["info", "warning", "blocking"] },
7962
- message: { type: "string" },
7963
- subject: { $ref: "#/$defs/subject" },
7964
- expected: { type: "string", minLength: 1 },
7965
- actual: { type: "string" },
7966
- hint: { type: "string", minLength: 1 },
7967
- authority: { type: "string", enum: ["producer", "pack", "catalog"] },
7968
- evidence: { type: "array", items: { type: "object" } },
7969
- recoveryIntents: { type: "array", items: { type: "string", minLength: 1 } }
7970
- }
7971
- },
7972
- subject: {
7973
- type: "object",
7974
- additionalProperties: false,
7975
- required: ["type", "id"],
7976
- properties: {
7977
- type: { type: "string", enum: ["asset", "package", "resource"] },
7978
- id: { type: "string", minLength: 1 }
7979
- }
7980
- },
7981
- relation: {
7982
- type: "object",
7983
- additionalProperties: false,
7984
- required: ["from", "to", "type", "provenance"],
7985
- properties: {
7986
- from: { $ref: "#/$defs/subject" },
7987
- to: { $ref: "#/$defs/subject" },
7988
- type: { type: "string", minLength: 1 },
7989
- policy: { type: "object" },
7990
- provenance: { $ref: "#/$defs/provenance" }
7991
- }
7992
- }
7993
- }
7994
- };
7995
-
7996
- // src/schema-compiled.ts
7997
- var ajv = new import_ajv.default({ strict: true, allErrors: false });
7998
- (0, import_ajv_formats.default)(ajv, ["uuid"]);
7999
- var validateMeta = ajv.compile(meta_schema_default);
8000
- var validatePack = ajv.compile(pack_schema_default);
8001
- function validatePackV2(value) {
8002
- if (!validatePack(value) || !isPackV2Shape(value)) return false;
8003
- const seenGuids = /* @__PURE__ */ new Set();
8004
- for (const asset of value.assets) {
8005
- if (seenGuids.has(asset.guid)) return false;
8006
- seenGuids.add(asset.guid);
8007
- }
8008
- return true;
8009
- }
8010
- function isPackV2Shape(value) {
8011
- return typeof value === "object" && value !== null && "schemaVersion" in value && value.schemaVersion === "2.0.0";
8012
- }
8013
- var SCRIPTABLE_PACK_ASSET_KINDS = [
8014
- "mesh",
8015
- "material",
8016
- "scene",
8017
- "texture",
8018
- "equirect",
8019
- "sampler",
8020
- "font",
8021
- "render-pipeline",
8022
- "tileset",
8023
- "video",
8024
- "skeleton",
8025
- "skin",
8026
- "animation-clip",
8027
- "animation-graph",
8028
- "audio",
8029
- "particle-effect"
8030
- ];
8031
- function isScriptablePackAssetKind(value) {
8032
- return SCRIPTABLE_PACK_ASSET_KINDS.includes(value);
8033
- }
8034
- function sceneComponentFieldType(value) {
8035
- if (typeof value === "string") return value;
8036
- if (isRecord2(value) && typeof value.type === "string") return value.type;
8037
- return void 0;
8038
- }
8039
- function projectScriptablePackSceneComponents(components) {
8040
- return (components ?? []).map((component) => ({
8041
- name: component.name,
8042
- fields: Object.fromEntries(
8043
- Object.entries(component.fields).map(([fieldName, field]) => [
8044
- fieldName,
8045
- sceneComponentFieldType(field)
8046
- ])
8047
- )
8048
- }));
8049
- }
8050
- var SCRIPTABLE_PACK_REQUEST_ID_SCHEMA = {
8051
- type: "string",
8052
- minLength: 1,
8053
- maxLength: 128,
8054
- pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$",
8055
- description: "Caller-minted identity for one idempotent ScriptablePack operation."
8056
- };
8057
- var SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA = {
8058
- type: "string",
8059
- minLength: 8,
8060
- pattern: "^[^/].*\\.pack\\.ts$",
8061
- description: "Game-root-relative ScriptablePack source path."
8062
- };
8063
- var SCRIPTABLE_PACK_OWNER_GUID_SCHEMA = {
8064
- type: "string",
8065
- format: "uuid",
8066
- description: "Catalog GUID used to resolve the producer-owned source subject."
8067
- };
8068
- var SCRIPTABLE_PACK_REVISION_SCHEMA = {
8069
- type: "string",
8070
- minLength: 64,
8071
- maxLength: 64,
8072
- pattern: "^[a-f0-9]{64}$",
8073
- description: "SHA-256 source revision returned by preflight."
8074
- };
8075
- var SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA = { type: "string", minLength: 1 };
8076
- var SCRIPTABLE_PACK_ASSET_KIND_SCHEMA = {
8077
- enum: SCRIPTABLE_PACK_ASSET_KINDS,
8078
- description: "Ordinary Asset kind supported by the ScriptablePack producer/loader matrix."
8079
- };
8080
- var SCRIPTABLE_PACK_NAME_SCHEMA = { type: "string", minLength: 1 };
8081
- function scriptablePackArgsSchema(properties, required, options = {}) {
8082
- const subjectRequired = ["requestId", ...required];
8083
- return {
8084
- type: "object",
8085
- properties: {
8086
- sourcePath: SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA,
8087
- ownerGuid: SCRIPTABLE_PACK_OWNER_GUID_SCHEMA,
8088
- requestId: SCRIPTABLE_PACK_REQUEST_ID_SCHEMA,
8089
- ...properties
8090
- },
8091
- required: subjectRequired,
8092
- ...options.subject === false ? {} : {
8093
- anyOf: [
8094
- { required: [...subjectRequired, "sourcePath"] },
8095
- { required: [...subjectRequired, "ownerGuid"] },
8096
- ...options.guidSubject === false ? [] : [{ required: [...subjectRequired, "guid"] }]
8097
- ]
8098
- },
8099
- additionalProperties: false
8100
- };
8101
- }
8102
- [
8103
- {
8104
- id: "asset-source.create",
8105
- kind: "create",
8106
- domain: "session",
8107
- title: "Create Asset Source",
8108
- argsSchema: scriptablePackArgsSchema(
8109
- {
8110
- name: SCRIPTABLE_PACK_NAME_SCHEMA,
8111
- initialOutput: {
8112
- type: "object",
8113
- properties: {
8114
- sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
8115
- kind: SCRIPTABLE_PACK_ASSET_KIND_SCHEMA,
8116
- name: SCRIPTABLE_PACK_NAME_SCHEMA
8117
- },
8118
- required: ["sourceKey", "kind"],
8119
- additionalProperties: false
8120
- }
8121
- },
8122
- ["sourcePath", "initialOutput"],
8123
- { subject: false }
8124
- )
8125
- },
8126
- {
8127
- id: "asset-source.add-output",
8128
- kind: "add-output",
8129
- domain: "session",
8130
- title: "Add Asset Source Output",
8131
- argsSchema: scriptablePackArgsSchema(
8132
- {
8133
- sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
8134
- assetKind: SCRIPTABLE_PACK_ASSET_KIND_SCHEMA,
8135
- name: SCRIPTABLE_PACK_NAME_SCHEMA,
8136
- expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
8137
- },
8138
- ["sourceKey", "assetKind", "expectedRevision"]
8139
- )
8140
- },
8141
- {
8142
- id: "asset-source.add-external-asset",
8143
- kind: "add-external-asset",
8144
- domain: "session",
8145
- title: "Add Asset Source External Asset",
8146
- argsSchema: scriptablePackArgsSchema(
8147
- {
8148
- alias: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
8149
- guid: { type: "string", format: "uuid" },
8150
- expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
8151
- },
8152
- ["alias", "guid", "expectedRevision"],
8153
- { guidSubject: false }
8154
- )
8155
- },
8156
- {
8157
- id: "asset-source.rename",
8158
- kind: "rename",
8159
- domain: "session",
8160
- title: "Rename Asset Source Display Name",
8161
- argsSchema: scriptablePackArgsSchema(
8162
- {
8163
- target: {
8164
- oneOf: [
8165
- {
8166
- type: "object",
8167
- properties: { kind: { const: "package" } },
8168
- required: ["kind"],
8169
- additionalProperties: false
8170
- },
8171
- {
8172
- type: "object",
8173
- properties: {
8174
- kind: { const: "output" },
8175
- sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA
8176
- },
8177
- required: ["kind", "sourceKey"],
8178
- additionalProperties: false
8179
- }
8180
- ]
8181
- },
8182
- name: SCRIPTABLE_PACK_NAME_SCHEMA,
8183
- expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
8184
- },
8185
- ["target", "name", "expectedRevision"]
8186
- )
8187
- },
8188
- {
8189
- id: "asset-source.remove-output",
8190
- kind: "remove-output",
8191
- domain: "session",
8192
- title: "Remove Asset Source Output",
8193
- destructive: true,
8194
- argsSchema: scriptablePackArgsSchema(
8195
- {
8196
- sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
8197
- confirmIncomingRefs: { type: "array", items: { type: "string" } },
8198
- expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
8199
- },
8200
- ["sourceKey", "expectedRevision"]
8201
- )
8202
- },
8203
- {
8204
- id: "asset-source.clone",
8205
- kind: "clone",
8206
- domain: "session",
8207
- title: "Clone Asset Source",
8208
- argsSchema: scriptablePackArgsSchema(
8209
- {
8210
- targetPath: SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA,
8211
- expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
8212
- },
8213
- ["targetPath", "expectedRevision"]
8214
- )
8215
- },
8216
- {
8217
- id: "asset-source.rebuild",
8218
- kind: "rebuild",
8219
- domain: "session",
8220
- title: "Rebuild Asset Source",
8221
- argsSchema: scriptablePackArgsSchema({ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA }, [
8222
- "expectedRevision"
8223
- ])
8224
- },
8225
- {
8226
- id: "asset-source.cold-cook",
8227
- kind: "cold-cook",
8228
- domain: "session",
8229
- title: "Cold Cook Asset Source",
8230
- argsSchema: scriptablePackArgsSchema({ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA }, [
8231
- "expectedRevision"
8232
- ])
8233
- }
8234
- ];
8235
- function actual(value) {
8236
- if (value === null) return "null";
8237
- if (Array.isArray(value)) return "array";
8238
- if (ArrayBuffer.isView(value)) return value.constructor.name;
8239
- return typeof value;
8240
- }
8241
- function invalid(propertyPath, expected, value, sourcePath) {
8242
- return err({
8243
- code: "pack-source-definition-invalid",
8244
- expected,
8245
- hint: "repair the default exported ScriptablePack definition, then inspect Meta again",
8246
- detail: {
8247
- ...sourcePath === void 0 ? {} : { sourcePath },
8248
- propertyPath,
8249
- actual: actual(value)
8250
- }
8251
- });
8252
- }
8253
- function isRecord2(value) {
8254
- return value !== null && typeof value === "object" && !Array.isArray(value);
8255
- }
8256
- function isAssetGuid(value) {
8257
- return value instanceof Uint8Array && value.byteLength === 16;
8258
- }
8259
- function guidKey(guid) {
8260
- return AssetGuid.format(guid);
8261
- }
8262
- function freezeDefinition(definition) {
8263
- const assets = Object.fromEntries(
8264
- Object.entries(definition.assets).map(([sourceKey, descriptor]) => [
8265
- sourceKey,
8266
- Object.freeze({ ...descriptor, guid: descriptor.guid.slice() })
8267
- ])
8268
- );
8269
- const externalAssets = Object.fromEntries(
8270
- Object.entries(definition.externalAssets).map(([alias, guid]) => [
8271
- alias,
8272
- guid.slice()
8273
- ])
8274
- );
8275
- const sceneComponents = definition.sceneComponents === void 0 ? void 0 : Object.freeze(
8276
- projectScriptablePackSceneComponents(definition.sceneComponents).map(
8277
- (component) => Object.freeze({
8278
- ...component,
8279
- fields: Object.freeze({ ...component.fields })
8280
- })
8281
- )
8282
- );
8283
- return Object.freeze({
8284
- ...definition,
8285
- packageId: definition.packageId.slice(),
8286
- assets: Object.freeze(assets),
8287
- externalAssets: Object.freeze(externalAssets),
8288
- ...sceneComponents === void 0 ? {} : { sceneComponents }
8289
- });
8290
- }
8291
- function validateScriptablePackDefinition(value, sourcePath) {
8292
- if (!isRecord2(value))
8293
- return invalid("$", "a ScriptablePack definition object", value, sourcePath);
8294
- if (value.schemaVersion !== "1.0.0") {
8295
- return invalid("$.schemaVersion", "the literal '1.0.0'", value.schemaVersion, sourcePath);
8296
- }
8297
- if (!isAssetGuid(value.packageId)) {
8298
- return invalid("$.packageId", "a 16-byte AssetGuid", value.packageId, sourcePath);
8299
- }
8300
- if (value.name !== void 0 && typeof value.name !== "string") {
8301
- return invalid("$.name", "a string when present", value.name, sourcePath);
8302
- }
8303
- if (!isRecord2(value.assets) || Object.keys(value.assets).length === 0) {
8304
- return invalid(
8305
- "$.assets",
8306
- "a non-empty sourceKey to descriptor object",
8307
- value.assets,
8308
- sourcePath
8309
- );
8310
- }
8311
- if (!isRecord2(value.externalAssets)) {
8312
- return invalid(
8313
- "$.externalAssets",
8314
- "an alias to AssetGuid object",
8315
- value.externalAssets,
8316
- sourcePath
8317
- );
8318
- }
8319
- if (value.sceneComponents !== void 0) {
8320
- if (!Array.isArray(value.sceneComponents)) {
8321
- return invalid(
8322
- "$.sceneComponents",
8323
- "an array of component tokens or neutral schema rows when present",
8324
- value.sceneComponents,
8325
- sourcePath
8326
- );
8327
- }
8328
- const componentNames = /* @__PURE__ */ new Set();
8329
- for (const [componentIndex, component] of value.sceneComponents.entries()) {
8330
- if (!isRecord2(component)) {
8331
- return invalid(
8332
- `$.sceneComponents[${componentIndex}]`,
8333
- "a component token or neutral schema row",
8334
- component,
8335
- sourcePath
8336
- );
8698
+ type: "object",
8699
+ additionalProperties: false,
8700
+ required: ["name"],
8701
+ properties: {
8702
+ name: { type: "string", minLength: 1 },
8703
+ profile: { type: "string", minLength: 1 },
8704
+ version: { type: "string", minLength: 1 }
8337
8705
  }
8338
- if (typeof component.name !== "string" || component.name.trim().length === 0) {
8339
- return invalid(
8340
- `$.sceneComponents[${componentIndex}].name`,
8341
- "a non-empty component name",
8342
- component.name,
8343
- sourcePath
8344
- );
8706
+ },
8707
+ integrity: {
8708
+ type: "object",
8709
+ additionalProperties: false,
8710
+ required: ["algorithm", "digest"],
8711
+ properties: {
8712
+ algorithm: { const: "sha256" },
8713
+ digest: { type: "string", minLength: 1 }
8345
8714
  }
8346
- if (componentNames.has(component.name)) {
8347
- return invalid(
8348
- `$.sceneComponents[${componentIndex}].name`,
8349
- "component names to be unique within one ScriptablePack",
8350
- component.name,
8351
- sourcePath
8352
- );
8715
+ },
8716
+ provenance: {
8717
+ type: "object",
8718
+ additionalProperties: false,
8719
+ required: ["provider", "version"],
8720
+ properties: {
8721
+ provider: { type: "string", minLength: 1 },
8722
+ version: { type: "string", minLength: 1 },
8723
+ source: { type: "string", minLength: 1 }
8353
8724
  }
8354
- componentNames.add(component.name);
8355
- if (!isRecord2(component.fields)) {
8356
- return invalid(
8357
- `$.sceneComponents[${componentIndex}].fields`,
8358
- "a field-name to schema-type object",
8359
- component.fields,
8360
- sourcePath
8361
- );
8725
+ },
8726
+ revision: {
8727
+ type: "object",
8728
+ additionalProperties: false,
8729
+ required: ["digest", "observedAt", "rootId"],
8730
+ properties: {
8731
+ digest: { type: "string", minLength: 1 },
8732
+ observedAt: { type: "number" },
8733
+ rootId: { type: "string", minLength: 1 }
8362
8734
  }
8363
- for (const [fieldName, field] of Object.entries(component.fields)) {
8364
- const type = sceneComponentFieldType(field);
8365
- if (fieldName.trim().length === 0 || type === void 0 || type.trim().length === 0) {
8366
- return invalid(
8367
- `$.sceneComponents[${componentIndex}].fields`,
8368
- "field names with non-empty string schema types",
8369
- field,
8370
- sourcePath
8371
- );
8372
- }
8735
+ },
8736
+ diagnostic: {
8737
+ type: "object",
8738
+ additionalProperties: false,
8739
+ required: ["code", "severity"],
8740
+ properties: {
8741
+ code: { type: "string", minLength: 1 },
8742
+ severity: { type: "string", enum: ["info", "warning", "blocking"] },
8743
+ message: { type: "string" },
8744
+ subject: { $ref: "#/$defs/subject" },
8745
+ expected: { type: "string", minLength: 1 },
8746
+ actual: { type: "string" },
8747
+ hint: { type: "string", minLength: 1 },
8748
+ authority: { type: "string", enum: ["producer", "pack", "catalog"] },
8749
+ evidence: { type: "array", items: { type: "object" } },
8750
+ recoveryIntents: { type: "array", items: { type: "string", minLength: 1 } }
8751
+ }
8752
+ },
8753
+ subject: {
8754
+ type: "object",
8755
+ additionalProperties: false,
8756
+ required: ["type", "id"],
8757
+ properties: {
8758
+ type: { type: "string", enum: ["asset", "package", "resource"] },
8759
+ id: { type: "string", minLength: 1 }
8760
+ }
8761
+ },
8762
+ relation: {
8763
+ type: "object",
8764
+ additionalProperties: false,
8765
+ required: ["from", "to", "type", "provenance"],
8766
+ properties: {
8767
+ from: { $ref: "#/$defs/subject" },
8768
+ to: { $ref: "#/$defs/subject" },
8769
+ type: { type: "string", minLength: 1 },
8770
+ policy: { type: "object" },
8771
+ provenance: { $ref: "#/$defs/provenance" }
8373
8772
  }
8374
8773
  }
8375
8774
  }
8376
- if (typeof value.build !== "function") {
8377
- return invalid("$.build", "a build(assetReader) function", value.build, sourcePath);
8378
- }
8379
- const packageGuid = guidKey(value.packageId);
8380
- const localGuids = /* @__PURE__ */ new Set();
8381
- for (const [sourceKey, descriptor] of Object.entries(value.assets)) {
8382
- if (sourceKey.trim().length === 0) {
8383
- return invalid("$.assets", "non-empty sourceKey object keys", sourceKey, sourcePath);
8384
- }
8385
- if (!isRecord2(descriptor)) {
8386
- return invalid(
8387
- `$.assets[${JSON.stringify(sourceKey)}]`,
8388
- "an asset descriptor",
8389
- descriptor,
8390
- sourcePath
8391
- );
8392
- }
8393
- if (!isAssetGuid(descriptor.guid)) {
8394
- return invalid(
8395
- `$.assets[${JSON.stringify(sourceKey)}].guid`,
8396
- "a 16-byte AssetGuid",
8397
- descriptor.guid,
8398
- sourcePath
8399
- );
8400
- }
8401
- if (typeof descriptor.kind !== "string" || !isScriptablePackAssetKind(descriptor.kind)) {
8402
- return invalid(
8403
- `$.assets[${JSON.stringify(sourceKey)}].kind`,
8404
- "one of SCRIPTABLE_PACK_ASSET_KINDS",
8405
- descriptor.kind,
8406
- sourcePath
8407
- );
8408
- }
8409
- if (descriptor.name !== void 0 && typeof descriptor.name !== "string") {
8410
- return invalid(
8411
- `$.assets[${JSON.stringify(sourceKey)}].name`,
8412
- "a string when present",
8413
- descriptor.name,
8414
- sourcePath
8415
- );
8416
- }
8417
- const guid = guidKey(descriptor.guid);
8418
- if (guid === packageGuid || localGuids.has(guid)) {
8419
- return invalid(
8420
- `$.assets[${JSON.stringify(sourceKey)}].guid`,
8421
- "a GUID unique within the package and distinct from packageId",
8422
- descriptor.guid,
8423
- sourcePath
8424
- );
8425
- }
8426
- localGuids.add(guid);
8427
- }
8428
- const externalGuids = /* @__PURE__ */ new Set();
8429
- for (const [alias, guidValue] of Object.entries(value.externalAssets)) {
8430
- if (alias.trim().length === 0) {
8431
- return invalid("$.externalAssets", "non-empty alias object keys", alias, sourcePath);
8432
- }
8433
- if (!isAssetGuid(guidValue)) {
8434
- return invalid(
8435
- `$.externalAssets[${JSON.stringify(alias)}]`,
8436
- "a 16-byte AssetGuid",
8437
- guidValue,
8438
- sourcePath
8439
- );
8440
- }
8441
- const guid = guidKey(guidValue);
8442
- if (guid === packageGuid || localGuids.has(guid) || externalGuids.has(guid)) {
8443
- return invalid(
8444
- `$.externalAssets[${JSON.stringify(alias)}]`,
8445
- "a unique foreign GUID not owned by this package",
8446
- guidValue,
8447
- sourcePath
8448
- );
8449
- }
8450
- externalGuids.add(guid);
8775
+ };
8776
+
8777
+ // src/schema-compiled.ts
8778
+ var ajv = new import_ajv.default({ strict: true, allErrors: false });
8779
+ (0, import_ajv_formats.default)(ajv, ["uuid"]);
8780
+ var validateMeta = ajv.compile(meta_schema_default);
8781
+ var validatePack = ajv.compile(pack_schema_default);
8782
+ function validatePackV2(value) {
8783
+ if (!validatePack(value) || !isPackV2Shape(value)) return false;
8784
+ const seenGuids = /* @__PURE__ */ new Set();
8785
+ for (const asset of value.assets) {
8786
+ if (seenGuids.has(asset.guid)) return false;
8787
+ seenGuids.add(asset.guid);
8451
8788
  }
8452
- return ok(freezeDefinition(value));
8789
+ return true;
8453
8790
  }
8454
- function projectScriptablePackMeta(definition, source) {
8455
- const subAssets = Object.entries(definition.assets).sort(([left], [right]) => left.localeCompare(right)).map(([sourceKey, descriptor], sourceIndex) => ({
8456
- guid: guidKey(descriptor.guid),
8457
- sourceIndex,
8458
- sourceKey,
8459
- kind: descriptor.kind,
8460
- ...descriptor.name === void 0 ? {} : { name: descriptor.name }
8461
- }));
8462
- const externalAssets = Object.entries(definition.externalAssets).sort(([left], [right]) => left.localeCompare(right)).map(([alias, guid]) => ({ alias, guid: guidKey(guid) }));
8463
- return {
8464
- schemaVersion: "1.0.0",
8465
- kind: "external-asset-package",
8466
- packageId: guidKey(definition.packageId),
8467
- ...definition.name === void 0 ? {} : { name: definition.name },
8468
- importer: "pack-ts",
8469
- source,
8470
- importSettings: { contractVersion: "1.0.0", externalAssets },
8471
- subAssets
8472
- };
8791
+ function isPackV2Shape(value) {
8792
+ return typeof value === "object" && value !== null && "schemaVersion" in value && value.schemaVersion === "2.0.0";
8473
8793
  }
8474
8794
  var IMPORT_META_RESOLVE_FLAG = "--experimental-import-meta-resolve";
8475
8795
  function scriptablePackWorkerExecArgv() {
@@ -8518,50 +8838,51 @@ async function inventoryScriptablePackSource(sourcePath, initialSourceText) {
8518
8838
  }
8519
8839
  function serializeFailure(value) {
8520
8840
  if (value !== null && typeof value === "object") {
8521
- const failure = value;
8841
+ const failure2 = value;
8522
8842
  return {
8523
- name: failure.name,
8524
- code: failure.code,
8525
- expected: failure.expected,
8526
- actual: failure.actual,
8527
- hint: failure.hint,
8528
- detail: failure.detail,
8529
- message: failure.message
8843
+ name: failure2.name,
8844
+ code: failure2.code,
8845
+ expected: failure2.expected,
8846
+ actual: failure2.actual,
8847
+ hint: failure2.hint,
8848
+ detail: failure2.detail,
8849
+ message: failure2.message
8530
8850
  };
8531
8851
  }
8532
8852
  return { message: String(value) };
8533
8853
  }
8534
8854
  function hydrateFailure(value) {
8535
8855
  if (value === null || typeof value !== "object") return value;
8536
- const failure = value;
8537
- if (failure.name === "AssetError" && typeof failure.code === "string" && typeof failure.expected === "string" && typeof failure.hint === "string") {
8856
+ const failure2 = value;
8857
+ if (failure2.name === "AssetError" && typeof failure2.code === "string" && typeof failure2.expected === "string" && typeof failure2.hint === "string") {
8538
8858
  const args = {
8539
- code: failure.code,
8540
- expected: failure.expected,
8541
- hint: failure.hint
8859
+ code: failure2.code,
8860
+ expected: failure2.expected,
8861
+ hint: failure2.hint
8542
8862
  };
8543
- return failure.detail === void 0 ? new AssetError(args) : new AssetError({
8863
+ return failure2.detail === void 0 ? new AssetError(args) : new AssetError({
8544
8864
  ...args,
8545
- detail: failure.detail
8865
+ detail: failure2.detail
8546
8866
  });
8547
8867
  }
8548
- if (failure.name === "ImportError" && typeof failure.code === "string" && typeof failure.expected === "string" && typeof failure.hint === "string" && failure.detail !== void 0) {
8868
+ if (failure2.name === "ImportError" && typeof failure2.code === "string" && typeof failure2.expected === "string" && typeof failure2.hint === "string" && failure2.detail !== void 0) {
8549
8869
  return new ImportError({
8550
- code: failure.code,
8551
- expected: failure.expected,
8552
- hint: failure.hint,
8553
- detail: failure.detail,
8554
- ...typeof failure.actual === "string" ? { actual: failure.actual } : {}
8870
+ code: failure2.code,
8871
+ expected: failure2.expected,
8872
+ hint: failure2.hint,
8873
+ detail: failure2.detail,
8874
+ ...typeof failure2.actual === "string" ? { actual: failure2.actual } : {}
8555
8875
  });
8556
8876
  }
8557
- if (typeof failure.message === "string") {
8558
- const error = new Error(failure.message);
8559
- if (typeof failure.name === "string") error.name = failure.name;
8877
+ if (typeof failure2.message === "string") {
8878
+ const error = new Error(failure2.message);
8879
+ if (typeof failure2.name === "string") error.name = failure2.name;
8560
8880
  return error;
8561
8881
  }
8562
8882
  return value;
8563
8883
  }
8564
8884
  var WorkerScriptablePackExecutor = class {
8885
+ supportsPackParameters = true;
8565
8886
  worker;
8566
8887
  compileRoot;
8567
8888
  nextBuildId = 0;
@@ -8589,7 +8910,7 @@ var WorkerScriptablePackExecutor = class {
8589
8910
  resolveLoad({
8590
8911
  default: value.definition === void 0 ? void 0 : {
8591
8912
  ...value.definition,
8592
- build: (reader) => this.runBuild(reader)
8913
+ build: (readByGuid, context) => this.runBuild({ readByGuid }, context)
8593
8914
  }
8594
8915
  });
8595
8916
  } else if (value.kind === "load-threw") {
@@ -8621,7 +8942,7 @@ var WorkerScriptablePackExecutor = class {
8621
8942
  })();
8622
8943
  return this.disposal;
8623
8944
  }
8624
- runBuild(reader) {
8945
+ runBuild(reader, context) {
8625
8946
  const worker = this.worker;
8626
8947
  if (worker === void 0) return Promise.reject(new Error("ScriptablePack worker is closed"));
8627
8948
  if (this.build !== void 0)
@@ -8629,7 +8950,7 @@ var WorkerScriptablePackExecutor = class {
8629
8950
  const id = this.nextBuildId++;
8630
8951
  return new Promise((resolveBuild, rejectBuild) => {
8631
8952
  this.build = { id, reader, resolve: resolveBuild, reject: rejectBuild };
8632
- worker.postMessage({ kind: "build", buildId: id });
8953
+ worker.postMessage({ kind: "build", buildId: id, context });
8633
8954
  });
8634
8955
  }
8635
8956
  onMessage(message) {
@@ -8662,11 +8983,11 @@ function scriptablePackWorkerUrl() {
8662
8983
  const bundledWorker = new URL("./scriptable-pack-worker.mjs", import.meta.url);
8663
8984
  return existsSync(fileURLToPath(bundledWorker)) ? bundledWorker : new URL("../dist/scriptable-pack-worker.mjs", import.meta.url);
8664
8985
  }
8665
- function loadFailure(sourcePath, reason, phase, diagnostic, timeoutMs) {
8666
- return err({
8667
- code: "pack-source-load-failed",
8668
- expected: "a trusted synchronous module with a valid default ScriptablePack export",
8669
- hint: "repair the module load or initialization failure, then inspect Meta again",
8986
+ function scriptablePackLoadFailure(sourcePath, reason, phase, diagnostic, timeoutMs) {
8987
+ return {
8988
+ code: "pack-parameter-invalid",
8989
+ expected: "a trusted Pack v2 authoring module with a valid default export",
8990
+ hint: "repair the source module or its build timeout, then inspect the Pack again",
8670
8991
  detail: {
8671
8992
  sourcePath,
8672
8993
  reason,
@@ -8674,20 +8995,6 @@ function loadFailure(sourcePath, reason, phase, diagnostic, timeoutMs) {
8674
8995
  diagnostic,
8675
8996
  ...timeoutMs === void 0 ? {} : { timeoutMs }
8676
8997
  }
8677
- });
8678
- }
8679
- function buildTimeoutFailure(sourcePath, timeoutMs) {
8680
- return {
8681
- code: "pack-source-load-failed",
8682
- expected: "a ScriptablePack build to settle within the configured build timeout",
8683
- hint: "repair the authored build, then retry through a fresh ScriptablePack generation",
8684
- detail: {
8685
- sourcePath,
8686
- reason: "timeout",
8687
- phase: "build",
8688
- timeoutMs,
8689
- diagnostic: `ScriptablePack build exceeded ${timeoutMs}ms`
8690
- }
8691
8998
  };
8692
8999
  }
8693
9000
  async function loadScriptablePack(sourcePath, options = {}) {
@@ -8706,34 +9013,49 @@ async function loadScriptablePack(sourcePath, options = {}) {
8706
9013
  ]);
8707
9014
  if (loaded === timeoutSignal) {
8708
9015
  disposeReason = "timeout";
8709
- return loadFailure(
8710
- sourcePath,
8711
- "timeout",
8712
- "module-load",
8713
- `ScriptablePack module initialization exceeded ${timeoutMs}ms`,
8714
- timeoutMs
9016
+ return err(
9017
+ scriptablePackLoadFailure(
9018
+ sourcePath,
9019
+ "timeout",
9020
+ "module-load",
9021
+ `Pack module initialization exceeded ${timeoutMs}ms`,
9022
+ timeoutMs
9023
+ )
8715
9024
  );
8716
9025
  }
8717
9026
  const moduleValue = loaded !== null && typeof loaded === "object" && "default" in loaded ? loaded.default : void 0;
8718
- const validated = validateScriptablePackDefinition(moduleValue, sourcePath);
9027
+ const validated = validatePackDefinition(moduleValue, sourcePath);
8719
9028
  if (!validated.ok) {
8720
9029
  disposeReason = "failure";
8721
9030
  return validated;
8722
9031
  }
8723
9032
  if (options.metadataOnly === true) {
8724
9033
  disposeReason = "complete";
8725
- return validated;
9034
+ return ok(validated.value);
8726
9035
  }
8727
9036
  const definition = validated.value;
9037
+ const build = definition.build;
8728
9038
  return ok({
8729
9039
  ...definition,
8730
- build: async (reader) => {
9040
+ build: async (context) => {
8731
9041
  let buildTimedOut = false;
8732
9042
  let buildTimeout;
8733
- const timeoutResult = err(buildTimeoutFailure(sourcePath, buildTimeoutMs));
9043
+ const timeoutResult = err(
9044
+ scriptablePackLoadFailure(
9045
+ sourcePath,
9046
+ "timeout",
9047
+ "build",
9048
+ `ScriptablePack build exceeded ${buildTimeoutMs}ms`,
9049
+ buildTimeoutMs
9050
+ )
9051
+ );
8734
9052
  try {
9053
+ const invocation = "supportsPackParameters" in executor && executor.supportsPackParameters === true ? build(context.readByGuid, {
9054
+ packageId: [...context.packageId],
9055
+ ..."values" in context && context.values !== void 0 ? { values: context.values } : {}
9056
+ }) : definition.build(context);
8735
9057
  const built = await Promise.race([
8736
- Promise.resolve(definition.build(reader)),
9058
+ Promise.resolve(invocation),
8737
9059
  new Promise((resolve6) => {
8738
9060
  buildTimeout = setTimeout(() => {
8739
9061
  buildTimedOut = true;
@@ -8756,9 +9078,15 @@ async function loadScriptablePack(sourcePath, options = {}) {
8756
9078
  }
8757
9079
  });
8758
9080
  } catch (error) {
8759
- const diagnostic = error instanceof Error ? error.message : String(error);
8760
9081
  disposeReason = "failure";
8761
- return loadFailure(sourcePath, "module-load", "module-load", diagnostic);
9082
+ return err(
9083
+ scriptablePackLoadFailure(
9084
+ sourcePath,
9085
+ "module-load",
9086
+ "module-load",
9087
+ error instanceof Error ? error.message : String(error)
9088
+ )
9089
+ );
8762
9090
  } finally {
8763
9091
  if (timeout !== void 0) clearTimeout(timeout);
8764
9092
  if (disposeReason !== void 0) await executor.dispose?.(disposeReason);
@@ -8772,8 +9100,12 @@ function ok4(value) {
8772
9100
  function packErr(error) {
8773
9101
  return { ok: false, error };
8774
9102
  }
9103
+ function record(value) {
9104
+ return value !== null && typeof value === "object" && !Array.isArray(value);
9105
+ }
8775
9106
  var BLACKLIST = /* @__PURE__ */ new Set([
8776
9107
  "node_modules",
9108
+ "__tests__",
8777
9109
  ".forgeax-harness",
8778
9110
  ".forgeax",
8779
9111
  ".git",
@@ -8877,10 +9209,87 @@ async function scanValidated(roots, opts = {}, capture) {
8877
9209
  const scriptablePaths = rawPaths.filter((p) => p.endsWith(".pack.ts"));
8878
9210
  const guidToPath = /* @__PURE__ */ new Map();
8879
9211
  const packRefs = /* @__PURE__ */ new Map();
9212
+ const packageIdToPath = /* @__PURE__ */ new Map();
9213
+ const packageKind = /* @__PURE__ */ new Map();
9214
+ const instanceParents = [];
9215
+ function registerPackage(packageId2, path, kind) {
9216
+ if (packageId2 === void 0) return void 0;
9217
+ const normalized = packageId2.toLowerCase();
9218
+ const existing = packageIdToPath.get(normalized);
9219
+ if (existing !== void 0) {
9220
+ return makePackError("pack-guid-collision", {
9221
+ paths: [existing, path],
9222
+ guid: normalized
9223
+ });
9224
+ }
9225
+ packageIdToPath.set(normalized, path);
9226
+ packageKind.set(normalized, kind);
9227
+ return void 0;
9228
+ }
8880
9229
  for (const packPath of packPaths) {
8881
9230
  const loaded = await readValidatedJson(packPath, "pack-malformed-pack", validatePack);
8882
9231
  if (!loaded.ok) return loaded;
8883
9232
  const { raw, parsed } = loaded.value;
9233
+ if (record(parsed) && parsed.schemaVersion === "3.0.0") {
9234
+ const authoring = parsePackSourceJson(parsed);
9235
+ if (!authoring.ok) {
9236
+ return packErr(
9237
+ makePackError("pack-malformed-pack", {
9238
+ path: packPath,
9239
+ ajvErrors: [{ instancePath: "", message: authoring.error.code }]
9240
+ })
9241
+ );
9242
+ }
9243
+ const packageId2 = authoring.value.packageId;
9244
+ const packageCollision2 = registerPackage(
9245
+ PackageId.format(packageId2),
9246
+ packPath,
9247
+ authoring.value.format
9248
+ );
9249
+ if (packageCollision2 !== void 0) return packErr(packageCollision2);
9250
+ if (authoring.value.format === "instance") {
9251
+ instanceParents.push({
9252
+ path: packPath,
9253
+ packageId: PackageId.format(authoring.value.packageId),
9254
+ parent: PackageId.format(authoring.value.parent)
9255
+ });
9256
+ } else {
9257
+ const projected = projectDirectPackJson(authoring.value);
9258
+ if (!projected.ok) {
9259
+ return packErr(
9260
+ makePackError("pack-malformed-pack", {
9261
+ path: packPath,
9262
+ ajvErrors: [{ instancePath: "/assets", message: projected.error.code }]
9263
+ })
9264
+ );
9265
+ }
9266
+ for (const asset of projected.value.assets) {
9267
+ const normalizedGuid = asset.guid.toLowerCase();
9268
+ const existing = guidToPath.get(normalizedGuid);
9269
+ if (existing !== void 0) {
9270
+ return packErr(
9271
+ makePackError("pack-guid-collision", {
9272
+ paths: [existing, packPath],
9273
+ guid: normalizedGuid
9274
+ })
9275
+ );
9276
+ }
9277
+ guidToPath.set(normalizedGuid, packPath);
9278
+ packRefs.set(normalizedGuid, [
9279
+ ...asset.refs.map((ref) => ref.toLowerCase()),
9280
+ ...extractMountSourceGuids(asset)
9281
+ ]);
9282
+ }
9283
+ }
9284
+ capture?.declarations.set(packPath, {
9285
+ format: "pack.json",
9286
+ sourcePath: packPath,
9287
+ sourceRevision: `sha256:${createHash("sha256").update(raw).digest("hex")}`,
9288
+ sourceText: raw,
9289
+ value: parsed
9290
+ });
9291
+ continue;
9292
+ }
8884
9293
  const packageContract = validateProducerContract(parsed);
8885
9294
  if (!packageContract.ok) {
8886
9295
  return packErr(
@@ -8891,6 +9300,8 @@ async function scanValidated(roots, opts = {}, capture) {
8891
9300
  );
8892
9301
  }
8893
9302
  const packObj = parsed;
9303
+ const packageCollision = registerPackage(packObj.packageId, packPath, "legacy");
9304
+ if (packageCollision !== void 0) return packErr(packageCollision);
8894
9305
  for (const asset of packObj.assets) {
8895
9306
  if (asset.kind === "particle-effect" && asset.execution === "direct" && (asset.refs.length > 0 || Object.keys(asset.artifacts ?? {}).length > 0)) {
8896
9307
  return packErr(
@@ -8973,8 +9384,14 @@ async function scanValidated(roots, opts = {}, capture) {
8973
9384
  ...extractMountSourceGuids(asset)
8974
9385
  ]);
8975
9386
  }
9387
+ capture?.declarations.set(packPath, {
9388
+ format: "pack.json",
9389
+ sourcePath: packPath,
9390
+ sourceRevision: `sha256:${createHash("sha256").update(raw).digest("hex")}`,
9391
+ sourceText: raw,
9392
+ value: packObj
9393
+ });
8976
9394
  }
8977
- const { paths: assetPaths } = loadAssetConfig(process.cwd());
8978
9395
  for (const metaPath of metaPaths) {
8979
9396
  const loaded = await readValidatedJson(metaPath, "pack-malformed-meta", validateMeta);
8980
9397
  if (!loaded.ok) return loaded;
@@ -8989,6 +9406,14 @@ async function scanValidated(roots, opts = {}, capture) {
8989
9406
  );
8990
9407
  }
8991
9408
  const metaObj = parsed;
9409
+ const packageCollision = registerPackage(metaObj.packageId, metaPath, "legacy");
9410
+ if (packageCollision !== void 0) return packErr(packageCollision);
9411
+ capture?.declarations.set(metaPath, {
9412
+ format: "meta.json",
9413
+ sourcePath: metaPath,
9414
+ sourceRevision: `sha256:${createHash("sha256").update(raw).digest("hex")}`,
9415
+ value: metaObj
9416
+ });
8992
9417
  for (const sub of metaObj.subAssets) {
8993
9418
  if (!isValidAssetGuidString(sub.guid)) {
8994
9419
  return packErr(
@@ -9022,11 +9447,7 @@ async function scanValidated(roots, opts = {}, capture) {
9022
9447
  );
9023
9448
  }
9024
9449
  }
9025
- const sourceResolved = resolveAssetSource(metaPath, metaObj.source, assetPaths);
9026
- if (!sourceResolved.ok) {
9027
- return packErr(sourceResolved.error);
9028
- }
9029
- const expectedSourcePath = sourceResolved.value;
9450
+ const expectedSourcePath = resolveAssetSource(metaPath, metaObj.source);
9030
9451
  try {
9031
9452
  await stat(expectedSourcePath);
9032
9453
  } catch {
@@ -9046,23 +9467,24 @@ async function scanValidated(roots, opts = {}, capture) {
9046
9467
  return packErr(
9047
9468
  makePackError("pack-malformed-meta", {
9048
9469
  path: sourcePath,
9049
- ajvErrors: [{ instancePath: "", message: "ScriptablePack source read failed" }]
9470
+ ajvErrors: [{ instancePath: "", message: "Pack source read failed" }]
9050
9471
  })
9051
9472
  );
9052
9473
  }
9053
- const loaded = await loadScriptablePack(sourcePath, {
9474
+ const loaderOptions = {
9054
9475
  ...opts.scriptablePack ?? {},
9055
- ...{ metadataOnly: true }
9056
- });
9476
+ ...capture === void 0 ? { metadataOnly: true } : {}
9477
+ };
9478
+ const loaded = await loadScriptablePack(sourcePath, loaderOptions);
9057
9479
  if (!loaded.ok) {
9058
- const diagnostic = "diagnostic" in loaded.error.detail ? loaded.error.detail.diagnostic : void 0;
9480
+ const diagnostic = loaded.error.detail.diagnostic;
9059
9481
  return packErr(
9060
9482
  makePackError("pack-malformed-meta", {
9061
9483
  path: sourcePath,
9062
9484
  ajvErrors: [
9063
9485
  {
9064
9486
  instancePath: "",
9065
- message: diagnostic === void 0 ? loaded.error.code : `${loaded.error.code}: ${diagnostic}`
9487
+ message: typeof diagnostic === "string" ? `${loaded.error.code}: ${diagnostic}` : loaded.error.code
9066
9488
  }
9067
9489
  ]
9068
9490
  })
@@ -9075,32 +9497,81 @@ async function scanValidated(roots, opts = {}, capture) {
9075
9497
  return packErr(
9076
9498
  makePackError("pack-malformed-meta", {
9077
9499
  path: sourcePath,
9078
- ajvErrors: [{ instancePath: "", message: "ScriptablePack source closure read failed" }]
9500
+ ajvErrors: [{ instancePath: "", message: "Pack source closure read failed" }]
9079
9501
  })
9080
9502
  );
9081
9503
  }
9504
+ const packageCollision = registerPackage(
9505
+ PackageId.format(loaded.value.packageId),
9506
+ sourcePath,
9507
+ "scriptable"
9508
+ );
9509
+ if (packageCollision !== void 0) return packErr(packageCollision);
9082
9510
  const meta = projectScriptablePackMeta(loaded.value, sourcePath);
9083
- const topology = validateProducerOutputs(meta.subAssets);
9084
- if (!topology.ok) {
9511
+ capture?.declarations.set(sourcePath, {
9512
+ format: "pack.ts",
9513
+ sourcePath,
9514
+ sourceRevision: `sha256:${createHash("sha256").update(source).digest("hex")}`,
9515
+ value: meta,
9516
+ definition: loaded.value,
9517
+ sourceClosure
9518
+ });
9519
+ }
9520
+ const parentByPackageId = new Map(
9521
+ instanceParents.map((instance) => [instance.packageId.toLowerCase(), instance])
9522
+ );
9523
+ for (const instance of instanceParents) {
9524
+ const parentId = instance.parent.toLowerCase();
9525
+ const parentPath = packageIdToPath.get(parentId);
9526
+ if (parentPath === void 0) {
9085
9527
  return packErr(
9086
- makePackError("pack-malformed-meta", {
9087
- path: sourcePath,
9088
- ajvErrors: [{ instancePath: "/subAssets", message: topology.error.code }]
9528
+ makePackError("pack-malformed-pack", {
9529
+ path: instance.path,
9530
+ reason: "pack-parent-not-found",
9531
+ ajvErrors: [
9532
+ {
9533
+ instancePath: "/parent",
9534
+ message: `parent packageId ${instance.parent} was not found`
9535
+ }
9536
+ ]
9089
9537
  })
9090
9538
  );
9091
9539
  }
9092
- ({
9093
- sourceRevision: `sha256:${createHash("sha256").update(source).digest("hex")}`,
9094
- definition: loaded.value});
9095
- for (const sub of meta.subAssets) {
9096
- const guid = sub.guid.toLowerCase();
9097
- const existing = guidToPath.get(guid);
9098
- if (existing !== void 0) {
9540
+ const kind = packageKind.get(parentId);
9541
+ if (kind !== "scriptable" && kind !== "instance") {
9542
+ return packErr(
9543
+ makePackError("pack-malformed-pack", {
9544
+ path: instance.path,
9545
+ reason: "pack-parent-has-no-parameters",
9546
+ ajvErrors: [
9547
+ {
9548
+ instancePath: "/parent",
9549
+ message: `parent ${instance.parent} is not a ScriptablePack source with parameters`
9550
+ }
9551
+ ]
9552
+ })
9553
+ );
9554
+ }
9555
+ }
9556
+ for (const instance of instanceParents) {
9557
+ const chain = /* @__PURE__ */ new Set();
9558
+ let current = instance.packageId.toLowerCase();
9559
+ while (true) {
9560
+ if (chain.has(current)) {
9099
9561
  return packErr(
9100
- makePackError("pack-guid-collision", { paths: [existing, sourcePath], guid })
9562
+ makePackError("pack-malformed-pack", {
9563
+ path: instance.path,
9564
+ reason: "pack-parent-cycle",
9565
+ ajvErrors: [
9566
+ { instancePath: "/parent", message: `parent chain repeats packageId ${current}` }
9567
+ ]
9568
+ })
9101
9569
  );
9102
9570
  }
9103
- guidToPath.set(guid, sourcePath);
9571
+ chain.add(current);
9572
+ const next = parentByPackageId.get(current);
9573
+ if (next === void 0) break;
9574
+ current = next.parent.toLowerCase();
9104
9575
  }
9105
9576
  }
9106
9577
  const visited = /* @__PURE__ */ new Set();
@@ -9139,6 +9610,59 @@ async function scanValidated(roots, opts = {}, capture) {
9139
9610
  async function scan(roots, opts = {}) {
9140
9611
  return scanValidated(roots, opts);
9141
9612
  }
9613
+ async function scanInventory(roots, opts = {}) {
9614
+ const declarations = /* @__PURE__ */ new Map();
9615
+ const scanned = await scanValidated(roots, opts, { declarations });
9616
+ if (!scanned.ok) return scanned;
9617
+ const inventory = [];
9618
+ for (const sourcePath of scanned.value) {
9619
+ const declaration = declarations.get(sourcePath);
9620
+ if (declaration?.format !== "pack.json") continue;
9621
+ if (declaration.value.schemaVersion === "3.0.0") {
9622
+ const parsed = parsePackSourceJson(declaration.value);
9623
+ if (!parsed.ok) {
9624
+ return packErr(
9625
+ makePackError("pack-malformed-pack", {
9626
+ path: sourcePath,
9627
+ ajvErrors: [{ instancePath: "", message: parsed.error.code }]
9628
+ })
9629
+ );
9630
+ }
9631
+ if (parsed.value.format !== "direct") continue;
9632
+ const projected = projectDirectPackJson(parsed.value);
9633
+ if (!projected.ok) {
9634
+ return packErr(
9635
+ makePackError("pack-malformed-pack", {
9636
+ path: sourcePath,
9637
+ ajvErrors: [{ instancePath: "/assets", message: projected.error.code }]
9638
+ })
9639
+ );
9640
+ }
9641
+ for (const [index, asset] of projected.value.assets.entries()) {
9642
+ inventory.push({
9643
+ guid: asset.guid,
9644
+ kind: asset.kind,
9645
+ sourcePath,
9646
+ sourceRevision: declaration.sourceRevision,
9647
+ sourceKey: asset.sourceKey,
9648
+ sourceIndex: index
9649
+ });
9650
+ }
9651
+ continue;
9652
+ }
9653
+ for (const [index, asset] of declaration.value.assets.entries()) {
9654
+ inventory.push({
9655
+ guid: asset.guid,
9656
+ kind: asset.kind,
9657
+ sourcePath,
9658
+ sourceRevision: declaration.sourceRevision,
9659
+ ...asset.sourceKey === void 0 ? {} : { sourceKey: asset.sourceKey },
9660
+ ...asset.sourceIndex === void 0 ? { sourceIndex: index } : { sourceIndex: asset.sourceIndex }
9661
+ });
9662
+ }
9663
+ }
9664
+ return ok4({ paths: scanned.value, inventory, declarations });
9665
+ }
9142
9666
 
9143
9667
  // src/evidence/source-inventory.ts
9144
9668
  function fingerprint(meta, source) {
@@ -9181,32 +9705,41 @@ async function readSourceInventory(request) {
9181
9705
  let authored;
9182
9706
  for (const path of paths) {
9183
9707
  if (path.endsWith(".pack.ts")) {
9184
- const loaded = await loadScriptablePack(path, { metadataOnly: true });
9185
- if (!loaded.ok) continue;
9186
- const meta = projectScriptablePackMeta(loaded.value, path);
9187
- if (meta.subAssets.some((asset) => asset.guid.toLowerCase() === guid)) {
9188
- return { origin: "sourceMeta", sourcePath: path };
9189
- }
9190
9708
  continue;
9191
9709
  }
9192
9710
  const raw = await readFile(path, "utf8").catch(() => void 0);
9193
9711
  if (raw === void 0) continue;
9194
9712
  let parsed;
9195
9713
  try {
9196
- parsed = JSON.parse(raw);
9714
+ const value = JSON.parse(raw);
9715
+ if (value === null || typeof value !== "object" || Array.isArray(value)) continue;
9716
+ parsed = value;
9197
9717
  } catch {
9198
9718
  continue;
9199
9719
  }
9200
9720
  if (path.endsWith(".pack.json")) {
9201
- if (parsed.assets?.some(
9202
- (asset) => typeof asset.guid === "string" && (asset.guid === request.guid || asset.guid.toLowerCase() === guid)
9721
+ if (parsed.schemaVersion === "3.0.0") {
9722
+ const direct = parsePackSourceJson(parsed);
9723
+ if (direct.ok && direct.value.format === "direct") {
9724
+ const projected = projectDirectPackJson(direct.value);
9725
+ if (projected.ok && projected.value.assets.some((asset) => asset.guid.toLowerCase() === guid)) {
9726
+ authored = { origin: "authoredPack", sourcePath: path };
9727
+ }
9728
+ }
9729
+ } else if (Array.isArray(parsed.assets) && parsed.assets.some(
9730
+ (asset) => asset !== null && typeof asset === "object" && !Array.isArray(asset) && typeof asset.guid === "string" && (asset.guid === request.guid || asset.guid.toLowerCase() === guid)
9203
9731
  )) {
9204
9732
  authored = { origin: "authoredPack", sourcePath: path };
9205
9733
  }
9206
9734
  continue;
9207
9735
  }
9208
9736
  if (path.endsWith(".meta.json")) {
9209
- const source = sourceFromMeta(path, parsed, request.guid, raw);
9737
+ const source = sourceFromMeta(
9738
+ path,
9739
+ parsed,
9740
+ request.guid,
9741
+ raw
9742
+ );
9210
9743
  if (source !== void 0) return source;
9211
9744
  }
9212
9745
  }
@@ -9225,6 +9758,9 @@ function parsePackV2(value) {
9225
9758
  }
9226
9759
 
9227
9760
  // src/cli-asset.ts
9761
+ function isRecord3(value) {
9762
+ return value !== null && typeof value === "object" && !Array.isArray(value);
9763
+ }
9228
9764
  function emitError2(ctx, err5) {
9229
9765
  const payload = {
9230
9766
  code: err5.code,
@@ -9236,7 +9772,7 @@ function emitError2(ctx, err5) {
9236
9772
  return 1;
9237
9773
  }
9238
9774
  async function scanEntries(roots, ctx) {
9239
- const result = await scan(roots);
9775
+ const result = await scanInventory(roots);
9240
9776
  if (!result.ok) {
9241
9777
  emitError2(ctx, {
9242
9778
  code: result.error.code,
@@ -9247,77 +9783,55 @@ async function scanEntries(roots, ctx) {
9247
9783
  return { ok: false };
9248
9784
  }
9249
9785
  const entries = [];
9250
- const packPaths = result.value.filter((p) => p.endsWith(".pack.json"));
9251
- const metaPaths = result.value.filter((p) => p.endsWith(".meta.json"));
9252
- for (const packPath of packPaths) {
9253
- let parsed;
9254
- try {
9255
- const raw = await readFile(packPath, "utf-8");
9256
- parsed = JSON.parse(raw);
9257
- } catch {
9258
- continue;
9259
- }
9260
- const packObj = parsed;
9261
- if (!Array.isArray(packObj.assets)) continue;
9262
- for (const asset of packObj.assets) {
9263
- if (typeof asset.guid === "string" && typeof asset.kind === "string") {
9264
- entries.push({
9265
- guid: asset.guid,
9266
- kind: asset.kind,
9267
- sourcePath: packPath,
9268
- ...typeof asset.name === "string" ? { name: asset.name } : {}
9269
- });
9786
+ for (const declaration of result.value.declarations.values()) {
9787
+ if (declaration.format !== "meta.json") continue;
9788
+ const sourcePath = declaration.sourcePath;
9789
+ const assets = declaration.value.subAssets;
9790
+ for (const asset of assets) {
9791
+ if (!isRecord3(asset) || typeof asset.guid !== "string" || typeof asset.kind !== "string") {
9792
+ continue;
9270
9793
  }
9794
+ const name = typeof asset.name === "string" ? asset.name : typeof asset.sourceKey === "string" ? asset.sourceKey : void 0;
9795
+ entries.push({
9796
+ guid: asset.guid,
9797
+ kind: asset.kind,
9798
+ sourcePath,
9799
+ ...name === void 0 ? {} : { name }
9800
+ });
9271
9801
  }
9272
9802
  }
9273
- for (const metaPath of metaPaths) {
9274
- let parsed;
9275
- try {
9276
- const raw = await readFile(metaPath, "utf-8");
9277
- parsed = JSON.parse(raw);
9278
- } catch {
9803
+ const names = /* @__PURE__ */ new Map();
9804
+ for (const declaration of result.value.declarations.values()) {
9805
+ if (declaration.format !== "pack.json") continue;
9806
+ if (declaration.value.schemaVersion === "3.0.0") {
9807
+ for (const [sourceKey, asset] of Object.entries(declaration.value.assets ?? {})) {
9808
+ if (isRecord3(asset) && typeof asset.name === "string") {
9809
+ names.set(`${declaration.sourcePath}:${sourceKey}`, asset.name);
9810
+ }
9811
+ }
9279
9812
  continue;
9280
9813
  }
9281
- const metaObj = parsed;
9282
- if (!Array.isArray(metaObj.subAssets)) continue;
9283
- for (const sub of metaObj.subAssets) {
9284
- if (typeof sub.guid === "string" && typeof sub.kind === "string") {
9285
- const name = typeof sub.name === "string" ? sub.name : typeof sub.sourceKey === "string" ? sub.sourceKey : void 0;
9286
- entries.push({
9287
- guid: sub.guid,
9288
- kind: sub.kind,
9289
- sourcePath: metaPath,
9290
- ...name === void 0 ? {} : { name }
9291
- });
9814
+ for (const asset of declaration.value.assets) {
9815
+ if (typeof asset.name === "string") {
9816
+ names.set(`${declaration.sourcePath}:${asset.guid.toLowerCase()}`, asset.name);
9292
9817
  }
9293
9818
  }
9294
9819
  }
9295
- for (const sourcePath of result.value.filter((path) => path.endsWith(".pack.ts"))) {
9296
- const loaded = await loadScriptablePack(sourcePath, { metadataOnly: true });
9297
- if (!loaded.ok) {
9298
- emitError2(ctx, loaded.error);
9299
- return { ok: false };
9300
- }
9301
- const meta = projectScriptablePackMeta(loaded.value, sourcePath);
9302
- for (const sub of meta.subAssets) {
9303
- entries.push({ guid: sub.guid, kind: sub.kind, sourcePath });
9304
- }
9305
- }
9306
- const firstByGuid = /* @__PURE__ */ new Map();
9307
- for (const entry of entries) {
9308
- const guid = entry.guid.toLowerCase();
9309
- const first = firstByGuid.get(guid);
9310
- if (first !== void 0) {
9311
- emitError2(ctx, {
9312
- code: "pack-guid-collision",
9313
- expected: "one author declaration per GUID across Meta, Pack v2, and ScriptablePack sources",
9314
- hint: "allocate a new durable GUID through the asset authoring gateway, then rerun verify",
9315
- detail: { guid, paths: [first.sourcePath, entry.sourcePath] }
9316
- });
9317
- return { ok: false };
9318
- }
9319
- firstByGuid.set(guid, entry);
9820
+ for (const inventoryEntry of result.value.inventory) {
9821
+ const declaration = result.value.declarations.get(inventoryEntry.sourcePath);
9822
+ const namedByKey = inventoryEntry.sourceKey === void 0 ? names.get(`${inventoryEntry.sourcePath}:${inventoryEntry.guid.toLowerCase()}`) : names.get(`${inventoryEntry.sourcePath}:${inventoryEntry.sourceKey}`);
9823
+ const name = namedByKey ?? names.get(`${inventoryEntry.sourcePath}:${inventoryEntry.guid.toLowerCase()}`);
9824
+ entries.push({
9825
+ guid: inventoryEntry.guid,
9826
+ kind: inventoryEntry.kind,
9827
+ sourcePath: inventoryEntry.sourcePath,
9828
+ ...name === void 0 ? {} : { name },
9829
+ ...declaration?.format === "pack.json" && declaration.value.schemaVersion === "3.0.0" && inventoryEntry.sourceKey !== void 0 && name === void 0 ? { name: inventoryEntry.sourceKey } : {}
9830
+ });
9320
9831
  }
9832
+ entries.sort(
9833
+ (left, right) => `${left.sourcePath}:${left.guid}`.localeCompare(`${right.sourcePath}:${right.guid}`)
9834
+ );
9321
9835
  return { ok: true, value: entries };
9322
9836
  }
9323
9837
  function helpBody() {
@@ -9400,7 +9914,9 @@ async function runMeta(rest, ctx) {
9400
9914
  });
9401
9915
  }
9402
9916
  const cwd = ctx.cwd ?? process.cwd();
9403
- const loaded = await loadScriptablePack(absolutePath(source, cwd), { metadataOnly: true });
9917
+ const loaded = await loadScriptablePack(absolutePath(source, cwd), {
9918
+ metadataOnly: true
9919
+ });
9404
9920
  if (!loaded.ok) return emitError2(ctx, loaded.error);
9405
9921
  ctx.stdoutWrite(JSON.stringify(projectScriptablePackMeta(loaded.value, source)));
9406
9922
  return 0;
@@ -9569,13 +10085,13 @@ async function readJson(path, ctx) {
9569
10085
  }
9570
10086
  }
9571
10087
  function catalogRows(value) {
9572
- if (Array.isArray(value)) return value.filter(isRecord2);
9573
- if (!isRecord2(value) || !Array.isArray(value.entries)) return void 0;
9574
- return value.entries.filter(isRecord2);
10088
+ if (Array.isArray(value)) return value.filter(isRecord3);
10089
+ if (!isRecord3(value) || !Array.isArray(value.entries)) return void 0;
10090
+ return value.entries.filter(isRecord3);
9575
10091
  }
9576
10092
  function packagePath(projectRoot, packageUrl) {
9577
- const relative3 = packageUrl.replace(/^\/+/, "");
9578
- return resolve(projectRoot, relative3);
10093
+ const relative2 = packageUrl.replace(/^\/+/, "");
10094
+ return resolve(projectRoot, relative2);
9579
10095
  }
9580
10096
  function artifactInputs(pack, packagePathValue) {
9581
10097
  return Promise.all(