@pulse-compute/wasm-compiler 0.0.0 → 1.0.0-beta.2

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 (104) hide show
  1. package/README.md +53 -1
  2. package/bin/provider-proof-composition.js +34 -0
  3. package/bin/pulsewasm-extract.js +20 -0
  4. package/package.json +60 -5
  5. package/src/artifacts-dir.js +13 -0
  6. package/src/ast-json.js +52 -0
  7. package/src/build-manifest.js +354 -0
  8. package/src/canonical-api-compiler.js +269 -0
  9. package/src/canonical-native-compiler.js +411 -0
  10. package/src/canonical-native-plan.js +1478 -0
  11. package/src/canonical-project-compiler.js +1224 -0
  12. package/src/canonical-router-compiler.js +25 -0
  13. package/src/cli-intents.js +1235 -0
  14. package/src/cli.js +1927 -0
  15. package/src/codegen/assemblyscript-compile.js +3 -0
  16. package/src/codegen/assemblyscript-core.js +3 -0
  17. package/src/codegen/assemblyscript-shape.js +3 -0
  18. package/src/codegen/assemblyscript-wasm-smoke.js +3 -0
  19. package/src/codegen/backend-capabilities.js +3 -0
  20. package/src/codegen/channel-broadcaster.js +3 -0
  21. package/src/codegen/compiled-handlers.js +3 -0
  22. package/src/codegen/compiled-wasm-runtime.js +3 -0
  23. package/src/codegen/config-references.js +248 -0
  24. package/src/codegen/dispatch-ts.js +145 -0
  25. package/src/codegen/effect-composition.js +331 -0
  26. package/src/codegen/effect-runtime.js +418 -0
  27. package/src/codegen/execution-harness-ts.js +467 -0
  28. package/src/codegen/handler-bindings-ts.js +298 -0
  29. package/src/codegen/handler-library-contracts.js +3 -0
  30. package/src/codegen/host-capabilities.js +3 -0
  31. package/src/codegen/host-runtime-kernel.js +3 -0
  32. package/src/codegen/integrated-compiled-app.js +3 -0
  33. package/src/codegen/json-body.js +3 -0
  34. package/src/codegen/library-sidecars.js +3 -0
  35. package/src/codegen/local-harness-ts.js +453 -0
  36. package/src/codegen/pulse-wrapper.js +217 -0
  37. package/src/codegen/request-result-headers.js +3 -0
  38. package/src/codegen/schema-json-compile.js +3 -0
  39. package/src/codegen/schema-json-sidecar-v2.js +3 -0
  40. package/src/codegen/schema-json-sidecar.js +3 -0
  41. package/src/codegen/streaming-passthrough.js +3 -0
  42. package/src/codegen/wasm-host-abi.js +3 -0
  43. package/src/codegen/wasm-host-bridge.js +3 -0
  44. package/src/compiled-wasm-host-runtime-kv.js +3 -0
  45. package/src/config-resolver.js +813 -0
  46. package/src/crypto-requirement-planner.js +89 -0
  47. package/src/definitions/config-schema.js +14 -0
  48. package/src/definitions/handler-roles.js +14 -0
  49. package/src/definitions/path-grammar.js +14 -0
  50. package/src/definitions/router-api.js +14 -0
  51. package/src/diagnostics/codes.js +14 -0
  52. package/src/diagnostics/reporter.js +14 -0
  53. package/src/diagnostics.js +14 -0
  54. package/src/dispatch-table.js +400 -0
  55. package/src/events/event-emit.js +265 -0
  56. package/src/events/event-topology.js +127 -0
  57. package/src/execution-plan.js +463 -0
  58. package/src/extractor.js +2816 -0
  59. package/src/handler-eval.js +1154 -0
  60. package/src/handler-table.js +326 -0
  61. package/src/index.js +19 -0
  62. package/src/javascript-application-plan.js +181 -0
  63. package/src/kv-provider.js +3 -0
  64. package/src/path-table.js +60 -0
  65. package/src/path.js +14 -0
  66. package/src/patterns/config-define.js +30 -0
  67. package/src/patterns/dependency-call.js +18 -0
  68. package/src/patterns/env-lookup.js +13 -0
  69. package/src/patterns/handler-reference.js +29 -0
  70. package/src/patterns/path-literal.js +35 -0
  71. package/src/patterns/result.js +15 -0
  72. package/src/patterns/router-chain-call.js +50 -0
  73. package/src/patterns/router-construction.js +19 -0
  74. package/src/project/package-reachability.js +782 -0
  75. package/src/project/reachable-graph-builder.js +992 -0
  76. package/src/project/reachable-graph-contract.js +54 -0
  77. package/src/project/reachable-graph-implementation.js +36 -0
  78. package/src/project/router-module-linker.js +710 -0
  79. package/src/project-config-compiler.js +222 -0
  80. package/src/project-target-support.js +500 -0
  81. package/src/provider-toolchain.js +299 -0
  82. package/src/spine/async-surface-normalizer.js +328 -0
  83. package/src/spine/canonical-handler-ir.js +336 -0
  84. package/src/spine/canonical-native-module.js +87 -0
  85. package/src/spine/canonical-native-plan.js +89 -0
  86. package/src/spine/canonical-project.js +76 -0
  87. package/src/spine/canonical-router.js +155 -0
  88. package/src/spine/canonical-source.js +165 -0
  89. package/src/spine/diagnostic-authority.js +290 -0
  90. package/src/spine/equivalence.js +262 -0
  91. package/src/spine/guest-unit-stage.js +87 -0
  92. package/src/spine/handler-ir-emitter.js +455 -0
  93. package/src/spine/handler-ir-managed.js +1598 -0
  94. package/src/spine/handler-ir.js +797 -0
  95. package/src/spine/handler-surface-authority.js +588 -0
  96. package/src/spine/package-operation-seam.js +1015 -0
  97. package/src/spine/pipeline.js +202 -0
  98. package/src/spine/plain-handler-frontend.js +545 -0
  99. package/src/spine/provider-requirement-authority.js +208 -0
  100. package/src/spine/router-control-contract.js +17 -0
  101. package/src/spine/router-handler-frontend.js +514 -0
  102. package/src/spine/router-handler-ir.js +372 -0
  103. package/src/spine/router-topology-frontend.js +638 -0
  104. package/src/stable-id.js +14 -0
@@ -0,0 +1,1015 @@
1
+ 'use strict';
2
+
3
+ const crypto = require('node:crypto');
4
+ const fs = require('node:fs');
5
+ const { createRequire } = require('node:module');
6
+ const path = require('node:path');
7
+ const ts = require('typescript');
8
+ const { discoverLowerableLibraryManifests } = require('@pulse-compute/wasm-library-kit/compiler/handler-library-contracts');
9
+ const { buildPackageOwnedLoweringPlan } = require('@pulse-compute/wasm-library-kit/compiler/package-lowering');
10
+ const {
11
+ CANONICAL_PACKAGE_OPERATION_VERSION,
12
+ PACKAGE_LOWERING_BUNDLE_VERSION,
13
+ PACKAGE_CONTRACT_CATALOG_VERSION,
14
+ PACKAGE_CRYPTO_REQUIREMENT_VERSION,
15
+ PACKAGE_INTRINSIC_VERSION,
16
+ PACKAGE_INSPECTION_ARTIFACT_VERSION,
17
+ PACKAGE_MANAGED_HANDLER_DESCRIPTOR_VERSION,
18
+ CANONICAL_PACKAGE_EFFECT_FIELDS,
19
+ createCanonicalPackageOperation,
20
+ normalizeCanonicalPackageOperation,
21
+ normalizePackageLoweringBundle,
22
+ normalizeGuestUnitContribution,
23
+ normalizeCanonicalGuestUnitContribution
24
+ } = require('@pulse-compute/wasm-contracts/package/package-contract');
25
+ const {
26
+ CRYPTO_SEMANTIC_OWNER
27
+ } = require('@pulse-compute/wasm-contracts/crypto/contracts');
28
+
29
+ function loadPackageContractDiscovery() {
30
+ try {
31
+ return require('@pulse-compute/wasm-library-kit/compiler/package-contracts');
32
+ } catch (error) {
33
+ if (error && error.code === 'MODULE_NOT_FOUND' && String(error.message).includes('@pulse-compute/wasm-library-kit')) {
34
+ return require('../../../library-kit/src/compiler/package-contracts.js');
35
+ }
36
+ throw error;
37
+ }
38
+ }
39
+ const { discoverPulsePackageContracts } = loadPackageContractDiscovery();
40
+
41
+ const PACKAGE_OPERATION_RECOGNITION_VERSION = 'pulse.package-operation-recognition.v1';
42
+ const PACKAGE_RESULT_ADAPTER_VERSION = 'pulse.package-result-adapter.v1';
43
+ const recognitionsByCompiled = new WeakMap();
44
+
45
+ class PackageOperationSeamError extends Error {
46
+ constructor(code, message, detail = {}) {
47
+ super(message);
48
+ this.name = 'PackageOperationSeamError';
49
+ this.code = code;
50
+ this.detail = Object.freeze({ ...detail });
51
+ }
52
+ }
53
+
54
+ function cloneJson(value) {
55
+ if (Array.isArray(value)) return value.map(cloneJson);
56
+ if (!value || typeof value !== 'object') return value;
57
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, cloneJson(child)]));
58
+ }
59
+
60
+ function deepFreeze(value) {
61
+ if (!value || typeof value !== 'object' || Object.isFrozen(value)) return value;
62
+ for (const child of Object.values(value)) deepFreeze(child);
63
+ return Object.freeze(value);
64
+ }
65
+
66
+ function sortedUnique(values) {
67
+ return Object.freeze([...new Set((values || []).filter((value) => typeof value === 'string' && value.length > 0))].sort());
68
+ }
69
+
70
+ function sha256(value) {
71
+ return crypto.createHash('sha256').update(value).digest('hex');
72
+ }
73
+
74
+ function catalogDescriptor(record, productRecord) {
75
+ const manifest = record && record.manifest || {};
76
+ const validation = record && record.validation || {};
77
+ const compiler = manifest.compiler && typeof manifest.compiler === 'object' ? manifest.compiler : {};
78
+ const facade = manifest.facade && typeof manifest.facade === 'object' ? manifest.facade : {};
79
+ const wasm = manifest.modes && manifest.modes.wasm || {};
80
+ const jsEngine = manifest.modes && (manifest.modes.jsEngine || manifest.modes.js_engine || manifest.modes['js-engine']) || {};
81
+ const product = productRecord && productRecord.contract || null;
82
+ const nativeSupported = Boolean(
83
+ product
84
+ && ['supported', 'provider-dependent'].includes(product.targets.native.status)
85
+ && compiler.trust === 'first-party'
86
+ && validation.status === 'ok'
87
+ && wasm.mode !== 'lowering-plan-only'
88
+ && wasm.sidecar
89
+ );
90
+ const javascriptDeclared = Boolean(
91
+ product
92
+ && ['supported', 'provider-dependent'].includes(product.targets.javascript.status)
93
+ && jsEngine.behavior
94
+ && !['lowering-marker-only', 'runtime-not-realized'].includes(jsEngine.behavior)
95
+ );
96
+ return deepFreeze({
97
+ contractId: String(manifest.contractId || ''),
98
+ packageName: String(manifest.npmPackage || record && record.packageName || ''),
99
+ lowerableSubpath: String(manifest.lowerableSubpath || ''),
100
+ compatibilitySubpaths: sortedUnique(manifest.publicApi && manifest.publicApi.compatibilitySubpaths || []),
101
+ facadeSymbols: sortedUnique(facade.symbols || []),
102
+ compilerTrust: String(compiler.trust || ''),
103
+ compilerOwner: String(compiler.builderOwner || ''),
104
+ validationStatus: String(validation.status || 'unknown'),
105
+ manifestVersion: String(manifest.version || ''),
106
+ manifestHash: sha256(JSON.stringify(manifest)),
107
+ manifestFile: record && record.manifestFile ? path.resolve(record.manifestFile) : null,
108
+ packageDir: record && record.packageDir ? path.resolve(record.packageDir) : null,
109
+ hostCapabilities: sortedUnique(wasm.hostCapabilities || []),
110
+ targetSupport: Object.freeze({
111
+ native: nativeSupported,
112
+ javascript: javascriptDeclared ? 'declared' : 'not-realized'
113
+ }),
114
+ productContract: product ? Object.freeze({
115
+ version: product.version,
116
+ metadataHash: productRecord.metadataHash,
117
+ profileFragment: product.ownership.profileFragment,
118
+ helperImports: product.ownership.helperImports,
119
+ reExportImports: product.ownership.reExportImports,
120
+ composition: product.composition,
121
+ targets: product.targets,
122
+ conformance: product.conformance,
123
+ docs: product.docs
124
+ }) : null
125
+ });
126
+ }
127
+
128
+ function discoverPackageContractCatalog(options = {}) {
129
+ const cwd = path.resolve(options.cwd || options.rootDir || process.cwd());
130
+ const records = discoverLowerableLibraryManifests({
131
+ cwd,
132
+ workspaceRoot: options.workspaceRoot,
133
+ scanNodeModules: options.scanNodeModules !== false
134
+ });
135
+ const productCatalog = discoverPulsePackageContracts({
136
+ cwd,
137
+ workspaceRoot: options.workspaceRoot,
138
+ scanNodeModules: options.scanNodeModules !== false
139
+ });
140
+ const productsByContract = new Map(productCatalog.contracts.map((entry) => [entry.contractId, { contract: entry, metadataHash: entry.metadataHash }]));
141
+ const contracts = records.map((record) => {
142
+ const contractId = record.manifest && record.manifest.contractId;
143
+ const productRecord = productsByContract.get(contractId);
144
+ if (!productRecord) throw new TypeError(`Trusted package lowerer ${contractId || record.packageName} requires static Pulse product metadata.`);
145
+ return catalogDescriptor(record, productRecord);
146
+ })
147
+ .filter((entry) => entry.contractId && entry.packageName && entry.lowerableSubpath)
148
+ .sort((left, right) => left.contractId.localeCompare(right.contractId));
149
+ const seenContracts = new Set();
150
+ const seenSubpaths = new Set();
151
+ for (const entry of contracts) {
152
+ if (seenContracts.has(entry.contractId)) throw new PackageOperationSeamError('PULSE_PACKAGE_CONTRACT_DUPLICATE', `Duplicate package contract ${entry.contractId}.`, { contractId: entry.contractId });
153
+ for (const subpath of new Set([entry.lowerableSubpath, ...entry.compatibilitySubpaths])) {
154
+ if (seenSubpaths.has(subpath)) throw new PackageOperationSeamError('PULSE_PACKAGE_SUBPATH_DUPLICATE', `Package subpath ${subpath} is owned by more than one package contract.`, { lowerableSubpath: subpath });
155
+ seenSubpaths.add(subpath);
156
+ }
157
+ seenContracts.add(entry.contractId);
158
+ }
159
+ return deepFreeze({
160
+ version: PACKAGE_CONTRACT_CATALOG_VERSION,
161
+ productCatalog: Object.freeze({
162
+ version: productCatalog.version,
163
+ discoveryVersion: productCatalog.discoveryVersion,
164
+ contracts: productCatalog.contracts,
165
+ profileFragments: productCatalog.profileFragments,
166
+ helperImports: productCatalog.helperImports,
167
+ policy: productCatalog.policy
168
+ }),
169
+ contracts: Object.freeze(contracts),
170
+ policy: Object.freeze({
171
+ trustedFirstPartyOnly: true,
172
+ sourceSubstringSelection: false,
173
+ graphReachabilitySelection: true,
174
+ publicRegistration: false,
175
+ dynamicDiscoveryHooks: false,
176
+ productMetadataVersion: productCatalog.version,
177
+ productMetadataSeparateFromLowerer: true,
178
+ profileFragmentOwnershipRequired: true,
179
+ javascriptSupportExplicit: true
180
+ })
181
+ });
182
+ }
183
+
184
+ function effectWithSourceFile(effect, sourceFile) {
185
+ if (!sourceFile || !effect || typeof effect !== 'object') return deepFreeze(cloneJson(effect));
186
+ const value = cloneJson(effect);
187
+ if (value.loc && typeof value.loc === 'object') value.loc.file = String(sourceFile);
188
+ return deepFreeze(value);
189
+ }
190
+
191
+ function schemaReferenceWithSourceFile(reference, sourceFile) {
192
+ if (!reference || typeof reference !== 'object') return deepFreeze(cloneJson(reference));
193
+ const value = cloneJson(reference);
194
+ if (sourceFile) value.file = String(sourceFile);
195
+ return deepFreeze(value);
196
+ }
197
+
198
+ function canonicalPackageSchemaReference(reference) {
199
+ const id = String(reference && reference.id || '');
200
+ const usage = String(reference && reference.usage || '');
201
+ const capability = String(reference && reference.capability || '');
202
+ const position = reference && reference.position;
203
+ if (
204
+ !id
205
+ || !usage
206
+ || !['schema.decode', 'schema.encode'].includes(capability)
207
+ || !position
208
+ || !Number.isSafeInteger(Number(position.line))
209
+ || Number(position.line) < 1
210
+ || !Number.isSafeInteger(Number(position.column))
211
+ || Number(position.column) < 1
212
+ || !Number.isSafeInteger(Number(position.offset))
213
+ || Number(position.offset) < 0
214
+ ) {
215
+ throw new PackageOperationSeamError(
216
+ 'PULSE_PACKAGE_SCHEMA_REFERENCE_INVALID',
217
+ 'Package-owned schema references require an ID, usage, schema capability, and source position.',
218
+ { id, usage, capability }
219
+ );
220
+ }
221
+ return deepFreeze({
222
+ id,
223
+ usage,
224
+ capability,
225
+ ...(reference.file ? { file: String(reference.file).replace(/\\/g, '/') } : {}),
226
+ ...(reference.responseCaseId ? { responseCaseId: String(reference.responseCaseId) } : {}),
227
+ position: Object.freeze({
228
+ line: Number(position.line),
229
+ column: Number(position.column),
230
+ offset: Number(position.offset)
231
+ })
232
+ });
233
+ }
234
+
235
+ function planWithSourceFile(plan, sourceFile) {
236
+ const value = cloneJson(plan);
237
+ if (sourceFile && Array.isArray(value.canonicalEffects)) {
238
+ value.canonicalEffects = value.canonicalEffects.map((effect) => effectWithSourceFile(effect, sourceFile));
239
+ }
240
+ if (sourceFile && Array.isArray(value.canonicalIntrinsics)) {
241
+ value.canonicalIntrinsics = value.canonicalIntrinsics.map((intrinsic) => effectWithSourceFile(intrinsic, sourceFile));
242
+ }
243
+ if (sourceFile && Array.isArray(value.schemaReferences)) {
244
+ value.schemaReferences = value.schemaReferences.map((reference) => schemaReferenceWithSourceFile(reference, sourceFile));
245
+ }
246
+ return deepFreeze(value);
247
+ }
248
+
249
+ function packageDescriptor(record, operationCount, intrinsicCount = 0) {
250
+ const manifest = record && record.manifest || {};
251
+ const compiler = manifest.compiler && typeof manifest.compiler === 'object' ? manifest.compiler : {};
252
+ const wasm = manifest.modes && manifest.modes.wasm || {};
253
+ return deepFreeze({
254
+ contractId: String(manifest.contractId || ''),
255
+ package: String(manifest.npmPackage || record && record.packageName || ''),
256
+ lowerableSubpath: String(manifest.lowerableSubpath || ''),
257
+ builder: {
258
+ owner: String(compiler.builderOwner || manifest.npmPackage || record && record.packageName || ''),
259
+ trust: String(compiler.trust || ''),
260
+ entry: String(compiler.entry || ''),
261
+ export: String(compiler.export || '')
262
+ },
263
+ mode: String(wasm.mode || ''),
264
+ sidecar: typeof wasm.sidecar === 'string' ? wasm.sidecar : undefined,
265
+ hostCapabilities: sortedUnique(wasm.hostCapabilities || []),
266
+ operationCount,
267
+ intrinsicCount
268
+ });
269
+ }
270
+
271
+ function canonicalPackageIntrinsic(intrinsic, record) {
272
+ if (!intrinsic || intrinsic.version !== PACKAGE_INTRINSIC_VERSION) {
273
+ throw new PackageOperationSeamError(
274
+ 'PULSE_PACKAGE_INTRINSIC_INVALID',
275
+ `Trusted package intrinsics require ${PACKAGE_INTRINSIC_VERSION}.`,
276
+ { intrinsic }
277
+ );
278
+ }
279
+ const manifest = record && record.manifest || {};
280
+ const value = {
281
+ ...cloneJson(intrinsic),
282
+ contractId: String(intrinsic.contractId || manifest.contractId || ''),
283
+ package: String(intrinsic.package || manifest.npmPackage || ''),
284
+ import: String(intrinsic.import || manifest.lowerableSubpath || ''),
285
+ kind: String(intrinsic.kind || ''),
286
+ operation: String(intrinsic.operation || ''),
287
+ intrinsic: String(intrinsic.intrinsic || ''),
288
+ packageIntrinsic: intrinsic.packageIntrinsic ? String(intrinsic.packageIntrinsic) : undefined,
289
+ compilerName: String(intrinsic.compilerName || ''),
290
+ valueKind: String(intrinsic.valueKind || 'unknown'),
291
+ argumentIndexes: Array.isArray(intrinsic.argumentIndexes) ? intrinsic.argumentIndexes.map(Number) : [],
292
+ staticArguments: Array.isArray(intrinsic.staticArguments)
293
+ ? intrinsic.staticArguments.map((entry) => cloneJson(entry))
294
+ : []
295
+ };
296
+ for (const field of ['contractId', 'package', 'import', 'kind', 'operation', 'intrinsic', 'compilerName']) {
297
+ if (!value[field]) {
298
+ throw new PackageOperationSeamError('PULSE_PACKAGE_INTRINSIC_INVALID', `Package intrinsic requires ${field}.`, { field, intrinsic });
299
+ }
300
+ }
301
+ if (
302
+ !value.range
303
+ || !Number.isSafeInteger(Number(value.range.start))
304
+ || value.argumentIndexes.some((index) => !Number.isSafeInteger(index) || index < 0)
305
+ ) {
306
+ throw new PackageOperationSeamError('PULSE_PACKAGE_INTRINSIC_INVALID', 'Package intrinsic requires a source range and non-negative argument indexes.', { intrinsic });
307
+ }
308
+ return deepFreeze(value);
309
+ }
310
+
311
+ function canonicalRealizationArtifact(artifact, record) {
312
+ const manifest = record && record.manifest || {};
313
+ const value = cloneJson(artifact);
314
+ const id = String(value && value.id || '');
315
+ const contractId = String(value && value.contractId || '');
316
+ const packageName = String(value && value.package || '');
317
+ const version = String(value && value.version || '');
318
+ const kind = String(value && value.kind || '');
319
+ const mediaType = String(value && value.mediaType || '');
320
+ if (
321
+ !id
322
+ || !version
323
+ || !kind
324
+ || !mediaType
325
+ || contractId !== String(manifest.contractId || '')
326
+ || packageName !== String(manifest.npmPackage || '')
327
+ || !value.data
328
+ || typeof value.data !== 'object'
329
+ ) {
330
+ throw new PackageOperationSeamError(
331
+ 'PULSE_PACKAGE_REALIZATION_ARTIFACT_INVALID',
332
+ 'Package realization artifacts require versioned owner identity, media type, and private data.',
333
+ { id, version, kind, mediaType, contractId, package: packageName }
334
+ );
335
+ }
336
+ return deepFreeze(value);
337
+ }
338
+
339
+ function canonicalInspectionArtifact(artifact, record) {
340
+ const manifest = record && record.manifest || {};
341
+ const value = cloneJson(artifact);
342
+ const id = String(value && value.id || '');
343
+ const contractId = String(value && value.contractId || '');
344
+ const packageName = String(value && value.package || '');
345
+ const version = String(value && value.version || '');
346
+ const kind = String(value && value.kind || '');
347
+ const mediaType = String(value && value.mediaType || '');
348
+ const file = String(value && value.file || '').replace(/\\/g, '/');
349
+ const unsafeFile = !file
350
+ || path.posix.isAbsolute(file)
351
+ || file === '..'
352
+ || file.startsWith('../')
353
+ || file.includes('/../')
354
+ || !file.endsWith('.json');
355
+ if (
356
+ version !== PACKAGE_INSPECTION_ARTIFACT_VERSION
357
+ || !id
358
+ || !kind
359
+ || mediaType !== 'application/json'
360
+ || unsafeFile
361
+ || contractId !== String(manifest.contractId || '')
362
+ || packageName !== String(manifest.npmPackage || '')
363
+ || !value.data
364
+ || typeof value.data !== 'object'
365
+ || Array.isArray(value.data)
366
+ ) {
367
+ throw new PackageOperationSeamError(
368
+ 'PULSE_PACKAGE_INSPECTION_ARTIFACT_INVALID',
369
+ `Package inspection artifacts require ${PACKAGE_INSPECTION_ARTIFACT_VERSION}, exact owner identity, a safe JSON file, and static data.`,
370
+ { id, version, kind, mediaType, file, contractId, package: packageName }
371
+ );
372
+ }
373
+ return deepFreeze(value);
374
+ }
375
+
376
+ function canonicalManagedHandlerDescriptor(descriptor) {
377
+ const value = cloneJson(descriptor);
378
+ if (
379
+ !value
380
+ || typeof value !== 'object'
381
+ || Array.isArray(value)
382
+ || value.version !== PACKAGE_MANAGED_HANDLER_DESCRIPTOR_VERSION
383
+ || typeof value.id !== 'string'
384
+ || value.id.length === 0
385
+ ) {
386
+ throw new PackageOperationSeamError(
387
+ 'PULSE_MANAGED_HANDLER_DESCRIPTOR_INVALID',
388
+ `Package managed-handler contributions require ${PACKAGE_MANAGED_HANDLER_DESCRIPTOR_VERSION} and a stable ID.`,
389
+ { version: value && value.version, id: value && value.id }
390
+ );
391
+ }
392
+ return deepFreeze(value);
393
+ }
394
+
395
+ function canonicalPackageCryptoRequirement(requirement, record) {
396
+ const manifest = record && record.manifest || {};
397
+ const value = cloneJson(requirement);
398
+ const allowed = new Set([
399
+ 'version',
400
+ 'requestedBy',
401
+ 'semanticOwner',
402
+ 'reachable',
403
+ 'algorithms'
404
+ ]);
405
+ const unsupported = Object.keys(value || {}).filter((key) => !allowed.has(key)).sort();
406
+ if (
407
+ !value
408
+ || typeof value !== 'object'
409
+ || Array.isArray(value)
410
+ || value.version !== PACKAGE_CRYPTO_REQUIREMENT_VERSION
411
+ || value.requestedBy !== String(manifest.npmPackage || record && record.packageName || '')
412
+ || value.semanticOwner !== CRYPTO_SEMANTIC_OWNER
413
+ || value.reachable !== true
414
+ || !Array.isArray(value.algorithms)
415
+ || value.algorithms.length === 0
416
+ || value.algorithms.some((algorithm) => typeof algorithm !== 'string' || algorithm.trim().length === 0)
417
+ || unsupported.length > 0
418
+ ) {
419
+ throw new PackageOperationSeamError(
420
+ 'PULSE_PACKAGE_CRYPTO_REQUIREMENT_INVALID',
421
+ 'Package crypto requirements require versioned package ownership, crypto semantic ownership, reachability, and non-empty algorithms.',
422
+ {
423
+ version: value && value.version,
424
+ requestedBy: value && value.requestedBy,
425
+ semanticOwner: value && value.semanticOwner,
426
+ reachable: value && value.reachable,
427
+ unsupported
428
+ }
429
+ );
430
+ }
431
+ return deepFreeze({
432
+ version: PACKAGE_CRYPTO_REQUIREMENT_VERSION,
433
+ requestedBy: value.requestedBy,
434
+ semanticOwner: value.semanticOwner,
435
+ reachable: true,
436
+ algorithms: sortedUnique(value.algorithms.map((algorithm) => algorithm.trim()))
437
+ });
438
+ }
439
+
440
+ function combinePackageCryptoRequirements(requirements) {
441
+ const grouped = new Map();
442
+ for (const requirement of requirements || []) {
443
+ const key = `${requirement.requestedBy}\u0000${requirement.semanticOwner}`;
444
+ const current = grouped.get(key) || {
445
+ version: PACKAGE_CRYPTO_REQUIREMENT_VERSION,
446
+ requestedBy: requirement.requestedBy,
447
+ semanticOwner: requirement.semanticOwner,
448
+ reachable: true,
449
+ algorithms: new Set()
450
+ };
451
+ for (const algorithm of requirement.algorithms || []) current.algorithms.add(algorithm);
452
+ grouped.set(key, current);
453
+ }
454
+ return Object.freeze([...grouped.values()]
455
+ .map((entry) => deepFreeze({
456
+ version: entry.version,
457
+ requestedBy: entry.requestedBy,
458
+ semanticOwner: entry.semanticOwner,
459
+ reachable: true,
460
+ algorithms: Object.freeze([...entry.algorithms].sort())
461
+ }))
462
+ .sort((left, right) => left.requestedBy.localeCompare(right.requestedBy)
463
+ || left.semanticOwner.localeCompare(right.semanticOwner)));
464
+ }
465
+
466
+ function canonicalGuestUnitSelection(contribution, record) {
467
+ let contributingPackageManifest;
468
+ let packageRoot;
469
+ try {
470
+ const requestingPackageManifest = JSON.parse(
471
+ fs.readFileSync(path.join(record.packageDir, 'package.json'), 'utf8')
472
+ );
473
+ const declaredOwner = contribution && typeof contribution.owner === 'string'
474
+ ? contribution.owner
475
+ : record.packageName;
476
+ if (declaredOwner === record.packageName) {
477
+ packageRoot = fs.realpathSync(record.packageDir);
478
+ } else {
479
+ if (!Object.prototype.hasOwnProperty.call(
480
+ requestingPackageManifest.dependencies || {},
481
+ declaredOwner
482
+ )) {
483
+ throw new TypeError('guest-unit owner is not a declared package dependency');
484
+ }
485
+ const resolvedEntry = createRequire(path.join(record.packageDir, 'package.json')).resolve(declaredOwner);
486
+ let candidate = path.dirname(fs.realpathSync(resolvedEntry));
487
+ let found = false;
488
+ while (candidate !== path.dirname(candidate)) {
489
+ const candidateManifest = path.join(candidate, 'package.json');
490
+ if (fs.existsSync(candidateManifest)) {
491
+ const parsed = JSON.parse(fs.readFileSync(candidateManifest, 'utf8'));
492
+ if (parsed.name === declaredOwner) {
493
+ packageRoot = fs.realpathSync(candidate);
494
+ found = true;
495
+ break;
496
+ }
497
+ }
498
+ candidate = path.dirname(candidate);
499
+ }
500
+ if (!found) throw new TypeError('guest-unit owner package root could not be resolved');
501
+ }
502
+ contributingPackageManifest = JSON.parse(
503
+ fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8')
504
+ );
505
+ if (
506
+ contributingPackageManifest.name !== declaredOwner
507
+ ) {
508
+ throw new TypeError('guest-unit owner is not the contributing package or a declared package dependency');
509
+ }
510
+ } catch (error) {
511
+ throw new PackageOperationSeamError(
512
+ 'PULSE_GUEST_UNIT_OWNER_MISMATCH',
513
+ `Guest-unit owner package ${contribution && contribution.owner || record.packageName || '<unknown>'} has no readable declared package identity.`,
514
+ { cause: error && error.message }
515
+ );
516
+ }
517
+ let normalized;
518
+ try {
519
+ normalized = normalizeGuestUnitContribution({
520
+ version: contribution.version,
521
+ id: contribution.id,
522
+ manifest: contribution.manifest
523
+ }, {
524
+ owner: contributingPackageManifest.name,
525
+ packageVersion: contributingPackageManifest.version
526
+ });
527
+ if (
528
+ contribution.packageVersion !== undefined
529
+ && contribution.packageVersion !== contributingPackageManifest.version
530
+ ) throw new TypeError('guest-unit package version does not match its owner');
531
+ } catch (error) {
532
+ throw new PackageOperationSeamError(
533
+ 'PULSE_GUEST_UNIT_INVALID',
534
+ `Trusted package ${record.packageName || '<unknown>'} produced an invalid guest-unit contribution.`,
535
+ { cause: error && error.message }
536
+ );
537
+ }
538
+ return deepFreeze({
539
+ ...normalizeCanonicalGuestUnitContribution(normalized),
540
+ packageRoot
541
+ });
542
+ }
543
+
544
+ function operationHostCapabilities(manifest, effect) {
545
+ const wasm = manifest && manifest.modes && manifest.modes.wasm;
546
+ const lowerings = wasm && Array.isArray(wasm.lowerings) ? wasm.lowerings : [];
547
+ const lowering = lowerings.find((entry) => String(entry.tsSymbol || '') === String(effect.kind || ''));
548
+ return sortedUnique(lowering && lowering.hostCapabilities || []);
549
+ }
550
+
551
+ function canonicalPackageOperation(effect, record, order) {
552
+ const manifest = record && record.manifest || {};
553
+ try {
554
+ return createCanonicalPackageOperation(effect, {
555
+ contractId: manifest.contractId,
556
+ npmPackage: manifest.npmPackage || record && record.packageName,
557
+ lowerableSubpath: manifest.lowerableSubpath,
558
+ hostCapabilities: operationHostCapabilities(manifest, effect)
559
+ }, order);
560
+ } catch (error) {
561
+ throw new PackageOperationSeamError(
562
+ 'PULSE_PACKAGE_OPERATION_INVALID',
563
+ `Trusted package ${manifest.contractId || record && record.packageName || '<unknown>'} produced an invalid canonical operation.`,
564
+ { order, cause: error && error.message }
565
+ );
566
+ }
567
+ }
568
+
569
+ function assertCanonicalPackageOperation(operation) {
570
+ try {
571
+ return normalizeCanonicalPackageOperation(operation);
572
+ } catch (error) {
573
+ throw new PackageOperationSeamError(
574
+ 'PULSE_PACKAGE_OPERATION_INVALID',
575
+ `Expected an exact ${CANONICAL_PACKAGE_OPERATION_VERSION} record.`,
576
+ { id: operation && operation.id, cause: error && error.message }
577
+ );
578
+ }
579
+ }
580
+
581
+ function selectPackageRecords(manifestRecords, sourceText, selectedContracts) {
582
+ const selected = [];
583
+ const seen = new Set();
584
+ const requested = Array.isArray(selectedContracts)
585
+ ? new Set(selectedContracts.map((value) => String(value)).filter(Boolean))
586
+ : null;
587
+ for (const record of manifestRecords) {
588
+ const manifest = record && record.manifest || {};
589
+ const lowerableSubpath = String(manifest.lowerableSubpath || '');
590
+ const contractId = String(manifest.contractId || '');
591
+ const selectedByGraph = requested && requested.has(contractId);
592
+ const compatibilitySubpaths = manifest.publicApi && Array.isArray(manifest.publicApi.compatibilitySubpaths)
593
+ ? manifest.publicApi.compatibilitySubpaths.map(String)
594
+ : [];
595
+ const selectedByCompatibilityScan = !requested && [lowerableSubpath, ...compatibilitySubpaths].some((specifier) => sourceText.includes(specifier));
596
+ if (!lowerableSubpath || !contractId || seen.has(contractId) || (!selectedByGraph && !selectedByCompatibilityScan)) continue;
597
+ seen.add(contractId);
598
+ selected.push(record);
599
+ }
600
+ if (requested) {
601
+ const missing = [...requested].filter((contractId) => !seen.has(contractId)).sort();
602
+ if (missing.length > 0) throw new PackageOperationSeamError(
603
+ 'PULSE_PACKAGE_CONTRACT_NOT_FOUND',
604
+ `Reachable graph selected package contract(s) that are absent from the trusted manifest catalog: ${missing.join(', ')}.`,
605
+ { missing }
606
+ );
607
+ }
608
+ return selected;
609
+ }
610
+
611
+ function recognizeProjectPackageOperations(entryFile, options = {}) {
612
+ const absoluteEntry = path.resolve(entryFile);
613
+ const rootDir = path.resolve(options.rootDir || path.dirname(absoluteEntry));
614
+ const sourceText = options.sourceText === undefined ? fs.readFileSync(absoluteEntry, 'utf8') : String(options.sourceText);
615
+ const manifestRecords = discoverLowerableLibraryManifests({
616
+ cwd: rootDir,
617
+ workspaceRoot: options.workspaceRoot,
618
+ scanNodeModules: true
619
+ });
620
+ const selected = selectPackageRecords(manifestRecords, sourceText, options.selectedContracts);
621
+ const sourceName = String(options.sourceName || absoluteEntry).replace(/\\/g, '/');
622
+ const sourceFile = ts.createSourceFile(sourceName, sourceText, ts.ScriptTarget.ES2022, true, /\.[cm]?tsx?$/.test(sourceName) ? ts.ScriptKind.TS : ts.ScriptKind.JS);
623
+ const operations = [];
624
+ const packages = [];
625
+ const plans = [];
626
+ const resultAdapters = [];
627
+ const intrinsics = [];
628
+ const schemaReferences = [];
629
+ const realizationArtifacts = [];
630
+ const inspectionArtifacts = [];
631
+ const managedHandlers = [];
632
+ const guestUnits = [];
633
+ const cryptoRequirements = [];
634
+ const diagnostics = [];
635
+ let order = 0;
636
+
637
+ for (const record of selected) {
638
+ // This source-aware step is package recognition and validation. The later
639
+ // package-lowering phase receives only the canonical operations below.
640
+ const result = buildPackageOwnedLoweringPlan({
641
+ cwd: rootDir,
642
+ workspaceRoot: options.workspaceRoot,
643
+ manifestRecords,
644
+ contractId: record.manifest.contractId,
645
+ sourcePath: sourceName,
646
+ sourceText,
647
+ sourceFile,
648
+ generatedBy: options.generatedBy,
649
+ schemaBundle: options.schemaBundle
650
+ });
651
+ diagnostics.push(...(result.diagnostics || []));
652
+ const contributions = result.contributions || {};
653
+ const canonicalEffects = contributions.canonicalEffects || [];
654
+ const recognized = canonicalEffects.map((effect) => canonicalPackageOperation(effect, record, ++order));
655
+ const adapters = contributions.resultAdapters || [];
656
+ for (const adapter of adapters) {
657
+ if (!adapter || adapter.version !== PACKAGE_RESULT_ADAPTER_VERSION) {
658
+ throw new PackageOperationSeamError('PULSE_PACKAGE_RESULT_ADAPTER_INVALID', `Package ${record.manifest.contractId} produced an invalid result adapter.`, { adapter });
659
+ }
660
+ resultAdapters.push(effectWithSourceFile(adapter, sourceName));
661
+ }
662
+ const recognizedIntrinsics = (contributions.canonicalIntrinsics || [])
663
+ .map((intrinsic) => canonicalPackageIntrinsic(intrinsic, record));
664
+ intrinsics.push(...recognizedIntrinsics.map((intrinsic) => effectWithSourceFile(intrinsic, sourceName)));
665
+ const recognizedSchemaReferences = (contributions.schemaReferences || [])
666
+ .map(canonicalPackageSchemaReference)
667
+ .map((reference) => schemaReferenceWithSourceFile(reference, sourceName));
668
+ schemaReferences.push(...recognizedSchemaReferences);
669
+ realizationArtifacts.push(...(contributions.realizationArtifacts || [])
670
+ .map((artifact) => canonicalRealizationArtifact(artifact, record)));
671
+ inspectionArtifacts.push(...(contributions.inspectionArtifacts || [])
672
+ .map((artifact) => canonicalInspectionArtifact(artifact, record)));
673
+ managedHandlers.push(...(contributions.managedHandlers || [])
674
+ .map(canonicalManagedHandlerDescriptor));
675
+ guestUnits.push(...(contributions.guestUnits || [])
676
+ .map((contribution) => canonicalGuestUnitSelection(contribution, record)));
677
+ const recognizedCryptoRequirements = (contributions.cryptoRequirements || [])
678
+ .map((requirement) => canonicalPackageCryptoRequirement(requirement, record));
679
+ cryptoRequirements.push(...recognizedCryptoRequirements);
680
+ operations.push(...recognized);
681
+ packages.push(packageDescriptor(record, recognized.length, recognizedIntrinsics.length));
682
+ plans.push(Object.freeze({
683
+ contractId: String(record.manifest.contractId),
684
+ package: String(record.manifest.npmPackage),
685
+ lowerableSubpath: String(record.manifest.lowerableSubpath),
686
+ status: result.artifact && result.artifact.status || (result.hasErrors ? 'error' : 'ok'),
687
+ canonicalEffects: Object.freeze(canonicalEffects.map((effect) => Object.freeze({ ...effect }))),
688
+ canonicalIntrinsics: Object.freeze(recognizedIntrinsics),
689
+ schemaReferences: Object.freeze(recognizedSchemaReferences),
690
+ cryptoRequirements: Object.freeze(recognizedCryptoRequirements)
691
+ }));
692
+ }
693
+
694
+ const dependencies = Object.freeze(selected.map((record) => path.resolve(record.manifestFile)).filter(Boolean).sort());
695
+ const publicSourceName = options.publicSourceName ? String(options.publicSourceName) : undefined;
696
+ const publicExtensions = Object.freeze({
697
+ active: operations.length > 0 || intrinsics.length > 0,
698
+ allowedRuntimeImports: sortedUnique(selected.flatMap((record) => {
699
+ const manifest = record.manifest || {};
700
+ const compatibility = manifest.publicApi && Array.isArray(manifest.publicApi.compatibilitySubpaths)
701
+ ? manifest.publicApi.compatibilitySubpaths.map(String)
702
+ : [];
703
+ return [String(manifest.lowerableSubpath), ...compatibility];
704
+ })),
705
+ effects: Object.freeze(operations.map((operation) => effectWithSourceFile(operation.canonicalEffect, publicSourceName))),
706
+ intrinsics: Object.freeze(intrinsics.map((intrinsic) => effectWithSourceFile(intrinsic, publicSourceName))),
707
+ schemaReferences: Object.freeze(schemaReferences.map((reference) => schemaReferenceWithSourceFile(reference, publicSourceName))),
708
+ resultAdapters: Object.freeze(resultAdapters.map((adapter) => effectWithSourceFile(adapter, publicSourceName))),
709
+ plans: Object.freeze(plans.map((plan) => planWithSourceFile(plan, publicSourceName))),
710
+ diagnostics: Object.freeze(diagnostics),
711
+ // Preserve the sealed public package-extension envelope. Graph-selected
712
+ // manifest dependencies remain private recognition facts and join watch
713
+ // inputs at the project compiler boundary.
714
+ dependencies: Object.freeze([])
715
+ });
716
+ return deepFreeze({
717
+ version: PACKAGE_OPERATION_RECOGNITION_VERSION,
718
+ operations: Object.freeze(operations),
719
+ intrinsics: Object.freeze(intrinsics),
720
+ schemaReferences: Object.freeze(schemaReferences),
721
+ realizationArtifacts: Object.freeze(realizationArtifacts),
722
+ inspectionArtifacts: Object.freeze(inspectionArtifacts),
723
+ managedHandlers: Object.freeze(managedHandlers),
724
+ guestUnits: Object.freeze(guestUnits),
725
+ cryptoRequirements: combinePackageCryptoRequirements(cryptoRequirements),
726
+ resultAdapters: Object.freeze(resultAdapters),
727
+ packages: Object.freeze(packages),
728
+ selectedContracts: Object.freeze(selected.map((record) => String(record.manifest.contractId))),
729
+ dependencies,
730
+ publicExtensions,
731
+ diagnostics: publicExtensions.diagnostics,
732
+ errors: Object.freeze(publicExtensions.diagnostics.filter((entry) => String(entry.severity || 'error') === 'error')),
733
+ policy: Object.freeze({
734
+ sourceAwareRecognition: true,
735
+ selection: Array.isArray(options.selectedContracts) ? 'reachable-graph' : 'compatibility-source-scan',
736
+ lateLoweringReceivesSourceAst: false,
737
+ lateLoweringReceivesSourceText: false,
738
+ lateLoweringInput: CANONICAL_PACKAGE_OPERATION_VERSION,
739
+ firstPartyBuildersOnly: true,
740
+ externalRegistration: false
741
+ })
742
+ });
743
+ }
744
+
745
+ function combinePackageOperationRecognitions(recognitions = []) {
746
+ const inputs = recognitions.filter((entry) => entry && entry.version === PACKAGE_OPERATION_RECOGNITION_VERSION);
747
+ const flattened = inputs.flatMap((recognition) => recognition.operations || []).sort((left, right) => {
748
+ const leftFile = String(left.source && left.source.file || '');
749
+ const rightFile = String(right.source && right.source.file || '');
750
+ return leftFile.localeCompare(rightFile)
751
+ || Number(left.range && left.range.start || 0) - Number(right.range && right.range.start || 0)
752
+ || left.contractId.localeCompare(right.contractId)
753
+ || left.kind.localeCompare(right.kind);
754
+ });
755
+ const operations = flattened.map((operation, index) => deepFreeze({
756
+ ...cloneJson(operation),
757
+ id: `${operation.contractId}:${index + 1}:${operation.kind}`,
758
+ order: index + 1
759
+ }));
760
+ const packageRecords = new Map();
761
+ for (const recognition of inputs) {
762
+ for (const record of recognition.packages || []) {
763
+ if (!packageRecords.has(record.contractId)) packageRecords.set(record.contractId, cloneJson(record));
764
+ }
765
+ }
766
+ const intrinsics = inputs.flatMap((entry) => entry.intrinsics || []).sort((a, b) => String(a.loc && a.loc.file || '').localeCompare(String(b.loc && b.loc.file || '')) || Number(a.range && a.range.start || 0) - Number(b.range && b.range.start || 0));
767
+ const schemaReferences = inputs.flatMap((entry) => entry.schemaReferences || []).sort((a, b) => String(a.file || '').localeCompare(String(b.file || ''))
768
+ || Number(a.position && a.position.offset || 0) - Number(b.position && b.position.offset || 0)
769
+ || String(a.id || '').localeCompare(String(b.id || '')));
770
+ const packages = [...packageRecords.values()].map((record) => deepFreeze({
771
+ ...record,
772
+ operationCount: operations.filter((operation) => operation.contractId === record.contractId).length,
773
+ intrinsicCount: intrinsics.filter((intrinsic) => intrinsic.contractId === record.contractId).length
774
+ })).sort((left, right) => left.contractId.localeCompare(right.contractId));
775
+ const resultAdapters = inputs.flatMap((entry) => entry.resultAdapters || []).sort((a, b) => String(a.loc && a.loc.file || '').localeCompare(String(b.loc && b.loc.file || '')) || Number(a.range && a.range.start || 0) - Number(b.range && b.range.start || 0));
776
+ const realizationArtifactRecords = new Map();
777
+ for (const artifact of inputs.flatMap((entry) => entry.realizationArtifacts || [])) {
778
+ const id = String(artifact && artifact.id || '');
779
+ const fingerprint = sha256(JSON.stringify(artifact));
780
+ const existing = realizationArtifactRecords.get(id);
781
+ if (existing && existing.fingerprint !== fingerprint) {
782
+ throw new PackageOperationSeamError(
783
+ 'PULSE_PACKAGE_REALIZATION_ARTIFACT_CONFLICT',
784
+ `Package realization artifact ${id} has conflicting private data.`,
785
+ { id }
786
+ );
787
+ }
788
+ if (!existing) realizationArtifactRecords.set(id, { fingerprint, artifact });
789
+ }
790
+ const realizationArtifacts = [...realizationArtifactRecords.values()]
791
+ .map((entry) => deepFreeze(cloneJson(entry.artifact)))
792
+ .sort((left, right) => left.id.localeCompare(right.id));
793
+ const inspectionArtifactRecords = new Map();
794
+ for (const artifact of inputs.flatMap((entry) => entry.inspectionArtifacts || [])) {
795
+ const id = String(artifact && artifact.id || '');
796
+ const fingerprint = sha256(JSON.stringify(artifact));
797
+ const existing = inspectionArtifactRecords.get(id);
798
+ if (existing && existing.fingerprint !== fingerprint) {
799
+ throw new PackageOperationSeamError(
800
+ 'PULSE_PACKAGE_INSPECTION_ARTIFACT_CONFLICT',
801
+ `Package inspection artifact ${id} has conflicting static data.`,
802
+ { id }
803
+ );
804
+ }
805
+ if (!existing) inspectionArtifactRecords.set(id, { fingerprint, artifact });
806
+ }
807
+ const inspectionArtifacts = [...inspectionArtifactRecords.values()]
808
+ .map((entry) => deepFreeze(cloneJson(entry.artifact)))
809
+ .sort((left, right) => left.id.localeCompare(right.id));
810
+ const managedHandlerRecords = new Map();
811
+ for (const descriptor of inputs.flatMap((entry) => entry.managedHandlers || [])) {
812
+ const id = String(descriptor && descriptor.id || '');
813
+ const fingerprint = sha256(JSON.stringify(descriptor));
814
+ const existing = managedHandlerRecords.get(id);
815
+ if (existing && existing.fingerprint !== fingerprint) {
816
+ throw new PackageOperationSeamError(
817
+ 'PULSE_MANAGED_HANDLER_DESCRIPTOR_CONFLICT',
818
+ `Managed handler descriptor ${id} has conflicting static declarations.`,
819
+ { id }
820
+ );
821
+ }
822
+ if (!existing) managedHandlerRecords.set(id, { fingerprint, descriptor });
823
+ }
824
+ const managedHandlers = [...managedHandlerRecords.values()]
825
+ .map((entry) => deepFreeze(cloneJson(entry.descriptor)))
826
+ .sort((left, right) => left.id.localeCompare(right.id));
827
+ const guestUnitRecords = new Map();
828
+ for (const unit of inputs.flatMap((entry) => entry.guestUnits || [])) {
829
+ const id = String(unit && unit.id || '');
830
+ const fingerprint = sha256(JSON.stringify(unit));
831
+ const existing = guestUnitRecords.get(id);
832
+ if (existing && existing.fingerprint !== fingerprint) {
833
+ throw new PackageOperationSeamError(
834
+ 'PULSE_GUEST_UNIT_CONFLICT',
835
+ `Guest-unit contribution ${id} has conflicting package selections.`,
836
+ { id }
837
+ );
838
+ }
839
+ if (!existing) guestUnitRecords.set(id, { fingerprint, unit });
840
+ }
841
+ const guestUnits = [...guestUnitRecords.values()]
842
+ .map((entry) => deepFreeze(cloneJson(entry.unit)))
843
+ .sort((left, right) => left.id.localeCompare(right.id));
844
+ const cryptoRequirements = combinePackageCryptoRequirements(
845
+ inputs.flatMap((entry) => entry.cryptoRequirements || [])
846
+ );
847
+ const diagnostics = inputs.flatMap((entry) => entry.diagnostics || []);
848
+ const dependencies = sortedUnique(inputs.flatMap((entry) => entry.dependencies || []));
849
+ const publicExtensions = deepFreeze({
850
+ active: operations.length > 0 || intrinsics.length > 0,
851
+ allowedRuntimeImports: sortedUnique(inputs.flatMap((entry) => entry.publicExtensions && entry.publicExtensions.allowedRuntimeImports || [])),
852
+ effects: Object.freeze(operations.map((operation) => deepFreeze(cloneJson(operation.canonicalEffect)))),
853
+ intrinsics: Object.freeze(intrinsics.map((intrinsic) => deepFreeze(cloneJson(intrinsic)))),
854
+ schemaReferences: Object.freeze(schemaReferences.map((reference) => deepFreeze(cloneJson(reference)))),
855
+ resultAdapters: Object.freeze(resultAdapters.map((adapter) => deepFreeze(cloneJson(adapter)))),
856
+ plans: Object.freeze(inputs.flatMap((entry) => entry.publicExtensions && entry.publicExtensions.plans || []).map((entry) => deepFreeze(cloneJson(entry)))),
857
+ diagnostics: Object.freeze(diagnostics.map((entry) => deepFreeze(cloneJson(entry)))),
858
+ dependencies: Object.freeze([])
859
+ });
860
+ return deepFreeze({
861
+ version: PACKAGE_OPERATION_RECOGNITION_VERSION,
862
+ operations: Object.freeze(operations),
863
+ intrinsics: Object.freeze(intrinsics),
864
+ schemaReferences: Object.freeze(schemaReferences),
865
+ realizationArtifacts: Object.freeze(realizationArtifacts),
866
+ inspectionArtifacts: Object.freeze(inspectionArtifacts),
867
+ managedHandlers: Object.freeze(managedHandlers),
868
+ guestUnits: Object.freeze(guestUnits),
869
+ cryptoRequirements,
870
+ resultAdapters: Object.freeze(resultAdapters),
871
+ packages: Object.freeze(packages),
872
+ selectedContracts: sortedUnique(inputs.flatMap((entry) => entry.selectedContracts || [])),
873
+ dependencies,
874
+ publicExtensions,
875
+ diagnostics: publicExtensions.diagnostics,
876
+ errors: Object.freeze(publicExtensions.diagnostics.filter((entry) => String(entry.severity || 'error') === 'error')),
877
+ policy: Object.freeze({
878
+ sourceAwareRecognition: true,
879
+ selection: 'reachable-graph-per-module',
880
+ lateLoweringReceivesSourceAst: false,
881
+ lateLoweringReceivesSourceText: false,
882
+ lateLoweringInput: CANONICAL_PACKAGE_OPERATION_VERSION,
883
+ firstPartyBuildersOnly: true,
884
+ externalRegistration: false
885
+ })
886
+ });
887
+ }
888
+
889
+ function packageOperationRecognitionFromEffects(effects = []) {
890
+ const operations = effects.map((effect, index) => canonicalPackageOperation(
891
+ Object.fromEntries(CANONICAL_PACKAGE_EFFECT_FIELDS
892
+ .filter((field) => effect && Object.prototype.hasOwnProperty.call(effect, field))
893
+ .map((field) => [field, effect[field]])),
894
+ {
895
+ packageName: effect && effect.package,
896
+ manifest: {
897
+ contractId: effect && effect.contractId,
898
+ npmPackage: effect && effect.package,
899
+ lowerableSubpath: effect && effect.import,
900
+ compiler: { builderOwner: effect && effect.package, trust: 'first-party' },
901
+ modes: { wasm: { hostCapabilities: [], lowerings: [] } }
902
+ }
903
+ }, index + 1));
904
+ const counts = new Map();
905
+ const records = new Map();
906
+ for (const operation of operations) {
907
+ counts.set(operation.contractId, (counts.get(operation.contractId) || 0) + 1);
908
+ if (!records.has(operation.contractId)) records.set(operation.contractId, {
909
+ contractId: operation.contractId,
910
+ package: operation.package,
911
+ lowerableSubpath: operation.lowerableSubpath,
912
+ builder: { owner: operation.package, trust: 'first-party', entry: '', export: '' },
913
+ mode: '',
914
+ hostCapabilities: Object.freeze([])
915
+ });
916
+ }
917
+ const packages = [...records.values()].map((record) => deepFreeze({ ...record, operationCount: counts.get(record.contractId) || 0 }));
918
+ return deepFreeze({
919
+ version: PACKAGE_OPERATION_RECOGNITION_VERSION,
920
+ operations: Object.freeze(operations),
921
+ intrinsics: Object.freeze([]),
922
+ schemaReferences: Object.freeze(effects.flatMap((effect) => effect && Array.isArray(effect.schemaReferences) ? effect.schemaReferences : []).map(canonicalPackageSchemaReference)),
923
+ realizationArtifacts: Object.freeze([]),
924
+ inspectionArtifacts: Object.freeze([]),
925
+ managedHandlers: Object.freeze([]),
926
+ guestUnits: Object.freeze([]),
927
+ cryptoRequirements: Object.freeze([]),
928
+ resultAdapters: Object.freeze([]),
929
+ packages: Object.freeze(packages),
930
+ selectedContracts: Object.freeze(packages.map((entry) => entry.contractId)),
931
+ dependencies: Object.freeze([]),
932
+ publicExtensions: Object.freeze({
933
+ active: operations.length > 0,
934
+ allowedRuntimeImports: sortedUnique(packages.flatMap((entry) => [entry.lowerableSubpath, ...(entry.compatibilitySubpaths || [])])),
935
+ effects: Object.freeze(operations.map((operation) => deepFreeze(cloneJson(operation.canonicalEffect)))),
936
+ intrinsics: Object.freeze([]),
937
+ schemaReferences: Object.freeze(effects.flatMap((effect) => effect && Array.isArray(effect.schemaReferences) ? effect.schemaReferences : []).map(canonicalPackageSchemaReference)),
938
+ resultAdapters: Object.freeze([]),
939
+ plans: Object.freeze([]), diagnostics: Object.freeze([]), dependencies: Object.freeze([])
940
+ }),
941
+ diagnostics: Object.freeze([]), errors: Object.freeze([]),
942
+ policy: Object.freeze({
943
+ sourceAwareRecognition: false,
944
+ lateLoweringReceivesSourceAst: false,
945
+ lateLoweringReceivesSourceText: false,
946
+ lateLoweringInput: CANONICAL_PACKAGE_OPERATION_VERSION,
947
+ firstPartyBuildersOnly: true,
948
+ externalRegistration: false
949
+ })
950
+ });
951
+ }
952
+
953
+ function lowerCanonicalPackageOperations(recognition) {
954
+ if (!recognition || recognition.version !== PACKAGE_OPERATION_RECOGNITION_VERSION || !Array.isArray(recognition.operations)) {
955
+ throw new PackageOperationSeamError('PULSE_PACKAGE_OPERATION_BUNDLE_INVALID', `Package lowering requires ${PACKAGE_OPERATION_RECOGNITION_VERSION}.`, {
956
+ version: recognition && recognition.version
957
+ });
958
+ }
959
+ try {
960
+ return normalizePackageLoweringBundle({
961
+ inputVersion: PACKAGE_OPERATION_RECOGNITION_VERSION,
962
+ operations: recognition.operations,
963
+ packages: recognition.packages || [],
964
+ schemaReferences: recognition.schemaReferences || [],
965
+ realizationArtifacts: recognition.realizationArtifacts || [],
966
+ guestUnits: recognition.guestUnits || [],
967
+ cryptoRequirements: recognition.cryptoRequirements || []
968
+ });
969
+ } catch (error) {
970
+ throw new PackageOperationSeamError(
971
+ 'PULSE_PACKAGE_OPERATION_BUNDLE_INVALID',
972
+ `Package lowering requires an exact ${PACKAGE_LOWERING_BUNDLE_VERSION} boundary.`,
973
+ { cause: error && error.message }
974
+ );
975
+ }
976
+ }
977
+
978
+ function packageExtensionsForRecognition(recognition) {
979
+ if (!recognition || recognition.version !== PACKAGE_OPERATION_RECOGNITION_VERSION) {
980
+ throw new PackageOperationSeamError('PULSE_PACKAGE_OPERATION_BUNDLE_INVALID', 'Expected a package operation recognition bundle.');
981
+ }
982
+ return recognition.publicExtensions;
983
+ }
984
+
985
+ function attachPackageOperationRecognition(compiled, recognition) {
986
+ if (!compiled || typeof compiled !== 'object') throw new TypeError('attachPackageOperationRecognition requires a compiled program.');
987
+ if (!recognition || recognition.version !== PACKAGE_OPERATION_RECOGNITION_VERSION) throw new TypeError('attachPackageOperationRecognition requires a recognition bundle.');
988
+ recognitionsByCompiled.set(compiled, recognition);
989
+ return compiled;
990
+ }
991
+
992
+ function packageOperationRecognitionForCompiled(compiled) {
993
+ return compiled && typeof compiled === 'object' ? recognitionsByCompiled.get(compiled) : undefined;
994
+ }
995
+
996
+ module.exports = Object.freeze({
997
+ CANONICAL_PACKAGE_OPERATION_VERSION,
998
+ PACKAGE_OPERATION_RECOGNITION_VERSION,
999
+ PACKAGE_LOWERING_BUNDLE_VERSION,
1000
+ PACKAGE_RESULT_ADAPTER_VERSION,
1001
+ PACKAGE_INTRINSIC_VERSION,
1002
+ PACKAGE_CRYPTO_REQUIREMENT_VERSION,
1003
+ PACKAGE_INSPECTION_ARTIFACT_VERSION,
1004
+ PACKAGE_CONTRACT_CATALOG_VERSION,
1005
+ PackageOperationSeamError,
1006
+ assertCanonicalPackageOperation,
1007
+ discoverPackageContractCatalog,
1008
+ recognizeProjectPackageOperations,
1009
+ combinePackageOperationRecognitions,
1010
+ packageOperationRecognitionFromEffects,
1011
+ lowerCanonicalPackageOperations,
1012
+ packageExtensionsForRecognition,
1013
+ attachPackageOperationRecognition,
1014
+ packageOperationRecognitionForCompiled
1015
+ });