@telorun/analyzer 0.62.1 → 0.63.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/dist/analysis-registry.d.ts.map +1 -1
- package/dist/analysis-registry.js +6 -0
- package/dist/analyzer.d.ts +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +343 -13
- package/dist/call-graph.d.ts.map +1 -1
- package/dist/call-graph.js +2 -7
- package/dist/flatten-for-analyzer.js +1 -1
- package/dist/import-resolution-diagnostics.d.ts +9 -2
- package/dist/import-resolution-diagnostics.d.ts.map +1 -1
- package/dist/import-resolution-diagnostics.js +26 -7
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/invocation-contract.d.ts +6 -1
- package/dist/invocation-contract.d.ts.map +1 -1
- package/dist/invocation-contract.js +27 -4
- package/dist/loaded-types.d.ts +12 -3
- package/dist/loaded-types.d.ts.map +1 -1
- package/dist/manifest-loader.d.ts +0 -1
- package/dist/manifest-loader.d.ts.map +1 -1
- package/dist/manifest-loader.js +62 -41
- package/dist/manifest-schemas.d.ts +699 -0
- package/dist/manifest-schemas.d.ts.map +1 -1
- package/dist/manifest-schemas.js +306 -14
- package/dist/module-compatibility.d.ts +40 -0
- package/dist/module-compatibility.d.ts.map +1 -0
- package/dist/module-compatibility.js +52 -0
- package/dist/ref-slot-reading.d.ts +30 -0
- package/dist/ref-slot-reading.d.ts.map +1 -0
- package/dist/ref-slot-reading.js +139 -0
- package/dist/referrer-rule.d.ts +67 -0
- package/dist/referrer-rule.d.ts.map +1 -0
- package/dist/referrer-rule.js +96 -0
- package/dist/release/index.d.ts +1 -1
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +1 -1
- package/dist/release/version-stamp.d.ts +16 -0
- package/dist/release/version-stamp.d.ts.map +1 -1
- package/dist/release/version-stamp.js +52 -0
- package/dist/release/workspace-config.d.ts +10 -6
- package/dist/release/workspace-config.d.ts.map +1 -1
- package/dist/release/workspace-config.js +10 -6
- package/dist/resolve-schema-ref-kinds.d.ts +4 -3
- package/dist/resolve-schema-ref-kinds.d.ts.map +1 -1
- package/dist/resolve-schema-ref-kinds.js +16 -0
- package/dist/resolve-throws-union.d.ts.map +1 -1
- package/dist/resolve-throws-union.js +4 -3
- package/dist/resolve-zone-containment.d.ts +99 -0
- package/dist/resolve-zone-containment.d.ts.map +1 -0
- package/dist/resolve-zone-containment.js +212 -0
- package/dist/resolve-zone-requirements.d.ts +5 -0
- package/dist/resolve-zone-requirements.d.ts.map +1 -1
- package/dist/resolve-zone-requirements.js +48 -7
- package/dist/resource-rule.d.ts +106 -0
- package/dist/resource-rule.d.ts.map +1 -0
- package/dist/resource-rule.js +236 -0
- package/dist/rule-condition.d.ts +50 -0
- package/dist/rule-condition.d.ts.map +1 -0
- package/dist/rule-condition.js +108 -0
- package/dist/schema-keywords.d.ts.map +1 -1
- package/dist/schema-keywords.js +20 -0
- package/dist/schema-projection.d.ts +171 -0
- package/dist/schema-projection.d.ts.map +1 -0
- package/dist/schema-projection.js +317 -0
- package/dist/step-slot.d.ts +39 -0
- package/dist/step-slot.d.ts.map +1 -0
- package/dist/step-slot.js +49 -0
- package/dist/telo-version.d.ts +1 -1
- package/dist/telo-version.js +1 -1
- package/dist/validate-cel-context.d.ts.map +1 -1
- package/dist/validate-cel-context.js +17 -3
- package/dist/validate-durable-regions.d.ts +15 -0
- package/dist/validate-durable-regions.d.ts.map +1 -0
- package/dist/validate-durable-regions.js +336 -0
- package/dist/validate-references.d.ts.map +1 -1
- package/dist/validate-references.js +44 -2
- package/dist/validate-referrer-rules.d.ts +120 -0
- package/dist/validate-referrer-rules.d.ts.map +1 -0
- package/dist/validate-referrer-rules.js +255 -0
- package/dist/validate-resource-rules.d.ts +114 -0
- package/dist/validate-resource-rules.d.ts.map +1 -0
- package/dist/validate-resource-rules.js +283 -0
- package/dist/validate-schema-projection.d.ts +32 -0
- package/dist/validate-schema-projection.d.ts.map +1 -0
- package/dist/validate-schema-projection.js +110 -0
- package/dist/validate-step-inputs.d.ts +2 -1
- package/dist/validate-step-inputs.d.ts.map +1 -1
- package/dist/validate-step-inputs.js +5 -3
- package/dist/validate-throws-coverage.d.ts.map +1 -1
- package/dist/validate-throws-coverage.js +11 -5
- package/dist/validate-zone-slots.d.ts +2 -2
- package/dist/validate-zone-slots.d.ts.map +1 -1
- package/dist/validate-zone-slots.js +202 -6
- package/dist/validate-zone-violations.d.ts +12 -0
- package/dist/validate-zone-violations.d.ts.map +1 -0
- package/dist/validate-zone-violations.js +169 -0
- package/dist/value-type-keyword.d.ts +1 -1
- package/dist/value-type-keyword.d.ts.map +1 -1
- package/dist/value-type-keyword.js +4 -0
- package/dist/zone-slot.d.ts +61 -0
- package/dist/zone-slot.d.ts.map +1 -1
- package/dist/zone-slot.js +86 -5
- package/package.json +2 -2
- package/src/analysis-registry.ts +6 -0
- package/src/analyzer.ts +395 -14
- package/src/call-graph.ts +2 -8
- package/src/flatten-for-analyzer.ts +1 -1
- package/src/import-resolution-diagnostics.ts +25 -7
- package/src/index.ts +73 -0
- package/src/invocation-contract.ts +45 -2
- package/src/loaded-types.ts +12 -3
- package/src/manifest-loader.ts +87 -55
- package/src/manifest-schemas.ts +328 -14
- package/src/module-compatibility.ts +72 -0
- package/src/ref-slot-reading.ts +156 -0
- package/src/referrer-rule.ts +116 -0
- package/src/release/index.ts +1 -0
- package/src/release/version-stamp.ts +58 -0
- package/src/release/workspace-config.ts +10 -6
- package/src/resolve-schema-ref-kinds.ts +28 -4
- package/src/resolve-throws-union.ts +4 -3
- package/src/resolve-zone-containment.ts +329 -0
- package/src/resolve-zone-requirements.ts +67 -7
- package/src/resource-rule.ts +252 -0
- package/src/rule-condition.ts +126 -0
- package/src/schema-keywords.ts +24 -0
- package/src/schema-projection.ts +403 -0
- package/src/step-slot.ts +64 -0
- package/src/telo-version.ts +1 -1
- package/src/validate-cel-context.ts +17 -3
- package/src/validate-durable-regions.ts +401 -0
- package/src/validate-references.ts +57 -2
- package/src/validate-referrer-rules.ts +373 -0
- package/src/validate-resource-rules.ts +401 -0
- package/src/validate-schema-projection.ts +184 -0
- package/src/validate-step-inputs.ts +5 -3
- package/src/validate-throws-coverage.ts +12 -5
- package/src/validate-zone-slots.ts +192 -8
- package/src/validate-zone-violations.ts +190 -0
- package/src/value-type-keyword.ts +4 -0
- package/src/zone-slot.ts +114 -5
|
@@ -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;AAKhG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;wDAEwD;AACxD,MAAM,WAAW,YAAY;IAC3B;0CACsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,sFAAsF;IACtF,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;8EAG0E;IAC1E,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IAEpE,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI;IAIjD,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAIpE;;+EAE2E;IAC3E,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAI9E,wFAAwF;IACxF,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAIzD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI7C;;;;;;;;;;uBAUmB;IACnB,qBAAqB,CAAC,SAAS,EAAE,gBAAgB,EAAE,GAAG,IAAI;IAI1D;;;;;;;OAOG;IACH,mBAAmB,CACjB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,EAClC,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACnC,IAAI;IAkBP;;;;;;OAMG;IACH,oBAAoB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,YAAY,EAAE;IAoBhE;;;;;;wBAMoB;IACpB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAQtD;;;;;;mEAM+D;IAC/D,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAInE;;;oBAGgB;IAChB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAIpE,OAAO,CAAC,eAAe;
|
|
1
|
+
{"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -131,6 +131,12 @@ export class AnalysisRegistry {
|
|
|
131
131
|
const def = this.resolveDefinition(kind);
|
|
132
132
|
if (!def)
|
|
133
133
|
return undefined;
|
|
134
|
+
// A KIND-level query: there is no instance, so a DECLARATION-derived slot
|
|
135
|
+
// (`x-telo-schema-projection-from`) has no reference to project from and is
|
|
136
|
+
// left as the kind declared it. That is the honest answer here — the
|
|
137
|
+
// projected shape is a property of one instance, not of the kind — and it is
|
|
138
|
+
// why passing no manifest cannot silently drop a projection: the per-resource
|
|
139
|
+
// analysis pass is what resolves and reports them.
|
|
134
140
|
return resolveContract(direction, undefined, def, {
|
|
135
141
|
resolveDefinition: this.scopedDefResolver(),
|
|
136
142
|
typeManifestsFor: () => [],
|
package/dist/analyzer.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export declare function resolveLocalRef(schema: Record<string, any> | undefined,
|
|
|
37
37
|
* failure with no diagnostic attached to it. */
|
|
38
38
|
export declare function gatherPropertySchemas(schema: Record<string, any>, root?: Record<string, any>): Array<[string, Record<string, any>]>;
|
|
39
39
|
/**
|
|
40
|
-
* Generic, role-driven walk over
|
|
40
|
+
* Generic, role-driven walk over a step array. Calls
|
|
41
41
|
* `visit(step, stepPath)` for every step — top-level and nested through the
|
|
42
42
|
* `x-telo-topology-role` forms (`branch`, `branch-list`, `case-map`). This is
|
|
43
43
|
* the single definition of how steps nest, shared by `buildStepContextSchema`
|
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,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAWzE,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;AAsBlC,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
|
package/dist/analyzer.js
CHANGED
|
@@ -17,8 +17,16 @@ import { REF_VALIDATION_SKIP_KINDS } from "./system-kinds.js";
|
|
|
17
17
|
import { resolveRefSentinels } from "./resolve-ref-sentinels.js";
|
|
18
18
|
import { resolveSchemaRefKinds } from "./resolve-schema-ref-kinds.js";
|
|
19
19
|
import { runZoneAnalysis } from "./resolve-zone-requirements.js";
|
|
20
|
+
import { validateDurableRegions } from "./validate-durable-regions.js";
|
|
21
|
+
import { validateZoneViolations } from "./validate-zone-violations.js";
|
|
20
22
|
import { MANIFEST_SCHEMA_URI, ManifestRootSchema } from "./manifest-schemas.js";
|
|
21
23
|
import { validateZoneSlotDeclarations } from "./validate-zone-slots.js";
|
|
24
|
+
import { validateSchemaProjection, } from "./validate-schema-projection.js";
|
|
25
|
+
import { evaluateResourceRules, reportResourceRules, reportUnexercisedRule, ruleExercised, validateResourceRuleDeclarations, } from "./validate-resource-rules.js";
|
|
26
|
+
import { readResourceRules } from "./resource-rule.js";
|
|
27
|
+
import { readReferrerRules } from "./referrer-rule.js";
|
|
28
|
+
import { evaluateReferrerRules, referrerRuleExercised, reportReferrerRules, reportUnexercisedReferrerRule, validateReferrerRuleDeclarations, } from "./validate-referrer-rules.js";
|
|
29
|
+
import { describeProjectionFailure, } from "./schema-projection.js";
|
|
22
30
|
import { validateDynamicSelectors, validateRefSlotDeclarations, } from "./validate-ref-slots.js";
|
|
23
31
|
import { validateValueTypeSlots, } from "./validate-value-type-slots.js";
|
|
24
32
|
import { resolveSchemaTypeRefs } from "./resolve-schema-type-refs.js";
|
|
@@ -47,6 +55,7 @@ import { validateReferences } from "./validate-references.js";
|
|
|
47
55
|
import { validateReferenceForms } from "./validate-reference-forms.js";
|
|
48
56
|
import { validateUnusedDeclarations } from "./validate-unused-declarations.js";
|
|
49
57
|
import { validateThrowsCoverage } from "./validate-throws-coverage.js";
|
|
58
|
+
import { readStepSlot } from "./step-slot.js";
|
|
50
59
|
const SELF_PREFIX = "Self.";
|
|
51
60
|
/**
|
|
52
61
|
* `StaticAnalyzer.analyze()` requires `metadata.source` (non-empty) and
|
|
@@ -256,7 +265,7 @@ export function gatherPropertySchemas(schema, root) {
|
|
|
256
265
|
return out;
|
|
257
266
|
}
|
|
258
267
|
/**
|
|
259
|
-
* Generic, role-driven walk over
|
|
268
|
+
* Generic, role-driven walk over a step array. Calls
|
|
260
269
|
* `visit(step, stepPath)` for every step — top-level and nested through the
|
|
261
270
|
* `x-telo-topology-role` forms (`branch`, `branch-list`, `case-map`). This is
|
|
262
271
|
* the single definition of how steps nest, shared by `buildStepContextSchema`
|
|
@@ -309,7 +318,7 @@ export function walkStepArray(steps, stepItemSchema, rootSchema, basePath, visit
|
|
|
309
318
|
});
|
|
310
319
|
}
|
|
311
320
|
/**
|
|
312
|
-
* Build a `steps` context schema
|
|
321
|
+
* Build a `steps` context schema for a kind's step body.
|
|
313
322
|
* Walks each step in the manifest array, resolves the invoked resource's output
|
|
314
323
|
* contract, and builds `steps.<name>.result` context entries.
|
|
315
324
|
*
|
|
@@ -330,7 +339,7 @@ export function walkStepArray(steps, stepItemSchema, rootSchema, basePath, visit
|
|
|
330
339
|
* sub-properties (e.g. elseif: [{ if, then }]).
|
|
331
340
|
* - `case-map` — value is an object whose values are step arrays (e.g. cases).
|
|
332
341
|
* No specific Run.Sequence field name is hardcoded; any kind that uses
|
|
333
|
-
*
|
|
342
|
+
* a step body and tags its branch fields with these roles works.
|
|
334
343
|
*/
|
|
335
344
|
function buildStepContextSchema(manifest, defSchema, allManifests, defs, aliases, scopes) {
|
|
336
345
|
const props = defSchema.properties;
|
|
@@ -339,7 +348,7 @@ function buildStepContextSchema(manifest, defSchema, allManifests, defs, aliases
|
|
|
339
348
|
const contractScope = analyzerContractScope(defs, aliases, scopes, allManifests);
|
|
340
349
|
const readingModule = manifest.metadata?.module;
|
|
341
350
|
for (const [fieldName, fieldSchema] of Object.entries(props)) {
|
|
342
|
-
const stepCtx = fieldSchema
|
|
351
|
+
const stepCtx = readStepSlot(fieldSchema);
|
|
343
352
|
if (!stepCtx)
|
|
344
353
|
continue;
|
|
345
354
|
const invokeField = stepCtx.invoke;
|
|
@@ -488,7 +497,7 @@ const NO_ENTRY_POINT_CAPABILITIES = new Set([
|
|
|
488
497
|
"Telo.Sink",
|
|
489
498
|
]);
|
|
490
499
|
/**
|
|
491
|
-
* Validate
|
|
500
|
+
* Validate step `invoke` references (e.g. `Run.Sequence`
|
|
492
501
|
* steps).
|
|
493
502
|
*
|
|
494
503
|
* The reference field map deliberately does NOT descend into step `invoke`
|
|
@@ -507,7 +516,7 @@ const NO_ENTRY_POINT_CAPABILITIES = new Set([
|
|
|
507
516
|
* contract has no entry point → `REFERENCE_KIND_MISMATCH` (runtime
|
|
508
517
|
* `ERR_RESOURCE_NOT_INVOKABLE`).
|
|
509
518
|
*
|
|
510
|
-
* Generic and topology-driven — it walks steps via the same
|
|
519
|
+
* Generic and topology-driven — it walks steps via the same step-slot
|
|
511
520
|
* / `x-telo-topology-role` annotations `buildStepContextSchema` uses (through the
|
|
512
521
|
* shared `walkStepArray`), so nested branches (then/else/do/catch/cases) are
|
|
513
522
|
* covered and no `Run.Sequence` field name is hardcoded. The cross-module
|
|
@@ -626,8 +635,7 @@ function validateStepInvokeReferences(allManifests, defs, aliases) {
|
|
|
626
635
|
const resource = { kind: m.kind, name: meta.name };
|
|
627
636
|
const filePath = typeof meta.source === "string" ? meta.source : undefined;
|
|
628
637
|
for (const [fieldName, fieldSchema] of Object.entries(defSchema.properties)) {
|
|
629
|
-
const
|
|
630
|
-
const invokeField = stepCtx?.invoke;
|
|
638
|
+
const invokeField = readStepSlot(fieldSchema)?.invoke;
|
|
631
639
|
if (!invokeField)
|
|
632
640
|
continue;
|
|
633
641
|
const steps = m[fieldName];
|
|
@@ -1032,13 +1040,18 @@ export class StaticAnalyzer {
|
|
|
1032
1040
|
}
|
|
1033
1041
|
seen.add(alias);
|
|
1034
1042
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1043
|
+
// An import whose target identity was never established registers NO
|
|
1044
|
+
// alias. The name is never guessed from the source string: a guess that
|
|
1045
|
+
// is usually right is what turned "this import did not resolve" into an
|
|
1046
|
+
// assertion that a published dependency was malformed, naming a module
|
|
1047
|
+
// no registry could ever hold. With no alias, every use degrades to
|
|
1048
|
+
// "cannot resolve alias '<X>'" — which points at the import the author
|
|
1049
|
+
// has to fix, and which the loader has already reported on its own line.
|
|
1050
|
+
if (alias && source && resolvedModuleName) {
|
|
1051
|
+
const targetModule = resolvedModuleName;
|
|
1037
1052
|
// Module identity is registered globally so x-telo-ref resolution sees
|
|
1038
1053
|
// transitively-imported modules regardless of which scope brought them in.
|
|
1039
|
-
|
|
1040
|
-
defs.registerModuleIdentity(resolvedNamespace ?? null, resolvedModuleName);
|
|
1041
|
-
}
|
|
1054
|
+
defs.registerModuleIdentity(resolvedNamespace ?? null, resolvedModuleName);
|
|
1042
1055
|
// `metadata.reExportedKinds` (stamped by flattenForAnalyzer / the editor projection)
|
|
1043
1056
|
// maps an exported suffix to the true owning module's canonical kind for kinds this
|
|
1044
1057
|
// import transitively re-exports (`exports.kinds: [Alias.Kind]`).
|
|
@@ -1092,6 +1105,55 @@ export class StaticAnalyzer {
|
|
|
1092
1105
|
const refConstraintIssues = [];
|
|
1093
1106
|
const refSlotIssues = [];
|
|
1094
1107
|
const zoneSlotIssues = [];
|
|
1108
|
+
// One place a rule report becomes a diagnostic. The pass decided WHAT and
|
|
1109
|
+
// WHERE; this only carries it across to the diagnostic shape.
|
|
1110
|
+
const SEVERITY = {
|
|
1111
|
+
error: DiagnosticSeverity.Error,
|
|
1112
|
+
warning: DiagnosticSeverity.Warning,
|
|
1113
|
+
information: DiagnosticSeverity.Information,
|
|
1114
|
+
};
|
|
1115
|
+
const resourceRuleDiagnostic = (report) => ({
|
|
1116
|
+
severity: SEVERITY[report.severity],
|
|
1117
|
+
code: report.code,
|
|
1118
|
+
source: SOURCE,
|
|
1119
|
+
message: report.message,
|
|
1120
|
+
data: {
|
|
1121
|
+
resource: {
|
|
1122
|
+
kind: report.manifest.kind,
|
|
1123
|
+
name: report.manifest.metadata?.name,
|
|
1124
|
+
},
|
|
1125
|
+
filePath: report.manifest.metadata?.source,
|
|
1126
|
+
path: report.path,
|
|
1127
|
+
rule: report.rule,
|
|
1128
|
+
},
|
|
1129
|
+
});
|
|
1130
|
+
const referrerRuleDiagnostic = (report) => ({
|
|
1131
|
+
severity: SEVERITY[report.severity],
|
|
1132
|
+
code: report.code,
|
|
1133
|
+
source: SOURCE,
|
|
1134
|
+
message: report.message,
|
|
1135
|
+
data: {
|
|
1136
|
+
resource: {
|
|
1137
|
+
kind: report.manifest.kind,
|
|
1138
|
+
name: report.manifest.metadata?.name,
|
|
1139
|
+
},
|
|
1140
|
+
filePath: report.manifest.metadata?.source,
|
|
1141
|
+
path: report.path,
|
|
1142
|
+
rule: report.rule,
|
|
1143
|
+
},
|
|
1144
|
+
});
|
|
1145
|
+
const projectionIssues = [];
|
|
1146
|
+
const resourceRuleIssues = [];
|
|
1147
|
+
const referrerRuleIssues = [];
|
|
1148
|
+
// A rule that never had anything to iterate is never proven — the second way
|
|
1149
|
+
// coverage varies invisibly, beside the dynamic-leaf skip. Tracked across the
|
|
1150
|
+
// whole run and reported once, since "empty on every resource" is not a fact
|
|
1151
|
+
// any single resource can establish.
|
|
1152
|
+
const ruleExercise = new Map();
|
|
1153
|
+
// Same for a referrer rule, where "never exercised" means nothing the
|
|
1154
|
+
// `referrer:` filter matches ever referenced a resource of the kind — which
|
|
1155
|
+
// is exactly what a typo in that filter looks like from the outside.
|
|
1156
|
+
const referrerRuleExercise = new Map();
|
|
1095
1157
|
// `x-telo-type` is checked on EVERY manifest, not only on definition docs: a
|
|
1096
1158
|
// schema fragment is written wherever a kind declares a schema-valued field,
|
|
1097
1159
|
// so an inline `inputType:` on an ordinary resource carries one just as a
|
|
@@ -1124,6 +1186,28 @@ export class StaticAnalyzer {
|
|
|
1124
1186
|
refConstraintIssues.push(...issues);
|
|
1125
1187
|
refSlotIssues.push(...validateRefSlotDeclarations(m));
|
|
1126
1188
|
zoneSlotIssues.push(...validateZoneSlotDeclarations(m));
|
|
1189
|
+
projectionIssues.push(...validateSchemaProjection(m));
|
|
1190
|
+
// Checked against the MERGED schema, so an `in:` pointer naming an
|
|
1191
|
+
// inherited field resolves — which is what lets a rule shared by every
|
|
1192
|
+
// backend be declared once on the abstract they extend.
|
|
1193
|
+
resourceRuleIssues.push(...validateResourceRuleDeclarations(m, effectiveAuthorSchema(m, (k) => defs.resolve(aliases.resolveKind(k) ?? k) ?? defs.resolve(k))));
|
|
1194
|
+
referrerRuleIssues.push(...validateReferrerRuleDeclarations(m));
|
|
1195
|
+
for (const rule of readReferrerRules(m.schema)) {
|
|
1196
|
+
referrerRuleExercise.set(`${m.metadata?.module}.${m.metadata?.name}#${rule.code}`, {
|
|
1197
|
+
manifest: m,
|
|
1198
|
+
rule,
|
|
1199
|
+
exercised: false,
|
|
1200
|
+
seen: false,
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
for (const rule of readResourceRules(m.schema)) {
|
|
1204
|
+
ruleExercise.set(`${m.metadata?.module}.${m.metadata?.name}#${rule.code}`, {
|
|
1205
|
+
manifest: m,
|
|
1206
|
+
rule,
|
|
1207
|
+
exercised: false,
|
|
1208
|
+
seen: false,
|
|
1209
|
+
});
|
|
1210
|
+
}
|
|
1127
1211
|
}
|
|
1128
1212
|
const resolvedCapability = def.capability
|
|
1129
1213
|
? (scopeResolver.resolveKind(def.capability) ?? def.capability)
|
|
@@ -1177,6 +1261,24 @@ export class StaticAnalyzer {
|
|
|
1177
1261
|
};
|
|
1178
1262
|
const filePath = issue.manifest.metadata?.source;
|
|
1179
1263
|
const data = { resource, filePath, path: issue.path };
|
|
1264
|
+
if (issue.annotation === "referrer") {
|
|
1265
|
+
// Mirrors ZONE_PROVIDER_UNRESOLVED: a filter naming no kind matches no
|
|
1266
|
+
// referrer, so the rule would pass on every manifest while checking
|
|
1267
|
+
// nothing — reported at the kind that wrote it, since the consumer
|
|
1268
|
+
// cannot see that the check is inert.
|
|
1269
|
+
diagnostics.push({
|
|
1270
|
+
severity: DiagnosticSeverity.Error,
|
|
1271
|
+
code: "REFERRER_RULE_INVALID",
|
|
1272
|
+
source: SOURCE,
|
|
1273
|
+
message: `x-telo-referrer-rules 'referrer: ${issue.ref}' at '${issue.path}' names no kind. ` +
|
|
1274
|
+
`The prefix must be an import alias declared in this file's 'imports:' map, ` +
|
|
1275
|
+
`'Self' for a kind in this library, or 'Telo' for a built-in. A filter that ` +
|
|
1276
|
+
`matches nothing leaves the rule inert. Known aliases: ` +
|
|
1277
|
+
`${issue.knownAliases?.join(", ") || "(none)"}.`,
|
|
1278
|
+
data,
|
|
1279
|
+
});
|
|
1280
|
+
continue;
|
|
1281
|
+
}
|
|
1180
1282
|
if (issue.annotation === "zone") {
|
|
1181
1283
|
// Mirrors X_TELO_REF_UNRESOLVED: an unresolvable provider kind would
|
|
1182
1284
|
// leave the requirement silently unenforced — no provider ever
|
|
@@ -1262,6 +1364,57 @@ export class StaticAnalyzer {
|
|
|
1262
1364
|
// OPPOSITE directions — a dropped requirement is silently unenforced, a
|
|
1263
1365
|
// dropped provision invents failures — so neither can be left to
|
|
1264
1366
|
// leniency.
|
|
1367
|
+
// A projection nothing can read does not fail — it stops typing the
|
|
1368
|
+
// consumers counting on it, which puts a misspelled field back where the
|
|
1369
|
+
// projection exists to catch it earlier.
|
|
1370
|
+
for (const issue of resourceRuleIssues) {
|
|
1371
|
+
diagnostics.push({
|
|
1372
|
+
severity: DiagnosticSeverity.Error,
|
|
1373
|
+
code: issue.code,
|
|
1374
|
+
source: SOURCE,
|
|
1375
|
+
message: issue.message,
|
|
1376
|
+
data: {
|
|
1377
|
+
resource: {
|
|
1378
|
+
kind: issue.manifest.kind,
|
|
1379
|
+
name: issue.manifest.metadata?.name,
|
|
1380
|
+
},
|
|
1381
|
+
filePath: issue.manifest.metadata?.source,
|
|
1382
|
+
path: issue.path,
|
|
1383
|
+
},
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
1386
|
+
for (const issue of referrerRuleIssues) {
|
|
1387
|
+
diagnostics.push({
|
|
1388
|
+
severity: DiagnosticSeverity.Error,
|
|
1389
|
+
code: issue.code,
|
|
1390
|
+
source: SOURCE,
|
|
1391
|
+
message: issue.message,
|
|
1392
|
+
data: {
|
|
1393
|
+
resource: {
|
|
1394
|
+
kind: issue.manifest.kind,
|
|
1395
|
+
name: issue.manifest.metadata?.name,
|
|
1396
|
+
},
|
|
1397
|
+
filePath: issue.manifest.metadata?.source,
|
|
1398
|
+
path: issue.path,
|
|
1399
|
+
},
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
for (const issue of projectionIssues) {
|
|
1403
|
+
diagnostics.push({
|
|
1404
|
+
severity: DiagnosticSeverity.Error,
|
|
1405
|
+
code: issue.code,
|
|
1406
|
+
source: SOURCE,
|
|
1407
|
+
message: issue.message,
|
|
1408
|
+
data: {
|
|
1409
|
+
resource: {
|
|
1410
|
+
kind: issue.manifest.kind,
|
|
1411
|
+
name: issue.manifest.metadata?.name,
|
|
1412
|
+
},
|
|
1413
|
+
filePath: issue.manifest.metadata?.source,
|
|
1414
|
+
path: issue.path,
|
|
1415
|
+
},
|
|
1416
|
+
});
|
|
1417
|
+
}
|
|
1265
1418
|
for (const issue of zoneSlotIssues) {
|
|
1266
1419
|
diagnostics.push({
|
|
1267
1420
|
severity: DiagnosticSeverity.Error,
|
|
@@ -1296,6 +1449,57 @@ export class StaticAnalyzer {
|
|
|
1296
1449
|
aliases,
|
|
1297
1450
|
aliasesByModule,
|
|
1298
1451
|
}));
|
|
1452
|
+
/**
|
|
1453
|
+
* Whether a referrer of `kind` satisfies a referrer rule's `referrer:`
|
|
1454
|
+
* filter, which is canonical by the time it gets here (`resolveSchemaRefKinds`
|
|
1455
|
+
* rewrote it in the DECLARING module's scope). The referring manifest's own
|
|
1456
|
+
* `kind:` is not — it is whatever alias its author imported the kind under —
|
|
1457
|
+
* so it is resolved the same way every other kind comparison in this pass
|
|
1458
|
+
* resolves one. Liskov-substitutable, matching `checkKind`: a child of the
|
|
1459
|
+
* named kind is one.
|
|
1460
|
+
*/
|
|
1461
|
+
const kindMatches = (filter, kind) => {
|
|
1462
|
+
const resolved = aliases.resolveKind(kind) ?? kind;
|
|
1463
|
+
if (resolved === filter)
|
|
1464
|
+
return true;
|
|
1465
|
+
return defs
|
|
1466
|
+
.getByExtends(filter)
|
|
1467
|
+
.some((d) => `${d.metadata.module}.${d.metadata.name}` === resolved);
|
|
1468
|
+
};
|
|
1469
|
+
/**
|
|
1470
|
+
* The resources that reach `manifest`, with the slot each one reaches it
|
|
1471
|
+
* through. A step's edge is attributed to the resource whose body declares
|
|
1472
|
+
* it: a step is not a manifest, and the requirement is about the resource
|
|
1473
|
+
* that has to declare something.
|
|
1474
|
+
*
|
|
1475
|
+
* Deduplication is the evaluation's, not this function's — a referrer
|
|
1476
|
+
* reaching one resource through two slots is two sites, and which one anchors
|
|
1477
|
+
* the diagnostic is a reporting decision.
|
|
1478
|
+
*/
|
|
1479
|
+
const referrersOf = (manifest, graph) => {
|
|
1480
|
+
const name = manifest.metadata?.name;
|
|
1481
|
+
if (!name)
|
|
1482
|
+
return [];
|
|
1483
|
+
const node = graph.resource(manifest.kind, name) ?? graph.resourceByName(name);
|
|
1484
|
+
if (!node)
|
|
1485
|
+
return [];
|
|
1486
|
+
const out = [];
|
|
1487
|
+
for (const edge of graph.edgesTo(node.id)) {
|
|
1488
|
+
const from = graph.nodes.get(edge.from);
|
|
1489
|
+
if (!from)
|
|
1490
|
+
continue;
|
|
1491
|
+
const owner = from.type === "step" ? graph.nodes.get(from.owner) : from;
|
|
1492
|
+
if (!owner || owner.type !== "resource")
|
|
1493
|
+
continue;
|
|
1494
|
+
out.push({
|
|
1495
|
+
manifest: owner.manifest,
|
|
1496
|
+
kind: owner.kind,
|
|
1497
|
+
name: owner.name,
|
|
1498
|
+
path: edge.path,
|
|
1499
|
+
});
|
|
1500
|
+
}
|
|
1501
|
+
return out;
|
|
1502
|
+
};
|
|
1299
1503
|
// A `use` case map's selector written in CEL is a hard diagnostic — a call
|
|
1300
1504
|
// graph known only at runtime is not statically analyzable, and no fallback
|
|
1301
1505
|
// is conservative for every consumer. Scoped to the entry's own modules:
|
|
@@ -1323,6 +1527,29 @@ export class StaticAnalyzer {
|
|
|
1323
1527
|
moduleDocuments: options?.moduleDocuments,
|
|
1324
1528
|
cache: zoneExportCache,
|
|
1325
1529
|
}));
|
|
1530
|
+
// Durable regions — the SAME graph again, walked DOWNWARD this time.
|
|
1531
|
+
// Every rule here keys off a zone attribute rather than off any kind, so
|
|
1532
|
+
// a backend that ships its own workflow kind is covered without the
|
|
1533
|
+
// analyzer knowing it exists: going native costs a module, not a change
|
|
1534
|
+
// here.
|
|
1535
|
+
const resolveRegionDef = (kind, module) => {
|
|
1536
|
+
const scope = (module ? aliasesByModule.get(module) : undefined) ?? aliases;
|
|
1537
|
+
const canonical = scope.resolveKind(kind);
|
|
1538
|
+
return defs.resolve(kind) ?? (canonical ? defs.resolve(canonical) : undefined);
|
|
1539
|
+
};
|
|
1540
|
+
diagnostics.push(...validateDurableRegions({
|
|
1541
|
+
graph: getCallGraph(),
|
|
1542
|
+
resolveDef: resolveRegionDef,
|
|
1543
|
+
reportModules: rootModules,
|
|
1544
|
+
}),
|
|
1545
|
+
// The same walk once more, over EVERY attribute rather than the two
|
|
1546
|
+
// durability names — a region must not contain a resource that declares
|
|
1547
|
+
// it cannot honour what the region promises.
|
|
1548
|
+
...validateZoneViolations({
|
|
1549
|
+
graph: getCallGraph(),
|
|
1550
|
+
resolveDef: resolveRegionDef,
|
|
1551
|
+
reportModules: rootModules,
|
|
1552
|
+
}));
|
|
1326
1553
|
}
|
|
1327
1554
|
// Phase 2.6: register each named `Telo.Type` resource's schema under its
|
|
1328
1555
|
// canonical module-scoped id (`telo://<module>/<name>`), validate
|
|
@@ -1672,6 +1899,56 @@ export class StaticAnalyzer {
|
|
|
1672
1899
|
});
|
|
1673
1900
|
}
|
|
1674
1901
|
}
|
|
1902
|
+
// Resource rules — relationships between this resource's own fields that
|
|
1903
|
+
// JSON Schema cannot state, declared by the kind as CEL over `self` and
|
|
1904
|
+
// `this`. Read off the AUTHOR-FACING schema, so an `extends` child without
|
|
1905
|
+
// `base:` inherits its parent's rules and one that declares its own
|
|
1906
|
+
// replaces them, exactly as the rest of the config contract merges.
|
|
1907
|
+
// The finding→diagnostic mapping lives with the finding vocabulary in
|
|
1908
|
+
// `validate-resource-rules.ts`, the shape every neighbouring pass uses:
|
|
1909
|
+
// issues out, one emit here.
|
|
1910
|
+
const ruleDeclarer = definition.metadata?.module;
|
|
1911
|
+
for (const report of reportResourceRules(m, definition, evaluateResourceRules(m, authorSchema), !ruleDeclarer || rootModules.has(ruleDeclarer))) {
|
|
1912
|
+
diagnostics.push(resourceRuleDiagnostic(report));
|
|
1913
|
+
}
|
|
1914
|
+
for (const rule of readResourceRules(authorSchema)) {
|
|
1915
|
+
const key = `${definition.metadata?.module}.${definition.metadata?.name}#${rule.code}`;
|
|
1916
|
+
const tracked = ruleExercise.get(key);
|
|
1917
|
+
if (!tracked)
|
|
1918
|
+
continue;
|
|
1919
|
+
tracked.seen = true;
|
|
1920
|
+
if (ruleExercised(m, rule))
|
|
1921
|
+
tracked.exercised = true;
|
|
1922
|
+
}
|
|
1923
|
+
// Referrer rules — what must be true of whoever REFERENCES this resource,
|
|
1924
|
+
// declared by the kind that has the requirement rather than by the kind
|
|
1925
|
+
// that must satisfy it. The subject is chosen by the EDGE, so no kind
|
|
1926
|
+
// literal appears on the referring side, where the spelling would be the
|
|
1927
|
+
// consumer's import alias rather than anything the rule's author controls.
|
|
1928
|
+
// A consumer of the shared call graph, never a second traversal.
|
|
1929
|
+
const referrerRules = readReferrerRules(authorSchema);
|
|
1930
|
+
if (referrerRules.length > 0) {
|
|
1931
|
+
const referrers = referrersOf(m, getCallGraph());
|
|
1932
|
+
for (const report of reportReferrerRules(m, definition, evaluateReferrerRules(m, authorSchema, referrers, kindMatches), !ruleDeclarer || rootModules.has(ruleDeclarer))) {
|
|
1933
|
+
// A VIOLATION is the referrer's data, so it is reported only when that
|
|
1934
|
+
// manifest is the entry's own — the same direction a resource-rule
|
|
1935
|
+
// violation takes, one hop further out.
|
|
1936
|
+
const owner = report.manifest.metadata?.module;
|
|
1937
|
+
if (report.code === "REFERRER_RULE_VIOLATED" && owner && !rootModules.has(owner)) {
|
|
1938
|
+
continue;
|
|
1939
|
+
}
|
|
1940
|
+
diagnostics.push(referrerRuleDiagnostic(report));
|
|
1941
|
+
}
|
|
1942
|
+
for (const rule of referrerRules) {
|
|
1943
|
+
const key = `${definition.metadata?.module}.${definition.metadata?.name}#${rule.code}`;
|
|
1944
|
+
const tracked = referrerRuleExercise.get(key);
|
|
1945
|
+
if (!tracked)
|
|
1946
|
+
continue;
|
|
1947
|
+
tracked.seen = true;
|
|
1948
|
+
if (referrerRuleExercised(rule, referrers, kindMatches))
|
|
1949
|
+
tracked.exercised = true;
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1675
1952
|
// Validate inline resources nested inside this resource's body (e.g. a
|
|
1676
1953
|
// Run.Sequence step's `invoke: { kind, ...config }`). These sit at
|
|
1677
1954
|
// x-telo-ref slots reached only through local `$ref`s, which the
|
|
@@ -1700,6 +1977,23 @@ export class StaticAnalyzer {
|
|
|
1700
1977
|
}
|
|
1701
1978
|
// (Invocation context compatibility check is handled via x-telo-context in the CEL pass below)
|
|
1702
1979
|
}
|
|
1980
|
+
// A rule whose collection was empty on every resource of its kind is a rule
|
|
1981
|
+
// nothing proved. `check()` types `self` only shallowly (cel-js takes a flat
|
|
1982
|
+
// field map, so `columns` is `map`), which means a typo below the first level
|
|
1983
|
+
// survives declaration validation and is caught only by evaluation — so a
|
|
1984
|
+
// rule that never evaluated has been verified by nothing at all. Reported
|
|
1985
|
+
// only when the kind HAS resources here: a kind nobody instantiated in this
|
|
1986
|
+
// workspace says nothing about the rule.
|
|
1987
|
+
for (const tracked of ruleExercise.values()) {
|
|
1988
|
+
if (!tracked.seen || tracked.exercised)
|
|
1989
|
+
continue;
|
|
1990
|
+
diagnostics.push(resourceRuleDiagnostic(reportUnexercisedRule(tracked.manifest, tracked.rule)));
|
|
1991
|
+
}
|
|
1992
|
+
for (const tracked of referrerRuleExercise.values()) {
|
|
1993
|
+
if (!tracked.seen || tracked.exercised)
|
|
1994
|
+
continue;
|
|
1995
|
+
diagnostics.push(referrerRuleDiagnostic(reportUnexercisedReferrerRule(tracked.manifest, tracked.rule)));
|
|
1996
|
+
}
|
|
1703
1997
|
// Template-body structural validations: check that template entry-points produce
|
|
1704
1998
|
// values matching the contract of their dispatch target and (for `provide:`)
|
|
1705
1999
|
// the abstract this definition `extends`. CEL fields inside the templated
|
|
@@ -1768,6 +2062,42 @@ export class StaticAnalyzer {
|
|
|
1768
2062
|
}
|
|
1769
2063
|
}
|
|
1770
2064
|
}
|
|
2065
|
+
// A consumer's slot typed from a referenced declaration
|
|
2066
|
+
// (`x-telo-schema-projection-from`) fails in the direction that is hardest
|
|
2067
|
+
// to notice: the contract silently reopens, so a misspelled field passes
|
|
2068
|
+
// `telo check` exactly as it did before the projection existed. That is the
|
|
2069
|
+
// failure the projection exists to move earlier, so it is reported here
|
|
2070
|
+
// rather than left to degrade. Entry-module-scoped, like
|
|
2071
|
+
// `X_TELO_REF_UNRESOLVED` — a published dependency's slot is not the
|
|
2072
|
+
// consumer's to fix.
|
|
2073
|
+
for (const m of allManifests) {
|
|
2074
|
+
const md = m;
|
|
2075
|
+
if (typeof md.kind !== "string" || md.kind.startsWith("Telo."))
|
|
2076
|
+
continue;
|
|
2077
|
+
const ownModule = md.metadata?.module;
|
|
2078
|
+
if (ownModule && !rootModules.has(ownModule))
|
|
2079
|
+
continue;
|
|
2080
|
+
const definition = contractScope.resolveIn(md.kind, ownModule);
|
|
2081
|
+
if (!definition)
|
|
2082
|
+
continue;
|
|
2083
|
+
const failures = [];
|
|
2084
|
+
for (const direction of ["inputType", "outputType"]) {
|
|
2085
|
+
resolveContract(direction, md, definition, contractScope, failures);
|
|
2086
|
+
}
|
|
2087
|
+
for (const failure of failures) {
|
|
2088
|
+
diagnostics.push({
|
|
2089
|
+
severity: DiagnosticSeverity.Error,
|
|
2090
|
+
code: "SCHEMA_PROJECTION_FROM_UNRESOLVED",
|
|
2091
|
+
source: SOURCE,
|
|
2092
|
+
message: `${md.kind}: ${describeProjectionFailure(failure)}`,
|
|
2093
|
+
data: {
|
|
2094
|
+
resource: { kind: md.kind, name: md.metadata?.name },
|
|
2095
|
+
filePath: md.metadata?.source,
|
|
2096
|
+
path: failure.pointer.replace(/^\//, ""),
|
|
2097
|
+
},
|
|
2098
|
+
});
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
1771
2101
|
// Validate CEL syntax and context variable access in all manifests. The
|
|
1772
2102
|
// walker discovers every compiled CEL node by scanning the value tree and
|
|
1773
2103
|
// hands back the `x-telo-context` schema matched at the enclosing path; the
|
package/dist/call-graph.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call-graph.d.ts","sourceRoot":"","sources":["../src/call-graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAOnE,OAAO,EAIL,KAAK,MAAM,EACX,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"call-graph.d.ts","sourceRoot":"","sources":["../src/call-graph.ts"],"names":[],"mappings":"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"}
|
package/dist/call-graph.js
CHANGED
|
@@ -2,6 +2,7 @@ import { isRefSentinel, isTaggedSentinel } from "@telorun/templating";
|
|
|
2
2
|
import { enclosingOf, propertySchemas, resolveLocalRef, } from "./manifest-navigation.js";
|
|
3
3
|
import { visitManifest } from "./manifest-visitor.js";
|
|
4
4
|
import { possibleUses, readRefSlot, transfersControl, } from "./ref-slot.js";
|
|
5
|
+
import { isStepSlot } from "./step-slot.js";
|
|
5
6
|
import { isRefEntry, resolveFieldEntries } from "./reference-field-map.js";
|
|
6
7
|
import { DEPENDENCY_GRAPH_SKIP_KINDS as SYSTEM_KINDS } from "./system-kinds.js";
|
|
7
8
|
export const resourceId = (kind, name) => `${kind}\0${name}`;
|
|
@@ -126,11 +127,6 @@ function resolveUseAtSite(entry, root, concretePath, schemaDefault) {
|
|
|
126
127
|
: "unmatched";
|
|
127
128
|
return { use: possibleUses(slot), unresolved: entry.useCases, unresolvedReason };
|
|
128
129
|
}
|
|
129
|
-
/** Names the step-list annotation on an array property, if any. */
|
|
130
|
-
function stepContextOf(schema) {
|
|
131
|
-
const annotation = schema?.["x-telo-step-context"];
|
|
132
|
-
return annotation && typeof annotation === "object" ? annotation : undefined;
|
|
133
|
-
}
|
|
134
130
|
/** A resolved plain reference value (`{kind, name}`, optionally `alias`) — the
|
|
135
131
|
* shape `resolveRefSentinels` leaves at a ref site. NOT a step: a bare boot
|
|
136
132
|
* target written `!ref X` must not mint a step node. */
|
|
@@ -339,8 +335,7 @@ export function buildCallGraph(resources, registry, options = {}) {
|
|
|
339
335
|
return;
|
|
340
336
|
const collected = [];
|
|
341
337
|
for (const [key, propSchema] of propertySchemas(schema)) {
|
|
342
|
-
|
|
343
|
-
if (!annotation)
|
|
338
|
+
if (!isStepSlot(propSchema))
|
|
344
339
|
continue;
|
|
345
340
|
const value = node.manifest[key];
|
|
346
341
|
if (!Array.isArray(value))
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import type { LoadedGraph } from "./loaded-types.js";
|
|
2
2
|
import { type AnalysisDiagnostic } from "./types.js";
|
|
3
3
|
/**
|
|
4
|
-
* Convert a graph's import
|
|
5
|
-
*
|
|
4
|
+
* Convert a graph's import failures (`graph.errors`) into structured, coded
|
|
5
|
+
* diagnostics. This is the single source of truth for surfacing a broken
|
|
6
6
|
* import — every host (CLI, VS Code, telo-editor) routes these instead of each
|
|
7
7
|
* re-deriving the channel and drifting (the VS Code extension used to drop it
|
|
8
8
|
* entirely, showing nothing for a broken import).
|
|
9
9
|
*
|
|
10
|
+
* Three codes, because three different people fix them:
|
|
11
|
+
* `INVALID_IMPORT_SOURCE` (the ref is not a module reference at all),
|
|
12
|
+
* `IMPORT_UNRESOLVED` (a well-formed ref that could not be obtained), and
|
|
13
|
+
* `INVALID_IMPORT_TARGET` (obtained, but not an importable library — an
|
|
14
|
+
* application, no library document, or one that names no module). Collapsing
|
|
15
|
+
* the last into the second would tell an author to fix a ref that is correct.
|
|
16
|
+
*
|
|
10
17
|
* The analyzer owns only this raw channel conversion; the *presentation* policy
|
|
11
18
|
* — which analysis cascade to hold back for a compromised file — lives in
|
|
12
19
|
* `@telorun/ide-support`'s `assembleGraphDiagnostics`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-resolution-diagnostics.d.ts","sourceRoot":"","sources":["../src/import-resolution-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"import-resolution-diagnostics.d.ts","sourceRoot":"","sources":["../src/import-resolution-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAyCzE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,WAAW,GAAG,kBAAkB,EAAE,CAepF"}
|