@telorun/analyzer 0.53.0 → 0.55.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 (76) hide show
  1. package/dist/analysis-registry.d.ts +20 -0
  2. package/dist/analysis-registry.d.ts.map +1 -1
  3. package/dist/analysis-registry.js +36 -3
  4. package/dist/analyzer.d.ts +3 -2
  5. package/dist/analyzer.d.ts.map +1 -1
  6. package/dist/analyzer.js +188 -26
  7. package/dist/builtins.d.ts.map +1 -1
  8. package/dist/builtins.js +32 -12
  9. package/dist/call-graph.d.ts +189 -0
  10. package/dist/call-graph.d.ts.map +1 -0
  11. package/dist/call-graph.js +617 -0
  12. package/dist/dependency-graph.d.ts +17 -7
  13. package/dist/dependency-graph.d.ts.map +1 -1
  14. package/dist/dependency-graph.js +36 -65
  15. package/dist/flatten-for-analyzer.d.ts +8 -0
  16. package/dist/flatten-for-analyzer.d.ts.map +1 -1
  17. package/dist/flatten-for-analyzer.js +32 -0
  18. package/dist/index.d.ts +14 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +7 -1
  21. package/dist/manifest-navigation.d.ts +32 -0
  22. package/dist/manifest-navigation.d.ts.map +1 -0
  23. package/dist/manifest-navigation.js +91 -0
  24. package/dist/manifest-visitor.js +1 -1
  25. package/dist/ref-slot.d.ts +125 -0
  26. package/dist/ref-slot.d.ts.map +1 -0
  27. package/dist/ref-slot.js +226 -0
  28. package/dist/reference-field-map.d.ts +15 -1
  29. package/dist/reference-field-map.d.ts.map +1 -1
  30. package/dist/reference-field-map.js +29 -35
  31. package/dist/resolve-schema-ref-kinds.d.ts +4 -0
  32. package/dist/resolve-schema-ref-kinds.d.ts.map +1 -1
  33. package/dist/resolve-schema-ref-kinds.js +31 -8
  34. package/dist/resolve-zone-requirements.d.ts +110 -0
  35. package/dist/resolve-zone-requirements.d.ts.map +1 -0
  36. package/dist/resolve-zone-requirements.js +541 -0
  37. package/dist/types.d.ts +8 -0
  38. package/dist/types.d.ts.map +1 -1
  39. package/dist/validate-observed-state.d.ts +14 -13
  40. package/dist/validate-observed-state.d.ts.map +1 -1
  41. package/dist/validate-observed-state.js +21 -88
  42. package/dist/validate-ref-slots.d.ts +48 -0
  43. package/dist/validate-ref-slots.d.ts.map +1 -0
  44. package/dist/validate-ref-slots.js +219 -0
  45. package/dist/validate-references.d.ts.map +1 -1
  46. package/dist/validate-references.js +8 -1
  47. package/dist/validate-zone-slots.d.ts +39 -0
  48. package/dist/validate-zone-slots.d.ts.map +1 -0
  49. package/dist/validate-zone-slots.js +114 -0
  50. package/dist/zone-module-documents.d.ts +27 -0
  51. package/dist/zone-module-documents.d.ts.map +1 -0
  52. package/dist/zone-module-documents.js +1 -0
  53. package/dist/zone-slot.d.ts +61 -0
  54. package/dist/zone-slot.d.ts.map +1 -0
  55. package/dist/zone-slot.js +91 -0
  56. package/package.json +3 -3
  57. package/src/analysis-registry.ts +36 -2
  58. package/src/analyzer.ts +206 -24
  59. package/src/builtins.ts +32 -12
  60. package/src/call-graph.ts +827 -0
  61. package/src/dependency-graph.ts +34 -68
  62. package/src/flatten-for-analyzer.ts +32 -0
  63. package/src/index.ts +47 -0
  64. package/src/manifest-navigation.ts +91 -0
  65. package/src/manifest-visitor.ts +1 -1
  66. package/src/ref-slot.ts +273 -0
  67. package/src/reference-field-map.ts +39 -36
  68. package/src/resolve-schema-ref-kinds.ts +34 -7
  69. package/src/resolve-zone-requirements.ts +781 -0
  70. package/src/types.ts +8 -0
  71. package/src/validate-observed-state.ts +26 -92
  72. package/src/validate-ref-slots.ts +293 -0
  73. package/src/validate-references.ts +8 -1
  74. package/src/validate-zone-slots.ts +175 -0
  75. package/src/zone-module-documents.ts +27 -0
  76. package/src/zone-slot.ts +116 -0
@@ -36,6 +36,18 @@ export declare class AnalysisRegistry {
36
36
  /** An alias crossing no import boundary, never gated — `Self`, the `Telo` built-ins. */
37
37
  registerUngatedAlias(alias: string, target: string): void;
38
38
  resolveKind(kind: string): string | undefined;
39
+ /** Rewrite `telo://Self/<type>` / `telo://<Alias>/<type>` schema references in
40
+ * `manifests` to the canonical id their type registered under, in the scope
41
+ * each doc was declared in. Idempotent — an already-canonical ref resolves to
42
+ * no module and is left alone.
43
+ *
44
+ * `analyze()` runs this over its own view; a caller holding a separately
45
+ * flattened projection (the kernel's build-time validator warm, which must
46
+ * resolve a `$ref` contract exactly as the runtime will) needs it applied to
47
+ * that projection too. Exposed as a method because the alias tables are this
48
+ * registry's, and handing them out would make every consumer's scoping its
49
+ * own problem. */
50
+ resolveSchemaTypeRefs(manifests: ResourceManifest[]): void;
39
51
  /**
40
52
  * Iterates a resource's reference and scope fields as declared by its definition.
41
53
  * Calls onRef for each plain reference field and onScope for each scope field.
@@ -82,6 +94,14 @@ export declare class AnalysisRegistry {
82
94
  * of modules. */
83
95
  private scopedDefResolver;
84
96
  private capabilitiesForRefs;
97
+ /** Like {@link capabilityForRef}, but a capability GROUP — an abstract with no
98
+ * `capability` of its own that other capability abstracts extend, i.e.
99
+ * `Telo.Executable` over Invocable and Runnable — expands to its leaves.
100
+ * Classification consumers (the editor's port flavor) match against leaf
101
+ * capabilities, so without expansion every `Telo.Executable` slot would fall
102
+ * out of both classification sets and silently stop rendering — and so would
103
+ * slots constrained to the next abstract-of-abstracts. */
104
+ private leafCapabilitiesForRef;
85
105
  /**
86
106
  * Walks a manifest's annotation sites (refs, scopes, schema-from, CEL) via
87
107
  * the shared manifest visitor, bound to this registry's definitions and
@@ -1 +1 @@
1
- {"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ import { computeSuggestKind, computeValidUserFacingKinds } from "./kind-suggest.
5
5
  import { visitManifest as runVisitManifest } from "./manifest-visitor.js";
6
6
  import { resolveContract } from "./invocation-contract.js";
7
7
  import { isRefEntry, isScopeEntry } from "./reference-field-map.js";
8
+ import { resolveSchemaTypeRefs as resolveSchemaTypeRefsIn } from "./resolve-schema-type-refs.js";
8
9
  /**
9
10
  * Accumulates type and alias knowledge for a running kernel or analysis session.
10
11
  * Wraps AliasResolver and DefinitionRegistry into a single domain-level interface
@@ -33,6 +34,20 @@ export class AnalysisRegistry {
33
34
  resolveKind(kind) {
34
35
  return this.aliases.resolveKind(kind);
35
36
  }
37
+ /** Rewrite `telo://Self/<type>` / `telo://<Alias>/<type>` schema references in
38
+ * `manifests` to the canonical id their type registered under, in the scope
39
+ * each doc was declared in. Idempotent — an already-canonical ref resolves to
40
+ * no module and is left alone.
41
+ *
42
+ * `analyze()` runs this over its own view; a caller holding a separately
43
+ * flattened projection (the kernel's build-time validator warm, which must
44
+ * resolve a `$ref` contract exactly as the runtime will) needs it applied to
45
+ * that projection too. Exposed as a method because the alias tables are this
46
+ * registry's, and handing them out would make every consumer's scoping its
47
+ * own problem. */
48
+ resolveSchemaTypeRefs(manifests) {
49
+ resolveSchemaTypeRefsIn(manifests, this.aliases, this.aliasesByModule);
50
+ }
36
51
  /**
37
52
  * Iterates a resource's reference and scope fields as declared by its definition.
38
53
  * Calls onRef for each plain reference field and onScope for each scope field.
@@ -132,12 +147,30 @@ export class AnalysisRegistry {
132
147
  capabilitiesForRefs(refs) {
133
148
  const out = [];
134
149
  for (const ref of refs) {
135
- const cap = this.capabilityForRef(ref);
136
- if (cap && !out.includes(cap))
137
- out.push(cap);
150
+ for (const cap of this.leafCapabilitiesForRef(ref)) {
151
+ if (!out.includes(cap))
152
+ out.push(cap);
153
+ }
138
154
  }
139
155
  return out;
140
156
  }
157
+ /** Like {@link capabilityForRef}, but a capability GROUP — an abstract with no
158
+ * `capability` of its own that other capability abstracts extend, i.e.
159
+ * `Telo.Executable` over Invocable and Runnable — expands to its leaves.
160
+ * Classification consumers (the editor's port flavor) match against leaf
161
+ * capabilities, so without expansion every `Telo.Executable` slot would fall
162
+ * out of both classification sets and silently stop rendering — and so would
163
+ * slots constrained to the next abstract-of-abstracts. */
164
+ leafCapabilitiesForRef(xTeloRef) {
165
+ const cap = this.capabilityForRef(xTeloRef);
166
+ if (!cap)
167
+ return [];
168
+ const leaves = this.defs
169
+ .getByExtends(cap)
170
+ .filter((d) => d.kind === "Telo.Abstract" && !d.capability)
171
+ .map((d) => `${d.metadata.module}.${d.metadata.name}`);
172
+ return leaves.length > 0 ? leaves : [cap];
173
+ }
141
174
  /**
142
175
  * Walks a manifest's annotation sites (refs, scopes, schema-from, CEL) via
143
176
  * the shared manifest visitor, bound to this registry's definitions and
@@ -4,6 +4,7 @@ import { AnalysisRegistry } from "./analysis-registry.js";
4
4
  import { type CelHandlers } from "./cel-environment.js";
5
5
  import { DefinitionRegistry } from "./definition-registry.js";
6
6
  import { type ContractScope } from "./invocation-contract.js";
7
+ import { type ZoneExportCache } from "./resolve-zone-requirements.js";
7
8
  import { type AnalysisDiagnostic, type AnalysisOptions } from "./types.js";
8
9
  /** The {@link ContractScope} the analyzer resolves invocation contracts in: kinds
9
10
  * resolve in the module that declared the definition they were read off (so an
@@ -60,8 +61,8 @@ export declare class StaticAnalyzer {
60
61
  * `analyze()`. A missing position throws a clear error rather than
61
62
  * silently producing wrong diagnostics.
62
63
  */
63
- analyze(manifests: ResourceManifest[], options?: AnalysisOptions, registry?: AnalysisRegistry): AnalysisDiagnostic[];
64
- analyzeErrors(manifests: ResourceManifest[], options?: AnalysisOptions, registry?: AnalysisRegistry): AnalysisDiagnostic[];
64
+ analyze(manifests: ResourceManifest[], options?: AnalysisOptions, registry?: AnalysisRegistry, zoneExportCache?: ZoneExportCache): AnalysisDiagnostic[];
65
+ analyzeErrors(manifests: ResourceManifest[], options?: AnalysisOptions, registry?: AnalysisRegistry, zoneExportCache?: ZoneExportCache): AnalysisDiagnostic[];
65
66
  normalize(manifests: ResourceManifest[], registry: AnalysisRegistry, crossModuleTargets?: ResourceManifest[]): ResourceManifest[];
66
67
  prepare(manifests: ResourceManifest[], registry: AnalysisRegistry): {
67
68
  diagnostics: AnalysisDiagnostic[];
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
package/dist/analyzer.js CHANGED
@@ -5,6 +5,7 @@ import { buildCelEnvironment, buildImportInputCelEnvironment, buildTypedCelEnvir
5
5
  import { DefinitionRegistry } from "./definition-registry.js";
6
6
  import { effectiveAuthorSchema } from "./extends-resolution.js";
7
7
  import { PERMISSIVE_CONTRACT, resolveContract, } from "./invocation-contract.js";
8
+ import { buildCallGraph } from "./call-graph.js";
8
9
  import { buildDependencyGraph, formatCycle } from "./dependency-graph.js";
9
10
  import { buildKernelGlobalsSchema, KERNEL_GLOBAL_NAMES, mergeKernelGlobalsIntoContext, } from "./kernel-globals.js";
10
11
  import { buildObservedStateIndex, buildObservedStateResourcesSchema, collectRunReachableNames, observedStateRead, validateObservedStateDeclarations, } from "./validate-observed-state.js";
@@ -15,6 +16,9 @@ import { normalizeInlineResources } from "./normalize-inline-resources.js";
15
16
  import { REF_VALIDATION_SKIP_KINDS } from "./system-kinds.js";
16
17
  import { resolveRefSentinels } from "./resolve-ref-sentinels.js";
17
18
  import { resolveSchemaRefKinds } from "./resolve-schema-ref-kinds.js";
19
+ import { runZoneAnalysis } from "./resolve-zone-requirements.js";
20
+ import { validateZoneSlotDeclarations } from "./validate-zone-slots.js";
21
+ import { validateDynamicSelectors, validateRefSlotDeclarations, } from "./validate-ref-slots.js";
18
22
  import { resolveSchemaTypeRefs } from "./resolve-schema-type-refs.js";
19
23
  import { validateSchemaTypeRefs } from "./validate-schema-type-refs.js";
20
24
  import { rewriteSyntheticOrigins } from "./rewrite-synthetic-origins.js";
@@ -380,23 +384,76 @@ function buildStepContextSchema(manifest, defSchema, allManifests, defs, aliases
380
384
  }
381
385
  return undefined;
382
386
  }
383
- /**
384
- * Capabilities whose instances structurally expose no `invoke`/`run` method, so
385
- * a step `invoke` of one always fails at runtime with ERR_RESOURCE_NOT_INVOKABLE
386
- * (kernel dispatch checks method presence, not capability — evaluation-context.ts).
387
- * `Telo.Service` is intentionally absent: some services are invocable (a function
388
- * handler dispatched directly, e.g. `Lambda.Function`), so it can't be rejected
389
- * statically without false positives. This is the sound subset of the runtime rule.
390
- */
391
387
  /** The built-in namespace: globally resolvable, crossing no import boundary. */
392
388
  const TELO_BUILTIN_MODULE = "Telo";
393
- const NON_INVOKABLE_CAPABILITIES = new Set([
394
- "Telo.Provider",
389
+ /** One mapping from a ref-slot issue to a diagnostic — the shape is identical
390
+ * for the schema-level and the manifest-level (dynamic selector) checks. */
391
+ function refSlotIssueDiagnostic(issue) {
392
+ return {
393
+ severity: DiagnosticSeverity.Error,
394
+ code: issue.code,
395
+ source: SOURCE,
396
+ message: issue.message,
397
+ data: {
398
+ resource: { kind: issue.manifest.kind, name: issue.manifest.metadata?.name },
399
+ filePath: issue.manifest.metadata?.source,
400
+ path: issue.path,
401
+ },
402
+ };
403
+ }
404
+ /**
405
+ * Is this kind acceptable in a slot that transfers control?
406
+ *
407
+ * The executable side is a POSITIVE test against the `Telo.Executable`
408
+ * hierarchy: a capability that is, or `extends`, `Telo.Executable` is
409
+ * executable, so a future executable capability opts in with one `extends:`
410
+ * edge — no name list here to keep in step. This replaced
411
+ * `NON_INVOKABLE_CAPABILITIES`, a maintained set of capabilities the analyzer
412
+ * believed could never be invoked, which was unsound in the direction that
413
+ * rejects working manifests: it listed `Telo.Provider`, and `Ai.Model` is a
414
+ * Provider the agent controller invokes directly — the divergence being
415
+ * structural versus nominal, since the kernel tests method presence at dispatch
416
+ * while any static test can only read a declared capability.
417
+ *
418
+ * Outside the hierarchy nothing is guessed: `Telo.Provider` (entry points by
419
+ * convention) and `Telo.Service` (some services are invocable) pass, an unknown
420
+ * capability passes (rejecting it would be the wrong polarity for third-party
421
+ * extensions), and only the kernel-owned capabilities whose CONTRACT has no
422
+ * entry point — `Telo.Type`, `Telo.Mount`, `Telo.Template`, `Telo.Sink` (a sink
423
+ * is written to through a direct contract on the controller instance, never
424
+ * dispatched) — are rejected. That last set is the capabilities' own
425
+ * definition, not a belief about controllers.
426
+ */
427
+ function isExecutableKind(kind, defs, aliases) {
428
+ const canonical = aliases.resolveKind(kind) ?? kind;
429
+ const def = defs.resolve(canonical);
430
+ if (!def)
431
+ return true;
432
+ const capability = def.capability;
433
+ if (!capability)
434
+ return true;
435
+ if (capabilityExtendsExecutable(capability, defs))
436
+ return true;
437
+ return !NO_ENTRY_POINT_CAPABILITIES.has(capability);
438
+ }
439
+ /** Does this capability name `Telo.Executable` or extend it, transitively?
440
+ * Derived from the abstract hierarchy at call time, never from a name list. */
441
+ function capabilityExtendsExecutable(capability, defs) {
442
+ let current = capability;
443
+ const seen = new Set();
444
+ while (current && !seen.has(current)) {
445
+ if (current === "Telo.Executable")
446
+ return true;
447
+ seen.add(current);
448
+ current = defs.resolve(current)?.extends;
449
+ }
450
+ return false;
451
+ }
452
+ /** Kernel-owned capabilities whose contract declares no entry point. */
453
+ const NO_ENTRY_POINT_CAPABILITIES = new Set([
395
454
  "Telo.Mount",
396
455
  "Telo.Type",
397
456
  "Telo.Template",
398
- // A sink is written to through a direct contract on the controller instance,
399
- // never dispatched — so invoking one is statically wrong.
400
457
  "Telo.Sink",
401
458
  ]);
402
459
  /**
@@ -414,9 +471,10 @@ const NON_INVOKABLE_CAPABILITIES = new Set([
414
471
  * *kind* instead of an exported instance (`!ref Stream.Of`) — is a still-a-
415
472
  * sentinel after Phase 2.5 resolution → `UNRESOLVED_REFERENCE` (runtime
416
473
  * `ERR_RESOURCE_NOT_FOUND`).
417
- * - Invokability: a resolved instance whose capability structurally has no
418
- * invoke/run method (`NON_INVOKABLE_CAPABILITIES`) `REFERENCE_KIND_MISMATCH`
419
- * (runtime `ERR_RESOURCE_NOT_INVOKABLE`).
474
+ * - Invokability: a resolved instance whose kind fails `isExecutableKind`
475
+ * outside the `Telo.Executable` hierarchy AND declaring a capability whose
476
+ * contract has no entry point → `REFERENCE_KIND_MISMATCH` (runtime
477
+ * `ERR_RESOURCE_NOT_INVOKABLE`).
420
478
  *
421
479
  * Generic and topology-driven — it walks steps via the same `x-telo-step-context`
422
480
  * / `x-telo-topology-role` annotations `buildStepContextSchema` uses (through the
@@ -506,17 +564,15 @@ function validateStepInvokeReferences(allManifests, defs, aliases) {
506
564
  // Resolved `{kind, name}` (or an inline `{kind, …}` definition) — the
507
565
  // instance exists. Mirror the kernel's ERR_RESOURCE_NOT_INVOKABLE, which
508
566
  // fires when the instance has neither an `invoke` nor a `run` method
509
- // (evaluation-context.ts). That is a per-instance property, not a pure
510
- // capability, so only capabilities that STRUCTURALLY expose no such method
511
- // are rejected statically — Service is intentionally excluded, since some
512
- // services are invocable (e.g. a function handler dispatched directly).
567
+ // (evaluation-context.ts). That is a per-instance property, so the static
568
+ // test only rejects a kind whose declared capability names no entry point.
513
569
  if (!value || typeof value !== "object" || Array.isArray(value))
514
570
  return;
515
571
  const kind = value.kind;
516
572
  if (typeof kind !== "string")
517
573
  return;
518
- const capability = defs.resolve(aliases.resolveKind(kind) ?? kind)?.capability;
519
- if (typeof capability === "string" && NON_INVOKABLE_CAPABILITIES.has(capability)) {
574
+ if (!isExecutableKind(kind, defs, aliases)) {
575
+ const capability = defs.resolve(aliases.resolveKind(kind) ?? kind)?.capability;
520
576
  diagnostics.push({
521
577
  severity: DiagnosticSeverity.Error,
522
578
  code: "REFERENCE_KIND_MISMATCH",
@@ -774,7 +830,7 @@ export class StaticAnalyzer {
774
830
  * `analyze()`. A missing position throws a clear error rather than
775
831
  * silently producing wrong diagnostics.
776
832
  */
777
- analyze(manifests, options, registry) {
833
+ analyze(manifests, options, registry, zoneExportCache) {
778
834
  assertManifestPositions(manifests);
779
835
  const diagnostics = [];
780
836
  // Use pre-seeded registries from the provided AnalysisRegistry, or create fresh ones.
@@ -943,6 +999,8 @@ export class StaticAnalyzer {
943
999
  // of alias choices. `capability` covers the legacy implements-this-abstract overload;
944
1000
  // `extends` is the canonical first-class form.
945
1001
  const refConstraintIssues = [];
1002
+ const refSlotIssues = [];
1003
+ const zoneSlotIssues = [];
946
1004
  for (const m of manifests) {
947
1005
  if (m.kind !== "Telo.Definition" && m.kind !== "Telo.Abstract")
948
1006
  continue;
@@ -959,11 +1017,35 @@ export class StaticAnalyzer {
959
1017
  // still on the deprecated form — or with a constraint that no longer
960
1018
  // resolves — is not the consumer's to fix, and every import would
961
1019
  // otherwise flood `telo check` with unactionable noise.
962
- if (!ownModule || rootModules.has(ownModule))
1020
+ if (!ownModule || rootModules.has(ownModule)) {
963
1021
  refConstraintIssues.push(...issues);
1022
+ refSlotIssues.push(...validateRefSlotDeclarations(m));
1023
+ zoneSlotIssues.push(...validateZoneSlotDeclarations(m));
1024
+ }
964
1025
  const resolvedCapability = def.capability
965
1026
  ? (scopeResolver.resolveKind(def.capability) ?? def.capability)
966
1027
  : def.capability;
1028
+ // `Telo.Executable` is a slot constraint — the x-telo-ref parent of
1029
+ // Invocable and Runnable — and names no lifecycle role. The kernel
1030
+ // rejects it at load; without this the analyzer would report "no issues"
1031
+ // on a manifest that cannot boot.
1032
+ if (resolvedCapability === "Telo.Executable" &&
1033
+ (!ownModule || rootModules.has(ownModule))) {
1034
+ diagnostics.push({
1035
+ severity: DiagnosticSeverity.Error,
1036
+ code: "CAPABILITY_NOT_DECLARABLE",
1037
+ source: SOURCE,
1038
+ message: `'${def.metadata?.name}' declares capability: Telo.Executable, which is an ` +
1039
+ `x-telo-ref slot constraint (the parent Telo.Invocable and Telo.Runnable extend), ` +
1040
+ `not a declarable lifecycle role. Declare 'Telo.Invocable' (invoke) or ` +
1041
+ `'Telo.Runnable' (run) instead.`,
1042
+ data: {
1043
+ resource: { kind: m.kind, name: m.metadata?.name },
1044
+ filePath: m.metadata?.source,
1045
+ path: "capability",
1046
+ },
1047
+ });
1048
+ }
967
1049
  const resolvedExtends = def.extends
968
1050
  ? (scopeResolver.resolveKind(def.extends) ?? def.extends)
969
1051
  : def.extends;
@@ -992,6 +1074,23 @@ export class StaticAnalyzer {
992
1074
  };
993
1075
  const filePath = issue.manifest.metadata?.source;
994
1076
  const data = { resource, filePath, path: issue.path };
1077
+ if (issue.annotation === "zone") {
1078
+ // Mirrors X_TELO_REF_UNRESOLVED: an unresolvable provider kind would
1079
+ // leave the requirement silently unenforced — no provider ever
1080
+ // matches a kind that does not exist.
1081
+ diagnostics.push({
1082
+ severity: DiagnosticSeverity.Error,
1083
+ code: "ZONE_PROVIDER_UNRESOLVED",
1084
+ source: SOURCE,
1085
+ message: `x-telo-requires-zone '${issue.ref}' at '${issue.path}' names no kind. The prefix ` +
1086
+ `must be an import alias declared in this file's 'imports:' map, 'Self' for a kind ` +
1087
+ `in this library, or 'Telo' for a built-in. An unresolvable zone would leave the ` +
1088
+ `requirement silently unenforced. Known aliases: ` +
1089
+ `${issue.knownAliases?.join(", ") || "(none)"}.`,
1090
+ data,
1091
+ });
1092
+ continue;
1093
+ }
995
1094
  if (issue.reason === "legacy") {
996
1095
  diagnostics.push({
997
1096
  severity: DiagnosticSeverity.Warning,
@@ -1031,6 +1130,31 @@ export class StaticAnalyzer {
1031
1130
  }
1032
1131
  }
1033
1132
  diagnostics.push(...validateReferenceForms(manifests, defs, aliases, aliasesByModule));
1133
+ // The x-telo-ref annotation's own validity — the strict half of the
1134
+ // accessor split; `readRefSlot` stays lenient so surfaces keep working
1135
+ // mid-migration, and this reports what leniency would silently absorb.
1136
+ for (const issue of refSlotIssues)
1137
+ diagnostics.push(refSlotIssueDiagnostic(issue));
1138
+ // Same split for the two zone annotations. Unreadable ones fail in
1139
+ // OPPOSITE directions — a dropped requirement is silently unenforced, a
1140
+ // dropped provision invents failures — so neither can be left to
1141
+ // leniency.
1142
+ for (const issue of zoneSlotIssues) {
1143
+ diagnostics.push({
1144
+ severity: DiagnosticSeverity.Error,
1145
+ code: issue.code,
1146
+ source: SOURCE,
1147
+ message: issue.message,
1148
+ data: {
1149
+ resource: {
1150
+ kind: issue.manifest.kind,
1151
+ name: issue.manifest.metadata?.name,
1152
+ },
1153
+ filePath: issue.manifest.metadata?.source,
1154
+ path: issue.path,
1155
+ },
1156
+ });
1157
+ }
1034
1158
  }
1035
1159
  // Phase 2: extract inline resources from x-telo-ref slots into first-class manifests
1036
1160
  const allManifests = normalizeInlineResources(manifests, defs, aliases, aliasesByModule);
@@ -1039,6 +1163,44 @@ export class StaticAnalyzer {
1039
1163
  // kernel controllers) see a uniform shape. Runs after normalize so both
1040
1164
  // original and inline-extracted manifests have their sentinels resolved.
1041
1165
  resolveRefSentinels(allManifests, aliases, aliasesByModule, [], defs);
1166
+ // ONE typed reference graph per analysis. Both graph consumers in this
1167
+ // pass (the dynamic-selector check and run-reachability) read the same
1168
+ // build — constructing it per consumer is strictly more work than the
1169
+ // walks it replaced, and performance is a core goal. Lazy, so a
1170
+ // skipValidation pass with no observed state builds nothing.
1171
+ let callGraphMemo;
1172
+ const getCallGraph = () => (callGraphMemo ??= buildCallGraph(allManifests, defs, {
1173
+ aliases,
1174
+ aliasesByModule,
1175
+ }));
1176
+ // A `use` case map's selector written in CEL is a hard diagnostic — a call
1177
+ // graph known only at runtime is not statically analyzable, and no fallback
1178
+ // is conservative for every consumer. Scoped to the entry's own modules:
1179
+ // a published dependency's manifest is not the consumer's to fix.
1180
+ if (!options?.skipValidation) {
1181
+ for (const issue of validateDynamicSelectors(allManifests, defs, aliases, aliasesByModule, getCallGraph())) {
1182
+ const ownModule = issue.manifest.metadata?.module;
1183
+ if (ownModule && !rootModules.has(ownModule))
1184
+ continue;
1185
+ diagnostics.push(refSlotIssueDiagnostic(issue));
1186
+ }
1187
+ // Zone requirements — a projection over the same graph: propagate along
1188
+ // `call` edges, discharge at providing slots under correlation, fire at
1189
+ // terminating edges and boot. Imported libraries' export contracts are
1190
+ // derived over their full documents (options.moduleDocuments — the
1191
+ // flattened view no longer holds their internal dispatch chains), cached
1192
+ // per library in the host-lifetime `zoneExportCache`.
1193
+ diagnostics.push(...runZoneAnalysis({
1194
+ manifests: allManifests,
1195
+ graph: getCallGraph(),
1196
+ defs,
1197
+ aliases,
1198
+ aliasesByModule,
1199
+ rootModules,
1200
+ moduleDocuments: options?.moduleDocuments,
1201
+ cache: zoneExportCache,
1202
+ }));
1203
+ }
1042
1204
  // Phase 2.6: register each named `Telo.Type` resource's schema under its
1043
1205
  // canonical module-scoped id (`telo://<module>/<name>`), validate
1044
1206
  // `telo://Self|Alias/Type` schema refs resolve to one, then rewrite those
@@ -1195,7 +1357,7 @@ export class StaticAnalyzer {
1195
1357
  const observedState = buildObservedStateIndex(allManifests, defs, aliases, moduleScopes);
1196
1358
  const reportsObservedState = [...observedState.values()].some((r) => r.status);
1197
1359
  const runReachable = reportsObservedState
1198
- ? collectRunReachableNames(allManifests, defs, aliases)
1360
+ ? collectRunReachableNames(getCallGraph())
1199
1361
  : new Set();
1200
1362
  // Build typed kernel globals schema so x-telo-context chain validation
1201
1363
  // recognises variables, secrets, resources, env automatically
@@ -1789,8 +1951,8 @@ export class StaticAnalyzer {
1789
1951
  // the chain root so position-index lookups land on the parent doc.
1790
1952
  return rewriteSyntheticOrigins(diagnostics, allManifests);
1791
1953
  }
1792
- analyzeErrors(manifests, options, registry) {
1793
- return this.analyze(manifests, options, registry).filter((d) => d.severity === DiagnosticSeverity.Error);
1954
+ analyzeErrors(manifests, options, registry, zoneExportCache) {
1955
+ return this.analyze(manifests, options, registry, zoneExportCache).filter((d) => d.severity === DiagnosticSeverity.Error);
1794
1956
  }
1795
1957
  normalize(manifests, registry,
1796
1958
  // Forwarded foreign exports used only as cross-module resolution targets (see
@@ -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,EAmsB/C,CAAC"}
1
+ {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AA6JvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,EAqtB/C,CAAC"}
package/dist/builtins.js CHANGED
@@ -134,7 +134,9 @@ const ROOT_LOGGING_SCHEMA = {
134
134
  type: "array",
135
135
  items: {
136
136
  type: "object",
137
- "x-telo-ref": "Telo.LogSink",
137
+ // A sink is written to directly by the logging pipeline, never through
138
+ // `ctx.invoke` — so from the Application's side it is held, not called.
139
+ "x-telo-ref": { kind: "Telo.LogSink", use: "dependency" },
138
140
  "x-telo-inline": true,
139
141
  },
140
142
  },
@@ -143,9 +145,22 @@ const ROOT_LOGGING_SCHEMA = {
143
145
  };
144
146
  export const KERNEL_BUILTINS = [
145
147
  { kind: "Telo.Abstract", metadata: { name: "Template", module: "Telo" } },
146
- { kind: "Telo.Abstract", metadata: { name: "Runnable", module: "Telo" } },
148
+ // "Control can be transferred to this" the parent of Invocable and Runnable,
149
+ // and the only thing a slot that accepts either needs to say. It is a SLOT
150
+ // CONSTRAINT, never a lifecycle role: `capability: Telo.Executable` is rejected
151
+ // because it is absent from the kernel's `KNOWN_CAPABILITIES` enum, which is
152
+ // what keeps "what a resource is" and "what a slot does with it" separate.
153
+ //
154
+ // `Telo.Service` is deliberately NOT under it. A Service's `run()` is a
155
+ // lifecycle start the kernel dispatches differently (no ambient scope, so
156
+ // inbound work roots its own trace), and admitting it here would make every
157
+ // step's `invoke:` slot accept a service. Boot-target slots that genuinely take
158
+ // `Runnable | Service` stay kind lists — the honest shape for a heterogeneous
159
+ // set.
160
+ { kind: "Telo.Abstract", metadata: { name: "Executable", module: "Telo" } },
161
+ { kind: "Telo.Abstract", metadata: { name: "Runnable", module: "Telo" }, extends: "Telo.Executable" },
147
162
  { kind: "Telo.Abstract", metadata: { name: "Service", module: "Telo" } },
148
- { kind: "Telo.Abstract", metadata: { name: "Invocable", module: "Telo" } },
163
+ { kind: "Telo.Abstract", metadata: { name: "Invocable", module: "Telo" }, extends: "Telo.Executable" },
149
164
  { kind: "Telo.Abstract", metadata: { name: "Mount", module: "Telo" } },
150
165
  { kind: "Telo.Abstract", metadata: { name: "Type", module: "Telo" } },
151
166
  {
@@ -544,12 +559,16 @@ export const KERNEL_BUILTINS = [
544
559
  "x-telo-step-context": { invoke: "invoke", outputType: "outputType" },
545
560
  type: "array",
546
561
  items: {
562
+ // A genuinely heterogeneous set stays a kind list: `Telo.Service` is
563
+ // deliberately outside `Telo.Executable`, since a service's `run()`
564
+ // is a lifecycle start the kernel dispatches without an ambient
565
+ // scope.
566
+ "x-telo-ref": { kind: ["Telo.Runnable", "Telo.Service"], use: "call" },
547
567
  anyOf: [
548
- { type: "string", "x-telo-ref": "Telo.Runnable" },
549
- { type: "string", "x-telo-ref": "Telo.Service" },
568
+ { type: "string" },
550
569
  // Post-resolution shape that `resolveRefSentinels`
551
570
  // substitutes a `!ref <name>` sentinel into. The
552
- // adjacent `x-telo-ref` constraints govern the kind
571
+ // adjacent `x-telo-ref` constraint governs the kind
553
572
  // check; this branch only admits the structural form so
554
573
  // AJV doesn't reject a resolved ref.
555
574
  {
@@ -569,9 +588,9 @@ export const KERNEL_BUILTINS = [
569
588
  required: ["ref"],
570
589
  properties: {
571
590
  ref: {
591
+ "x-telo-ref": { kind: ["Telo.Runnable", "Telo.Service"], use: "call" },
572
592
  anyOf: [
573
- { type: "string", "x-telo-ref": "Telo.Runnable" },
574
- { type: "string", "x-telo-ref": "Telo.Service" },
593
+ { type: "string" },
575
594
  {
576
595
  type: "object",
577
596
  required: ["kind", "name"],
@@ -603,6 +622,11 @@ export const KERNEL_BUILTINS = [
603
622
  name: { type: "string" },
604
623
  invoke: {
605
624
  "x-telo-topology-role": "invoke",
625
+ "x-telo-ref": {
626
+ kind: "Telo.Executable",
627
+ use: "call",
628
+ inputs: "/inputs",
629
+ },
606
630
  type: "object",
607
631
  required: ["kind", "name"],
608
632
  properties: {
@@ -610,10 +634,6 @@ export const KERNEL_BUILTINS = [
610
634
  name: { type: "string" },
611
635
  },
612
636
  additionalProperties: true,
613
- anyOf: [
614
- { "x-telo-ref": "Telo.Invocable" },
615
- { "x-telo-ref": "Telo.Runnable" },
616
- ],
617
637
  },
618
638
  inputs: {
619
639
  // Same annotation Run.Sequence steps carry: it is what makes