@astrale-os/kernel-dsl 0.2.0-beta.30 → 0.2.0-beta.31

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.
@@ -91,7 +91,7 @@ export interface Method<out Projection = unknown> {
91
91
  export type ProjectionOfCallable<Value extends Function | Method> = Value extends Function<infer Projection> ? Projection : Value extends Method<infer Projection> ? Projection : never;
92
92
  /** Internal lowering access; Callable authoring handles expose no public configuration object. */
93
93
  export declare function callableConfiguration(value: Function | Method): CallableInput;
94
- export type PolicyObjectAuthoring = Class | Function | Policy | View | CoreNode;
94
+ export type PolicyObjectAuthoring = Class | Function | Method | Policy | View | CoreNode;
95
95
  export type PolicyObjectInput = Lazy<PolicyObjectAuthoring | PolicyObjectRef>;
96
96
  export declare function func<const Config extends FunctionInput, Input = ValueInputOf<Config['input']>, Output = CallableOutputOf<Config['output']>, Auth extends FunctionAuth = Config['auth']>(config: Config): Function<CallableProjection<Input, Output, Auth, false, 'default'>>;
97
97
  export declare function method<const Config extends MethodInput, Input = ValueInputOf<Config['input']>, Output = CallableOutputOf<Config['output']>, Auth extends FunctionAuth = Config['auth'], Static extends boolean = Config extends {
@@ -1,4 +1,3 @@
1
- import { MethodKey } from '../../../addressing/index.js';
2
1
  import { classConfiguration } from '../../class/authoring.js';
3
2
  import { escapeToken, fail } from '../../schema/diagnostic.js';
4
3
  import { isAuthoringValue } from '../../schema/handle.js';
@@ -42,7 +41,13 @@ function captureExecutables(input, context) {
42
41
  for (const [methodName, method] of Object.entries(methods ?? {})) {
43
42
  const pointer = `/classes/${escapeToken(definitionName)}/methods/${escapeToken(methodName)}`;
44
43
  assertMethod(method, pointer);
45
- context.ownership.capture(method, MethodKey.of({ origin: context.origin, kind: 'class', name: definitionName }, methodName), pointer);
44
+ const ref = {
45
+ kind: 'method',
46
+ owner: { origin: context.origin, kind: 'class', name: definitionName },
47
+ name: methodName,
48
+ };
49
+ context.ownership.captureDefinition(method, ref, pointer);
50
+ context.capturePolicyObject(method, ref);
46
51
  }
47
52
  }
48
53
  for (const [name, value] of Object.entries(input.views ?? {})) {
@@ -2,7 +2,7 @@ import type { CoreRef, ClassRef, DefinitionRef, FunctionRef, PolicyRef, ViewRef
2
2
  import type { DomainDependency } from '../../../addressing/index.js';
3
3
  import type { ClassKind } from '../../../language/class/model/class.js';
4
4
  import type { CoreEndpointRef } from '../../../language/core/model/core.js';
5
- import type { PolicyObjectRef } from '../../../language/policy/model/policy.js';
5
+ import type { PolicyObjectRef } from '../../../language/index.js';
6
6
  import type { ValueSchemaRegistry } from '../../../language/value/reference/registry.js';
7
7
  import type { DomainSchema, DomainSchemaIR } from '../../../schema/model/schema.js';
8
8
  import type { Function, PolicyObjectInput } from '../../callable/authoring.js';
@@ -40,5 +40,5 @@ export declare class BuilderContext {
40
40
  noteDomainEndpointReferences(schema: DomainSchemaIR): void;
41
41
  private assertVisible;
42
42
  private classKind;
43
- private capturePolicyObject;
43
+ capturePolicyObject(value: object, ref: PolicyObjectRef): void;
44
44
  }
@@ -1,5 +1,6 @@
1
1
  import { compareDefinitionRefs, compareUnicode, definitionRefIndex, } from '../../../addressing/ordering.js';
2
2
  import { DEPENDENCY_ALIAS_PATTERN } from '../../../addressing/patterns.js';
3
+ import { policyObjectKey, policyObjectOrigin } from '../../../language/index.js';
3
4
  import { graphNodePathSchema } from '../../../language/value/syntax/node-path/schema.js';
4
5
  import { revisionOfDomainSchema } from '../../../schema/canonical/revision.js';
5
6
  import { requireDomainClosure } from '../../../schema/resolution/closure.js';
@@ -114,16 +115,18 @@ export class BuilderContext {
114
115
  : typeof value === 'object' && value !== null
115
116
  ? (this.policyObjects.get(value) ?? this.ownership.definition(value))
116
117
  : undefined;
117
- const dependency = ref === undefined ? undefined : this.#dependencies.get(ref.origin)?.schema;
118
+ const origin = ref === undefined ? undefined : policyObjectOrigin(ref);
119
+ const dependency = origin === undefined ? undefined : this.#dependencies.get(origin)?.schema;
118
120
  const admitted = ref !== undefined &&
119
- (ref.origin === this.origin
120
- ? this.policyObjectRefs.has(definitionRefIndex(ref))
121
+ (origin === this.origin
122
+ ? this.policyObjectRefs.has(policyObjectKey(ref))
121
123
  : dependency !== undefined && hasPolicyObject(dependency, ref));
122
124
  if (!admitted || ref === undefined) {
123
- fail('BUILDER_POLICY_REF', pointer, 'Policy ref(...) must name one registered local or direct-dependency Definition, Function, Policy, View, or Core Node.');
125
+ fail('BUILDER_POLICY_REF', pointer, 'Policy ref(...) must name one registered local or direct-dependency Definition, Function, Method, Policy, View, or Core Node.');
124
126
  }
125
- if (ref.origin !== this.origin)
126
- this.usedForeignOrigins.add(ref.origin);
127
+ const admittedOrigin = policyObjectOrigin(ref);
128
+ if (admittedOrigin !== this.origin)
129
+ this.usedForeignOrigins.add(admittedOrigin);
127
130
  return { ...ref };
128
131
  }
129
132
  resolveCoreEndpoint(value, pointer) {
@@ -196,7 +199,7 @@ export class BuilderContext {
196
199
  }
197
200
  capturePolicyObject(value, ref) {
198
201
  this.policyObjects.set(value, ref);
199
- this.policyObjectRefs.add(definitionRefIndex(ref));
202
+ this.policyObjectRefs.add(policyObjectKey(ref));
200
203
  }
201
204
  }
202
205
  function escapePointer(value) {
@@ -234,6 +237,8 @@ function isPolicyObjectRef(value) {
234
237
  if (typeof value !== 'object' || value === null)
235
238
  return false;
236
239
  const candidate = value;
240
+ if (candidate.kind === 'method')
241
+ return isDefinitionRef(candidate.owner) && typeof candidate.name === 'string';
237
242
  return (typeof candidate.origin === 'string' &&
238
243
  typeof candidate.name === 'string' &&
239
244
  (candidate.kind === 'class' ||
@@ -252,6 +257,11 @@ function definitionRefsOf(schema) {
252
257
  }
253
258
  function hasPolicyObject(schema, ref) {
254
259
  switch (ref.kind) {
260
+ case 'method': {
261
+ const owner = schema.classes[ref.owner.name];
262
+ const method = owner?.kind === 'node' ? owner.methods[ref.name] : undefined;
263
+ return method !== undefined && method.inheritance !== 'abstract';
264
+ }
255
265
  case 'class':
256
266
  return Object.hasOwn(schema.classes, ref.name);
257
267
  case 'function':
@@ -1,4 +1,4 @@
1
- import type { PolicyObjectRef } from '../../../language/policy/model/policy.js';
1
+ import type { PolicyObjectRef } from '../../../language/index.js';
2
2
  export declare class OwnershipCapture {
3
3
  #private;
4
4
  captureDefinition(value: object, ref: PolicyObjectRef, pointer: string): void;
@@ -1,3 +1,4 @@
1
+ import { policyObjectKey } from '../../../language/index.js';
1
2
  import { fail } from '../../schema/diagnostic.js';
2
3
  const definitionOwners = new WeakMap();
3
4
  const semanticOwners = new WeakMap();
@@ -5,7 +6,7 @@ export class OwnershipCapture {
5
6
  #definitions = new Map();
6
7
  #owners = new Map();
7
8
  captureDefinition(value, ref, pointer) {
8
- this.capture(value, `${ref.origin}:${ref.kind}.${ref.name}`, pointer);
9
+ this.capture(value, policyObjectKey(ref), pointer);
9
10
  this.#definitions.set(value, ref);
10
11
  }
11
12
  capture(value, owner, pointer) {
@@ -494,7 +494,7 @@ function policyTerm(input, variableOnly, path) {
494
494
  const value = object(input, 'Policy pattern term', path);
495
495
  if (!variableOnly && value.kind === 'ref') {
496
496
  exact(value, ['kind', 'ref'], 'Policy reference term', path);
497
- definitionRef(value.ref, undefined, 'Policy reference term', `${path}/ref`);
497
+ policyObjectRef(value.ref, `${path}/ref`);
498
498
  return;
499
499
  }
500
500
  if (value.kind === 'variable') {
@@ -548,7 +548,7 @@ function policyCheckObject(input, objectPath) {
548
548
  }
549
549
  else if (target.kind === 'ref') {
550
550
  exact(target, ['kind', 'ref'], 'Callable Policy object ref', objectPath);
551
- definitionRef(target.ref, undefined, 'Callable Policy object ref', `${objectPath}/ref`);
551
+ policyObjectRef(target.ref, `${objectPath}/ref`);
552
552
  }
553
553
  else
554
554
  invalid('Callable Policy object', undefined, `${objectPath}/kind`);
@@ -560,6 +560,17 @@ function coreEndpoint(input, label, path) {
560
560
  else
561
561
  definitionRef(value, 'core', label, path);
562
562
  }
563
+ function policyObjectRef(input, path) {
564
+ const ref = object(input, 'Policy object ref', path);
565
+ if (ref.kind !== 'method') {
566
+ definitionRef(input, undefined, 'Policy object ref', path);
567
+ return;
568
+ }
569
+ exact(ref, ['kind', 'owner', 'name'], 'Policy Method ref', path);
570
+ definitionRef(ref.owner, 'class', 'Policy Method owner', `${path}/owner`);
571
+ if (typeof ref.name !== 'string' || !MEMBER_NAME_PATTERN.test(ref.name))
572
+ invalid('Policy Method name', undefined, `${path}/name`);
573
+ }
563
574
  function definitionRef(input, kind, label, path) {
564
575
  if (!isDefinitionRef(input) || (kind !== undefined && input.kind !== kind))
565
576
  invalid(label, undefined, path);
@@ -1,9 +1,9 @@
1
1
  import { json } from '@astrale-os/kernel-dsl/value';
2
2
  import { Key, PropertyKey as PropertyKeyValue } from '../../addressing/index.js';
3
3
  import { compareUnicode } from '../../addressing/ordering.js';
4
+ import { policyObjectOrigin, policyVariableClass } from '../../language/index.js';
4
5
  import { branchesOf, branchProduct, capBranches, isConnected, targetMode, termKey, } from '../../language/policy/analysis/branches.js';
5
6
  import { BRANCH_OVERFLOW, MAX_BRANCHES, MAX_CHECK_DEPTH, MAX_CHECK_LEAVES, MAX_DOMAINS, MAX_EDGES, MAX_PATTERN_DEPTH, MAX_REPEAT, MAX_VARIABLES, measureChecks, } from '../../language/policy/analysis/budgets.js';
6
- import { policyVariableClass } from '../../language/policy/model/policy.js';
7
7
  import { normalizePolicyChecks, normalizePolicyExpression, } from '../../language/policy/normalization/normalize.js';
8
8
  import { validateValueProgram } from '../../language/value/evaluate/program.js';
9
9
  import { GRAPH_NODE_PATH_SCHEMA_ID } from '../../language/value/syntax/node-path/schema.js';
@@ -348,15 +348,15 @@ function validatePolicyExpression(context, entry, expression, path, local) {
348
348
  }
349
349
  function validatePattern(context, expression, path, scope, declared) {
350
350
  if ('sameNode' in expression) {
351
- validatePolicyTerm(expression.sameNode.left, `${path}/sameNode/left`, scope);
352
- validatePolicyTerm(expression.sameNode.right, `${path}/sameNode/right`, scope);
351
+ validatePolicyTerm(context, expression.sameNode.left, `${path}/sameNode/left`, scope);
352
+ validatePolicyTerm(context, expression.sameNode.right, `${path}/sameNode/right`, scope);
353
353
  return;
354
354
  }
355
355
  if ('source' in expression) {
356
356
  if (context.classes.get(Key.of(expression.class))?.value.kind !== 'edge')
357
357
  fail(`${path}/class`, 'Policy pattern Class must resolve to an Edge Class.');
358
- validatePolicyTerm(expression.source, `${path}/source`, scope);
359
- validatePolicyTerm(expression.target, `${path}/target`, scope);
358
+ validatePolicyTerm(context, expression.source, `${path}/source`, scope);
359
+ validatePolicyTerm(context, expression.target, `${path}/target`, scope);
360
360
  if (expression.repeat !== undefined &&
361
361
  (!Number.isInteger(expression.repeat.min) ||
362
362
  !Number.isInteger(expression.repeat.max) ||
@@ -389,10 +389,18 @@ function validatePattern(context, expression, path, scope, declared) {
389
389
  fail(path, 'Policy pattern composition must be non-empty.');
390
390
  values.forEach((value, index) => validatePattern(context, value, `${path}/${index}`, scope, declared));
391
391
  }
392
- function validatePolicyTerm(term, path, scope) {
392
+ function validatePolicyTerm(context, term, path, scope) {
393
+ if (term.kind === 'ref' && term.ref.kind === 'method')
394
+ validatePolicyMethod(context, term.ref, `${path}/ref`);
393
395
  if (term.kind === 'variable' && !scope.has(term.id))
394
396
  fail(path, 'Policy variable is outside its declaring scope.');
395
397
  }
398
+ function validatePolicyMethod(context, ref, path) {
399
+ const owner = context.classes.get(Key.of(ref.owner))?.value;
400
+ const method = owner?.kind === 'node' ? owner.methods.find((method) => method.name === ref.name) : undefined;
401
+ if (method === undefined || method.inheritance === 'abstract')
402
+ fail(path, 'Policy Method ref must name an exact concrete Method declaration.');
403
+ }
396
404
  function validatePolicyCycles(entry, local, entryIndex) {
397
405
  const visiting = new Set();
398
406
  const visited = new Set();
@@ -422,6 +430,8 @@ function validateCallablePolicy(context, entry, expression, inputIndex, fields,
422
430
  fail(`${path}/check`, 'Callable Policy must reference a local named Policy.');
423
431
  const objects = 'check' in expression ? { object: expression.object } : expression.sameNode;
424
432
  for (const [side, object] of Object.entries(objects)) {
433
+ if (object.kind === 'ref' && object.ref.kind === 'method')
434
+ validatePolicyMethod(context, object.ref, `${path}/${side}/ref`);
425
435
  if (object.kind === 'self' && !instanceMethod)
426
436
  fail(`${path}/${side}`, 'self is valid only for an instance Method.');
427
437
  if (object.kind === 'input' &&
@@ -590,7 +600,7 @@ function callableObjectContracts(context, entry, input, receiver, object) {
590
600
  }
591
601
  const projection = ref.kind === 'class'
592
602
  ? 'Class'
593
- : ref.kind === 'function'
603
+ : ref.kind === 'function' || ref.kind === 'method'
594
604
  ? 'Function'
595
605
  : ref.kind === 'policy'
596
606
  ? 'Policy'
@@ -893,7 +903,7 @@ function measureCompiledPattern(pattern, origin) {
893
903
  edgeCounts: [1],
894
904
  domains: new Set([
895
905
  origin,
896
- ...[pattern.sameNode.left, pattern.sameNode.right].flatMap((term) => term.kind === 'ref' ? [term.ref.origin] : []),
906
+ ...[pattern.sameNode.left, pattern.sameNode.right].flatMap((term) => term.kind === 'ref' ? [policyObjectOrigin(term.ref)] : []),
897
907
  ]),
898
908
  };
899
909
  if ('source' in pattern)
@@ -903,7 +913,7 @@ function measureCompiledPattern(pattern, origin) {
903
913
  domains: new Set([
904
914
  origin,
905
915
  pattern.class.origin,
906
- ...[pattern.source, pattern.target].flatMap((term) => term.kind === 'ref' ? [term.ref.origin] : []),
916
+ ...[pattern.source, pattern.target].flatMap((term) => term.kind === 'ref' ? [policyObjectOrigin(term.ref)] : []),
907
917
  ]),
908
918
  };
909
919
  if ('exists' in pattern) {
@@ -20,7 +20,7 @@ export type { Definition } from './definition.js';
20
20
  export type { ResolvedDefinition, ResolvedDefinitionOf } from './resolved.js';
21
21
  export type { Diagnostic, DiagnosticCode } from './validation/diagnostic.js';
22
22
  export type * from './policy/model/policy.js';
23
- export { policyVariableClass, policyVariableSelector } from './policy/model/policy.js';
23
+ export { policyVariableClass, policyVariableSelector, policyObjectKey, policyObjectOrigin, } from './policy/model/policy.js';
24
24
  export type * from './policy/resolved.js';
25
25
  export type * from './view/model/view.js';
26
26
  export type * from './view/resolved.js';
@@ -1,3 +1,3 @@
1
1
  export { stateMachine } from './state/index.js';
2
2
  export { PropertyValues } from './class/property-values.js';
3
- export { policyVariableClass, policyVariableSelector } from './policy/model/policy.js';
3
+ export { policyVariableClass, policyVariableSelector, policyObjectKey, policyObjectOrigin, } from './policy/model/policy.js';
@@ -1,5 +1,5 @@
1
1
  import { definitionRefIndex } from '../../../addressing/ordering.js';
2
- import { policyVariableSelector } from '../model/policy.js';
2
+ import { policyObjectKey, policyVariableSelector } from '../model/policy.js';
3
3
  import { BRANCH_OVERFLOW } from './budgets.js';
4
4
  export function branchesOf(pattern, namespace) {
5
5
  const variables = collectVariableClasses(pattern, namespace);
@@ -62,7 +62,7 @@ export function termKey(term, namespace) {
62
62
  return term.kind === 'variable'
63
63
  ? variableKey(namespace, term.id)
64
64
  : term.kind === 'ref'
65
- ? `ref:${definitionRefIndex(term.ref)}`
65
+ ? `ref:${term.ref.kind === 'method' ? policyObjectKey(term.ref) : definitionRefIndex(term.ref)}`
66
66
  : term.kind;
67
67
  }
68
68
  function branchesForNode(pattern, namespace, variables) {
@@ -1,4 +1,4 @@
1
1
  export type * from './model/policy.js';
2
- export { policyVariableClass, policyVariableSelector } from './model/policy.js';
2
+ export { policyVariableClass, policyVariableSelector, policyObjectKey, policyObjectOrigin, } from './model/policy.js';
3
3
  export type * from './resolved.js';
4
4
  export * from './normalization/normalize.js';
@@ -1,2 +1,2 @@
1
- export { policyVariableClass, policyVariableSelector } from './model/policy.js';
1
+ export { policyVariableClass, policyVariableSelector, policyObjectKey, policyObjectOrigin, } from './model/policy.js';
2
2
  export * from './normalization/normalize.js';
@@ -1,4 +1,4 @@
1
- import type { CoreRef, ClassRef, FunctionRef, PolicyRef, ViewRef, DefinitionBase } from '../../../addressing/index.js';
1
+ import type { CoreRef, ClassRef, FunctionRef, PolicyRef, ViewRef, DefinitionBase, MethodAddress } from '../../../addressing/index.js';
2
2
  export type PolicyPatternTerm = {
3
3
  readonly kind: 'subject';
4
4
  } | {
@@ -85,7 +85,10 @@ export interface PolicyDefinition extends DefinitionBase<PolicyRef> {
85
85
  readonly description?: string;
86
86
  }
87
87
  /** Local Domain members whose installed projection resolves through one exact member Path. */
88
- export type PolicyObjectRef = ClassRef | FunctionRef | PolicyRef | ViewRef | CoreRef;
88
+ export type PolicyObjectRef = ClassRef | FunctionRef | PolicyRef | ViewRef | CoreRef | MethodAddress;
89
+ /** Exact projected identity, including Class-owned Method declarations. */
90
+ export declare function policyObjectKey(ref: PolicyObjectRef): string;
91
+ export declare function policyObjectOrigin(ref: PolicyObjectRef): string;
89
92
  export type PolicyCheckObject = {
90
93
  readonly kind: 'self';
91
94
  } | {
@@ -7,3 +7,12 @@ export function policyVariableClass(variable) {
7
7
  const selector = policyVariableSelector(variable);
8
8
  return selector.kind === 'any' ? undefined : selector.class;
9
9
  }
10
+ /** Exact projected identity, including Class-owned Method declarations. */
11
+ export function policyObjectKey(ref) {
12
+ return ref.kind === 'method'
13
+ ? `${ref.owner.origin}:class.${ref.owner.name}.method.${ref.name}`
14
+ : `${ref.origin}:${ref.kind}.${ref.name}`;
15
+ }
16
+ export function policyObjectOrigin(ref) {
17
+ return ref.kind === 'method' ? ref.owner.origin : ref.origin;
18
+ }
@@ -1,6 +1,6 @@
1
1
  import { json } from '@astrale-os/kernel-dsl/value';
2
2
  import { definitionRefIndex, compareDefinitionRefs } from '../../../addressing/ordering.js';
3
- import { policyVariableSelector } from '../model/policy.js';
3
+ import { policyObjectKey, policyVariableSelector } from '../model/policy.js';
4
4
  const textEncoder = new TextEncoder();
5
5
  export function normalizePolicyExpression(value) {
6
6
  if ('match' in value) {
@@ -146,7 +146,7 @@ function termColor(term, colors) {
146
146
  if (term.kind === 'variable')
147
147
  return `variable:${colors.get(term.id) ?? '?'}`;
148
148
  if (term.kind === 'ref')
149
- return `ref:${definitionRefIndex(term.ref)}`;
149
+ return `ref:${term.ref.kind === 'method' ? policyObjectKey(term.ref) : definitionRefIndex(term.ref)}`;
150
150
  return term.kind;
151
151
  }
152
152
  function collectFirstUseKeys(value, colors, result, prefix = '$') {
@@ -82,13 +82,13 @@ function collectPolicyPatternRefs(expression, add) {
82
82
  if ('sameNode' in expression) {
83
83
  for (const term of [expression.sameNode.left, expression.sameNode.right])
84
84
  if (term.kind === 'ref')
85
- add(term.ref);
85
+ add(term.ref.kind === 'method' ? term.ref.owner : term.ref);
86
86
  return;
87
87
  }
88
88
  if ('source' in expression) {
89
89
  for (const term of [expression.source, expression.target])
90
90
  if (term.kind === 'ref')
91
- add(term.ref);
91
+ add(term.ref.kind === 'method' ? term.ref.owner : term.ref);
92
92
  add(expression.class);
93
93
  return;
94
94
  }
@@ -108,13 +108,15 @@ function collectPolicyCheckRefs(expression, add) {
108
108
  if ('sameNode' in expression) {
109
109
  for (const term of [expression.sameNode.left, expression.sameNode.right])
110
110
  if (term.kind === 'ref')
111
- add(term.ref);
111
+ add(term.ref.kind === 'method' ? term.ref.owner : term.ref);
112
112
  return;
113
113
  }
114
114
  if ('check' in expression) {
115
115
  add(expression.check);
116
116
  if (expression.object.kind === 'ref')
117
- add(expression.object.ref);
117
+ add(expression.object.ref.kind === 'method'
118
+ ? expression.object.ref.owner
119
+ : expression.object.ref);
118
120
  return;
119
121
  }
120
122
  const children = 'allOf' in expression ? expression.allOf : expression.anyOf;
@@ -63,6 +63,7 @@ const coreRefSchema = strictObject({
63
63
  const domainRefSchema = strictObject({ kind: literal('domain') });
64
64
  const coreEndpointRefSchema = discriminatedUnion('kind', [coreRefSchema, domainRefSchema]);
65
65
  const policyObjectRefSchema = discriminatedUnion('kind', [
66
+ strictObject({ kind: literal('method'), owner: classRefSchema, name: memberNameSchema }),
66
67
  classRefSchema,
67
68
  functionRefSchema,
68
69
  policyRefSchema,
@@ -1,5 +1,5 @@
1
+ import { policyObjectOrigin, policyVariableClass } from '../../../language/index.js';
1
2
  import { BRANCH_OVERFLOW, MAX_BRANCHES, MAX_CHECK_DEPTH, MAX_CHECK_LEAVES, MAX_DOMAINS, MAX_EDGES, MAX_PATTERN_DEPTH, MAX_REPEAT, MAX_VARIABLES, measureChecks, } from '../../../language/policy/analysis/budgets.js';
2
- import { policyVariableClass } from '../../../language/policy/model/policy.js';
3
3
  import { escapePointer } from './context.js';
4
4
  export { BRANCH_OVERFLOW, MAX_BRANCHES, MAX_CHECK_DEPTH, MAX_CHECK_LEAVES, MAX_DOMAINS, MAX_EDGES, MAX_PATTERN_DEPTH, MAX_REPEAT, MAX_VARIABLES, measureChecks, };
5
5
  export function validatePolicyBudgets(context) {
@@ -52,7 +52,7 @@ function measurePattern(pattern, ownOrigin) {
52
52
  edgeCounts: [1],
53
53
  domains: new Set([
54
54
  ownOrigin,
55
- ...[pattern.sameNode.left, pattern.sameNode.right].flatMap((term) => term.kind === 'ref' ? [term.ref.origin] : []),
55
+ ...[pattern.sameNode.left, pattern.sameNode.right].flatMap((term) => term.kind === 'ref' ? [policyObjectOrigin(term.ref)] : []),
56
56
  ]),
57
57
  };
58
58
  if (isEdge(pattern)) {
@@ -62,7 +62,7 @@ function measurePattern(pattern, ownOrigin) {
62
62
  domains: new Set([
63
63
  ownOrigin,
64
64
  pattern.class.origin,
65
- ...[pattern.source, pattern.target].flatMap((term) => term.kind === 'ref' ? [term.ref.origin] : []),
65
+ ...[pattern.source, pattern.target].flatMap((term) => term.kind === 'ref' ? [policyObjectOrigin(term.ref)] : []),
66
66
  ]),
67
67
  };
68
68
  }
@@ -1,4 +1,4 @@
1
- import type { PolicyObjectRef } from '../../../language/policy/model/policy.js';
1
+ import type { PolicyObjectRef } from '../../../language/index.js';
2
2
  import type { PolicyValidationContext } from './context.js';
3
3
  import type { ObjectContract } from './typing.js';
4
4
  export declare function referenceContracts(validation: PolicyValidationContext, ref: PolicyObjectRef, pointer: string): readonly ObjectContract[] | undefined;
@@ -1,6 +1,5 @@
1
- import { Key } from '../../../addressing/index.js';
2
1
  import { definitionRefIndex } from '../../../addressing/ordering.js';
3
- const formatDefinitionRef = Key.of;
2
+ import { policyObjectKey, policyObjectOrigin } from '../../../language/index.js';
4
3
  const KERNEL_ORIGIN = 'kernel.astrale.ai';
5
4
  const PROJECTION_CLASS = nodeClassRef('Class');
6
5
  const PROJECTION_FUNCTION = nodeClassRef('Function');
@@ -8,12 +7,12 @@ const PROJECTION_POLICY = nodeClassRef('Policy');
8
7
  const PROJECTION_VIEW = nodeClassRef('View');
9
8
  export function referenceContracts(validation, ref, pointer) {
10
9
  const candidate = validation.environment.candidate;
11
- const local = ref.origin === candidate.origin;
12
- const direct = Object.values(candidate.dependencies).some((entry) => entry.origin === ref.origin);
10
+ const local = policyObjectOrigin(ref) === candidate.origin;
11
+ const direct = Object.values(candidate.dependencies).some((entry) => entry.origin === policyObjectOrigin(ref));
13
12
  const owner = local
14
13
  ? candidate
15
14
  : direct
16
- ? validation.environment.dependencies.get(ref.origin)
15
+ ? validation.environment.dependencies.get(policyObjectOrigin(ref))
17
16
  : undefined;
18
17
  if (owner === undefined)
19
18
  return invalidPolicyObjectRef(validation, ref, pointer);
@@ -24,6 +23,13 @@ export function referenceContracts(validation, ref, pointer) {
24
23
  ? [{ kind: 'exact', ref: PROJECTION_CLASS }]
25
24
  : invalidPolicyObjectRef(validation, ref, pointer);
26
25
  }
26
+ case 'method': {
27
+ const declaringClass = owner.classes[ref.owner.name];
28
+ const method = declaringClass?.kind === 'node' ? declaringClass.methods[ref.name] : undefined;
29
+ return method === undefined || method.inheritance === 'abstract'
30
+ ? invalidPolicyObjectRef(validation, ref, pointer)
31
+ : [{ kind: 'exact', ref: PROJECTION_FUNCTION }];
32
+ }
27
33
  case 'function':
28
34
  return owner.functions[ref.name] === undefined
29
35
  ? invalidPolicyObjectRef(validation, ref, pointer)
@@ -56,7 +62,7 @@ export function referenceContracts(validation, ref, pointer) {
56
62
  return invalidPolicyObjectRef(validation, ref, pointer);
57
63
  }
58
64
  function invalidPolicyObjectRef(validation, ref, pointer) {
59
- validation.add('PL_REF', `${pointer}/ref`, `${formatDefinitionRef(ref)} is not an exact local or direct-dependency projected Policy object.`, formatDefinitionRef(ref));
65
+ validation.add('PL_REF', `${pointer}/ref`, `${policyObjectKey(ref)} is not an exact local or direct-dependency projected Policy object.`, policyObjectKey(ref));
60
66
  return undefined;
61
67
  }
62
68
  function nodeClassRef(name) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/kernel-dsl",
3
- "version": "0.2.0-beta.30",
3
+ "version": "0.2.0-beta.31",
4
4
  "description": "Astrale Kernel DSL - Schema authoring, inference, and IR serialization",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {