@astrale-os/kernel-dsl 1.0.0-beta.12 → 1.0.0-beta.13

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 (106) hide show
  1. package/dist/v1/addressing/definition-ref.js +21 -37
  2. package/dist/v1/addressing/ordering.d.ts +2 -0
  3. package/dist/v1/addressing/ordering.js +4 -0
  4. package/dist/v1/addressing/patterns.d.ts +0 -1
  5. package/dist/v1/addressing/patterns.js +0 -5
  6. package/dist/v1/builder/class/authoring.js +5 -28
  7. package/dist/v1/builder/lowering/schema/context.js +2 -4
  8. package/dist/v1/builder/lowering/value/path.js +2 -4
  9. package/dist/v1/builder/lowering/value/zod.js +1 -3
  10. package/dist/v1/builder/schema/define.d.ts +0 -1
  11. package/dist/v1/builder/schema/diagnostic.d.ts +2 -1
  12. package/dist/v1/builder/schema/diagnostic.js +5 -10
  13. package/dist/v1/builder/schema/projection.d.ts +1 -1
  14. package/dist/v1/builder/value/full-match.d.ts +0 -1
  15. package/dist/v1/builder/value/full-match.js +0 -1
  16. package/dist/v1/bundle/codec.js +2 -4
  17. package/dist/v1/bundle/diagnostic.js +3 -7
  18. package/dist/v1/bundle/structure.js +2 -4
  19. package/dist/v1/compiled/admission/diagnostic.d.ts +1 -1
  20. package/dist/v1/compiled/admission/diagnostic.js +1 -3
  21. package/dist/v1/compiled/admission/revision.d.ts +9 -1
  22. package/dist/v1/compiled/admission/revision.js +6 -3
  23. package/dist/v1/compiled/admission/semantics/class.d.ts +4 -1
  24. package/dist/v1/compiled/admission/semantics/class.js +4 -8
  25. package/dist/v1/compiled/admission/semantics/core.d.ts +1 -24
  26. package/dist/v1/compiled/admission/semantics/core.js +54 -34
  27. package/dist/v1/compiled/admission/semantics/edge.d.ts +2 -4
  28. package/dist/v1/compiled/admission/semantics/edge.js +6 -65
  29. package/dist/v1/compiled/admission/semantics/policy/callable.js +0 -2
  30. package/dist/v1/compiled/admission/semantics/policy/contracts.d.ts +5 -20
  31. package/dist/v1/compiled/admission/semantics/policy/contracts.js +8 -21
  32. package/dist/v1/compiled/admission/semantics/policy/parity.js +13 -22
  33. package/dist/v1/compiled/admission/semantics/policy/pattern.d.ts +4 -1
  34. package/dist/v1/compiled/admission/semantics/policy/pattern.js +4 -16
  35. package/dist/v1/compiled/admission/semantics/policy/typing.d.ts +2 -24
  36. package/dist/v1/compiled/admission/semantics/policy/typing.js +19 -201
  37. package/dist/v1/compiled/compiler/compile.js +6 -8
  38. package/dist/v1/compiled/diagnostic.js +2 -3
  39. package/dist/v1/compiled/loader/load.d.ts +3 -2
  40. package/dist/v1/compiled/loader/load.js +10 -44
  41. package/dist/v1/domain/create.js +3 -5
  42. package/dist/v1/domain/namespace/member-collection.js +4 -6
  43. package/dist/v1/domain/validation/create.d.ts +0 -1
  44. package/dist/v1/domain/validation/create.js +0 -35
  45. package/dist/v1/language/class/inheritance.d.ts +18 -0
  46. package/dist/v1/language/class/inheritance.js +73 -0
  47. package/dist/v1/language/class/property-values.js +2 -4
  48. package/dist/v1/language/core/facts.d.ts +72 -0
  49. package/dist/v1/language/core/facts.js +95 -0
  50. package/dist/v1/language/policy/analysis/branches.d.ts +8 -0
  51. package/dist/v1/language/policy/analysis/branches.js +2 -1
  52. package/dist/v1/language/policy/analysis/budgets.d.ts +13 -1
  53. package/dist/v1/language/policy/analysis/budgets.js +104 -0
  54. package/dist/v1/language/policy/analysis/typing.d.ts +48 -0
  55. package/dist/v1/language/policy/analysis/typing.js +338 -0
  56. package/dist/v1/language/validation/diagnostic.d.ts +14 -0
  57. package/dist/v1/language/validation/diagnostic.js +21 -0
  58. package/dist/v1/language/value/compile/fields.js +4 -8
  59. package/dist/v1/language/value/profile/rules.js +5 -7
  60. package/dist/v1/language/value/profile/validate.js +1 -10
  61. package/dist/v1/language/value/reference/recursion.js +2 -22
  62. package/dist/v1/language/value/syntax/pointer.d.ts +2 -0
  63. package/dist/v1/language/value/syntax/pointer.js +5 -2
  64. package/dist/v1/language/value/syntax/walk.d.ts +2 -0
  65. package/dist/v1/language/value/syntax/walk.js +19 -20
  66. package/dist/v1/schema/compatibility/diff.js +2 -4
  67. package/dist/v1/schema/compatibility/meaning/footprint.js +16 -50
  68. package/dist/v1/schema/compatibility/structure/requirements.js +26 -58
  69. package/dist/v1/schema/compatibility/walk.d.ts +17 -0
  70. package/dist/v1/schema/compatibility/walk.js +41 -0
  71. package/dist/v1/schema/diagnostic.js +3 -11
  72. package/dist/v1/schema/resolution/context.js +3 -5
  73. package/dist/v1/schema/validation/callable.js +3 -5
  74. package/dist/v1/schema/validation/class.js +10 -52
  75. package/dist/v1/schema/validation/core.js +65 -199
  76. package/dist/v1/schema/validation/domain.js +1 -10
  77. package/dist/v1/schema/validation/domain.structure.js +2 -4
  78. package/dist/v1/schema/validation/policy/budgets.js +5 -112
  79. package/dist/v1/schema/validation/policy/context.d.ts +5 -3
  80. package/dist/v1/schema/validation/policy/context.js +5 -3
  81. package/dist/v1/schema/validation/policy/objects.d.ts +1 -1
  82. package/dist/v1/schema/validation/policy/objects.js +6 -14
  83. package/dist/v1/schema/validation/policy/references.js +5 -6
  84. package/dist/v1/schema/validation/policy/typing.d.ts +3 -18
  85. package/dist/v1/schema/validation/policy/typing.js +22 -356
  86. package/dist/v1/schema/validation/policy/uses.d.ts +1 -1
  87. package/dist/v1/schema/validation/policy/uses.js +9 -22
  88. package/dist/v1/schema/validation/policy/validate.js +3 -2
  89. package/dist/v1/schema/validation/value-api.js +2 -2
  90. package/dist/v1/schema/validation/value.js +5 -7
  91. package/dist/v1/schema/validation/view.js +4 -8
  92. package/package.json +1 -1
  93. package/dist/v1/compiled/admission/semantics/cardinality.d.ts +0 -5
  94. package/dist/v1/compiled/admission/semantics/cardinality.js +0 -128
  95. package/dist/v1/compiled/admission/semantics/policy/equality.d.ts +0 -8
  96. package/dist/v1/compiled/admission/semantics/policy/equality.js +0 -27
  97. package/dist/v1/compiled/admission/semantics/policy/measure.d.ts +0 -9
  98. package/dist/v1/compiled/admission/semantics/policy/measure.js +0 -81
  99. package/dist/v1/compiled/admission/semantics/policy/variants.d.ts +0 -10
  100. package/dist/v1/compiled/admission/semantics/policy/variants.js +0 -65
  101. package/dist/v1/language/class/index.d.ts +0 -8
  102. package/dist/v1/language/class/index.js +0 -1
  103. package/dist/v1/language/core/index.d.ts +0 -2
  104. package/dist/v1/language/core/index.js +0 -1
  105. package/dist/v1/language/value/index.d.ts +0 -11
  106. package/dist/v1/language/value/index.js +0 -8
@@ -1,16 +1,19 @@
1
1
  import { Key } from '../../../addressing/index.js';
2
2
  import { isMethodExecutable } from '../../../language/callable/executable.js';
3
- import { coveringNodeUniqueTuples, nodeUniqueKeys } from '../../../language/class/unique.js';
3
+ import { coveringEdgeUniqueTuples, coveringNodeUniqueTuples, edgeUniqueKeys, nodeUniqueKeys, } from '../../../language/class/unique.js';
4
+ import { checkCoreEdgeSet, checkHeldKeys, coreEndpointsSatisfy, } from '../../../language/core/facts.js';
4
5
  import {} from '../../../language/core/model/core.js';
5
6
  import { policyObjectOrigin, policyObjectKey, projectedMemberClass, } from '../../../language/index.js';
6
7
  import { bindValueProgram } from '../../../language/value/compile/load.js';
7
8
  import { validateValueProgram } from '../../../language/value/evaluate/program.js';
9
+ import { escapePointerToken } from '../../../language/value/syntax/pointer.js';
8
10
  import {} from '../../model/schema.js';
9
11
  import { fail } from '../diagnostic.js';
10
- import { validateCoreEdgeSet } from './cardinality.js';
11
12
  import { isCompiledEdge, classSatisfiesAny, } from './context.js';
13
+ import { sameIncidentEndpoint } from './edge.js';
12
14
  /** Admit local Core Nodes, Properties and Edge endpoint contracts. */
13
15
  export function validateCore(candidate, context) {
16
+ const resolve = (ref) => context.classes.get(Key.of(ref))?.value;
14
17
  for (const [entryIndex, entry] of candidate.closure.entries()) {
15
18
  const nodes = new Map();
16
19
  for (const [index, value] of entry.definitions.core.entries()) {
@@ -32,7 +35,9 @@ export function validateCore(candidate, context) {
32
35
  pointer: path,
33
36
  });
34
37
  }
35
- validateCoreNodeKeys(context, nodes);
38
+ checkHeldKeys(nodes.values(), (node) => nodeUniqueKeys(coveringNodeUniqueTuples(node.class.value, resolve), {
39
+ props: node.value.properties,
40
+ }), (node) => fail(node.pointer, 'Core Node holds a key another Core Node holds.'));
36
41
  const edges = [];
37
42
  for (const [index, value] of entry.facts.core.entries()) {
38
43
  const path = `/closure/${entryIndex}/facts/core/${index}`;
@@ -48,14 +53,7 @@ export function validateCore(candidate, context) {
48
53
  validateCoreProperties(value.properties, analysis, `${path}/properties`);
49
54
  const source = resolveCoreEndpoint(context, entry, value.source, nodes, `${path}/source`);
50
55
  const target = resolveCoreEndpoint(context, entry, value.target, nodes, `${path}/target`);
51
- const declaration = classValue.value;
52
- const satisfies = declaration.orientation === 'directed'
53
- ? endpointSatisfies(context, source, declaration.endpoints.source.accepts) &&
54
- endpointSatisfies(context, target, declaration.endpoints.target.accepts)
55
- : (endpointSatisfies(context, source, declaration.endpoints[0].accepts) &&
56
- endpointSatisfies(context, target, declaration.endpoints[1].accepts)) ||
57
- (endpointSatisfies(context, source, declaration.endpoints[1].accepts) &&
58
- endpointSatisfies(context, target, declaration.endpoints[0].accepts));
56
+ const satisfies = coreEndpointsSatisfy(classValue.value, source, target, (endpoint, accepts) => endpointSatisfies(context, endpoint, accepts));
59
57
  if (!satisfies)
60
58
  fail(path, 'Core Edge endpoints do not satisfy its exact Class.');
61
59
  edges.push({
@@ -66,37 +64,61 @@ export function validateCore(candidate, context) {
66
64
  pointer: path,
67
65
  });
68
66
  }
69
- validateCoreEdgeSet(context, entry, entryIndex, nodes, edges);
67
+ checkCoreEdgeSet({
68
+ edges: edges.map((edge) => ({
69
+ edge,
70
+ class: Key.of(edge.value.class),
71
+ contract: edge.class.value,
72
+ source: edge.source,
73
+ target: edge.target,
74
+ })),
75
+ classes: entry.definitions.classes
76
+ .filter(isCompiledEdge)
77
+ .map((value) => ({ key: Key.of(value.ref), contract: value })),
78
+ nodes: [...nodes.values()].map(({ key, value, pointer }) => ({
79
+ key,
80
+ class: value.class,
81
+ pointer,
82
+ })),
83
+ satisfies: (ref, accepts) => classSatisfiesAny(context, ref, accepts),
84
+ keys: ({ edge }) => edgeUniqueKeys(coveringEdgeUniqueTuples(edge.class.value, resolve), {
85
+ source: edge.source.key,
86
+ target: edge.target.key,
87
+ props: edge.value.properties,
88
+ }),
89
+ sameIncident: sameIncidentEndpoint,
90
+ report: (issue) => coreEdgeFailure(issue, entryIndex),
91
+ });
70
92
  }
71
93
  }
72
- /** No two Core Nodes hold one key under a tuple covering their Classes (DV-NODE-UNIQUE). */
73
- function validateCoreNodeKeys(context, nodes) {
74
- const resolve = (ref) => context.classes.get(Key.of(ref))?.value;
75
- const holders = new Set();
76
- for (const node of nodes.values()) {
77
- const keys = nodeUniqueKeys(coveringNodeUniqueTuples(node.class.value, resolve), {
78
- props: node.value.properties,
79
- });
80
- if (keys.some((key) => holders.has(key)))
81
- fail(node.pointer, 'Core Node holds a key another Core Node holds.');
82
- for (const key of keys)
83
- holders.add(key);
94
+ function coreEdgeFailure(issue, entryIndex) {
95
+ switch (issue.kind) {
96
+ case 'identity':
97
+ return fail(issue.edge.pointer, 'Core Edge duplicates an exact normalized Edge identity.');
98
+ case 'no-self':
99
+ return fail(issue.edge.pointer, 'Core Edge violates noSelf.');
100
+ case 'key':
101
+ return fail(issue.edge.pointer, 'Core Edge holds a key another Core Edge holds.');
102
+ case 'acyclic':
103
+ return fail(`/closure/${entryIndex}/facts/core`, 'Core Edge set violates exact-Class acyclicity.');
104
+ case 'degree':
105
+ return fail(issue.pointer, `Core degree ${issue.degree} violates Edge count ${issue.count}.`);
84
106
  }
85
107
  }
86
108
  function validateCoreProperties(values, analysis, path) {
87
109
  for (const key of Object.keys(values))
88
110
  if (!analysis.properties.has(key))
89
- fail(`${path}/${escapePointer(key)}`, 'Core properties contain an unknown Property key.');
111
+ fail(`${path}/${escapePointerToken(key)}`, 'Core properties contain an unknown Property key.');
90
112
  for (const property of analysis.properties.values()) {
91
113
  if (!Object.hasOwn(values, property.key)) {
92
114
  if (property.declaration.required && property.declaration.auto === undefined)
93
- fail(`${path}/${escapePointer(property.key)}`, 'Core properties omit a required Property.');
115
+ fail(`${path}/${escapePointerToken(property.key)}`, 'Core properties omit a required Property.');
94
116
  continue;
95
117
  }
96
118
  if (property.declaration.auto !== undefined)
97
- fail(`${path}/${escapePointer(property.key)}`, 'Core properties cannot author an automatic Property.');
119
+ fail(`${path}/${escapePointerToken(property.key)}`, 'Core properties cannot author an automatic Property.');
98
120
  if (validateValueProgram(bindValueProgram(property.entry.values[property.declaration.value], property.entry.patterns), values[property.key]).length > 0)
99
- fail(`${path}/${escapePointer(property.key)}`, 'Core Property value does not satisfy its exact contract.');
121
+ fail(`${path}/${escapePointerToken(property.key)}`, 'Core Property value does not satisfy its exact contract.');
100
122
  }
101
123
  }
102
124
  function resolveCoreEndpoint(context, entry, ref, nodes, path) {
@@ -109,7 +131,8 @@ function resolveCoreEndpoint(context, entry, ref, nodes, path) {
109
131
  return nodes.get(Key.of(ref)) ?? undeclared();
110
132
  if (!declaresProjectedMember(context, entry, ref))
111
133
  return undeclared();
112
- return { key: policyObjectKey(ref), class: projectedMemberClass(ref), pointer: path };
134
+ // A projected member's degree is reported at the endpoint that names it.
135
+ return { key: policyObjectKey(ref), member: { class: projectedMemberClass(ref), pointer: path } };
113
136
  }
114
137
  /** Only a projected declaration can carry a Core fact; an abstract Method is never projected. */
115
138
  function declaresProjectedMember(context, entry, ref) {
@@ -130,10 +153,7 @@ function declaresProjectedMember(context, entry, ref) {
130
153
  function endpointSatisfies(context, endpoint, accepts) {
131
154
  if ('value' in endpoint)
132
155
  return classSatisfiesAny(context, endpoint.value.class, accepts);
133
- if ('class' in endpoint)
134
- return classSatisfiesAny(context, endpoint.class, accepts);
156
+ if ('member' in endpoint)
157
+ return classSatisfiesAny(context, endpoint.member.class, accepts);
135
158
  return true;
136
159
  }
137
- function escapePointer(value) {
138
- return value.replaceAll('~', '~0').replaceAll('/', '~1');
139
- }
@@ -1,8 +1,6 @@
1
- import { type EdgeCount, type IncidentEndpoint } from '../../../language/class/model/edge.js';
1
+ import { type IncidentEndpoint } from '../../../language/class/model/edge.js';
2
2
  import { type SemanticIndex } from './context.js';
3
- /** Check Edge endpoint contracts and safe inheritance refinement. */
3
+ /** Check safe Edge inheritance refinement; the wire and closure checks own the endpoints. */
4
4
  export declare function validateEdges(context: SemanticIndex): void;
5
5
  /** Compare undirected endpoint acceptance and cardinality contracts. */
6
6
  export declare function sameIncidentEndpoint(left: IncidentEndpoint, right: IncidentEndpoint): boolean;
7
- /** Interpret an Edge count as inclusive degree bounds. */
8
- export declare function countBounds(value: EdgeCount): readonly [number, number];
@@ -1,71 +1,25 @@
1
1
  import { Key } from '../../../addressing/index.js';
2
2
  import { compareUnicode } from '../../../addressing/ordering.js';
3
- import { isGraphRoot } from '../../../language/class/inheritance.js';
3
+ import { edgeContractRefines } from '../../../language/class/inheritance.js';
4
4
  import {} from '../../../language/class/model/edge.js';
5
5
  import { fail } from '../diagnostic.js';
6
- import { isCompiledEdge, classSatisfiesAny, } from './context.js';
7
- /** Check Edge endpoint contracts and safe inheritance refinement. */
6
+ import { isCompiledEdge, classSatisfiesAny } from './context.js';
7
+ /** Check safe Edge inheritance refinement; the wire and closure checks own the endpoints. */
8
8
  export function validateEdges(context) {
9
9
  for (const located of context.classes.values()) {
10
10
  if (!isCompiledEdge(located.value))
11
11
  continue;
12
12
  const edge = located.value;
13
- const endpoints = edge.orientation === 'directed'
14
- ? [edge.endpoints.source, edge.endpoints.target]
15
- : edge.endpoints;
16
- if (endpoints[0].role === endpoints[1].role)
17
- fail(`${located.pointer}/endpoints`, 'Edge endpoint roles must differ.');
18
- for (const [endpointIndex, endpoint] of endpoints.entries()) {
19
- const seen = new Set();
20
- for (const [acceptIndex, ref] of endpoint.accepts.entries()) {
21
- const key = Key.of(ref);
22
- if (seen.has(key))
23
- fail(`${located.pointer}/endpoints/${endpointIndex}/accepts/${acceptIndex}`, 'Edge endpoint repeats an accepted Class.');
24
- seen.add(key);
25
- if (context.classes.get(key)?.value.kind !== 'node')
26
- fail(`${located.pointer}/endpoints/${endpointIndex}/accepts/${acceptIndex}`, 'Edge endpoint must accept a Node Class.');
27
- }
28
- }
29
13
  for (const [parentIndex, parentRef] of edge.extends.entries()) {
30
14
  const parent = context.classes.get(Key.of(parentRef))?.value;
31
- if (parent !== undefined && isCompiledEdge(parent) && !edgeRefines(context, edge, parent)) {
15
+ if (parent !== undefined &&
16
+ isCompiledEdge(parent) &&
17
+ !edgeContractRefines(edge, parent, (candidate, accepts) => classSatisfiesAny(context, candidate, accepts))) {
32
18
  fail(`${located.pointer}/extends/${parentIndex}`, 'Edge Class does not safely refine its parent.');
33
19
  }
34
20
  }
35
21
  }
36
22
  }
37
- function edgeRefines(context, child, parent) {
38
- if (isGraphRoot(parent))
39
- return true;
40
- if (child.orientation !== parent.orientation)
41
- return false;
42
- if (parent.constraints.noSelf === true && child.constraints.noSelf !== true)
43
- return false;
44
- if (parent.constraints.acyclic === true && child.constraints.acyclic !== true)
45
- return false;
46
- if (child.orientation === 'directed' && parent.orientation === 'directed') {
47
- return (endpointRefines(context, child.endpoints.source, parent.endpoints.source) &&
48
- countRefines(child.endpoints.source.outgoing, parent.endpoints.source.outgoing) &&
49
- endpointRefines(context, child.endpoints.target, parent.endpoints.target) &&
50
- countRefines(child.endpoints.target.incoming, parent.endpoints.target.incoming));
51
- }
52
- if (child.orientation !== 'undirected' || parent.orientation !== 'undirected')
53
- return false;
54
- const refine = (a, b) => endpointRefines(context, child.endpoints[a], parent.endpoints[b]) &&
55
- countRefines(child.endpoints[a].incident, parent.endpoints[b].incident);
56
- const direct = refine(0, 0) && refine(1, 1);
57
- if (direct)
58
- return true;
59
- return refine(0, 1) && refine(1, 0);
60
- }
61
- function endpointRefines(context, child, parent) {
62
- return child.accepts.every((accepted) => classSatisfiesAny(context, accepted, parent.accepts));
63
- }
64
- function countRefines(child, parent) {
65
- const [childMin, childMax] = countBounds(child);
66
- const [parentMin, parentMax] = countBounds(parent);
67
- return childMin >= parentMin && childMax <= parentMax;
68
- }
69
23
  /** Compare undirected endpoint acceptance and cardinality contracts. */
70
24
  export function sameIncidentEndpoint(left, right) {
71
25
  const a = left.accepts.map(Key.of).sort(compareUnicode);
@@ -74,16 +28,3 @@ export function sameIncidentEndpoint(left, right) {
74
28
  a.length === b.length &&
75
29
  a.every((value, index) => value === b[index]));
76
30
  }
77
- /** Interpret an Edge count as inclusive degree bounds. */
78
- export function countBounds(value) {
79
- switch (value) {
80
- case '0..*':
81
- return [0, Number.POSITIVE_INFINITY];
82
- case '1..*':
83
- return [1, Number.POSITIVE_INFINITY];
84
- case '0..1':
85
- return [0, 1];
86
- case '1':
87
- return [1, 1];
88
- }
89
- }
@@ -28,8 +28,6 @@ export function validateCallablePolicy(context, entry, expression, inputIndex, f
28
28
  return;
29
29
  }
30
30
  const children = 'allOf' in expression ? expression.allOf : expression.anyOf;
31
- if (children.length === 0)
32
- fail(path, 'Callable Policy composition must be non-empty.');
33
31
  children.forEach((child, index) => validateCallablePolicy(context, entry, child, inputIndex, fields, instanceMethod, `${path}/${index}`));
34
32
  }
35
33
  function isSingleNodePathField(context, entry, inputIndex, field) {
@@ -1,24 +1,9 @@
1
- import type { PolicyCheckObject } from '../../../../language/policy/model/policy.js';
1
+ import type { ObjectContract } from '../../../../language/policy/analysis/typing.js';
2
2
  import { type ClassRef } from '../../../../addressing/index.js';
3
+ import { type PolicyCheckObject, type PolicyObjectRef } from '../../../../language/policy/model/policy.js';
3
4
  import { type CompiledSchemaEntry } from '../../../model/schema.js';
4
5
  import { type SemanticIndex } from '../context.js';
5
- /** The default protected object contract or one exact Class. */
6
- export type CompiledObjectContract = {
7
- readonly kind: 'default';
8
- } | {
9
- readonly kind: 'exact';
10
- readonly ref: ClassRef;
11
- };
12
- /** The protected object or endpoint contracts of one Policy use. */
13
- export type CompiledPolicyUse = {
14
- readonly kind: 'object';
15
- readonly object: CompiledObjectContract;
16
- } | {
17
- readonly kind: 'edge';
18
- readonly source: CompiledObjectContract;
19
- readonly target: CompiledObjectContract;
20
- };
21
6
  /** Resolve callable Policy objects to their protected Class contracts. */
22
- export declare function callableObjectContracts(context: SemanticIndex, entry: CompiledSchemaEntry, input: number, receiver: ClassRef | undefined, object: PolicyCheckObject): readonly CompiledObjectContract[] | undefined;
23
- /** Select the protected contract for an object or Edge endpoint term. */
24
- export declare function compiledTargetContract(term: string, use: CompiledPolicyUse): CompiledObjectContract | undefined;
7
+ export declare function callableObjectContracts(context: SemanticIndex, entry: CompiledSchemaEntry, input: number, receiver: ClassRef | undefined, object: PolicyCheckObject): readonly ObjectContract[] | undefined;
8
+ /** Resolve a referenced Policy object to its protected Class contract. */
9
+ export declare function referenceContract(context: SemanticIndex, ref: PolicyObjectRef): ObjectContract | undefined;
@@ -1,4 +1,5 @@
1
1
  import { Key } from '../../../../addressing/index.js';
2
+ import { projectedMemberClass, } from '../../../../language/policy/model/policy.js';
2
3
  import {} from '../../../model/schema.js';
3
4
  import {} from '../context.js';
4
5
  /** Resolve callable Policy objects to their protected Class contracts. */
@@ -9,24 +10,16 @@ export function callableObjectContracts(context, entry, input, receiver, object)
9
10
  if (object.kind === 'input') {
10
11
  return nodePathAccepts(entry, input, object.field).map((ref) => ({ kind: 'exact', ref }));
11
12
  }
12
- const ref = object.ref;
13
+ const contract = referenceContract(context, object.ref);
14
+ return contract === undefined ? undefined : [contract];
15
+ }
16
+ /** Resolve a referenced Policy object to its protected Class contract. */
17
+ export function referenceContract(context, ref) {
13
18
  if (ref.kind === 'core') {
14
19
  const node = context.core.get(Key.of(ref))?.value;
15
- return node === undefined ? undefined : [{ kind: 'exact', ref: node.class }];
20
+ return node === undefined ? undefined : { kind: 'exact', ref: node.class };
16
21
  }
17
- const projection = ref.kind === 'class'
18
- ? 'Class'
19
- : ref.kind === 'function' || ref.kind === 'method'
20
- ? 'Function'
21
- : ref.kind === 'policy'
22
- ? 'Policy'
23
- : 'View';
24
- return [
25
- {
26
- kind: 'exact',
27
- ref: { origin: 'kernel.astrale.ai', kind: 'class', name: projection },
28
- },
29
- ];
22
+ return { kind: 'exact', ref: projectedMemberClass(ref) };
30
23
  }
31
24
  function nodePathAccepts(entry, input, field) {
32
25
  const root = entry.values[input]?.nodes[entry.values[input].root]?.schema;
@@ -37,9 +30,3 @@ function nodePathAccepts(entry, input, field) {
37
30
  ? annotation.accepts
38
31
  : [];
39
32
  }
40
- /** Select the protected contract for an object or Edge endpoint term. */
41
- export function compiledTargetContract(term, use) {
42
- if (use.kind === 'object')
43
- return term === 'object' ? use.object : undefined;
44
- return term === 'source' ? use.source : term === 'target' ? use.target : undefined;
45
- }
@@ -1,20 +1,20 @@
1
- import { Key } from '../../../../addressing/index.js';
2
- import {} from '../../../../language/class/model/edge.js';
1
+ import {} from '../../../../addressing/index.js';
3
2
  import { branchesOf, targetMode, isConnected, } from '../../../../language/policy/analysis/branches.js';
4
- import { MAX_PATTERN_DEPTH, MAX_BRANCHES, MAX_EDGES, MAX_DOMAINS, measureChecks, MAX_CHECK_DEPTH, MAX_CHECK_LEAVES, } from '../../../../language/policy/analysis/budgets.js';
5
- import { admittedCheckClasses, neverAdmittedClasses, } from '../../../../language/policy/analysis/checks.js';
3
+ import { MAX_PATTERN_DEPTH, MAX_BRANCHES, MAX_EDGES, MAX_DOMAINS, measureChecks, MAX_CHECK_DEPTH, MAX_CHECK_LEAVES, policyMeasurer, } from '../../../../language/policy/analysis/budgets.js';
4
+ import { neverAdmittedClasses, } from '../../../../language/policy/analysis/checks.js';
5
+ import {} from '../../../../language/policy/analysis/typing.js';
6
6
  import { checksNameTheCaller, isClassRuleChecks, } from '../../../../language/policy/model/policy.js';
7
7
  import { normalizePolicyExpression } from '../../../../language/policy/normalization/normalize.js';
8
8
  import {} from '../../../model/schema.js';
9
9
  import { fail } from '../../diagnostic.js';
10
10
  import { isCompiledEdge } from '../context.js';
11
11
  import { callableObjectContracts } from './contracts.js';
12
- import { measureCompiledPolicy } from './measure.js';
13
- import { CompiledPolicyTyping } from './typing.js';
12
+ import { compiledPolicyTyping } from './typing.js';
14
13
  /** Check Policy typing and expansion budgets against the entry’s own closure. */
15
14
  export function validatePolicyParity(context, entry, entryIndex, policies, origins) {
16
15
  const normalized = new Map([...policies].map(([name, policy]) => [name, normalizePolicyExpression(policy.expression)]));
17
- const typing = new CompiledPolicyTyping(context, entry, normalized, origins);
16
+ const typing = compiledPolicyTyping(context, entry, normalized, origins);
17
+ const measurePolicy = policyMeasurer(entry.origin, normalized, (ref) => ref.origin === entry.origin);
18
18
  for (const [name, declaration] of policies) {
19
19
  const path = `/closure/${entryIndex}/definitions/policies/${declarationIndex(entry, 'policies', name)}`;
20
20
  if ('match' in declaration.expression) {
@@ -27,7 +27,7 @@ export function validatePolicyParity(context, entry, entryIndex, policies, origi
27
27
  }
28
28
  }
29
29
  }
30
- const measure = measureCompiledPolicy(entry.origin, name, normalized, new Set());
30
+ const measure = measurePolicy(name);
31
31
  if (measure !== undefined &&
32
32
  (measure.depth > MAX_PATTERN_DEPTH ||
33
33
  measure.edgeCounts.length > MAX_BRANCHES ||
@@ -35,7 +35,7 @@ export function validatePolicyParity(context, entry, entryIndex, policies, origi
35
35
  measure.domains.size > MAX_DOMAINS)) {
36
36
  fail(path, 'Policy expansion exceeds the V1 depth, branch, Edge, or Domain budget.');
37
37
  }
38
- const branches = typing.expandedBranches(name, new Set(), `$${name}`);
38
+ const branches = typing.expandedBranches(name, `$${name}`);
39
39
  if (branches !== undefined) {
40
40
  for (const branch of branches) {
41
41
  const mode = targetMode(branch);
@@ -67,12 +67,7 @@ export function validatePolicyParity(context, entry, entryIndex, policies, origi
67
67
  }
68
68
  }
69
69
  else if (isCompiledEdge(definition)) {
70
- const endpoints = definition.orientation === 'directed'
71
- ? [definition.endpoints.source, definition.endpoints.target]
72
- : definition.endpoints;
73
- const sources = typing.concreteEndpointClasses(endpoints[0].accepts);
74
- const targets = typing.concreteEndpointClasses(endpoints[1].accepts);
75
- if (sources.some((source) => targets.some((target) => !typing.policyAcceptsEdge(policy.name, { kind: 'exact', ref: source }, { kind: 'exact', ref: target })))) {
70
+ if (!typing.policyAcceptsEdgeClass(policy.name, definition)) {
76
71
  fail(path, `${label} Policy is incompatible with an accepted Edge endpoint pair.`);
77
72
  }
78
73
  }
@@ -121,15 +116,11 @@ function validatePolicyChecks(context, typing, entry, expression, input, receive
121
116
  const contracts = callableObjectContracts(context, entry, input, receiver, value.object);
122
117
  if (contracts === undefined)
123
118
  return;
124
- const typings = new Map(contracts.map((contract) => [
125
- contract.kind === 'exact' ? Key.of(contract.ref) : 'default',
126
- typing.policyBranchTyping(value.check.name, contract),
127
- ]));
128
- const admitted = admittedCheckClasses(typings);
129
- if (admitted === undefined) {
119
+ const classes = typing.checkLeafClasses(value.check.name, contracts);
120
+ if (classes === undefined) {
130
121
  fail(pointer, `Named Policy is incompatible with ${SITE[site].objects}.`);
131
122
  }
132
- leaves.set(value, { accepted: [...typings.keys()], admitted });
123
+ leaves.set(value, classes);
133
124
  };
134
125
  visit(expression, path);
135
126
  const [never] = neverAdmittedClasses(expression, leaves);
@@ -2,7 +2,10 @@ import { type MethodAddress } from '../../../../addressing/index.js';
2
2
  import { type PolicyExpression } from '../../../../language/policy/model/policy.js';
3
3
  import { type CompiledSchemaEntry } from '../../../model/schema.js';
4
4
  import { type SemanticIndex, type CompiledPolicy } from '../context.js';
5
- /** Check named Policy composition and scoped pattern references. */
5
+ /**
6
+ * Check named Policy composition and scoped pattern references. The wire grammar already bounds
7
+ * repeats and variables and refuses empty compositions.
8
+ */
6
9
  export declare function validatePolicyExpression(context: SemanticIndex, entry: CompiledSchemaEntry, expression: PolicyExpression, path: string, local: ReadonlyMap<string, CompiledPolicy>): void;
7
10
  /** Require an exact executable Method declaration for a Policy reference. */
8
11
  export declare function validatePolicyMethod(context: SemanticIndex, ref: MethodAddress, path: string): void;
@@ -1,20 +1,20 @@
1
1
  import { Key } from '../../../../addressing/index.js';
2
2
  import { isMethodExecutable } from '../../../../language/callable/executable.js';
3
3
  import { policyVariableClass } from '../../../../language/index.js';
4
- import { MAX_REPEAT, MAX_VARIABLES } from '../../../../language/policy/analysis/budgets.js';
5
4
  import {} from '../../../../language/policy/model/policy.js';
6
5
  import {} from '../../../model/schema.js';
7
6
  import { fail } from '../../diagnostic.js';
8
7
  import {} from '../context.js';
9
- /** Check named Policy composition and scoped pattern references. */
8
+ /**
9
+ * Check named Policy composition and scoped pattern references. The wire grammar already bounds
10
+ * repeats and variables and refuses empty compositions.
11
+ */
10
12
  export function validatePolicyExpression(context, entry, expression, path, local) {
11
13
  if ('match' in expression) {
12
14
  validatePattern(context, expression.match, `${path}/match`, new Set(), new Set());
13
15
  return;
14
16
  }
15
17
  const values = 'allOf' in expression ? expression.allOf : expression.anyOf;
16
- if (values.length === 0)
17
- fail(path, 'Named Policy composition must be non-empty.');
18
18
  for (const [index, ref] of values.entries()) {
19
19
  if (ref.origin !== entry.origin || ref.kind !== 'policy' || !local.has(ref.name))
20
20
  fail(`${path}/${index}`, 'Named Policy composition must reference a local Policy.');
@@ -31,19 +31,9 @@ function validatePattern(context, expression, path, scope, declared) {
31
31
  fail(`${path}/class`, 'Policy pattern Class must resolve to an Edge Class.');
32
32
  validatePolicyTerm(context, expression.source, `${path}/source`, scope);
33
33
  validatePolicyTerm(context, expression.target, `${path}/target`, scope);
34
- if (expression.repeat !== undefined &&
35
- (!Number.isInteger(expression.repeat.min) ||
36
- !Number.isInteger(expression.repeat.max) ||
37
- expression.repeat.min < 0 ||
38
- expression.repeat.max < expression.repeat.min ||
39
- expression.repeat.max > MAX_REPEAT))
40
- fail(`${path}/repeat`, 'Policy repeat is outside the V1 bounds.');
41
34
  return;
42
35
  }
43
36
  if ('exists' in expression) {
44
- if (expression.exists.nodes.length > MAX_VARIABLES) {
45
- fail(`${path}/exists/nodes`, 'Policy exists exceeds the V1 variable budget.');
46
- }
47
37
  const nested = new Set(scope);
48
38
  for (const [index, node] of expression.exists.nodes.entries()) {
49
39
  const id = node.variable.id;
@@ -59,8 +49,6 @@ function validatePattern(context, expression, path, scope, declared) {
59
49
  return;
60
50
  }
61
51
  const values = 'allOf' in expression ? expression.allOf : expression.anyOf;
62
- if (values.length === 0)
63
- fail(path, 'Policy pattern composition must be non-empty.');
64
52
  values.forEach((value, index) => validatePattern(context, value, `${path}/${index}`, scope, declared));
65
53
  }
66
54
  function validatePolicyTerm(context, term, path, scope) {
@@ -1,28 +1,6 @@
1
- import { type ClassRef } from '../../../../addressing/index.js';
2
- import { type PatternBranch } from '../../../../language/policy/analysis/branches.js';
1
+ import { PolicyTyping } from '../../../../language/policy/analysis/typing.js';
3
2
  import { type PolicyExpression } from '../../../../language/policy/model/policy.js';
4
3
  import { type CompiledSchemaEntry } from '../../../model/schema.js';
5
4
  import { type SemanticIndex } from '../context.js';
6
- import { type CompiledObjectContract, type CompiledPolicyUse } from './contracts.js';
7
5
  /** Types one entry's Policies against the Node Classes of its own closure, as source admission. */
8
- export declare class CompiledPolicyTyping {
9
- readonly context: SemanticIndex;
10
- readonly entry: CompiledSchemaEntry;
11
- readonly normalized: ReadonlyMap<string, PolicyExpression>;
12
- readonly allNodeClasses: readonly ClassRef[];
13
- readonly concreteNodeClasses: readonly ClassRef[];
14
- constructor(context: SemanticIndex, entry: CompiledSchemaEntry, normalized: ReadonlyMap<string, PolicyExpression>, origins: ReadonlySet<string>);
15
- expandedBranches(name: string, visiting: Set<string>, namespace: string): readonly PatternBranch[] | undefined;
16
- policyAccepts(name: string, object: CompiledObjectContract): boolean;
17
- policyBranchTyping(name: string, object: CompiledObjectContract): readonly boolean[] | undefined;
18
- policyAcceptsEdge(name: string, source: CompiledObjectContract, target: CompiledObjectContract): boolean;
19
- concreteEndpointClasses(accepts: readonly ClassRef[]): readonly ClassRef[];
20
- endpointsOverlap(left: readonly ClassRef[], right: readonly ClassRef[]): boolean;
21
- branchIsTyped(branch: PatternBranch, use: CompiledPolicyUse): boolean;
22
- private constraintsSatisfiable;
23
- private applyInitial;
24
- private applyExact;
25
- private applyAnyNodeClass;
26
- private applyRequirement;
27
- private applyEndpoint;
28
- }
6
+ export declare function compiledPolicyTyping(context: SemanticIndex, entry: CompiledSchemaEntry, normalized: ReadonlyMap<string, PolicyExpression>, origins: ReadonlySet<string>): PolicyTyping;