@telorun/analyzer 0.50.0 → 0.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,7 +48,9 @@ See [examples/](./examples/) for a list of working applications.
48
48
 
49
49
  ## Status
50
50
 
51
- Telo is under **active development**. The core runtime, module system, and standard library are functional, but the API surface — including YAML shapes — may change without notice. Not yet recommended for production use.
51
+ Telo is under heavy development. While it is pre-1.0, breaking changes ship in **minor** releases — manifest shapes, kind schemas, and APIs can change between versions. Pin your imports and expect to update manifests when you upgrade. The core runtime, module system, and standard library are functional, but Telo is not yet recommended for production use.
52
+
53
+ **1.0 lands when the Rust kernel reaches feature parity with the Node.js implementation** — that is the milestone that freezes the manifest contract across runtimes.
52
54
 
53
55
  ## The Meaning of Telo
54
56
 
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIzE,OAAO,EACL,aAAa,EAEb,KAAK,YAAY,EAElB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EACL,KAAK,aAAa,EAGnB,MAAM,0BAA0B,CAAC;AA+BlC,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAoF/F;;;;;uDAKuD;AACvD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAClC,aAAa,GAAG;IAAE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAAA;CAAE,CAO9F;AA6FD;0CAC0C;AAC1C,eAAO,MAAM,eAAe,GAAI,OAAO;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,KAAG,OACT,CAAC;AAErD;8EAC8E;AAC9E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD;AAuBD;2DAC2D;AAC3D,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EACvC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACxB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CASjC;AAED;4EAC4E;AAC5E,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAmBvG;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EAAE,EAChB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EAC/C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAC3D,IAAI,CAiDN;AA2jBD,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;gBAEzB,OAAO,GAAE,qBAA0B;IAI/C;;;;;;;;;;;;;;OAcG;IACH,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,kBAAkB,EAAE;IA4oCvB,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,kBAAkB,EAAE;IAMvB,SAAS,CACP,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,EAI1B,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,GACtC,gBAAgB,EAAE;IAyBrB,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,GACzB;QAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;CAsB5F"}
package/dist/analyzer.js CHANGED
@@ -6,7 +6,7 @@ import { DefinitionRegistry } from "./definition-registry.js";
6
6
  import { effectiveAuthorSchema } from "./extends-resolution.js";
7
7
  import { PERMISSIVE_CONTRACT, resolveContract, } from "./invocation-contract.js";
8
8
  import { buildDependencyGraph, formatCycle } from "./dependency-graph.js";
9
- import { buildKernelGlobalsSchema, mergeKernelGlobalsIntoContext } from "./kernel-globals.js";
9
+ import { buildKernelGlobalsSchema, KERNEL_GLOBAL_NAMES, mergeKernelGlobalsIntoContext, } from "./kernel-globals.js";
10
10
  import { buildObservedStateIndex, buildObservedStateResourcesSchema, collectRunReachableNames, observedStateRead, validateObservedStateDeclarations, } from "./validate-observed-state.js";
11
11
  import { computeSuggestKind } from "./kind-suggest.js";
12
12
  import { visitManifest } from "./manifest-visitor.js";
@@ -21,8 +21,9 @@ import { rewriteSyntheticOrigins } from "./rewrite-synthetic-origins.js";
21
21
  import { celTypeSatisfiesJsonSchema, substituteCelFields, validateAgainstSchema, } from "./schema-compat.js";
22
22
  import { collectValueSchemaIssues } from "./validate-value-schema.js";
23
23
  import { DiagnosticSeverity } from "./types.js";
24
- import { extractAccessChains, extractCelRegionScopes, extractContextsFromSchema, getManifestItem, pathMatchesScope, resolveContextAnnotations, } from "./validate-cel-context.js";
24
+ import { extractAccessChains, extractCelRegionScopes, extractContextsFromSchema, getManifestItem, pathMatchesScope, resolveContextAnnotations, resolveTypeFieldToSchema, } from "./validate-cel-context.js";
25
25
  import { buildEvalPaths, evalPathsCover } from "./eval-paths.js";
26
+ import { BINDINGS_ANNOTATION, bindingContextProperties, bindingPathChain, CEL_RESERVED_WORDS, findBindingSites, resolveBindingOrder, schemaAtChain, } from "./cel-bindings.js";
26
27
  import { validateExtends } from "./validate-extends.js";
27
28
  import { validateLogging } from "./validate-logging.js";
28
29
  import { validateModuleArtifact } from "./validate-module-artifact.js";
@@ -307,12 +308,18 @@ function buildStepContextSchema(manifest, defSchema, allManifests, defs, aliases
307
308
  continue;
308
309
  const invokeField = stepCtx.invoke;
309
310
  const outputTypeField = stepCtx.outputType;
311
+ // Optional: the field a step uses to produce a result without dispatching.
312
+ // Only a kind that declares one has pure steps at all.
313
+ const valueField = stepCtx.value;
310
314
  if (!invokeField || !outputTypeField)
311
315
  continue;
312
316
  const steps = manifest[fieldName];
313
317
  if (!Array.isArray(steps))
314
318
  continue;
315
319
  const stepItemSchema = resolveLocalRef(fieldSchema.items, defSchema);
320
+ // The instance's own input contract, for typing a pure step that just
321
+ // forwards one of its values.
322
+ const ownInputs = resolveTypeFieldToSchema(manifest.inputType, allManifests);
316
323
  const stepProperties = {};
317
324
  walkStepArray(steps, stepItemSchema, defSchema, fieldName, (s) => {
318
325
  const name = s.name;
@@ -321,8 +328,29 @@ function buildStepContextSchema(manifest, defSchema, allManifests, defs, aliases
321
328
  // wrappers (try/if/while/switch/throw) don't produce a result and must
322
329
  // not shadow real entries with a permissive `additionalProperties: true`,
323
330
  // or unknown step references slip through chain validation.
324
- if (typeof name !== "string" || !invoke || typeof invoke !== "object")
331
+ if (typeof name !== "string")
325
332
  return;
333
+ if (!invoke || typeof invoke !== "object") {
334
+ // A pure step dispatches nothing, so there is no contract to resolve.
335
+ // Where its expression is a plain chain into something already typed —
336
+ // an earlier step's result, or the kind's own inputs — that type carries
337
+ // through; anything else (arithmetic, a call, a comprehension) stays
338
+ // permissive rather than guessed. Same rule as a named binding's.
339
+ if (valueField && valueField in s) {
340
+ const scopeRoot = {
341
+ properties: {
342
+ steps: { type: "object", properties: { ...stepProperties } },
343
+ ...(ownInputs ? { inputs: ownInputs } : {}),
344
+ },
345
+ };
346
+ const chained = schemaAtChain(bindingPathChain(s[valueField]), scopeRoot);
347
+ stepProperties[name] = {
348
+ type: "object",
349
+ properties: { result: chained ?? PERMISSIVE_CONTRACT },
350
+ };
351
+ }
352
+ return;
353
+ }
326
354
  const invokedKind = invoke.kind;
327
355
  const invokedName = invoke.name;
328
356
  // A named `!ref` carries the target's own manifest (which may narrow the
@@ -618,6 +646,26 @@ function errorContextForPath(path, scopes) {
618
646
  }
619
647
  return best?.schema;
620
648
  }
649
+ /** Add a kind's named bindings to a resolved context, when the context declares
650
+ * a bindings region. They go UNDER the context's own properties: a scope
651
+ * variable wins over a same-named binding at runtime, so static typing has to
652
+ * agree (the collision itself is `BINDING_NAME_RESERVED`). */
653
+ function withBindingNames(contextSchema, resource) {
654
+ const field = contextSchema[BINDINGS_ANNOTATION];
655
+ if (typeof field !== "string")
656
+ return contextSchema;
657
+ const bindings = resource[field];
658
+ if (bindings === null || typeof bindings !== "object" || Array.isArray(bindings)) {
659
+ return contextSchema;
660
+ }
661
+ return {
662
+ ...contextSchema,
663
+ properties: {
664
+ ...bindingContextProperties(bindings, contextSchema),
665
+ ...(contextSchema.properties ?? {}),
666
+ },
667
+ };
668
+ }
621
669
  /** Member-access chains in a CEL expression, or none when it doesn't parse.
622
670
  * Best-effort: a syntax error is reported by the engine pass, not here. */
623
671
  function celAccessChains(env, expr) {
@@ -1414,6 +1462,9 @@ export class StaticAnalyzer {
1414
1462
  // `x-telo-step-context` / `x-telo-error-context` scopes. A `!cel` outside
1415
1463
  // every region is read as a literal — the runtime never evaluates it.
1416
1464
  let celEvalPaths = [];
1465
+ // The bindings field this kind declares (if any), read by the CEL sites that
1466
+ // see the names it introduces.
1467
+ let celBindingSites;
1417
1468
  // The compile half alone: a field that resolves at startup, where observed
1418
1469
  // state cannot exist yet.
1419
1470
  let celCompilePaths = [];
@@ -1444,6 +1495,72 @@ export class StaticAnalyzer {
1444
1495
  }
1445
1496
  }
1446
1497
  celErrorScopes = collectErrorContextScopes(e.definition?.schema);
1498
+ celBindingSites = findBindingSites(e.definition?.schema);
1499
+ if (celBindingSites) {
1500
+ const declared = m[celBindingSites.field];
1501
+ const bindingsName = m.metadata?.name;
1502
+ const bindingsFile = m.metadata?.source;
1503
+ const resourceRef = { kind: m.kind, name: bindingsName ?? "" };
1504
+ // Which field holds the bindings would otherwise be decided by
1505
+ // schema walk order, silently.
1506
+ if (celBindingSites.fields.length > 1) {
1507
+ diagnostics.push({
1508
+ severity: DiagnosticSeverity.Error,
1509
+ code: "BINDING_FIELD_AMBIGUOUS",
1510
+ source: SOURCE,
1511
+ message: `${m.kind}/${bindingsName}: the kind's schema points '${BINDINGS_ANNOTATION}' at more than one field (${celBindingSites.fields.join(", ")}). Every annotated context must name the same bindings field.`,
1512
+ data: { resource: resourceRef, filePath: bindingsFile, path: celBindingSites.field },
1513
+ });
1514
+ }
1515
+ if (declared !== null && typeof declared === "object" && !Array.isArray(declared)) {
1516
+ for (const cycle of resolveBindingOrder(declared).cycles) {
1517
+ diagnostics.push({
1518
+ severity: DiagnosticSeverity.Error,
1519
+ code: "BINDING_CYCLE",
1520
+ source: SOURCE,
1521
+ message: `${m.kind}/${bindingsName}: '${celBindingSites.field}' has a cycle — ${cycle.join(" → ")}. A binding is resolved from the ones it references, so it cannot reference itself, directly or through others.`,
1522
+ data: {
1523
+ resource: resourceRef,
1524
+ filePath: bindingsFile,
1525
+ path: `${celBindingSites.field}.${cycle[0]}`,
1526
+ },
1527
+ });
1528
+ }
1529
+ // Every name the CEL environment already binds at this site: the
1530
+ // kernel globals (registered straight onto the environment, not
1531
+ // contributed by any annotation), the scope the annotated contexts
1532
+ // declare, and the two the analyzer merges per site. Shadowing one
1533
+ // would leave the binding silently unreachable there — as would
1534
+ // naming it after a CEL keyword, which never lexes as a reference.
1535
+ const inScope = new Set([
1536
+ ...KERNEL_GLOBAL_NAMES,
1537
+ ...celBindingSites.scopeNames,
1538
+ ]);
1539
+ if (celStepContextSchema)
1540
+ inScope.add("steps");
1541
+ if (celErrorScopes.size > 0)
1542
+ inScope.add("error");
1543
+ const keywords = new Set(CEL_RESERVED_WORDS);
1544
+ for (const name of Object.keys(declared)) {
1545
+ const shadows = inScope.has(name);
1546
+ if (!shadows && !keywords.has(name))
1547
+ continue;
1548
+ diagnostics.push({
1549
+ severity: DiagnosticSeverity.Error,
1550
+ code: "BINDING_NAME_RESERVED",
1551
+ source: SOURCE,
1552
+ message: shadows
1553
+ ? `${m.kind}/${bindingsName}: binding '${name}' shadows a variable already in scope here (${[...inScope].sort().join(", ")}). Rename the binding — a scope variable always wins, so this one would never be read.`
1554
+ : `${m.kind}/${bindingsName}: binding '${name}' is a CEL keyword, so no expression can read it as a reference. Rename the binding.`,
1555
+ data: {
1556
+ resource: resourceRef,
1557
+ filePath: bindingsFile,
1558
+ path: `${celBindingSites.field}.${name}`,
1559
+ },
1560
+ });
1561
+ }
1562
+ }
1563
+ }
1447
1564
  // The non-eval-field check only applies to runtime resource instances:
1448
1565
  // structural / templating kinds (capability `Telo.Template`, or no
1449
1566
  // definition) carry CEL the kernel evaluates by other rules.
@@ -1565,7 +1682,7 @@ export class StaticAnalyzer {
1565
1682
  aliases,
1566
1683
  allManifests: allManifests,
1567
1684
  });
1568
- effectiveContext = mergeKernelGlobalsIntoContext(resolvedContext, kernelGlobals);
1685
+ effectiveContext = mergeKernelGlobalsIntoContext(withBindingNames(resolvedContext, m), kernelGlobals);
1569
1686
  }
1570
1687
  else if (observedStateContext) {
1571
1688
  // No `x-telo-context` matched, so nothing was chain-validated here
package/dist/cel-ast.d.ts CHANGED
@@ -1,4 +1,14 @@
1
1
  import { type ASTNode as CelJsNode } from "@marcbachmann/cel-js";
2
+ /** A CEL body that does not parse — an author's expression, mid-typing or
3
+ * malformed. Owned here so a consumer can be lenient about author syntax
4
+ * (navigation, completion) without also swallowing a defect in the wrapper
5
+ * below, and so the third-party parser's error type stays internal, exactly as
6
+ * its AST type does. */
7
+ export declare class CelParseError extends Error {
8
+ readonly source: string;
9
+ readonly cause: unknown;
10
+ constructor(source: string, cause: unknown);
11
+ }
2
12
  /** Read-only CEL expression tree owned by the analyzer. The third-party
3
13
  * `@marcbachmann/cel-js` `ASTNode` stays an internal detail — `wrapCelAst`
4
14
  * translates it into this union so no external AST type leaks through the
@@ -79,7 +89,9 @@ export interface CelSegment {
79
89
  source: string;
80
90
  /** True when a `${{` has no matching `}}` yet (the user is mid-typing). */
81
91
  open: boolean;
82
- /** Lazily parse + wrap; ranges are already absolute. */
92
+ /** Lazily parse + wrap; ranges are already absolute. Throws `CelParseError`
93
+ * when the body doesn't parse — an `open` segment recovers to its longest
94
+ * parseable prefix instead, so only a closed one can throw. */
83
95
  ast(): CelNode;
84
96
  }
85
97
  /** Maps a `@marcbachmann/cel-js` node into the analyzer `CelNode`, translating
@@ -1 +1 @@
1
- {"version":3,"file":"cel-ast.d.ts","sourceRoot":"","sources":["../src/cel-ast.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cel-ast.d.ts","sourceRoot":"","sources":["../src/cel-ast.ts"],"names":[],"mappings":"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"}
package/dist/cel-ast.js CHANGED
@@ -1,4 +1,31 @@
1
- import { parse } from "@marcbachmann/cel-js";
1
+ import { ParseError, parse } from "@marcbachmann/cel-js";
2
+ /** A CEL body that does not parse — an author's expression, mid-typing or
3
+ * malformed. Owned here so a consumer can be lenient about author syntax
4
+ * (navigation, completion) without also swallowing a defect in the wrapper
5
+ * below, and so the third-party parser's error type stays internal, exactly as
6
+ * its AST type does. */
7
+ export class CelParseError extends Error {
8
+ source;
9
+ cause;
10
+ constructor(source, cause) {
11
+ super(cause instanceof Error ? cause.message : String(cause));
12
+ this.source = source;
13
+ this.cause = cause;
14
+ this.name = "CelParseError";
15
+ }
16
+ }
17
+ /** Parse a CEL body, translating the parser's own failure into `CelParseError`.
18
+ * Anything else (a bug in `wrapCelAst`) propagates untouched. */
19
+ function parseCel(source) {
20
+ try {
21
+ return parse(source).ast;
22
+ }
23
+ catch (error) {
24
+ if (error instanceof ParseError)
25
+ throw new CelParseError(source, error);
26
+ throw error;
27
+ }
28
+ }
2
29
  const BINARY_OPS = new Set([
3
30
  "!=",
4
31
  "==",
@@ -115,10 +142,13 @@ function parseLenient(source, segmentStart, range) {
115
142
  if (!trimmed)
116
143
  break;
117
144
  try {
118
- return wrapCelAst(parse(trimmed).ast, segmentStart);
145
+ return wrapCelAst(parseCel(trimmed), segmentStart);
119
146
  }
120
- catch {
121
- // try the next-shorter prefix
147
+ catch (error) {
148
+ // Only a body that doesn't parse warrants the next-shorter prefix; a
149
+ // wrapper defect is not something a shorter prefix fixes.
150
+ if (!(error instanceof CelParseError))
151
+ throw error;
122
152
  }
123
153
  }
124
154
  return { kind: "ident", range, name: source.trim() };
@@ -142,7 +172,7 @@ export function buildCelSegments(scalarText, scalarStart, tag, taggedSource) {
142
172
  range,
143
173
  source: taggedSource,
144
174
  open: false,
145
- ast: () => wrapCelAst(parse(taggedSource).ast, bodyStart),
175
+ ast: () => wrapCelAst(parseCel(taggedSource), bodyStart),
146
176
  },
147
177
  ];
148
178
  }
@@ -160,7 +190,7 @@ export function buildCelSegments(scalarText, scalarStart, tag, taggedSource) {
160
190
  range: [scalarStart + match.index, scalarStart + match.index + whole.length],
161
191
  source,
162
192
  open: false,
163
- ast: () => wrapCelAst(parse(source).ast, bodyStart),
193
+ ast: () => wrapCelAst(parseCel(source), bodyStart),
164
194
  });
165
195
  lastClosedEnd = match.index + whole.length;
166
196
  }
@@ -0,0 +1,57 @@
1
+ /** Annotation on an `x-telo-context` node naming the resource field that holds
2
+ * the kind's named CEL bindings. The field is read from the RESOURCE ROOT, not
3
+ * the per-scope manifest item: a bindings map belongs to the resource, while the
4
+ * contexts that see it may be anchored anywhere (a decision table annotates both
5
+ * `choices` and `default`). */
6
+ export declare const BINDINGS_ANNOTATION = "x-telo-bindings-from";
7
+ export interface BindingSites {
8
+ /** Resource field holding the bindings map. */
9
+ field: string;
10
+ /** Every field named by an annotation on this kind. More than one is a
11
+ * kind-authoring mistake: which of them holds the bindings would be decided
12
+ * by schema walk order. */
13
+ fields: string[];
14
+ /** Variable names the annotated contexts declare — a binding may not shadow one. */
15
+ scopeNames: Set<string>;
16
+ }
17
+ /**
18
+ * CEL keywords. A binding named after one is unreachable — `true` lexes as a
19
+ * literal, `in` as an operator — so it is reserved alongside the scope names,
20
+ * which turns silence into a diagnostic.
21
+ */
22
+ export declare const CEL_RESERVED_WORDS: readonly string[];
23
+ /** Locate a kind's bindings field and the scope names its annotated contexts
24
+ * declare. Returns undefined for a kind that declares no bindings region. */
25
+ export declare function findBindingSites(definitionSchema: Record<string, any> | undefined): BindingSites | undefined;
26
+ /** Each binding's dependencies, restricted to its siblings — an identifier that
27
+ * names something else in scope (`inputs`, `item`) is not an edge. */
28
+ export declare function bindingDependencies(bindings: Record<string, unknown>): Map<string, Set<string>>;
29
+ /** Member-access chain for a binding whose value is one bare dotted identifier
30
+ * expression (`inputs.user.name`). Null for anything else — a literal, a call,
31
+ * a comprehension, a structured value — none of which reduces to a typed path. */
32
+ export declare function bindingPathChain(value: unknown): string[] | null;
33
+ /**
34
+ * The context properties a bindings map contributes: each name typed from its
35
+ * expression where that expression is a chain into an already-typed scope
36
+ * variable, and left open otherwise.
37
+ *
38
+ * Gradual by design — the same stance `x-telo-context-element-from` takes. An
39
+ * open schema costs a missed `CEL_UNKNOWN_FIELD` under that name; inventing a
40
+ * type would cost a false one.
41
+ */
42
+ export declare function bindingContextProperties(bindings: Record<string, unknown>, contextSchema: Record<string, any>): Record<string, any>;
43
+ /** Walk a member-access chain through a schema's `properties`, returning the
44
+ * terminal node or undefined once the path leaves typed schema. */
45
+ export declare function schemaAtChain(chain: string[] | null, root: Record<string, any>): Record<string, any> | undefined;
46
+ /**
47
+ * Evaluation order derived from the reference graph, plus any cycles found.
48
+ *
49
+ * Order is what the editor and diagnostics show; the runtime does not need it,
50
+ * since lazy evaluation reaches a binding's dependencies by construction. A
51
+ * cycle is reported as the path that closes it (`a → b → a`).
52
+ */
53
+ export declare function resolveBindingOrder(bindings: Record<string, unknown>): {
54
+ order: string[];
55
+ cycles: string[][];
56
+ };
57
+ //# sourceMappingURL=cel-bindings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cel-bindings.d.ts","sourceRoot":"","sources":["../src/cel-bindings.ts"],"names":[],"mappings":"AAIA;;;;gCAIgC;AAChC,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd;;gCAE4B;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,oFAAoF;IACpF,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAsB/C,CAAC;AAEF;8EAC8E;AAC9E,wBAAgB,gBAAgB,CAC9B,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GAChD,YAAY,GAAG,SAAS,CAW1B;AAuDD;uEACuE;AACvE,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAW1B;AAED;;mFAEmF;AACnF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,IAAI,CAQhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACjC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAMrB;AAED;oEACoE;AACpE,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACxB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CASjC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACtE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACpB,CAwBA"}
@@ -0,0 +1,207 @@
1
+ import { isCompiledValue } from "@telorun/sdk";
2
+ import { buildCelEnvironment, extractAccessChains } from "@telorun/templating";
3
+ import { extractContextsFromSchema } from "./validate-cel-context.js";
4
+ /** Annotation on an `x-telo-context` node naming the resource field that holds
5
+ * the kind's named CEL bindings. The field is read from the RESOURCE ROOT, not
6
+ * the per-scope manifest item: a bindings map belongs to the resource, while the
7
+ * contexts that see it may be anchored anywhere (a decision table annotates both
8
+ * `choices` and `default`). */
9
+ export const BINDINGS_ANNOTATION = "x-telo-bindings-from";
10
+ /**
11
+ * CEL keywords. A binding named after one is unreachable — `true` lexes as a
12
+ * literal, `in` as an operator — so it is reserved alongside the scope names,
13
+ * which turns silence into a diagnostic.
14
+ */
15
+ export const CEL_RESERVED_WORDS = [
16
+ "as",
17
+ "break",
18
+ "const",
19
+ "continue",
20
+ "else",
21
+ "false",
22
+ "for",
23
+ "function",
24
+ "if",
25
+ "import",
26
+ "in",
27
+ "let",
28
+ "loop",
29
+ "namespace",
30
+ "null",
31
+ "package",
32
+ "return",
33
+ "true",
34
+ "var",
35
+ "void",
36
+ "while",
37
+ ];
38
+ /** Locate a kind's bindings field and the scope names its annotated contexts
39
+ * declare. Returns undefined for a kind that declares no bindings region. */
40
+ export function findBindingSites(definitionSchema) {
41
+ if (!definitionSchema)
42
+ return undefined;
43
+ const fields = [];
44
+ const scopeNames = new Set();
45
+ for (const { schema } of extractContextsFromSchema(definitionSchema)) {
46
+ const declared = schema?.[BINDINGS_ANNOTATION];
47
+ if (typeof declared !== "string" || declared.length === 0)
48
+ continue;
49
+ if (!fields.includes(declared))
50
+ fields.push(declared);
51
+ for (const name of Object.keys(schema.properties ?? {}))
52
+ scopeNames.add(name);
53
+ }
54
+ return fields.length > 0 ? { field: fields[0], fields, scopeNames } : undefined;
55
+ }
56
+ const TEMPLATE_RE = /\$\{\{\s*([^}]+?)\s*\}\}/g;
57
+ const EXACT_TEMPLATE_RE = /^\s*\$\{\{\s*([^}]+?)\s*\}\}\s*$/;
58
+ /** Parser for expressions that reach here uncompiled. Built once; the base
59
+ * environment is stateless and shared with the runtime's own. */
60
+ let parseEnv;
61
+ /**
62
+ * Root identifiers an expression source reads — the first element of every
63
+ * member-access chain, which is what a dependency edge is made of.
64
+ *
65
+ * Parsed, never lexed: `inputs.total` reads `inputs`, not `total`, and a name
66
+ * inside a string literal reads nothing. A token scan would make two bindings
67
+ * named after each other's *fields* look mutually recursive and reject a correct
68
+ * manifest — the worst outcome a static check has. An expression that does not
69
+ * parse contributes no edges; its syntax error is the engine pass's to report.
70
+ */
71
+ function addRootIdentifiers(source, out) {
72
+ try {
73
+ parseEnv ??= buildCelEnvironment();
74
+ for (const chain of extractAccessChains(parseEnv.parse(source).ast)) {
75
+ if (chain.length > 0)
76
+ out.add(chain[0]);
77
+ }
78
+ }
79
+ catch {
80
+ // Unparseable — see above.
81
+ }
82
+ }
83
+ /** Root identifiers a binding's value reads. Walks the whole value so a
84
+ * structured binding (a map with `!cel` leaves) is covered, and reads both a
85
+ * compiled expression and a still-raw `${{ }}` string — the editor's
86
+ * round-trip view never compiles. An untagged plain string is a literal, not
87
+ * an expression, and contributes nothing. */
88
+ function collectRefs(value, out) {
89
+ if (isCompiledValue(value)) {
90
+ const refs = value.refs;
91
+ if (refs)
92
+ for (const ref of refs)
93
+ out.add(ref);
94
+ else
95
+ addRootIdentifiers(value.source ?? "", out);
96
+ return;
97
+ }
98
+ if (typeof value === "string") {
99
+ for (const match of value.matchAll(TEMPLATE_RE))
100
+ addRootIdentifiers(match[1], out);
101
+ return;
102
+ }
103
+ if (Array.isArray(value)) {
104
+ for (const entry of value)
105
+ collectRefs(entry, out);
106
+ return;
107
+ }
108
+ if (value !== null && typeof value === "object") {
109
+ for (const entry of Object.values(value))
110
+ collectRefs(entry, out);
111
+ }
112
+ }
113
+ /** Each binding's dependencies, restricted to its siblings — an identifier that
114
+ * names something else in scope (`inputs`, `item`) is not an edge. */
115
+ export function bindingDependencies(bindings) {
116
+ const names = new Set(Object.keys(bindings));
117
+ const deps = new Map();
118
+ for (const [name, value] of Object.entries(bindings)) {
119
+ const refs = new Set();
120
+ collectRefs(value, refs);
121
+ const own = new Set();
122
+ for (const ref of refs)
123
+ if (names.has(ref))
124
+ own.add(ref);
125
+ deps.set(name, own);
126
+ }
127
+ return deps;
128
+ }
129
+ /** Member-access chain for a binding whose value is one bare dotted identifier
130
+ * expression (`inputs.user.name`). Null for anything else — a literal, a call,
131
+ * a comprehension, a structured value — none of which reduces to a typed path. */
132
+ export function bindingPathChain(value) {
133
+ let source;
134
+ if (isCompiledValue(value))
135
+ source = value.source;
136
+ else if (typeof value === "string")
137
+ source = value.match(EXACT_TEMPLATE_RE)?.[1];
138
+ if (source === undefined)
139
+ return null;
140
+ const expr = source.trim();
141
+ if (!/^[A-Za-z_]\w*(\.[A-Za-z_]\w*)*$/.test(expr))
142
+ return null;
143
+ return expr.split(".");
144
+ }
145
+ /**
146
+ * The context properties a bindings map contributes: each name typed from its
147
+ * expression where that expression is a chain into an already-typed scope
148
+ * variable, and left open otherwise.
149
+ *
150
+ * Gradual by design — the same stance `x-telo-context-element-from` takes. An
151
+ * open schema costs a missed `CEL_UNKNOWN_FIELD` under that name; inventing a
152
+ * type would cost a false one.
153
+ */
154
+ export function bindingContextProperties(bindings, contextSchema) {
155
+ const props = {};
156
+ for (const [name, value] of Object.entries(bindings)) {
157
+ props[name] = schemaAtChain(bindingPathChain(value), contextSchema) ?? {};
158
+ }
159
+ return props;
160
+ }
161
+ /** Walk a member-access chain through a schema's `properties`, returning the
162
+ * terminal node or undefined once the path leaves typed schema. */
163
+ export function schemaAtChain(chain, root) {
164
+ if (!chain)
165
+ return undefined;
166
+ let current = root;
167
+ for (const key of chain) {
168
+ const props = current?.properties;
169
+ if (!props || !(key in props))
170
+ return undefined;
171
+ current = props[key];
172
+ }
173
+ return current && typeof current === "object" ? current : undefined;
174
+ }
175
+ /**
176
+ * Evaluation order derived from the reference graph, plus any cycles found.
177
+ *
178
+ * Order is what the editor and diagnostics show; the runtime does not need it,
179
+ * since lazy evaluation reaches a binding's dependencies by construction. A
180
+ * cycle is reported as the path that closes it (`a → b → a`).
181
+ */
182
+ export function resolveBindingOrder(bindings) {
183
+ const deps = bindingDependencies(bindings);
184
+ const order = [];
185
+ const cycles = [];
186
+ const state = new Map();
187
+ const path = [];
188
+ const visit = (name) => {
189
+ const seen = state.get(name);
190
+ if (seen === "done")
191
+ return;
192
+ if (seen === "visiting") {
193
+ cycles.push([...path.slice(path.indexOf(name)), name]);
194
+ return;
195
+ }
196
+ state.set(name, "visiting");
197
+ path.push(name);
198
+ for (const dep of deps.get(name) ?? [])
199
+ visit(dep);
200
+ path.pop();
201
+ state.set(name, "done");
202
+ order.push(name);
203
+ };
204
+ for (const name of Object.keys(bindings))
205
+ visit(name);
206
+ return { order, cycles };
207
+ }
package/dist/index.d.ts CHANGED
@@ -5,6 +5,8 @@ export { importResolutionDiagnostics } from "./import-resolution-diagnostics.js"
5
5
  export type { GraphLoadError, ImportEdge, LoadedFile, LoadedGraph, LoadedModule, ParseError, } from "./loaded-types.js";
6
6
  export { flattenForAnalyzer, flattenLoadedModule, forwardReExportManifests, parseExportEntry, reExportSpecsFromExports, resolveExportedKinds, selectModuleManifestsForAnalysis, stampExportedKinds, stampReExportedKinds, type ParsedExportEntry, type ReExportSpec, } from "./flatten-for-analyzer.js";
7
7
  export { buildEvalPaths, evalPathCovers } from "./eval-paths.js";
8
+ export { BINDINGS_ANNOTATION, bindingContextProperties, bindingDependencies, findBindingSites, resolveBindingOrder, } from "./cel-bindings.js";
9
+ export type { BindingSites } from "./cel-bindings.js";
8
10
  export { applyObservedStateNode, buildObservedStateIndex, buildObservedStateResourcesSchema, collectRunReachableNames, observedStateRead, validateObservedStateDeclarations, OBSERVED_STATE_SCHEMA, } from "./validate-observed-state.js";
9
11
  export type { AnalyzedResource, ObservedStateRead } from "./validate-observed-state.js";
10
12
  export { moduleScopedDefResolver, scopeResolverForModule } from "./alias-resolver.js";
@@ -36,7 +38,7 @@ export type { DocumentPosition } from "./position-metadata.js";
36
38
  export { HttpSource } from "./sources/http-source.js";
37
39
  export { RegistrySource } from "./sources/registry-source.js";
38
40
  export { defaultSources } from "./sources/default-sources.js";
39
- export { splitIntegrity, foldIntegrity, verifyIntegrity, verifiedFetch, sha256Base64Url, IntegrityError, } from "./sources/integrity.js";
41
+ export { splitIntegrity, foldIntegrity, isCanonicalIntegrity, verifyIntegrity, verifiedFetch, sha256Base64Url, IntegrityError, } from "./sources/integrity.js";
40
42
  export { parseModuleRef, isRegistryRef } from "./sources/module-ref.js";
41
43
  export type { ParsedModuleRef } from "./sources/module-ref.js";
42
44
  export { OCI_SCHEME, isOciRef, parseOciRef } from "./sources/oci-ref.js";
@@ -54,7 +56,7 @@ export { validateModuleArtifact } from "./validate-module-artifact.js";
54
56
  export { withSyntheticPositions } from "./with-synthetic-positions.js";
55
57
  export { documentToAst, parseToAst } from "./yaml-ast.js";
56
58
  export type { AstDocument, AstMap, AstNode, AstPair, AstScalar, AstSeq } from "./yaml-ast.js";
57
- export { buildCelSegments, wrapCelAst } from "./cel-ast.js";
59
+ export { CelParseError, buildCelSegments, wrapCelAst } from "./cel-ast.js";
58
60
  export type { CelNode, CelSegment } from "./cel-ast.js";
59
61
  export { DEFAULT_MANIFEST_FILENAME, DiagnosticSeverity } from "./types.js";
60
62
  export type { AnalysisDiagnostic, AnalysisOptions, LoaderInitOptions, LoadOptions, ManifestSource, Position, PositionIndex, Range } from "./types.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}