@telorun/analyzer 0.70.0 → 0.72.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 (122) hide show
  1. package/dist/analysis-registry.d.ts.map +1 -1
  2. package/dist/analysis-registry.js +4 -5
  3. package/dist/analyzer.d.ts.map +1 -1
  4. package/dist/analyzer.js +92 -10
  5. package/dist/call-graph.d.ts.map +1 -1
  6. package/dist/call-graph.js +10 -4
  7. package/dist/catch-scope.d.ts +72 -0
  8. package/dist/catch-scope.d.ts.map +1 -0
  9. package/dist/catch-scope.js +102 -0
  10. package/dist/cel-scope-query.d.ts +14 -0
  11. package/dist/cel-scope-query.d.ts.map +1 -1
  12. package/dist/cel-scope-query.js +36 -6
  13. package/dist/definition-registry.d.ts.map +1 -1
  14. package/dist/definition-registry.js +3 -4
  15. package/dist/deprecation.d.ts +21 -0
  16. package/dist/deprecation.d.ts.map +1 -0
  17. package/dist/deprecation.js +26 -0
  18. package/dist/flatten-for-analyzer.d.ts +2 -2
  19. package/dist/flatten-for-analyzer.d.ts.map +1 -1
  20. package/dist/flatten-for-analyzer.js +1 -1
  21. package/dist/index.d.ts +5 -3
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +3 -2
  24. package/dist/manifest-visitor.d.ts +17 -1
  25. package/dist/manifest-visitor.d.ts.map +1 -1
  26. package/dist/manifest-visitor.js +16 -4
  27. package/dist/migrations/report.d.ts +1 -1
  28. package/dist/migrations/report.d.ts.map +1 -1
  29. package/dist/migrations/report.js +5 -0
  30. package/dist/module-alias-scope.d.ts +65 -0
  31. package/dist/module-alias-scope.d.ts.map +1 -0
  32. package/dist/module-alias-scope.js +25 -0
  33. package/dist/{zone-module-documents.d.ts → module-documents.d.ts} +11 -7
  34. package/dist/module-documents.d.ts.map +1 -0
  35. package/dist/ref-sentinel-target.d.ts +38 -0
  36. package/dist/ref-sentinel-target.d.ts.map +1 -0
  37. package/dist/ref-sentinel-target.js +13 -0
  38. package/dist/ref-slot.d.ts +15 -0
  39. package/dist/ref-slot.d.ts.map +1 -1
  40. package/dist/ref-slot.js +7 -0
  41. package/dist/resolve-schema-type-refs.d.ts.map +1 -1
  42. package/dist/resolve-schema-type-refs.js +2 -1
  43. package/dist/resolve-throws-union.d.ts +47 -2
  44. package/dist/resolve-throws-union.d.ts.map +1 -1
  45. package/dist/resolve-throws-union.js +199 -20
  46. package/dist/resolve-zone-requirements.d.ts +3 -3
  47. package/dist/resolve-zone-requirements.d.ts.map +1 -1
  48. package/dist/resolve-zone-requirements.js +12 -12
  49. package/dist/schema-compat.d.ts.map +1 -1
  50. package/dist/schema-compat.js +13 -1
  51. package/dist/schema-error-report.d.ts.map +1 -1
  52. package/dist/schema-error-report.js +48 -4
  53. package/dist/schema-keywords.d.ts.map +1 -1
  54. package/dist/schema-keywords.js +3 -1
  55. package/dist/schema-walk.d.ts +27 -0
  56. package/dist/schema-walk.d.ts.map +1 -1
  57. package/dist/schema-walk.js +44 -0
  58. package/dist/telo-version.d.ts +1 -1
  59. package/dist/telo-version.js +1 -1
  60. package/dist/template-body.d.ts.map +1 -1
  61. package/dist/template-body.js +2 -4
  62. package/dist/types.d.ts +20 -3
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/types.js +11 -0
  65. package/dist/validate-identifier-names.d.ts +2 -2
  66. package/dist/validate-identifier-names.d.ts.map +1 -1
  67. package/dist/validate-identifier-names.js +22 -7
  68. package/dist/validate-invocation-contract.d.ts +5 -0
  69. package/dist/validate-invocation-contract.d.ts.map +1 -1
  70. package/dist/validate-invocation-contract.js +114 -3
  71. package/dist/validate-logging.d.ts.map +1 -1
  72. package/dist/validate-logging.js +2 -2
  73. package/dist/validate-ref-slots.d.ts +1 -1
  74. package/dist/validate-ref-slots.d.ts.map +1 -1
  75. package/dist/validate-ref-slots.js +34 -0
  76. package/dist/validate-references.d.ts +16 -5
  77. package/dist/validate-references.d.ts.map +1 -1
  78. package/dist/validate-references.js +57 -15
  79. package/dist/validate-resource-inputs.d.ts +1 -26
  80. package/dist/validate-resource-inputs.d.ts.map +1 -1
  81. package/dist/validate-resource-inputs.js +12 -2
  82. package/dist/validate-schema-type-refs.d.ts.map +1 -1
  83. package/dist/validate-schema-type-refs.js +2 -1
  84. package/dist/validate-throws-coverage.d.ts +5 -1
  85. package/dist/validate-throws-coverage.d.ts.map +1 -1
  86. package/dist/validate-throws-coverage.js +241 -86
  87. package/package.json +3 -3
  88. package/src/analysis-registry.ts +4 -5
  89. package/src/analyzer.ts +115 -11
  90. package/src/call-graph.ts +9 -3
  91. package/src/catch-scope.ts +157 -0
  92. package/src/cel-scope-query.ts +45 -8
  93. package/src/definition-registry.ts +3 -6
  94. package/src/deprecation.ts +36 -0
  95. package/src/flatten-for-analyzer.ts +3 -3
  96. package/src/index.ts +10 -3
  97. package/src/manifest-visitor.ts +30 -5
  98. package/src/migrations/report.ts +5 -1
  99. package/src/module-alias-scope.ts +94 -0
  100. package/src/{zone-module-documents.ts → module-documents.ts} +10 -6
  101. package/src/ref-sentinel-target.ts +46 -0
  102. package/src/ref-slot.ts +19 -0
  103. package/src/resolve-schema-type-refs.ts +2 -1
  104. package/src/resolve-throws-union.ts +253 -20
  105. package/src/resolve-zone-requirements.ts +14 -14
  106. package/src/schema-compat.ts +13 -0
  107. package/src/schema-error-report.ts +50 -6
  108. package/src/schema-keywords.ts +4 -1
  109. package/src/schema-walk.ts +56 -0
  110. package/src/telo-version.ts +1 -1
  111. package/src/template-body.ts +2 -5
  112. package/src/types.ts +21 -3
  113. package/src/validate-identifier-names.ts +28 -9
  114. package/src/validate-invocation-contract.ts +128 -2
  115. package/src/validate-logging.ts +2 -3
  116. package/src/validate-ref-slots.ts +41 -1
  117. package/src/validate-references.ts +74 -14
  118. package/src/validate-resource-inputs.ts +26 -3
  119. package/src/validate-schema-type-refs.ts +2 -1
  120. package/src/validate-throws-coverage.ts +344 -92
  121. package/dist/zone-module-documents.d.ts.map +0 -1
  122. /package/dist/{zone-module-documents.js → module-documents.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"schema-keywords.d.ts","sourceRoot":"","sources":["../src/schema-keywords.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,4EAA4E;AAC5E,QAAA,MAAM,gBAAgB,EAAG,kBAA2B,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D;iDACiD;AACjD,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AASrE;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAuJ/D;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAMxC,OAAO,CAAC,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,gBAAgB,CAAC,GACtE,OAAO,WAAW,EACpB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwJxB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,EAAE,MAAM,CAC/C,OAAO,gBAAgB,EACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQxB,CAAC"}
1
+ {"version":3,"file":"schema-keywords.d.ts","sourceRoot":"","sources":["../src/schema-keywords.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,4EAA4E;AAC5E,QAAA,MAAM,gBAAgB,EAAG,kBAA2B,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D;iDACiD;AACjD,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AASrE;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAuJ/D;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAMxC,OAAO,CAAC,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,gBAAgB,CAAC,GACtE,OAAO,WAAW,EACpB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA2JxB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,EAAE,MAAM,CAC/C,OAAO,gBAAgB,EACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQxB,CAAC"}
@@ -340,7 +340,9 @@ export const TELO_SCHEMA_ANNOTATIONS = {
340
340
  },
341
341
  "x-telo-catches-for": {
342
342
  title: "Catches for",
343
- description: "Names the field whose failures this branch list handles.",
343
+ description: "Whose failures this catch list renders: a sibling field naming the handler, " +
344
+ "or the EMPTY string for everything this resource drives — a scope-level list, " +
345
+ "which owes coverage of nothing itself and answers for every site it encloses.",
344
346
  type: "string",
345
347
  },
346
348
  };
@@ -1,3 +1,5 @@
1
+ import { type RefSlot } from "./ref-slot.js";
2
+ import { type StepSlot } from "./step-slot.js";
1
3
  /** Resolve a local `$ref` (only `#/$defs/<name>` form) against the root schema.
2
4
  * Non-refs and unresolved refs pass through unchanged. */
3
5
  export declare function resolveLocalRef(schema: Record<string, any> | undefined, root: Record<string, any>): Record<string, any> | undefined;
@@ -22,4 +24,29 @@ export declare function gatherPropertySchemas(schema: Record<string, any>, root?
22
24
  * hardcoded; recursion is driven entirely by the schema annotations.
23
25
  */
24
26
  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;
27
+ /** A slot through which a resource drives another. */
28
+ export type DrivenSlot = {
29
+ kind: "step";
30
+ slot: StepSlot;
31
+ data: unknown[];
32
+ path: string;
33
+ } | {
34
+ kind: "ref";
35
+ slot: RefSlot;
36
+ data: unknown;
37
+ path: string;
38
+ };
39
+ /**
40
+ * Every slot of one resource through which it drives another, schema and data in
41
+ * tandem.
42
+ *
43
+ * One traversal with two consumers — the inherited union here, and the catch
44
+ * scope enclosure in `validate-throws-coverage.ts` — because both ask the same
45
+ * structural question and two copies would eventually disagree about where the
46
+ * walk stops. It terminates on the manifest's own depth, and it stops AT a step
47
+ * slot (that traversal owns everything below it, `try`/`catch` subtraction
48
+ * included) and AT a reference slot (a resolved ref is a leaf, `{kind, name}`,
49
+ * with nothing beneath it to visit).
50
+ */
51
+ export declare function forEachDrivenSlot(schema: unknown, data: unknown, visit: (slot: DrivenSlot) => void, path?: string): void;
25
52
  //# sourceMappingURL=schema-walk.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema-walk.d.ts","sourceRoot":"","sources":["../src/schema-walk.ts"],"names":[],"mappings":"AAYA;2DAC2D;AAC3D,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EACvC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACxB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAqBjC;AAID;;;;;;;;iDAQiD;AACjD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACzB,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAsBtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EAAE,EAChB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EAC/C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAC3D,IAAI,CAiDN"}
1
+ {"version":3,"file":"schema-walk.d.ts","sourceRoot":"","sources":["../src/schema-walk.ts"],"names":[],"mappings":"AAWA,OAAO,EAAe,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE7D;2DAC2D;AAC3D,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EACvC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACxB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAqBjC;AAID;;;;;;;;iDAQiD;AACjD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACzB,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAsBtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EAAE,EAChB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EAC/C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAC3D,IAAI,CAiDN;AACD,sDAAsD;AACtD,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,OAAO,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,EACjC,IAAI,SAAK,GACR,IAAI,CA8BN"}
@@ -9,6 +9,8 @@
9
9
  * scope rule is consumed by the IDE, which must not pull the pass in behind it.
10
10
  */
11
11
  import { MANIFEST_SCHEMA_URI, ManifestRootSchema } from "./manifest-schemas.js";
12
+ import { readRefSlot } from "./ref-slot.js";
13
+ import { readStepSlot } from "./step-slot.js";
12
14
  /** Resolve a local `$ref` (only `#/$defs/<name>` form) against the root schema.
13
15
  * Non-refs and unresolved refs pass through unchanged. */
14
16
  export function resolveLocalRef(schema, root) {
@@ -124,3 +126,45 @@ export function walkStepArray(steps, stepItemSchema, rootSchema, basePath, visit
124
126
  }
125
127
  });
126
128
  }
129
+ /**
130
+ * Every slot of one resource through which it drives another, schema and data in
131
+ * tandem.
132
+ *
133
+ * One traversal with two consumers — the inherited union here, and the catch
134
+ * scope enclosure in `validate-throws-coverage.ts` — because both ask the same
135
+ * structural question and two copies would eventually disagree about where the
136
+ * walk stops. It terminates on the manifest's own depth, and it stops AT a step
137
+ * slot (that traversal owns everything below it, `try`/`catch` subtraction
138
+ * included) and AT a reference slot (a resolved ref is a leaf, `{kind, name}`,
139
+ * with nothing beneath it to visit).
140
+ */
141
+ export function forEachDrivenSlot(schema, data, visit, path = "") {
142
+ if (!schema || typeof schema !== "object" || data === undefined || data === null)
143
+ return;
144
+ const node = schema;
145
+ const stepSlot = readStepSlot(node);
146
+ if (stepSlot) {
147
+ if (Array.isArray(data))
148
+ visit({ kind: "step", slot: stepSlot, data, path });
149
+ return;
150
+ }
151
+ const refSlot = readRefSlot(node);
152
+ if (refSlot) {
153
+ visit({ kind: "ref", slot: refSlot, data, path });
154
+ return;
155
+ }
156
+ const props = node.properties;
157
+ if (props && typeof data === "object" && !Array.isArray(data)) {
158
+ const obj = data;
159
+ for (const [key, propSchema] of Object.entries(props)) {
160
+ if (obj[key] === undefined)
161
+ continue;
162
+ forEachDrivenSlot(propSchema, obj[key], visit, path ? `${path}.${key}` : key);
163
+ }
164
+ }
165
+ if (node.items && Array.isArray(data)) {
166
+ for (const [i, item] of data.entries()) {
167
+ forEachDrivenSlot(node.items, item, visit, `${path}[${i}]`);
168
+ }
169
+ }
170
+ }
@@ -1,3 +1,3 @@
1
1
  /** The surface generation this analyzer implements. */
2
- export declare const TELO_SURFACE_VERSION = "0.86.0";
2
+ export declare const TELO_SURFACE_VERSION = "0.88.0";
3
3
  //# sourceMappingURL=telo-version.d.ts.map
@@ -5,4 +5,4 @@
5
5
  // its release identity, this is the scale a module's `requires.telo` range is
6
6
  // written against, and every kernel in every language reports the same scale.
7
7
  /** The surface generation this analyzer implements. */
8
- export const TELO_SURFACE_VERSION = "0.86.0";
8
+ export const TELO_SURFACE_VERSION = "0.88.0";
@@ -1 +1 @@
1
- {"version":3,"file":"template-body.d.ts","sourceRoot":"","sources":["../src/template-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,YAAY;IAC3B;qBACiB;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,UAAU,EAAE,kBAAkB,GAAG,SAAS,CAAC;CAC5C;AAED;mDACmD;AACnD,wBAAgB,cAAc,CAC5B,CAAC,EAAE,gBAAgB,EACnB,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,GAAG,SAAS,EAClC,MAAM,EAAE,YAAY,GAAG,SAAS,GAC/B,YAAY,EAAE,CA8BhB;AAED,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAIhE;AAED;;+EAE+E;AAC/E,wBAAgB,WAAW,CAAC,CAAC,SAAS;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EACtD,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,IAAI,EAAE,MAAM,GACX,CAAC,GAAG,SAAS,CAEf;AAED;;;;6CAI6C;AAC7C,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAQxF"}
1
+ {"version":3,"file":"template-body.d.ts","sourceRoot":"","sources":["../src/template-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,YAAY;IAC3B;qBACiB;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,UAAU,EAAE,kBAAkB,GAAG,SAAS,CAAC;CAC5C;AAED;mDACmD;AACnD,wBAAgB,cAAc,CAC5B,CAAC,EAAE,gBAAgB,EACnB,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,GAAG,SAAS,EAClC,MAAM,EAAE,YAAY,GAAG,SAAS,GAC/B,YAAY,EAAE,CA0BhB;AAED,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAIhE;AAED;;+EAE+E;AAC/E,wBAAgB,WAAW,CAAC,CAAC,SAAS;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EACtD,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,IAAI,EAAE,MAAM,GACX,CAAC,GAAG,SAAS,CAEf;AAED;;;;6CAI6C;AAC7C,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAQxF"}
@@ -1,3 +1,4 @@
1
+ import { moduleAliasScope } from "./module-alias-scope.js";
1
2
  /** The template bodies a manifest declares — empty for anything that is not a
2
3
  * `Telo.Definition` with a `resources:` array. */
3
4
  export function templateBodies(m, registry, aliases, scopes) {
@@ -9,10 +10,7 @@ export function templateBodies(m, registry, aliases, scopes) {
9
10
  // A nested kind is written through the alias scope of the module that DECLARED
10
11
  // the definition, never the consumer's — the same rule every other kind
11
12
  // resolution in a forwarded manifest follows.
12
- const ownModule = m.metadata?.module;
13
- const scope = (ownModule && scopes && !scopes.rootModules.has(ownModule)
14
- ? scopes.aliasesByModule.get(ownModule)
15
- : undefined) ?? aliases;
13
+ const scope = moduleAliasScope(m.metadata, aliases, scopes?.aliasesByModule);
16
14
  const out = [];
17
15
  for (let i = 0; i < bodies.length; i++) {
18
16
  const body = bodies[i];
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { HostVersions } from "./requires-block.js";
2
- import type { ZoneModuleDocuments } from "./zone-module-documents.js";
2
+ import type { ModuleDocuments } from "./module-documents.js";
3
3
  /** Matches LSP DiagnosticSeverity values exactly.
4
4
  * https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnosticSeverity */
5
5
  export declare const DiagnosticSeverity: {
@@ -9,6 +9,18 @@ export declare const DiagnosticSeverity: {
9
9
  readonly Hint: 4;
10
10
  };
11
11
  export type DiagnosticSeverity = (typeof DiagnosticSeverity)[keyof typeof DiagnosticSeverity];
12
+ /** Matches LSP DiagnosticTag values exactly.
13
+ * https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnosticTag
14
+ *
15
+ * Declared whole rather than trimmed to what Telo emits today, for the reason
16
+ * the severity ladder above is: it is someone else's closed vocabulary, and a
17
+ * partial copy of one is what drifts. `Unnecessary` (rendered faded) has an
18
+ * obvious future consumer in the unused-declaration checks. */
19
+ export declare const DiagnosticTag: {
20
+ readonly Unnecessary: 1;
21
+ readonly Deprecated: 2;
22
+ };
23
+ export type DiagnosticTag = (typeof DiagnosticTag)[keyof typeof DiagnosticTag];
12
24
  /** Default entry-point filename when a directory is given instead of a file. */
13
25
  export declare const DEFAULT_MANIFEST_FILENAME = "telo.yaml";
14
26
  export interface Position {
@@ -65,6 +77,11 @@ export interface AnalysisDiagnostic {
65
77
  /** e.g. "telo-analyzer" */
66
78
  source?: string;
67
79
  message: string;
80
+ /** What KIND of thing this is, orthogonal to how loudly it asks to be dealt
81
+ * with. A deprecation is warning-grade *and* a deprecation; severity alone
82
+ * can only say the first, which is why an editor renders a deprecated symbol
83
+ * struck through rather than merely yellow. */
84
+ tags?: DiagnosticTag[];
68
85
  /** Telo-specific extras such as { resource: { kind, name }, path } */
69
86
  data?: unknown;
70
87
  }
@@ -130,10 +147,10 @@ export interface AnalysisOptions {
130
147
  /** Imported libraries' FULL document sets, for the zone stage's per-library
131
148
  * export derivation — the flattened analysis view forwards only each
132
149
  * library's export surface, never its internal dispatch chain. Collected
133
- * from a LoadedGraph via `collectZoneModuleDocuments`. Omitting it skips
150
+ * from a LoadedGraph via `collectModuleDocuments`. Omitting it skips
134
151
  * the derivation (the under-approximating direction — the runtime check
135
152
  * remains the enforcement). */
136
- moduleDocuments?: ZoneModuleDocuments[];
153
+ moduleDocuments?: ModuleDocuments[];
137
154
  /** When true, `analyze()` runs the state-mutating setup (module identity /
138
155
  * alias / definition registration plus `normalizeInlineResources`) but
139
156
  * skips every diagnostic-producing pass — per-resource validation, the
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js CHANGED
@@ -6,6 +6,17 @@ export const DiagnosticSeverity = {
6
6
  Information: 3,
7
7
  Hint: 4,
8
8
  };
9
+ /** Matches LSP DiagnosticTag values exactly.
10
+ * https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnosticTag
11
+ *
12
+ * Declared whole rather than trimmed to what Telo emits today, for the reason
13
+ * the severity ladder above is: it is someone else's closed vocabulary, and a
14
+ * partial copy of one is what drifts. `Unnecessary` (rendered faded) has an
15
+ * obvious future consumer in the unused-declaration checks. */
16
+ export const DiagnosticTag = {
17
+ Unnecessary: 1,
18
+ Deprecated: 2,
19
+ };
9
20
  /** Default entry-point filename when a directory is given instead of a file. */
10
21
  export const DEFAULT_MANIFEST_FILENAME = "telo.yaml";
11
22
  /** Single reader for a diagnostic's fix, so no consumer re-derives the shape
@@ -1,5 +1,5 @@
1
1
  import type { ResourceManifest } from "@telorun/sdk";
2
- import type { AliasResolver } from "./alias-resolver.js";
2
+ import { type AliasResolver, type ModuleScopes } from "./alias-resolver.js";
3
3
  import type { CallGraph } from "./call-graph.js";
4
4
  import type { DefinitionRegistry } from "./definition-registry.js";
5
5
  import { type AnalysisDiagnostic } from "./types.js";
@@ -27,5 +27,5 @@ import { type AnalysisDiagnostic } from "./types.js";
27
27
  *
28
28
  * Browser-safe.
29
29
  */
30
- export declare function validateIdentifierNames(manifests: ResourceManifest[], registry: DefinitionRegistry, aliases: AliasResolver, rootModules: Set<string>, graph: CallGraph): AnalysisDiagnostic[];
30
+ export declare function validateIdentifierNames(manifests: ResourceManifest[], registry: DefinitionRegistry, aliases: AliasResolver, rootModules: Set<string>, graph: CallGraph, scopes: ModuleScopes): AnalysisDiagnostic[];
31
31
  //# sourceMappingURL=validate-identifier-names.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate-identifier-names.d.ts","sourceRoot":"","sources":["../src/validate-identifier-names.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAQnE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIrD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,EACxB,KAAK,EAAE,SAAS,GACf,kBAAkB,EAAE,CAwEtB"}
1
+ {"version":3,"file":"validate-identifier-names.d.ts","sourceRoot":"","sources":["../src/validate-identifier-names.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AASnE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIrD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,EACxB,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,YAAY,GACnB,kBAAkB,EAAE,CAyEtB"}
@@ -1,3 +1,5 @@
1
+ import { moduleScopedDefResolver, } from "./alias-resolver.js";
2
+ import { inheritedCapability } from "./extends-resolution.js";
1
3
  import { TYPE_LEVEL_DOC_KINDS, checkName, } from "./identifier-name.js";
2
4
  import { isInjectedDeclaration } from "./resource-input.js";
3
5
  const SOURCE = "telo-analyzer";
@@ -25,8 +27,9 @@ const SOURCE = "telo-analyzer";
25
27
  *
26
28
  * Browser-safe.
27
29
  */
28
- export function validateIdentifierNames(manifests, registry, aliases, rootModules, graph) {
30
+ export function validateIdentifierNames(manifests, registry, aliases, rootModules, graph, scopes) {
29
31
  const out = [];
32
+ const resolveDef = moduleScopedDefResolver(registry, aliases, scopes);
30
33
  for (const manifest of manifests) {
31
34
  const metadata = manifest.metadata;
32
35
  const name = typeof metadata?.name === "string" ? metadata.name : undefined;
@@ -45,7 +48,7 @@ export function validateIdentifierNames(manifests, registry, aliases, rootModule
45
48
  const ownModule = metadata?.module;
46
49
  if (ownModule && !rootModules.has(ownModule))
47
50
  continue;
48
- const level = levelFor(manifest, registry, aliases);
51
+ const level = levelFor(manifest, resolveDef, ownModule);
49
52
  push(out, checkName(name, level, surfaceFor(manifest.kind)), {
50
53
  kind: manifest.kind,
51
54
  name,
@@ -106,17 +109,29 @@ export function validateIdentifierNames(manifests, registry, aliases, rootModule
106
109
  * a resource. Capability-driven rather than by kind name, so no resource kind
107
110
  * is hardcoded here.
108
111
  *
112
+ * **The capability is the INHERITED one**, not the leaf declaration. Capability
113
+ * is inherited and immutable along `extends` — a kind omits it to take its
114
+ * ancestor's — so reading the leaf answers `undefined` for every kind that does,
115
+ * and the fallback then calls a type a value. That is not hypothetical: it is
116
+ * exactly `Type.JsonSchema`, a pure alias of the built-in (`extends:
117
+ * Telo.JsonSchema`, no `capability:` of its own), so a shape declared through
118
+ * the deprecated spelling was reported as miscased while the identical
119
+ * declaration written as `kind: Telo.JsonSchema` was not. Renaming on that
120
+ * report is worse than the warning: `extends:` between two named shapes is not a
121
+ * reference slot, so the inheritance edge does not move with the name.
122
+ *
109
123
  * An unresolvable kind falls back to value level — the honest default, since
110
124
  * `UNDEFINED_KIND` already reports the real problem and guessing type level
111
125
  * would stack a case error on top of it.
112
126
  */
113
- function levelFor(manifest, registry, aliases) {
127
+ function levelFor(manifest, resolveDef, ownModule) {
114
128
  if (TYPE_LEVEL_DOC_KINDS.has(manifest.kind))
115
129
  return "type";
116
- // The root resolver is the right one unconditionally: every manifest
117
- // reaching here belongs to a root module, the others having been skipped.
118
- const canonical = aliases.resolveKind(manifest.kind) ?? manifest.kind;
119
- return registry.resolve(canonical)?.capability === "Telo.Type" ? "type" : "value";
130
+ // The top-level lookup is in the module that WROTE the `kind:` — a root one,
131
+ // the others having been skipped above while the chain walk re-scopes at
132
+ // every hop, since an `extends` alias belongs to the file declaring it.
133
+ const def = resolveDef.in(manifest.kind, ownModule);
134
+ return inheritedCapability(def, resolveDef) === "Telo.Type" ? "type" : "value";
120
135
  }
121
136
  /** The noun phrase a diagnostic uses as its subject. */
122
137
  function surfaceFor(kind) {
@@ -18,6 +18,11 @@ import { type AnalysisDiagnostic } from "./types.js";
18
18
  * whose input contract is now `inputType:`.
19
19
  * - CONTRACT_TYPE_NOT_FOUND: a contract names a type that is not declared in
20
20
  * scope, so every call through it would fail at dispatch.
21
+ * - CONTRACT_NOT_SUBSTITUTABLE: a definition replaces an ancestor's contract
22
+ * with a shape that cannot stand in for it. The one check nothing else makes:
23
+ * contracts resolve to the nearest declaration in BOTH halves, so a child that
24
+ * declares its own is compared against its abstract by neither the analyzer
25
+ * nor dispatch.
21
26
  *
22
27
  * Deliberately NOT diagnosed: an input that is neither `required:` nor
23
28
  * defaulted. It is indistinguishable from a genuinely optional one — `Ai.Text`
@@ -1 +1 @@
1
- {"version":3,"file":"validate-invocation-contract.d.ts","sourceRoot":"","sources":["../src/validate-invocation-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AASnE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIzE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,EACtB,eAAe,GAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAa,GACtD,kBAAkB,EAAE,CA4CtB"}
1
+ {"version":3,"file":"validate-invocation-contract.d.ts","sourceRoot":"","sources":["../src/validate-invocation-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAanE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,EACtB,eAAe,GAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAa,GACtD,kBAAkB,EAAE,CA4CtB"}
@@ -1,5 +1,8 @@
1
- import { effectiveContractField, mappingFieldFor, needsContractMapping, } from "./extends-resolution.js";
1
+ import { ancestorChain, effectiveContractField, mappingFieldFor, needsContractMapping, } from "./extends-resolution.js";
2
+ import { resolveTypeFieldToSchema } from "./validate-cel-context.js";
3
+ import { moduleAliasScope } from "./module-alias-scope.js";
2
4
  import { buildReferenceFieldMap, isRefEntry } from "./reference-field-map.js";
5
+ import { checkSchemaCompatibility } from "./schema-compat.js";
3
6
  import { DiagnosticSeverity } from "./types.js";
4
7
  const SOURCE = "telo-analyzer";
5
8
  /**
@@ -18,6 +21,11 @@ const SOURCE = "telo-analyzer";
18
21
  * whose input contract is now `inputType:`.
19
22
  * - CONTRACT_TYPE_NOT_FOUND: a contract names a type that is not declared in
20
23
  * scope, so every call through it would fail at dispatch.
24
+ * - CONTRACT_NOT_SUBSTITUTABLE: a definition replaces an ancestor's contract
25
+ * with a shape that cannot stand in for it. The one check nothing else makes:
26
+ * contracts resolve to the nearest declaration in BOTH halves, so a child that
27
+ * declares its own is compared against its abstract by neither the analyzer
28
+ * nor dispatch.
21
29
  *
22
30
  * Deliberately NOT diagnosed: an input that is neither `required:` nor
23
31
  * defaulted. It is indistinguishable from a genuinely optional one — `Ai.Text`
@@ -29,8 +37,7 @@ const SOURCE = "telo-analyzer";
29
37
  export function validateInvocationContract(manifests, registry, aliases, aliasesByModule = new Map()) {
30
38
  const diagnostics = [];
31
39
  const resolveDef = (kind, from) => {
32
- const module = from?.metadata?.module;
33
- const scope = (module ? aliasesByModule.get(module) : undefined) ?? aliases;
40
+ const scope = moduleAliasScope(from?.metadata, aliases, aliasesByModule);
34
41
  return registry.resolve(kind) ?? registry.resolve(scope.resolveKind(kind) ?? kind);
35
42
  };
36
43
  // A published dependency's declarations are not the consumer's to fix.
@@ -58,6 +65,7 @@ export function validateInvocationContract(manifests, registry, aliases, aliases
58
65
  if (m.kind === "Telo.Definition" || m.kind === "Telo.Abstract") {
59
66
  checkMappingRequired(m, resource, filePath, resolveDef, diagnostics);
60
67
  checkContractResolves(m, md, manifests, resource, filePath, diagnostics);
68
+ checkAncestorSubstitutability(m, md, manifests, resource, filePath, resolveDef, diagnostics);
61
69
  continue;
62
70
  }
63
71
  // A RESOURCE (an instance of some kind) — a leftover `inputs:` map is only
@@ -318,6 +326,109 @@ function namedTypeReference(value) {
318
326
  return undefined;
319
327
  return typeof ref.name === "string" ? ref.name : undefined;
320
328
  }
329
+ /**
330
+ * A REPLACING CONTRACT MUST STILL STAND IN FOR THE ONE IT REPLACES.
331
+ *
332
+ * Contracts resolve to the NEAREST declaration and never merge, which is right —
333
+ * a call signature is not additive, and a backend narrowing `status` to the
334
+ * states it actually has could not express that through a merge. But the
335
+ * consequence is that an abstract's contract binds only the children that
336
+ * declare none of their own: a child that declares one is checked against
337
+ * nothing, statically or at dispatch, since `resolveBoundContract` stops at the
338
+ * same nearest declaration. So an abstract could state a floor every
339
+ * implementation must answer with (`Durable.Run`'s `runId` / `status`, the
340
+ * identity every later question about a run is asked by) and have that floor hold
341
+ * for exactly the implementations that declared nothing — while the real ones,
342
+ * which all declare their own, escaped it. A slot typed by the abstract would
343
+ * then be typed by a promise nothing kept.
344
+ *
345
+ * The rule is substitutability, and its direction differs per contract because
346
+ * one is produced and the other consumed:
347
+ *
348
+ * - `outputType` is COVARIANT — a consumer written against the ancestor reads
349
+ * the ancestor's shape, so the child's output must be acceptable where the
350
+ * ancestor's is declared. Dropping a required property is what breaks it.
351
+ * - `inputType` is CONTRAVARIANT — a caller written against the ancestor sends
352
+ * the ancestor's shape, so the ancestor's input must be acceptable where the
353
+ * child's is declared. Requiring an input the ancestor never mentions is what
354
+ * breaks it: no such caller could satisfy it.
355
+ *
356
+ * **Only an ABSTRACT ancestor's contract is a contract**, and that narrowing is a
357
+ * decision rather than an oversight. Extending a CONCRETE kind is how a friendlier
358
+ * schema is put over an existing controller — `base:` reshapes its config and
359
+ * `inputs:` / `result:` translate its call signature — so a child there is
360
+ * SUPPOSED to present different inputs, and demanding substitutability would
361
+ * reject the pattern the standard library and every custom-kind example are built
362
+ * on. An abstract has no implementation to reshape: extending one is a claim to
363
+ * BE the thing, its contract is written for implementors, and a slot typed by it
364
+ * is polymorphic by construction — which is exactly where an unkept promise has
365
+ * nowhere to be caught.
366
+ *
367
+ * A direction the child BRIDGES (`inputs:` for inputs, `result:` for outputs) is
368
+ * skipped for the same reason one hop down: the mapping is the author saying the
369
+ * shapes differ deliberately and are translated.
370
+ *
371
+ * The comparison is {@link checkSchemaCompatibility}, which reports only DEFINITE
372
+ * mismatches — a union, an absent `type`, an undeclared argument all read as
373
+ * compatible — so narrowing a value's type, adding an optional property or
374
+ * restricting an enum stays legal, which is the whole point of letting a child
375
+ * replace the contract at all.
376
+ */
377
+ function checkAncestorSubstitutability(m, md, manifests, resource, filePath, resolveDef, diagnostics) {
378
+ const def = m;
379
+ for (const direction of ["inputType", "outputType"]) {
380
+ const own = md[direction];
381
+ if (own === undefined || own === null)
382
+ continue;
383
+ // A declared bridge says the shapes differ on purpose and are translated.
384
+ if (md[mappingFieldFor(direction)] != null)
385
+ continue;
386
+ // The nearest ANCESTOR that declares it — the contract this one replaces.
387
+ // Walking past self is the whole question: `contractDeclarer` would answer
388
+ // "this one", which is what nothing checks.
389
+ const ancestor = ancestorChain(def, resolveDef).find((a) => {
390
+ const inherited = a[direction];
391
+ return inherited !== undefined && inherited !== null;
392
+ });
393
+ if (!ancestor || ancestor.kind !== "Telo.Abstract")
394
+ continue;
395
+ const inherited = ancestor[direction];
396
+ // The WHOLE manifest set, which is what `analyzerContractScope`'s
397
+ // `typeManifestsFor` hands `resolveContract` — so this resolves a named type
398
+ // exactly as the resolver the kernel binds with does. Filtering to the
399
+ // declaring module looked more careful and was strictly worse: a contract
400
+ // naming a shape from a shared module resolved to nothing, and an
401
+ // unresolvable side is skipped, so the check silently switched itself off for
402
+ // precisely the libraries that factor their shapes out. Nothing else caught
403
+ // it either — `CONTRACT_TYPE_NOT_FOUND` finds the type through its own global
404
+ // fallback, so such a kind passed `telo check` with no diagnostic at all.
405
+ const ownSchema = resolveTypeFieldToSchema(own, manifests);
406
+ const ancestorSchema = resolveTypeFieldToSchema(inherited, manifests);
407
+ // An unresolvable side says nothing about compatibility; CONTRACT_TYPE_NOT_FOUND
408
+ // is what reports a contract that names a type nothing declares.
409
+ if (!ownSchema || !ancestorSchema)
410
+ continue;
411
+ const { compatible, issues } = direction === "outputType"
412
+ ? checkSchemaCompatibility(ownSchema, ancestorSchema)
413
+ : checkSchemaCompatibility(ancestorSchema, ownSchema);
414
+ if (compatible)
415
+ continue;
416
+ const ancestorName = `${ancestor.metadata?.module ?? ""}.${ancestor.metadata?.name ?? "?"}`.replace(/^\./, "");
417
+ const why = direction === "outputType"
418
+ ? `every caller that holds this through '${ancestorName}' reads the shape that kind declares`
419
+ : `a caller that holds this through '${ancestorName}' sends the shape that kind declares`;
420
+ diagnostics.push({
421
+ severity: DiagnosticSeverity.Error,
422
+ code: "CONTRACT_NOT_SUBSTITUTABLE",
423
+ source: SOURCE,
424
+ message: `${m.kind}/${resource.name}: \`${direction}\` replaces the one declared by '${ancestorName}' ` +
425
+ `with a shape that cannot stand in for it — ${issues.join("; ")}. Contracts replace rather ` +
426
+ `than merge, so nothing re-checks this at dispatch: ${why}. Restate the fields ` +
427
+ `'${ancestorName}' declares, or drop \`${direction}\` to inherit the contract unchanged.`,
428
+ data: { resource, filePath, path: direction },
429
+ });
430
+ }
431
+ }
321
432
  /** A child that inherits its controller and REPLACES a contract must bridge it:
322
433
  * contracts resolve to the nearest declaration and never merge, so the
323
434
  * inherited controller only understands its own shape. Without the mapping the
@@ -1 +1 @@
1
- {"version":3,"file":"validate-logging.d.ts","sourceRoot":"","sources":["../src/validate-logging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIzE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,EACtB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAC3C,kBAAkB,EAAE,CAqBtB"}
1
+ {"version":3,"file":"validate-logging.d.ts","sourceRoot":"","sources":["../src/validate-logging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAKzE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,EACtB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAC3C,kBAAkB,EAAE,CAqBtB"}
@@ -1,5 +1,6 @@
1
1
  import { parseRedactionPath, RedactionPathError } from "./redaction-path.js";
2
2
  import { DiagnosticSeverity } from "./types.js";
3
+ import { moduleAliasScope } from "./module-alias-scope.js";
3
4
  const SOURCE = "telo-analyzer";
4
5
  /**
5
6
  * Static validation of the `logging:` block — `kernel/specs/logging.md` §14.1
@@ -106,8 +107,7 @@ function isSinkKind(manifest, registry, aliases, aliasesByModule) {
106
107
  return false;
107
108
  if (manifest.kind === "Telo.ConsoleSink" || manifest.kind === "Telo.FileSink")
108
109
  return true;
109
- const ownModule = manifest.metadata?.module;
110
- const resolver = (ownModule ? aliasesByModule?.get(ownModule) : undefined) ?? aliases;
110
+ const resolver = moduleAliasScope(manifest.metadata, aliases, aliasesByModule);
111
111
  const canonical = resolver.resolveKind(manifest.kind) ?? manifest.kind;
112
112
  return registry.resolve(canonical)?.capability === "Telo.Sink";
113
113
  }
@@ -31,7 +31,7 @@ import type { AliasResolver } from "./alias-resolver.js";
31
31
  import { type CallGraph } from "./call-graph.js";
32
32
  import type { DefinitionRegistry } from "./definition-registry.js";
33
33
  export interface RefSlotIssue {
34
- code: "X_TELO_REF_INVALID_USE" | "X_TELO_REF_MISSING_USE" | "X_TELO_REF_MISSING_KIND" | "X_TELO_REF_USE_CONFLICT" | "X_TELO_REF_DYNAMIC_SELECTOR";
34
+ code: "X_TELO_REF_INVALID_USE" | "X_TELO_REF_MISSING_USE" | "X_TELO_REF_MISSING_KIND" | "X_TELO_REF_USE_CONFLICT" | "X_TELO_REF_DYNAMIC_SELECTOR" | "X_TELO_REF_UNKNOWN_KEY" | "X_TELO_REF_INVALID_THROWS_THROUGH";
35
35
  /** The definition (schema issues) or resource (selector issues) at fault. */
36
36
  manifest: ResourceManifest;
37
37
  /** Schema path of the slot (schema issues) or concrete value path of the
@@ -1 +1 @@
1
- {"version":3,"file":"validate-ref-slots.d.ts","sourceRoot":"","sources":["../src/validate-ref-slots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,MAAM,WAAW,YAAY;IAC3B,IAAI,EACA,wBAAwB,GACxB,wBAAwB,GACxB,yBAAyB,GACzB,yBAAyB,GACzB,6BAA6B,CAAC;IAClC,6EAA6E;IAC7E,QAAQ,EAAE,gBAAgB,CAAC;IAC3B;qDACiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAuJD,iEAAiE;AACjE,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,gBAAgB,GAAG,YAAY,EAAE,CA2CxF;AAED;;iFAEiF;AACjF,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,gBAAgB,EAAE,EAChC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,CAAC,EAAE,aAAa,EACvB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EAC5C,KAAK,CAAC,EAAE,SAAS,GAChB,YAAY,EAAE,CA0BhB"}
1
+ {"version":3,"file":"validate-ref-slots.d.ts","sourceRoot":"","sources":["../src/validate-ref-slots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,MAAM,WAAW,YAAY;IAC3B,IAAI,EACA,wBAAwB,GACxB,wBAAwB,GACxB,yBAAyB,GACzB,yBAAyB,GACzB,6BAA6B,GAC7B,wBAAwB,GACxB,mCAAmC,CAAC;IACxC,6EAA6E;IAC7E,QAAQ,EAAE,gBAAgB,CAAC;IAC3B;qDACiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AA6LD,iEAAiE;AACjE,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,gBAAgB,GAAG,YAAY,EAAE,CA2CxF;AAED;;iFAEiF;AACjF,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,gBAAgB,EAAE,EAChC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,CAAC,EAAE,aAAa,EACvB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EAC5C,KAAK,CAAC,EAAE,SAAS,GAChB,YAAY,EAAE,CA0BhB"}
@@ -83,8 +83,42 @@ function checkAnnotation(annotation, manifest, path, issues) {
83
83
  }
84
84
  }
85
85
  }
86
+ // `throwsThrough` is read as `=== true`, so anything else is silently absent —
87
+ // and absent means the declaring resource's catch scope stops enclosing what
88
+ // it holds, so every route under it starts reporting UNCOVERED_THROW_CODE with
89
+ // nothing naming the cause. The same failure `X_TELO_REF_INVALID_USE` exists
90
+ // to prevent, one key over.
91
+ if (obj.throwsThrough !== undefined && typeof obj.throwsThrough !== "boolean") {
92
+ issues.push({
93
+ code: "X_TELO_REF_INVALID_THROWS_THROUGH",
94
+ manifest,
95
+ path,
96
+ message: `x-telo-ref at '${path}' declares 'throwsThrough: ${JSON.stringify(obj.throwsThrough)}', ` +
97
+ `which is not a boolean. Only 'true' declares that throws from this slot's target ` +
98
+ `surface through the declaring resource; anything else reads as absent, which ` +
99
+ `silently stops its catch list from enclosing what it holds.`,
100
+ });
101
+ }
102
+ // Closed, for the reason the token sets are: a misspelled key is indexed by
103
+ // nothing and read by nothing, so it validates, ships, and does exactly what
104
+ // omitting it would.
105
+ for (const key of Object.keys(obj)) {
106
+ if (REF_ANNOTATION_KEYS.has(key))
107
+ continue;
108
+ issues.push({
109
+ code: "X_TELO_REF_UNKNOWN_KEY",
110
+ manifest,
111
+ path,
112
+ message: `x-telo-ref at '${path}' declares unrecognized key '${key}'. Known keys: ` +
113
+ `${[...REF_ANNOTATION_KEYS].sort().join(", ")}. An unrecognized key is read by nothing, ` +
114
+ `so it has exactly the effect of leaving it out.`,
115
+ });
116
+ }
86
117
  return declaredUses(use);
87
118
  }
119
+ /** Every key the structured `x-telo-ref` form accepts — the write side of
120
+ * `readRefSlot`'s read side. Adding one belongs in both. */
121
+ const REF_ANNOTATION_KEYS = new Set(["kind", "use", "inputs", "throwsThrough"]);
88
122
  /** True when a node is a reference slot: it carries `x-telo-ref` directly or on
89
123
  * an `anyOf`/`oneOf` branch. */
90
124
  function carriesRefAnnotation(obj) {
@@ -11,12 +11,23 @@ import type { DefinitionRegistry } from "./definition-registry.js";
11
11
  *
12
12
  * A value satisfies the slot when it transitively extends the target kind, or —
13
13
  * for a CONCRETE target — IS that kind; `getByExtends` is the same transitive
14
- * subtype index for both, and an abstract is satisfied only by an implementer,
15
- * never by the abstract itself (which is non-instantiable). Accepts a constraint
16
- * that resolves to nothing, and an abstract with no loaded implementations:
17
- * partial context, where a rejection would be a guess.
14
+ * subtype index for both. Accepts a constraint that resolves to nothing, and an
15
+ * abstract with no loaded implementations: partial context, where a rejection
16
+ * would be a guess.
17
+ *
18
+ * An abstract is satisfied only by an implementer, never by the abstract itself,
19
+ * because a resource declared `kind: <some abstract>` is refused at `create()`
20
+ * and reported as `ABSTRACT_KIND_INSTANTIATED` at its declaration — so accepting
21
+ * it here would leave the reference sites silent about a manifest that cannot
22
+ * run. `isDeclaration` is the ONE exception and it is not an instance: a
23
+ * library's `resources:` entry is constrained by kind alone, so its kind-only
24
+ * stand-in routinely IS an abstract (`connection: {kind: Sql.Connection}`), and
25
+ * every use of that name inside the library is a reference to it.
18
26
  */
19
- export declare function kindSatisfies(resolved: string, targetKind: string, registry: DefinitionRegistry): boolean;
27
+ export declare function kindSatisfies(resolved: string, targetKind: string, registry: DefinitionRegistry,
28
+ /** The referent is a kind-only stand-in for a `resources:` entry rather than a
29
+ * resource anything instantiates, so identity satisfies an abstract slot. */
30
+ isDeclaration?: boolean): boolean;
20
31
  /**
21
32
  * Phase 3 — Reference validation.
22
33
  *
@@ -1 +1 @@
1
- {"version":3,"file":"validate-references.d.ts","sourceRoot":"","sources":["../src/validate-references.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAarD,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAE/F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAInE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,kBAAkB,GAC3B,OAAO,CAwBT;AA8DD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,EAAE,eAAe,GACvB,kBAAkB,EAAE,CA2gBtB"}
1
+ {"version":3,"file":"validate-references.d.ts","sourceRoot":"","sources":["../src/validate-references.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAarD,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAE/F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAMnE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,kBAAkB;AAC5B;8EAC8E;AAC9E,aAAa,UAAQ,GACpB,OAAO,CAwBT;AAgED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,EAAE,eAAe,GACvB,kBAAkB,EAAE,CAwjBtB"}