@telorun/analyzer 0.72.0 → 0.74.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 (208) hide show
  1. package/dist/analyzer.d.ts.map +1 -1
  2. package/dist/analyzer.js +76 -20
  3. package/dist/artifact-axes.d.ts +14 -0
  4. package/dist/artifact-axes.d.ts.map +1 -0
  5. package/dist/artifact-axes.js +12 -0
  6. package/dist/artifact-layer-index.d.ts +2 -2
  7. package/dist/artifact-layer-index.d.ts.map +1 -1
  8. package/dist/artifact-layer-index.js +9 -4
  9. package/dist/artifact-selector.d.ts +47 -21
  10. package/dist/artifact-selector.d.ts.map +1 -1
  11. package/dist/artifact-selector.js +85 -16
  12. package/dist/builtins.d.ts.map +1 -1
  13. package/dist/builtins.js +144 -113
  14. package/dist/call-graph.d.ts +12 -1
  15. package/dist/call-graph.d.ts.map +1 -1
  16. package/dist/call-graph.js +22 -0
  17. package/dist/catch-scope.js +1 -1
  18. package/dist/cel-scope-query.d.ts.map +1 -1
  19. package/dist/cel-scope-query.js +32 -11
  20. package/dist/cel-scope.d.ts.map +1 -1
  21. package/dist/cel-scope.js +1 -0
  22. package/dist/eval-paths.d.ts +36 -5
  23. package/dist/eval-paths.d.ts.map +1 -1
  24. package/dist/eval-paths.js +47 -6
  25. package/dist/extends-resolution.d.ts +12 -0
  26. package/dist/extends-resolution.d.ts.map +1 -1
  27. package/dist/extends-resolution.js +23 -0
  28. package/dist/forwarded-declaration.d.ts +26 -0
  29. package/dist/forwarded-declaration.d.ts.map +1 -0
  30. package/dist/forwarded-declaration.js +31 -0
  31. package/dist/index.d.ts +10 -4
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +5 -2
  34. package/dist/kernel-globals.d.ts.map +1 -1
  35. package/dist/kernel-globals.js +21 -5
  36. package/dist/module-alias-scope.d.ts +11 -0
  37. package/dist/module-alias-scope.d.ts.map +1 -1
  38. package/dist/module-alias-scope.js +10 -0
  39. package/dist/module-file-claims.d.ts +17 -1
  40. package/dist/module-file-claims.d.ts.map +1 -1
  41. package/dist/module-file-claims.js +38 -3
  42. package/dist/module-named-files.d.ts +72 -0
  43. package/dist/module-named-files.d.ts.map +1 -0
  44. package/dist/module-named-files.js +115 -0
  45. package/dist/native-entries.d.ts +83 -0
  46. package/dist/native-entries.d.ts.map +1 -0
  47. package/dist/native-entries.js +169 -0
  48. package/dist/nearest-name.d.ts +22 -0
  49. package/dist/nearest-name.d.ts.map +1 -0
  50. package/dist/nearest-name.js +43 -0
  51. package/dist/normalize-inline-resources.d.ts +41 -13
  52. package/dist/normalize-inline-resources.d.ts.map +1 -1
  53. package/dist/normalize-inline-resources.js +236 -54
  54. package/dist/reference-field-map.d.ts +59 -1
  55. package/dist/reference-field-map.d.ts.map +1 -1
  56. package/dist/reference-field-map.js +200 -34
  57. package/dist/release/destinations.d.ts +59 -0
  58. package/dist/release/destinations.d.ts.map +1 -0
  59. package/dist/release/destinations.js +75 -0
  60. package/dist/release/index.d.ts +6 -2
  61. package/dist/release/index.d.ts.map +1 -1
  62. package/dist/release/index.js +3 -1
  63. package/dist/release/ledger.d.ts +20 -11
  64. package/dist/release/ledger.d.ts.map +1 -1
  65. package/dist/release/ledger.js +43 -14
  66. package/dist/release/payload-digest.d.ts +2 -1
  67. package/dist/release/payload-digest.d.ts.map +1 -1
  68. package/dist/release/payload-digest.js +2 -1
  69. package/dist/release/release-plan.d.ts +3 -2
  70. package/dist/release/release-plan.d.ts.map +1 -1
  71. package/dist/release/release-plan.js +12 -19
  72. package/dist/release/workspace-config.d.ts +114 -34
  73. package/dist/release/workspace-config.d.ts.map +1 -1
  74. package/dist/release/workspace-config.js +322 -38
  75. package/dist/release/workspace-schema.d.ts +41 -0
  76. package/dist/release/workspace-schema.d.ts.map +1 -0
  77. package/dist/release/workspace-schema.js +77 -0
  78. package/dist/resolve-ref-sentinels.d.ts.map +1 -1
  79. package/dist/resolve-ref-sentinels.js +8 -5
  80. package/dist/resolve-throws-union.d.ts +25 -4
  81. package/dist/resolve-throws-union.d.ts.map +1 -1
  82. package/dist/resolve-throws-union.js +62 -32
  83. package/dist/resolve-zone-requirements.d.ts.map +1 -1
  84. package/dist/resolve-zone-requirements.js +2 -1
  85. package/dist/rewrite-synthetic-origins.d.ts +6 -1
  86. package/dist/rewrite-synthetic-origins.d.ts.map +1 -1
  87. package/dist/rewrite-synthetic-origins.js +107 -13
  88. package/dist/schema-compat.d.ts.map +1 -1
  89. package/dist/schema-compat.js +18 -5
  90. package/dist/schema-error-report.d.ts +7 -0
  91. package/dist/schema-error-report.d.ts.map +1 -1
  92. package/dist/schema-error-report.js +9 -4
  93. package/dist/schema-walk.d.ts +47 -13
  94. package/dist/schema-walk.d.ts.map +1 -1
  95. package/dist/schema-walk.js +150 -30
  96. package/dist/scope-declarations.d.ts +59 -0
  97. package/dist/scope-declarations.d.ts.map +1 -0
  98. package/dist/scope-declarations.js +45 -0
  99. package/dist/source-entries.d.ts +119 -0
  100. package/dist/source-entries.d.ts.map +1 -0
  101. package/dist/source-entries.js +349 -0
  102. package/dist/step-bodies.d.ts +24 -0
  103. package/dist/step-bodies.d.ts.map +1 -0
  104. package/dist/step-bodies.js +28 -0
  105. package/dist/telo-version.d.ts +1 -1
  106. package/dist/telo-version.js +1 -1
  107. package/dist/template-body.d.ts +10 -0
  108. package/dist/template-body.d.ts.map +1 -1
  109. package/dist/template-body.js +25 -0
  110. package/dist/validate-cel-context.d.ts +23 -8
  111. package/dist/validate-cel-context.d.ts.map +1 -1
  112. package/dist/validate-cel-context.js +51 -18
  113. package/dist/validate-exports.d.ts +28 -0
  114. package/dist/validate-exports.d.ts.map +1 -0
  115. package/dist/validate-exports.js +146 -0
  116. package/dist/validate-extends.d.ts.map +1 -1
  117. package/dist/validate-extends.js +37 -1
  118. package/dist/validate-module-artifact.d.ts +4 -2
  119. package/dist/validate-module-artifact.d.ts.map +1 -1
  120. package/dist/validate-module-artifact.js +43 -4
  121. package/dist/validate-native-entries.d.ts +15 -0
  122. package/dist/validate-native-entries.d.ts.map +1 -0
  123. package/dist/validate-native-entries.js +103 -0
  124. package/dist/validate-observed-state.d.ts +7 -1
  125. package/dist/validate-observed-state.d.ts.map +1 -1
  126. package/dist/validate-observed-state.js +24 -6
  127. package/dist/validate-provider-coherence.d.ts +4 -8
  128. package/dist/validate-provider-coherence.d.ts.map +1 -1
  129. package/dist/validate-provider-coherence.js +12 -123
  130. package/dist/validate-reference-forms.d.ts.map +1 -1
  131. package/dist/validate-reference-forms.js +2 -2
  132. package/dist/validate-references.d.ts.map +1 -1
  133. package/dist/validate-references.js +152 -65
  134. package/dist/validate-scope-reach.d.ts +31 -0
  135. package/dist/validate-scope-reach.d.ts.map +1 -0
  136. package/dist/validate-scope-reach.js +180 -0
  137. package/dist/validate-source-entries.d.ts +16 -0
  138. package/dist/validate-source-entries.d.ts.map +1 -0
  139. package/dist/validate-source-entries.js +90 -0
  140. package/dist/validate-template-body.d.ts +36 -0
  141. package/dist/validate-template-body.d.ts.map +1 -0
  142. package/dist/validate-template-body.js +246 -0
  143. package/dist/validate-throws-coverage.d.ts.map +1 -1
  144. package/dist/validate-throws-coverage.js +21 -39
  145. package/dist/value-type-keyword.d.ts +22 -5
  146. package/dist/value-type-keyword.d.ts.map +1 -1
  147. package/dist/value-type-keyword.js +16 -7
  148. package/package.json +4 -3
  149. package/src/analyzer.ts +97 -20
  150. package/src/artifact-axes.ts +24 -0
  151. package/src/artifact-layer-index.ts +9 -6
  152. package/src/artifact-selector.ts +110 -35
  153. package/src/builtins.ts +160 -113
  154. package/src/call-graph.ts +30 -0
  155. package/src/catch-scope.ts +1 -1
  156. package/src/cel-scope-query.ts +28 -9
  157. package/src/cel-scope.ts +1 -0
  158. package/src/eval-paths.ts +53 -6
  159. package/src/extends-resolution.ts +24 -0
  160. package/src/forwarded-declaration.ts +32 -0
  161. package/src/index.ts +37 -1
  162. package/src/kernel-globals.ts +28 -5
  163. package/src/migrations/CLAUDE.md +35 -0
  164. package/src/module-alias-scope.ts +17 -0
  165. package/src/module-file-claims.ts +63 -4
  166. package/src/module-named-files.ts +162 -0
  167. package/src/native-entries.ts +227 -0
  168. package/src/nearest-name.ts +47 -0
  169. package/src/normalize-inline-resources.ts +326 -70
  170. package/src/reference-field-map.ts +257 -52
  171. package/src/release/CLAUDE.md +32 -0
  172. package/src/release/destinations.ts +105 -0
  173. package/src/release/index.ts +33 -2
  174. package/src/release/ledger.ts +51 -21
  175. package/src/release/payload-digest.ts +2 -1
  176. package/src/release/release-plan.ts +16 -26
  177. package/src/release/workspace-config.ts +483 -47
  178. package/src/release/workspace-schema.ts +99 -0
  179. package/src/resolve-ref-sentinels.ts +7 -6
  180. package/src/resolve-throws-union.ts +87 -32
  181. package/src/resolve-zone-requirements.ts +2 -1
  182. package/src/rewrite-synthetic-origins.ts +107 -16
  183. package/src/schema-compat.ts +18 -4
  184. package/src/schema-error-report.ts +16 -4
  185. package/src/schema-walk.ts +162 -34
  186. package/src/scope-declarations.ts +98 -0
  187. package/src/source-entries.ts +502 -0
  188. package/src/step-bodies.ts +55 -0
  189. package/src/telo-version.ts +1 -1
  190. package/src/template-body.ts +25 -0
  191. package/src/validate-cel-context.ts +60 -18
  192. package/src/validate-exports.ts +185 -0
  193. package/src/validate-extends.ts +43 -0
  194. package/src/validate-module-artifact.ts +46 -3
  195. package/src/validate-native-entries.ts +147 -0
  196. package/src/validate-observed-state.ts +36 -7
  197. package/src/validate-provider-coherence.ts +17 -127
  198. package/src/validate-reference-forms.ts +2 -3
  199. package/src/validate-references.ts +151 -66
  200. package/src/validate-scope-reach.ts +213 -0
  201. package/src/validate-source-entries.ts +120 -0
  202. package/src/validate-template-body.ts +274 -0
  203. package/src/validate-throws-coverage.ts +24 -31
  204. package/src/value-type-keyword.ts +35 -9
  205. package/dist/validate-template-dispatch.d.ts +0 -27
  206. package/dist/validate-template-dispatch.d.ts.map +0 -1
  207. package/dist/validate-template-dispatch.js +0 -95
  208. package/src/validate-template-dispatch.ts +0 -99
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAiBzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAgC9B,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAWvF,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AA4DjE,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAkGpB;0CAC0C;AAC1C,eAAO,MAAM,eAAe,GAAI,OAAO;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,KAAG,OACT,CAAC;AAErD;8EAC8E;AAC9E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD;AAqUD,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACtC;AA6DD,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAkFD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;gBAEzB,OAAO,GAAE,qBAA0B;IAI/C;;;;;;;;;;;;;;OAcG;IACH,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,EAC3B,eAAe,CAAC,EAAE,eAAe,GAChC,kBAAkB,EAAE;IAsiEvB,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,EAC3B,eAAe,CAAC,EAAE,eAAe,GAChC,kBAAkB,EAAE;IAMvB,SAAS,CACP,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,EAI1B,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,GACtC,gBAAgB,EAAE;IAyBrB,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,GACzB;QAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;CAsB5F"}
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAiBzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAuC9B,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAWvF,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AA4DjE,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAwGpB;0CAC0C;AAC1C,eAAO,MAAM,eAAe,GAAI,OAAO;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,KAAG,OACT,CAAC;AAErD;8EAC8E;AAC9E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD;AAqUD,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACtC;AA6DD,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAkFD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;gBAEzB,OAAO,GAAE,qBAA0B;IAI/C;;;;;;;;;;;;;;OAcG;IACH,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,EAC3B,eAAe,CAAC,EAAE,eAAe,GAChC,kBAAkB,EAAE;IAsmEvB,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,EAC3B,eAAe,CAAC,EAAE,eAAe,GAChC,kBAAkB,EAAE;IAMvB,SAAS,CACP,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,EAI1B,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,GACtC,gBAAgB,EAAE;IAyBrB,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,GACzB;QAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;CAsB5F"}
package/dist/analyzer.js CHANGED
@@ -4,12 +4,12 @@ import { AliasResolver, scopeResolverForModule, } from "./alias-resolver.js";
4
4
  import { buildCelEnvironment, isKindDocument, } from "./cel-environment.js";
5
5
  import { DefinitionRegistry } from "./definition-registry.js";
6
6
  import { readDeprecation } from "./deprecation.js";
7
- import { effectiveAuthorSchema } from "./extends-resolution.js";
7
+ import { effectiveAuthorSchema, inheritedCapability, inheritedRequiredFields, } from "./extends-resolution.js";
8
8
  import { analyzerContractScope, resolveContract, } from "./invocation-contract.js";
9
9
  import { buildCallGraph } from "./call-graph.js";
10
10
  import { buildDependencyGraph, formatCycle } from "./dependency-graph.js";
11
11
  import { buildKernelGlobalsIndex, KERNEL_GLOBAL_NAMES, } from "./kernel-globals.js";
12
- import { buildObservedStateIndex, buildObservedStateResourcesSchema, collectRunReachableNames, observedStateRead, validateObservedStateDeclarations, } from "./validate-observed-state.js";
12
+ import { buildObservedStateIndex, buildObservedStateResourcesSchema, collectRunReachableNames, forwardedResourceKey, observedStateRead, validateObservedStateDeclarations, } from "./validate-observed-state.js";
13
13
  import { computeSuggestKind } from "./kind-suggest.js";
14
14
  import { visitManifest } from "./manifest-visitor.js";
15
15
  import { declaringModuleScope, moduleAliasScope } from "./module-alias-scope.js";
@@ -47,13 +47,15 @@ import { celTypeSatisfiesJsonSchema, checkSchemaCompatibility, navigateSchemaToE
47
47
  import { collectValueSchemaIssues } from "./validate-value-schema.js";
48
48
  import { DiagnosticSeverity, DiagnosticTag, } from "./types.js";
49
49
  import { extractAccessChains, } from "./validate-cel-context.js";
50
- import { celEvalModeAt, celEvalSites, mergeCelEvalSites, NO_CEL_EVAL_SITES, } from "./eval-paths.js";
50
+ import { celEvalModeAt, celEvalSites, implicitEvalSites, mergeCelEvalSites, NO_CEL_EVAL_SITES, } from "./eval-paths.js";
51
51
  import { BINDINGS_ANNOTATION, findBindingSites, resolveBindingOrder, } from "./cel-bindings.js";
52
52
  import { CEL_RESERVED_WORDS, checkName } from "./identifier-name.js";
53
53
  import { validateIdentifierNames } from "./validate-identifier-names.js";
54
54
  import { validateExtends } from "./validate-extends.js";
55
55
  import { validateLogging } from "./validate-logging.js";
56
56
  import { validateModuleArtifact } from "./validate-module-artifact.js";
57
+ import { validateNativeEntries } from "./validate-native-entries.js";
58
+ import { validateSourceEntries } from "./validate-source-entries.js";
57
59
  import { validateIncludePlacement } from "./validate-include-placement.js";
58
60
  import { validateModuleMetadata } from "./validate-module-metadata.js";
59
61
  import { validateRequires } from "./validate-requires.js";
@@ -66,8 +68,11 @@ import { kindSatisfies, validateReferences } from "./validate-references.js";
66
68
  import { validateReferenceForms } from "./validate-reference-forms.js";
67
69
  import { isInjectedDeclaration } from "./resource-input.js";
68
70
  import { validateResourceInputs } from "./validate-resource-inputs.js";
69
- import { validateTemplateDispatch } from "./validate-template-dispatch.js";
71
+ import { validateExports } from "./validate-exports.js";
72
+ import { validateTemplateBody } from "./validate-template-body.js";
70
73
  import { validateUnusedDeclarations } from "./validate-unused-declarations.js";
74
+ import { validateScopedNameReach } from "./validate-scope-reach.js";
75
+ import { isForwardedDeclaration } from "./forwarded-declaration.js";
71
76
  import { validateThrowsCoverage } from "./validate-throws-coverage.js";
72
77
  import { readStepSlot } from "./step-slot.js";
73
78
  const SELF_PREFIX = "Self.";
@@ -276,7 +281,7 @@ function validateStepInvokeReferences(allManifests, defs, aliases) {
276
281
  const meta = r.metadata;
277
282
  if (typeof meta?.name !== "string" || REF_VALIDATION_SKIP_KINDS.has(r.kind))
278
283
  continue;
279
- if (meta.forwardedExport === true) {
284
+ if (isForwardedDeclaration(r)) {
280
285
  if (typeof meta.module === "string")
281
286
  loadedModules.add(meta.module);
282
287
  continue;
@@ -342,7 +347,7 @@ function validateStepInvokeReferences(allManifests, defs, aliases) {
342
347
  const meta = m.metadata;
343
348
  if (typeof meta?.name !== "string" ||
344
349
  REF_VALIDATION_SKIP_KINDS.has(m.kind) ||
345
- meta.forwardedExport === true)
350
+ isForwardedDeclaration(m))
346
351
  continue;
347
352
  const def = defs.resolve(aliases.resolveKind(m.kind) ?? m.kind);
348
353
  const defSchema = def?.schema;
@@ -1301,6 +1306,11 @@ export class StaticAnalyzer {
1301
1306
  // would otherwise fail on a consumer's machine — or, for a mistyped platform
1302
1307
  // axis, silently offer one platform's binary to every host.
1303
1308
  diagnostics.push(...validateModuleArtifact(allManifests));
1309
+ // The module doc's `native:` block: each rule decides whether a platform's
1310
+ // file can ever match a host, or whether two layers would write one path.
1311
+ diagnostics.push(...validateNativeEntries(allManifests, rootModules));
1312
+ // The module doc's `sources:` block: where each staged file comes from.
1313
+ diagnostics.push(...validateSourceEntries(allManifests, rootModules));
1304
1314
  // The descriptive `metadata:` surface. Nothing in the kernel branches on
1305
1315
  // these fields, which is precisely why they need a check: a mistyped one
1306
1316
  // has no runtime failure mode that would ever surface it.
@@ -1551,9 +1561,8 @@ export class StaticAnalyzer {
1551
1561
  // `kind`/CEL are authored in that module's scope (e.g. `Self.X` → that module, not the
1552
1562
  // consumer). Re-validating against the consumer's scope yields false UNDEFINED_KIND /
1553
1563
  // scope-mismatch errors, so skip — they participate here only as resolution targets.
1554
- if (m.metadata?.forwardedExport === true) {
1564
+ if (isForwardedDeclaration(m))
1555
1565
  continue;
1556
- }
1557
1566
  // A kind-only stand-in for a `resources:` entry is a DECLARATION, not an
1558
1567
  // instantiation: its kind is routinely an abstract and its configuration
1559
1568
  // is the importer's to supply, so validating it here would report a
@@ -1746,12 +1755,37 @@ export class StaticAnalyzer {
1746
1755
  // is caught here rather than on the one input that selects it.
1747
1756
  const valueSchemaIssues = collectValueSchemaIssues(m, schema, allManifests);
1748
1757
  const issues = [...ajvIssues, ...valueSchemaIssues];
1758
+ // WHY A FIELD THIS KIND EXISTS TO SUPPLY IS STILL REQUIRED OF ITS
1759
+ // CONSUMER. A child that `extends` and declares no `base:` is authored
1760
+ // against merge(parent, own), so the parent's `required` stays on the
1761
+ // CHILD's surface — and a kind written to wire that field internally
1762
+ // then demands it from the consumer anyway. The `base:` mapping is what
1763
+ // narrows (with it the surface is the child's own schema alone), and
1764
+ // nothing in "is missing required property" points there, which is what
1765
+ // turns one mistake into a three-step dead end.
1766
+ //
1767
+ // Matched against names DERIVED from the parent, never by parsing the
1768
+ // message: which fields are inherited is a fact about the definition,
1769
+ // and a check that reads a validator's prose breaks when the prose does.
1770
+ const inheritedRequired = inheritedRequiredFields(definition, (k) => defs.resolve(aliases.resolveKind(k) ?? k) ?? defs.resolve(k));
1771
+ const parentKind = definition?.extends;
1749
1772
  for (const issue of issues) {
1773
+ // Keyed on the STRUCTURED failure, never on the sentence: the field
1774
+ // names are derived from the parent, and matching them against the
1775
+ // validator's prose would break when the prose changes and mis-fire on
1776
+ // any other issue quoting the same name (an `additionalProperties`
1777
+ // rejection, an `enum` listing).
1778
+ const inherited = issue.keyword === "required" && issue.missingProperty !== undefined
1779
+ ? inheritedRequired.filter((f) => f === issue.missingProperty)
1780
+ : [];
1781
+ const hint = inherited.length > 0 && parentKind
1782
+ ? ` — ${inherited.map((f) => `'${f}'`).join(", ")} ${inherited.length > 1 ? "come" : "comes"} from '${parentKind}', which this kind extends without a 'base:' mapping, so the parent's required fields stay on this kind's author surface. Add 'base:' to set them internally; that also narrows the surface to this kind's own schema.`
1783
+ : "";
1750
1784
  diagnostics.push({
1751
1785
  severity: DiagnosticSeverity.Error,
1752
1786
  code: "SCHEMA_VIOLATION",
1753
1787
  source: SOURCE,
1754
- message: `${m.kind}/${resource.name}: ${issue.message}`,
1788
+ message: `${m.kind}/${resource.name}: ${issue.message}${hint}`,
1755
1789
  data: { resource, filePath, path: issue.path },
1756
1790
  });
1757
1791
  }
@@ -2116,8 +2150,14 @@ export class StaticAnalyzer {
2116
2150
  }
2117
2151
  // The non-eval-field check only applies to runtime resource instances:
2118
2152
  // structural / templating kinds (capability `Telo.Template`, or no
2119
- // definition) carry CEL the kernel evaluates by other rules.
2120
- const capability = e.definition?.capability;
2153
+ // definition) carry CEL the kernel evaluates by other rules. The
2154
+ // capability is INHERITED along `extends` — an inheritance kind
2155
+ // writes none of its own — and reading the declared one left the
2156
+ // rule off for every such kind, and its expressions untyped.
2157
+ const resolveDef = (k) => defs.resolve(aliases.resolveKind(k) ?? k) ?? defs.resolve(k);
2158
+ const capability = e.definition
2159
+ ? inheritedCapability(e.definition, resolveDef)
2160
+ : undefined;
2121
2161
  celRuleApplies =
2122
2162
  !!e.definition?.schema && capability !== undefined && capability !== "Telo.Template";
2123
2163
  if (celRuleApplies) {
@@ -2129,12 +2169,14 @@ export class StaticAnalyzer {
2129
2169
  // the own schema here reported `CEL_IN_NON_EVAL_FIELD` for an
2130
2170
  // expression the runtime evaluates correctly, which is the two halves
2131
2171
  // disagreeing about what the manifest means.
2132
- const ownSchema = effectiveAuthorSchema(e.definition, (k) => defs.resolve(aliases.resolveKind(k) ?? k) ?? defs.resolve(k));
2172
+ const ownSchema = effectiveAuthorSchema(e.definition, resolveDef);
2133
2173
  const capabilityDef = capability ? defs.resolve(capability) : undefined;
2134
2174
  // A `Telo.Provider`'s fields are implicitly compile-eval — the
2135
2175
  // capability abstract carries the root annotation — so its reads are
2136
- // covered here without the provider restating anything.
2137
- celSites = mergeCelEvalSites(celEvalSites(ownSchema), celEvalSites(capabilityDef?.schema));
2176
+ // covered here without the provider restating anything. A base-form
2177
+ // child's own fields are too (`implicitEvalSites`): `base:` reads
2178
+ // them once at create().
2179
+ celSites = mergeCelEvalSites(celEvalSites(ownSchema), celEvalSites(capabilityDef?.schema), implicitEvalSites(e.definition));
2138
2180
  }
2139
2181
  else {
2140
2182
  celSites = NO_CEL_EVAL_SITES;
@@ -2175,8 +2217,16 @@ export class StaticAnalyzer {
2175
2217
  continue;
2176
2218
  // An import's exported instance is indexed under `<Alias>.<name>`,
2177
2219
  // the two-level shape it publishes under, so a cross-module read
2178
- // is checked exactly like a local one.
2179
- const reported = observedState.get(read.alias ? `${read.alias}.${read.name}` : read.name);
2220
+ // is checked exactly like a local one. A bare name read inside a
2221
+ // dependency's own manifest names that dependency's resource.
2222
+ const readerModule = isForwardedDeclaration(m)
2223
+ ? m.metadata?.module
2224
+ : undefined;
2225
+ const reported = observedState.get(read.alias
2226
+ ? `${read.alias}.${read.name}`
2227
+ : readerModule !== undefined
2228
+ ? forwardedResourceKey(readerModule, read.name)
2229
+ : read.name);
2180
2230
  if (celRuleApplies && celEvalModeAt(celSites, path) === "compile") {
2181
2231
  diagnostics.push({
2182
2232
  severity: DiagnosticSeverity.Error,
@@ -2403,12 +2453,18 @@ export class StaticAnalyzer {
2403
2453
  diagnostics.push(...validateThrowsCoverage(allManifests, defs, aliases, this.celEnv, aliasesByModule, rootModules, libraryManifests));
2404
2454
  // Warn about declared variables / secrets / ports that no CEL references.
2405
2455
  diagnostics.push(...validateUnusedDeclarations(allManifests, this.celEnv));
2406
- // A `!ref` at a definition's dispatch slot must name a sibling `resources:`
2407
- // entry — the slot no reference pass reaches, so the tag would otherwise
2408
- // advertise a resolution nothing performs.
2409
- diagnostics.push(...validateTemplateDispatch(allManifests, rootModules));
2456
+ // A template body's reference surface its entry names, its dispatch slots
2457
+ // and the ref slots inside each entry — which no reference pass reaches,
2458
+ // since a `Telo.Definition` is in both skip sets.
2459
+ diagnostics.push(...validateTemplateBody(allManifests, defs, aliases, aliasesByModule, rootModules));
2460
+ // A library's export list, resolved against what it declares — otherwise a
2461
+ // listed name that exists nowhere fails in the consumer's file.
2462
+ diagnostics.push(...validateExports(allManifests, defs, aliases, rootModules));
2410
2463
  // A library's declared resource inputs, and every import that supplies them.
2411
2464
  diagnostics.push(...validateResourceInputs(allManifests, defs, aliases, rootModules, (supplied, required, isDeclaration) => kindSatisfies(supplied, required, defs, isDeclaration)));
2465
+ // An inline declaration referencing a name declared by a scope it was
2466
+ // written inside but is created outside of.
2467
+ diagnostics.push(...validateScopedNameReach(allManifests, defs, aliases, aliasesByModule, rootModules, (expr) => celAccessChains(this.celEnv, expr)));
2412
2468
  // Reroute diagnostics on synthetic (inline-extracted) resources back to
2413
2469
  // the chain root so position-index lookups land on the parent doc.
2414
2470
  return rewriteSyntheticOrigins(suppressUnreadableModuleDiagnostics(diagnostics, unreadableFiles), allManifests);
@@ -0,0 +1,14 @@
1
+ /** The selector platform axes, in canonical order. Closed as a set of axis
2
+ * names; the set of values stays open. */
3
+ export declare const PLATFORM_AXES: readonly ["os", "arch", "libc", "abi"];
4
+ export type PlatformAxis = (typeof PLATFORM_AXES)[number];
5
+ /** A form an axis value must take beyond the shared token grammar. */
6
+ export interface AxisValueForm {
7
+ readonly pattern: RegExp;
8
+ /** The form as a reader writes it, e.g. `<family>-<version>`. */
9
+ readonly form: string;
10
+ readonly examples: readonly string[];
11
+ }
12
+ /** The axes whose values carry a form of their own. */
13
+ export declare const AXIS_VALUE_FORMS: Readonly<Partial<Record<PlatformAxis, AxisValueForm>>>;
14
+ //# sourceMappingURL=artifact-axes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-axes.d.ts","sourceRoot":"","sources":["../src/artifact-axes.ts"],"names":[],"mappings":"AAEA;2CAC2C;AAC3C,eAAO,MAAM,aAAa,wCAAyC,CAAC;AAEpE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAMnF,CAAC"}
@@ -0,0 +1,12 @@
1
+ // GENERATED by scripts/generate-artifact-axes.mjs from analyzer/artifact-axes/axes.json — do not edit.
2
+ /** The selector platform axes, in canonical order. Closed as a set of axis
3
+ * names; the set of values stays open. */
4
+ export const PLATFORM_AXES = ["os", "arch", "libc", "abi"];
5
+ /** The axes whose values carry a form of their own. */
6
+ export const AXIS_VALUE_FORMS = {
7
+ abi: {
8
+ pattern: new RegExp("^[a-z][a-z0-9_]*-[0-9]+(\\.[0-9]+)*$"),
9
+ form: "<family>-<version>",
10
+ examples: ["node-137", "telo-2"],
11
+ },
12
+ };
@@ -30,7 +30,7 @@
30
30
  import { type ArtifactSelector, type LayerRole, type PlatformTarget } from "./artifact-selector.js";
31
31
  export interface ArtifactLayer {
32
32
  role: LayerRole;
33
- /** Present on the code-bearing roles (`controller`, `library`) only. */
33
+ /** Present on the selector-keyed roles (`controller`, `library`, `native`) only. */
34
34
  selector?: ArtifactSelector;
35
35
  /** OCI blob digest — addresses the layer and verifies the transfer. */
36
36
  blob: string;
@@ -48,7 +48,7 @@ export declare class LayerIndexError extends Error {
48
48
  */
49
49
  export declare function parseLayerIndex(value: unknown, describe?: string): ArtifactLayer[];
50
50
  /** The singleton layer for a role, or undefined when the artifact has none. */
51
- export declare function singletonLayer(layers: readonly ArtifactLayer[], role: Exclude<LayerRole, "controller" | "library">): ArtifactLayer | undefined;
51
+ export declare function singletonLayer(layers: readonly ArtifactLayer[], role: Exclude<LayerRole, "controller" | "library" | "native">): ArtifactLayer | undefined;
52
52
  /** The layer of one code role carrying exactly `selector`, or undefined.
53
53
  *
54
54
  * By exact key rather than by re-matching a host: the candidate being resolved
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-layer-index.d.ts","sourceRoot":"","sources":["../src/artifact-layer-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAOL,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,cAAc,EACpB,MAAM,wBAAwB,CAAC;AAQhC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,yBAAyB;gBAE1B,MAAM,EAAE,MAAM;CAI3B;AAiBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,SAAW,GAAG,aAAa,EAAE,CAmEpF;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAC5B,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,YAAY,GAAG,SAAS,CAAC,GACjD,aAAa,GAAG,SAAS,CAE3B;AAED;;;;uBAIuB;AACvB,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,YAAY,GAAG,SAAS,CAAC,EAClD,QAAQ,EAAE,gBAAgB,GACzB,aAAa,GAAG,SAAS,CAK3B;AAED;;;6BAG6B;AAC7B,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,MAAM,EAAE,cAAc,GACrB,aAAa,EAAE,CAOjB"}
1
+ {"version":3,"file":"artifact-layer-index.d.ts","sourceRoot":"","sources":["../src/artifact-layer-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAML,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,cAAc,EACpB,MAAM,wBAAwB,CAAC;AAQhC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,yBAAyB;gBAE1B,MAAM,EAAE,MAAM;CAI3B;AAiBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,SAAW,GAAG,aAAa,EAAE,CAuEpF;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAC5B,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,YAAY,GAAG,SAAS,GAAG,QAAQ,CAAC,GAC5D,aAAa,GAAG,SAAS,CAE3B;AAED;;;;uBAIuB;AACvB,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,YAAY,GAAG,SAAS,CAAC,EAClD,QAAQ,EAAE,gBAAgB,GACzB,aAAa,GAAG,SAAS,CAK3B;AAED;;;6BAG6B;AAC7B,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,MAAM,EAAE,cAAc,GACrB,aAAa,EAAE,CAOjB"}
@@ -27,7 +27,7 @@
27
27
  * Browser-safe: `telo check`, the editor and the hub validate an index through
28
28
  * this module; only the kernel fetches and extracts.
29
29
  */
30
- import { LAYER_ROLES, isLayerRole, normalizeSelector, roleCarriesSelector, selectorKey, selectorMatches, } from "./artifact-selector.js";
30
+ import { isLayerRole, normalizeSelector, roleCarriesSelector, selectorKey, selectorMatches, } from "./artifact-selector.js";
31
31
  /** OCI content digest: `sha256:` + 64 lowercase hex. */
32
32
  const BLOB_DIGEST = /^sha256:[0-9a-f]{64}$/;
33
33
  /** Telo content digest: `sha256-` + unpadded base64url of 32 bytes. */
@@ -70,9 +70,11 @@ export function parseLayerIndex(value, describe = "layers") {
70
70
  }
71
71
  const entry = raw;
72
72
  if (typeof entry.role !== "string" || entry.role === "") {
73
- throw new LayerIndexError(`${where}: role is required and must be one of ${LAYER_ROLES.map((r) => `'${r}'`).join(", ")}; ` +
73
+ throw new LayerIndexError(`${where}: role is required and must be a non-empty string; ` +
74
74
  `got ${entry.role === undefined ? "nothing" : `'${String(entry.role)}'`}.`);
75
75
  }
76
+ const blob = digest("blob", entry.blob, where);
77
+ const integrity = digest("integrity", entry.integrity, where);
76
78
  // A role this runtime does not know is SKIPPED, never rejected. Roles are
77
79
  // added over time, and a runtime that cannot name one cannot need it — while
78
80
  // throwing would make the whole manifest unreadable, so a module gaining a
@@ -88,6 +90,9 @@ export function parseLayerIndex(value, describe = "layers") {
88
90
  throw new LayerIndexError(`${where}: a ${role} layer must declare a selector.`);
89
91
  }
90
92
  selector = normalizeSelector(entry.selector, where);
93
+ // An unknown axis skips the entry as an unknown role does (spec §3.1).
94
+ if (selector === undefined)
95
+ return;
91
96
  // Scoped by role: a module's `js` controller layer and its `js` library
92
97
  // layer are different layers with the same selector, and only a collision
93
98
  // *within* one role means two layers claim one address.
@@ -110,8 +115,8 @@ export function parseLayerIndex(value, describe = "layers") {
110
115
  layers.push({
111
116
  role,
112
117
  ...(selector ? { selector } : {}),
113
- blob: digest("blob", entry.blob, where),
114
- integrity: digest("integrity", entry.integrity, where),
118
+ blob,
119
+ integrity,
115
120
  });
116
121
  });
117
122
  return layers;
@@ -3,7 +3,8 @@
3
3
  * controller candidate is chosen by, and the key a controller layer of a module
4
4
  * artifact is stored under.
5
5
  *
6
- * A selector is `format` plus the optional platform axes `os` / `arch` / `libc`.
6
+ * A selector is `format` plus the optional platform axes, whose vocabulary is
7
+ * data (`analyzer/artifact-axes/axes.json`, generated into `PLATFORM_AXES`).
7
8
  * Matching is one rule, applied per axis: an axis the selector omits accepts
8
9
  * anything, an axis it states must be equal. That is what lets a `js` controller
9
10
  * be platform-neutral and a `napi` controller be pinned to one triple, with no
@@ -24,9 +25,11 @@
24
25
  * canonical OCI/GOOS names at the kernel boundary, since these values are
25
26
  * published into OCI descriptors.
26
27
  */
27
- /** The role a layer plays in a module artifact. `controller` and `library` layers
28
- * carry a selector; `assets` and `common` are singletons and carry none. */
29
- export type LayerRole = "controller" | "library" | "assets" | "common";
28
+ import { PLATFORM_AXES, type PlatformAxis } from "./artifact-axes.js";
29
+ /** The role a layer plays in a module artifact. `controller`, `library` and
30
+ * `native` layers carry a selector; `assets` and `common` are singletons and
31
+ * carry none. */
32
+ export type LayerRole = "controller" | "library" | "native" | "assets" | "common";
30
33
  export declare const LAYER_ROLES: readonly LayerRole[];
31
34
  export declare function isLayerRole(value: unknown): value is LayerRole;
32
35
  /** The roles that hold executable code, and are therefore per format rather than
@@ -36,39 +39,41 @@ export declare function isLayerRole(value: unknown): value is LayerRole;
36
39
  * A singleton would be wrong the moment a second runtime ships. */
37
40
  export declare const CODE_LAYER_ROLES: readonly LayerRole[];
38
41
  export declare function roleCarriesSelector(role: LayerRole): boolean;
39
- /** The platform axes, in canonical order. Not a closed vocabulary of *values* —
40
- * new architectures appear without a Telo release — only of axis names. */
41
- export declare const PLATFORM_AXES: readonly ["os", "arch", "libc"];
42
- export type PlatformAxis = (typeof PLATFORM_AXES)[number];
43
- export interface ArtifactSelector {
42
+ export { PLATFORM_AXES, type PlatformAxis };
43
+ export interface ArtifactSelector extends Partial<Record<PlatformAxis, string>> {
44
44
  /** Bundled controller format: the PURL name segment (`js`, `napi`, `wasm`, …). */
45
45
  format: string;
46
- os?: string;
47
- arch?: string;
48
- libc?: string;
49
46
  }
50
47
  /** What a selector is matched against: the host the kernel runs on, or the
51
- * target `telo install --platform` is warming a cache for. An axis left
52
- * undetermined (a host whose libc cannot be detected) matches no selector that
53
- * constrains it — refusing to load is the safe direction for a native binary. */
54
- export interface PlatformTarget {
48
+ * target `telo install` is warming a cache for. An axis left undetermined (a
49
+ * host whose libc cannot be detected) matches no selector that constrains it —
50
+ * refusing to load is the safe direction for a native binary. */
51
+ export interface PlatformTarget extends Partial<Record<PlatformAxis, string>> {
55
52
  format?: string;
56
- os?: string;
57
- arch?: string;
58
- libc?: string;
59
53
  }
60
54
  export declare class ArtifactSelectorError extends Error {
61
55
  readonly code = "INVALID_ARTIFACT_SELECTOR";
62
56
  constructor(detail: string);
63
57
  }
58
+ /** Validate and normalize one selector value: the shared token grammar, plus the
59
+ * axis's own value form where the vocabulary declares one. */
60
+ export declare function normalizeAxisValue(axis: string, raw: unknown, describe: string): string;
64
61
  /**
65
62
  * Build a selector from a controller candidate's format and qualifier map.
66
63
  * Qualifier keys other than the platform axes are ignored — `path` and the
67
64
  * sibling list live in the same map and are not part of the selector.
68
65
  */
69
66
  export declare function selectorFromQualifiers(format: unknown, qualifiers: Readonly<Record<string, unknown>> | undefined, describe?: string): ArtifactSelector;
70
- /** Validate and normalize a selector read off a published layer index. */
71
- export declare function normalizeSelector(value: unknown, describe?: string): ArtifactSelector;
67
+ /**
68
+ * Validate and normalize a selector read off a published layer index.
69
+ *
70
+ * Returns undefined when the selector carries an axis this runtime does not
71
+ * know: the layer is for a newer runtime, and the caller skips it whole. The
72
+ * unknown axis is never dropped — two layers differing only in it would then
73
+ * claim one address. The known axes are still validated, since their grammar
74
+ * does not change with the axis set.
75
+ */
76
+ export declare function normalizeSelector(value: unknown, describe?: string): ArtifactSelector | undefined;
72
77
  /**
73
78
  * The canonical stable key for a selector: sorted `axis=value` pairs joined by
74
79
  * `;`. Used to group entry points into layers at publish time and to detect two
@@ -85,4 +90,25 @@ export declare function describeSelector(selector: ArtifactSelector): string;
85
90
  * not be handed a `libc=gnu` binary on the assumption it will run.
86
91
  */
87
92
  export declare function selectorMatches(selector: ArtifactSelector, target: PlatformTarget): boolean;
93
+ /**
94
+ * The axes `selector` constrains and `target` leaves undetermined, when those
95
+ * alone keep the two from matching — what a warm skips for want of a value rather
96
+ * than because the selector is for another platform. `undefined` when the
97
+ * selector matches, or differs on a determined axis.
98
+ */
99
+ export declare function undeterminedAxesBlockingMatch(selector: ArtifactSelector, target: PlatformTarget): PlatformAxis[] | undefined;
100
+ /** A selector that no host can match as its author meant it. */
101
+ export interface SelectorContradiction {
102
+ /** Suffix of the diagnostic code; each surface prefixes its own. */
103
+ readonly rule: "NAPI_ABI_FORBIDDEN" | "LIBC_OFF_LINUX";
104
+ readonly axis: PlatformAxis;
105
+ readonly detail: string;
106
+ }
107
+ /**
108
+ * The combinations of axes the grammar accepts and no host can mean: an N-API
109
+ * addon stating a runtime ABI, and a libc on an os that has none. Shared by every
110
+ * surface that authors a selector — `native:` entries, controller candidates and
111
+ * `exports.code:` entries — so each reports the same rule under its own prefix.
112
+ */
113
+ export declare function selectorContradictions(selector: ArtifactSelector): SelectorContradiction[];
88
114
  //# sourceMappingURL=artifact-selector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-selector.d.ts","sourceRoot":"","sources":["../src/artifact-selector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;6EAC6E;AAC7E,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEvE,eAAO,MAAM,WAAW,EAAE,SAAS,SAAS,EAAkD,CAAC;AAE/F,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAE9D;AAED;;;;oEAIoE;AACpE,eAAO,MAAM,gBAAgB,EAAE,SAAS,SAAS,EAA8B,CAAC;AAEhF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAE5D;AAED;4EAC4E;AAC5E,eAAO,MAAM,aAAa,iCAAkC,CAAC;AAE7D,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,MAAM,WAAW,gBAAgB;IAC/B,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;kFAGkF;AAClF,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,+BAA+B;gBAEhC,MAAM,EAAE,MAAM;CAI3B;AAsBD;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,EACf,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,EACzD,QAAQ,SAAwB,GAC/B,gBAAgB,CAUlB;AAED,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,QAAQ,SAAmB,GAC1B,gBAAgB,CAelB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAO9D;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAKnE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAQ3F"}
1
+ {"version":3,"file":"artifact-selector.d.ts","sourceRoot":"","sources":["../src/artifact-selector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAoB,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAExF;;kBAEkB;AAClB,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAElF,eAAO,MAAM,WAAW,EAAE,SAAS,SAAS,EAM3C,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAE9D;AAED;;;;oEAIoE;AACpE,eAAO,MAAM,gBAAgB,EAAE,SAAS,SAAS,EAA8B,CAAC;AAOhF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAE5D;AAED,OAAO,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,CAAC;AAE5C,MAAM,WAAW,gBAAiB,SAAQ,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC7E,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;kEAGkE;AAClE,MAAM,WAAW,cAAe,SAAQ,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,+BAA+B;gBAEhC,MAAM,EAAE,MAAM;CAI3B;AAMD;+DAC+D;AAC/D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAqBvF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,EACf,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,EACzD,QAAQ,SAAwB,GAC/B,gBAAgB,CAUlB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,QAAQ,SAAmB,GAC1B,gBAAgB,GAAG,SAAS,CAU9B;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAO9D;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAKnE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAQ3F;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,EAAE,cAAc,GACrB,YAAY,EAAE,GAAG,SAAS,CAU5B;AAED,gEAAgE;AAChE,MAAM,WAAW,qBAAqB;IACpC,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CAAC;IACvD,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,qBAAqB,EAAE,CAqB1F"}
@@ -3,7 +3,8 @@
3
3
  * controller candidate is chosen by, and the key a controller layer of a module
4
4
  * artifact is stored under.
5
5
  *
6
- * A selector is `format` plus the optional platform axes `os` / `arch` / `libc`.
6
+ * A selector is `format` plus the optional platform axes, whose vocabulary is
7
+ * data (`analyzer/artifact-axes/axes.json`, generated into `PLATFORM_AXES`).
7
8
  * Matching is one rule, applied per axis: an axis the selector omits accepts
8
9
  * anything, an axis it states must be equal. That is what lets a `js` controller
9
10
  * be platform-neutral and a `napi` controller be pinned to one triple, with no
@@ -24,7 +25,14 @@
24
25
  * canonical OCI/GOOS names at the kernel boundary, since these values are
25
26
  * published into OCI descriptors.
26
27
  */
27
- export const LAYER_ROLES = ["controller", "library", "assets", "common"];
28
+ import { AXIS_VALUE_FORMS, PLATFORM_AXES } from "./artifact-axes.js";
29
+ export const LAYER_ROLES = [
30
+ "controller",
31
+ "library",
32
+ "native",
33
+ "assets",
34
+ "common",
35
+ ];
28
36
  export function isLayerRole(value) {
29
37
  return typeof value === "string" && LAYER_ROLES.includes(value);
30
38
  }
@@ -34,12 +42,14 @@ export function isLayerRole(value) {
34
42
  * different files, and a consumer resolves the one its own runtime can import.
35
43
  * A singleton would be wrong the moment a second runtime ships. */
36
44
  export const CODE_LAYER_ROLES = ["controller", "library"];
45
+ /** Every role keyed by a selector, one layer per selector: the code roles, plus
46
+ * `native` — a platform-specific file the runtime does not import as code,
47
+ * declared in the module doc's `native:` block. */
48
+ const SELECTOR_LAYER_ROLES = [...CODE_LAYER_ROLES, "native"];
37
49
  export function roleCarriesSelector(role) {
38
- return CODE_LAYER_ROLES.includes(role);
50
+ return SELECTOR_LAYER_ROLES.includes(role);
39
51
  }
40
- /** The platform axes, in canonical order. Not a closed vocabulary of *values* —
41
- * new architectures appear without a Telo release — only of axis names. */
42
- export const PLATFORM_AXES = ["os", "arch", "libc"];
52
+ export { PLATFORM_AXES };
43
53
  export class ArtifactSelectorError extends Error {
44
54
  code = "INVALID_ARTIFACT_SELECTOR";
45
55
  constructor(detail) {
@@ -50,7 +60,9 @@ export class ArtifactSelectorError extends Error {
50
60
  /** Canonical token shape for every selector value. Lowercase, so the same
51
61
  * platform written two ways is one layer rather than two. */
52
62
  const TOKEN = /^[a-z0-9][a-z0-9_.-]*$/;
53
- function normalizeToken(axis, raw, describe) {
63
+ /** Validate and normalize one selector value: the shared token grammar, plus the
64
+ * axis's own value form where the vocabulary declares one. */
65
+ export function normalizeAxisValue(axis, raw, describe) {
54
66
  if (typeof raw !== "string") {
55
67
  throw new ArtifactSelectorError(`${describe}: ${axis} must be a string, got ${raw === null ? "null" : typeof raw}.`);
56
68
  }
@@ -59,6 +71,11 @@ function normalizeToken(axis, raw, describe) {
59
71
  throw new ArtifactSelectorError(`${describe}: ${axis} value '${raw}' is not a canonical token. ` +
60
72
  `Use lowercase letters, digits, '.', '-' or '_', starting with a letter or digit.`);
61
73
  }
74
+ const valueForm = AXIS_VALUE_FORMS[axis];
75
+ if (valueForm && !valueForm.pattern.test(value)) {
76
+ throw new ArtifactSelectorError(`${describe}: ${axis} value '${raw}' must have the form ${valueForm.form}, ` +
77
+ `e.g. ${valueForm.examples.map((e) => `'${e}'`).join(" or ")}.`);
78
+ }
62
79
  return value;
63
80
  }
64
81
  /**
@@ -68,28 +85,33 @@ function normalizeToken(axis, raw, describe) {
68
85
  */
69
86
  export function selectorFromQualifiers(format, qualifiers, describe = "controller selector") {
70
87
  const selector = {
71
- format: normalizeToken("format", format, describe),
88
+ format: normalizeAxisValue("format", format, describe),
72
89
  };
73
90
  for (const axis of PLATFORM_AXES) {
74
91
  const raw = qualifiers?.[axis];
75
92
  if (raw === undefined || raw === "")
76
93
  continue;
77
- selector[axis] = normalizeToken(axis, raw, describe);
94
+ selector[axis] = normalizeAxisValue(axis, raw, describe);
78
95
  }
79
96
  return selector;
80
97
  }
81
- /** Validate and normalize a selector read off a published layer index. */
98
+ /**
99
+ * Validate and normalize a selector read off a published layer index.
100
+ *
101
+ * Returns undefined when the selector carries an axis this runtime does not
102
+ * know: the layer is for a newer runtime, and the caller skips it whole. The
103
+ * unknown axis is never dropped — two layers differing only in it would then
104
+ * claim one address. The known axes are still validated, since their grammar
105
+ * does not change with the axis set.
106
+ */
82
107
  export function normalizeSelector(value, describe = "layer selector") {
83
108
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
84
109
  throw new ArtifactSelectorError(`${describe}: expected an object of selector axes.`);
85
110
  }
86
111
  const record = value;
87
- const unknown = Object.keys(record).filter((k) => k !== "format" && !PLATFORM_AXES.includes(k));
88
- if (unknown.length > 0) {
89
- throw new ArtifactSelectorError(`${describe}: unknown selector ${unknown.length === 1 ? "axis" : "axes"} ` +
90
- `${unknown.map((k) => `'${k}'`).join(", ")}. Known axes: format, ${PLATFORM_AXES.join(", ")}.`);
91
- }
92
- return selectorFromQualifiers(record.format, record, describe);
112
+ const selector = selectorFromQualifiers(record.format, record, describe);
113
+ const carriesUnknownAxis = Object.keys(record).some((k) => k !== "format" && !PLATFORM_AXES.includes(k));
114
+ return carriesUnknownAxis ? undefined : selector;
93
115
  }
94
116
  /**
95
117
  * The canonical stable key for a selector: sorted `axis=value` pairs joined by
@@ -129,3 +151,50 @@ export function selectorMatches(selector, target) {
129
151
  }
130
152
  return true;
131
153
  }
154
+ /**
155
+ * The axes `selector` constrains and `target` leaves undetermined, when those
156
+ * alone keep the two from matching — what a warm skips for want of a value rather
157
+ * than because the selector is for another platform. `undefined` when the
158
+ * selector matches, or differs on a determined axis.
159
+ */
160
+ export function undeterminedAxesBlockingMatch(selector, target) {
161
+ if (target.format !== undefined && selector.format !== target.format)
162
+ return undefined;
163
+ const axes = [];
164
+ for (const axis of PLATFORM_AXES) {
165
+ const constraint = selector[axis];
166
+ if (constraint === undefined)
167
+ continue;
168
+ if (target[axis] === undefined)
169
+ axes.push(axis);
170
+ else if (target[axis] !== constraint)
171
+ return undefined;
172
+ }
173
+ return axes.length > 0 ? axes : undefined;
174
+ }
175
+ /**
176
+ * The combinations of axes the grammar accepts and no host can mean: an N-API
177
+ * addon stating a runtime ABI, and a libc on an os that has none. Shared by every
178
+ * surface that authors a selector — `native:` entries, controller candidates and
179
+ * `exports.code:` entries — so each reports the same rule under its own prefix.
180
+ */
181
+ export function selectorContradictions(selector) {
182
+ const out = [];
183
+ if (selector.format === "napi" && selector.abi !== undefined) {
184
+ out.push({
185
+ rule: "NAPI_ABI_FORBIDDEN",
186
+ axis: "abi",
187
+ detail: `an N-API addon is ABI-stable across runtime releases and states no abi — remove ` +
188
+ `abi ${selector.abi}, which would keep it from loading anywhere else.`,
189
+ });
190
+ }
191
+ if (selector.libc !== undefined && selector.os !== undefined && selector.os !== "linux") {
192
+ out.push({
193
+ rule: "LIBC_OFF_LINUX",
194
+ axis: "libc",
195
+ detail: `libc is only determined on linux, so a selector for os '${selector.os}' that states ` +
196
+ `libc ${selector.libc} could never match a host. Remove libc.`,
197
+ });
198
+ }
199
+ return out;
200
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AA8OvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,EA+tB/C,CAAC"}
1
+ {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAkFA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAoSvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,EA+pB/C,CAAC"}