@astrale-os/kernel-dsl 0.2.0-beta.28 → 0.2.0-beta.29

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.
@@ -43,6 +43,7 @@ export interface NodeClassInput {
43
43
  readonly data?: MediaType;
44
44
  readonly methods?: Readonly<Record<string, Method>>;
45
45
  readonly icon?: string;
46
+ /** Local observation Policies; inherited by no descendant and forbidden on abstract Classes. */
46
47
  readonly policies?: {
47
48
  readonly read?: Lazy<Policy>;
48
49
  readonly traverse?: Lazy<Policy>;
@@ -53,6 +54,7 @@ export interface EdgeClassOptions {
53
54
  readonly description?: string;
54
55
  readonly extends?: readonly EdgeClassReferenceInput[];
55
56
  readonly properties?: PropertyRecordInput;
57
+ /** Local observation Policies; inherited by no descendant and forbidden on abstract Classes. */
56
58
  readonly policies?: {
57
59
  readonly read?: Lazy<Policy>;
58
60
  readonly traverse?: Lazy<Policy>;
@@ -178,6 +178,10 @@ function policyKey(value) {
178
178
  }
179
179
  function validateClassFacets(context) {
180
180
  for (const located of context.classes.values()) {
181
+ if (located.value.abstract &&
182
+ (located.value.policies.read !== undefined || located.value.policies.traverse !== undefined)) {
183
+ fail(`${located.pointer}/policies`, 'Abstract Classes cannot declare observation Policies.');
184
+ }
181
185
  for (const [index, property] of located.value.properties.entries()) {
182
186
  const path = `${located.pointer}/properties/${index}`;
183
187
  if (property.auto !== undefined) {
@@ -252,26 +256,7 @@ function edgeRefines(context, child, parent) {
252
256
  const direct = refine(0, 0) && refine(1, 1);
253
257
  if (direct)
254
258
  return true;
255
- const reverse = refine(0, 1) && refine(1, 0);
256
- return reverse && !hasEffectiveEdgePolicy(context, parent, new Set());
257
- }
258
- function hasEffectiveEdgePolicy(context, declaration, visited) {
259
- if (declaration.policies.read !== undefined || declaration.policies.traverse !== undefined) {
260
- return true;
261
- }
262
- for (const parentRef of declaration.extends) {
263
- const key = Key.of(parentRef);
264
- if (visited.has(key))
265
- continue;
266
- visited.add(key);
267
- const parent = context.classes.get(key)?.value;
268
- if (parent !== undefined &&
269
- isCompiledEdge(parent) &&
270
- hasEffectiveEdgePolicy(context, parent, visited)) {
271
- return true;
272
- }
273
- }
274
- return false;
259
+ return refine(0, 1) && refine(1, 0);
275
260
  }
276
261
  function endpointRefines(context, child, parent) {
277
262
  return child.accepts.every((accepted) => classSatisfiesAny(context, accepted, parent.accepts));
@@ -1,4 +1,4 @@
1
- import { compareUnicode, Key, MethodKey as MethodKeyValue, PropertyKey as PropertyKeyValue, } from '../../addressing/index.js';
1
+ import { Key, MethodKey as MethodKeyValue, PropertyKey as PropertyKeyValue, } from '../../addressing/index.js';
2
2
  import { acceptPropertyValues } from '../../language/class/property-values.js';
3
3
  import { appendPointer } from '../../language/value/syntax/pointer.js';
4
4
  import { createMethodCollection, createPropertyCollection } from '../namespace/member-collection.js';
@@ -24,16 +24,6 @@ export function createClasses(definitions, validation) {
24
24
  throw new TypeError(`Class ${key} extends a Class of another graph kind.`);
25
25
  }
26
26
  const shell = {};
27
- const policies = Object.freeze({
28
- read: Object.freeze(uniquePolicyRefs([
29
- ...parents.flatMap((parent) => [...parent.policies.read]),
30
- ...(definition.policies.read === undefined ? [] : [definition.policies.read]),
31
- ])),
32
- traverse: Object.freeze(uniquePolicyRefs([
33
- ...parents.flatMap((parent) => [...parent.policies.traverse]),
34
- ...(definition.policies.traverse === undefined ? [] : [definition.policies.traverse]),
35
- ])),
36
- });
37
27
  const effectiveProperties = new Map();
38
28
  const effectiveMethods = new Map();
39
29
  let inheritedData;
@@ -102,7 +92,7 @@ export function createClasses(definitions, validation) {
102
92
  abstract: definition.abstract,
103
93
  definition,
104
94
  extends: Object.freeze(parents),
105
- policies,
95
+ policies: definition.policies,
106
96
  data: definition.kind === 'node' ? (ownData ?? inheritedData) : undefined,
107
97
  properties: createPropertyCollection(effectiveProperties.values()),
108
98
  methods: createMethodCollection(instanceMethods),
@@ -110,7 +100,6 @@ export function createClasses(definitions, validation) {
110
100
  self: Object.freeze({
111
101
  data: definition.kind === 'node' ? ownData : undefined,
112
102
  properties: createPropertyCollection(ownProperties),
113
- policies: definition.policies,
114
103
  methods: createMethodCollection(ownInstanceMethods),
115
104
  static: Object.freeze({ methods: createMethodCollection(ownStaticMethods) }),
116
105
  }),
@@ -138,12 +127,6 @@ export function createClasses(definitions, validation) {
138
127
  resolve(definition.ref);
139
128
  return resolved;
140
129
  }
141
- function uniquePolicyRefs(values) {
142
- const result = new Map();
143
- for (const value of values)
144
- result.set(Key.of(value), value);
145
- return [...result.values()].sort((left, right) => compareUnicode(Key.of(left), Key.of(right)));
146
- }
147
130
  function validateProperties(abstract, properties, input) {
148
131
  if (abstract) {
149
132
  return [
@@ -1,5 +1,5 @@
1
1
  import type { Value as PortableValue } from '@astrale-os/kernel-dsl/value';
2
- import type { ClassRef, DefinitionKey, Key, PolicyRef, PropertyKey } from '../../addressing/index.js';
2
+ import type { ClassRef, DefinitionKey, Key, PropertyKey } from '../../addressing/index.js';
3
3
  import type { ResolvedMethodCollection } from '../callable/resolved.js';
4
4
  import type { StateTopology } from '../state/index.js';
5
5
  import type { Diagnostic } from '../validation/diagnostic.js';
@@ -25,11 +25,6 @@ export interface ResolvedData {
25
25
  readonly owner: ResolvedClass<'node'>;
26
26
  readonly definition: DataDefinition;
27
27
  }
28
- export interface ResolvedClassPolicies {
29
- /** Effective read Policies for this Node or Edge Class. */
30
- readonly read: readonly PolicyRef[];
31
- readonly traverse: readonly PolicyRef[];
32
- }
33
28
  export type ResolvedPropertyCollection<ByKey extends Readonly<Record<PropertyKey, ResolvedProperty<unknown>>> = Readonly<Record<PropertyKey, ResolvedProperty<unknown>>>, ByName extends Readonly<Record<string, ResolvedProperty<unknown>>> = Readonly<Record<never, never>>> = Readonly<ByName> & Iterable<ByKey[keyof ByKey]> & {
34
29
  readonly byKey: ByKey;
35
30
  get<Key extends keyof ByKey>(key: Key): ByKey[Key];
@@ -47,8 +42,8 @@ export interface ResolvedClass<Kind extends ClassKind = ClassKind, Properties ex
47
42
  readonly abstract: boolean;
48
43
  readonly definition: Definition;
49
44
  readonly extends: Parents & readonly ResolvedClass<Kind>[];
50
- /** Effective inherited Policy conjunction, deduplicated by exact Policy ref. */
51
- readonly policies: ResolvedClassPolicies;
45
+ /** Local observation Policies; Class inheritance never contributes an attachment. */
46
+ readonly policies: Definition['policies'];
52
47
  readonly data: Kind extends 'node' ? ResolvedData | undefined : undefined;
53
48
  readonly properties: Properties;
54
49
  readonly methods: Kind extends 'node' ? InstanceMethods : ResolvedMethodCollection<Record<never, never>>;
@@ -58,8 +53,6 @@ export interface ResolvedClass<Kind extends ClassKind = ClassKind, Properties ex
58
53
  readonly self: {
59
54
  readonly data: Kind extends 'node' ? ResolvedData | undefined : undefined;
60
55
  readonly properties: SelfProperties;
61
- /** Policies declared by this exact Class only. */
62
- readonly policies: Definition['policies'];
63
56
  readonly methods: Kind extends 'node' ? SelfInstanceMethods : ResolvedMethodCollection<Record<never, never>>;
64
57
  readonly static: {
65
58
  readonly methods: Kind extends 'node' ? SelfStaticMethods : ResolvedMethodCollection<Record<never, never>>;
@@ -15,6 +15,10 @@ export function validateDefinitions(environment, analysis) {
15
15
  if (!sameRef(declaration.ref, ref)) {
16
16
  diagnostics.push(diagnostic('DV_REF_RESOLVES', `${pointer}/ref`, `Class ref must be exactly ${formatDefinitionRef(ref)}.`, formatDefinitionRef(declaration.ref)));
17
17
  }
18
+ if (declaration.abstract &&
19
+ (declaration.policies.read !== undefined || declaration.policies.traverse !== undefined)) {
20
+ diagnostics.push(diagnostic('DV_CLASS_ABSTRACT', `${pointer}/policies`, 'Abstract Classes cannot declare observation Policies.'));
21
+ }
18
22
  validateFacet(environment, declaration, pointer, diagnostics);
19
23
  validateParents(environment, ref, declaration.kind, declaration.extends, diagnostics);
20
24
  if (declaration.kind === 'edge') {
@@ -159,27 +163,7 @@ function edgeContractRefines(environment, child, parent) {
159
163
  const direct = refines(0, 0) && refines(1, 1);
160
164
  if (direct)
161
165
  return true;
162
- const reverse = refines(0, 1) && refines(1, 0);
163
- return reverse && !hasEffectiveEdgePolicy(environment, parent, new Set());
164
- }
165
- function hasEffectiveEdgePolicy(environment, declaration, visited) {
166
- if (declaration.policies.read !== undefined || declaration.policies.traverse !== undefined) {
167
- return true;
168
- }
169
- for (const parentRef of declaration.extends) {
170
- const key = definitionRefIndex(parentRef);
171
- if (visited.has(key))
172
- continue;
173
- visited.add(key);
174
- const parent = environment.resolveAny(parentRef);
175
- if (parent !== undefined &&
176
- parent.ref.kind === 'class' &&
177
- parent.declaration.kind === 'edge' &&
178
- hasEffectiveEdgePolicy(environment, parent.declaration, visited)) {
179
- return true;
180
- }
181
- }
182
- return false;
166
+ return refines(0, 1) && refines(1, 0);
183
167
  }
184
168
  function endpointRefines(environment, child, parent) {
185
169
  return child.accepts.every((accepted) => classSatisfies(environment, accepted, parent.accepts));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/kernel-dsl",
3
- "version": "0.2.0-beta.28",
3
+ "version": "0.2.0-beta.29",
4
4
  "description": "Astrale Kernel DSL - Schema authoring, inference, and IR serialization",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {