@forgeax/engine-pack 0.1.23 → 0.1.25
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.
- package/README.md +12 -6
- package/dist/build.d.ts +4 -4
- package/dist/build.d.ts.map +1 -1
- package/dist/build.mjs +390 -294
- package/dist/build.mjs.map +1 -1
- package/dist/cli-asset.mjs +33 -35
- package/dist/cli-asset.mjs.map +1 -1
- package/dist/evidence/material-cook.d.ts +26 -0
- package/dist/evidence/material-cook.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +121 -27
- package/dist/index.mjs.map +1 -1
- package/dist/material-cook.d.ts +1 -1
- package/dist/material-cook.d.ts.map +1 -1
- package/dist/material-cook.mjs +102 -4
- package/dist/material-cook.mjs.map +1 -1
- package/dist/{parameterized-pack-node.d.ts → pack-authoring-node.d.ts} +7 -7
- package/dist/pack-authoring-node.d.ts.map +1 -0
- package/dist/{parameterized-pack-node.mjs → pack-authoring-node.mjs} +59 -63
- package/dist/pack-authoring-node.mjs.map +1 -0
- package/dist/{parameterized-pack.d.ts → pack-authoring.d.ts} +28 -31
- package/dist/pack-authoring.d.ts.map +1 -0
- package/dist/pack-authoring.mjs +1137 -0
- package/dist/pack-authoring.mjs.map +1 -0
- package/dist/runtime.mjs +1 -1
- package/dist/runtime.mjs.map +1 -1
- package/dist/scanner.d.ts +11 -9
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.mjs +36 -34
- package/dist/scanner.mjs.map +1 -1
- package/dist/schema.mjs +1 -1
- package/dist/schema.mjs.map +1 -1
- package/dist/scriptable-pack-node.d.ts +4 -4
- package/dist/scriptable-pack-node.d.ts.map +1 -1
- package/dist/scriptable-pack-node.mjs +18 -20
- package/dist/scriptable-pack-node.mjs.map +1 -1
- package/dist/scriptable-pack.d.ts +3 -2
- package/dist/scriptable-pack.d.ts.map +1 -1
- package/dist/scriptable-pack.mjs +19 -23
- package/dist/scriptable-pack.mjs.map +1 -1
- package/package.json +2 -7
- package/schema/pack.schema.json +1 -1
- package/src/__tests__/material-cook-receipt-layer-plan.unit.test.ts +16 -0
- package/src/__tests__/material-cook-schema.unit.test.ts +62 -0
- package/src/__tests__/material-declaration-boundary.unit.test.ts +35 -0
- package/src/__tests__/material-surface-consumer-census.test.ts +24 -0
- package/src/__tests__/material-surface-publication.unit.test.ts +159 -0
- package/src/__tests__/material-surface-wire.unit.test.ts +30 -0
- package/src/__tests__/{parameterized-pack-authoring-gateway.unit.test.ts → pack-authoring-gateway.unit.test.ts} +9 -9
- package/src/__tests__/{parameterized-pack.unit.test.ts → pack-authoring.unit.test.ts} +10 -10
- package/src/__tests__/{parameterized-pack-scanner.unit.test.ts → pack-scanner.unit.test.ts} +6 -6
- package/src/__tests__/scanner-inventory.contract.test.ts +2 -4
- package/src/__tests__/scanner-inventory.test.ts +7 -6
- package/src/__tests__/scriptable-pack-cli.integration.test.ts +1 -1
- package/src/build.ts +10 -8
- package/src/catalog-builder.ts +3 -3
- package/src/cli-asset.ts +5 -5
- package/src/evidence/material-cook.ts +170 -7
- package/src/evidence/source-inventory.ts +3 -3
- package/src/index.ts +6 -1
- package/src/material-cook.ts +3 -0
- package/src/{parameterized-pack-node.ts → pack-authoring-node.ts} +71 -73
- package/src/{parameterized-pack.ts → pack-authoring.ts} +59 -74
- package/src/scanner.ts +33 -31
- package/src/schema/material-cook.schema.json +47 -1
- package/src/scriptable-pack-node.ts +25 -25
- package/src/scriptable-pack.ts +3 -2
- package/dist/__tests__/ai-recovery.unit.test.d.ts +0 -2
- package/dist/__tests__/ai-recovery.unit.test.d.ts.map +0 -1
- package/dist/__tests__/artifact-path.test.d.ts +0 -2
- package/dist/__tests__/artifact-path.test.d.ts.map +0 -1
- package/dist/__tests__/asset-evidence-error-hints.test.d.ts +0 -2
- package/dist/__tests__/asset-evidence-error-hints.test.d.ts.map +0 -1
- package/dist/__tests__/asset-evidence-lifecycle.test.d.ts +0 -2
- package/dist/__tests__/asset-evidence-lifecycle.test.d.ts.map +0 -1
- package/dist/__tests__/asset-evidence-schema.test.d.ts +0 -2
- package/dist/__tests__/asset-evidence-schema.test.d.ts.map +0 -1
- package/dist/__tests__/atlas-cli-region-mismatch.test.d.ts +0 -2
- package/dist/__tests__/atlas-cli-region-mismatch.test.d.ts.map +0 -1
- package/dist/__tests__/atlas-error-code-owner.test-d.d.ts +0 -2
- package/dist/__tests__/atlas-error-code-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/cli-asset-evidence.integration.test.d.ts +0 -2
- package/dist/__tests__/cli-asset-evidence.integration.test.d.ts.map +0 -1
- package/dist/__tests__/cli.unit.test.d.ts +0 -2
- package/dist/__tests__/cli.unit.test.d.ts.map +0 -1
- package/dist/__tests__/evidence-source-inventory.unit.test.d.ts +0 -2
- package/dist/__tests__/evidence-source-inventory.unit.test.d.ts.map +0 -1
- package/dist/__tests__/guid-collision.unit.test.d.ts +0 -2
- package/dist/__tests__/guid-collision.unit.test.d.ts.map +0 -1
- package/dist/__tests__/guid-validator-surface.unit.test.d.ts +0 -2
- package/dist/__tests__/guid-validator-surface.unit.test.d.ts.map +0 -1
- package/dist/__tests__/inventory-schema.test.d.ts +0 -2
- package/dist/__tests__/inventory-schema.test.d.ts.map +0 -1
- package/dist/__tests__/material-cook-dependencies.unit.test.d.ts +0 -2
- package/dist/__tests__/material-cook-dependencies.unit.test.d.ts.map +0 -1
- package/dist/__tests__/material-cook-receipt.unit.test.d.ts +0 -2
- package/dist/__tests__/material-cook-receipt.unit.test.d.ts.map +0 -1
- package/dist/__tests__/material-cook-schema.unit.test.d.ts +0 -2
- package/dist/__tests__/material-cook-schema.unit.test.d.ts.map +0 -1
- package/dist/__tests__/mesh-bin-consumer-surface.unit.test.d.ts +0 -2
- package/dist/__tests__/mesh-bin-consumer-surface.unit.test.d.ts.map +0 -1
- package/dist/__tests__/mesh-bin-contract.unit.test.d.ts +0 -2
- package/dist/__tests__/mesh-bin-contract.unit.test.d.ts.map +0 -1
- package/dist/__tests__/meta-schema-optional.test.d.ts +0 -2
- package/dist/__tests__/meta-schema-optional.test.d.ts.map +0 -1
- package/dist/__tests__/meta-source-overrides.unit.test.d.ts +0 -2
- package/dist/__tests__/meta-source-overrides.unit.test.d.ts.map +0 -1
- package/dist/__tests__/native-cooker-registry.test.d.ts +0 -2
- package/dist/__tests__/native-cooker-registry.test.d.ts.map +0 -1
- package/dist/__tests__/offline-evidence-artifact-verification-owner.test-d.d.ts +0 -2
- package/dist/__tests__/offline-evidence-artifact-verification-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/offline-evidence.integration.test.d.ts +0 -2
- package/dist/__tests__/offline-evidence.integration.test.d.ts.map +0 -1
- package/dist/__tests__/owner-chain.integration.test.d.ts +0 -2
- package/dist/__tests__/owner-chain.integration.test.d.ts.map +0 -1
- package/dist/__tests__/pack-v2-fixture-migration.test.d.ts +0 -2
- package/dist/__tests__/pack-v2-fixture-migration.test.d.ts.map +0 -1
- package/dist/__tests__/pack-v2-schema.test.d.ts +0 -2
- package/dist/__tests__/pack-v2-schema.test.d.ts.map +0 -1
- package/dist/__tests__/pack.unit.test.d.ts +0 -2
- package/dist/__tests__/pack.unit.test.d.ts.map +0 -1
- package/dist/__tests__/package-finalizer.contract.test.d.ts +0 -2
- package/dist/__tests__/package-finalizer.contract.test.d.ts.map +0 -1
- package/dist/__tests__/parameterized-pack-authoring-gateway.unit.test.d.ts +0 -2
- package/dist/__tests__/parameterized-pack-authoring-gateway.unit.test.d.ts.map +0 -1
- package/dist/__tests__/parameterized-pack-scanner.unit.test.d.ts +0 -2
- package/dist/__tests__/parameterized-pack-scanner.unit.test.d.ts.map +0 -1
- package/dist/__tests__/parameterized-pack.unit.test.d.ts +0 -2
- package/dist/__tests__/parameterized-pack.unit.test.d.ts.map +0 -1
- package/dist/__tests__/producer-contract-schema.unit.test.d.ts +0 -2
- package/dist/__tests__/producer-contract-schema.unit.test.d.ts.map +0 -1
- package/dist/__tests__/resolve-asset-source.test.d.ts +0 -2
- package/dist/__tests__/resolve-asset-source.test.d.ts.map +0 -1
- package/dist/__tests__/runtime-projection.unit.test.d.ts +0 -2
- package/dist/__tests__/runtime-projection.unit.test.d.ts.map +0 -1
- package/dist/__tests__/runtime.browser.test.d.ts +0 -2
- package/dist/__tests__/runtime.browser.test.d.ts.map +0 -1
- package/dist/__tests__/scanner-blacklist.test.d.ts +0 -2
- package/dist/__tests__/scanner-blacklist.test.d.ts.map +0 -1
- package/dist/__tests__/scanner-inventory.contract.test.d.ts +0 -2
- package/dist/__tests__/scanner-inventory.contract.test.d.ts.map +0 -1
- package/dist/__tests__/scanner-inventory.test.d.ts +0 -2
- package/dist/__tests__/scanner-inventory.test.d.ts.map +0 -1
- package/dist/__tests__/scanner-mount-cycle.test.d.ts +0 -2
- package/dist/__tests__/scanner-mount-cycle.test.d.ts.map +0 -1
- package/dist/__tests__/scriptable-pack-cli.integration.test.d.ts +0 -2
- package/dist/__tests__/scriptable-pack-cli.integration.test.d.ts.map +0 -1
- package/dist/__tests__/scriptable-pack-ddc-key.unit.test.d.ts +0 -2
- package/dist/__tests__/scriptable-pack-ddc-key.unit.test.d.ts.map +0 -1
- package/dist/__tests__/topology-actions.unit.test.d.ts +0 -2
- package/dist/__tests__/topology-actions.unit.test.d.ts.map +0 -1
- package/dist/__tests__/topology.unit.test.d.ts +0 -2
- package/dist/__tests__/topology.unit.test.d.ts.map +0 -1
- package/dist/parameterized-pack-node.d.ts.map +0 -1
- package/dist/parameterized-pack-node.mjs.map +0 -1
- package/dist/parameterized-pack.d.ts.map +0 -1
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
MaterialValue,
|
|
8
8
|
Result,
|
|
9
9
|
} from '@forgeax/engine-types';
|
|
10
|
-
import { err, MATERIAL_TEXTURE_SLOTS, ok } from '@forgeax/engine-types';
|
|
10
|
+
import { deriveStandardLayerPlan, err, MATERIAL_TEXTURE_SLOTS, ok } from '@forgeax/engine-types';
|
|
11
11
|
import { sha256 } from '@noble/hashes/sha2.js';
|
|
12
12
|
import { bytesToHex } from '@noble/hashes/utils.js';
|
|
13
13
|
|
|
@@ -25,6 +25,19 @@ export interface MaterialCookArtifact {
|
|
|
25
25
|
readonly bytes: Uint8Array;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/** Backend capability projection for one immutable cooked material artifact. */
|
|
29
|
+
export interface MaterialCookVariantContext {
|
|
30
|
+
readonly backend: 'webgpu' | 'webgl2' | 'wgpu-native';
|
|
31
|
+
readonly capability: 'storage-buffer' | 'uniform-fallback';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Additional backend artifact published with one material generation. */
|
|
35
|
+
export interface MaterialCookVariant {
|
|
36
|
+
readonly context: MaterialCookVariantContext;
|
|
37
|
+
readonly specializationKey: string;
|
|
38
|
+
readonly artifact: MaterialCookArtifact;
|
|
39
|
+
}
|
|
40
|
+
|
|
28
41
|
export interface MaterialCookWasmProvenance {
|
|
29
42
|
readonly sourceContentKey: string;
|
|
30
43
|
readonly artifactSha256: string;
|
|
@@ -56,7 +69,11 @@ export interface MaterialCookReceipt {
|
|
|
56
69
|
readonly profile: string;
|
|
57
70
|
readonly compilerVersion: string;
|
|
58
71
|
readonly identity: MaterialCookIdentity;
|
|
59
|
-
readonly derivedInterface: {
|
|
72
|
+
readonly derivedInterface: {
|
|
73
|
+
readonly layoutIdentity: string;
|
|
74
|
+
/** Build-time Standard physical lowering identity, when the root is Standard. */
|
|
75
|
+
readonly layerPlanIdentity?: string;
|
|
76
|
+
};
|
|
60
77
|
}
|
|
61
78
|
|
|
62
79
|
export interface MaterialParameterContract {
|
|
@@ -71,6 +88,10 @@ export interface CookedMaterialRecord {
|
|
|
71
88
|
readonly materialGuid?: string;
|
|
72
89
|
readonly publicationGeneration?: number;
|
|
73
90
|
readonly specializationKey?: string;
|
|
91
|
+
/** Compiler context used by the primary `artifact` entry. */
|
|
92
|
+
readonly variantContext?: MaterialCookVariantContext;
|
|
93
|
+
/** Additional immutable artifacts for other backend capability lanes. */
|
|
94
|
+
readonly variants?: readonly MaterialCookVariant[];
|
|
74
95
|
readonly artifactDigest?: string;
|
|
75
96
|
readonly sourceClosure?: readonly string[];
|
|
76
97
|
readonly parameterContract?: MaterialParameterContract;
|
|
@@ -101,6 +122,37 @@ export interface MaterialCookIdentityExpectation {
|
|
|
101
122
|
readonly inputDigest?: string;
|
|
102
123
|
}
|
|
103
124
|
|
|
125
|
+
const STANDARD_ROOT_MODULES = new Set([
|
|
126
|
+
'forgeax::default-standard-pbr',
|
|
127
|
+
'forgeax::pbr-skin',
|
|
128
|
+
'forgeax_material::standard',
|
|
129
|
+
'forgeax_material::pbr-skin',
|
|
130
|
+
'forgeax::default-shadow-caster',
|
|
131
|
+
]);
|
|
132
|
+
|
|
133
|
+
/** Shared ownership predicate for the built-in Standard material root. */
|
|
134
|
+
export function isStandardRootModule(module: string): boolean {
|
|
135
|
+
return STANDARD_ROOT_MODULES.has(module);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function isStandardMaterialRecord(record: Pick<CookedMaterialRecord, 'resolved'>): boolean {
|
|
139
|
+
return record.resolved.passes.some((pass) => isStandardRootModule(pass.program.module));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Recompute the Standard layer identity from the admitted resolved root.
|
|
144
|
+
* Material admission and runtime loading share this owner so a stale receipt
|
|
145
|
+
* cannot select a different physical layer plan after cooking.
|
|
146
|
+
*/
|
|
147
|
+
export function materialLayerPlanIdentity(
|
|
148
|
+
record: Pick<CookedMaterialRecord, 'resolved'>,
|
|
149
|
+
): string | undefined {
|
|
150
|
+
if (!isStandardMaterialRecord(record)) {
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
return deriveStandardLayerPlan(record.resolved.parameters, record.resolved.passes).identity;
|
|
154
|
+
}
|
|
155
|
+
|
|
104
156
|
function unique(values: readonly string[]): readonly string[] {
|
|
105
157
|
return [...new Set(values)].sort();
|
|
106
158
|
}
|
|
@@ -224,6 +276,17 @@ function invalid(field: string, actual?: unknown): Result<never, MaterialCookRec
|
|
|
224
276
|
});
|
|
225
277
|
}
|
|
226
278
|
|
|
279
|
+
function normalizeArtifactBytes(value: unknown): Uint8Array | undefined {
|
|
280
|
+
if (Array.isArray(value)) {
|
|
281
|
+
return value.every((byte) => Number.isInteger(byte) && byte >= 0 && byte <= 255)
|
|
282
|
+
? Uint8Array.from(value)
|
|
283
|
+
: undefined;
|
|
284
|
+
}
|
|
285
|
+
if (!ArrayBuffer.isView(value)) return undefined;
|
|
286
|
+
const view = value as ArrayBufferView;
|
|
287
|
+
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength).slice();
|
|
288
|
+
}
|
|
289
|
+
|
|
227
290
|
const IDENTITY_FIELDS = [
|
|
228
291
|
'materialContractDigest',
|
|
229
292
|
'sourceRevision',
|
|
@@ -286,6 +349,16 @@ export function validateMaterialCookReceipt(
|
|
|
286
349
|
if (derivedInterface.layoutIdentity !== identity.layoutIdentity) {
|
|
287
350
|
return invalid('receipt.derivedInterface.layoutIdentity', derivedInterface.layoutIdentity);
|
|
288
351
|
}
|
|
352
|
+
if (
|
|
353
|
+
derivedInterface.layerPlanIdentity !== undefined &&
|
|
354
|
+
(typeof derivedInterface.layerPlanIdentity !== 'string' ||
|
|
355
|
+
derivedInterface.layerPlanIdentity.length === 0)
|
|
356
|
+
) {
|
|
357
|
+
return invalid(
|
|
358
|
+
'receipt.derivedInterface.layerPlanIdentity',
|
|
359
|
+
derivedInterface.layerPlanIdentity,
|
|
360
|
+
);
|
|
361
|
+
}
|
|
289
362
|
for (const field of ['sourceClosure', 'profile', 'compilerVersion']) {
|
|
290
363
|
const fieldValue = candidate[field];
|
|
291
364
|
if (
|
|
@@ -320,7 +393,12 @@ export function validateMaterialCookReceipt(
|
|
|
320
393
|
profile: candidate.profile as string,
|
|
321
394
|
compilerVersion: candidate.compilerVersion as string,
|
|
322
395
|
identity,
|
|
323
|
-
derivedInterface: {
|
|
396
|
+
derivedInterface: {
|
|
397
|
+
layoutIdentity: derivedInterface.layoutIdentity as string,
|
|
398
|
+
...(derivedInterface.layerPlanIdentity === undefined
|
|
399
|
+
? {}
|
|
400
|
+
: { layerPlanIdentity: derivedInterface.layerPlanIdentity as string }),
|
|
401
|
+
},
|
|
324
402
|
});
|
|
325
403
|
}
|
|
326
404
|
|
|
@@ -341,6 +419,49 @@ export function validateCookedMaterialRecord(
|
|
|
341
419
|
return invalid('publicationGeneration', candidate.publicationGeneration);
|
|
342
420
|
if (candidate.specializationKey !== undefined && typeof candidate.specializationKey !== 'string')
|
|
343
421
|
return invalid('specializationKey');
|
|
422
|
+
if (candidate.variantContext !== undefined) {
|
|
423
|
+
if (candidate.variantContext === null || typeof candidate.variantContext !== 'object')
|
|
424
|
+
return invalid('variantContext');
|
|
425
|
+
const context = candidate.variantContext as Record<string, unknown>;
|
|
426
|
+
if (
|
|
427
|
+
(context.backend !== 'webgpu' &&
|
|
428
|
+
context.backend !== 'webgl2' &&
|
|
429
|
+
context.backend !== 'wgpu-native') ||
|
|
430
|
+
(context.capability !== 'storage-buffer' && context.capability !== 'uniform-fallback')
|
|
431
|
+
)
|
|
432
|
+
return invalid('variantContext', candidate.variantContext);
|
|
433
|
+
}
|
|
434
|
+
if (candidate.variants !== undefined) {
|
|
435
|
+
if (!Array.isArray(candidate.variants)) return invalid('variants');
|
|
436
|
+
for (const [index, value] of candidate.variants.entries()) {
|
|
437
|
+
if (value === null || typeof value !== 'object') return invalid(`variants[${index}]`);
|
|
438
|
+
const variant = value as Record<string, unknown>;
|
|
439
|
+
const context = variant.context;
|
|
440
|
+
if (context === null || typeof context !== 'object')
|
|
441
|
+
return invalid(`variants[${index}].context`);
|
|
442
|
+
const contextRecord = context as Record<string, unknown>;
|
|
443
|
+
if (
|
|
444
|
+
(contextRecord.backend !== 'webgpu' &&
|
|
445
|
+
contextRecord.backend !== 'webgl2' &&
|
|
446
|
+
contextRecord.backend !== 'wgpu-native') ||
|
|
447
|
+
(contextRecord.capability !== 'storage-buffer' &&
|
|
448
|
+
contextRecord.capability !== 'uniform-fallback')
|
|
449
|
+
)
|
|
450
|
+
return invalid(`variants[${index}].context`, context);
|
|
451
|
+
if (typeof variant.specializationKey !== 'string' || variant.specializationKey.length === 0)
|
|
452
|
+
return invalid(`variants[${index}].specializationKey`);
|
|
453
|
+
if (variant.artifact === null || typeof variant.artifact !== 'object')
|
|
454
|
+
return invalid(`variants[${index}].artifact`);
|
|
455
|
+
const variantArtifact = variant.artifact as Record<string, unknown>;
|
|
456
|
+
if (
|
|
457
|
+
typeof variantArtifact.mediaType !== 'string' ||
|
|
458
|
+
typeof variantArtifact.path !== 'string' ||
|
|
459
|
+
typeof variantArtifact.digest !== 'string' ||
|
|
460
|
+
normalizeArtifactBytes(variantArtifact.bytes) === undefined
|
|
461
|
+
)
|
|
462
|
+
return invalid(`variants[${index}].artifact`);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
344
465
|
if (candidate.artifactDigest !== undefined && typeof candidate.artifactDigest !== 'string')
|
|
345
466
|
return invalid('artifactDigest');
|
|
346
467
|
if (
|
|
@@ -380,6 +501,33 @@ export function validateCookedMaterialRecord(
|
|
|
380
501
|
artifactDigest: artifact.digest as string,
|
|
381
502
|
});
|
|
382
503
|
if (!receiptResult.ok) return receiptResult;
|
|
504
|
+
const resolved = candidate.resolved as Record<string, unknown>;
|
|
505
|
+
if (!Array.isArray(resolved.passes)) return invalid('resolved.passes', resolved.passes);
|
|
506
|
+
if (!Array.isArray(resolved.parameters))
|
|
507
|
+
return invalid('resolved.parameters', resolved.parameters);
|
|
508
|
+
if (
|
|
509
|
+
resolved.values === null ||
|
|
510
|
+
typeof resolved.values !== 'object' ||
|
|
511
|
+
Array.isArray(resolved.values)
|
|
512
|
+
)
|
|
513
|
+
return invalid('resolved.values', resolved.values);
|
|
514
|
+
let expectedLayerPlanIdentity: string | undefined;
|
|
515
|
+
try {
|
|
516
|
+
expectedLayerPlanIdentity = materialLayerPlanIdentity({
|
|
517
|
+
resolved: resolved as unknown as CookedMaterialRecord['resolved'],
|
|
518
|
+
});
|
|
519
|
+
} catch (error) {
|
|
520
|
+
return invalid('resolved.layerPlanIdentity', error instanceof Error ? error.message : error);
|
|
521
|
+
}
|
|
522
|
+
if (
|
|
523
|
+
expectedLayerPlanIdentity !== undefined &&
|
|
524
|
+
receiptResult.value.derivedInterface.layerPlanIdentity !== expectedLayerPlanIdentity
|
|
525
|
+
) {
|
|
526
|
+
return invalid(
|
|
527
|
+
'receipt.derivedInterface.layerPlanIdentity',
|
|
528
|
+
receiptResult.value.derivedInterface.layerPlanIdentity,
|
|
529
|
+
);
|
|
530
|
+
}
|
|
383
531
|
if (candidate.artifactDigest !== undefined && candidate.artifactDigest !== artifact.digest)
|
|
384
532
|
return invalid('artifactDigest', candidate.artifactDigest);
|
|
385
533
|
if (
|
|
@@ -391,12 +539,25 @@ export function validateCookedMaterialRecord(
|
|
|
391
539
|
...candidate,
|
|
392
540
|
artifact: {
|
|
393
541
|
...artifact,
|
|
394
|
-
bytes:
|
|
395
|
-
? Uint8Array.from(artifact.bytes as Uint8Array)
|
|
396
|
-
: Uint8Array.from(artifact.bytes as number[]),
|
|
542
|
+
bytes: normalizeArtifactBytes(artifact.bytes) as Uint8Array,
|
|
397
543
|
},
|
|
544
|
+
...(Array.isArray(candidate.variants)
|
|
545
|
+
? {
|
|
546
|
+
variants: candidate.variants.map((value) => {
|
|
547
|
+
const variant = value as Record<string, unknown>;
|
|
548
|
+
const variantArtifact = variant.artifact as Record<string, unknown>;
|
|
549
|
+
return {
|
|
550
|
+
...variant,
|
|
551
|
+
artifact: {
|
|
552
|
+
...variantArtifact,
|
|
553
|
+
bytes: normalizeArtifactBytes(variantArtifact.bytes) as Uint8Array,
|
|
554
|
+
},
|
|
555
|
+
};
|
|
556
|
+
}),
|
|
557
|
+
}
|
|
558
|
+
: {}),
|
|
398
559
|
receipt: receiptResult.value,
|
|
399
|
-
} as CookedMaterialRecord;
|
|
560
|
+
} as unknown as CookedMaterialRecord;
|
|
400
561
|
return ok(normalized);
|
|
401
562
|
}
|
|
402
563
|
|
|
@@ -407,6 +568,8 @@ export function projectCookedMaterialRecord(
|
|
|
407
568
|
resolved: record.resolved,
|
|
408
569
|
refs: record.refs,
|
|
409
570
|
artifact: record.artifact,
|
|
571
|
+
...(record.variantContext === undefined ? {} : { variantContext: record.variantContext }),
|
|
572
|
+
...(record.variants === undefined ? {} : { variants: record.variants }),
|
|
410
573
|
receipt: record.receipt,
|
|
411
574
|
schemaVersion: record.schemaVersion,
|
|
412
575
|
};
|
|
@@ -2,7 +2,7 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
import { readdir, readFile } from 'node:fs/promises';
|
|
3
3
|
import { basename, dirname, join, relative, resolve, sep } from 'node:path';
|
|
4
4
|
import type { SourceDeclarationEvidence } from '@forgeax/engine-types';
|
|
5
|
-
import {
|
|
5
|
+
import { parsePackSourceJson, projectDirectPackJson } from '../pack-authoring.js';
|
|
6
6
|
import { SCANNER_BLACKLIST, scan } from '../scanner.js';
|
|
7
7
|
|
|
8
8
|
/** Project root and GUID used to locate an authoritative source declaration. */
|
|
@@ -149,7 +149,7 @@ export async function readSourceInventory(
|
|
|
149
149
|
let authored: SourceDeclarationEvidence | undefined;
|
|
150
150
|
for (const path of paths) {
|
|
151
151
|
if (path.endsWith('.pack.ts')) {
|
|
152
|
-
//
|
|
152
|
+
// ScriptablePack source identity is a build result, not a declaration
|
|
153
153
|
// table. The source index therefore records the source only after the
|
|
154
154
|
// producer publishes its materialized Pack output.
|
|
155
155
|
continue;
|
|
@@ -166,7 +166,7 @@ export async function readSourceInventory(
|
|
|
166
166
|
}
|
|
167
167
|
if (path.endsWith('.pack.json')) {
|
|
168
168
|
if (parsed.schemaVersion === '3.0.0') {
|
|
169
|
-
const direct =
|
|
169
|
+
const direct = parsePackSourceJson(parsed);
|
|
170
170
|
if (direct.ok && direct.value.format === 'direct') {
|
|
171
171
|
const projected = projectDirectPackJson(direct.value);
|
|
172
172
|
if (
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,8 @@ export {
|
|
|
7
7
|
collectMaterialCookRefs,
|
|
8
8
|
createMaterialArtifactDigest,
|
|
9
9
|
createMaterialCookIdentity,
|
|
10
|
+
isStandardMaterialRecord,
|
|
11
|
+
isStandardRootModule,
|
|
10
12
|
type MaterialCookArtifact,
|
|
11
13
|
type MaterialCookIdentity,
|
|
12
14
|
type MaterialCookIdentityExpectation,
|
|
@@ -14,7 +16,10 @@ export {
|
|
|
14
16
|
type MaterialCookReceipt,
|
|
15
17
|
type MaterialCookRecordError,
|
|
16
18
|
type MaterialCookRefs,
|
|
19
|
+
type MaterialCookVariant,
|
|
20
|
+
type MaterialCookVariantContext,
|
|
17
21
|
type MaterialCookWasmProvenance,
|
|
22
|
+
materialLayerPlanIdentity,
|
|
18
23
|
projectCookedMaterialRecord,
|
|
19
24
|
serializeCookedMaterialRecord,
|
|
20
25
|
serializeMaterialCookReceipt,
|
|
@@ -40,7 +45,7 @@ export {
|
|
|
40
45
|
type MeshBinHeaderV4,
|
|
41
46
|
writeMeshBinHeader,
|
|
42
47
|
} from './mesh-bin-contract.js';
|
|
43
|
-
export * from './
|
|
48
|
+
export * from './pack-authoring.js';
|
|
44
49
|
export { validateProducerContract, validateProducerOutputs } from './producer-contract.js';
|
|
45
50
|
export {
|
|
46
51
|
type AssetReader,
|
package/src/material-cook.ts
CHANGED
|
@@ -7,7 +7,10 @@ export {
|
|
|
7
7
|
type MaterialCookReceipt,
|
|
8
8
|
type MaterialCookRecordError,
|
|
9
9
|
type MaterialCookRefs,
|
|
10
|
+
type MaterialCookVariant,
|
|
11
|
+
type MaterialCookVariantContext,
|
|
10
12
|
type MaterialCookWasmProvenance,
|
|
13
|
+
materialLayerPlanIdentity,
|
|
11
14
|
projectCookedMaterialRecord,
|
|
12
15
|
serializeCookedMaterialRecord,
|
|
13
16
|
serializeMaterialCookReceipt,
|