@kalada/adapter-scheman 0.1.0

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/dist/index.js ADDED
@@ -0,0 +1,1308 @@
1
+ import { describeEnvironment, createManualProvider, calculateEditorGraphAdmission, readSemanticType } from '@kalada/host';
2
+
3
+ // src/adapter.ts
4
+
5
+ // src/analysis-limits.ts
6
+ var DEFAULT_SCHEMAN_ANALYSIS_LIMITS = Object.freeze({
7
+ maxNodes: 2048,
8
+ maxEdges: 8192,
9
+ maxTypeDepth: 32
10
+ });
11
+ function resolveAnalysisLimits(requested) {
12
+ return Object.freeze({
13
+ maxNodes: bounded(requested?.maxNodes, DEFAULT_SCHEMAN_ANALYSIS_LIMITS.maxNodes),
14
+ maxEdges: bounded(requested?.maxEdges, DEFAULT_SCHEMAN_ANALYSIS_LIMITS.maxEdges),
15
+ maxTypeDepth: bounded(requested?.maxTypeDepth, DEFAULT_SCHEMAN_ANALYSIS_LIMITS.maxTypeDepth)
16
+ });
17
+ }
18
+ function bounded(value, maximum) {
19
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1) return maximum;
20
+ return Math.min(value, maximum);
21
+ }
22
+
23
+ // src/capability-wrappers.ts
24
+ function decodeStandardSchema(validator, value) {
25
+ const standard = validator["~standard"];
26
+ const outcome = standard.validate(value);
27
+ if (isThenableWithoutGet(outcome)) return outcome;
28
+ const issues = readDataSlot(outcome, "issues");
29
+ if (issues.found && issues.value !== void 0)
30
+ throw new Error("Standard Schema validation failed");
31
+ const decoded = readDataSlot(outcome, "value");
32
+ if (!decoded.found) throw new Error("Standard Schema returned an invalid outcome");
33
+ return decoded.value;
34
+ }
35
+ function convertWithFinalPolicy(codec, policy, value) {
36
+ const output = codec.convert(value);
37
+ if (isThenableWithoutGet(output)) return output;
38
+ if (policy === "safe-integer-and-kalada-type" && !isSafeInteger(output)) {
39
+ throw new Error("Codec output violates final conversion policy");
40
+ }
41
+ return output;
42
+ }
43
+ function isSafeInteger(value) {
44
+ return typeof value === "number" && Number.isSafeInteger(value);
45
+ }
46
+ function readDataSlot(input, key) {
47
+ if ((typeof input !== "object" || input === null) && typeof input !== "function") {
48
+ return Object.freeze({ found: false });
49
+ }
50
+ let current = input;
51
+ const seen = /* @__PURE__ */ new Set();
52
+ try {
53
+ while (current && !seen.has(current)) {
54
+ seen.add(current);
55
+ const descriptor = Object.getOwnPropertyDescriptor(current, key);
56
+ if (descriptor) {
57
+ return "value" in descriptor ? Object.freeze({ found: true, value: descriptor.value }) : Object.freeze({ found: false });
58
+ }
59
+ current = Object.getPrototypeOf(current);
60
+ }
61
+ } catch {
62
+ return Object.freeze({ found: false });
63
+ }
64
+ return Object.freeze({ found: false });
65
+ }
66
+ function isThenableWithoutGet(input) {
67
+ if ((typeof input !== "object" || input === null) && typeof input !== "function") return false;
68
+ let current = input;
69
+ const seen = /* @__PURE__ */ new Set();
70
+ try {
71
+ while (current && !seen.has(current)) {
72
+ seen.add(current);
73
+ const descriptor = Object.getOwnPropertyDescriptor(current, "then");
74
+ if (descriptor) return !("value" in descriptor) || typeof descriptor.value === "function";
75
+ current = Object.getPrototypeOf(current);
76
+ }
77
+ return false;
78
+ } catch {
79
+ return true;
80
+ }
81
+ }
82
+
83
+ // src/local-reference.ts
84
+ function eligibleLocalReference(nodeId, node, document) {
85
+ if (!node.target || node.unresolved || !node.reference.startsWith("#")) return false;
86
+ if (!document.nodes[node.target.nodeId]) return false;
87
+ return !document.diagnostics.some(
88
+ (diagnostic) => blockedReferenceCode(diagnostic.code) && (diagnostic.nodeId === nodeId || diagnostic.nodeId === node.target?.nodeId)
89
+ );
90
+ }
91
+ function blockedReferenceCode(code) {
92
+ return code === "JSON_RESOURCE_REBASE_UNSUPPORTED" || code === "JSON_UNRESOLVED_REFERENCE" || code === "JSON_INVALID_REFERENCE";
93
+ }
94
+
95
+ // src/editor-edge-budget.ts
96
+ var EditorAdmissionBudget = class {
97
+ definitions;
98
+ maximum;
99
+ rootResolution;
100
+ reserve;
101
+ admittedSourceEdges = 0;
102
+ children = 0;
103
+ evidenceUsed = false;
104
+ resolutions = 0;
105
+ truncated = false;
106
+ closed = false;
107
+ constructor(maximum, definitions, rootBounded) {
108
+ this.maximum = maximum;
109
+ this.definitions = definitions;
110
+ this.rootResolution = rootBounded ? 0 : 1;
111
+ this.reserve = rootBounded ? 0 : 1;
112
+ }
113
+ claimChild(reference3, selected) {
114
+ const local = selected.has(reference3.nodeId);
115
+ if (!this.canAdmit(1, local ? 1 : 0)) return false;
116
+ this.children += 1;
117
+ this.resolutions += local ? 1 : 0;
118
+ this.admittedSourceEdges += 1;
119
+ return true;
120
+ }
121
+ claimChildren(references, selected) {
122
+ const resolutions = references.filter((item) => selected.has(item.nodeId)).length;
123
+ if (!this.canAdmit(references.length, resolutions)) return false;
124
+ this.children += references.length;
125
+ this.resolutions += resolutions;
126
+ this.admittedSourceEdges += references.length;
127
+ return true;
128
+ }
129
+ claimDefinitionReference() {
130
+ if (!this.canAdmit(0, 1)) return false;
131
+ this.resolutions += 1;
132
+ this.admittedSourceEdges += 1;
133
+ return true;
134
+ }
135
+ evidenceEdge(_sourceId) {
136
+ this.truncated = true;
137
+ this.closed = true;
138
+ if (this.evidenceUsed || this.reserve === 0) return null;
139
+ this.evidenceUsed = true;
140
+ return null;
141
+ }
142
+ limitNode(sourceId) {
143
+ this.truncated = true;
144
+ this.closed = true;
145
+ return edgeLimitShape(sourceId);
146
+ }
147
+ admission() {
148
+ return calculateEditorGraphAdmission({
149
+ maxEdges: this.maximum,
150
+ roots: 1,
151
+ definitions: this.definitions,
152
+ children: this.children,
153
+ resolutions: this.rootResolution + this.resolutions,
154
+ evidenceReserve: this.reserve
155
+ });
156
+ }
157
+ get exhausted() {
158
+ return this.closed;
159
+ }
160
+ canAdmit(children, resolutions) {
161
+ if (this.closed) return false;
162
+ const admission = calculateEditorGraphAdmission({
163
+ maxEdges: this.maximum,
164
+ roots: 1,
165
+ definitions: this.definitions,
166
+ children: this.children + children,
167
+ resolutions: this.rootResolution + this.resolutions + resolutions,
168
+ evidenceReserve: this.reserve
169
+ });
170
+ if (admission.backboneAdmitted && !admission.truncated) return true;
171
+ this.truncated = true;
172
+ this.closed = true;
173
+ return false;
174
+ }
175
+ };
176
+ var RequiredNamesBudget = class {
177
+ maximumPerObject;
178
+ total;
179
+ retained = 0;
180
+ constructor(document, selected, maximum) {
181
+ this.maximumPerObject = maximum;
182
+ this.total = selectedRequiredNames(document, selected);
183
+ }
184
+ retain(values) {
185
+ const retained = values.slice(0, this.maximumPerObject);
186
+ this.retained += retained.length;
187
+ return retained;
188
+ }
189
+ requiresEvidence(node) {
190
+ return node.kind === "object" && node.required.length > this.maximumPerObject;
191
+ }
192
+ summary() {
193
+ return Object.freeze({
194
+ retained: this.retained,
195
+ total: this.total,
196
+ truncated: this.retained < this.total
197
+ });
198
+ }
199
+ };
200
+ function selectEditorNodes(document, maximumNodes, maximumEdges) {
201
+ if (maximumEdges < 4) {
202
+ return Object.freeze({ ids: /* @__PURE__ */ new Set(), rootBounded: true, truncated: true });
203
+ }
204
+ const maximum = Math.min(maximumNodes, maximumEdges - 3);
205
+ const ids = /* @__PURE__ */ new Set();
206
+ let truncated = false;
207
+ const add = (nodeId) => {
208
+ if (ids.has(nodeId) || !Object.hasOwn(document.nodes, nodeId)) return;
209
+ if (ids.size < maximum) ids.add(nodeId);
210
+ else truncated = true;
211
+ };
212
+ add(document.root.input.nodeId);
213
+ add(document.root.output.nodeId);
214
+ for (const definition of document.definitions) add(definition.node.nodeId);
215
+ for (const nodeId in document.nodes) {
216
+ if (!Object.hasOwn(document.nodes, nodeId)) continue;
217
+ add(nodeId);
218
+ }
219
+ return Object.freeze({ ids, rootBounded: false, truncated });
220
+ }
221
+ function countSourceEditorEdges(document, selected) {
222
+ let total = 0;
223
+ for (const nodeId of selected) {
224
+ const node = document.nodes[nodeId];
225
+ if (!node) continue;
226
+ total += nodeSourceEdges(nodeId, node, document);
227
+ }
228
+ return total;
229
+ }
230
+ function selectedRequiredNames(document, selected) {
231
+ let total = 0;
232
+ for (const nodeId of selected) {
233
+ const node = document.nodes[nodeId];
234
+ if (node?.kind === "object") total += node.required.length;
235
+ }
236
+ return total;
237
+ }
238
+ function nodeSourceEdges(nodeId, node, document) {
239
+ let total = applicatorEdgeCount(node);
240
+ if (node.kind === "object") total += node.properties.length + (node.additionalProperties ? 1 : 0);
241
+ if (node.kind === "array") total += 1;
242
+ if (node.kind === "tuple") total += node.items.length + (node.rest ? 1 : 0);
243
+ if (node.kind === "record") total += 2;
244
+ if (node.kind === "union") total += node.alternatives.length;
245
+ if (node.kind === "intersection") total += node.operands.length;
246
+ if (node.kind === "wrapper") total += 1;
247
+ if (node.kind === "ref" && eligibleLocalReference(nodeId, node, document)) total += 1;
248
+ return total;
249
+ }
250
+ function applicatorEdgeCount(node) {
251
+ const applicators = node.applicators;
252
+ if (!applicators) return 0;
253
+ let total = 0;
254
+ for (const name of ["if", "then", "else", "not", "contains", "propertyNames"]) {
255
+ if (applicators[name]) total += 1;
256
+ }
257
+ return total + Object.keys(applicators.patternProperties ?? {}).length + Object.keys(applicators.dependentSchemas ?? {}).length;
258
+ }
259
+ function edgeLimitShape(sourceId) {
260
+ return {
261
+ kind: "unknown",
262
+ reason: `bounded-edge:${sourceId}`,
263
+ evidenceCode: "edge-limit",
264
+ sourceId
265
+ };
266
+ }
267
+
268
+ // src/editor-relations.ts
269
+ function nodeEvidence(nodeId, node, selected, budget, requiredNames) {
270
+ const relations = applicatorRelations(nodeId, node.applicators, selected, budget);
271
+ const required = requiredNames.requiresEvidence(node) ? requiredNamesLimitRelation(nodeId, budget) : [];
272
+ return {
273
+ sourceId: nodeId,
274
+ ...node.metadata === void 0 ? {} : { annotations: node.metadata },
275
+ ...node.constraints === void 0 ? {} : { constraints: node.constraints },
276
+ relations: Object.freeze([...relations, ...required])
277
+ };
278
+ }
279
+ function applicatorRelations(nodeId, applicators, selected, budget) {
280
+ if (!applicators) return Object.freeze([]);
281
+ const output = [];
282
+ for (const name of ["if", "then", "else", "not", "contains", "propertyNames"]) {
283
+ const target = applicators[name];
284
+ if (!target) continue;
285
+ const shape = edgeReference(target, `${nodeId}.${name}`, selected, budget);
286
+ if (!shape) break;
287
+ output.push({ name, shape });
288
+ if (isEdgeLimit(shape)) return Object.freeze(output);
289
+ }
290
+ if (addKeyedRelations(
291
+ nodeId,
292
+ "patternProperties",
293
+ applicators.patternProperties,
294
+ output,
295
+ selected,
296
+ budget
297
+ )) {
298
+ return Object.freeze(output);
299
+ }
300
+ addKeyedRelations(
301
+ nodeId,
302
+ "dependentSchemas",
303
+ applicators.dependentSchemas,
304
+ output,
305
+ selected,
306
+ budget
307
+ );
308
+ return Object.freeze(output);
309
+ }
310
+ function addKeyedRelations(nodeId, name, input, output, selected, budget) {
311
+ for (const [key, target] of Object.entries(input ?? {})) {
312
+ const shape = edgeReference(target, `${nodeId}.${name}.${key}`, selected, budget);
313
+ if (!shape) return true;
314
+ output.push({ name, key, shape });
315
+ if (isEdgeLimit(shape)) return true;
316
+ }
317
+ return false;
318
+ }
319
+ function requiredNamesLimitRelation(nodeId, budget) {
320
+ const shape = budget.evidenceEdge(`${nodeId}.requiredNames`);
321
+ return shape ? [{ name: "requiredNames", shape }] : [];
322
+ }
323
+ function edgeReference(value, source, selected, budget) {
324
+ if (budget.claimChild(value, selected)) return reference(value.nodeId, selected);
325
+ return budget.evidenceEdge(source);
326
+ }
327
+ function reference(definition, selected) {
328
+ if (selected.has(definition)) return { kind: "reference", definition };
329
+ return {
330
+ kind: "unknown",
331
+ reason: `bounded:${definition}`,
332
+ evidenceCode: "node-limit",
333
+ sourceId: definition
334
+ };
335
+ }
336
+ function isEdgeLimit(shape) {
337
+ return shape.kind === "unknown" && shape.evidenceCode === "edge-limit";
338
+ }
339
+
340
+ // src/editor-document.ts
341
+ function schemanEditorDocument(source, limits) {
342
+ const selection = selectEditorNodes(source, limits.maxNodes, limits.maxEdges);
343
+ const requiredNames = new RequiredNamesBudget(source, selection.ids, limits.maxEdges);
344
+ const sourceEdgeTotal = countSourceEditorEdges(source, selection.ids);
345
+ const budget = new EditorAdmissionBudget(
346
+ limits.maxEdges,
347
+ selection.ids.size,
348
+ selection.rootBounded
349
+ );
350
+ const converted = convertDefinitions(source, selection.ids, budget, requiredNames);
351
+ const definitions = prioritizedDefinitions(source, selection.ids, converted);
352
+ const requiredNamesSummary = requiredNames.summary();
353
+ const sourceEdges = Object.freeze({
354
+ retained: budget.admittedSourceEdges,
355
+ total: sourceEdgeTotal,
356
+ truncated: budget.admittedSourceEdges < sourceEdgeTotal
357
+ });
358
+ const evidence = [];
359
+ if (sourceEdges.truncated || requiredNamesSummary.truncated) evidence.push("edge-limit");
360
+ if (selection.truncated) evidence.push("node-limit");
361
+ return Object.freeze({
362
+ admission: budget.admission(),
363
+ document: Object.freeze({
364
+ root: selection.rootBounded ? budget.limitNode(source.root.input.nodeId) : reference2(source.root.input.nodeId, selection.ids),
365
+ definitions: Object.freeze(definitions),
366
+ evidence: Object.freeze(evidence)
367
+ }),
368
+ retainedNodes: definitions.length,
369
+ retainedEdges: budget.admittedSourceEdges,
370
+ sourceEdges,
371
+ nodeTruncated: selection.truncated,
372
+ edgeTruncated: sourceEdges.truncated,
373
+ requiredNames: requiredNamesSummary,
374
+ truncated: selection.truncated || sourceEdges.truncated || requiredNamesSummary.truncated
375
+ });
376
+ }
377
+ function convertDefinitions(source, selected, budget, requiredNames) {
378
+ const converted = /* @__PURE__ */ new Map();
379
+ for (const nodeId of selected) {
380
+ const node = source.nodes[nodeId];
381
+ if (node)
382
+ converted.set(nodeId, convertNode(nodeId, node, source, selected, budget, requiredNames));
383
+ }
384
+ return converted;
385
+ }
386
+ function prioritizedDefinitions(source, selected, converted) {
387
+ const ids = [source.root.input.nodeId, ...Object.keys(source.nodes)];
388
+ const emitted = /* @__PURE__ */ new Set();
389
+ const definitions = [];
390
+ for (const nodeId of ids) {
391
+ if (emitted.has(nodeId) || !selected.has(nodeId)) continue;
392
+ const shape = converted.get(nodeId);
393
+ if (!shape) continue;
394
+ emitted.add(nodeId);
395
+ definitions.push(Object.freeze({ name: nodeId, shape }));
396
+ }
397
+ return definitions;
398
+ }
399
+ function convertNode(nodeId, node, document, selected, budget, requiredNames) {
400
+ if (budget.exhausted) return budget.limitNode(nodeId);
401
+ const shape = convertStructure(nodeId, node, document, selected, budget, requiredNames);
402
+ const evidence = nodeEvidence(nodeId, node, selected, budget, requiredNames);
403
+ return { ...shape, ...evidence };
404
+ }
405
+ function convertStructure(nodeId, node, document, selected, budget, requiredNames) {
406
+ const simple = simpleShape(node);
407
+ if (simple) return simple;
408
+ if (node.kind === "object") return objectShape(nodeId, node, selected, budget, requiredNames);
409
+ if (node.kind === "array") return singleChildShape("array", nodeId, node.items, selected, budget);
410
+ if (node.kind === "tuple") return tupleShape(nodeId, node, selected, budget);
411
+ if (node.kind === "record") return recordShape(nodeId, node, selected, budget);
412
+ if (node.kind === "union") return unionShape(nodeId, node, selected, budget);
413
+ if (node.kind === "intersection") {
414
+ return {
415
+ kind: "intersection",
416
+ operands: boundedReferences(node.operands, `${nodeId}.operand`, selected, budget)
417
+ };
418
+ }
419
+ if (node.kind === "ref") return referenceShape(nodeId, node, document, selected, budget);
420
+ if (node.kind === "wrapper") {
421
+ const inner = edgeReference2(node.inner, `${nodeId}.inner`, selected, budget);
422
+ return inner ? {
423
+ kind: "wrapper",
424
+ wrapper: node.wrapper,
425
+ inner,
426
+ ...node.value === void 0 ? {} : { value: node.value }
427
+ } : budget.limitNode(nodeId);
428
+ }
429
+ return { kind: "unknown", reason: `unsupported:${nodeId}` };
430
+ }
431
+ function simpleShape(node) {
432
+ if (node.kind === "unknown") return { kind: "unknown", reason: node.reason };
433
+ if (node.kind === "opaque") return { kind: "opaque", reason: node.reason };
434
+ if (node.kind === "unconstrained") return { kind: "unconstrained", domain: node.domain };
435
+ if (node.kind === "never") return { kind: "never" };
436
+ if (node.kind === "primitive") return { kind: "scalar", name: node.type };
437
+ if (node.kind === "literal") return { kind: "literal", value: node.value };
438
+ if (node.kind === "enum") return { kind: "enum", values: node.values };
439
+ return void 0;
440
+ }
441
+ function objectShape(nodeId, node, selected, budget, requiredNames) {
442
+ const properties = [];
443
+ let limited = false;
444
+ for (const property of node.properties) {
445
+ const shape = edgeReference2(
446
+ property.node,
447
+ `${nodeId}.property.${property.name}`,
448
+ selected,
449
+ budget
450
+ );
451
+ if (!shape) break;
452
+ properties.push({
453
+ name: property.name,
454
+ required: property.presence === "required",
455
+ presence: property.presence,
456
+ shape
457
+ });
458
+ if (isEdgeLimit2(shape)) {
459
+ limited = true;
460
+ break;
461
+ }
462
+ }
463
+ const additional = limited ? null : optionalEdgeReference(node.additionalProperties, `${nodeId}.additional`, selected, budget);
464
+ return {
465
+ kind: "object",
466
+ properties,
467
+ requiredNames: requiredNames.retain(node.required),
468
+ unknownKeys: node.unknownKeys,
469
+ ...additional ? { additionalProperties: additional } : {}
470
+ };
471
+ }
472
+ function tupleShape(nodeId, node, selected, budget) {
473
+ const items = boundedReferences(node.items, `${nodeId}.item`, selected, budget);
474
+ const rest = isEdgeLimit2(items.at(-1)) ? null : optionalEdgeReference(node.rest, `${nodeId}.rest`, selected, budget);
475
+ return { kind: "tuple", items, ...rest ? { rest } : {} };
476
+ }
477
+ function recordShape(nodeId, node, selected, budget) {
478
+ if (!budget.claimChildren([node.key, node.value], selected)) return budget.limitNode(nodeId);
479
+ return {
480
+ kind: "record",
481
+ key: reference2(node.key.nodeId, selected),
482
+ value: reference2(node.value.nodeId, selected),
483
+ exhaustive: node.exhaustive
484
+ };
485
+ }
486
+ function unionShape(nodeId, node, selected, budget) {
487
+ return {
488
+ kind: "union",
489
+ variants: boundedReferences(node.alternatives, `${nodeId}.variant`, selected, budget),
490
+ semantics: node.semantics,
491
+ ...node.discriminator === void 0 ? {} : { discriminator: node.discriminator }
492
+ };
493
+ }
494
+ function singleChildShape(kind, nodeId, value, selected, budget) {
495
+ const element = edgeReference2(value, `${nodeId}.items`, selected, budget);
496
+ return element ? { kind, element } : budget.limitNode(nodeId);
497
+ }
498
+ function referenceShape(nodeId, node, document, selected, budget) {
499
+ if (!eligibleLocalReference(nodeId, node, document)) {
500
+ return {
501
+ kind: "reference",
502
+ definition: `unsupported:${nodeId}`,
503
+ reference: node.reference,
504
+ unresolved: node.unresolved ?? "non-local-reference"
505
+ };
506
+ }
507
+ const target = node.target?.nodeId;
508
+ if (!selected.has(target)) {
509
+ return {
510
+ kind: "unknown",
511
+ reason: `bounded-reference:${node.reference}`,
512
+ evidenceCode: "node-limit"
513
+ };
514
+ }
515
+ if (!budget.claimDefinitionReference()) return budget.limitNode(nodeId);
516
+ return { kind: "reference", definition: target, reference: node.reference };
517
+ }
518
+ function boundedReferences(values, source, selected, budget) {
519
+ const output = [];
520
+ for (let index = 0; index < values.length; index += 1) {
521
+ const value = values[index];
522
+ if (!value) continue;
523
+ const shape = edgeReference2(value, `${source}.${String(index)}`, selected, budget);
524
+ if (!shape) break;
525
+ output.push(shape);
526
+ if (isEdgeLimit2(shape)) break;
527
+ }
528
+ return output;
529
+ }
530
+ function optionalEdgeReference(value, source, selected, budget) {
531
+ return value ? edgeReference2(value, source, selected, budget) : null;
532
+ }
533
+ function edgeReference2(value, source, selected, budget) {
534
+ if (budget.claimChild(value, selected)) return reference2(value.nodeId, selected);
535
+ return budget.evidenceEdge(source);
536
+ }
537
+ function isEdgeLimit2(shape) {
538
+ return shape?.kind === "unknown" && shape.evidenceCode === "edge-limit";
539
+ }
540
+ function reference2(definition, selected) {
541
+ if (selected.has(definition)) return { kind: "reference", definition };
542
+ return {
543
+ kind: "unknown",
544
+ reason: `bounded:${definition}`,
545
+ evidenceCode: "node-limit",
546
+ sourceId: definition
547
+ };
548
+ }
549
+
550
+ // src/editor-invariants.ts
551
+ function validNormalizedEditorGraph(graph, bindingId, intendedSourceId) {
552
+ if (!graph.admission || graph.admission.total > graph.admission.budget) return false;
553
+ const root = graph.roots.find((item) => item.bindingId === bindingId);
554
+ if (!root) return false;
555
+ const rootNode = nodeById(graph, root.nodeId);
556
+ if (!rootNode || !validRootNode(graph, rootNode, intendedSourceId)) return false;
557
+ return graph.nodes.every(validReferenceBoundary);
558
+ }
559
+ function validRootNode(graph, root, intendedSourceId) {
560
+ if (intentionalBoundedUnknown(root)) return true;
561
+ if (root.kind !== "reference" || root.status !== "resolved" || !root.target) return false;
562
+ const target = nodeById(graph, root.target.nodeId);
563
+ return Boolean(
564
+ target && (target.sourceId === intendedSourceId || intentionalBoundedUnknown(target))
565
+ );
566
+ }
567
+ function validReferenceBoundary(node) {
568
+ if (node.kind !== "reference") return true;
569
+ if (node.unresolved !== void 0) {
570
+ return node.status === "unresolved" && node.availability === "unavailable" && !node.target;
571
+ }
572
+ if (node.reference !== void 0 && !node.reference.startsWith("#")) return true;
573
+ return node.status === "resolved";
574
+ }
575
+ function intentionalBoundedUnknown(node) {
576
+ return node.kind === "unknown" && node.evidence.some((item) => item.code === "edge-limit" || item.code === "node-limit");
577
+ }
578
+ function nodeById(graph, nodeId) {
579
+ return graph.nodes.find((node) => node.id === nodeId);
580
+ }
581
+ function resolveProfile(options, conservative) {
582
+ try {
583
+ return resolveProfileSafely(options, conservative);
584
+ } catch {
585
+ return failed("SCHEMAN_ADAPTER_PROFILE_MALFORMED", "<unavailable>");
586
+ }
587
+ }
588
+ function resolveProfileSafely(options, conservative) {
589
+ const nodeId = options.document.root.output.nodeId;
590
+ const node = options.document.nodes[nodeId];
591
+ if (!node) return failed("SCHEMAN_ADAPTER_UNRESOLVED_ROOT", nodeId);
592
+ const local = readNodeProfile(node, nodeId);
593
+ if (!local.ok) return local;
594
+ const override = options.binding.override ? readPayload(options.binding.override, false, nodeId) : Object.freeze({ ok: true, value: void 0 });
595
+ if (!override.ok) return override;
596
+ const selected = override.value ?? local.value;
597
+ const source = override.value ? "override" : local.value ? "x-kalada" : "conservative";
598
+ if (!selected) return success({ type: conservative, source, finalValidation: "kalada-type" });
599
+ const compatibility = checkCompatibility(selected, conservative, node, options, nodeId);
600
+ if (!compatibility.ok) return compatibility;
601
+ return success({
602
+ ...selected,
603
+ source,
604
+ finalValidation: selected.lossy === "safe-integer-bigint-to-number" ? "safe-integer-and-kalada-type" : "kalada-type"
605
+ });
606
+ }
607
+ function readNodeProfile(node, nodeId) {
608
+ const metadata = optionalRecord(node.metadata);
609
+ const constraints = optionalRecord(node.constraints);
610
+ if (!metadata.ok || !constraints.ok) return failed("SCHEMAN_ADAPTER_PROFILE_MALFORMED", nodeId);
611
+ const direct = ownSlot(metadata.value, "x-kalada");
612
+ const extensions = nestedRecord(metadata.value, "extensions");
613
+ const annotations = nestedRecord(metadata.value, "annotations");
614
+ if (!extensions.ok || !annotations.ok) return failed("SCHEMAN_ADAPTER_PROFILE_MALFORMED", nodeId);
615
+ const extension = ownSlot(extensions.value, "x-kalada");
616
+ const annotation = ownSlot(annotations.value, "x-kalada");
617
+ const constrained = ownSlot(constraints.value, "x-kalada");
618
+ if (annotation.present || constrained.present || direct.present && extension.present) {
619
+ return failed("SCHEMAN_ADAPTER_PROFILE_CONFLICT", nodeId);
620
+ }
621
+ const payload = direct.present ? direct : extension;
622
+ if (!payload.present) return Object.freeze({ ok: true });
623
+ return readPayload(payload.value, true, nodeId);
624
+ }
625
+ function readPayload(input, versioned, nodeId) {
626
+ const inspected = ownRecord(input);
627
+ const allowed = versioned ? ["version", "type", "codec", "lossy"] : ["type", "codec", "lossy"];
628
+ if (!inspected.ok) return failed("SCHEMAN_ADAPTER_PROFILE_MALFORMED", nodeId);
629
+ const record = inspected.value;
630
+ if (!exactAllowedKeys(inspected, allowed) || versioned && record.version !== 1) {
631
+ return failed("SCHEMAN_ADAPTER_PROFILE_MALFORMED", nodeId);
632
+ }
633
+ const type = readSemanticType(record.type);
634
+ const codec = readBoundedText(record.codec);
635
+ const lossy = readLossPolicy(record.lossy);
636
+ if (!type.ok || codec === null || lossy === null) {
637
+ return failed("SCHEMAN_ADAPTER_PROFILE_MALFORMED", nodeId);
638
+ }
639
+ return success({
640
+ type: type.value,
641
+ ...codec ? { codec } : {},
642
+ ...lossy ? { lossy } : {},
643
+ source: versioned ? "x-kalada" : "override",
644
+ finalValidation: "kalada-type"
645
+ });
646
+ }
647
+ function checkCompatibility(profile, conservative, node, options, nodeId) {
648
+ const conversion = !sameType(profile.type, conservative) || profile.lossy !== void 0;
649
+ if (conversion && !profile.codec) return failed("SCHEMAN_ADAPTER_CODEC_REQUIRED", nodeId);
650
+ if (profile.lossy && !validLossPolicy(profile, node)) {
651
+ return failed("SCHEMAN_ADAPTER_PROFILE_INCOMPATIBLE", nodeId);
652
+ }
653
+ if (profile.codec && !matchingCodec(profile.codec, options)) {
654
+ return failed("SCHEMAN_ADAPTER_CODEC_MISMATCH", nodeId);
655
+ }
656
+ return success(profile);
657
+ }
658
+ function validLossPolicy(profile, node) {
659
+ if (profile.lossy === "safe-integer-bigint-to-number") {
660
+ return node.kind === "primitive" && node.type === "bigint" && isPrimitive(profile.type, "number");
661
+ }
662
+ if (profile.lossy === "heterogeneous-union-to-json") {
663
+ return node.kind === "union" && isPrimitive(profile.type, "json");
664
+ }
665
+ return true;
666
+ }
667
+ function matchingCodec(id, options) {
668
+ const codec = options.codec;
669
+ return Boolean(
670
+ codec && codec.id === id && codec.mode === options.mode && codec.capabilityVersion.length > 0 && codec.configurationDigest.length > 0
671
+ );
672
+ }
673
+ function isPrimitive(type, name) {
674
+ return type !== "dynamic" && type.kind === "primitive-type" && type.name === name;
675
+ }
676
+ function sameType(left, right) {
677
+ return JSON.stringify(left) === JSON.stringify(right);
678
+ }
679
+ function readBoundedText(value) {
680
+ if (value === void 0) return void 0;
681
+ return typeof value === "string" && value.length > 0 && value.length <= 256 ? value : null;
682
+ }
683
+ function readLossPolicy(value) {
684
+ if (value === void 0) return void 0;
685
+ return value === "safe-integer-bigint-to-number" || value === "heterogeneous-union-to-json" ? value : null;
686
+ }
687
+ function exactAllowedKeys(record, allowed) {
688
+ return record.keys.includes("type") && record.keys.every((key) => allowed.includes(key));
689
+ }
690
+ function ownRecord(input) {
691
+ if (typeof input !== "object" || input === null) return Object.freeze({ ok: false });
692
+ const reflected = reflectRecord(input);
693
+ if (!reflected) return Object.freeze({ ok: false });
694
+ const output = /* @__PURE__ */ Object.create(null);
695
+ for (const key of reflected.keys) output[key] = reflected.descriptors[key]?.value;
696
+ return Object.freeze({
697
+ ok: true,
698
+ value: Object.freeze(output),
699
+ keys: Object.freeze(reflected.keys)
700
+ });
701
+ }
702
+ function reflectRecord(input) {
703
+ try {
704
+ if (Array.isArray(input)) return null;
705
+ const prototype = Object.getPrototypeOf(input);
706
+ if (prototype !== null && prototype !== Object.prototype) return null;
707
+ const ownKeys = Reflect.ownKeys(input);
708
+ if (ownKeys.some((key) => typeof key !== "string")) return null;
709
+ const keys = ownKeys;
710
+ const descriptors = /* @__PURE__ */ Object.create(null);
711
+ for (const key of keys) {
712
+ const descriptor = Object.getOwnPropertyDescriptor(input, key);
713
+ if (!descriptor || !("value" in descriptor)) return null;
714
+ descriptors[key] = descriptor;
715
+ }
716
+ return { keys, descriptors };
717
+ } catch {
718
+ return null;
719
+ }
720
+ }
721
+ function optionalRecord(input) {
722
+ if (input === void 0 || isProfileFreeOwnedValue(input)) return Object.freeze({ ok: true });
723
+ const record = ownRecord(input);
724
+ return record.ok ? Object.freeze({ ok: true, value: record }) : Object.freeze({ ok: false });
725
+ }
726
+ function isProfileFreeOwnedValue(input) {
727
+ if (input === null || typeof input === "string" || typeof input === "boolean") return true;
728
+ if (typeof input === "number") return Number.isFinite(input);
729
+ return Array.isArray(input);
730
+ }
731
+ function nestedRecord(parent, key) {
732
+ const slot = ownSlot(parent, key);
733
+ return slot.present ? optionalRecord(slot.value) : Object.freeze({ ok: true });
734
+ }
735
+ function ownSlot(record, key) {
736
+ if (!record?.keys.includes(key)) return Object.freeze({ present: false });
737
+ return Object.freeze({ present: true, value: record.value[key] });
738
+ }
739
+ function success(value) {
740
+ return Object.freeze({ ok: true, value: Object.freeze(value) });
741
+ }
742
+ function failed(code, nodeId) {
743
+ return Object.freeze({
744
+ ok: false,
745
+ diagnostics: Object.freeze([
746
+ Object.freeze({ code, severity: "error", side: "output", sourcePointer: "", nodeId })
747
+ ])
748
+ });
749
+ }
750
+
751
+ // src/semantic-mapping.ts
752
+ var primitive = (name) => Object.freeze({ kind: "primitive-type", name });
753
+ function projectOutput(document, limits) {
754
+ const rootId = document.root.output.nodeId;
755
+ const graph = collectGraph(rootId, document, limits);
756
+ if (graph.bounded) return boundedProjection(rootId);
757
+ const safe = jsonSafety(graph, document);
758
+ const states = projectionStates(graph, safe, document, limits.maxTypeDepth);
759
+ const type = states.get(rootId)?.type ?? "dynamic";
760
+ return Object.freeze({ type, diagnostics: projectionDiagnostics(type, rootId) });
761
+ }
762
+ function collectGraph(rootId, document, limits) {
763
+ const nodes = /* @__PURE__ */ new Map();
764
+ const pending = [rootId];
765
+ let edges = 0;
766
+ let bounded2 = false;
767
+ while (pending.length > 0) {
768
+ const nodeId = pending.pop();
769
+ if (!nodeId || nodes.has(nodeId)) continue;
770
+ if (nodes.size >= limits.maxNodes) {
771
+ bounded2 = true;
772
+ break;
773
+ }
774
+ const node = document.nodes[nodeId];
775
+ if (!node) continue;
776
+ nodes.set(nodeId, node);
777
+ const children = projectionChildren(nodeId, node, document);
778
+ for (let index = children.length - 1; index >= 0; index -= 1) {
779
+ edges += 1;
780
+ if (edges > limits.maxEdges) {
781
+ bounded2 = true;
782
+ break;
783
+ }
784
+ pending.push(children[index]);
785
+ }
786
+ if (bounded2) break;
787
+ }
788
+ return Object.freeze({ nodes, bounded: bounded2 });
789
+ }
790
+ function projectionChildren(nodeId, node, document) {
791
+ if (hasApplicators(node)) return [];
792
+ if (node.kind === "object") {
793
+ return [
794
+ ...node.properties.map((property) => property.node.nodeId),
795
+ ...node.additionalProperties ? [node.additionalProperties.nodeId] : []
796
+ ];
797
+ }
798
+ if (node.kind === "array") return [node.items.nodeId];
799
+ if (node.kind === "tuple") return refs([...node.items, ...node.rest ? [node.rest] : []]);
800
+ if (node.kind === "record") return [node.key.nodeId, node.value.nodeId];
801
+ if (node.kind === "union") return refs(node.alternatives);
802
+ if (node.kind === "intersection") return refs(node.operands);
803
+ if (node.kind === "wrapper") return [node.inner.nodeId];
804
+ if (node.kind === "ref" && eligibleLocalReference(nodeId, node, document)) {
805
+ return [node.target?.nodeId];
806
+ }
807
+ return [];
808
+ }
809
+ function jsonSafety(graph, document) {
810
+ const safe = /* @__PURE__ */ new Map();
811
+ const stringKeys = stringKeyDomains(graph, document);
812
+ for (const [nodeId, node] of graph.nodes) safe.set(nodeId, jsonCandidate(nodeId, node, document));
813
+ for (let pass = 0; pass < graph.nodes.size; pass += 1) {
814
+ let changed = false;
815
+ for (const [nodeId, node] of graph.nodes) {
816
+ if (!safe.get(nodeId) || jsonDependenciesSafe(nodeId, node, safe, stringKeys, document))
817
+ continue;
818
+ safe.set(nodeId, false);
819
+ changed = true;
820
+ }
821
+ if (!changed) break;
822
+ }
823
+ return safe;
824
+ }
825
+ function jsonCandidate(nodeId, node, document) {
826
+ if (hasApplicators(node)) return false;
827
+ if (node.kind === "primitive") {
828
+ return ["null", "boolean", "number", "integer", "string"].includes(node.type);
829
+ }
830
+ if (node.kind === "literal") return isJsonValue(node.value);
831
+ if (node.kind === "enum") return node.values.every(isJsonValue);
832
+ if (node.kind === "unconstrained") return node.domain === "json";
833
+ if (node.kind === "ref") return eligibleLocalReference(nodeId, node, document);
834
+ if (node.kind === "wrapper") return node.wrapper === "readonly" || node.wrapper === "brand";
835
+ return ["object", "array", "tuple", "record", "union", "intersection"].includes(node.kind);
836
+ }
837
+ function jsonDependenciesSafe(nodeId, node, safe, stringKeys, document) {
838
+ if (node.kind === "object") return objectDependenciesSafe(node, safe);
839
+ if (node.kind === "array") return safe.get(node.items.nodeId) === true;
840
+ if (node.kind === "tuple")
841
+ return refsSafe([...node.items, ...node.rest ? [node.rest] : []], safe);
842
+ if (node.kind === "record") {
843
+ return stringKeys.get(node.key.nodeId) === true && safe.get(node.value.nodeId) === true;
844
+ }
845
+ if (node.kind === "union") return refsSafe(node.alternatives, safe);
846
+ if (node.kind === "intersection") return refsSafe(node.operands, safe);
847
+ if (node.kind === "wrapper") return safe.get(node.inner.nodeId) === true;
848
+ if (node.kind === "ref" && eligibleLocalReference(nodeId, node, document)) {
849
+ return safe.get(node.target?.nodeId) === true;
850
+ }
851
+ return true;
852
+ }
853
+ function objectDependenciesSafe(node, safe) {
854
+ if (!node.properties.every((property) => safe.get(property.node.nodeId) === true)) return false;
855
+ const additionalSafe = node.additionalProperties ? safe.get(node.additionalProperties.nodeId) === true : false;
856
+ if (node.unknownKeys === "schema") return additionalSafe;
857
+ if (node.unknownKeys === "passthrough" || node.unknownKeys === "unknown") return additionalSafe;
858
+ return !node.additionalProperties || additionalSafe;
859
+ }
860
+ function stringKeyDomains(graph, document) {
861
+ const output = /* @__PURE__ */ new Map();
862
+ for (const [nodeId, node] of graph.nodes) output.set(nodeId, directStringDomain(node));
863
+ for (let pass = 0; pass < graph.nodes.size; pass += 1) {
864
+ let changed = false;
865
+ for (const [nodeId, node] of graph.nodes) {
866
+ if (output.get(nodeId) || !derivedStringDomain(nodeId, node, output, document)) continue;
867
+ output.set(nodeId, true);
868
+ changed = true;
869
+ }
870
+ if (!changed) break;
871
+ }
872
+ return output;
873
+ }
874
+ function directStringDomain(node) {
875
+ if (node.kind === "primitive") return node.type === "string";
876
+ if (node.kind === "literal") return typeof node.value === "string";
877
+ return node.kind === "enum" && node.values.length > 0 && node.values.every((item) => typeof item === "string");
878
+ }
879
+ function derivedStringDomain(nodeId, node, domains, document) {
880
+ if (node.kind === "wrapper" && (node.wrapper === "readonly" || node.wrapper === "brand")) {
881
+ return domains.get(node.inner.nodeId) === true;
882
+ }
883
+ if (node.kind === "ref" && eligibleLocalReference(nodeId, node, document)) {
884
+ return domains.get(node.target?.nodeId) === true;
885
+ }
886
+ if (node.kind === "union") return node.alternatives.every((ref) => domains.get(ref.nodeId));
887
+ if (node.kind === "intersection") return node.operands.every((ref) => domains.get(ref.nodeId));
888
+ return false;
889
+ }
890
+ function projectionStates(graph, safe, document, maxDepth) {
891
+ const states = /* @__PURE__ */ new Map();
892
+ for (const [nodeId, node] of graph.nodes) {
893
+ const direct = directProjection(node, safe.get(nodeId) === true);
894
+ if (direct) states.set(nodeId, direct);
895
+ }
896
+ for (let pass = 0; pass < graph.nodes.size; pass += 1) {
897
+ let changed = false;
898
+ for (const [nodeId, node] of graph.nodes) {
899
+ if (states.has(nodeId)) continue;
900
+ const derived = derivedProjection(nodeId, node, states, document, maxDepth);
901
+ if (!derived) continue;
902
+ states.set(nodeId, derived);
903
+ changed = true;
904
+ }
905
+ if (!changed) break;
906
+ }
907
+ return states;
908
+ }
909
+ function directProjection(node, jsonSafe) {
910
+ if (hasApplicators(node)) return null;
911
+ if (node.kind === "primitive") return state(primitiveProjection(node.type));
912
+ if (node.kind === "literal") return state(literalProjection(node.value));
913
+ if (node.kind === "enum") return state(enumProjection(node.values));
914
+ if (node.kind === "unconstrained" && node.domain === "json") return state(primitive("json"));
915
+ if (["object", "record", "tuple"].includes(node.kind) && jsonSafe)
916
+ return state(primitive("json"));
917
+ return null;
918
+ }
919
+ function derivedProjection(nodeId, node, states, document, maxDepth) {
920
+ if (node.kind === "array") return arrayState(states.get(node.items.nodeId), maxDepth);
921
+ if (node.kind === "union") return sharedState(node.alternatives, states);
922
+ if (node.kind === "intersection") return sharedState(node.operands, states);
923
+ if (node.kind === "wrapper" && (node.wrapper === "readonly" || node.wrapper === "brand")) {
924
+ return states.get(node.inner.nodeId) ?? null;
925
+ }
926
+ if (node.kind === "ref" && eligibleLocalReference(nodeId, node, document)) {
927
+ return states.get(node.target?.nodeId) ?? null;
928
+ }
929
+ return null;
930
+ }
931
+ function primitiveProjection(type) {
932
+ if (type === "null" || type === "boolean" || type === "string") return primitive(type);
933
+ return type === "number" || type === "integer" ? primitive("number") : "dynamic";
934
+ }
935
+ function literalProjection(value) {
936
+ const domain = primitiveDomain(value);
937
+ return domain ? primitive(domain) : "dynamic";
938
+ }
939
+ function enumProjection(values) {
940
+ const domains = new Set(values.map(primitiveDomain));
941
+ const [domain] = domains;
942
+ return domains.size === 1 && domain ? primitive(domain) : "dynamic";
943
+ }
944
+ function arrayState(element, maxDepth) {
945
+ if (!element || element.type === "dynamic" || element.depth >= maxDepth) return null;
946
+ return Object.freeze({
947
+ type: Object.freeze({ kind: "array-type", element: element.type }),
948
+ depth: element.depth + 1
949
+ });
950
+ }
951
+ function sharedState(refs2, states) {
952
+ const values = refs2.map((ref) => states.get(ref.nodeId));
953
+ const first = values[0];
954
+ if (!first || first.type === "dynamic" || values.some((item) => !item)) return null;
955
+ return values.every((item) => sameType2(item?.type, first.type)) ? first : null;
956
+ }
957
+ function state(type) {
958
+ return type === "dynamic" ? null : Object.freeze({ type, depth: 0 });
959
+ }
960
+ function refsSafe(values, safe) {
961
+ return values.every((ref) => safe.get(ref.nodeId) === true);
962
+ }
963
+ function refs(values) {
964
+ return values.map((value) => value.nodeId);
965
+ }
966
+ function primitiveDomain(value) {
967
+ if (value === null) return "null";
968
+ if (typeof value === "boolean") return "boolean";
969
+ if (typeof value === "string") return "string";
970
+ return typeof value === "number" && Number.isFinite(value) ? "number" : null;
971
+ }
972
+ function isJsonValue(input) {
973
+ const pending = [input];
974
+ let visits = 0;
975
+ while (pending.length > 0) {
976
+ const value = pending.pop();
977
+ visits += 1;
978
+ if (visits > 1e4) return false;
979
+ if (primitiveDomain(value)) continue;
980
+ if (Array.isArray(value)) {
981
+ pending.push(...value);
982
+ continue;
983
+ }
984
+ if (typeof value !== "object" || value === null) return false;
985
+ pending.push(...Object.values(value));
986
+ }
987
+ return true;
988
+ }
989
+ function hasApplicators(node) {
990
+ const value = node.applicators;
991
+ if (!value) return false;
992
+ if (value.if || value.then || value.else || value.not || value.contains || value.propertyNames)
993
+ return true;
994
+ return Object.keys(value.patternProperties ?? {}).length > 0 || Object.keys(value.dependentSchemas ?? {}).length > 0;
995
+ }
996
+ function sameType2(left, right) {
997
+ return left !== void 0 && JSON.stringify(left) === JSON.stringify(right);
998
+ }
999
+ function projectionDiagnostics(type, nodeId) {
1000
+ if (type !== "dynamic") return Object.freeze([]);
1001
+ return Object.freeze([
1002
+ warning("SCHEMAN_ADAPTER_UNSUPPORTED_EVIDENCE", nodeId),
1003
+ warning("SCHEMAN_ADAPTER_DYNAMIC_PROJECTION", nodeId)
1004
+ ]);
1005
+ }
1006
+ function boundedProjection(nodeId) {
1007
+ return Object.freeze({
1008
+ type: "dynamic",
1009
+ diagnostics: Object.freeze([
1010
+ warning("SCHEMAN_ADAPTER_ANALYSIS_LIMIT", nodeId),
1011
+ warning("SCHEMAN_ADAPTER_DYNAMIC_PROJECTION", nodeId)
1012
+ ])
1013
+ });
1014
+ }
1015
+ function warning(code, nodeId) {
1016
+ return Object.freeze({ code, severity: "warning", side: "output", sourcePointer: "", nodeId });
1017
+ }
1018
+
1019
+ // src/adapter.ts
1020
+ var validatorHandle = "scheman-validator";
1021
+ var codecHandle = "scheman-codec";
1022
+ var maximumSourceRecords = 512;
1023
+ function adaptSchemanDocument(options) {
1024
+ const document = options.document;
1025
+ const invalid = validateDocument(document);
1026
+ if (invalid) return failure(invalid);
1027
+ const limits = resolveAnalysisLimits(options.analysisLimits);
1028
+ const projection = projectOutput(document, limits);
1029
+ const profile = resolveProfile(options, projection.type);
1030
+ if (!profile.ok) return Object.freeze({ ok: false, diagnostics: profile.diagnostics });
1031
+ const editor = schemanEditorDocument(document, limits);
1032
+ const sourceEvidence = boundedSourceEvidence(
1033
+ document,
1034
+ Math.min(limits.maxNodes, maximumSourceRecords)
1035
+ );
1036
+ const described = describeEnvironment(
1037
+ adapterProvider(options, document, profile.value, limits, editor, sourceEvidence)
1038
+ );
1039
+ if (!described.ok) return failure(adapterFailure("SCHEMAN_ADAPTER_INVALID_DOCUMENT"));
1040
+ if (!validNormalizedEditorGraph(
1041
+ described.environment.editorGraph,
1042
+ options.binding.id,
1043
+ document.root.input.nodeId
1044
+ )) {
1045
+ return failure(adapterFailure("SCHEMAN_ADAPTER_INVALID_DOCUMENT"));
1046
+ }
1047
+ return Object.freeze({
1048
+ ok: true,
1049
+ environment: described.environment,
1050
+ capabilitySnapshot: described.capabilitySnapshot,
1051
+ diagnostics: Object.freeze([
1052
+ ...sourceDiagnostics(sourceEvidence.diagnostics.values),
1053
+ ...projection.diagnostics,
1054
+ ...sourceLimitDiagnostics(sourceEvidence, editor)
1055
+ ]),
1056
+ ...options.validator ? { retainedValidator: options.validator.validator } : {}
1057
+ });
1058
+ }
1059
+ function adapterProvider(options, document, profile, limits, editor, sourceEvidence) {
1060
+ return createManualProvider({
1061
+ mode: options.mode,
1062
+ providerId: options.providerId,
1063
+ providerVersion: options.providerVersion,
1064
+ configurationDigest: options.configurationDigest,
1065
+ cacheable: options.cacheable,
1066
+ capabilities: configuredCapabilities(options, profile),
1067
+ bindings: [
1068
+ {
1069
+ id: options.binding.id,
1070
+ name: options.binding.name,
1071
+ path: options.binding.path,
1072
+ semanticType: profile.type,
1073
+ editorShape: editor.document,
1074
+ ...options.validator ? { validatorHandle } : {},
1075
+ ...profile.codec ? { codecHandle } : {},
1076
+ metadata: environmentMetadata(document, profile, limits, editor, sourceEvidence),
1077
+ provenance: [schemanProvenance(document)]
1078
+ }
1079
+ ]
1080
+ });
1081
+ }
1082
+ function validateDocument(document) {
1083
+ if (document.formatVersion !== 1) return adapterFailure("SCHEMAN_ADAPTER_FORMAT_VERSION");
1084
+ if (!document.root?.input?.nodeId || !document.root?.output?.nodeId) {
1085
+ return adapterFailure("SCHEMAN_ADAPTER_INVALID_DOCUMENT");
1086
+ }
1087
+ if (!document.nodes[document.root.input.nodeId] || !document.nodes[document.root.output.nodeId]) {
1088
+ return adapterFailure("SCHEMAN_ADAPTER_UNRESOLVED_ROOT");
1089
+ }
1090
+ return void 0;
1091
+ }
1092
+ function configuredCapabilities(options, profile) {
1093
+ const capabilities = [];
1094
+ if (options.validator) capabilities.push(validatorCapability(options.validator));
1095
+ const codec = options.codec;
1096
+ if (codec) {
1097
+ capabilities.push({
1098
+ handle: codecHandle,
1099
+ kind: "codec",
1100
+ mode: codec.mode,
1101
+ capabilityId: codec.id,
1102
+ capabilityVersion: codec.capabilityVersion,
1103
+ configurationDigest: codec.configurationDigest,
1104
+ cacheable: codec.cacheable,
1105
+ convert: (value) => convertWithFinalPolicy(codec, profile.finalValidation, value)
1106
+ });
1107
+ }
1108
+ return capabilities;
1109
+ }
1110
+ function validatorCapability(config) {
1111
+ return {
1112
+ handle: validatorHandle,
1113
+ kind: "validator",
1114
+ mode: config.mode,
1115
+ capabilityId: config.capabilityId,
1116
+ capabilityVersion: config.capabilityVersion,
1117
+ configurationDigest: config.configurationDigest,
1118
+ cacheable: config.cacheable,
1119
+ decode: (value) => decodeStandardSchema(config.validator, value)
1120
+ };
1121
+ }
1122
+ function environmentMetadata(document, profile, limits, editor, sourceEvidence) {
1123
+ const sourceRetention = sourceRetentionMetadata(document, editor, sourceEvidence);
1124
+ return {
1125
+ scheman: {
1126
+ formatVersion: document.formatVersion,
1127
+ nodeIdScope: "document-local",
1128
+ roots: { input: document.root.input.nodeId, output: document.root.output.nodeId },
1129
+ capabilities: document.capabilities,
1130
+ definitions: sourceEvidence.definitions.values,
1131
+ diagnostics: sourceEvidence.diagnostics.values,
1132
+ metadata: document.metadata,
1133
+ bounded: {
1134
+ limits,
1135
+ retainedNodes: editor.retainedNodes,
1136
+ retainedEdges: editor.retainedEdges,
1137
+ nodes: {
1138
+ retained: editor.retainedNodes,
1139
+ total: Object.keys(document.nodes).length,
1140
+ truncated: editor.nodeTruncated
1141
+ },
1142
+ edges: editor.sourceEdges,
1143
+ requiredNames: editor.requiredNames,
1144
+ definitions: sourceEvidence.definitions.summary,
1145
+ diagnostics: sourceEvidence.diagnostics.summary,
1146
+ sourceRetention,
1147
+ hostAdmissionPlan: editor.admission,
1148
+ truncated: editor.nodeTruncated || editor.edgeTruncated || editor.requiredNames.truncated || sourceEvidence.definitions.summary.truncated || sourceEvidence.diagnostics.summary.truncated
1149
+ }
1150
+ },
1151
+ policy: profile
1152
+ };
1153
+ }
1154
+ function sourceRetentionMetadata(document, editor, sourceEvidence) {
1155
+ return {
1156
+ nodes: {
1157
+ retained: editor.retainedNodes,
1158
+ total: Object.keys(document.nodes).length,
1159
+ truncated: editor.nodeTruncated
1160
+ },
1161
+ edges: editor.sourceEdges,
1162
+ requiredNames: editor.requiredNames,
1163
+ definitions: sourceEvidence.definitions.summary,
1164
+ diagnostics: sourceEvidence.diagnostics.summary
1165
+ };
1166
+ }
1167
+ function schemanProvenance(document) {
1168
+ const metadata = document.metadata;
1169
+ return Object.freeze({
1170
+ providerId: "@scheman/core",
1171
+ providerVersion: "2.0.0",
1172
+ ...typeof metadata.provider === "string" ? { extractor: metadata.provider } : {}
1173
+ });
1174
+ }
1175
+ function sourceDiagnostics(diagnostics) {
1176
+ return diagnostics.map((diagnostic) => wrapSourceDiagnostic(diagnostic));
1177
+ }
1178
+ function boundedSourceEvidence(document, maximum) {
1179
+ return {
1180
+ definitions: boundedRecords(document.definitions, maximum),
1181
+ diagnostics: boundedRecords(document.diagnostics, maximum)
1182
+ };
1183
+ }
1184
+ function boundedRecords(values, maximum) {
1185
+ const retained = values.slice(0, maximum);
1186
+ return {
1187
+ values: retained,
1188
+ summary: {
1189
+ retained: retained.length,
1190
+ total: values.length,
1191
+ truncated: retained.length < values.length
1192
+ }
1193
+ };
1194
+ }
1195
+ function sourceLimitDiagnostics(evidence, editor) {
1196
+ const sourcePointer = limitSourcePointer(evidence, editor);
1197
+ if (!sourcePointer) return Object.freeze([]);
1198
+ const diagnostic = Object.freeze({
1199
+ code: "SCHEMAN_ADAPTER_ANALYSIS_LIMIT",
1200
+ severity: "warning",
1201
+ side: "output",
1202
+ sourcePointer
1203
+ });
1204
+ return Object.freeze([diagnostic]);
1205
+ }
1206
+ function limitSourcePointer(evidence, editor) {
1207
+ if (evidence.definitions.summary.truncated) return "/definitions";
1208
+ if (evidence.diagnostics.summary.truncated) return "/diagnostics";
1209
+ if (editor.requiredNames.truncated) return "/nodes/*/required";
1210
+ return void 0;
1211
+ }
1212
+ function wrapSourceDiagnostic(diagnostic) {
1213
+ return Object.freeze({
1214
+ code: diagnostic.code,
1215
+ severity: diagnostic.severity,
1216
+ side: diagnostic.side,
1217
+ sourcePointer: diagnostic.sourcePointer,
1218
+ ...diagnostic.nodeId ? { nodeId: diagnostic.nodeId } : {},
1219
+ provenance: Object.freeze({ providerId: "@scheman/core", formatVersion: "1" })
1220
+ });
1221
+ }
1222
+ function adapterFailure(code) {
1223
+ return Object.freeze({ code, severity: "error", side: "output", sourcePointer: "" });
1224
+ }
1225
+ function failure(diagnostic) {
1226
+ return Object.freeze({ ok: false, diagnostics: Object.freeze([diagnostic]) });
1227
+ }
1228
+
1229
+ // src/mapping-table.ts
1230
+ var SCHEMAN_SEMANTIC_MAPPING = Object.freeze([
1231
+ { scheman: "primitive:null|boolean|string", projection: "same primitive", condition: "always" },
1232
+ {
1233
+ scheman: "primitive:number|integer",
1234
+ projection: "number",
1235
+ condition: "always; constraints retained"
1236
+ },
1237
+ {
1238
+ scheman: "literal|enum",
1239
+ projection: "single primitive domain",
1240
+ condition: "all values share one supported domain"
1241
+ },
1242
+ { scheman: "array", projection: "array-type", condition: "item projection is concrete" },
1243
+ {
1244
+ scheman: "object|record|tuple",
1245
+ projection: "json",
1246
+ condition: "entire reachable graph is JSON-safe"
1247
+ },
1248
+ {
1249
+ scheman: "union|intersection",
1250
+ projection: "shared concrete type",
1251
+ condition: "every operand agrees"
1252
+ },
1253
+ { scheman: "ref", projection: "target projection", condition: "same-document target resolves" },
1254
+ {
1255
+ scheman: "wrapper:readonly|brand",
1256
+ projection: "inner projection",
1257
+ condition: "wrapper is non-transforming"
1258
+ },
1259
+ { scheman: "unconstrained:json", projection: "json", condition: "JSON domain is explicit" },
1260
+ {
1261
+ scheman: "unknown|opaque|never|unconstrained:js",
1262
+ projection: "dynamic",
1263
+ condition: "unless explicitly overridden"
1264
+ },
1265
+ {
1266
+ scheman: "primitive:undefined|void|bigint|symbol|date|NaN",
1267
+ projection: "dynamic",
1268
+ condition: "unless explicitly overridden"
1269
+ },
1270
+ {
1271
+ scheman: "wrapper:optional|nullable|default|catch|pipeline|effect|coerce",
1272
+ projection: "dynamic",
1273
+ condition: "unless explicitly overridden"
1274
+ }
1275
+ ]);
1276
+ var SCHEMAN_MAPPING_FIXTURE_MATRIX = Object.freeze([
1277
+ ["primitive-null", "null"],
1278
+ ["primitive-boolean", "boolean"],
1279
+ ["primitive-string", "string"],
1280
+ ["primitive-number", "number"],
1281
+ ["primitive-integer", "number"],
1282
+ ["literal-primitive", "primitive-domain"],
1283
+ ["enum-single-domain", "primitive-domain"],
1284
+ ["enum-mixed-domain", "dynamic"],
1285
+ ["array-concrete-item", "array-type"],
1286
+ ["array-dynamic-item", "dynamic"],
1287
+ ["json-safe-object-record-tuple", "json"],
1288
+ ["homogeneous-union-intersection", "shared-concrete"],
1289
+ ["heterogeneous-union", "dynamic"],
1290
+ ["resolved-local-ref", "target"],
1291
+ ["unresolved-or-external-ref", "dynamic"],
1292
+ ["readonly-or-brand-wrapper", "inner"],
1293
+ ["json-unconstrained", "json"],
1294
+ ["unknown-opaque-never-js-unconstrained", "dynamic"],
1295
+ ["undefined-void-bigint-symbol-date-nan", "dynamic"],
1296
+ ["optional-nullable-default-catch-effect-pipeline-coerce", "dynamic"],
1297
+ ["unsupported-applicator", "dynamic"]
1298
+ ]);
1299
+
1300
+ // src/index.ts
1301
+ var DENY_SCHEMAN_EXECUTION_PERMISSIONS = Object.freeze({
1302
+ zod: Object.freeze({ shape: false, lazy: false, metadata: false }),
1303
+ standardJson: false
1304
+ });
1305
+
1306
+ export { DEFAULT_SCHEMAN_ANALYSIS_LIMITS, DENY_SCHEMAN_EXECUTION_PERMISSIONS, SCHEMAN_MAPPING_FIXTURE_MATRIX, SCHEMAN_SEMANTIC_MAPPING, adaptSchemanDocument };
1307
+ //# sourceMappingURL=index.js.map
1308
+ //# sourceMappingURL=index.js.map