@telorun/analyzer 0.57.0 → 0.58.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 (116) hide show
  1. package/dist/analyzer.d.ts.map +1 -1
  2. package/dist/analyzer.js +91 -9
  3. package/dist/cel-environment.d.ts.map +1 -1
  4. package/dist/cel-environment.js +6 -3
  5. package/dist/definition-registry.d.ts +5 -0
  6. package/dist/definition-registry.d.ts.map +1 -1
  7. package/dist/definition-registry.js +9 -0
  8. package/dist/index.d.ts +10 -2
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +6 -2
  11. package/dist/invocation-contract.d.ts +21 -13
  12. package/dist/invocation-contract.d.ts.map +1 -1
  13. package/dist/invocation-contract.js +43 -46
  14. package/dist/loaded-types.d.ts +13 -0
  15. package/dist/loaded-types.d.ts.map +1 -1
  16. package/dist/manifest-loader.d.ts +8 -1
  17. package/dist/manifest-loader.d.ts.map +1 -1
  18. package/dist/manifest-loader.js +33 -6
  19. package/dist/migrations/driver.d.ts +69 -0
  20. package/dist/migrations/driver.d.ts.map +1 -0
  21. package/dist/migrations/driver.js +200 -0
  22. package/dist/migrations/entries/index.d.ts +3 -0
  23. package/dist/migrations/entries/index.d.ts.map +1 -0
  24. package/dist/migrations/entries/index.js +9 -0
  25. package/dist/migrations/entries/normalize-value-types.json +48 -0
  26. package/dist/migrations/entries/ref-slot-scalar-type.json +20 -0
  27. package/dist/migrations/entry-data.d.ts +25 -0
  28. package/dist/migrations/entry-data.d.ts.map +1 -0
  29. package/dist/migrations/entry-data.js +171 -0
  30. package/dist/migrations/index.d.ts +22 -0
  31. package/dist/migrations/index.d.ts.map +1 -0
  32. package/dist/migrations/index.js +19 -0
  33. package/dist/migrations/match.d.ts +162 -0
  34. package/dist/migrations/match.d.ts.map +1 -0
  35. package/dist/migrations/match.js +295 -0
  36. package/dist/migrations/patch.d.ts +68 -0
  37. package/dist/migrations/patch.d.ts.map +1 -0
  38. package/dist/migrations/patch.js +236 -0
  39. package/dist/migrations/provenance.d.ts +25 -0
  40. package/dist/migrations/provenance.d.ts.map +1 -0
  41. package/dist/migrations/provenance.js +118 -0
  42. package/dist/migrations/registry.d.ts +35 -0
  43. package/dist/migrations/registry.d.ts.map +1 -0
  44. package/dist/migrations/registry.js +35 -0
  45. package/dist/migrations/report.d.ts +28 -0
  46. package/dist/migrations/report.d.ts.map +1 -0
  47. package/dist/migrations/report.js +144 -0
  48. package/dist/migrations/types.d.ts +115 -0
  49. package/dist/migrations/types.d.ts.map +1 -0
  50. package/dist/migrations/types.js +24 -0
  51. package/dist/migrations/yaml-edit.d.ts +21 -0
  52. package/dist/migrations/yaml-edit.d.ts.map +1 -0
  53. package/dist/migrations/yaml-edit.js +245 -0
  54. package/dist/parse-loaded-file.d.ts +8 -0
  55. package/dist/parse-loaded-file.d.ts.map +1 -1
  56. package/dist/parse-loaded-file.js +22 -13
  57. package/dist/resolve-schema-type-refs.d.ts +29 -12
  58. package/dist/resolve-schema-type-refs.d.ts.map +1 -1
  59. package/dist/resolve-schema-type-refs.js +89 -16
  60. package/dist/schema-compat.d.ts +35 -9
  61. package/dist/schema-compat.d.ts.map +1 -1
  62. package/dist/schema-compat.js +180 -64
  63. package/dist/schema-region.d.ts +33 -0
  64. package/dist/schema-region.d.ts.map +1 -0
  65. package/dist/schema-region.js +45 -0
  66. package/dist/types.d.ts +17 -0
  67. package/dist/types.d.ts.map +1 -1
  68. package/dist/validate-cel-context.d.ts.map +1 -1
  69. package/dist/validate-cel-context.js +29 -3
  70. package/dist/validate-step-inputs.d.ts +8 -1
  71. package/dist/validate-step-inputs.d.ts.map +1 -1
  72. package/dist/validate-step-inputs.js +47 -2
  73. package/dist/validate-value-type-slots.d.ts +43 -0
  74. package/dist/validate-value-type-slots.d.ts.map +1 -0
  75. package/dist/validate-value-type-slots.js +142 -0
  76. package/dist/value-type-keyword.d.ts +60 -0
  77. package/dist/value-type-keyword.d.ts.map +1 -0
  78. package/dist/value-type-keyword.js +119 -0
  79. package/dist/yaml-source-edit.d.ts +56 -0
  80. package/dist/yaml-source-edit.d.ts.map +1 -0
  81. package/dist/yaml-source-edit.js +93 -0
  82. package/package.json +3 -3
  83. package/src/analyzer.ts +99 -6
  84. package/src/cel-environment.ts +6 -3
  85. package/src/definition-registry.ts +10 -0
  86. package/src/index.ts +26 -2
  87. package/src/invocation-contract.ts +43 -48
  88. package/src/loaded-types.ts +13 -0
  89. package/src/manifest-loader.ts +37 -6
  90. package/src/migrations/driver.ts +262 -0
  91. package/src/migrations/entries/index.ts +10 -0
  92. package/src/migrations/entries/normalize-value-types.json +48 -0
  93. package/src/migrations/entries/ref-slot-scalar-type.json +20 -0
  94. package/src/migrations/entry-data.ts +207 -0
  95. package/src/migrations/index.ts +22 -0
  96. package/src/migrations/match.ts +382 -0
  97. package/src/migrations/patch.ts +265 -0
  98. package/src/migrations/provenance.ts +167 -0
  99. package/src/migrations/registry.ts +40 -0
  100. package/src/migrations/report.ts +169 -0
  101. package/src/migrations/types.ts +144 -0
  102. package/src/migrations/yaml-edit.ts +260 -0
  103. package/src/parse-loaded-file.ts +31 -12
  104. package/src/resolve-schema-type-refs.ts +93 -16
  105. package/src/schema-compat.ts +212 -74
  106. package/src/schema-region.ts +46 -0
  107. package/src/types.ts +17 -0
  108. package/src/validate-cel-context.ts +36 -3
  109. package/src/validate-step-inputs.ts +56 -1
  110. package/src/validate-value-type-slots.ts +182 -0
  111. package/src/value-type-keyword.ts +135 -0
  112. package/src/yaml-source-edit.ts +106 -0
  113. package/dist/binary-slot.d.ts +0 -39
  114. package/dist/binary-slot.d.ts.map +0 -1
  115. package/dist/binary-slot.js +0 -58
  116. package/src/binary-slot.ts +0 -71
@@ -1 +1 @@
1
- {"version":3,"file":"loaded-types.d.ts","sourceRoot":"","sources":["../src/loaded-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;4EAI4E;AAC5E,MAAM,WAAW,UAAU;IACzB;+DAC2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf;gEAC4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb;;+EAE2E;IAC3E,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB;+EAC2E;IAC3E,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,6EAA6E;IAC7E,SAAS,EAAE,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1C,0EAA0E;IAC1E,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,0EAA0E;IAC1E,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;mCACmC;AACnC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB;oEACgE;IAChE,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED;;;;;sCAKsC;AACtC,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB;;;kEAG8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB;6EACyE;IACzE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;kDAE8C;IAC9C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;0BAC0B;AAC1B,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC;IACpB;;wBAEoB;IACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACnC;;;;2BAIuB;IACvB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAClD;;;iFAG6E;IAC7E,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;;;iDAG6C;IAC7C,kBAAkB,EAAE,kBAAkB,EAAE,CAAC;IACzC;;;8EAG0E;IAC1E,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;IACvC;yCACqC;IACrC,MAAM,EAAE,cAAc,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B;8BAC0B;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ;;qEAEiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;gFAE4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC;CACd"}
1
+ {"version":3,"file":"loaded-types.d.ts","sourceRoot":"","sources":["../src/loaded-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;4EAI4E;AAC5E,MAAM,WAAW,UAAU;IACzB;+DAC2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf;gEAC4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb;;+EAE2E;IAC3E,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB;+EAC2E;IAC3E,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,6EAA6E;IAC7E,SAAS,EAAE,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1C,0EAA0E;IAC1E,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,0EAA0E;IAC1E,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B;;;;2DAIuD;IACvD,UAAU,EAAE,cAAc,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;mCACmC;AACnC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB;oEACgE;IAChE,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED;;;;;sCAKsC;AACtC,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB;;;kEAG8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB;6EACyE;IACzE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;kDAE8C;IAC9C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;0BAC0B;AAC1B,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC;IACpB;;wBAEoB;IACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACnC;;;;2BAIuB;IACvB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAClD;;;iFAG6E;IAC7E,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;;;;sDAIkD;IAClD,oBAAoB,EAAE,kBAAkB,EAAE,CAAC;IAC3C;;;iDAG6C;IAC7C,kBAAkB,EAAE,kBAAkB,EAAE,CAAC;IACzC;;;8EAG0E;IAC1E,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;IACvC;yCACqC;IACrC,MAAM,EAAE,cAAc,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B;8BAC0B;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ;;qEAEiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;gFAE4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC;CACd"}
@@ -15,6 +15,7 @@ export declare class Loader {
15
15
  private readonly urlToSource;
16
16
  protected sources: ManifestSource[];
17
17
  private readonly celEnv;
18
+ private readonly migrations?;
18
19
  /** Sources are resolved in order — the first whose `supports(url)` matches
19
20
  * wins. The caller (composition root) decides which concrete sources exist
20
21
  * and supplies them; `defaultSources()` bundles the browser-safe built-ins
@@ -50,7 +51,13 @@ export declare class Loader {
50
51
  * caller opted in. Desugaring lives here, not in the pure `parseLoadedFile`,
51
52
  * so round-trip consumers (the editor) keep a raw manifest/AST/position
52
53
  * triple they can pair by index; only resolved consumers that pass
53
- * `desugarImports` see synthetic Telo.Import manifests. */
54
+ * `desugarImports` see synthetic Telo.Import manifests.
55
+ *
56
+ * The migration phase runs inside `parseLoadedFile`, i.e. before desugaring —
57
+ * a rule must only ever match author-written nodes, and the position is what
58
+ * makes that structural rather than a convention. Nothing needs the later
59
+ * position: the `imports:` map is read straight off the module manifest and is
60
+ * equally available before desugaring. */
54
61
  private parseAndMaybeDesugar;
55
62
  /** Raw text of any already-cached variant for `source`, so a cache miss on
56
63
  * one (compile, desugar) variant reparses without a second source read. */
@@ -1 +1 @@
1
- {"version":3,"file":"manifest-loader.d.ts","sourceRoot":"","sources":["../src/manifest-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,UAAU,EACV,WAAW,EACX,YAAY,EACb,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAwCpB,qBAAa,MAAM;IACjB;;;yEAGqE;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAE3D;;;;;8BAK0B;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IAEzD,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC;;;;mBAIe;gBACH,OAAO,GAAE,cAAc,EAAO,EAAE,OAAO,GAAE,iBAAsB;IAK3E,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAKtC,OAAO,CAAC,IAAI;IAMN,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUrD;;;;2CAIuC;IACvC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI7C;;;;;;;;;gFAS4E;IAC5E,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAYzB;;;+BAG2B;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAyCvE;;;;gEAI4D;IAC5D,OAAO,CAAC,oBAAoB;IAa5B;gFAC4E;IAC5E,OAAO,CAAC,cAAc;IAQtB;;wEAEoE;IAC9D,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAsB3E;;;qCAGiC;IAC3B,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAiI9E;;;;;;;;sBAQkB;IAClB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAOlE,OAAO,CAAC,6BAA6B;IAarC,OAAO,CAAC,mCAAmC;IAc3C,OAAO,CAAC,2BAA2B;YAkCrB,eAAe;IAmB7B;;;0CAGsC;IAChC,gBAAgB,CACpB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CA0B5D"}
1
+ {"version":3,"file":"manifest-loader.d.ts","sourceRoot":"","sources":["../src/manifest-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,UAAU,EACV,WAAW,EACX,YAAY,EACb,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AA2DpB,qBAAa,MAAM;IACjB;;;yEAGqE;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAE3D;;;;;8BAK0B;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IAEzD,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAA4B;IAExD;;;;mBAIe;gBACH,OAAO,GAAE,cAAc,EAAO,EAAE,OAAO,GAAE,iBAAsB;IAM3E,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAKtC,OAAO,CAAC,IAAI;IAMN,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUrD;;;;2CAIuC;IACvC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI7C;;;;;;;;;gFAS4E;IAC5E,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAYzB;;;+BAG2B;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAyCvE;;;;;;;;;;6CAUyC;IACzC,OAAO,CAAC,oBAAoB;IAe5B;gFAC4E;IAC5E,OAAO,CAAC,cAAc;IAQtB;;wEAEoE;IAC9D,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAsB3E;;;qCAGiC;IAC3B,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAkI9E;;;;;;;;sBAQkB;IAClB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAOlE,OAAO,CAAC,6BAA6B;IAarC,OAAO,CAAC,mCAAmC;IAc3C,OAAO,CAAC,2BAA2B;YAkCrB,eAAe;IAmB7B;;;0CAGsC;IAChC,gBAAgB,CACpB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CA0B5D"}
@@ -24,18 +24,34 @@ function collectParseDiagnostics(modules) {
24
24
  }
25
25
  return diagnostics;
26
26
  }
27
+ /** Rewrite always, report locally. Every file in the graph was migrated, but a
28
+ * published dependency's manifest is not the consumer's to fix and its author
29
+ * is the only person who can — so only the entry module's own files (owner +
30
+ * its `include:` partials) report. Same rule `X_TELO_REF_UNRESOLVED` follows. */
31
+ function collectMigrationDiagnostics(entry) {
32
+ const diagnostics = [];
33
+ for (const file of [entry.owner, ...entry.partials]) {
34
+ diagnostics.push(...file.migrations.diagnostics);
35
+ }
36
+ return diagnostics;
37
+ }
27
38
  const SYSTEM_KINDS = new Set([
28
39
  "Telo.Application",
29
40
  "Telo.Library",
30
41
  "Telo.Import",
31
42
  "Telo.Definition",
32
43
  ]);
33
- /** File cache variant tags: compile (c/r) × desugarImports (d/n). A desugared
34
- * and a raw load of the same file are distinct entries so neither sees the
35
- * wrong manifest tree. */
36
- const CACHE_VARIANTS = ["rn", "rd", "cn", "cd"];
44
+ /** File cache variant tags: compile (c/r) × desugarImports (d/n) × migrate
45
+ * (m/x). A desugared and a raw load of the same file are distinct entries so
46
+ * neither sees the wrong manifest tree, and the migration axis is there for
47
+ * the same reason the editor's round-trip view and `telo migrate` must see
48
+ * the author's spelling, everything else the current one. */
49
+ const CACHE_VARIANTS = [
50
+ "rnx", "rdx", "cnx", "cdx",
51
+ "rnm", "rdm", "cnm", "cdm",
52
+ ];
37
53
  function variantKey(options) {
38
- return `${options?.compile ? "c" : "r"}${options?.desugarImports ? "d" : "n"}`;
54
+ return `${options?.compile ? "c" : "r"}${options?.desugarImports ? "d" : "n"}${options?.migrate ? "m" : "x"}`;
39
55
  }
40
56
  export class Loader {
41
57
  /** LoadedFile cache keyed by `${compile ? "compiled" : "raw"}:${source}`.
@@ -52,6 +68,7 @@ export class Loader {
52
68
  urlToSource = new Map();
53
69
  sources;
54
70
  celEnv;
71
+ migrations;
55
72
  /** Sources are resolved in order — the first whose `supports(url)` matches
56
73
  * wins. The caller (composition root) decides which concrete sources exist
57
74
  * and supplies them; `defaultSources()` bundles the browser-safe built-ins
@@ -60,6 +77,7 @@ export class Loader {
60
77
  constructor(sources = [], options = {}) {
61
78
  this.sources = [...sources];
62
79
  this.celEnv = buildCelEnvironment(options.celHandlers);
80
+ this.migrations = options.migrations;
63
81
  }
64
82
  register(source) {
65
83
  this.sources.unshift(source);
@@ -157,11 +175,19 @@ export class Loader {
157
175
  * caller opted in. Desugaring lives here, not in the pure `parseLoadedFile`,
158
176
  * so round-trip consumers (the editor) keep a raw manifest/AST/position
159
177
  * triple they can pair by index; only resolved consumers that pass
160
- * `desugarImports` see synthetic Telo.Import manifests. */
178
+ * `desugarImports` see synthetic Telo.Import manifests.
179
+ *
180
+ * The migration phase runs inside `parseLoadedFile`, i.e. before desugaring —
181
+ * a rule must only ever match author-written nodes, and the position is what
182
+ * makes that structural rather than a convention. Nothing needs the later
183
+ * position: the `imports:` map is read straight off the module manifest and is
184
+ * equally available before desugaring. */
161
185
  parseAndMaybeDesugar(source, requestedUrl, text, options) {
162
186
  const loaded = parseLoadedFile(source, requestedUrl, text, {
163
187
  compile: options?.compile,
164
188
  celEnv: this.celEnv,
189
+ migrate: options?.migrate,
190
+ migrations: this.migrations,
165
191
  });
166
192
  return options?.desugarImports ? desugarLoadedFile(loaded) : loaded;
167
193
  }
@@ -318,6 +344,7 @@ export class Loader {
318
344
  modules,
319
345
  importEdges,
320
346
  overrides,
347
+ migrationDiagnostics: collectMigrationDiagnostics(entry),
321
348
  versionDiagnostics: diagnostics,
322
349
  parseDiagnostics: collectParseDiagnostics(modules),
323
350
  errors,
@@ -0,0 +1,69 @@
1
+ /** The migration driver — one pass, one set of guarantees.
2
+ *
3
+ * **Composition is the driver's guarantee, not each entry's proof
4
+ * obligation.** The match set is frozen against the pre-migration tree, so no
5
+ * rule can match a node another rule produced; rules within an entry apply in
6
+ * order at each match; entries never see one another's output. That matters
7
+ * once core and module entries are aggregated from different parties, where
8
+ * "it happens to work" is not determinism. Idempotency then follows from the
9
+ * driver rather than from every author getting it right: a rule matches only
10
+ * the legacy spelling, and re-running finds nothing.
11
+ *
12
+ * How a rewrite is REPORTED — the provenance record and the diagnostic — is
13
+ * `report.ts`. Nothing there can change what a migration does, and nothing
14
+ * here decides how it reads. */
15
+ import type { ResourceManifest } from "@telorun/sdk";
16
+ import type { Document } from "yaml";
17
+ import type { MigrationEntry, MigrationRewrite } from "./types.js";
18
+ import type { AnalysisDiagnostic } from "../types.js";
19
+ /** What one file's migration produced. */
20
+ export interface FileMigrations {
21
+ /** One record per applied rewrite, in application order. Empty when the file
22
+ * carried no legacy spelling — the overwhelmingly common case. */
23
+ readonly rewrites: readonly MigrationRewrite[];
24
+ /** One diagnostic per rewrite. Whether they are SURFACED is the graph's
25
+ * decision: a migration rewrites always, because the runtime must read
26
+ * artifacts published years ago, but reports only for the entry's own
27
+ * modules, because a published dependency is not the consumer's to fix. */
28
+ readonly diagnostics: readonly AnalysisDiagnostic[];
29
+ }
30
+ export declare const NO_MIGRATIONS: FileMigrations;
31
+ /**
32
+ * Run `entries` over one file's parsed documents, mutating `manifests` in
33
+ * place. Returns the provenance records and their diagnostics.
34
+ *
35
+ * The manifests are the loader's own projection of the file, never the
36
+ * author's text — nothing here can reach disk.
37
+ */
38
+ export declare function migrateManifests(args: {
39
+ source: string;
40
+ manifests: Array<ResourceManifest | null>;
41
+ entries?: readonly MigrationEntry[];
42
+ }): FileMigrations;
43
+ /**
44
+ * Migrate the author's YAML instead of the loader's tree — the operation
45
+ * `telo migrate` is the reference application of.
46
+ *
47
+ * `manifests` must be the RAW (un-migrated) projection of `documents`, since
48
+ * the matchers select legacy spellings. Returns `null` when nothing matched, so
49
+ * a caller can leave an untouched file untouched rather than rewriting
50
+ * identical bytes.
51
+ *
52
+ * `unwritable` names every rewrite the tree accepted but the TEXT could not
53
+ * express. The two appliers can disagree only in this direction, and the
54
+ * disagreement has to be reported: the diagnostic that sent the author here
55
+ * says "run `telo migrate`", so a location this silently skipped would keep
56
+ * warning with no way to act on it.
57
+ */
58
+ export declare function migrateFileText(args: {
59
+ source: string;
60
+ text: string;
61
+ documents: readonly Document[];
62
+ manifests: ReadonlyArray<ResourceManifest | null>;
63
+ entries?: readonly MigrationEntry[];
64
+ }): {
65
+ text: string;
66
+ rewrites: MigrationRewrite[];
67
+ unwritable: MigrationRewrite[];
68
+ } | null;
69
+ //# sourceMappingURL=driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/migrations/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;iCAaiC;AAEjC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAWrC,OAAO,KAAK,EACV,cAAc,EAGd,gBAAgB,EACjB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,0CAA0C;AAC1C,MAAM,WAAW,cAAc;IAC7B;uEACmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC/C;;;gFAG4E;IAC5E,QAAQ,CAAC,WAAW,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACrD;AAED,eAAO,MAAM,aAAa,EAAE,cAAkD,CAAC;AAE/E;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1C,OAAO,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CACrC,GAAG,cAAc,CAYjB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC/B,SAAS,EAAE,aAAa,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAClD,OAAO,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CACrC,GAAG;IACF,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC,GAAG,IAAI,CA8CP"}
@@ -0,0 +1,200 @@
1
+ /** The migration driver — one pass, one set of guarantees.
2
+ *
3
+ * **Composition is the driver's guarantee, not each entry's proof
4
+ * obligation.** The match set is frozen against the pre-migration tree, so no
5
+ * rule can match a node another rule produced; rules within an entry apply in
6
+ * order at each match; entries never see one another's output. That matters
7
+ * once core and module entries are aggregated from different parties, where
8
+ * "it happens to work" is not determinism. Idempotency then follows from the
9
+ * driver rather than from every author getting it right: a rule matches only
10
+ * the legacy spelling, and re-running finds nothing.
11
+ *
12
+ * How a rewrite is REPORTED — the provenance record and the diagnostic — is
13
+ * `report.ts`. Nothing there can change what a migration does, and nothing
14
+ * here decides how it reads. */
15
+ import { applyEffectsToTree, formatMigrationPath, planPatch, } from "./patch.js";
16
+ import { applyTextEdits, planTextEdits } from "./yaml-edit.js";
17
+ import { applicableRules, buildMatchIndex, selectMatches } from "./match.js";
18
+ import { CORE_MIGRATIONS } from "./registry.js";
19
+ import { toDiagnostic, toRewrite } from "./report.js";
20
+ export const NO_MIGRATIONS = { rewrites: [], diagnostics: [] };
21
+ /**
22
+ * Run `entries` over one file's parsed documents, mutating `manifests` in
23
+ * place. Returns the provenance records and their diagnostics.
24
+ *
25
+ * The manifests are the loader's own projection of the file, never the
26
+ * author's text — nothing here can reach disk.
27
+ */
28
+ export function migrateManifests(args) {
29
+ const entries = args.entries ?? CORE_MIGRATIONS;
30
+ if (entries.length === 0)
31
+ return NO_MIGRATIONS;
32
+ const applied = applyAll(args.manifests, entries);
33
+ if (applied.length === 0)
34
+ return NO_MIGRATIONS;
35
+ const rewrites = applied.map((a) => toRewrite(a));
36
+ const diagnostics = applied.map((a, i) => toDiagnostic(a, rewrites[i], args.source, args.manifests));
37
+ return { rewrites, diagnostics };
38
+ }
39
+ /**
40
+ * Migrate the author's YAML instead of the loader's tree — the operation
41
+ * `telo migrate` is the reference application of.
42
+ *
43
+ * `manifests` must be the RAW (un-migrated) projection of `documents`, since
44
+ * the matchers select legacy spellings. Returns `null` when nothing matched, so
45
+ * a caller can leave an untouched file untouched rather than rewriting
46
+ * identical bytes.
47
+ *
48
+ * `unwritable` names every rewrite the tree accepted but the TEXT could not
49
+ * express. The two appliers can disagree only in this direction, and the
50
+ * disagreement has to be reported: the diagnostic that sent the author here
51
+ * says "run `telo migrate`", so a location this silently skipped would keep
52
+ * warning with no way to act on it.
53
+ */
54
+ export function migrateFileText(args) {
55
+ const entries = args.entries ?? CORE_MIGRATIONS;
56
+ if (entries.length === 0)
57
+ return null;
58
+ // Planned against a copy: the tree walk is what decides which patches apply
59
+ // (and in what order they refuse), so the YAML side must ask exactly the same
60
+ // question of exactly the same state rather than re-deriving it.
61
+ const scratch = args.manifests.map((m) => (m ? structuredClone(m) : null));
62
+ const applied = applyAll(scratch, entries);
63
+ if (applied.length === 0)
64
+ return null;
65
+ const edits = [];
66
+ const kept = [];
67
+ const skipped = [];
68
+ for (const patch of applied) {
69
+ const doc = args.documents[patch.documentIndex];
70
+ if (!doc) {
71
+ skipped.push(patch);
72
+ continue;
73
+ }
74
+ const planned = planTextEdits(doc, args.text, patch.plan.effects);
75
+ // A patch the tree accepted but the text cannot express (a block scalar
76
+ // span, a flow-style entry) leaves that node alone rather than half-written.
77
+ if (!planned) {
78
+ skipped.push(patch);
79
+ continue;
80
+ }
81
+ // Two patches whose spans overlap cannot both be spliced — the second would
82
+ // write into bytes the first replaced. The tree side has no equivalent,
83
+ // because an object write is idempotent where a splice is positional, so
84
+ // this is the one place the file applier is stricter: the later patch is
85
+ // dropped and its node stays as the author wrote it.
86
+ if (planned.some((edit) => edits.some((existing) => overlaps(edit, existing)))) {
87
+ skipped.push(patch);
88
+ continue;
89
+ }
90
+ edits.push(...planned);
91
+ kept.push(patch);
92
+ }
93
+ if (edits.length === 0 && skipped.length === 0)
94
+ return null;
95
+ return {
96
+ text: edits.length > 0 ? applyTextEdits(args.text, edits) : args.text,
97
+ rewrites: kept.map(toRewrite),
98
+ unwritable: skipped.map(toRewrite),
99
+ };
100
+ }
101
+ /** Whether two splices contend for the same bytes. A pure insertion (an empty
102
+ * span) collides only with a span that strictly contains its point. */
103
+ function overlaps(a, b) {
104
+ if (a.start === a.end)
105
+ return b.start < a.start && a.start < b.end;
106
+ if (b.start === b.end)
107
+ return a.start < b.start && b.start < a.end;
108
+ return a.start < b.end && b.start < a.end;
109
+ }
110
+ /** One pass: every match collected against the frozen pre-migration tree, then
111
+ * applied in entry order. */
112
+ function applyAll(manifests, entries) {
113
+ const candidates = [];
114
+ // One index per DOCUMENT, shared by every rule that can reach it — the walk
115
+ // is the expensive part and does not depend on the rule. This runs on the
116
+ // kernel's boot path for every file in the graph, so a walk per rule would
117
+ // scale the cost of loading any manifest with the size of the migration set.
118
+ //
119
+ // The `inKind` gate and the `under` regions are both known BEFORE the walk,
120
+ // so they bound it rather than filtering its output: a document no rule
121
+ // targets is never walked, and a region no rule names is never descended
122
+ // into. `type:` alone occurs a couple of hundred times in a standard-library
123
+ // manifest, so indexing sites that cannot be selected is the whole cost.
124
+ const flatRules = entries.flatMap((entry) => entry.rules.map((rule) => ({ entry, ops: rule.patch, match: rule.match })));
125
+ for (let documentIndex = 0; documentIndex < manifests.length; documentIndex++) {
126
+ const manifest = manifests[documentIndex];
127
+ if (!manifest)
128
+ continue;
129
+ const { rules, keys, roots } = applicableRules(flatRules, manifest.kind);
130
+ if (rules.length === 0)
131
+ continue;
132
+ const index = buildMatchIndex(manifest, keys, roots);
133
+ for (const { entry, ops, match } of rules) {
134
+ for (const path of selectMatches(index, manifest, match)) {
135
+ candidates.push({ entry, ops, documentIndex, path });
136
+ }
137
+ }
138
+ }
139
+ // Arrays whose LENGTH an already-applied patch changed, as
140
+ // `<documentIndex>:<dotted path>`. A frozen match names a sequence element by
141
+ // INDEX, and an index is not an identity: once a sibling patch inserted or
142
+ // removed an item, the same index names a different element — including one
143
+ // another rule just produced, which is exactly what the frozen match set
144
+ // exists to prevent. A key-based path needs no such record, because a rename
145
+ // or removal makes the stale path resolve to nothing and `planPatch` refuses
146
+ // it on its own.
147
+ const shiftedArrays = new Set();
148
+ const applied = [];
149
+ for (const candidate of candidates) {
150
+ const manifest = manifests[candidate.documentIndex];
151
+ if (!manifest)
152
+ continue;
153
+ if (indexIsStale(candidate.documentIndex, candidate.path, shiftedArrays))
154
+ continue;
155
+ const result = planPatch(manifest, candidate.path, candidate.ops);
156
+ // Refusal is not an error: the node stays as the author wrote it and the
157
+ // ordinary validator reports it with an accurate message.
158
+ if (!result.ok)
159
+ continue;
160
+ applyEffectsToTree(manifest, result.plan.effects);
161
+ for (const array of resizedArrays(candidate.documentIndex, result.plan.effects)) {
162
+ shiftedArrays.add(array);
163
+ }
164
+ applied.push({
165
+ entry: candidate.entry,
166
+ documentIndex: candidate.documentIndex,
167
+ matched: candidate.path,
168
+ plan: result.plan,
169
+ ops: candidate.ops,
170
+ });
171
+ }
172
+ return applied;
173
+ }
174
+ /** Arrays this patch resized, keyed for `shiftedArrays`. */
175
+ function resizedArrays(documentIndex, effects) {
176
+ const out = [];
177
+ for (const effect of effects) {
178
+ if (effect.kind === "insert-item") {
179
+ out.push(`${documentIndex}:${formatMigrationPath(effect.path)}`);
180
+ }
181
+ else if (effect.kind === "remove-entry" &&
182
+ typeof effect.path[effect.path.length - 1] === "number") {
183
+ out.push(`${documentIndex}:${formatMigrationPath(effect.path.slice(0, -1))}`);
184
+ }
185
+ }
186
+ return out;
187
+ }
188
+ /** Whether any index along `path` steps into an array a prior patch resized. */
189
+ function indexIsStale(documentIndex, path, shiftedArrays) {
190
+ if (shiftedArrays.size === 0)
191
+ return false;
192
+ for (let i = 0; i < path.length; i++) {
193
+ if (typeof path[i] !== "number")
194
+ continue;
195
+ if (shiftedArrays.has(`${documentIndex}:${formatMigrationPath(path.slice(0, i))}`)) {
196
+ return true;
197
+ }
198
+ }
199
+ return false;
200
+ }
@@ -0,0 +1,3 @@
1
+ /** Every entry file, in the order the driver applies them. */
2
+ export declare const MIGRATION_ENTRY_FILES: ReadonlyArray<readonly [file: string, data: unknown]>;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/migrations/entries/index.ts"],"names":[],"mappings":"AAKA,8DAA8D;AAC9D,eAAO,MAAM,qBAAqB,EAAE,aAAa,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAGvF,CAAC"}
@@ -0,0 +1,9 @@
1
+ // GENERATED by scripts/copy-migration-entries.mjs — do not edit, and do not commit.
2
+ // Source: analyzer/migrations/*.json (lexically ordered).
3
+ import e0 from "./normalize-value-types.json" with { type: "json" };
4
+ import e1 from "./ref-slot-scalar-type.json" with { type: "json" };
5
+ /** Every entry file, in the order the driver applies them. */
6
+ export const MIGRATION_ENTRY_FILES = [
7
+ ["normalize-value-types.json", e0],
8
+ ["ref-slot-scalar-type.json", e1],
9
+ ];
@@ -0,0 +1,48 @@
1
+ {
2
+ "$comment": "Three keywords answered one question — what is the value at this slot, beyond what JSON Schema's `type` can say — and each answered it differently. `inSchema` with the wildcard `inKind` / `under` is what makes this reachable at all: these annotations occur in author-written schema fragments inside ORDINARY resource documents (an inline `inputType:` on any kind that declares one, a route's `request.schema.body`), and that set of kinds is open, so enumerating it would be both incomplete and a violation of the topology-driven constraint. The wildcards are earned by the pairing the reader enforces: a schema region bounds where the walk may go, and an `x-telo-*` key — Telo vocabulary wherever it appears — bounds what it may touch. Each rule sets the value BEFORE renaming the key, so both match the frozen pre-migration tree; a rename first would leave the second rule looking for a node that no longer exists. `notUnder` keeps all three out of the data-bearing keywords, where a value may merely look like a schema.",
3
+ "id": "normalize-value-types",
4
+ "code": "X_TELO_TYPE_DEPRECATED",
5
+ "severity": "warning",
6
+ "reason": "The three value-type annotations were unified into one `x-telo-type`, whose names are `Telo.`-qualified like every other kernel-owned name. `x-telo-binary` and `x-telo-stream` said what a value IS just as `x-telo-type` did, differing only in posture toward the JSON Schema layer — so a fourth kind of value meant a fourth keyword and edits across four packages.",
7
+ "rules": [
8
+ {
9
+ "match": {
10
+ "key": "x-telo-stream",
11
+ "inKind": ["*"],
12
+ "under": ["*"],
13
+ "inSchema": true,
14
+ "value": true,
15
+ "notUnder": ["const", "default", "enum", "examples"]
16
+ },
17
+ "patch": [
18
+ { "op": "set-value", "value": "Telo.Stream" },
19
+ { "op": "rename-key", "to": "x-telo-type" }
20
+ ]
21
+ },
22
+ {
23
+ "match": {
24
+ "key": "x-telo-binary",
25
+ "inKind": ["*"],
26
+ "under": ["*"],
27
+ "inSchema": true,
28
+ "value": true,
29
+ "notUnder": ["const", "default", "enum", "examples"]
30
+ },
31
+ "patch": [
32
+ { "op": "set-value", "value": "Telo.Bytes" },
33
+ { "op": "rename-key", "to": "x-telo-type" }
34
+ ]
35
+ },
36
+ {
37
+ "match": {
38
+ "key": "x-telo-type",
39
+ "inKind": ["*"],
40
+ "under": ["*"],
41
+ "inSchema": true,
42
+ "valueOneOf": ["TcpPort", "UdpPort"],
43
+ "notUnder": ["const", "default", "enum", "examples"]
44
+ },
45
+ "patch": [{ "op": "set-value", "qualify": "Telo." }]
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$comment": "See README.md in this directory. `inKind` + `under` are the positive containment: `under` names TOP-LEVEL keys, so this rule can reach nothing but the schema blocks of a kind document — never the `resources:` template body, whose nested config may hold a key spelled `schema` over data. `withSibling` is what makes it precise — a scalar `type:` is stale only because an `x-telo-ref` sits beside it. `notUnder` then narrows within that region, keeping the rule out of the data-bearing keywords where a value may merely look like a schema.",
3
+ "id": "ref-slot-scalar-type",
4
+ "code": "X_TELO_REF_SCALAR_TYPE",
5
+ "severity": "warning",
6
+ "reason": "A reference is written with the `!ref` tag and resolves to an object, so a reference slot no longer carries the scalar `type:` that plain-string references were pinned to. Leaving it in place makes the slot reject the very value it is declared to accept, and every schema reader has had to know to ignore it.",
7
+ "rules": [
8
+ {
9
+ "match": {
10
+ "key": "type",
11
+ "inKind": ["Telo.Definition", "Telo.Abstract"],
12
+ "under": ["schema", "status", "inputType", "outputType"],
13
+ "valueOneOf": ["string", "number", "integer", "boolean"],
14
+ "withSibling": "x-telo-ref",
15
+ "notUnder": ["const", "default", "enum", "examples"]
16
+ },
17
+ "patch": [{ "op": "remove-entry" }]
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,25 @@
1
+ /** The on-disk shape of a migration entry, and its reader.
2
+ *
3
+ * An entry is DATA: one file per entry under `analyzer/migrations/`, consumed
4
+ * as one lexically ordered set. That is what makes adding a migration one file
5
+ * and retiring one deleting it, what ships the set in the published package,
6
+ * and what lets the Rust crate embed the identical files at build time rather
7
+ * than reimplementing each rewrite.
8
+ *
9
+ * **An entry contains no code.** Both halves — what a rule matches and what it
10
+ * patches — are data, so one file is read identically by every kernel. A
11
+ * predicate expressed in one language would mean one artifact is read two
12
+ * ways, invisibly, since a migration that succeeds is silent.
13
+ *
14
+ * Reading is STRICT. A malformed entry is an authoring mistake, and the
15
+ * alternative to throwing is a migration that silently does not run — the one
16
+ * failure mode a rewrite-on-load design cannot afford, because a migration
17
+ * that succeeds and one that never fires look identical. */
18
+ import type { MigrationEntry } from "./types.js";
19
+ /**
20
+ * Read one entry file's parsed data into a `MigrationEntry`.
21
+ *
22
+ * `file` names the entry file, so a failure says which one.
23
+ */
24
+ export declare function parseMigrationEntry(file: string, data: unknown): MigrationEntry;
25
+ //# sourceMappingURL=entry-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry-data.d.ts","sourceRoot":"","sources":["../../src/migrations/entry-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;6DAgB6D;AAI7D,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,YAAY,CAAC;AAgJpB;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,cAAc,CAiC/E"}