@telorun/analyzer 0.48.0 → 0.49.1
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/dist/analysis-registry.d.ts +22 -11
- package/dist/analysis-registry.d.ts.map +1 -1
- package/dist/analysis-registry.js +36 -39
- package/dist/analyzer.d.ts +38 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +115 -83
- package/dist/builtins.d.ts.map +1 -1
- package/dist/builtins.js +72 -1
- package/dist/extends-resolution.d.ts +41 -0
- package/dist/extends-resolution.d.ts.map +1 -1
- package/dist/extends-resolution.js +68 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/invocation-contract.d.ts +100 -0
- package/dist/invocation-contract.d.ts.map +1 -0
- package/dist/invocation-contract.js +208 -0
- package/dist/manifest-loader.d.ts +11 -0
- package/dist/manifest-loader.d.ts.map +1 -1
- package/dist/manifest-loader.js +20 -0
- package/dist/schema-compat.d.ts +12 -4
- package/dist/schema-compat.d.ts.map +1 -1
- package/dist/schema-compat.js +185 -9
- package/dist/validate-base-mapping.js +11 -1
- package/dist/validate-cel-context.d.ts +0 -6
- package/dist/validate-cel-context.d.ts.map +1 -1
- package/dist/validate-cel-context.js +51 -4
- package/dist/validate-invocation-contract.d.ts +30 -0
- package/dist/validate-invocation-contract.d.ts.map +1 -0
- package/dist/validate-invocation-contract.js +394 -0
- package/dist/validate-step-inputs.d.ts +24 -0
- package/dist/validate-step-inputs.d.ts.map +1 -0
- package/dist/validate-step-inputs.js +87 -0
- package/dist/validate-throws-coverage.d.ts +1 -1
- package/dist/validate-throws-coverage.d.ts.map +1 -1
- package/dist/validate-throws-coverage.js +9 -1
- package/package.json +3 -3
- package/src/analysis-registry.ts +44 -34
- package/src/analyzer.ts +171 -100
- package/src/builtins.ts +74 -1
- package/src/extends-resolution.ts +86 -0
- package/src/index.ts +13 -1
- package/src/invocation-contract.ts +275 -0
- package/src/manifest-loader.ts +20 -0
- package/src/schema-compat.ts +191 -8
- package/src/validate-base-mapping.ts +14 -1
- package/src/validate-cel-context.ts +49 -4
- package/src/validate-invocation-contract.ts +450 -0
- package/src/validate-step-inputs.ts +117 -0
- package/src/validate-throws-coverage.ts +12 -2
|
@@ -62,20 +62,25 @@ export declare class AnalysisRegistry {
|
|
|
62
62
|
* unresolvable. */
|
|
63
63
|
capabilityForRef(xTeloRef: string): string | undefined;
|
|
64
64
|
/** Resolves the JSON Schema for a kind's `invoke()` inputs, for editor hosts
|
|
65
|
-
* that render a typed inputs form.
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
65
|
+
* that render a typed inputs form. A thin wrapper over the shared contract
|
|
66
|
+
* resolver, so the form an editor renders is the contract `telo check` and the
|
|
67
|
+
* kernel enforce — nearest declaration along `extends`, replacing rather than
|
|
68
|
+
* merging. A bare named type reference is left unresolved (returns undefined,
|
|
69
|
+
* no manifests are in scope here) so the caller can fall back to a freeform
|
|
70
|
+
* map. Undefined when the kind declares no input contract. */
|
|
71
71
|
inputTypeForKind(kind: string): Record<string, unknown> | undefined;
|
|
72
|
-
/** Resolves the JSON Schema for a kind's `invoke()` / `
|
|
72
|
+
/** Resolves the JSON Schema for a kind's `invoke()` / `provide()` output, for
|
|
73
73
|
* editor hosts that render a typed output signature. Mirrors
|
|
74
|
-
* {@link inputTypeForKind}
|
|
75
|
-
*
|
|
76
|
-
* raw-schema forms; a bare named type reference is left unresolved. Undefined
|
|
77
|
-
* when the kind declares no output contract. */
|
|
74
|
+
* {@link inputTypeForKind}. Undefined when the kind declares no output
|
|
75
|
+
* contract. */
|
|
78
76
|
outputTypeForKind(kind: string): Record<string, unknown> | undefined;
|
|
77
|
+
private contractForKind;
|
|
78
|
+
/** A resolver that re-scopes at every hop of an `extends` chain: each kind is
|
|
79
|
+
* resolved in the module that DECLARED the definition it was read off, since
|
|
80
|
+
* `extends` aliases are lexical. `resolveParent` always passes that definition
|
|
81
|
+
* as `from`, so one resolver serves a chain of any depth crossing any number
|
|
82
|
+
* of modules. */
|
|
83
|
+
private scopedDefResolver;
|
|
79
84
|
private capabilitiesForRefs;
|
|
80
85
|
/**
|
|
81
86
|
* Walks a manifest's annotation sites (refs, scopes, schema-from, CEL) via
|
|
@@ -96,6 +101,12 @@ export declare class AnalysisRegistry {
|
|
|
96
101
|
*/
|
|
97
102
|
builtinDefinitions(): ResourceDefinition[];
|
|
98
103
|
resolveDefinition(kind: string): ResourceDefinition | undefined;
|
|
104
|
+
/** Resolve a kind in a named module's scope. The entry point for walking an
|
|
105
|
+
* `extends` chain from outside it (the kernel's contract binding): aliases are
|
|
106
|
+
* lexical, so each hop must resolve in the module that declared the definition
|
|
107
|
+
* the kind was read off. Falls back to the global table when the module is
|
|
108
|
+
* unknown or is a root. */
|
|
109
|
+
resolveDefinitionIn(kind: string, module?: string): ResourceDefinition | undefined;
|
|
99
110
|
/** A resolver scoped to `def`'s OWN module, for resolving that definition's
|
|
100
111
|
* `extends` target.
|
|
101
112
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKzE,OAAO,EAAqC,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,8 +3,8 @@ import { KERNEL_BUILTINS } from "./builtins.js";
|
|
|
3
3
|
import { DefinitionRegistry } from "./definition-registry.js";
|
|
4
4
|
import { computeSuggestKind, computeValidUserFacingKinds } from "./kind-suggest.js";
|
|
5
5
|
import { visitManifest as runVisitManifest } from "./manifest-visitor.js";
|
|
6
|
+
import { resolveContract } from "./invocation-contract.js";
|
|
6
7
|
import { isRefEntry, isScopeEntry } from "./reference-field-map.js";
|
|
7
|
-
import { resolveTypeFieldToSchema } from "./validate-cel-context.js";
|
|
8
8
|
/**
|
|
9
9
|
* Accumulates type and alias knowledge for a running kernel or analysis session.
|
|
10
10
|
* Wraps AliasResolver and DefinitionRegistry into a single domain-level interface
|
|
@@ -96,51 +96,38 @@ export class AnalysisRegistry {
|
|
|
96
96
|
return def.capability ?? kind;
|
|
97
97
|
}
|
|
98
98
|
/** Resolves the JSON Schema for a kind's `invoke()` inputs, for editor hosts
|
|
99
|
-
* that render a typed inputs form.
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
99
|
+
* that render a typed inputs form. A thin wrapper over the shared contract
|
|
100
|
+
* resolver, so the form an editor renders is the contract `telo check` and the
|
|
101
|
+
* kernel enforce — nearest declaration along `extends`, replacing rather than
|
|
102
|
+
* merging. A bare named type reference is left unresolved (returns undefined,
|
|
103
|
+
* no manifests are in scope here) so the caller can fall back to a freeform
|
|
104
|
+
* map. Undefined when the kind declares no input contract. */
|
|
105
105
|
inputTypeForKind(kind) {
|
|
106
|
-
|
|
107
|
-
if (!def)
|
|
108
|
-
return undefined;
|
|
109
|
-
const own = resolveTypeFieldToSchema(def.inputType, []);
|
|
110
|
-
if (own)
|
|
111
|
-
return own;
|
|
112
|
-
if (def.extends) {
|
|
113
|
-
const abstractDef = this.resolveDefinition(def.extends);
|
|
114
|
-
if (abstractDef) {
|
|
115
|
-
const inherited = resolveTypeFieldToSchema(abstractDef.inputType, []);
|
|
116
|
-
if (inherited)
|
|
117
|
-
return inherited;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return undefined;
|
|
106
|
+
return this.contractForKind(kind, "inputType");
|
|
121
107
|
}
|
|
122
|
-
/** Resolves the JSON Schema for a kind's `invoke()` / `
|
|
108
|
+
/** Resolves the JSON Schema for a kind's `invoke()` / `provide()` output, for
|
|
123
109
|
* editor hosts that render a typed output signature. Mirrors
|
|
124
|
-
* {@link inputTypeForKind}
|
|
125
|
-
*
|
|
126
|
-
* raw-schema forms; a bare named type reference is left unresolved. Undefined
|
|
127
|
-
* when the kind declares no output contract. */
|
|
110
|
+
* {@link inputTypeForKind}. Undefined when the kind declares no output
|
|
111
|
+
* contract. */
|
|
128
112
|
outputTypeForKind(kind) {
|
|
113
|
+
return this.contractForKind(kind, "outputType");
|
|
114
|
+
}
|
|
115
|
+
contractForKind(kind, direction) {
|
|
129
116
|
const def = this.resolveDefinition(kind);
|
|
130
117
|
if (!def)
|
|
131
118
|
return undefined;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
return
|
|
119
|
+
return resolveContract(direction, undefined, def, {
|
|
120
|
+
resolveDefinition: this.scopedDefResolver(),
|
|
121
|
+
typeManifestsFor: () => [],
|
|
122
|
+
})?.schema;
|
|
123
|
+
}
|
|
124
|
+
/** A resolver that re-scopes at every hop of an `extends` chain: each kind is
|
|
125
|
+
* resolved in the module that DECLARED the definition it was read off, since
|
|
126
|
+
* `extends` aliases are lexical. `resolveParent` always passes that definition
|
|
127
|
+
* as `from`, so one resolver serves a chain of any depth crossing any number
|
|
128
|
+
* of modules. */
|
|
129
|
+
scopedDefResolver() {
|
|
130
|
+
return (kind, from) => this.resolveDefinitionIn(kind, from?.metadata?.module);
|
|
144
131
|
}
|
|
145
132
|
capabilitiesForRefs(refs) {
|
|
146
133
|
const out = [];
|
|
@@ -178,6 +165,16 @@ export class AnalysisRegistry {
|
|
|
178
165
|
const resolved = ctx.aliases?.resolveKind(kind);
|
|
179
166
|
return ctx.definitions?.resolve(kind) ?? (resolved ? ctx.definitions?.resolve(resolved) : undefined);
|
|
180
167
|
}
|
|
168
|
+
/** Resolve a kind in a named module's scope. The entry point for walking an
|
|
169
|
+
* `extends` chain from outside it (the kernel's contract binding): aliases are
|
|
170
|
+
* lexical, so each hop must resolve in the module that declared the definition
|
|
171
|
+
* the kind was read off. Falls back to the global table when the module is
|
|
172
|
+
* unknown or is a root. */
|
|
173
|
+
resolveDefinitionIn(kind, module) {
|
|
174
|
+
const scope = (module ? this.aliasesByModule.get(module) : undefined) ?? this.aliases;
|
|
175
|
+
const canonical = scope.resolveKind(kind);
|
|
176
|
+
return this.defs.resolve(kind) ?? (canonical ? this.defs.resolve(canonical) : undefined);
|
|
177
|
+
}
|
|
181
178
|
/** A resolver scoped to `def`'s OWN module, for resolving that definition's
|
|
182
179
|
* `extends` target.
|
|
183
180
|
*
|
package/dist/analyzer.d.ts
CHANGED
|
@@ -1,7 +1,44 @@
|
|
|
1
|
-
import type { ResourceManifest } from "@telorun/sdk";
|
|
1
|
+
import type { ResourceDefinition, ResourceManifest } from "@telorun/sdk";
|
|
2
|
+
import { AliasResolver, type ModuleScopes } from "./alias-resolver.js";
|
|
2
3
|
import { AnalysisRegistry } from "./analysis-registry.js";
|
|
3
4
|
import { type CelHandlers } from "./cel-environment.js";
|
|
5
|
+
import { DefinitionRegistry } from "./definition-registry.js";
|
|
6
|
+
import { type ContractScope } from "./invocation-contract.js";
|
|
4
7
|
import { type AnalysisDiagnostic, type AnalysisOptions } from "./types.js";
|
|
8
|
+
/** The {@link ContractScope} the analyzer resolves invocation contracts in: kinds
|
|
9
|
+
* resolve in the module that declared the definition they were read off (so an
|
|
10
|
+
* `extends` chain crossing module boundaries re-scopes at every hop), and named
|
|
11
|
+
* `telo#Type` references resolve against the flattened manifest list. `resolveIn`
|
|
12
|
+
* is the top-level entry point, where the kind was written by the READING
|
|
13
|
+
* module and there is no declaring definition yet. */
|
|
14
|
+
export declare function analyzerContractScope(defs: DefinitionRegistry, aliases: AliasResolver, scopes: ModuleScopes, allManifests: Record<string, any>[]): ContractScope & {
|
|
15
|
+
resolveIn(kind: string, module?: string): ResourceDefinition | undefined;
|
|
16
|
+
};
|
|
17
|
+
/** True when an issue reports a property that is absent — its path points at a
|
|
18
|
+
* node the manifest does not contain. */
|
|
19
|
+
export declare const missingRequired: (issue: {
|
|
20
|
+
message: string;
|
|
21
|
+
}) => boolean;
|
|
22
|
+
/** The path minus its last segment: the node that should have contained the
|
|
23
|
+
* missing property. Empty for a top-level miss, which anchors on the map. */
|
|
24
|
+
export declare function containerOf(path: string): string;
|
|
25
|
+
/** Resolve a local `$ref` (only `#/$defs/<name>` form) against the root schema.
|
|
26
|
+
* Non-refs and unresolved refs pass through unchanged. */
|
|
27
|
+
export declare function resolveLocalRef(schema: Record<string, any> | undefined, root: Record<string, any>): Record<string, any> | undefined;
|
|
28
|
+
/** Gather property schemas from a (possibly variant-bearing) object schema:
|
|
29
|
+
* top-level `properties` plus every `oneOf` / `anyOf` / `allOf` branch. */
|
|
30
|
+
export declare function gatherPropertySchemas(schema: Record<string, any>): Array<[string, Record<string, any>]>;
|
|
31
|
+
/**
|
|
32
|
+
* Generic, role-driven walk over an `x-telo-step-context` step array. Calls
|
|
33
|
+
* `visit(step, stepPath)` for every step — top-level and nested through the
|
|
34
|
+
* `x-telo-topology-role` forms (`branch`, `branch-list`, `case-map`). This is
|
|
35
|
+
* the single definition of how steps nest, shared by `buildStepContextSchema`
|
|
36
|
+
* (which types `steps.<name>.result`) and `validateStepInvokeReferences` (which
|
|
37
|
+
* checks invoke refs), so the topology contract lives in one place — adding a
|
|
38
|
+
* role or nesting form updates both consumers at once. No resource kind is
|
|
39
|
+
* hardcoded; recursion is driven entirely by the schema annotations.
|
|
40
|
+
*/
|
|
41
|
+
export declare function walkStepArray(steps: unknown[], stepItemSchema: Record<string, any> | undefined, rootSchema: Record<string, any>, basePath: string, visit: (step: Record<string, any>, stepPath: string) => void): void;
|
|
5
42
|
export interface StaticAnalyzerOptions {
|
|
6
43
|
celHandlers?: CelHandlers;
|
|
7
44
|
}
|
package/dist/analyzer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
|
package/dist/analyzer.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { canonicalTypeSchemaId, OBSERVED_STATE_KEY } from "@telorun/sdk";
|
|
2
2
|
import { defaultRegistry, isRefSentinel, isTaggedSentinel } from "@telorun/templating";
|
|
3
|
-
import { AliasResolver, scopeResolverForModule } from "./alias-resolver.js";
|
|
3
|
+
import { AliasResolver, moduleScopedDefResolver, scopeResolverForModule, } from "./alias-resolver.js";
|
|
4
4
|
import { buildCelEnvironment, buildImportInputCelEnvironment, buildTypedCelEnvironment, } from "./cel-environment.js";
|
|
5
5
|
import { DefinitionRegistry } from "./definition-registry.js";
|
|
6
6
|
import { effectiveAuthorSchema } from "./extends-resolution.js";
|
|
7
|
+
import { PERMISSIVE_CONTRACT, resolveContract, } from "./invocation-contract.js";
|
|
7
8
|
import { buildDependencyGraph, formatCycle } from "./dependency-graph.js";
|
|
8
9
|
import { buildKernelGlobalsSchema, mergeKernelGlobalsIntoContext } from "./kernel-globals.js";
|
|
9
10
|
import { buildObservedStateIndex, buildObservedStateResourcesSchema, collectRunReachableNames, observedStateRead, validateObservedStateDeclarations, } from "./validate-observed-state.js";
|
|
@@ -20,12 +21,14 @@ import { rewriteSyntheticOrigins } from "./rewrite-synthetic-origins.js";
|
|
|
20
21
|
import { celTypeSatisfiesJsonSchema, substituteCelFields, validateAgainstSchema, } from "./schema-compat.js";
|
|
21
22
|
import { collectValueSchemaIssues } from "./validate-value-schema.js";
|
|
22
23
|
import { DiagnosticSeverity } from "./types.js";
|
|
23
|
-
import { extractAccessChains, extractCelRegionScopes, extractContextsFromSchema, getManifestItem, pathMatchesScope, resolveContextAnnotations,
|
|
24
|
+
import { extractAccessChains, extractCelRegionScopes, extractContextsFromSchema, getManifestItem, pathMatchesScope, resolveContextAnnotations, } from "./validate-cel-context.js";
|
|
24
25
|
import { buildEvalPaths, evalPathsCover } from "./eval-paths.js";
|
|
25
26
|
import { validateExtends } from "./validate-extends.js";
|
|
26
27
|
import { validateLogging } from "./validate-logging.js";
|
|
27
28
|
import { validateModuleArtifact } from "./validate-module-artifact.js";
|
|
28
29
|
import { validateBaseMapping } from "./validate-base-mapping.js";
|
|
30
|
+
import { validateInvocationContract } from "./validate-invocation-contract.js";
|
|
31
|
+
import { collectStepInputIssues } from "./validate-step-inputs.js";
|
|
29
32
|
import { validateNestedInlineResources } from "./validate-nested-inline.js";
|
|
30
33
|
import { validateProviderCoherence } from "./validate-provider-coherence.js";
|
|
31
34
|
import { validateReferences } from "./validate-references.js";
|
|
@@ -75,17 +78,19 @@ function resolveSelfOrAlias(value, ownModule, scopeResolver) {
|
|
|
75
78
|
}
|
|
76
79
|
return scopeResolver.resolveKind(value);
|
|
77
80
|
}
|
|
78
|
-
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
/** The {@link ContractScope} the analyzer resolves invocation contracts in: kinds
|
|
82
|
+
* resolve in the module that declared the definition they were read off (so an
|
|
83
|
+
* `extends` chain crossing module boundaries re-scopes at every hop), and named
|
|
84
|
+
* `telo#Type` references resolve against the flattened manifest list. `resolveIn`
|
|
85
|
+
* is the top-level entry point, where the kind was written by the READING
|
|
86
|
+
* module and there is no declaring definition yet. */
|
|
87
|
+
export function analyzerContractScope(defs, aliases, scopes, allManifests) {
|
|
88
|
+
const resolve = moduleScopedDefResolver(defs, aliases, scopes);
|
|
89
|
+
return {
|
|
90
|
+
resolveDefinition: resolve,
|
|
91
|
+
resolveIn: resolve.in,
|
|
92
|
+
typeManifestsFor: () => allManifests,
|
|
93
|
+
};
|
|
89
94
|
}
|
|
90
95
|
const SOURCE = "telo-analyzer";
|
|
91
96
|
/** Build a closed JSON Schema for the `self` CEL variable available inside a
|
|
@@ -119,50 +124,66 @@ function buildSelfSchema(definition, defs, aliases) {
|
|
|
119
124
|
};
|
|
120
125
|
}
|
|
121
126
|
/** Build the JSON Schema for the `inputs` CEL variable available inside an
|
|
122
|
-
* invocable template body
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const own = resolveTypeFieldToSchema(definition.inputType, allManifests);
|
|
131
|
-
if (own)
|
|
132
|
-
return own;
|
|
133
|
-
const ext = definition.extends;
|
|
134
|
-
if (typeof ext === "string" && ext.length > 0) {
|
|
135
|
-
const canonical = aliases.resolveKind(ext) ?? ext;
|
|
136
|
-
const abstractDef = defs.resolve(canonical);
|
|
137
|
-
if (abstractDef) {
|
|
138
|
-
const inherited = resolveTypeFieldToSchema(abstractDef.inputType, allManifests);
|
|
139
|
-
if (inherited)
|
|
140
|
-
return inherited;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return undefined;
|
|
127
|
+
* invocable template body — the shared contract resolver applied to the
|
|
128
|
+
* definition itself, so a body is typed against the exact signature callers are
|
|
129
|
+
* checked against and dispatch enforces. Walks the whole `extends` chain rather
|
|
130
|
+
* than one hop, so a definition two levels below the declaration still gets
|
|
131
|
+
* typed inputs. Undefined when nothing in the chain declares a contract —
|
|
132
|
+
* the caller signals opaque `map<string, dyn>` upstream. */
|
|
133
|
+
function lookupTemplateInputsSchema(definition, defs, aliases, allManifests, scopes) {
|
|
134
|
+
return resolveContract("inputType", undefined, definition, analyzerContractScope(defs, aliases, scopes, allManifests))?.schema;
|
|
144
135
|
}
|
|
145
136
|
/** Returns a "resolver-facing" view of the manifest where the fields used as
|
|
146
137
|
* navigation roots by Telo.Definition's `x-telo-context-from-root` annotations
|
|
147
138
|
* have been pre-augmented:
|
|
148
139
|
* - `schema` → augmented `self` schema (synthetic `name`/`kind`/metadata).
|
|
149
|
-
* - `inputType` → resolved
|
|
150
|
-
*
|
|
140
|
+
* - `inputType` → resolved through the shared contract resolver, so
|
|
141
|
+
* `x-telo-context-from-root: inputType` substitutes the
|
|
142
|
+
* real signature. Without it the annotation would replace
|
|
143
|
+
* the node verbatim with the inline `{kind, schema}` wrapper
|
|
144
|
+
* the standard library writes everywhere, typing `inputs` as
|
|
145
|
+
* `{kind, schema}` instead of the declared properties.
|
|
151
146
|
*
|
|
152
147
|
* For non-definition manifests the original object is returned. */
|
|
153
|
-
function manifestRootForResolver(m, defs, aliases, allManifests) {
|
|
148
|
+
function manifestRootForResolver(m, defs, aliases, allManifests, scopes) {
|
|
154
149
|
if (m.kind !== "Telo.Definition")
|
|
155
150
|
return m;
|
|
156
|
-
const inputs = lookupTemplateInputsSchema(m, defs, aliases, allManifests);
|
|
151
|
+
const inputs = lookupTemplateInputsSchema(m, defs, aliases, allManifests, scopes);
|
|
157
152
|
return {
|
|
158
153
|
...m,
|
|
159
154
|
schema: buildSelfSchema(m, defs, aliases),
|
|
160
155
|
...(inputs ? { inputType: inputs } : {}),
|
|
161
156
|
};
|
|
162
157
|
}
|
|
158
|
+
/** True when an issue reports a property that is absent — its path points at a
|
|
159
|
+
* node the manifest does not contain. */
|
|
160
|
+
export const missingRequired = (issue) => /is missing required property/.test(issue.message);
|
|
161
|
+
/** The path minus its last segment: the node that should have contained the
|
|
162
|
+
* missing property. Empty for a top-level miss, which anchors on the map. */
|
|
163
|
+
export function containerOf(path) {
|
|
164
|
+
const dot = path.lastIndexOf(".");
|
|
165
|
+
return dot === -1 ? "" : path.slice(0, dot);
|
|
166
|
+
}
|
|
167
|
+
/** How to name the owner of a resolved contract in a diagnostic. When the
|
|
168
|
+
* contract came from the definition's direct parent, echo the author's own
|
|
169
|
+
* spelling (`extends: Mcp.SessionProvider`) — that is the text they can find in
|
|
170
|
+
* their file. A contract inherited from further up the chain isn't written
|
|
171
|
+
* anywhere in this file, so the canonical `module.Kind` is what locates it. */
|
|
172
|
+
function contractOwnerLabel(definition, contract) {
|
|
173
|
+
const declaredBy = contract.declaredBy;
|
|
174
|
+
if (!declaredBy || declaredBy === definition) {
|
|
175
|
+
return String(definition.metadata?.name ?? definition.kind);
|
|
176
|
+
}
|
|
177
|
+
const parentSpelling = definition.extends;
|
|
178
|
+
const canonical = `${declaredBy.metadata.module}.${declaredBy.metadata.name}`;
|
|
179
|
+
if (typeof parentSpelling === "string" && parentSpelling.endsWith(`.${declaredBy.metadata.name}`)) {
|
|
180
|
+
return parentSpelling;
|
|
181
|
+
}
|
|
182
|
+
return canonical;
|
|
183
|
+
}
|
|
163
184
|
/** Resolve a local `$ref` (only `#/$defs/<name>` form) against the root schema.
|
|
164
185
|
* Non-refs and unresolved refs pass through unchanged. */
|
|
165
|
-
function resolveLocalRef(schema, root) {
|
|
186
|
+
export function resolveLocalRef(schema, root) {
|
|
166
187
|
if (!schema)
|
|
167
188
|
return undefined;
|
|
168
189
|
const ref = schema.$ref;
|
|
@@ -176,7 +197,7 @@ function resolveLocalRef(schema, root) {
|
|
|
176
197
|
}
|
|
177
198
|
/** Gather property schemas from a (possibly variant-bearing) object schema:
|
|
178
199
|
* top-level `properties` plus every `oneOf` / `anyOf` / `allOf` branch. */
|
|
179
|
-
function gatherPropertySchemas(schema) {
|
|
200
|
+
export function gatherPropertySchemas(schema) {
|
|
180
201
|
const out = [];
|
|
181
202
|
if (schema.properties && typeof schema.properties === "object") {
|
|
182
203
|
for (const [k, v] of Object.entries(schema.properties)) {
|
|
@@ -207,7 +228,7 @@ function gatherPropertySchemas(schema) {
|
|
|
207
228
|
* role or nesting form updates both consumers at once. No resource kind is
|
|
208
229
|
* hardcoded; recursion is driven entirely by the schema annotations.
|
|
209
230
|
*/
|
|
210
|
-
function walkStepArray(steps, stepItemSchema, rootSchema, basePath, visit) {
|
|
231
|
+
export function walkStepArray(steps, stepItemSchema, rootSchema, basePath, visit) {
|
|
211
232
|
const dispatchRole = (data, role, itemsSchema, path) => {
|
|
212
233
|
if (role === "branch" && Array.isArray(data)) {
|
|
213
234
|
walkStepArray(data, stepItemSchema, rootSchema, path, visit);
|
|
@@ -252,20 +273,18 @@ function walkStepArray(steps, stepItemSchema, rootSchema, basePath, visit) {
|
|
|
252
273
|
}
|
|
253
274
|
/**
|
|
254
275
|
* Build a `steps` context schema from `x-telo-step-context` annotation.
|
|
255
|
-
* Walks each step in the manifest array, resolves the invoked resource's
|
|
256
|
-
* and builds `steps.<name>.result` context entries.
|
|
276
|
+
* Walks each step in the manifest array, resolves the invoked resource's output
|
|
277
|
+
* contract, and builds `steps.<name>.result` context entries.
|
|
257
278
|
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
* 3. Permissive `{type: object, additionalProperties: true}` if neither
|
|
264
|
-
* yields a schema.
|
|
279
|
+
* Resolution is the shared {@link resolveContract} — the invoked resource
|
|
280
|
+
* manifest's own declaration, then the kind's, resolved to the nearest
|
|
281
|
+
* declaration along `extends`, then permissive. Sharing it with the kernel is
|
|
282
|
+
* what stops `telo check` from typing `steps.X.result` against one contract
|
|
283
|
+
* while dispatch validates against another.
|
|
265
284
|
*
|
|
266
|
-
*
|
|
267
|
-
* govern step-result chain validation — without it, the validator falls
|
|
268
|
-
* to permissive and the stream-opacity rule never fires.
|
|
285
|
+
* The kind layer is what makes `x-telo-stream` properties on definitions
|
|
286
|
+
* actually govern step-result chain validation — without it, the validator falls
|
|
287
|
+
* back to permissive and the stream-opacity rule never fires.
|
|
269
288
|
*
|
|
270
289
|
* Recursion into nested step arrays is annotation-driven via
|
|
271
290
|
* `x-telo-topology-role`. The analyzer recognises three role values:
|
|
@@ -276,10 +295,12 @@ function walkStepArray(steps, stepItemSchema, rootSchema, basePath, visit) {
|
|
|
276
295
|
* No specific Run.Sequence field name is hardcoded; any kind that uses
|
|
277
296
|
* `x-telo-step-context` and tags its branch fields with these roles works.
|
|
278
297
|
*/
|
|
279
|
-
function buildStepContextSchema(manifest, defSchema, allManifests, defs, aliases) {
|
|
298
|
+
function buildStepContextSchema(manifest, defSchema, allManifests, defs, aliases, scopes) {
|
|
280
299
|
const props = defSchema.properties;
|
|
281
300
|
if (!props)
|
|
282
301
|
return undefined;
|
|
302
|
+
const contractScope = analyzerContractScope(defs, aliases, scopes, allManifests);
|
|
303
|
+
const readingModule = manifest.metadata?.module;
|
|
283
304
|
for (const [fieldName, fieldSchema] of Object.entries(props)) {
|
|
284
305
|
const stepCtx = fieldSchema["x-telo-step-context"];
|
|
285
306
|
if (!stepCtx)
|
|
@@ -302,28 +323,22 @@ function buildStepContextSchema(manifest, defSchema, allManifests, defs, aliases
|
|
|
302
323
|
// or unknown step references slip through chain validation.
|
|
303
324
|
if (typeof name !== "string" || !invoke || typeof invoke !== "object")
|
|
304
325
|
return;
|
|
305
|
-
let outputSchema;
|
|
306
326
|
const invokedKind = invoke.kind;
|
|
307
327
|
const invokedName = invoke.name;
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
// Fallback: pull outputType from the kind's Telo.Definition. The
|
|
319
|
-
// resource manifest typically doesn't carry outputType; the def does.
|
|
320
|
-
if (!outputSchema && invokedKind) {
|
|
321
|
-
outputSchema = lookupDefinitionTypeField(invokedKind, outputTypeField, defs, aliases, allManifests);
|
|
322
|
-
}
|
|
328
|
+
// A named `!ref` carries the target's own manifest (which may narrow the
|
|
329
|
+
// contract for this one instance); an inline `{ kind, ... }` step IS the
|
|
330
|
+
// manifest. Either way the kind layer resolves through `extends`.
|
|
331
|
+
const invokedManifest = invokedName
|
|
332
|
+
? allManifests.find((m) => m.metadata?.name === invokedName && (!invokedKind || m.kind === invokedKind))
|
|
333
|
+
: invoke;
|
|
334
|
+
const invokedDef = invokedKind
|
|
335
|
+
? contractScope.resolveIn(invokedKind, readingModule)
|
|
336
|
+
: undefined;
|
|
337
|
+
const outputSchema = resolveContract(outputTypeField, invokedManifest, invokedDef, contractScope)?.schema;
|
|
323
338
|
stepProperties[name] = {
|
|
324
339
|
type: "object",
|
|
325
340
|
properties: {
|
|
326
|
-
result: outputSchema ??
|
|
341
|
+
result: outputSchema ?? PERMISSIVE_CONTRACT,
|
|
327
342
|
},
|
|
328
343
|
};
|
|
329
344
|
});
|
|
@@ -1318,6 +1333,7 @@ export class StaticAnalyzer {
|
|
|
1318
1333
|
// the abstract this definition `extends`. CEL fields inside the templated
|
|
1319
1334
|
// values are replaced with type-appropriate placeholders before AJV runs —
|
|
1320
1335
|
// same pattern as the per-resource schema validation above.
|
|
1336
|
+
const contractScope = analyzerContractScope(defs, aliases, { aliasesByModule, rootModules }, allManifests);
|
|
1321
1337
|
for (const m of allManifests) {
|
|
1322
1338
|
if (m.kind !== "Telo.Definition")
|
|
1323
1339
|
continue;
|
|
@@ -1360,25 +1376,23 @@ export class StaticAnalyzer {
|
|
|
1360
1376
|
// values passed to the dispatch target's invoke(). Validate against the
|
|
1361
1377
|
// target's declared `inputType` when both sides have one.
|
|
1362
1378
|
if (dispatchKind && md.inputs && typeof md.inputs === "object") {
|
|
1363
|
-
const targetSchema =
|
|
1379
|
+
const targetSchema = resolveContract("inputType", undefined, contractScope.resolveIn(dispatchKind, md.metadata?.module), contractScope)?.schema;
|
|
1364
1380
|
if (targetSchema) {
|
|
1365
1381
|
emitTargetMismatch(dispatchKind, targetSchema, md.inputs, "inputs");
|
|
1366
1382
|
}
|
|
1367
1383
|
}
|
|
1368
|
-
// Top-level `result:` is a post-call mapping that must satisfy
|
|
1369
|
-
//
|
|
1384
|
+
// Top-level `result:` is a post-call mapping that must satisfy THIS
|
|
1385
|
+
// definition's output contract — its own `outputType` when it declares
|
|
1386
|
+
// one, otherwise the nearest ancestor's. It's a sibling of whichever
|
|
1370
1387
|
// dispatch entry-point declared a kind-typed target (`provide:` or
|
|
1371
1388
|
// `invoke:`). The target's outputType lives on the dispatcher's `kind`
|
|
1372
1389
|
// and is what `result` is typed against *inside* CEL — separate role.
|
|
1373
1390
|
const hasDispatchObject = (provide && typeof provide === "object" && !Array.isArray(provide)) ||
|
|
1374
1391
|
(invoke && typeof invoke === "object" && !Array.isArray(invoke));
|
|
1375
1392
|
if (hasDispatchObject && md.result && typeof md.result === "object") {
|
|
1376
|
-
const
|
|
1377
|
-
if (
|
|
1378
|
-
|
|
1379
|
-
if (abstractSchema) {
|
|
1380
|
-
emitTargetMismatch(extendsValue, abstractSchema, md.result, "result");
|
|
1381
|
-
}
|
|
1393
|
+
const contract = resolveContract("outputType", undefined, md, contractScope);
|
|
1394
|
+
if (contract) {
|
|
1395
|
+
emitTargetMismatch(contractOwnerLabel(md, contract), contract.schema, md.result, "result");
|
|
1382
1396
|
}
|
|
1383
1397
|
}
|
|
1384
1398
|
}
|
|
@@ -1410,8 +1424,25 @@ export class StaticAnalyzer {
|
|
|
1410
1424
|
const m = e.source;
|
|
1411
1425
|
celInvocationContext = m.metadata?.xTeloInvocationContext;
|
|
1412
1426
|
celStepContextSchema = e.definition?.schema
|
|
1413
|
-
? buildStepContextSchema(m, e.definition.schema, allManifests, defs, aliases)
|
|
1427
|
+
? buildStepContextSchema(m, e.definition.schema, allManifests, defs, aliases, { aliasesByModule, rootModules })
|
|
1414
1428
|
: undefined;
|
|
1429
|
+
if (e.definition?.schema) {
|
|
1430
|
+
const stepName = m.metadata?.name;
|
|
1431
|
+
const stepFile = m.metadata?.source;
|
|
1432
|
+
for (const issue of collectStepInputIssues(m, e.definition.schema, allManifests, defs, aliases, { aliasesByModule, rootModules })) {
|
|
1433
|
+
diagnostics.push({
|
|
1434
|
+
severity: DiagnosticSeverity.Error,
|
|
1435
|
+
code: "CONTRACT_INPUTS_MISMATCH",
|
|
1436
|
+
source: SOURCE,
|
|
1437
|
+
message: `${m.kind}/${stepName}: inputs at '${issue.path}' do not satisfy ${issue.targetLabel}'s declared inputType: ${issue.message}`,
|
|
1438
|
+
data: {
|
|
1439
|
+
resource: { kind: m.kind, name: stepName ?? "" },
|
|
1440
|
+
filePath: stepFile,
|
|
1441
|
+
path: issue.path,
|
|
1442
|
+
},
|
|
1443
|
+
});
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1415
1446
|
celErrorScopes = collectErrorContextScopes(e.definition?.schema);
|
|
1416
1447
|
// The non-eval-field check only applies to runtime resource instances:
|
|
1417
1448
|
// structural / templating kinds (capability `Telo.Template`, or no
|
|
@@ -1527,7 +1558,7 @@ export class StaticAnalyzer {
|
|
|
1527
1558
|
const manifestItem = matchedScope
|
|
1528
1559
|
? getManifestItem(path, matchedScope, m)
|
|
1529
1560
|
: m;
|
|
1530
|
-
const rootForResolver = manifestRootForResolver(m, defs, aliases, allManifests);
|
|
1561
|
+
const rootForResolver = manifestRootForResolver(m, defs, aliases, allManifests, { aliasesByModule, rootModules });
|
|
1531
1562
|
const resolvedContext = resolveContextAnnotations(matchedContext, manifestItem, {
|
|
1532
1563
|
manifestRoot: rootForResolver,
|
|
1533
1564
|
defs,
|
|
@@ -1625,6 +1656,7 @@ export class StaticAnalyzer {
|
|
|
1625
1656
|
// Validate `extends` fields and flag legacy `capability: <UserAbstract>` overload.
|
|
1626
1657
|
diagnostics.push(...validateExtends(allManifests, defs, aliases));
|
|
1627
1658
|
diagnostics.push(...validateBaseMapping(allManifests, defs, aliases));
|
|
1659
|
+
diagnostics.push(...validateInvocationContract(allManifests, defs, aliases, aliasesByModule));
|
|
1628
1660
|
// Validate provider coherence rules for `provide:` template-target definitions.
|
|
1629
1661
|
diagnostics.push(...validateProviderCoherence(allManifests, defs, aliases));
|
|
1630
1662
|
// Validate throws: declarations and catches: coverage (rules 1, 2, 4, 7)
|
package/dist/builtins.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AA2JvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AA2JvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,EAmsB/C,CAAC"}
|