@astrale-os/kernel-core 0.9.0-beta.66 → 0.9.0-beta.67

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 (29) hide show
  1. package/dist/auth/authority/semantics/interpret.d.ts +6 -0
  2. package/dist/auth/authority/semantics/interpret.js +187 -14
  3. package/dist/auth/authority/semantics/snapshot.d.ts +6 -0
  4. package/dist/graph/mutate/language/wire.d.ts +11 -0
  5. package/dist/graph/mutate/result/index.d.ts +1 -0
  6. package/dist/graph/mutate/result/index.js +3 -1
  7. package/dist/graph/mutate/result/wire.d.ts +1 -0
  8. package/dist/graph/mutate/result/wire.js +5 -2
  9. package/dist/graph/node/identity/order.js +20 -0
  10. package/dist/graph/query/authoring/builder.js +29 -2
  11. package/dist/graph/query/authoring/model.d.ts +20 -1
  12. package/dist/graph/query/index.d.ts +3 -3
  13. package/dist/graph/query/index.js +1 -1
  14. package/dist/graph/query/language/codec.js +15 -0
  15. package/dist/graph/query/language/fingerprint.js +8 -0
  16. package/dist/graph/query/language/model.d.ts +19 -1
  17. package/dist/graph/query/language/wire.d.ts +11 -0
  18. package/dist/graph/query/language/wire.js +8 -1
  19. package/dist/graph/query/order/index.d.ts +8 -1
  20. package/dist/graph/query/order/index.js +20 -0
  21. package/dist/graph/query/reference/evaluate.js +5 -3
  22. package/dist/schema/kernel/schema.d.ts +115 -67
  23. package/dist/schema/kernel/syscalls/contracts/mutate.d.ts +13 -0
  24. package/dist/schema/kernel/syscalls/contracts/mutate.js +2 -1
  25. package/dist/schema/kernel/syscalls/contracts/query.d.ts +11 -0
  26. package/dist/schema/kernel/syscalls/declarations/index.d.ts +24 -0
  27. package/dist/schema/kernel/syscalls/declarations/mutate.d.ts +13 -0
  28. package/dist/schema/kernel/syscalls/declarations/query.d.ts +11 -0
  29. package/package.json +2 -2
@@ -15,6 +15,12 @@ export interface AuthorityEvaluationOptions {
15
15
  * as a captured fact table. Undefined leaves the atom to its meaning over the snapshot.
16
16
  */
17
17
  readonly atom?: (atom: AuthorityAtom, subject: NodeId | undefined) => boolean | undefined;
18
+ /**
19
+ * Pure observation of the snapshot's evidence token. It changes (Object.is) at every
20
+ * acquisition and stays stable otherwise; observing it must not acquire evidence.
21
+ * Stable snapshots may omit it. Tokens must not be mutated or reused across acquisitions.
22
+ */
23
+ readonly evidenceEpoch?: () => unknown;
18
24
  }
19
25
  /** Decisions of one program over one snapshot. Memoized evidence never outlives the evaluator. */
20
26
  export interface AuthorityEvaluator {
@@ -10,6 +10,9 @@ export function createAuthorityEvaluator(program, snapshot, vocabulary, options
10
10
  const references = new Map();
11
11
  const closures = new Map();
12
12
  const projections = new Map();
13
+ const walks = new Map();
14
+ const walkPlans = new WeakMap();
15
+ const existentialPlans = new WeakMap();
13
16
  const instanceOf = classKey(vocabulary.instanceOf);
14
17
  const reference = (path) => {
15
18
  const known = references.get(path.raw);
@@ -65,7 +68,8 @@ export function createAuthorityEvaluator(program, snapshot, vocabulary, options
65
68
  const key = classKey(ref);
66
69
  let nodes = projections.get(key);
67
70
  if (nodes === undefined) {
68
- nodes = Object.freeze([...new Set(snapshot.resolve(Path.project(ref)))].filter((node) => snapshot.node(node)));
71
+ const candidates = snapshot.classProjection?.(ref) ?? snapshot.resolve(Path.project(ref));
72
+ nodes = Object.freeze([...new Set(candidates)].filter((node) => snapshot.node(node)));
69
73
  projections.set(key, nodes);
70
74
  }
71
75
  return nodes;
@@ -77,19 +81,52 @@ export function createAuthorityEvaluator(program, snapshot, vocabulary, options
77
81
  * Bounded walks: a Node reached at any depth within [min, max], revisits allowed. Each hop may
78
82
  * take any member of the Edge Class extent.
79
83
  */
80
- const related = (source, extent, target, repeat) => {
84
+ const related = (expression, source, target) => {
85
+ const { repeat, via: extent } = expression;
81
86
  const min = repeat?.min ?? 1;
82
87
  const max = repeat?.max ?? 1;
88
+ // The empty walk is already a proof. Do not spend a read budget exploring longer walks.
83
89
  if (min === 0 && source === target)
84
90
  return true;
85
- let frontier = new Set([source]);
91
+ let plan = walkPlans.get(expression);
92
+ if (plan === undefined) {
93
+ const key = JSON.stringify([min, max, extent.map(classKey)]);
94
+ plan = walks.get(key);
95
+ if (plan === undefined) {
96
+ plan = new Map();
97
+ walks.set(key, plan);
98
+ }
99
+ walkPlans.set(expression, plan);
100
+ }
101
+ const epoch = options.evidenceEpoch?.();
102
+ let walk = plan.get(source);
103
+ if (walk === undefined || !Object.is(walk.epoch, epoch)) {
104
+ walk = { epoch, layers: [new Set([source])] };
105
+ plan.delete(source);
106
+ }
107
+ let frontier = walk.layers[0];
86
108
  for (let depth = 1; depth <= max && frontier.size > 0; depth++) {
87
- const next = new Set();
88
- for (const node of frontier) {
89
- for (const edge of extent)
90
- for (const reached of step(node, edge))
91
- next.add(reached);
109
+ let next = walk.layers[depth];
110
+ if (next === undefined) {
111
+ const before = options.evidenceEpoch?.();
112
+ const acquired = new Set();
113
+ for (const node of frontier) {
114
+ for (const edge of extent)
115
+ for (const reached of step(node, edge))
116
+ acquired.add(reached);
117
+ }
118
+ next = acquired;
119
+ walk.layers.push(next);
120
+ // Every retained layer must belong to the same epoch. A provisional prefix remains
121
+ // usable for this search only, even if its later extensions acquire no further evidence.
122
+ if (Object.is(walk.epoch, before) && Object.is(before, options.evidenceEpoch?.())) {
123
+ plan.set(source, walk);
124
+ }
125
+ else {
126
+ plan.delete(source);
127
+ }
92
128
  }
129
+ // Like the frozen interpreter, acquire no layer beyond the first admissible witness.
93
130
  if (depth >= min && next.has(target))
94
131
  return true;
95
132
  frontier = next;
@@ -127,7 +164,7 @@ export function createAuthorityEvaluator(program, snapshot, vocabulary, options
127
164
  case 'same-node':
128
165
  return term(expression.left, frame) === term(expression.right, frame);
129
166
  case 'related':
130
- return related(term(expression.source, frame), expression.via, term(expression.target, frame), expression.repeat);
167
+ return related(expression, term(expression.source, frame), term(expression.target, frame));
131
168
  case 'instance-of':
132
169
  return sameClass(classOf(term(expression.node, frame)), expression.class);
133
170
  case 'edge-class': {
@@ -155,13 +192,111 @@ export function createAuthorityEvaluator(program, snapshot, vocabulary, options
155
192
  };
156
193
  const exists = (expression, frame) => {
157
194
  const candidates = expression.nodes.map((local) => local.kind === 'any' ? snapshot.nodes() : snapshot.nodes(local.classes));
158
- const bind = (index, locals) => {
159
- if (index === expression.nodes.length)
160
- return holds(expression.where, { ...frame, locals });
195
+ // Acquire every extent in declaration order, even when the product has no tuple.
196
+ if (candidates.some((extent) => extent.length === 0))
197
+ return false;
198
+ let plan = existentialPlans.get(expression);
199
+ if (plan === undefined) {
200
+ const predicates = expression.where.op === 'all' ? expression.where.predicates : [expression.where];
201
+ const usedIndices = new Set();
202
+ // Each entry describes the whole prefix, including its earlier true predicates.
203
+ // gates[i] rejects values of local i; resets[i] invalidates their earlier context.
204
+ const gates = expression.nodes.map(() => []);
205
+ const resets = expression.nodes.map(() => []);
206
+ const dependency = predicates.map((predicate, item) => {
207
+ const used = localDependencies(predicate);
208
+ for (let index = 0; index < expression.nodes.length; index++) {
209
+ if (used.has(expression.nodes[index].id))
210
+ usedIndices.add(index);
211
+ }
212
+ const ordered = [...usedIndices].sort((left, right) => left - right);
213
+ const last = ordered.at(-1) ?? -1;
214
+ const earlier = ordered.at(-2) ?? -1;
215
+ if (last >= 0)
216
+ gates[last].push(item);
217
+ // An exclusion of the last dependency is valid only while all earlier ones stay fixed.
218
+ for (let index = 0; index <= earlier; index++)
219
+ resets[index].push(item);
220
+ return last;
221
+ });
222
+ plan = { predicates, dependency, gates, resets };
223
+ existentialPlans.set(expression, plan);
224
+ }
225
+ const { predicates, dependency, gates, resets } = plan;
226
+ const excluded = predicates.map(() => new Set());
227
+ const rejected = (index, node) => {
228
+ for (const item of gates[index])
229
+ if (excluded[item].has(node))
230
+ return true;
231
+ return false;
232
+ };
233
+ const clear = (item) => {
234
+ if (excluded[item].size === 0)
235
+ return;
236
+ excluded[item].clear();
237
+ };
238
+ let prefix = 0;
239
+ let observedEpoch = options.evidenceEpoch?.();
240
+ const refresh = () => {
241
+ const current = options.evidenceEpoch?.();
242
+ if (Object.is(current, observedEpoch))
243
+ return false;
244
+ observedEpoch = current;
245
+ prefix = 0;
246
+ excluded.forEach((_, item) => clear(item));
247
+ return true;
248
+ };
249
+ // -2 means a witness. Every other result identifies the last bound variable that
250
+ // may change the evaluated prefix. Descendants cannot alter its reads or result.
251
+ const locals = new Map(frame.locals);
252
+ const complete = { ...frame, locals };
253
+ const bind = (index) => {
254
+ if (index === expression.nodes.length) {
255
+ for (let item = prefix; item < predicates.length; item++) {
256
+ if (!holds(predicates[item], complete)) {
257
+ if (refresh())
258
+ return expression.nodes.length - 1;
259
+ const target = dependency[item];
260
+ if (target >= 0) {
261
+ const value = locals.get(expression.nodes[target].id);
262
+ if (!excluded[item].has(value)) {
263
+ excluded[item].add(value);
264
+ }
265
+ }
266
+ return dependency[item];
267
+ }
268
+ prefix = item + 1;
269
+ }
270
+ return -2;
271
+ }
161
272
  const id = expression.nodes[index].id;
162
- return candidates[index].some((node) => bind(index + 1, new Map([...locals, [id, node]])));
273
+ const previous = locals.get(id);
274
+ try {
275
+ for (let ordinal = 0; ordinal < candidates[index].length; ordinal++) {
276
+ refresh();
277
+ const node = candidates[index][ordinal];
278
+ if (rejected(index, node)) {
279
+ continue;
280
+ }
281
+ for (const item of resets[index])
282
+ clear(item);
283
+ while (prefix > 0 && dependency[prefix - 1] >= index)
284
+ prefix--;
285
+ locals.set(id, node);
286
+ const result = bind(index + 1);
287
+ if (result === -2 || result < index)
288
+ return result;
289
+ }
290
+ return index - 1;
291
+ }
292
+ finally {
293
+ if (previous === undefined)
294
+ locals.delete(id);
295
+ else
296
+ locals.set(id, previous);
297
+ }
163
298
  };
164
- return bind(0, frame.locals);
299
+ return bind(0) === -2;
165
300
  };
166
301
  return Object.freeze({
167
302
  admit() {
@@ -184,6 +319,44 @@ export function createAuthorityEvaluator(program, snapshot, vocabulary, options
184
319
  },
185
320
  });
186
321
  }
322
+ /** Locals whose assignment can affect the result of this expression. */
323
+ function localDependencies(expression) {
324
+ const result = new Set();
325
+ const addTerm = (term) => {
326
+ if (term.kind === 'local')
327
+ result.add(term.id);
328
+ };
329
+ const visit = (value) => {
330
+ switch (value.op) {
331
+ case 'all':
332
+ case 'any':
333
+ value.predicates.forEach(visit);
334
+ return;
335
+ case 'not':
336
+ visit(value.predicate);
337
+ return;
338
+ case 'as':
339
+ case 'exists':
340
+ visit(value.where);
341
+ return;
342
+ case 'same-node':
343
+ addTerm(value.left);
344
+ addTerm(value.right);
345
+ return;
346
+ case 'related':
347
+ addTerm(value.source);
348
+ addTerm(value.target);
349
+ return;
350
+ case 'instance-of':
351
+ addTerm(value.node);
352
+ return;
353
+ case 'class-authority':
354
+ addTerm(value.identity);
355
+ }
356
+ };
357
+ visit(expression);
358
+ return result;
359
+ }
187
360
  /** Every Identity a binder of the program names, sorted. */
188
361
  export function binderRoots(expressions) {
189
362
  const roots = new Set();
@@ -21,6 +21,12 @@ export interface AuthoritySnapshot {
21
21
  orientation(edge: ClassRef): 'directed' | 'undirected';
22
22
  /** Every live Node the Path reaches; a fixed term requires exactly one. */
23
23
  resolve(path: Path): readonly NodeId[];
24
+ /**
25
+ * Pinned Registry candidates for derived `instance_of`, admitted through `node` before use.
26
+ * An absent hook falls back to `resolve(Path.project(ref))`; an empty result never does.
27
+ * Fixed terms always use `resolve` independently of this projection.
28
+ */
29
+ classProjection?(ref: ClassRef): readonly NodeId[];
24
30
  /** Every live Node, restricted to exact Classes when given. */
25
31
  nodes(classes?: readonly ClassRef[]): readonly NodeId[];
26
32
  }
@@ -87,6 +87,17 @@ export declare const mutationAstSchema: import("zod").ZodObject<{
87
87
  }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
88
88
  kind: import("zod").ZodLiteral<"property.present">;
89
89
  property: import("zod").ZodString;
90
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
91
+ kind: import("zod").ZodLiteral<"property.range">;
92
+ property: import("zod").ZodString;
93
+ lower: import("zod").ZodOptional<import("zod").ZodObject<{
94
+ value: import("zod").ZodUnion<readonly [import("zod").ZodNumber, import("zod").ZodString]>;
95
+ inclusive: import("zod").ZodBoolean;
96
+ }, import("zod/v4/core").$strict>>;
97
+ upper: import("zod").ZodOptional<import("zod").ZodObject<{
98
+ value: import("zod").ZodUnion<readonly [import("zod").ZodNumber, import("zod").ZodString]>;
99
+ inclusive: import("zod").ZodBoolean;
100
+ }, import("zod/v4/core").$strict>>;
90
101
  }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
91
102
  kind: import("zod").ZodLiteral<"identity.equal">;
92
103
  identity: import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodObject<{
@@ -2,6 +2,7 @@ import type { NodeId } from '../../node/index.js';
2
2
  import type { LocalAlias } from '../language/index.js';
3
3
  export type MutationResult = {
4
4
  readonly createdNodes: Readonly<Record<LocalAlias, NodeId>>;
5
+ readonly replayed?: true;
5
6
  };
6
7
  export declare const MutationResult: {
7
8
  decode(input: unknown): MutationResult;
@@ -20,7 +20,8 @@ export function encodeMutationResult(input) {
20
20
  /** Decode unknown JSON into immutable admitted LocalAlias-to-NodeId results. */
21
21
  export function decodeMutationResult(input) {
22
22
  try {
23
- const encoded = decodeWire(mutationResultSchema, portable.accept(input), invalid).createdNodes;
23
+ const admitted = decodeWire(mutationResultSchema, portable.accept(input), invalid);
24
+ const encoded = admitted.createdNodes;
24
25
  const createdNodes = {};
25
26
  for (const binding of Object.keys(encoded).sort()) {
26
27
  const path = `/createdNodes/${escapePointer(binding)}`;
@@ -35,6 +36,7 @@ export function decodeMutationResult(input) {
35
36
  }
36
37
  return Object.freeze({
37
38
  createdNodes: Object.freeze(createdNodes),
39
+ ...(admitted.replayed === true ? { replayed: true } : {}),
38
40
  });
39
41
  }
40
42
  catch (error) {
@@ -1,3 +1,4 @@
1
1
  export declare const mutationResultSchema: import("zod").ZodObject<{
2
2
  createdNodes: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodString>;
3
+ replayed: import("zod").ZodOptional<import("zod").ZodLiteral<true>>;
3
4
  }, import("zod/v4/core").$strict>;
@@ -1,4 +1,7 @@
1
- import { record, strictObject, string } from 'zod';
1
+ import { literal, record, strictObject, string } from 'zod';
2
2
  const text = string().min(1);
3
3
  const binding = string().min(1).max(64);
4
- export const mutationResultSchema = strictObject({ createdNodes: record(binding, text) });
4
+ export const mutationResultSchema = strictObject({
5
+ createdNodes: record(binding, text),
6
+ replayed: literal(true).optional(),
7
+ });
@@ -1,6 +1,26 @@
1
1
  const encoder = new TextEncoder();
2
2
  /** Compare canonical Node identity by unsigned lexicographic UTF-8 byte order. */
3
3
  export function compareNodeIds(left, right) {
4
+ // UTF-8 preserves code point order, and identical UTF-16 prefixes encode identically. Below the
5
+ // surrogate block, the first differing code unit therefore decides the UTF-8 byte order.
6
+ const length = Math.min(left.length, right.length);
7
+ let index = 0;
8
+ while (index < length && left.charCodeAt(index) === right.charCodeAt(index))
9
+ index++;
10
+ if (index < length) {
11
+ const a = left.charCodeAt(index);
12
+ const b = right.charCodeAt(index);
13
+ if (a < 0xd800 && b < 0xd800)
14
+ return a < b ? -1 : 1;
15
+ }
16
+ else {
17
+ const next = (left.length > right.length ? left : right).charCodeAt(index);
18
+ if (Number.isNaN(next) || next < 0xdc00 || next > 0xdfff)
19
+ return Math.sign(left.length - right.length);
20
+ }
21
+ return compareUtf8(left, right);
22
+ }
23
+ function compareUtf8(left, right) {
4
24
  const a = encoder.encode(left);
5
25
  const b = encoder.encode(right);
6
26
  const length = Math.min(a.length, b.length);
@@ -40,6 +40,33 @@ export function Property(input) {
40
40
  isPresent() {
41
41
  return Object.freeze({ kind: 'property.present', property: key });
42
42
  },
43
+ greater: (value) => range(key, bound(value, false, 'lower'), undefined),
44
+ greaterOrEqual: (value) => range(key, bound(value, true, 'lower'), undefined),
45
+ less: (value) => range(key, undefined, bound(value, false, 'upper')),
46
+ lessOrEqual: (value) => range(key, undefined, bound(value, true, 'upper')),
47
+ between(lower, upper, bounds = {}) {
48
+ if (typeof lower !== typeof upper) {
49
+ invalid('/predicate/upper/value', 'Range bounds must have one kind');
50
+ }
51
+ return range(key, bound(lower, bounds.lower !== 'exclusive', 'lower'), bound(upper, bounds.upper !== 'exclusive', 'upper'));
52
+ },
53
+ });
54
+ }
55
+ function bound(value, inclusive, side) {
56
+ if (typeof value !== 'number' && typeof value !== 'string') {
57
+ invalid(`/predicate/${side}/value`, 'Range bound must be a number or a text');
58
+ }
59
+ return Object.freeze({
60
+ value: canonicalValue(value, `/predicate/${side}/value`),
61
+ inclusive,
62
+ });
63
+ }
64
+ function range(property, lower, upper) {
65
+ return Object.freeze({
66
+ kind: 'property.range',
67
+ property,
68
+ ...(lower === undefined ? {} : { lower }),
69
+ ...(upper === undefined ? {} : { upper }),
43
70
  });
44
71
  }
45
72
  /** Primary persistent Query V6 authoring entry point. */
@@ -190,12 +217,12 @@ function appendFilter(state, input, defaultBinding) {
190
217
  ...(state.edge === undefined ? {} : { edge: state.edge }),
191
218
  });
192
219
  }
193
- function canonicalValue(input) {
220
+ function canonicalValue(input, path = '/predicate/value') {
194
221
  try {
195
222
  return freezeValue(portable.json.decode(portable.json.encode(input)));
196
223
  }
197
224
  catch (cause) {
198
- invalid('/predicate/value', 'Invalid portable equality value', cause);
225
+ invalid(path, 'Invalid portable Property value', cause);
199
226
  }
200
227
  }
201
228
  function freezeValue(input) {
@@ -1,7 +1,7 @@
1
1
  import type * as dslApi from '@astrale-os/kernel-dsl/v1';
2
2
  import type * as portable from '@astrale-os/kernel-dsl/value';
3
3
  import type { NodeTarget } from '../../path/index.js';
4
- import type { EdgeBinding, NodeBinding, QueryBinding, QueryDirection, QueryEdgeIdentityPredicate, QueryEdgeProjection, QueryNodeIdentityPredicate, QueryNodeProjection, QueryPropertyOrder, QueryPropertyPredicate, QueryPropertyEqualPredicate, QueryPropertyPresentPredicate } from '../language/index.js';
4
+ import type { EdgeBinding, NodeBinding, QueryBinding, QueryDirection, QueryEdgeIdentityPredicate, QueryEdgeProjection, QueryNodeIdentityPredicate, QueryNodeProjection, QueryPropertyOrder, QueryPropertyPredicate, QueryPropertyEqualPredicate, QueryPropertyPresentPredicate, QueryPropertyRangeOf } from '../language/index.js';
5
5
  type NonEmpty<Value> = readonly [Value, ...Value[]];
6
6
  export type QueryClassInput<Kind extends 'node' | 'edge' = 'node' | 'edge'> = dslApi.ClassRef | dslApi.ClassKey | Readonly<{
7
7
  readonly ref: dslApi.ClassRef;
@@ -55,9 +55,28 @@ export type QueryCurrentNodeFilterInput = (Omit<QueryClassFilterInput, 'binding'
55
55
  }) | Extract<QueryIdentityFilterInput, {
56
56
  readonly binding: EdgeBinding;
57
57
  }>;
58
+ /** Whether each end of `between` includes its bound; both are inclusive by default. */
59
+ export interface QueryRangeBoundsInput {
60
+ readonly lower?: 'inclusive' | 'exclusive';
61
+ readonly upper?: 'inclusive' | 'exclusive';
62
+ }
63
+ /**
64
+ * Property predicate leaves. The range forms are one canonical `property.range` predicate: a
65
+ * number range compares numerically, a text range in code-point order.
66
+ */
58
67
  export interface QueryPropertyPredicateBuilder {
59
68
  equals(value: portable.Value): QueryPropertyEqualPredicate;
60
69
  isPresent(): QueryPropertyPresentPredicate;
70
+ greater(value: number): QueryPropertyRangeOf<number>;
71
+ greater(value: string): QueryPropertyRangeOf<string>;
72
+ greaterOrEqual(value: number): QueryPropertyRangeOf<number>;
73
+ greaterOrEqual(value: string): QueryPropertyRangeOf<string>;
74
+ less(value: number): QueryPropertyRangeOf<number>;
75
+ less(value: string): QueryPropertyRangeOf<string>;
76
+ lessOrEqual(value: number): QueryPropertyRangeOf<number>;
77
+ lessOrEqual(value: string): QueryPropertyRangeOf<string>;
78
+ between(lower: number, upper: number, bounds?: QueryRangeBoundsInput): QueryPropertyRangeOf<number>;
79
+ between(lower: string, upper: string, bounds?: QueryRangeBoundsInput): QueryPropertyRangeOf<string>;
61
80
  }
62
81
  export interface QueryExpandInput {
63
82
  readonly from: NodeBinding;
@@ -1,11 +1,11 @@
1
1
  /** Stable flat facade over Query language, authoring, result, and reference semantics. */
2
2
  export { Property, Query } from './authoring/index.js';
3
- export type { EdgeQueryBuilder, ExpandedQueryBuilder, NodeQueryBuilder, QueryCurrentNodeExpandInput, QueryCurrentNodeFilterInput, QueryClassInput, QueryEdgeClassInput, QueryEdgeInput, QueryClassFilterInput, QueryEdgeSourceInput, QueryEdgeGraphSelectInput, QueryEdgeSelectInput, QueryExpandInput, QueryFilterInput, QueryIdentityFilterInput, QueryNodeClassInput, QueryNodeGraphSelectInput, QueryNodeInput, QueryNodeSelectInput, QueryNodeSourceInput, QueryPropertyFilterInput, QueryPropertyPredicateBuilder, QuerySelectInput, QuerySourceInput, } from './authoring/index.js';
3
+ export type { EdgeQueryBuilder, ExpandedQueryBuilder, NodeQueryBuilder, QueryCurrentNodeExpandInput, QueryCurrentNodeFilterInput, QueryClassInput, QueryEdgeClassInput, QueryEdgeInput, QueryClassFilterInput, QueryEdgeSourceInput, QueryEdgeGraphSelectInput, QueryEdgeSelectInput, QueryExpandInput, QueryFilterInput, QueryIdentityFilterInput, QueryNodeClassInput, QueryNodeGraphSelectInput, QueryNodeInput, QueryNodeSelectInput, QueryNodeSourceInput, QueryPropertyFilterInput, QueryPropertyPredicateBuilder, QueryRangeBoundsInput, QuerySelectInput, QuerySourceInput, } from './authoring/index.js';
4
4
  export { QueryAST, QueryASTDecodeError } from './language/index.js';
5
- export type { EdgeBinding, NodeBinding, QueryBinding, QueryClassFilter, QueryClassPredicate, QueryClassSourceTerm, QueryClassSatisfiesPredicate, QueryClassEqualPredicate, QueryDirection, QueryEdgeSource, QueryEdgeSourceTerm, QueryEdgeSelect, QueryEdgeAST, QueryEdgeIdentityPredicate, QueryEdgeProjection, QueryExpand, QueryFingerprint, QueryIdentityFilter, QueryIdentityPredicate, QueryGraphSelect, QueryNodeAST, QueryNodeIdentityPredicate, QueryNodeProjection, QueryNodeSelect, QueryNodeSource, QueryNodeSourceTerm, QueryNodeTerminalSelect, QueryEdgeTerminalSelect, QueryOrderDirection, QueryPathSourceTerm, QueryPredicate, QueryProjectionShape, QueryPropertyEqualPredicate, QueryPropertyFilter, QueryPropertyOrder, QueryPropertyPredicate, QueryPropertyPresentPredicate, QuerySelect, QuerySingleSourceClassOf, QuerySource, QuerySourceClassesOf, QuerySourceTerm, QueryStep, QueryStructuralLimits, QueryUnrankedPlacement, } from './language/index.js';
5
+ export type { EdgeBinding, NodeBinding, QueryBinding, QueryClassFilter, QueryClassPredicate, QueryClassSourceTerm, QueryClassSatisfiesPredicate, QueryClassEqualPredicate, QueryDirection, QueryEdgeSource, QueryEdgeSourceTerm, QueryEdgeSelect, QueryEdgeAST, QueryEdgeIdentityPredicate, QueryEdgeProjection, QueryExpand, QueryFingerprint, QueryIdentityFilter, QueryIdentityPredicate, QueryGraphSelect, QueryNodeAST, QueryNodeIdentityPredicate, QueryNodeProjection, QueryNodeSelect, QueryNodeSource, QueryNodeSourceTerm, QueryNodeTerminalSelect, QueryEdgeTerminalSelect, QueryOrderDirection, QueryPathSourceTerm, QueryPredicate, QueryProjectionShape, QueryPropertyEqualPredicate, QueryPropertyFilter, QueryPropertyOrder, QueryPropertyPredicate, QueryPropertyPresentPredicate, QueryPropertyRangeOf, QueryPropertyRangePredicate, QueryRangeBound, QueryRangeValue, QuerySelect, QuerySingleSourceClassOf, QuerySource, QuerySourceClassesOf, QuerySourceTerm, QueryStep, QueryStructuralLimits, QueryUnrankedPlacement, } from './language/index.js';
6
6
  export { QueryResult, QueryResultDecodeError } from './result/index.js';
7
7
  export type { QueryEdgeComponentFor, QueryEdgeGraphResult, QueryEdgeItemFor, QueryEdgeResult, QueryGraphResult, QueryNodeComponentFor, QueryNodeGraphResult, QueryNodeItemFor, QueryNodeReference, QueryNodeResult, QueryResultFor, QueryResultForSelect, QuerySelection, QuerySelectionFor, } from './result/index.js';
8
- export { compareQueryIdentity, compareQueryRank, compareQueryText, compareQueryValue, } from './order/index.js';
8
+ export { compareQueryIdentity, compareQueryRank, compareQueryText, compareQueryValue, queryRangeContains, } from './order/index.js';
9
9
  export type { QueryRank, QueryRankIdentity, QueryRankOrder, QueryRankValue } from './order/index.js';
10
10
  export { QueryReference, QueryReferenceError } from './reference/index.js';
11
11
  export type { QueryReferenceContext, QueryReferenceClassClosure, QueryReferenceEvaluation, QueryReferenceFrontier, QueryReferenceIdentity, QueryReferenceOptions, QueryReferencePathWitness, QueryReferenceProperty, QueryReferenceTrace, } from './reference/index.js';
@@ -2,5 +2,5 @@
2
2
  export { Property, Query } from './authoring/index.js';
3
3
  export { QueryAST, QueryASTDecodeError } from './language/index.js';
4
4
  export { QueryResult, QueryResultDecodeError } from './result/index.js';
5
- export { compareQueryIdentity, compareQueryRank, compareQueryText, compareQueryValue, } from './order/index.js';
5
+ export { compareQueryIdentity, compareQueryRank, compareQueryText, compareQueryValue, queryRangeContains, } from './order/index.js';
6
6
  export { QueryReference, QueryReferenceError } from './reference/index.js';
@@ -194,6 +194,21 @@ function decodePredicate(input, path, binding) {
194
194
  if (input.kind === 'property.present') {
195
195
  return Object.freeze({ kind: 'property.present', property });
196
196
  }
197
+ if (input.kind === 'property.range') {
198
+ const lower = input.lower === undefined ? undefined : Object.freeze({ ...input.lower });
199
+ const upper = input.upper === undefined ? undefined : Object.freeze({ ...input.upper });
200
+ if (lower === undefined && upper === undefined)
201
+ invalid(path, 'Range requires a bound');
202
+ if (lower !== undefined && upper !== undefined && typeof lower.value !== typeof upper.value) {
203
+ invalid(`${path}/upper/value`, 'Range bounds must have one kind');
204
+ }
205
+ return Object.freeze({
206
+ kind: 'property.range',
207
+ property,
208
+ ...(lower === undefined ? {} : { lower }),
209
+ ...(upper === undefined ? {} : { upper }),
210
+ });
211
+ }
197
212
  return Object.freeze({
198
213
  kind: 'property.equal',
199
214
  property,
@@ -122,6 +122,14 @@ function predicateValue(predicate) {
122
122
  if (predicate.kind === 'property.present') {
123
123
  return { kind: predicate.kind, property: predicate.property };
124
124
  }
125
+ if (predicate.kind === 'property.range') {
126
+ return {
127
+ kind: predicate.kind,
128
+ property: predicate.property,
129
+ ...(predicate.lower === undefined ? {} : { lower: { ...predicate.lower } }),
130
+ ...(predicate.upper === undefined ? {} : { upper: { ...predicate.upper } }),
131
+ };
132
+ }
125
133
  if (predicate.kind === 'identity.equal') {
126
134
  return {
127
135
  kind: predicate.kind,
@@ -76,7 +76,25 @@ export interface QueryPropertyPresentPredicate {
76
76
  readonly kind: 'property.present';
77
77
  readonly property: PropertyKey;
78
78
  }
79
- export type QueryPropertyPredicate = QueryPropertyEqualPredicate | QueryPropertyPresentPredicate;
79
+ /** A range bound value: a finite number or a text, compared in Core order. */
80
+ export type QueryRangeValue = number | string;
81
+ /** One end of a range; an exclusive bound excludes a value equal to it. */
82
+ export interface QueryRangeBound<Value extends QueryRangeValue = QueryRangeValue> {
83
+ readonly value: Value;
84
+ readonly inclusive: boolean;
85
+ }
86
+ /**
87
+ * A stored value of the bounds' kind within at least one and at most two bounds: numeric order for
88
+ * numbers, code-point order for texts. Both bounds have one kind. Any other value never passes.
89
+ */
90
+ export type QueryPropertyRangePredicate = QueryPropertyRangeOf<number> | QueryPropertyRangeOf<string>;
91
+ export interface QueryPropertyRangeOf<Value extends QueryRangeValue> {
92
+ readonly kind: 'property.range';
93
+ readonly property: PropertyKey;
94
+ readonly lower?: QueryRangeBound<Value>;
95
+ readonly upper?: QueryRangeBound<Value>;
96
+ }
97
+ export type QueryPropertyPredicate = QueryPropertyEqualPredicate | QueryPropertyPresentPredicate | QueryPropertyRangePredicate;
80
98
  export interface QueryNodeIdentityPredicate {
81
99
  readonly kind: 'identity.equal';
82
100
  readonly identity: NodeId;
@@ -56,6 +56,17 @@ export declare const queryAstSchema: import("zod").ZodObject<{
56
56
  }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
57
57
  kind: import("zod").ZodLiteral<"property.present">;
58
58
  property: import("zod").ZodString;
59
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
60
+ kind: import("zod").ZodLiteral<"property.range">;
61
+ property: import("zod").ZodString;
62
+ lower: import("zod").ZodOptional<import("zod").ZodObject<{
63
+ value: import("zod").ZodUnion<readonly [import("zod").ZodNumber, import("zod").ZodString]>;
64
+ inclusive: import("zod").ZodBoolean;
65
+ }, import("zod/v4/core").$strict>>;
66
+ upper: import("zod").ZodOptional<import("zod").ZodObject<{
67
+ value: import("zod").ZodUnion<readonly [import("zod").ZodNumber, import("zod").ZodString]>;
68
+ inclusive: import("zod").ZodBoolean;
69
+ }, import("zod/v4/core").$strict>>;
59
70
  }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
60
71
  kind: import("zod").ZodLiteral<"identity.equal">;
61
72
  identity: import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodObject<{
@@ -1,4 +1,4 @@
1
- import { array, discriminatedUnion, enum as enumeration, literal, strictObject, string, union, unknown as unknownSchema, } from 'zod';
1
+ import { array, boolean, discriminatedUnion, enum as enumeration, literal, number, strictObject, string, union, unknown as unknownSchema, } from 'zod';
2
2
  import { QUERY_AST_FORMAT, QUERY_AST_LIMITS, QUERY_AST_VERSION } from './model.js';
3
3
  const text = string().min(1);
4
4
  const binding = text.max(64);
@@ -24,11 +24,18 @@ const source = discriminatedUnion('kind', [
24
24
  bindings: strictObject({ source: binding, edge: binding, target: binding }),
25
25
  }),
26
26
  ]);
27
+ const rangeBound = strictObject({ value: union([number(), string()]), inclusive: boolean() });
27
28
  const predicate = discriminatedUnion('kind', [
28
29
  strictObject({ kind: literal('class.satisfies'), class: classRef }),
29
30
  strictObject({ kind: literal('class.equal'), class: classRef }),
30
31
  strictObject({ kind: literal('property.equal'), property: text, value: unknownSchema() }),
31
32
  strictObject({ kind: literal('property.present'), property: text }),
33
+ strictObject({
34
+ kind: literal('property.range'),
35
+ property: text,
36
+ lower: rangeBound.optional(),
37
+ upper: rangeBound.optional(),
38
+ }),
32
39
  strictObject({
33
40
  kind: literal('identity.equal'),
34
41
  identity: union([text, strictObject({ source: text, target: text, class: text })]),
@@ -1,7 +1,8 @@
1
1
  import type { OrderingKind } from '@astrale-os/kernel-dsl/v1/language';
2
+ import type * as portable from '@astrale-os/kernel-dsl/value';
2
3
  import type { EdgeKey } from '../../edge/index.js';
3
4
  import type { NodeId } from '../../node/index.js';
4
- import type { QueryOrderDirection, QueryUnrankedPlacement } from '../language/index.js';
5
+ import type { QueryOrderDirection, QueryPropertyRangePredicate, QueryUnrankedPlacement } from '../language/index.js';
5
6
  /** The identity of one selected fact: a Node's NodeId or an Edge's complete EdgeKey. */
6
7
  export type QueryRankIdentity = NodeId | EdgeKey;
7
8
  /** A scalar ordering value of one proven kind; an instant is its canonical text. */
@@ -42,5 +43,11 @@ export declare function compareQueryValue(left: QueryRankValue, right: QueryRank
42
43
  * exactly that range.
43
44
  */
44
45
  export declare function compareQueryText(left: string, right: string): number;
46
+ /**
47
+ * Whether one stored value lies in a Property range: it has the kind of the bounds, a number in
48
+ * numeric order or a text in code-point order, and every present bound holds. A value of any other
49
+ * kind, an absent value included, is never in the range; this is never an error.
50
+ */
51
+ export declare function queryRangeContains(range: Pick<QueryPropertyRangePredicate, 'lower' | 'upper'>, value: portable.Value | undefined): boolean;
45
52
  /** Identity order: NodeId byte order, or EdgeKey (source, target, ClassKey) tuple order. */
46
53
  export declare function compareQueryIdentity(left: QueryRankIdentity, right: QueryRankIdentity): number;
@@ -49,6 +49,26 @@ export function compareQueryText(left, right) {
49
49
  }
50
50
  return Math.sign(left.length - right.length);
51
51
  }
52
+ /**
53
+ * Whether one stored value lies in a Property range: it has the kind of the bounds, a number in
54
+ * numeric order or a text in code-point order, and every present bound holds. A value of any other
55
+ * kind, an absent value included, is never in the range; this is never an error.
56
+ */
57
+ export function queryRangeContains(range, value) {
58
+ const kind = (range.lower ?? range.upper)?.value;
59
+ if (typeof value !== typeof kind || (typeof value !== 'number' && typeof value !== 'string')) {
60
+ return false;
61
+ }
62
+ const holds = (bound, sign) => {
63
+ if (bound === undefined)
64
+ return true;
65
+ const compared = typeof value === 'number'
66
+ ? Math.sign(value - bound.value)
67
+ : compareQueryText(value, bound.value);
68
+ return compared === 0 ? bound.inclusive : compared === sign;
69
+ };
70
+ return holds(range.lower, 1) && holds(range.upper, -1);
71
+ }
52
72
  /** Identity order: NodeId byte order, or EdgeKey (source, target, ClassKey) tuple order. */
53
73
  export function compareQueryIdentity(left, right) {
54
74
  if (typeof left === 'string' && typeof right === 'string')
@@ -6,7 +6,7 @@ import { GraphData } from '../../graph/index.js';
6
6
  import { NodeId as admitNodeId } from '../../node/index.js';
7
7
  import { compareNodeIds } from '../../node/index.js';
8
8
  import { encodeQueryAST, QueryASTDecodeError } from '../language/index.js';
9
- import { compareQueryRank } from '../order/index.js';
9
+ import { compareQueryRank, queryRangeContains } from '../order/index.js';
10
10
  import { decodeQueryResult } from '../result/index.js';
11
11
  import { QueryReferenceError } from './error.js';
12
12
  /** Independent backend-neutral executable Query V6 row algebra. */
@@ -142,8 +142,10 @@ function evaluate(ast, context, options) {
142
142
  if (!Object.hasOwn(value.value.props, predicate.property)) {
143
143
  return false;
144
144
  }
145
- return (predicate.kind === 'property.present' ||
146
- portable.equal(value.value.props[predicate.property], predicate.value));
145
+ const stored = value.value.props[predicate.property];
146
+ if (predicate.kind === 'property.range')
147
+ return queryRangeContains(predicate, stored);
148
+ return predicate.kind === 'property.present' || portable.equal(stored, predicate.value);
147
149
  });
148
150
  }
149
151
  stepRows.push(rows.length);
@@ -7923,6 +7923,17 @@ declare const KernelDefinitions: {
7923
7923
  } | {
7924
7924
  kind: "property.present";
7925
7925
  property: string;
7926
+ } | {
7927
+ kind: "property.range";
7928
+ property: string;
7929
+ lower?: {
7930
+ value: string | number;
7931
+ inclusive: boolean;
7932
+ } | undefined;
7933
+ upper?: {
7934
+ value: string | number;
7935
+ inclusive: boolean;
7936
+ } | undefined;
7926
7937
  } | {
7927
7938
  kind: "identity.equal";
7928
7939
  identity: string | {
@@ -8200,6 +8211,17 @@ declare const KernelDefinitions: {
8200
8211
  } | {
8201
8212
  kind: "property.present";
8202
8213
  property: string;
8214
+ } | {
8215
+ kind: "property.range";
8216
+ property: string;
8217
+ lower?: {
8218
+ value: string | number;
8219
+ inclusive: boolean;
8220
+ } | undefined;
8221
+ upper?: {
8222
+ value: string | number;
8223
+ inclusive: boolean;
8224
+ } | undefined;
8203
8225
  } | {
8204
8226
  kind: "identity.equal";
8205
8227
  identity: string | {
@@ -8332,10 +8354,12 @@ declare const KernelDefinitions: {
8332
8354
  origin: string;
8333
8355
  revision: string;
8334
8356
  }[] | undefined;
8357
+ idempotencyKey?: string | undefined;
8335
8358
  }, {
8336
8359
  readonly mode: 'value';
8337
8360
  readonly value: {
8338
8361
  createdNodes: Record<string, string>;
8362
+ replayed?: true | undefined;
8339
8363
  };
8340
8364
  }, "authorized", false, false, undefined>>;
8341
8365
  register: builder.Function<builder.CallableProjection<{
@@ -8759,21 +8783,24 @@ export declare const AuthorityRelations: Readonly<{
8759
8783
  };
8760
8784
  }>;
8761
8785
  /** Exact authorized Kernel Functions for which pristine Root receives direct can_use authority. */
8762
- export declare const KernelRootFunctions: readonly ((import("@astrale-os/kernel-dsl/v1").ResolvedFunction<{
8763
- node: string;
8764
- property: string;
8765
- } | {
8766
- slots: {
8767
- node: string;
8768
- property: string;
8769
- }[];
8770
- }, {
8771
- readonly mode: 'binary';
8786
+ export declare const KernelRootFunctions: readonly ((import("@astrale-os/kernel-dsl/v1").ResolvedFunction<import("@astrale-os/kernel-dsl/v1").BinaryInputProjection<{
8787
+ mediaType: string;
8788
+ }>, {
8789
+ readonly mode: 'value';
8790
+ readonly value: {
8791
+ receipt: string;
8792
+ ref: {
8793
+ digest: string;
8794
+ mediaType: string;
8795
+ size: number;
8796
+ };
8797
+ expiresAt: string;
8798
+ };
8772
8799
  }, "authorized", import("@astrale-os/kernel-dsl/v1").PolicyCheckExpression<import("@astrale-os/kernel-dsl/v1").PolicyRef, import("@astrale-os/kernel-dsl/v1/language").PolicyCheckObject>> & {
8773
- readonly ref: import("@astrale-os/kernel-dsl/v1").FunctionRef<"download"> & {
8800
+ readonly ref: import("@astrale-os/kernel-dsl/v1").FunctionRef<"upload"> & {
8774
8801
  readonly origin: "kernel.astrale.ai";
8775
8802
  };
8776
- readonly key: "kernel.astrale.ai:function.download";
8803
+ readonly key: "kernel.astrale.ai:function.upload";
8777
8804
  readonly execution: undefined;
8778
8805
  }) | (import("@astrale-os/kernel-dsl/v1").ResolvedFunction<{
8779
8806
  operation: string;
@@ -8808,39 +8835,6 @@ export declare const KernelRootFunctions: readonly ((import("@astrale-os/kernel-
8808
8835
  };
8809
8836
  readonly key: "kernel.astrale.ai:function.install";
8810
8837
  readonly execution: undefined;
8811
- }) | (import("@astrale-os/kernel-dsl/v1").ResolvedFunction<{
8812
- invocation?: {
8813
- source: string;
8814
- id: string;
8815
- } | undefined;
8816
- topics?: {
8817
- exact?: string[] | undefined;
8818
- prefixes?: string[] | undefined;
8819
- } | undefined;
8820
- principal?: string | undefined;
8821
- since?: string | undefined;
8822
- until?: string | undefined;
8823
- cursor?: string | undefined;
8824
- limit?: number | undefined;
8825
- }, {
8826
- readonly mode: 'value';
8827
- readonly value: {
8828
- records: unknown[];
8829
- frontier: {
8830
- id: string;
8831
- first?: number | undefined;
8832
- committed: number;
8833
- durable: number;
8834
- };
8835
- cursor?: string | undefined;
8836
- gap?: unknown;
8837
- };
8838
- }, "authorized", import("@astrale-os/kernel-dsl/v1").PolicyCheckExpression<import("@astrale-os/kernel-dsl/v1").PolicyRef, import("@astrale-os/kernel-dsl/v1/language").PolicyCheckObject>> & {
8839
- readonly ref: import("@astrale-os/kernel-dsl/v1").FunctionRef<"journal"> & {
8840
- readonly origin: "kernel.astrale.ai";
8841
- };
8842
- readonly key: "kernel.astrale.ai:function.journal";
8843
- readonly execution: undefined;
8844
8838
  }) | (import("@astrale-os/kernel-dsl/v1").ResolvedFunction<{
8845
8839
  ast: {
8846
8840
  format: "astrale.graph.mutation";
@@ -8928,6 +8922,17 @@ export declare const KernelRootFunctions: readonly ((import("@astrale-os/kernel-
8928
8922
  } | {
8929
8923
  kind: "property.present";
8930
8924
  property: string;
8925
+ } | {
8926
+ kind: "property.range";
8927
+ property: string;
8928
+ lower?: {
8929
+ value: string | number;
8930
+ inclusive: boolean;
8931
+ } | undefined;
8932
+ upper?: {
8933
+ value: string | number;
8934
+ inclusive: boolean;
8935
+ } | undefined;
8931
8936
  } | {
8932
8937
  kind: "identity.equal";
8933
8938
  identity: string | {
@@ -9060,10 +9065,12 @@ export declare const KernelRootFunctions: readonly ((import("@astrale-os/kernel-
9060
9065
  origin: string;
9061
9066
  revision: string;
9062
9067
  }[] | undefined;
9068
+ idempotencyKey?: string | undefined;
9063
9069
  }, {
9064
9070
  readonly mode: 'value';
9065
9071
  readonly value: {
9066
9072
  createdNodes: Record<string, string>;
9073
+ replayed?: true | undefined;
9067
9074
  };
9068
9075
  }, "authorized", import("@astrale-os/kernel-dsl/v1").PolicyCheckExpression<import("@astrale-os/kernel-dsl/v1").PolicyRef, import("@astrale-os/kernel-dsl/v1/language").PolicyCheckObject>> & {
9069
9076
  readonly ref: import("@astrale-os/kernel-dsl/v1").FunctionRef<"mutate"> & {
@@ -9129,6 +9136,17 @@ export declare const KernelRootFunctions: readonly ((import("@astrale-os/kernel-
9129
9136
  } | {
9130
9137
  kind: "property.present";
9131
9138
  property: string;
9139
+ } | {
9140
+ kind: "property.range";
9141
+ property: string;
9142
+ lower?: {
9143
+ value: string | number;
9144
+ inclusive: boolean;
9145
+ } | undefined;
9146
+ upper?: {
9147
+ value: string | number;
9148
+ inclusive: boolean;
9149
+ } | undefined;
9132
9150
  } | {
9133
9151
  kind: "identity.equal";
9134
9152
  identity: string | {
@@ -9379,24 +9397,54 @@ export declare const KernelRootFunctions: readonly ((import("@astrale-os/kernel-
9379
9397
  };
9380
9398
  readonly key: "kernel.astrale.ai:function.uninstall";
9381
9399
  readonly execution: undefined;
9382
- }) | (import("@astrale-os/kernel-dsl/v1").ResolvedFunction<import("@astrale-os/kernel-dsl/v1").BinaryInputProjection<{
9383
- mediaType: string;
9384
- }>, {
9400
+ }) | (import("@astrale-os/kernel-dsl/v1").ResolvedFunction<{
9401
+ invocation?: {
9402
+ source: string;
9403
+ id: string;
9404
+ } | undefined;
9405
+ topics?: {
9406
+ exact?: string[] | undefined;
9407
+ prefixes?: string[] | undefined;
9408
+ } | undefined;
9409
+ principal?: string | undefined;
9410
+ since?: string | undefined;
9411
+ until?: string | undefined;
9412
+ cursor?: string | undefined;
9413
+ limit?: number | undefined;
9414
+ }, {
9385
9415
  readonly mode: 'value';
9386
9416
  readonly value: {
9387
- receipt: string;
9388
- ref: {
9389
- digest: string;
9390
- mediaType: string;
9391
- size: number;
9417
+ records: unknown[];
9418
+ frontier: {
9419
+ id: string;
9420
+ first?: number | undefined;
9421
+ committed: number;
9422
+ durable: number;
9392
9423
  };
9393
- expiresAt: string;
9424
+ cursor?: string | undefined;
9425
+ gap?: unknown;
9394
9426
  };
9395
9427
  }, "authorized", import("@astrale-os/kernel-dsl/v1").PolicyCheckExpression<import("@astrale-os/kernel-dsl/v1").PolicyRef, import("@astrale-os/kernel-dsl/v1/language").PolicyCheckObject>> & {
9396
- readonly ref: import("@astrale-os/kernel-dsl/v1").FunctionRef<"upload"> & {
9428
+ readonly ref: import("@astrale-os/kernel-dsl/v1").FunctionRef<"journal"> & {
9397
9429
  readonly origin: "kernel.astrale.ai";
9398
9430
  };
9399
- readonly key: "kernel.astrale.ai:function.upload";
9431
+ readonly key: "kernel.astrale.ai:function.journal";
9432
+ readonly execution: undefined;
9433
+ }) | (import("@astrale-os/kernel-dsl/v1").ResolvedFunction<{
9434
+ node: string;
9435
+ property: string;
9436
+ } | {
9437
+ slots: {
9438
+ node: string;
9439
+ property: string;
9440
+ }[];
9441
+ }, {
9442
+ readonly mode: 'binary';
9443
+ }, "authorized", import("@astrale-os/kernel-dsl/v1").PolicyCheckExpression<import("@astrale-os/kernel-dsl/v1").PolicyRef, import("@astrale-os/kernel-dsl/v1/language").PolicyCheckObject>> & {
9444
+ readonly ref: import("@astrale-os/kernel-dsl/v1").FunctionRef<"download"> & {
9445
+ readonly origin: "kernel.astrale.ai";
9446
+ };
9447
+ readonly key: "kernel.astrale.ai:function.download";
9400
9448
  readonly execution: undefined;
9401
9449
  }) | (import("@astrale-os/kernel-dsl/v1").ResolvedMethod<{
9402
9450
  iss: string;
@@ -9425,17 +9473,6 @@ export declare const KernelRootFunctions: readonly ((import("@astrale-os/kernel-
9425
9473
  readonly name: "whois";
9426
9474
  readonly executable: true;
9427
9475
  readonly execution: undefined;
9428
- }) | (import("@astrale-os/kernel-dsl/v1").ResolvedMethod<{
9429
- audience?: string | undefined;
9430
- ttlSeconds: number;
9431
- identity: string;
9432
- }, {
9433
- readonly mode: 'value';
9434
- readonly value: string;
9435
- }, true, false, "authorized", import("@astrale-os/kernel-dsl/v1").PolicyCheckExpression<import("@astrale-os/kernel-dsl/v1").PolicyRef, import("@astrale-os/kernel-dsl/v1/language").PolicyCheckObject>, "kernel.astrale.ai:class.Identity.method.impersonate"> & {
9436
- readonly name: "impersonate";
9437
- readonly executable: true;
9438
- readonly execution: undefined;
9439
9476
  }) | (import("@astrale-os/kernel-dsl/v1").ResolvedMethod<{
9440
9477
  target: string;
9441
9478
  }, {
@@ -9468,6 +9505,17 @@ export declare const KernelRootFunctions: readonly ((import("@astrale-os/kernel-
9468
9505
  readonly name: "resolve";
9469
9506
  readonly executable: true;
9470
9507
  readonly execution: undefined;
9508
+ }) | (import("@astrale-os/kernel-dsl/v1").ResolvedMethod<{
9509
+ audience?: string | undefined;
9510
+ ttlSeconds: number;
9511
+ identity: string;
9512
+ }, {
9513
+ readonly mode: 'value';
9514
+ readonly value: string;
9515
+ }, true, false, "authorized", import("@astrale-os/kernel-dsl/v1").PolicyCheckExpression<import("@astrale-os/kernel-dsl/v1").PolicyRef, import("@astrale-os/kernel-dsl/v1/language").PolicyCheckObject>, "kernel.astrale.ai:class.Identity.method.impersonate"> & {
9516
+ readonly name: "impersonate";
9517
+ readonly executable: true;
9518
+ readonly execution: undefined;
9471
9519
  }))[];
9472
9520
  export { AuthorityOperationOrder, AuthorityOperations, operationOf } from '../authority/index.js';
9473
9521
  export type { AuthorityOperation, AuthorityRelation } from '../authority/index.js';
@@ -85,6 +85,17 @@ export declare const mutateInput: import("zod").ZodObject<{
85
85
  }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
86
86
  kind: import("zod").ZodLiteral<"property.present">;
87
87
  property: import("zod").ZodString;
88
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
89
+ kind: import("zod").ZodLiteral<"property.range">;
90
+ property: import("zod").ZodString;
91
+ lower: import("zod").ZodOptional<import("zod").ZodObject<{
92
+ value: import("zod").ZodUnion<readonly [import("zod").ZodNumber, import("zod").ZodString]>;
93
+ inclusive: import("zod").ZodBoolean;
94
+ }, import("zod/v4/core").$strict>>;
95
+ upper: import("zod").ZodOptional<import("zod").ZodObject<{
96
+ value: import("zod").ZodUnion<readonly [import("zod").ZodNumber, import("zod").ZodString]>;
97
+ inclusive: import("zod").ZodBoolean;
98
+ }, import("zod/v4/core").$strict>>;
88
99
  }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
89
100
  kind: import("zod").ZodLiteral<"identity.equal">;
90
101
  identity: import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodObject<{
@@ -251,7 +262,9 @@ export declare const mutateInput: import("zod").ZodObject<{
251
262
  origin: import("zod").ZodString;
252
263
  revision: import("zod").ZodString;
253
264
  }, import("zod/v4/core").$strict>>>;
265
+ idempotencyKey: import("zod").ZodOptional<import("zod").ZodString>;
254
266
  }, import("zod/v4/core").$strict>;
255
267
  export declare const mutateOutput: import("zod").ZodObject<{
256
268
  createdNodes: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodString>;
269
+ replayed: import("zod").ZodOptional<import("zod").ZodLiteral<true>>;
257
270
  }, import("zod/v4/core").$strict>;
@@ -1,8 +1,9 @@
1
- import { strictObject } from 'zod';
1
+ import { strictObject, string } from 'zod';
2
2
  import { mutationAstSchema, mutationResultSchema } from '#graph/mutate/wire';
3
3
  import { domainExpectations } from './expected.js';
4
4
  export const mutateInput = strictObject({
5
5
  ast: mutationAstSchema,
6
6
  expected: domainExpectations.optional(),
7
+ idempotencyKey: string().min(1).max(256).optional(),
7
8
  });
8
9
  export const mutateOutput = mutationResultSchema;
@@ -57,6 +57,17 @@ export declare const queryInput: import("zod").ZodObject<{
57
57
  }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
58
58
  kind: import("zod").ZodLiteral<"property.present">;
59
59
  property: import("zod").ZodString;
60
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
61
+ kind: import("zod").ZodLiteral<"property.range">;
62
+ property: import("zod").ZodString;
63
+ lower: import("zod").ZodOptional<import("zod").ZodObject<{
64
+ value: import("zod").ZodUnion<readonly [import("zod").ZodNumber, import("zod").ZodString]>;
65
+ inclusive: import("zod").ZodBoolean;
66
+ }, import("zod/v4/core").$strict>>;
67
+ upper: import("zod").ZodOptional<import("zod").ZodObject<{
68
+ value: import("zod").ZodUnion<readonly [import("zod").ZodNumber, import("zod").ZodString]>;
69
+ inclusive: import("zod").ZodBoolean;
70
+ }, import("zod/v4/core").$strict>>;
60
71
  }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
61
72
  kind: import("zod").ZodLiteral<"identity.equal">;
62
73
  identity: import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodObject<{
@@ -58,6 +58,17 @@ export declare const Functions: Readonly<{
58
58
  } | {
59
59
  kind: "property.present";
60
60
  property: string;
61
+ } | {
62
+ kind: "property.range";
63
+ property: string;
64
+ lower?: {
65
+ value: string | number;
66
+ inclusive: boolean;
67
+ } | undefined;
68
+ upper?: {
69
+ value: string | number;
70
+ inclusive: boolean;
71
+ } | undefined;
61
72
  } | {
62
73
  kind: "identity.equal";
63
74
  identity: string | {
@@ -335,6 +346,17 @@ export declare const Functions: Readonly<{
335
346
  } | {
336
347
  kind: "property.present";
337
348
  property: string;
349
+ } | {
350
+ kind: "property.range";
351
+ property: string;
352
+ lower?: {
353
+ value: string | number;
354
+ inclusive: boolean;
355
+ } | undefined;
356
+ upper?: {
357
+ value: string | number;
358
+ inclusive: boolean;
359
+ } | undefined;
338
360
  } | {
339
361
  kind: "identity.equal";
340
362
  identity: string | {
@@ -467,10 +489,12 @@ export declare const Functions: Readonly<{
467
489
  origin: string;
468
490
  revision: string;
469
491
  }[] | undefined;
492
+ idempotencyKey?: string | undefined;
470
493
  }, {
471
494
  readonly mode: 'value';
472
495
  readonly value: {
473
496
  createdNodes: Record<string, string>;
497
+ replayed?: true | undefined;
474
498
  };
475
499
  }, "authorized", false, false, undefined>>;
476
500
  register: builder.Function<builder.CallableProjection<{
@@ -86,6 +86,17 @@ export declare const Mutate: builder.Function<builder.CallableProjection<{
86
86
  } | {
87
87
  kind: "property.present";
88
88
  property: string;
89
+ } | {
90
+ kind: "property.range";
91
+ property: string;
92
+ lower?: {
93
+ value: string | number;
94
+ inclusive: boolean;
95
+ } | undefined;
96
+ upper?: {
97
+ value: string | number;
98
+ inclusive: boolean;
99
+ } | undefined;
89
100
  } | {
90
101
  kind: "identity.equal";
91
102
  identity: string | {
@@ -218,9 +229,11 @@ export declare const Mutate: builder.Function<builder.CallableProjection<{
218
229
  origin: string;
219
230
  revision: string;
220
231
  }[] | undefined;
232
+ idempotencyKey?: string | undefined;
221
233
  }, {
222
234
  readonly mode: 'value';
223
235
  readonly value: {
224
236
  createdNodes: Record<string, string>;
237
+ replayed?: true | undefined;
225
238
  };
226
239
  }, "authorized", false, false, undefined>>;
@@ -57,6 +57,17 @@ export declare const Query: builder.Function<builder.CallableProjection<{
57
57
  } | {
58
58
  kind: "property.present";
59
59
  property: string;
60
+ } | {
61
+ kind: "property.range";
62
+ property: string;
63
+ lower?: {
64
+ value: string | number;
65
+ inclusive: boolean;
66
+ } | undefined;
67
+ upper?: {
68
+ value: string | number;
69
+ inclusive: boolean;
70
+ } | undefined;
60
71
  } | {
61
72
  kind: "identity.equal";
62
73
  identity: string | {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/kernel-core",
3
- "version": "0.9.0-beta.66",
3
+ "version": "0.9.0-beta.67",
4
4
  "description": "Astrale Kernel Core - Types, Invariants, and Pure Logic",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -160,7 +160,7 @@
160
160
  "access": "public"
161
161
  },
162
162
  "dependencies": {
163
- "@astrale-os/kernel-dsl": "0.2.0-beta.48",
163
+ "@astrale-os/kernel-dsl": "0.2.0-beta.49",
164
164
  "@noble/hashes": "2.3.0",
165
165
  "@types/json-schema": "^7.0.15",
166
166
  "dequal": "2.0.3"