@telorun/analyzer 0.11.0 → 0.12.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.
Files changed (92) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +3 -3
  3. package/dist/adapters/http-adapter.d.ts +10 -0
  4. package/dist/adapters/http-adapter.d.ts.map +1 -0
  5. package/dist/adapters/http-adapter.js +18 -0
  6. package/dist/adapters/node-adapter.d.ts +17 -0
  7. package/dist/adapters/node-adapter.d.ts.map +1 -0
  8. package/dist/adapters/node-adapter.js +71 -0
  9. package/dist/adapters/registry-adapter.d.ts +15 -0
  10. package/dist/adapters/registry-adapter.d.ts.map +1 -0
  11. package/dist/adapters/registry-adapter.js +53 -0
  12. package/dist/analysis-registry.d.ts +7 -0
  13. package/dist/analysis-registry.d.ts.map +1 -1
  14. package/dist/analysis-registry.js +38 -0
  15. package/dist/analyzer.d.ts +15 -0
  16. package/dist/analyzer.d.ts.map +1 -1
  17. package/dist/analyzer.js +114 -10
  18. package/dist/builtins.d.ts.map +1 -1
  19. package/dist/builtins.js +58 -1
  20. package/dist/definition-registry.d.ts.map +1 -1
  21. package/dist/definition-registry.js +16 -0
  22. package/dist/dependency-graph.d.ts.map +1 -1
  23. package/dist/dependency-graph.js +27 -13
  24. package/dist/index.d.ts +2 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -0
  27. package/dist/kernel-globals.d.ts.map +1 -1
  28. package/dist/kernel-globals.js +9 -11
  29. package/dist/manifest-loader.d.ts +23 -1
  30. package/dist/manifest-loader.d.ts.map +1 -1
  31. package/dist/manifest-loader.js +66 -3
  32. package/dist/normalize-inline-resources.d.ts.map +1 -1
  33. package/dist/normalize-inline-resources.js +26 -14
  34. package/dist/position-metadata.d.ts +11 -2
  35. package/dist/position-metadata.d.ts.map +1 -1
  36. package/dist/position-metadata.js +18 -3
  37. package/dist/precompile.d.ts.map +1 -1
  38. package/dist/precompile.js +9 -1
  39. package/dist/reference-field-map.d.ts +21 -4
  40. package/dist/reference-field-map.d.ts.map +1 -1
  41. package/dist/reference-field-map.js +93 -25
  42. package/dist/residual-schema.d.ts +23 -0
  43. package/dist/residual-schema.d.ts.map +1 -0
  44. package/dist/residual-schema.js +45 -0
  45. package/dist/resolve-ref-sentinels.d.ts +27 -0
  46. package/dist/resolve-ref-sentinels.d.ts.map +1 -0
  47. package/dist/resolve-ref-sentinels.js +114 -0
  48. package/dist/rewrite-synthetic-origins.d.ts +10 -0
  49. package/dist/rewrite-synthetic-origins.d.ts.map +1 -0
  50. package/dist/rewrite-synthetic-origins.js +55 -0
  51. package/dist/schema-compat.d.ts +7 -1
  52. package/dist/schema-compat.d.ts.map +1 -1
  53. package/dist/schema-compat.js +19 -2
  54. package/dist/system-kinds.d.ts +25 -0
  55. package/dist/system-kinds.d.ts.map +1 -0
  56. package/dist/system-kinds.js +34 -0
  57. package/dist/types.d.ts +12 -0
  58. package/dist/types.d.ts.map +1 -1
  59. package/dist/validate-cel-context.d.ts +5 -0
  60. package/dist/validate-cel-context.d.ts.map +1 -1
  61. package/dist/validate-cel-context.js +27 -15
  62. package/dist/validate-provider-coherence.d.ts +23 -0
  63. package/dist/validate-provider-coherence.d.ts.map +1 -0
  64. package/dist/validate-provider-coherence.js +148 -0
  65. package/dist/validate-references.d.ts.map +1 -1
  66. package/dist/validate-references.js +141 -36
  67. package/dist/with-synthetic-positions.d.ts +28 -0
  68. package/dist/with-synthetic-positions.d.ts.map +1 -0
  69. package/dist/with-synthetic-positions.js +45 -0
  70. package/package.json +7 -4
  71. package/src/analysis-registry.ts +37 -0
  72. package/src/analyzer.ts +118 -12
  73. package/src/builtins.ts +58 -1
  74. package/src/definition-registry.ts +15 -0
  75. package/src/dependency-graph.ts +27 -14
  76. package/src/index.ts +2 -0
  77. package/src/kernel-globals.ts +9 -11
  78. package/src/manifest-loader.ts +69 -4
  79. package/src/normalize-inline-resources.ts +48 -13
  80. package/src/position-metadata.ts +18 -3
  81. package/src/precompile.ts +8 -1
  82. package/src/reference-field-map.ts +129 -24
  83. package/src/residual-schema.ts +49 -0
  84. package/src/resolve-ref-sentinels.ts +127 -0
  85. package/src/rewrite-synthetic-origins.ts +75 -0
  86. package/src/schema-compat.ts +19 -2
  87. package/src/system-kinds.ts +37 -0
  88. package/src/types.ts +12 -0
  89. package/src/validate-cel-context.ts +28 -15
  90. package/src/validate-provider-coherence.ts +166 -0
  91. package/src/validate-references.ts +138 -35
  92. package/src/with-synthetic-positions.ts +48 -0
@@ -26,25 +26,30 @@ export function isInlineResource(val) {
26
26
  return false;
27
27
  return true;
28
28
  }
29
- /** Resolves all values at a field map path in a resource config.
30
- * Path-segment markers:
31
- * - `[]` iterate array values at this key
29
+ /** Resolves all `{value, path}` entries at a field map path in a resource
30
+ * config. The returned `path` is the concrete dotted path produced by the
31
+ * substitutions below, matching the format `buildPositionIndex` keys on.
32
+ * Path-segment markers accepted in the input `path`:
33
+ * - `[]` iterate array values at this key, substituting `[N]` per item
34
+ * (e.g. `routes[]` → `routes[0]`, `routes[1]`, …).
32
35
  * - `{}` iterate map values (every value in an `additionalProperties`-typed
33
36
  * object — used for fields like `content[mime]` whose schema declares
34
- * a key-as-MIME map). The path is `<key>.{}.<rest>`. */
35
- export function resolveFieldValues(obj, path) {
37
+ * a key-as-MIME map). Substituted with the literal map key joined by
38
+ * a dot, so the input `content.{}.encoder` yields concrete paths
39
+ * like `content.application/json.encoder`. */
40
+ export function resolveFieldEntries(obj, path) {
36
41
  const parts = path.split(".");
37
- let current = [obj];
42
+ let current = [{ value: obj, path: "" }];
38
43
  for (const part of parts) {
39
44
  if (part === "{}") {
40
- // Iterate the values of every map currently in `current`.
41
45
  const next = [];
42
- for (const item of current) {
43
- if (!item || typeof item !== "object")
46
+ for (const entry of current) {
47
+ if (!entry.value || typeof entry.value !== "object")
44
48
  continue;
45
- for (const v of Object.values(item)) {
46
- if (v != null)
47
- next.push(v);
49
+ for (const [k, v] of Object.entries(entry.value)) {
50
+ if (v != null) {
51
+ next.push({ value: v, path: entry.path ? `${entry.path}.${k}` : k });
52
+ }
48
53
  }
49
54
  }
50
55
  current = next;
@@ -53,21 +58,32 @@ export function resolveFieldValues(obj, path) {
53
58
  const isArray = part.endsWith("[]");
54
59
  const key = isArray ? part.slice(0, -2) : part;
55
60
  const next = [];
56
- for (const item of current) {
57
- if (!item || typeof item !== "object")
61
+ for (const entry of current) {
62
+ if (!entry.value || typeof entry.value !== "object")
58
63
  continue;
59
- const val = item[key];
64
+ const val = entry.value[key];
60
65
  if (val == null)
61
66
  continue;
62
- if (isArray && Array.isArray(val))
63
- next.push(...val);
64
- else if (!isArray)
65
- next.push(val);
67
+ const basePath = entry.path ? `${entry.path}.${key}` : key;
68
+ if (isArray && Array.isArray(val)) {
69
+ for (let i = 0; i < val.length; i++) {
70
+ if (val[i] != null)
71
+ next.push({ value: val[i], path: `${basePath}[${i}]` });
72
+ }
73
+ }
74
+ else if (!isArray) {
75
+ next.push({ value: val, path: basePath });
76
+ }
66
77
  }
67
78
  current = next;
68
79
  }
69
80
  return current;
70
81
  }
82
+ /** Backwards-compat wrapper that drops the concrete path. Prefer
83
+ * `resolveFieldEntries` for new code that wants positions. */
84
+ export function resolveFieldValues(obj, path) {
85
+ return resolveFieldEntries(obj, path).map((e) => e.value);
86
+ }
71
87
  /**
72
88
  * Traverses a definition's JSON Schema once and returns a field map recording every
73
89
  * x-telo-ref slot and every x-telo-scope slot.
@@ -82,7 +98,7 @@ export function buildReferenceFieldMap(schema) {
82
98
  const map = new Map();
83
99
  if (schema.properties) {
84
100
  for (const [key, propSchema] of Object.entries(schema.properties)) {
85
- traverseNode(propSchema, key, map);
101
+ traverseNode(propSchema, key, map, schema);
86
102
  }
87
103
  }
88
104
  return map;
@@ -107,10 +123,23 @@ function collectRefs(node) {
107
123
  * hid behind the schema-from indirection. */
108
124
  export function buildFieldMapAtPath(schema, pathPrefix) {
109
125
  const map = new Map();
110
- traverseNode(schema, pathPrefix, map);
126
+ traverseNode(schema, pathPrefix, map, schema);
111
127
  return map;
112
128
  }
113
- function traverseNode(node, path, map) {
129
+ function traverseNode(node, path, map, root, visitedRefs = new Set()) {
130
+ // Local `$ref` is intentionally NOT followed. Descending into shared
131
+ // `$defs` (notably `Run.Sequence`'s `step` definition) would surface
132
+ // ref slots like `steps[].invoke` that Phase 5 then injects live
133
+ // instances into; today's `Run.Sequence` controller calls
134
+ // `instance.invoke()` directly when handed an instance, bypassing
135
+ // the kernel's `runInvoke` emit-Invoked path. The walker fix and the
136
+ // dispatcher fix need to land together — see the follow-up in
137
+ // [kernel/nodejs/plans/reference-syntax-unification.md] and the
138
+ // stopgap in `resource-context.ts:resolveChildren`. `visitedRefs`
139
+ // stays as a parameter so the recursive calls below thread the right
140
+ // signature; turning the descent back on is a single-branch change.
141
+ if (typeof node?.$ref === "string")
142
+ return;
114
143
  // Scope slot — record and stop; do not recurse into scope contents
115
144
  if ("x-telo-scope" in node) {
116
145
  map.set(path, { scope: node["x-telo-scope"] });
@@ -132,12 +161,32 @@ function traverseNode(node, path, map) {
132
161
  }
133
162
  // Array — recurse into items
134
163
  if (node.type === "array" && node.items) {
135
- traverseNode(node.items, path + "[]", map);
164
+ traverseNode(node.items, path + "[]", map, root, visitedRefs);
136
165
  }
137
166
  // Object — recurse into properties
138
167
  if (node.properties) {
139
168
  for (const [key, propSchema] of Object.entries(node.properties)) {
140
- traverseNode(propSchema, `${path}.${key}`, map);
169
+ traverseNode(propSchema, `${path}.${key}`, map, root, visitedRefs);
170
+ }
171
+ }
172
+ // Variant branches — descend into every alternative's properties / items.
173
+ // Schemas that discriminate on shape (Run.Sequence's step kinds:
174
+ // `oneOf: [{properties: {invoke}}, {properties: {try}}, ...]`) hide ref
175
+ // slots inside the branch. Walking each branch surfaces those slots into
176
+ // the field map so downstream passes (ref validation, sentinel
177
+ // resolution, dependency graph) cover them without a runtime fallback.
178
+ // The same field path may be added by multiple branches; the later
179
+ // assignment wins, which is fine — branches with the same field path
180
+ // share the same ref/context configuration (any divergence is already
181
+ // a schema bug).
182
+ for (const variantKey of ["oneOf", "anyOf", "allOf"]) {
183
+ const variants = node[variantKey];
184
+ if (!Array.isArray(variants))
185
+ continue;
186
+ for (const variant of variants) {
187
+ if (!variant || typeof variant !== "object")
188
+ continue;
189
+ traverseVariant(variant, path, map, root, visitedRefs);
141
190
  }
142
191
  }
143
192
  // Map — `additionalProperties: { ... }` describes every value in an
@@ -146,6 +195,25 @@ function traverseNode(node, path, map) {
146
195
  if (node.additionalProperties &&
147
196
  typeof node.additionalProperties === "object" &&
148
197
  !Array.isArray(node.additionalProperties)) {
149
- traverseNode(node.additionalProperties, `${path}.{}`, map);
198
+ traverseNode(node.additionalProperties, `${path}.{}`, map, root, visitedRefs);
199
+ }
200
+ }
201
+ /** Walk a single variant of a `oneOf` / `anyOf` / `allOf` branch. Only
202
+ * the properties / items / map slots are followed — collectRefs at the
203
+ * variant root is handled by the parent's `collectRefs(node)` already
204
+ * (anyOf of x-telo-ref branches is the canonical multi-ref shape). */
205
+ function traverseVariant(variant, path, map, root, visitedRefs = new Set()) {
206
+ if (variant.properties) {
207
+ for (const [key, propSchema] of Object.entries(variant.properties)) {
208
+ traverseNode(propSchema, `${path}.${key}`, map, root, visitedRefs);
209
+ }
210
+ }
211
+ if (variant.type === "array" && variant.items) {
212
+ traverseNode(variant.items, path + "[]", map, root, visitedRefs);
213
+ }
214
+ if (variant.additionalProperties &&
215
+ typeof variant.additionalProperties === "object" &&
216
+ !Array.isArray(variant.additionalProperties)) {
217
+ traverseNode(variant.additionalProperties, `${path}.{}`, map, root, visitedRefs);
150
218
  }
151
219
  }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Build the residual JSON Schema for a `variables` / `secrets` entry.
3
+ *
4
+ * For Telo.Application env-binding entries (those with an `env:` key), strips
5
+ * the kernel-specific wrapper keys `env` and `default` — `default` here is
6
+ * the *fallback host value* the kernel coerces when the env var is unset, not
7
+ * a JSON Schema annotation, so it must not leak into the validator.
8
+ *
9
+ * For Telo.Library entries (no `env:`), passes the entry through unchanged.
10
+ * Library `default:` is a standard JSON Schema annotation and stays.
11
+ *
12
+ * Single source of truth for "residual schema" referenced by both the
13
+ * analyzer's CEL globals normalization and the kernel's runtime env-var
14
+ * resolver — keeping them aligned prevents the two surfaces from drifting.
15
+ */
16
+ export declare function residualEntrySchema(entry: Record<string, unknown> | null | undefined): Record<string, unknown>;
17
+ /**
18
+ * Apply `residualEntrySchema` to every entry in a `variables` / `secrets` map.
19
+ * Returns a property-map suitable for use as the inner schema of CEL's
20
+ * `variables` / `secrets` namespaces.
21
+ */
22
+ export declare function residualEntrySchemaMap(entries: Record<string, unknown> | null | undefined): Record<string, Record<string, unknown>>;
23
+ //# sourceMappingURL=residual-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"residual-schema.d.ts","sourceRoot":"","sources":["../src/residual-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAChD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWzB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAClD,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAWzC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Build the residual JSON Schema for a `variables` / `secrets` entry.
3
+ *
4
+ * For Telo.Application env-binding entries (those with an `env:` key), strips
5
+ * the kernel-specific wrapper keys `env` and `default` — `default` here is
6
+ * the *fallback host value* the kernel coerces when the env var is unset, not
7
+ * a JSON Schema annotation, so it must not leak into the validator.
8
+ *
9
+ * For Telo.Library entries (no `env:`), passes the entry through unchanged.
10
+ * Library `default:` is a standard JSON Schema annotation and stays.
11
+ *
12
+ * Single source of truth for "residual schema" referenced by both the
13
+ * analyzer's CEL globals normalization and the kernel's runtime env-var
14
+ * resolver — keeping them aligned prevents the two surfaces from drifting.
15
+ */
16
+ export function residualEntrySchema(entry) {
17
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
18
+ return { type: "object", additionalProperties: true };
19
+ }
20
+ const isAppEnvBinding = "env" in entry;
21
+ const out = {};
22
+ for (const [key, value] of Object.entries(entry)) {
23
+ if (isAppEnvBinding && (key === "env" || key === "default"))
24
+ continue;
25
+ out[key] = value;
26
+ }
27
+ return out;
28
+ }
29
+ /**
30
+ * Apply `residualEntrySchema` to every entry in a `variables` / `secrets` map.
31
+ * Returns a property-map suitable for use as the inner schema of CEL's
32
+ * `variables` / `secrets` namespaces.
33
+ */
34
+ export function residualEntrySchemaMap(entries) {
35
+ const out = {};
36
+ if (!entries || typeof entries !== "object" || Array.isArray(entries)) {
37
+ return out;
38
+ }
39
+ for (const [name, value] of Object.entries(entries)) {
40
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
41
+ out[name] = residualEntrySchema(value);
42
+ }
43
+ }
44
+ return out;
45
+ }
@@ -0,0 +1,27 @@
1
+ import type { ResourceManifest } from "@telorun/sdk";
2
+ import type { AliasResolver } from "./alias-resolver.js";
3
+ import type { DefinitionRegistry } from "./definition-registry.js";
4
+ /**
5
+ * Walks every `x-telo-ref` slot in every non-system resource and rewrites
6
+ * `!ref <name>` sentinels in-place to `{kind: <resolved-kind>, name}`.
7
+ *
8
+ * The downstream pipeline (inline normalization, dependency graph, kernel
9
+ * controllers) expects every ref-slot value to be either a `{kind, name}`
10
+ * object, an inline-definition object, or a legacy bare string — resolving
11
+ * sentinels here keeps that contract intact so each consumer doesn't need
12
+ * its own sentinel branch.
13
+ *
14
+ * The walker assigns `kind` by name lookup (resource names are unique
15
+ * within a manifest scope). When the name doesn't resolve in the local
16
+ * `byName` map, the sentinel is left in place so `validateReferences`
17
+ * can emit the `UNRESOLVED_REFERENCE` diagnostic with full context.
18
+ *
19
+ * Mutation strategy: the field-path walker descends the resource tree
20
+ * directly and replaces the sentinel on its parent container. Re-parsing
21
+ * a string-encoded concrete path (the earlier shape) coupled the writer
22
+ * to the path-encoding rules of `resolveFieldEntries` — any new path
23
+ * marker would silently break this writer. Descending directly avoids
24
+ * that coupling.
25
+ */
26
+ export declare function resolveRefSentinels(resources: ResourceManifest[], registry: DefinitionRegistry, aliases?: AliasResolver, aliasesByModule?: Map<string, AliasResolver>): void;
27
+ //# sourceMappingURL=resolve-ref-sentinels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-ref-sentinels.d.ts","sourceRoot":"","sources":["../src/resolve-ref-sentinels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAInE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,CAAC,EAAE,aAAa,EACvB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAC3C,IAAI,CAsBN"}
@@ -0,0 +1,114 @@
1
+ import { isRefSentinel } from "@telorun/templating";
2
+ import { isRefEntry } from "./reference-field-map.js";
3
+ import { REF_RESOLUTION_SKIP_KINDS as SYSTEM_KINDS } from "./system-kinds.js";
4
+ /**
5
+ * Walks every `x-telo-ref` slot in every non-system resource and rewrites
6
+ * `!ref <name>` sentinels in-place to `{kind: <resolved-kind>, name}`.
7
+ *
8
+ * The downstream pipeline (inline normalization, dependency graph, kernel
9
+ * controllers) expects every ref-slot value to be either a `{kind, name}`
10
+ * object, an inline-definition object, or a legacy bare string — resolving
11
+ * sentinels here keeps that contract intact so each consumer doesn't need
12
+ * its own sentinel branch.
13
+ *
14
+ * The walker assigns `kind` by name lookup (resource names are unique
15
+ * within a manifest scope). When the name doesn't resolve in the local
16
+ * `byName` map, the sentinel is left in place so `validateReferences`
17
+ * can emit the `UNRESOLVED_REFERENCE` diagnostic with full context.
18
+ *
19
+ * Mutation strategy: the field-path walker descends the resource tree
20
+ * directly and replaces the sentinel on its parent container. Re-parsing
21
+ * a string-encoded concrete path (the earlier shape) coupled the writer
22
+ * to the path-encoding rules of `resolveFieldEntries` — any new path
23
+ * marker would silently break this writer. Descending directly avoids
24
+ * that coupling.
25
+ */
26
+ export function resolveRefSentinels(resources, registry, aliases, aliasesByModule) {
27
+ const byName = new Map();
28
+ for (const r of resources) {
29
+ if (r.metadata?.name && !SYSTEM_KINDS.has(r.kind)) {
30
+ byName.set(r.metadata.name, r);
31
+ }
32
+ }
33
+ for (const r of resources) {
34
+ if (!r.metadata?.name || !r.kind || SYSTEM_KINDS.has(r.kind))
35
+ continue;
36
+ const fieldMap = aliases && aliasesByModule
37
+ ? registry.expandedFieldMapForResource(r, aliases, aliasesByModule)
38
+ : registry.getFieldMapForKind(r.kind, aliases);
39
+ if (!fieldMap)
40
+ continue;
41
+ for (const [fieldPath, entry] of fieldMap) {
42
+ if (!isRefEntry(entry))
43
+ continue;
44
+ replaceSentinelsAtPath(r, fieldPath, byName);
45
+ }
46
+ }
47
+ }
48
+ /** Walks `obj` along `fieldPath` (dot notation with `[]` for arrays and
49
+ * `{}` for additionalProperties-typed maps) and replaces any `!ref`
50
+ * sentinel value at the terminal slot with `{kind, name}` looked up
51
+ * via `byName`. Mutates the parent container in place; no string-path
52
+ * round-trip. */
53
+ function replaceSentinelsAtPath(obj, fieldPath, byName) {
54
+ const parts = fieldPath.split(".");
55
+ descend(obj, parts, byName);
56
+ }
57
+ function descend(obj, parts, byName) {
58
+ if (obj == null || typeof obj !== "object" || parts.length === 0)
59
+ return;
60
+ const [head, ...rest] = parts;
61
+ // Map iteration: descend into every value of the current object.
62
+ if (head === "{}") {
63
+ const container = obj;
64
+ for (const key of Object.keys(container)) {
65
+ const child = container[key];
66
+ if (rest.length === 0) {
67
+ if (isRefSentinel(child)) {
68
+ const target = byName.get(child.source);
69
+ if (target)
70
+ container[key] = { kind: target.kind, name: child.source };
71
+ }
72
+ }
73
+ else {
74
+ descend(child, rest, byName);
75
+ }
76
+ }
77
+ return;
78
+ }
79
+ const isArr = head.endsWith("[]");
80
+ const key = isArr ? head.slice(0, -2) : head;
81
+ const container = obj;
82
+ const val = container[key];
83
+ if (val == null)
84
+ return;
85
+ if (isArr) {
86
+ if (!Array.isArray(val))
87
+ return;
88
+ for (let i = 0; i < val.length; i++) {
89
+ if (rest.length === 0) {
90
+ const elem = val[i];
91
+ if (isRefSentinel(elem)) {
92
+ const target = byName.get(elem.source);
93
+ if (target)
94
+ val[i] = { kind: target.kind, name: elem.source };
95
+ }
96
+ }
97
+ else {
98
+ descend(val[i], rest, byName);
99
+ }
100
+ }
101
+ }
102
+ else {
103
+ if (rest.length === 0) {
104
+ if (isRefSentinel(val)) {
105
+ const target = byName.get(val.source);
106
+ if (target)
107
+ container[key] = { kind: target.kind, name: val.source };
108
+ }
109
+ }
110
+ else {
111
+ descend(val, rest, byName);
112
+ }
113
+ }
114
+ }
@@ -0,0 +1,10 @@
1
+ import type { ResourceManifest } from "@telorun/sdk";
2
+ import type { AnalysisDiagnostic } from "./types.js";
3
+ /** Diagnostics emitted on synthetic manifests (resources extracted by
4
+ * `normalizeInlineResources`) carry the synthetic's identity in
5
+ * `data.resource`, which has no YAML source. Rewrite each such diagnostic
6
+ * back to the chain root: walk up `metadata.xTeloOrigin` until a manifest
7
+ * with no origin is reached, and prepend each hop's `pathFromParent` to
8
+ * `data.path` so position-index lookups against the root doc resolve. */
9
+ export declare function rewriteSyntheticOrigins(diagnostics: AnalysisDiagnostic[], manifests: ResourceManifest[]): AnalysisDiagnostic[];
10
+ //# sourceMappingURL=rewrite-synthetic-origins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewrite-synthetic-origins.d.ts","sourceRoot":"","sources":["../src/rewrite-synthetic-origins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAsBrD;;;;;0EAK0E;AAC1E,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,kBAAkB,EAAE,EACjC,SAAS,EAAE,gBAAgB,EAAE,GAC5B,kBAAkB,EAAE,CA0CtB"}
@@ -0,0 +1,55 @@
1
+ function readOrigin(manifest) {
2
+ if (!manifest)
3
+ return undefined;
4
+ const origin = manifest.metadata?.xTeloOrigin;
5
+ if (!origin ||
6
+ typeof origin.parentKind !== "string" ||
7
+ typeof origin.parentName !== "string" ||
8
+ typeof origin.pathFromParent !== "string") {
9
+ return undefined;
10
+ }
11
+ return origin;
12
+ }
13
+ /** Diagnostics emitted on synthetic manifests (resources extracted by
14
+ * `normalizeInlineResources`) carry the synthetic's identity in
15
+ * `data.resource`, which has no YAML source. Rewrite each such diagnostic
16
+ * back to the chain root: walk up `metadata.xTeloOrigin` until a manifest
17
+ * with no origin is reached, and prepend each hop's `pathFromParent` to
18
+ * `data.path` so position-index lookups against the root doc resolve. */
19
+ export function rewriteSyntheticOrigins(diagnostics, manifests) {
20
+ const byName = new Map();
21
+ for (const m of manifests) {
22
+ const name = m.metadata?.name;
23
+ if (typeof name === "string")
24
+ byName.set(name, m);
25
+ }
26
+ return diagnostics.map((d) => {
27
+ const data = d.data;
28
+ if (!data?.resource?.name)
29
+ return d;
30
+ let current = byName.get(data.resource.name);
31
+ let origin = readOrigin(current);
32
+ if (!origin)
33
+ return d;
34
+ let accumPath = typeof data.path === "string" ? data.path : "";
35
+ let rootKind = origin.parentKind;
36
+ let rootName = origin.parentName;
37
+ while (origin) {
38
+ accumPath = accumPath ? `${origin.pathFromParent}.${accumPath}` : origin.pathFromParent;
39
+ rootKind = origin.parentKind;
40
+ rootName = origin.parentName;
41
+ current = byName.get(origin.parentName);
42
+ origin = readOrigin(current);
43
+ }
44
+ const rootFilePath = current?.metadata?.source ?? data.filePath;
45
+ return {
46
+ ...d,
47
+ data: {
48
+ ...data,
49
+ resource: { kind: rootKind, name: rootName },
50
+ filePath: rootFilePath,
51
+ path: accumPath,
52
+ },
53
+ };
54
+ });
55
+ }
@@ -1,6 +1,12 @@
1
1
  declare const Ajv: any;
2
2
  /** Creates a configured AJV instance (allErrors, strict: false, with formats).
3
- * Called once for the module-level instance and once per DefinitionRegistry instance. */
3
+ * Also registers the kernel manifest root schema under `telo://manifest` so
4
+ * module YAMLs can `$ref` into the shared `$defs/ResourceRef` (and any future
5
+ * shared fragments) from this analyzer's AJV without each module having to
6
+ * bundle its own copy.
7
+ *
8
+ * Called once for the module-level instance and once per
9
+ * DefinitionRegistry instance. */
4
10
  export declare function createAjv(): InstanceType<typeof Ajv>;
5
11
  export interface CompatibilityResult {
6
12
  compatible: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"schema-compat.d.ts","sourceRoot":"","sources":["../src/schema-compat.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,GAAG,KAA0C,CAAC;AAEpD;0FAC0F;AAC1F,wBAAgB,SAAS,IAAI,YAAY,CAAC,OAAO,GAAG,CAAC,CAMpD;AAKD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;oEAEoE;AACpE,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC1B,mBAAmB,CAIrB;AAiDD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAelD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAGxE;AAuBD,mFAAmF;AACnF,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;CACd;AAED,0GAA0G;AAC1G,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,WAAW,EAAE,CAe/F;AAED;qFACqF;AACrF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAQ7E;AAED;;;;6DAI6D;AAC7D,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAsBjC;AAED,8DAA8D;AAC9D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,MAAM,CAuBnF;AAED,wFAAwF;AACxF,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAqBhG;AAED,6EAA6E;AAC7E,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAiB5E;AA2BD;iGACiG;AACjG,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC/B,OAAO,CA2BT"}
1
+ {"version":3,"file":"schema-compat.d.ts","sourceRoot":"","sources":["../src/schema-compat.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,GAAG,KAA0C,CAAC;AAEpD;;;;;;;mCAOmC;AACnC,wBAAgB,SAAS,IAAI,YAAY,CAAC,OAAO,GAAG,CAAC,CAOpD;AAKD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;oEAEoE;AACpE,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC1B,mBAAmB,CAIrB;AAiDD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAelD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAGxE;AAuBD,mFAAmF;AACnF,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;CACd;AAED,0GAA0G;AAC1G,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,WAAW,EAAE,CAe/F;AAED;qFACqF;AACrF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAQ7E;AAED;;;;6DAI6D;AAC7D,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAsBjC;AAED,8DAA8D;AAC9D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,MAAM,CAuBnF;AAED,wFAAwF;AACxF,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAqBhG;AAED,6EAA6E;AAC7E,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAiB5E;AA2BD;iGACiG;AACjG,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC/B,OAAO,CAqCT"}
@@ -1,14 +1,21 @@
1
1
  import AjvModule from "ajv";
2
2
  import addFormats from "ajv-formats";
3
- import { isTaggedSentinel } from "@telorun/templating";
3
+ import { isRefSentinel, isTaggedSentinel, ManifestRootSchema } from "@telorun/templating";
4
4
  const Ajv = AjvModule.default ?? AjvModule;
5
5
  /** Creates a configured AJV instance (allErrors, strict: false, with formats).
6
- * Called once for the module-level instance and once per DefinitionRegistry instance. */
6
+ * Also registers the kernel manifest root schema under `telo://manifest` so
7
+ * module YAMLs can `$ref` into the shared `$defs/ResourceRef` (and any future
8
+ * shared fragments) from this analyzer's AJV without each module having to
9
+ * bundle its own copy.
10
+ *
11
+ * Called once for the module-level instance and once per
12
+ * DefinitionRegistry instance. */
7
13
  export function createAjv() {
8
14
  const instance = new Ajv({ allErrors: true, strict: false });
9
15
  addFormats.default
10
16
  ? addFormats.default(instance)
11
17
  : addFormats(instance);
18
+ instance.addSchema(ManifestRootSchema);
12
19
  return instance;
13
20
  }
14
21
  const ajv = createAjv();
@@ -270,6 +277,16 @@ export function substituteCelFields(data, schema, rootSchema) {
270
277
  if (typeof data === "string" && CEL_PURE_RE.test(data)) {
271
278
  return celPlaceholderForSchema(resolved);
272
279
  }
280
+ // `!ref <name>` sentinels are identity markers, not runtime values —
281
+ // schemas that opt into `$ref: "telo://manifest#/$defs/ResourceRef"`
282
+ // (or `anyOf` it alongside other shapes) need the actual sentinel
283
+ // object so AJV validates it against ResourceRefSchema. Collapsing it
284
+ // to a CEL placeholder would either fail the schema (when the slot
285
+ // expects the ResourceRef shape) or mask validation errors (when the
286
+ // slot expects something else entirely).
287
+ if (isRefSentinel(data)) {
288
+ return data;
289
+ }
273
290
  if (isTaggedSentinel(data)) {
274
291
  return celPlaceholderForSchema(resolved);
275
292
  }
@@ -0,0 +1,25 @@
1
+ /** Resource-kind sets used by analysis passes to decide what counts as a
2
+ * user-defined instance vs. a system-level blueprint. Pulled into one
3
+ * place so the three passes (reference validation, dependency graph,
4
+ * ref-sentinel resolution) don't drift; each pass exports its own
5
+ * scoped view with a comment explaining what's in and what's out. */
6
+ /** Skipped by reference validation: type blueprints whose own ref slots
7
+ * belong to a different phase (definition schema validation rather than
8
+ * per-resource validation). Telo.Application and Telo.Library
9
+ * intentionally fall through — Application has `targets` (real refs) and
10
+ * Library is harmless (no ref-bearing fields). Telo.Import is also
11
+ * intentionally not skipped — its `source` is not an x-telo-ref slot, so
12
+ * walking it is cheap and consistent. */
13
+ export declare const REF_VALIDATION_SKIP_KINDS: ReadonlySet<string>;
14
+ /** Excluded from the dependency graph: kinds that are not runtime nodes.
15
+ * Telo.Abstract is intentionally not in this set today — abstracts have
16
+ * no resource manifests, so they never reach graph construction; if
17
+ * that ever changes, add it explicitly. */
18
+ export declare const DEPENDENCY_GRAPH_SKIP_KINDS: ReadonlySet<string>;
19
+ /** Skipped by `!ref` sentinel resolution: kinds whose bodies are
20
+ * blueprints or import-time metadata, not resource instances with
21
+ * user-referenced ref slots. Mirrors `REF_VALIDATION_SKIP_KINDS` but
22
+ * also drops Telo.Import (its `source` isn't a ref slot, and walking
23
+ * the field map on it is pointless since there's no registered kind). */
24
+ export declare const REF_RESOLUTION_SKIP_KINDS: ReadonlySet<string>;
25
+ //# sourceMappingURL=system-kinds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-kinds.d.ts","sourceRoot":"","sources":["../src/system-kinds.ts"],"names":[],"mappings":"AAAA;;;;sEAIsE;AAEtE;;;;;;0CAM0C;AAC1C,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,MAAM,CAGxD,CAAC;AAEH;;;4CAG4C;AAC5C,eAAO,MAAM,2BAA2B,EAAE,WAAW,CAAC,MAAM,CAG1D,CAAC;AAEH;;;;0EAI0E;AAC1E,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,MAAM,CAIxD,CAAC"}
@@ -0,0 +1,34 @@
1
+ /** Resource-kind sets used by analysis passes to decide what counts as a
2
+ * user-defined instance vs. a system-level blueprint. Pulled into one
3
+ * place so the three passes (reference validation, dependency graph,
4
+ * ref-sentinel resolution) don't drift; each pass exports its own
5
+ * scoped view with a comment explaining what's in and what's out. */
6
+ /** Skipped by reference validation: type blueprints whose own ref slots
7
+ * belong to a different phase (definition schema validation rather than
8
+ * per-resource validation). Telo.Application and Telo.Library
9
+ * intentionally fall through — Application has `targets` (real refs) and
10
+ * Library is harmless (no ref-bearing fields). Telo.Import is also
11
+ * intentionally not skipped — its `source` is not an x-telo-ref slot, so
12
+ * walking it is cheap and consistent. */
13
+ export const REF_VALIDATION_SKIP_KINDS = new Set([
14
+ "Telo.Definition",
15
+ "Telo.Abstract",
16
+ ]);
17
+ /** Excluded from the dependency graph: kinds that are not runtime nodes.
18
+ * Telo.Abstract is intentionally not in this set today — abstracts have
19
+ * no resource manifests, so they never reach graph construction; if
20
+ * that ever changes, add it explicitly. */
21
+ export const DEPENDENCY_GRAPH_SKIP_KINDS = new Set([
22
+ "Telo.Definition",
23
+ "Telo.Import",
24
+ ]);
25
+ /** Skipped by `!ref` sentinel resolution: kinds whose bodies are
26
+ * blueprints or import-time metadata, not resource instances with
27
+ * user-referenced ref slots. Mirrors `REF_VALIDATION_SKIP_KINDS` but
28
+ * also drops Telo.Import (its `source` isn't a ref slot, and walking
29
+ * the field map on it is pointless since there's no registered kind). */
30
+ export const REF_RESOLUTION_SKIP_KINDS = new Set([
31
+ "Telo.Definition",
32
+ "Telo.Abstract",
33
+ "Telo.Import",
34
+ ]);
package/dist/types.d.ts CHANGED
@@ -73,6 +73,18 @@ export interface LoaderInitOptions {
73
73
  }
74
74
  export interface AnalysisOptions {
75
75
  strictContexts?: boolean;
76
+ /** When true, `analyze()` runs the state-mutating setup (module identity /
77
+ * alias / definition registration plus `normalizeInlineResources`) but
78
+ * skips every diagnostic-producing pass — per-resource validation, the
79
+ * Library `env:` check, `validateExtends`, `validateProviderCoherence`,
80
+ * and `validateThrowsCoverage`. Used by the kernel when a previous load
81
+ * has already stamped the manifest set as valid (by content hash), so
82
+ * the registry still gets populated without paying the validation walk
83
+ * on every cold start. The caller takes responsibility for the
84
+ * correctness guarantee — pass this only when something durable
85
+ * (on-disk stamp) attests that the manifests passed a real analyze
86
+ * pass at the same analyzer / kernel version. */
87
+ skipValidation?: boolean;
76
88
  }
77
89
  /** Pre-seeded state for incremental analysis. Passed to StaticAnalyzer.analyze() so it does
78
90
  * not rebuild from scratch on every call. The provided instances are mutated — new definitions
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;qHACqH;AACrH,eAAO,MAAM,kBAAkB;;;;;CAKrB,CAAC;AACX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC;AAE9F,gFAAgF;AAChF,eAAO,MAAM,yBAAyB,cAAc,CAAC;AAErD,MAAM,WAAW,QAAQ;IACvB,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,QAAQ,CAAC;IAChB,GAAG,EAAE,QAAQ,CAAC;CACf;AAED;;oDAEoD;AACpD,MAAM,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAE/C;6EAC6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAExD;;qEAEiE;IACjE,UAAU,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEjE;;qEAEiE;IACjE,cAAc,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,WAAW;IAC1B;;;+EAG2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,YAAY,CAAC,EAAE,cAAc,EAAE,CAAC;IAChC,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,yDAAyD;IACzD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;6FACyF;IACzF,WAAW,CAAC,EAAE,OAAO,sBAAsB,EAAE,WAAW,CAAC;CAC1D;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;gEAKgE;AAChE,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,OAAO,qBAAqB,EAAE,aAAa,CAAC;IACtD,WAAW,CAAC,EAAE,OAAO,0BAA0B,EAAE,kBAAkB,CAAC;IACpE;;;;+EAI2E;IAC3E,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,qBAAqB,EAAE,aAAa,CAAC,CAAC;CAC5E"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;qHACqH;AACrH,eAAO,MAAM,kBAAkB;;;;;CAKrB,CAAC;AACX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC;AAE9F,gFAAgF;AAChF,eAAO,MAAM,yBAAyB,cAAc,CAAC;AAErD,MAAM,WAAW,QAAQ;IACvB,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,QAAQ,CAAC;IAChB,GAAG,EAAE,QAAQ,CAAC;CACf;AAED;;oDAEoD;AACpD,MAAM,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAE/C;6EAC6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAExD;;qEAEiE;IACjE,UAAU,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEjE;;qEAEiE;IACjE,cAAc,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,WAAW;IAC1B;;;+EAG2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,YAAY,CAAC,EAAE,cAAc,EAAE,CAAC;IAChC,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,yDAAyD;IACzD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;6FACyF;IACzF,WAAW,CAAC,EAAE,OAAO,sBAAsB,EAAE,WAAW,CAAC;CAC1D;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;;;;;sDAUkD;IAClD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;gEAKgE;AAChE,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,OAAO,qBAAqB,EAAE,aAAa,CAAC;IACtD,WAAW,CAAC,EAAE,OAAO,0BAA0B,EAAE,kBAAkB,CAAC;IACpE;;;;+EAI2E;IAC3E,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,qBAAqB,EAAE,aAAa,CAAC,CAAC;CAC5E"}
@@ -63,6 +63,11 @@ export declare function pathMatchesScope(exprPath: string, scope: string): boole
63
63
  * `manifestRoot.provide.kind` as a kind name, looks up the kind's Telo.Definition,
64
64
  * and returns the `outputType` schema.
65
65
  *
66
+ * Accepts either a single string or an array of strings. With an array, paths
67
+ * are tried in order and the first one that resolves to a usable schema wins —
68
+ * used by `result:` to find its dispatch target under whichever entry-point
69
+ * field (`provide:` or `invoke:`) the definition declares.
70
+ *
66
71
  * - `x-telo-context-ref-from`: existing form — reads `{kind, name}` object from
67
72
  * `manifestItem.<path>`, looks up the named manifest, returns its `<subpath>` field.
68
73
  *