solve-engine 1.0.0-beta.0 → 1.0.0-beta.2

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 (253) hide show
  1. package/dist/BytecodeBuilder-3egMyuDi.d.cts +274 -0
  2. package/dist/BytecodeBuilder-3egMyuDi.d.ts +274 -0
  3. package/dist/Configuration-fVpd-HC-.d.cts +228 -0
  4. package/dist/Configuration-fVpd-HC-.d.ts +228 -0
  5. package/dist/EngineError-DvPSnhZi.d.cts +304 -0
  6. package/dist/EngineError-DvPSnhZi.d.ts +304 -0
  7. package/dist/Lexer-BJdhlnej.d.cts +531 -0
  8. package/dist/Lexer-D9l4Yrk2.d.ts +531 -0
  9. package/dist/NormalizerRule-BrVoVjmP.d.cts +163 -0
  10. package/dist/NormalizerRule-CEjf1FyD.d.ts +163 -0
  11. package/dist/PackageRegistry-D-Tv_7ca.d.cts +2572 -0
  12. package/dist/PackageRegistry-DaH4aIKP.d.ts +2572 -0
  13. package/dist/Parselet-CK8cQu2a.d.cts +299 -0
  14. package/dist/Parselet-ConOIdRO.d.ts +299 -0
  15. package/dist/ScopeManager-B5k0nk05.d.ts +559 -0
  16. package/dist/ScopeManager-CKfQtl7l.d.cts +559 -0
  17. package/dist/Token-0jpvUdPY.d.cts +245 -0
  18. package/dist/Token-0jpvUdPY.d.ts +245 -0
  19. package/dist/VMCheckpoints-BmDwIXgK.d.ts +171 -0
  20. package/dist/VMCheckpoints-CqFuLwrT.d.cts +171 -0
  21. package/dist/Value-KtAQNHur.d.cts +295 -0
  22. package/dist/Value-KtAQNHur.d.ts +295 -0
  23. package/dist/chunk-2RWAXT6O.js +3 -0
  24. package/dist/chunk-2RWAXT6O.js.map +1 -0
  25. package/dist/chunk-34RRD7PC.js +1492 -0
  26. package/dist/chunk-34RRD7PC.js.map +1 -0
  27. package/dist/chunk-3PPFLFH4.js +5097 -0
  28. package/dist/chunk-3PPFLFH4.js.map +1 -0
  29. package/dist/chunk-3VGDNEE3.js +84 -0
  30. package/dist/chunk-3VGDNEE3.js.map +1 -0
  31. package/dist/chunk-3YNVWKR2.cjs +370 -0
  32. package/dist/chunk-3YNVWKR2.cjs.map +1 -0
  33. package/dist/chunk-47LRVGOT.cjs +316 -0
  34. package/dist/chunk-47LRVGOT.cjs.map +1 -0
  35. package/dist/chunk-4MG4XKO2.js +1644 -0
  36. package/dist/chunk-4MG4XKO2.js.map +1 -0
  37. package/dist/chunk-4QADQTWS.js +2392 -0
  38. package/dist/chunk-4QADQTWS.js.map +1 -0
  39. package/dist/chunk-53B6KDDJ.cjs +1651 -0
  40. package/dist/chunk-53B6KDDJ.cjs.map +1 -0
  41. package/dist/chunk-5X2PTP6F.cjs +104 -0
  42. package/dist/chunk-5X2PTP6F.cjs.map +1 -0
  43. package/dist/chunk-5YEMOYSE.js +264 -0
  44. package/dist/chunk-5YEMOYSE.js.map +1 -0
  45. package/dist/chunk-64W6GLLZ.js +481 -0
  46. package/dist/chunk-64W6GLLZ.js.map +1 -0
  47. package/dist/chunk-6BKTCEUP.cjs +233 -0
  48. package/dist/chunk-6BKTCEUP.cjs.map +1 -0
  49. package/dist/chunk-6NTVRDQV.cjs +1642 -0
  50. package/dist/chunk-6NTVRDQV.cjs.map +1 -0
  51. package/dist/chunk-6RDSQURE.js +290 -0
  52. package/dist/chunk-6RDSQURE.js.map +1 -0
  53. package/dist/chunk-75JP4BZX.js +93 -0
  54. package/dist/chunk-75JP4BZX.js.map +1 -0
  55. package/dist/chunk-B7LXJ6LC.cjs +36 -0
  56. package/dist/chunk-B7LXJ6LC.cjs.map +1 -0
  57. package/dist/chunk-BVAR5J2F.js +257 -0
  58. package/dist/chunk-BVAR5J2F.js.map +1 -0
  59. package/dist/chunk-C4XZV6E7.cjs +269 -0
  60. package/dist/chunk-C4XZV6E7.cjs.map +1 -0
  61. package/dist/chunk-CCJPSHGI.cjs +40 -0
  62. package/dist/chunk-CCJPSHGI.cjs.map +1 -0
  63. package/dist/chunk-CLL7RUQV.cjs +316 -0
  64. package/dist/chunk-CLL7RUQV.cjs.map +1 -0
  65. package/dist/chunk-DM3LMRBC.js +329 -0
  66. package/dist/chunk-DM3LMRBC.js.map +1 -0
  67. package/dist/chunk-DUEZFTK2.js +38 -0
  68. package/dist/chunk-DUEZFTK2.js.map +1 -0
  69. package/dist/chunk-EBSPLUW4.cjs +489 -0
  70. package/dist/chunk-EBSPLUW4.cjs.map +1 -0
  71. package/dist/chunk-EHAHVROS.cjs +261 -0
  72. package/dist/chunk-EHAHVROS.cjs.map +1 -0
  73. package/dist/chunk-EIGTWK5N.js +167 -0
  74. package/dist/chunk-EIGTWK5N.js.map +1 -0
  75. package/dist/chunk-EPOXXJBK.js +96 -0
  76. package/dist/chunk-EPOXXJBK.js.map +1 -0
  77. package/dist/chunk-FEAIOR7N.cjs +91 -0
  78. package/dist/chunk-FEAIOR7N.cjs.map +1 -0
  79. package/dist/chunk-G535KJEG.js +312 -0
  80. package/dist/chunk-G535KJEG.js.map +1 -0
  81. package/dist/chunk-GCM5JHMX.js +88 -0
  82. package/dist/chunk-GCM5JHMX.js.map +1 -0
  83. package/dist/chunk-GOLDJNMZ.js +368 -0
  84. package/dist/chunk-GOLDJNMZ.js.map +1 -0
  85. package/dist/chunk-GW32KPCU.cjs +360 -0
  86. package/dist/chunk-GW32KPCU.cjs.map +1 -0
  87. package/dist/chunk-HTXVVJRA.cjs +1549 -0
  88. package/dist/chunk-HTXVVJRA.cjs.map +1 -0
  89. package/dist/chunk-HWSZJQCI.js +311 -0
  90. package/dist/chunk-HWSZJQCI.js.map +1 -0
  91. package/dist/chunk-IF532O7C.js +101 -0
  92. package/dist/chunk-IF532O7C.js.map +1 -0
  93. package/dist/chunk-J73SJHR3.cjs +2415 -0
  94. package/dist/chunk-J73SJHR3.cjs.map +1 -0
  95. package/dist/chunk-JBSYC7BB.cjs +7473 -0
  96. package/dist/chunk-JBSYC7BB.cjs.map +1 -0
  97. package/dist/chunk-KVILKGMS.js +228 -0
  98. package/dist/chunk-KVILKGMS.js.map +1 -0
  99. package/dist/chunk-LIPPNDBE.js +258 -0
  100. package/dist/chunk-LIPPNDBE.js.map +1 -0
  101. package/dist/chunk-LR7YASZF.cjs +172 -0
  102. package/dist/chunk-LR7YASZF.cjs.map +1 -0
  103. package/dist/chunk-M4N5GA5Z.cjs +309 -0
  104. package/dist/chunk-M4N5GA5Z.cjs.map +1 -0
  105. package/dist/chunk-M5LX5AOO.js +7459 -0
  106. package/dist/chunk-M5LX5AOO.js.map +1 -0
  107. package/dist/chunk-MZOVP3WI.cjs +96 -0
  108. package/dist/chunk-MZOVP3WI.cjs.map +1 -0
  109. package/dist/chunk-N5YFR4UP.cjs +10 -0
  110. package/dist/chunk-N5YFR4UP.cjs.map +1 -0
  111. package/dist/chunk-NGBBNL4K.cjs +4 -0
  112. package/dist/chunk-NGBBNL4K.cjs.map +1 -0
  113. package/dist/chunk-NH2O2AUR.js +146 -0
  114. package/dist/chunk-NH2O2AUR.js.map +1 -0
  115. package/dist/chunk-NLNDMWZC.js +31 -0
  116. package/dist/chunk-NLNDMWZC.js.map +1 -0
  117. package/dist/chunk-NMCRQP3Z.cjs +778 -0
  118. package/dist/chunk-NMCRQP3Z.cjs.map +1 -0
  119. package/dist/chunk-NMD5VRN4.cjs +1327 -0
  120. package/dist/chunk-NMD5VRN4.cjs.map +1 -0
  121. package/dist/chunk-OC6LTXYS.cjs +286 -0
  122. package/dist/chunk-OC6LTXYS.cjs.map +1 -0
  123. package/dist/chunk-OT6OJY7C.cjs +114 -0
  124. package/dist/chunk-OT6OJY7C.cjs.map +1 -0
  125. package/dist/chunk-PFSDGGYL.js +8 -0
  126. package/dist/chunk-PFSDGGYL.js.map +1 -0
  127. package/dist/chunk-QNJ4ACRT.cjs +155 -0
  128. package/dist/chunk-QNJ4ACRT.cjs.map +1 -0
  129. package/dist/chunk-QWY3VEZN.js +1637 -0
  130. package/dist/chunk-QWY3VEZN.js.map +1 -0
  131. package/dist/chunk-RFYD5TJE.js +111 -0
  132. package/dist/chunk-RFYD5TJE.js.map +1 -0
  133. package/dist/chunk-RIN643A3.js +354 -0
  134. package/dist/chunk-RIN643A3.js.map +1 -0
  135. package/dist/chunk-RZCWSXTA.cjs +5122 -0
  136. package/dist/chunk-RZCWSXTA.cjs.map +1 -0
  137. package/dist/chunk-SDGRK7EP.js +774 -0
  138. package/dist/chunk-SDGRK7EP.js.map +1 -0
  139. package/dist/chunk-VEKIWQ3F.cjs +39 -0
  140. package/dist/chunk-VEKIWQ3F.cjs.map +1 -0
  141. package/dist/chunk-WQTTOGXC.cjs +99 -0
  142. package/dist/chunk-WQTTOGXC.cjs.map +1 -0
  143. package/dist/chunk-X6K3HUOY.cjs +86 -0
  144. package/dist/chunk-X6K3HUOY.cjs.map +1 -0
  145. package/dist/chunk-XJCMXB2E.cjs +333 -0
  146. package/dist/chunk-XJCMXB2E.cjs.map +1 -0
  147. package/dist/chunk-XVWCOTR6.js +1324 -0
  148. package/dist/chunk-XVWCOTR6.js.map +1 -0
  149. package/dist/chunk-YLJ4XMA6.js +33 -0
  150. package/dist/chunk-YLJ4XMA6.js.map +1 -0
  151. package/dist/chunk-Z2XP767T.cjs +35 -0
  152. package/dist/chunk-Z2XP767T.cjs.map +1 -0
  153. package/dist/chunk-Z4X2RWOF.js +37 -0
  154. package/dist/chunk-Z4X2RWOF.js.map +1 -0
  155. package/dist/constants.cjs +22 -0
  156. package/dist/constants.cjs.map +1 -0
  157. package/dist/constants.d.cts +12 -0
  158. package/dist/constants.d.ts +12 -0
  159. package/dist/constants.js +5 -0
  160. package/dist/constants.js.map +1 -0
  161. package/dist/engine.cjs +79 -0
  162. package/dist/engine.cjs.map +1 -0
  163. package/dist/engine.d.cts +587 -0
  164. package/dist/engine.d.ts +587 -0
  165. package/dist/engine.js +34 -0
  166. package/dist/engine.js.map +1 -0
  167. package/dist/errors.cjs +81 -0
  168. package/dist/errors.cjs.map +1 -0
  169. package/dist/errors.d.cts +95 -0
  170. package/dist/errors.d.ts +95 -0
  171. package/dist/errors.js +4 -0
  172. package/dist/errors.js.map +1 -0
  173. package/dist/format.cjs +171 -0
  174. package/dist/format.cjs.map +1 -0
  175. package/dist/format.d.cts +51 -0
  176. package/dist/format.d.ts +51 -0
  177. package/dist/format.js +168 -0
  178. package/dist/format.js.map +1 -0
  179. package/dist/index.cjs +97 -0
  180. package/dist/index.cjs.map +1 -0
  181. package/dist/index.d.cts +152 -0
  182. package/dist/index.d.ts +152 -0
  183. package/dist/index.js +75 -0
  184. package/dist/index.js.map +1 -0
  185. package/dist/language.cjs +308 -0
  186. package/dist/language.cjs.map +1 -0
  187. package/dist/language.d.cts +110 -0
  188. package/dist/language.d.ts +110 -0
  189. package/dist/language.js +287 -0
  190. package/dist/language.js.map +1 -0
  191. package/dist/lexer.cjs +64 -0
  192. package/dist/lexer.cjs.map +1 -0
  193. package/dist/lexer.d.cts +56 -0
  194. package/dist/lexer.d.ts +56 -0
  195. package/dist/lexer.js +11 -0
  196. package/dist/lexer.js.map +1 -0
  197. package/dist/normalizer.cjs +40 -0
  198. package/dist/normalizer.cjs.map +1 -0
  199. package/dist/normalizer.d.cts +364 -0
  200. package/dist/normalizer.d.ts +364 -0
  201. package/dist/normalizer.js +11 -0
  202. package/dist/normalizer.js.map +1 -0
  203. package/dist/packages.cjs +121 -0
  204. package/dist/packages.cjs.map +1 -0
  205. package/dist/packages.d.cts +691 -0
  206. package/dist/packages.d.ts +691 -0
  207. package/dist/packages.js +24 -0
  208. package/dist/packages.js.map +1 -0
  209. package/dist/parser.cjs +55 -0
  210. package/dist/parser.cjs.map +1 -0
  211. package/dist/parser.d.cts +46 -0
  212. package/dist/parser.d.ts +46 -0
  213. package/dist/parser.js +10 -0
  214. package/dist/parser.js.map +1 -0
  215. package/dist/pipeline-CrsRPmsv.d.ts +285 -0
  216. package/dist/pipeline-DPUQt7yL.d.cts +285 -0
  217. package/dist/resolvers.cjs +13 -0
  218. package/dist/resolvers.cjs.map +1 -0
  219. package/dist/resolvers.d.cts +111 -0
  220. package/dist/resolvers.d.ts +111 -0
  221. package/dist/resolvers.js +4 -0
  222. package/dist/resolvers.js.map +1 -0
  223. package/dist/services.cjs +21 -0
  224. package/dist/services.cjs.map +1 -0
  225. package/dist/services.d.cts +30 -0
  226. package/dist/services.d.ts +30 -0
  227. package/dist/services.js +4 -0
  228. package/dist/services.js.map +1 -0
  229. package/dist/uom.cjs +56 -0
  230. package/dist/uom.cjs.map +1 -0
  231. package/dist/uom.d.cts +224 -0
  232. package/dist/uom.d.ts +224 -0
  233. package/dist/uom.js +11 -0
  234. package/dist/uom.js.map +1 -0
  235. package/dist/utilities.cjs +32 -0
  236. package/dist/utilities.cjs.map +1 -0
  237. package/dist/utilities.d.cts +113 -0
  238. package/dist/utilities.d.ts +113 -0
  239. package/dist/utilities.js +7 -0
  240. package/dist/utilities.js.map +1 -0
  241. package/dist/variables.cjs +17 -0
  242. package/dist/variables.cjs.map +1 -0
  243. package/dist/variables.d.cts +87 -0
  244. package/dist/variables.d.ts +87 -0
  245. package/dist/variables.js +4 -0
  246. package/dist/variables.js.map +1 -0
  247. package/dist/vm.cjs +284 -0
  248. package/dist/vm.cjs.map +1 -0
  249. package/dist/vm.d.cts +68 -0
  250. package/dist/vm.d.ts +68 -0
  251. package/dist/vm.js +194 -0
  252. package/dist/vm.js.map +1 -0
  253. package/package.json +4 -4
@@ -0,0 +1,304 @@
1
+ /**
2
+ * The built-in error-code catalog, one typed const object per domain
3
+ * unioned together here for autocomplete/exhaustiveness in core engine
4
+ * code. Deliberately NOT one central enum: `IEnginePackage` is documented
5
+ * public SDK surface for third-party packages (see `api/PackageRegistry.ts`),
6
+ * and a closed enum would block an external package author from defining
7
+ * their own codes without editing this file. `EngineError.code`'s runtime
8
+ * type stays `string` for exactly that reason. This catalog is for the
9
+ * codes THIS repo owns and wants collision/typo checking on (see
10
+ * `__tests__/errors/ErrorCodeCatalog.spec.ts`), not a hard runtime
11
+ * whitelist.
12
+ *
13
+ * As each package migrates to `Result<void, EngineError>` (see this
14
+ * session's error-handling-refactor plan, Phase 5), it should export its
15
+ * own small `XxxErrorCodes` const object co-located with its parselets
16
+ * exactly like `CoreErrorCodes` below, just scoped to one domain, and get
17
+ * unioned into `ErrorCode` here. Until a package migrates, its existing
18
+ * free-string codes keep working (ErrorFactory accepts any string); they
19
+ * just aren't caught by the catalog's uniqueness/orphan checks yet.
20
+ */
21
+ /**
22
+ * Codes used directly by the parser/VM/engine/errors layers themselves
23
+ * confirmed against the current source, not aspirational. Grouped by
24
+ * pipeline stage via the comments, not a naming prefix (these predate any
25
+ * naming convention and renaming them is out of scope for introducing the
26
+ * catalog, only NEW codes need to follow a scoped/prefixed style, see
27
+ * `STACK_UNDERFLOW` etc. below).
28
+ */
29
+ declare const CoreErrorCodes: {
30
+ readonly INVALID_NUMBER_LITERAL: "INVALID_NUMBER_LITERAL";
31
+ readonly NO_PREFIX_PARSELET: "NO_PREFIX_PARSELET";
32
+ readonly UNEXPECTED_END_OF_INPUT: "UNEXPECTED_END_OF_INPUT";
33
+ readonly UNEXPECTED_TOKEN_TYPE: "UNEXPECTED_TOKEN_TYPE";
34
+ readonly NESTING_DEPTH_EXCEEDED: "NESTING_DEPTH_EXCEEDED";
35
+ readonly UNEXPECTED_END: "UNEXPECTED_END";
36
+ readonly UNEXPECTED_TRAILING_TOKEN: "UNEXPECTED_TRAILING_TOKEN";
37
+ readonly PARSE_ERROR: "PARSE_ERROR";
38
+ readonly TOO_MANY_NUMERIC_CONSTANTS: "TOO_MANY_NUMERIC_CONSTANTS";
39
+ readonly TOO_MANY_STRING_CONSTANTS: "TOO_MANY_STRING_CONSTANTS";
40
+ readonly NO_MATCHING_PHRASE_ALTERNATIVE: "NO_MATCHING_PHRASE_ALTERNATIVE";
41
+ readonly INVALID_PHRASE_PATTERN: "INVALID_PHRASE_PATTERN";
42
+ readonly PHRASE_KEYWORD_MISMATCH: "PHRASE_KEYWORD_MISMATCH";
43
+ /** User-defined-function definition parsing (`f(x, y) = ...`), an invalid token where a parameter name was expected. */
44
+ readonly USER_FUNCTION_INVALID_PARAM_NAME: "USER_FUNCTION_INVALID_PARAM_NAME";
45
+ /** `f() = ...` with zero parameters, indistinguishable from a plain no-arg function call, so rejected at definition time. */
46
+ readonly USER_FUNCTION_NO_PARAMS: "USER_FUNCTION_NO_PARAMS";
47
+ /** A user-defined function body calling an async plugin (weather/stocks/currency/...), rejected at definition time; v1 scope excludes async function bodies. */
48
+ readonly FUNCTION_BODY_MUST_BE_SYNCHRONOUS: "FUNCTION_BODY_MUST_BE_SYNCHRONOUS";
49
+ /** `BytecodeBuilder`'s `userFunctionBodies` side-table exceeding its capacity. Same class as `TOO_MANY_NUMERIC_CONSTANTS`/`TOO_MANY_STRING_CONSTANTS` below. */
50
+ readonly TOO_MANY_FUNCTION_DEFINITIONS: "TOO_MANY_FUNCTION_DEFINITIONS";
51
+ /** `BytecodeBuilder`'s `anonymousBodies` side-table (map/reduce inline transform bodies) exceeding its capacity. Same class as `TOO_MANY_FUNCTION_DEFINITIONS` above. */
52
+ readonly TOO_MANY_ANONYMOUS_BODIES: "TOO_MANY_ANONYMOUS_BODIES";
53
+ readonly EVALUATION_ERROR: "EVALUATION_ERROR";
54
+ readonly INSTRUCTION_LIMIT_EXCEEDED: "INSTRUCTION_LIMIT_EXCEEDED";
55
+ readonly STACK_LIMIT_EXCEEDED: "STACK_LIMIT_EXCEEDED";
56
+ /** New this phase. See `VM.ts`'s `safePop()`: a stack-underflow (corrupted bytecode, a buggy plugin) is now a controlled EngineError instead of a raw TypeError. Always `recoverable: false` (internal invariant violation). */
57
+ readonly STACK_UNDERFLOW: "STACK_UNDERFLOW";
58
+ readonly UNDEFINED_VARIABLE: "UNDEFINED_VARIABLE";
59
+ /** New this phase, the Tier-2/`LOAD_GLOBAL_VAR` hardening: a global variable read before its async preflight resolved, surfaced as a controlled error instead of pushing `undefined`. */
60
+ readonly GLOBAL_VARIABLE_NOT_RESOLVED: "GLOBAL_VARIABLE_NOT_RESOLVED";
61
+ readonly UNKNOWN_FUNCTION: "UNKNOWN_FUNCTION";
62
+ /** `unwrapEvalResult()`'s pending-when-expecting-value case, a caller-contract violation, not user-input. */
63
+ readonly UNEXPECTED_PENDING_RESULT: "UNEXPECTED_PENDING_RESULT";
64
+ /** User-defined-function call/definition errors (`CALL_USER_FUNCTION`/`DEFINE_USER_FUNCTION` opcodes), calling a name with no matching definition, calling with the wrong argument count, and the deliberate v1 restriction that a function body can't itself contain async work. */
65
+ readonly UNDEFINED_FUNCTION: "UNDEFINED_FUNCTION";
66
+ readonly FUNCTION_ARITY_MISMATCH: "FUNCTION_ARITY_MISMATCH";
67
+ readonly USER_FUNCTION_ASYNC_UNSUPPORTED: "USER_FUNCTION_ASYNC_UNSUPPORTED";
68
+ /** A map/reduce transform body (inline expression or user-defined function) calling an async plugin. Same v1 scope restriction as `USER_FUNCTION_ASYNC_UNSUPPORTED` above, enforced both at parse time (`MAP_REDUCE_TRANSFORM_MUST_BE_SYNCHRONOUS`, packages/mapreduce/) and as a defense-in-depth runtime backstop here. */
69
+ readonly MAP_REDUCE_ASYNC_UNSUPPORTED: "MAP_REDUCE_ASYNC_UNSUPPORTED";
70
+ /** `pushCallFrame()`'s recursion guard, a nested `CALL_USER_FUNCTION` re-enters `executeBytecode()`, so `maxInstructions` alone can't catch e.g. `f(x) = f(x)`; this is the dedicated backstop. `recoverable: true` (the default for `.execution()`), ordinary user-written infinite recursion, not an engine bug; the guard exists precisely so it surfaces as a clear error instead of overflowing the native call stack uncatchably. */
71
+ readonly FUNCTION_RECURSION_LIMIT_EXCEEDED: "FUNCTION_RECURSION_LIMIT_EXCEEDED";
72
+ /** `DEFINE_USER_FUNCTION`'s body-index lookup failing, a compiler/VM invariant violation (the opcode stream referenced a `userFunctionBodies` slot that doesn't exist), never a user-input error. */
73
+ readonly INTERNAL_MISSING_FUNCTION_BODY: "INTERNAL_MISSING_FUNCTION_BODY";
74
+ /** `MAP_INVOKE`/`REDUCE_INVOKE`'s anonymous-body-index lookup failing. Same class as `INTERNAL_MISSING_FUNCTION_BODY` above, for the `anonymousBodies` side-table instead of `userFunctionBodies`. */
75
+ readonly INTERNAL_MISSING_ANONYMOUS_BODY: "INTERNAL_MISSING_ANONYMOUS_BODY";
76
+ /** A coefficient grew past `RATIONAL_MAX_BITS`, e.g. repeated exact elimination multiplying denominators together. */
77
+ readonly SYMBOLIC_RATIONAL_OVERFLOW: "SYMBOLIC_RATIONAL_OVERFLOW";
78
+ /** `NaN` or `±Infinity` reaching a symbolic expression, neither of which has an exact rational value. */
79
+ readonly SYMBOLIC_NONFINITE_OPERAND: "SYMBOLIC_NONFINITE_OPERAND";
80
+ /** Division by an exactly-zero rational. Exact, unlike the double comparison it replaced, which could not distinguish a true zero from `5.551e-17`. */
81
+ readonly SYMBOLIC_DIVISION_BY_ZERO: "SYMBOLIC_DIVISION_BY_ZERO";
82
+ /** A tree exceeding `SYMBOLIC_MAX_NODES` entering the simplifier. */
83
+ readonly SYMBOLIC_NODE_LIMIT_EXCEEDED: "SYMBOLIC_NODE_LIMIT_EXCEEDED";
84
+ /** A builtin with no symbolic reading (`min`, `random`, the finance block, ...) applied to an expression still containing an unknown. Returned rather than computing against `toNumber()`'s placeholder zero. */
85
+ readonly SYMBOLIC_UNSUPPORTED_FUNCTION: "SYMBOLIC_UNSUPPORTED_FUNCTION";
86
+ /** The rational-root search exceeding `FACTOR_MAX_ROOT_CANDIDATES`. The candidate set is the product of two divisor sets, so a highly-composite coefficient escapes quickly. */
87
+ readonly SYMBOLIC_FACTOR_LIMIT_EXCEEDED: "SYMBOLIC_FACTOR_LIMIT_EXCEEDED";
88
+ /** An equation outside what the solver attempts: not a polynomial, above the degree ceiling, or non-linear in the unknown while another unknown is present. */
89
+ readonly SYMBOLIC_SOLVE_UNSUPPORTED: "SYMBOLIC_SOLVE_UNSUPPORTED";
90
+ /** `solve`'s second argument not being a bare name. */
91
+ readonly SOLVE_REQUIRES_VARIABLE_NAME: "SOLVE_REQUIRES_VARIABLE_NAME";
92
+ /** A derivative order outside 0..`DERIVATIVE_MAX_ORDER`. */
93
+ readonly SYMBOLIC_DERIVATIVE_ORDER_LIMIT: "SYMBOLIC_DERIVATIVE_ORDER_LIMIT";
94
+ /** An expression with no known elementary antiderivative. Reported rather than approximated, since a wrong integral is indistinguishable from a right one at the point of use. */
95
+ readonly SYMBOLIC_INTEGRAL_UNSUPPORTED: "SYMBOLIC_INTEGRAL_UNSUPPORTED";
96
+ /** A Taylor degree outside 0..`TAYLOR_MAX_DEGREE`. */
97
+ readonly SYMBOLIC_TAYLOR_DEGREE_LIMIT: "SYMBOLIC_TAYLOR_DEGREE_LIMIT";
98
+ /** A Taylor coefficient that does not reduce to an exact number at the expansion point. */
99
+ readonly SYMBOLIC_TAYLOR_INEXACT: "SYMBOLIC_TAYLOR_INEXACT";
100
+ /** An algebra verb's variable-name argument not being a bare name. */
101
+ readonly SYMBOLIC_REQUIRES_VARIABLE_NAME: "SYMBOLIC_REQUIRES_VARIABLE_NAME";
102
+ /** `jacobian` called with expressions containing no unknown to differentiate against. */
103
+ readonly SYMBOLIC_JACOBIAN_NO_VARIABLES: "SYMBOLIC_JACOBIAN_NO_VARIABLES";
104
+ /** A finite number whose decimal form could not be read back, which the regex covering every `Number.prototype.toString` output should make unreachable. */
105
+ readonly INTERNAL_RATIONAL_PARSE: "INTERNAL_RATIONAL_PARSE";
106
+ readonly EXPRESSION_TOO_LONG: "EXPRESSION_TOO_LONG";
107
+ readonly EXPRESSION_TOO_COMPLEX: "EXPRESSION_TOO_COMPLEX";
108
+ readonly NORMALIZED_TOKEN_LIMIT_EXCEEDED: "NORMALIZED_TOKEN_LIMIT_EXCEEDED";
109
+ /** `"=>"` with nothing before it, needs an expression or variable name to solve/simplify. */
110
+ readonly THEREFORE_REQUIRES_EXPRESSION: "THEREFORE_REQUIRES_EXPRESSION";
111
+ /** A `"=>"`-triggered expression called an async plugin (weather/stocks/currency). Same v1 scope restriction as user-function/map-reduce bodies. */
112
+ readonly THEREFORE_ASYNC_UNSUPPORTED: "THEREFORE_ASYNC_UNSUPPORTED";
113
+ readonly CONFIG_PATH_NOT_FOUND: "CONFIG_PATH_NOT_FOUND";
114
+ readonly INVALID_CONFIG_PATH: "INVALID_CONFIG_PATH";
115
+ readonly CONFIG_SECTION_NOT_FOUND: "CONFIG_SECTION_NOT_FOUND";
116
+ readonly CONFIG_PROPERTY_NOT_FOUND: "CONFIG_PROPERTY_NOT_FOUND";
117
+ readonly PLUGIN_OPERATOR_COLLISION: "PLUGIN_OPERATOR_COLLISION";
118
+ readonly PLUGIN_KEYWORD_COLLISION: "PLUGIN_KEYWORD_COLLISION";
119
+ readonly PLUGIN_UNIT_COLLISION: "PLUGIN_UNIT_COLLISION";
120
+ /** A package's declared `IEnginePackage.engineVersion` semver range doesn't satisfy the running engine's ENGINE_VERSION. See api/EngineVersionCompatibility.ts. */
121
+ readonly PACKAGE_ENGINE_VERSION_MISMATCH: "PACKAGE_ENGINE_VERSION_MISMATCH";
122
+ /** A package's declared `IEnginePackage.engineVersion` isn't a parseable semver range at all (a typo in the package's own descriptor). */
123
+ readonly PACKAGE_ENGINE_VERSION_INVALID_RANGE: "PACKAGE_ENGINE_VERSION_INVALID_RANGE";
124
+ /** `OpRegistry.allocateOpcode()`'s dynamic opcode pool (started at 201) exhausted, too many packages calling it. */
125
+ readonly OPCODE_POOL_EXHAUSTED: "OPCODE_POOL_EXHAUSTED";
126
+ /** `VMBuiltins.allocatePluginFunctionIndex()`'s 0-255 index pool (a single opcode-stream byte) exhausted. */
127
+ readonly PLUGIN_FUNCTION_INDEX_POOL_EXHAUSTED: "PLUGIN_FUNCTION_INDEX_POOL_EXHAUSTED";
128
+ readonly INVALID_RATE_UNIT: "INVALID_RATE_UNIT";
129
+ readonly INVALID_TIMECODE_UNIT: "INVALID_TIMECODE_UNIT";
130
+ readonly UNEXPECTED_ERROR: "UNEXPECTED_ERROR";
131
+ readonly UNKNOWN_ERROR: "UNKNOWN_ERROR";
132
+ };
133
+ /** Every error code the engine's own layers can produce, from {@link CoreErrorCodes}. */
134
+ type CoreErrorCode = (typeof CoreErrorCodes)[keyof typeof CoreErrorCodes];
135
+ /**
136
+ * The aggregated catalog type. Currently just `CoreErrorCode`, union in
137
+ * each package's own code-object type here as Phase 5 converts it, e.g.
138
+ * `CoreErrorCode | WeatherErrorCode | StocksErrorCode | ...`.
139
+ */
140
+ type ErrorCode = CoreErrorCode;
141
+
142
+ /**
143
+ * The engine's structured error type, the "Rust/Go-style, verbose, easy to
144
+ * tell the issue" half of the error-handling redesign (the other half is
145
+ * `Result.ts`).
146
+ *
147
+ * Historical note: an earlier version of this class (`UnifiedErrorFramework.ts`,
148
+ * still the import path most of the codebase uses. See that file, now a
149
+ * pure re-export barrel) had a much larger field set (`severity`,
150
+ * `recovery`, a 5-value enum, `ErrorRecoveryManager`) that was almost
151
+ * entirely dead: nothing downstream ever read `.severity`/`.recovery`,
152
+ * only `.message` reliably survived to a caller. This version is smaller
153
+ * and deliberately keeps only fields something actually consumes.
154
+ */
155
+
156
+ /** A character-offset (and optional line/col) span into the original expression text, for a future "underline the offending token" UI, not yet wired to one. */
157
+ interface SourceSpan {
158
+ start: number;
159
+ end: number;
160
+ line?: number;
161
+ col?: number;
162
+ }
163
+ /**
164
+ * Error classification, kept from the original framework, now actually
165
+ * consulted: it's the `format()` header and lets host code group errors
166
+ * by pipeline stage without string-matching `.code`.
167
+ */
168
+ declare enum ErrorCategory {
169
+ /** Errors during expression parsing. */
170
+ PARSING = "PARSING",
171
+ /** Errors during bytecode execution. */
172
+ EXECUTION = "EXECUTION",
173
+ /** Errors from input validation (safety limits, config). */
174
+ VALIDATION = "VALIDATION",
175
+ /** Errors from external services/APIs (currency rates, weather, stocks). */
176
+ EXTERNAL = "EXTERNAL",
177
+ /** Internal engine invariant violations. See `recoverable`'s doc comment. */
178
+ INTERNAL = "INTERNAL",
179
+ /** Configuration errors. */
180
+ CONFIG = "CONFIG"
181
+ }
182
+ /** Fields accepted when constructing an {@link EngineError}. */
183
+ interface EngineErrorInit {
184
+ /** Catalog code. See `errors/ErrorCode.ts`. Not a free string: every code used by a BUILT-IN package should be registered there so `ErrorCodeCatalog.spec.ts` can catch collisions/typos. Third-party packages may still use any string here, `EngineError.code`'s runtime type is `string`. */
185
+ code: ErrorCode | (string & {});
186
+ /** Short, single-line, `Error.message`-compatible. Existing `.toThrow(/pattern/)`/`.message` assertions keep working against this field, richer detail goes in `expected`/`found`/`suggestion`, not crammed into this string. */
187
+ message: string;
188
+ /** What the parser/validator/VM expected to see, in plain words, e.g. "a city name", "a 4-digit year", "end of expression". */
189
+ expected?: string;
190
+ /** What was actually found instead, e.g. "end of expression", `NUMBER "5"`, the offending token's literal text. */
191
+ found?: string;
192
+ /** An actionable, worked-example fix, e.g. `e.g. "weather in London"`. Mirrors this codebase's best existing messages (`WEATHER_EXPECTED_CITY`, `AS_CONVERTER_EXPECTED_NAME`). */
193
+ suggestion?: string;
194
+ /**
195
+ * `true` (the default) for every EXPECTED failure mode of user input or
196
+ * environment, bad syntax, an unknown variable/function, a safety limit
197
+ * exceeded, an external API being down. `false` is reserved for genuine
198
+ * ENGINE-INTERNAL invariant violations (corrupted bytecode, a stack
199
+ * underflow from a buggy plugin, an "impossible" state)
200
+ * `ErrorFactory.internal()`/`.config()` default to `false`, every other
201
+ * factory method defaults to `true`.
202
+ *
203
+ * This does NOT gate "does evaluation of the rest of the document
204
+ * continue", with this engine's per-line containment, it always does
205
+ * even for a `recoverable: false` error (see `ARCHITECTURE.md`'s
206
+ * async-batcher/Tier-2 hardening notes). It gates MESSAGE FRAMING and
207
+ * telemetry: "fix your syntax" vs. "this is an engine bug, worth
208
+ * reporting". See `EngineError.isFatal()`.
209
+ */
210
+ recoverable?: boolean;
211
+ /** Character-offset span into the source expression, when available. Not yet threaded through every call site, populate opportunistically, don't block on retrofitting every existing throw site. */
212
+ span?: SourceSpan;
213
+ /** Free-form structured context. The one field the pre-existing framework's real consumer (`ThreeTierEvaluator.ts`'s DAG-preservation-on-compile-error path) actually reads, kept name- and shape-compatible on purpose. */
214
+ context?: Record<string, unknown>;
215
+ /** The underlying error this one wraps, if any, passed straight through to native `Error.cause` (ES2022), so Node's default printer, most loggers, and `instanceof Error` tooling understand the chain for free. */
216
+ cause?: unknown;
217
+ }
218
+ /**
219
+ * The engine's structured error type. Still a real `Error` subclass (so
220
+ * `throw`/`catch`/`instanceof Error` all keep working exactly as before),
221
+ * but now every field except the removed `severity`/`recovery` pair is
222
+ * something real code reads.
223
+ */
224
+ declare class EngineError extends Error {
225
+ readonly category: ErrorCategory;
226
+ readonly code: string;
227
+ readonly expected?: string;
228
+ readonly found?: string;
229
+ readonly suggestion?: string;
230
+ readonly recoverable: boolean;
231
+ readonly span?: SourceSpan;
232
+ readonly context?: Record<string, unknown>;
233
+ readonly timestamp: Date;
234
+ /**
235
+ * Set explicitly (not via `super(message, {cause})`). This repo's
236
+ * `tsconfig.json` targets ES6/ES5-ES7 lib, which predates TypeScript's
237
+ * ES2022 `Error` constructor `cause`-option overload. `Error.prototype.cause`
238
+ * is still a real runtime feature in every target this engine actually
239
+ * runs in (Node 16.9+, all evergreen browsers, Electron/Obsidian's
240
+ * bundled Chromium) regardless of the TS lib target used to type-check
241
+ * against it, assigning it directly gets the same Node-printer/logger
242
+ * interop with no build-config change needed.
243
+ */
244
+ readonly cause?: unknown;
245
+ constructor(category: ErrorCategory, init: EngineErrorInit);
246
+ /** `!recoverable`. See `EngineErrorInit.recoverable`'s doc comment for what this actually gates (message framing/telemetry, not whether evaluation continues). */
247
+ isFatal(): boolean;
248
+ /** Walk `.cause` repeatedly, collecting the full chain (this error first). */
249
+ causeChain(): unknown[];
250
+ /**
251
+ * Rust/Go-style multi-line renderer, the NEW thing a host/CLI/test
252
+ * reaches for when it wants the full, verbose picture, as distinct from
253
+ * `.message` (kept short and stable for existing assertions). Example:
254
+ *
255
+ * ```
256
+ * error[WEATHER_EXPECTED_CITY]: Expected a city name after "weather in"
257
+ * expected: a city name
258
+ * found: end of expression
259
+ * suggestion: e.g. "weather in London"
260
+ * ```
261
+ */
262
+ format(): string;
263
+ toJSON(): Record<string, unknown>;
264
+ }
265
+ /**
266
+ * Factory for creating classified `EngineError`s. Every method accepts
267
+ * EITHER the original, minimal 3-arg shape (`code, message, context?`
268
+ * every existing call site across the codebase keeps compiling unchanged)
269
+ * OR the richer `EngineErrorInit` object (for `expected`/`found`/
270
+ * `suggestion`/`recoverable`/`span`/`cause`), upgrade a call site to the
271
+ * richer form only when you're already touching it, no separate churn
272
+ * pass required.
273
+ */
274
+ declare class ErrorFactory {
275
+ private static build;
276
+ static validation(code: string, message: string, context?: Record<string, unknown>): EngineError;
277
+ static validation(init: EngineErrorInit): EngineError;
278
+ static parsing(code: string, message: string, context?: Record<string, unknown>): EngineError;
279
+ static parsing(init: EngineErrorInit): EngineError;
280
+ static execution(code: string, message: string, context?: Record<string, unknown>): EngineError;
281
+ static execution(init: EngineErrorInit): EngineError;
282
+ static external(code: string, message: string, context?: Record<string, unknown>): EngineError;
283
+ static external(init: EngineErrorInit): EngineError;
284
+ /** Defaults `recoverable: false`, reserve for genuine engine-internal invariant violations, not user-input errors. */
285
+ static internal(code: string, message: string, context?: Record<string, unknown>): EngineError;
286
+ static internal(init: EngineErrorInit): EngineError;
287
+ /** Defaults `recoverable: false`, a bad config is an environment-setup problem, not a per-line user-input error. */
288
+ static config(code: string, message: string, context?: Record<string, unknown>): EngineError;
289
+ static config(init: EngineErrorInit): EngineError;
290
+ }
291
+ /**
292
+ * Normalize any thrown value into an `EngineError`, an `EngineError`
293
+ * passes through as-is; a plain `Error` gets wrapped (message preserved,
294
+ * original attached via `cause`); anything else becomes a generic
295
+ * "unknown error" wrapping the stringified value. Used at every
296
+ * throw-space/Result-space boundary (`Result.tryCatch`'s default
297
+ * `normalize`, the VM's outer execution try/catch, `AsyncResolutionBatcher`'s
298
+ * per-line containment) so a raw `TypeError` from a genuine engine bug
299
+ * still surfaces as a structured, catalogued error instead of an opaque
300
+ * uncaught exception.
301
+ */
302
+ declare function normalizeUnknownError(error: unknown): EngineError;
303
+
304
+ export { type CoreErrorCode as C, EngineError as E, type SourceSpan as S, CoreErrorCodes as a, type EngineErrorInit as b, ErrorCategory as c, type ErrorCode as d, ErrorFactory as e, normalizeUnknownError as n };
@@ -0,0 +1,304 @@
1
+ /**
2
+ * The built-in error-code catalog, one typed const object per domain
3
+ * unioned together here for autocomplete/exhaustiveness in core engine
4
+ * code. Deliberately NOT one central enum: `IEnginePackage` is documented
5
+ * public SDK surface for third-party packages (see `api/PackageRegistry.ts`),
6
+ * and a closed enum would block an external package author from defining
7
+ * their own codes without editing this file. `EngineError.code`'s runtime
8
+ * type stays `string` for exactly that reason. This catalog is for the
9
+ * codes THIS repo owns and wants collision/typo checking on (see
10
+ * `__tests__/errors/ErrorCodeCatalog.spec.ts`), not a hard runtime
11
+ * whitelist.
12
+ *
13
+ * As each package migrates to `Result<void, EngineError>` (see this
14
+ * session's error-handling-refactor plan, Phase 5), it should export its
15
+ * own small `XxxErrorCodes` const object co-located with its parselets
16
+ * exactly like `CoreErrorCodes` below, just scoped to one domain, and get
17
+ * unioned into `ErrorCode` here. Until a package migrates, its existing
18
+ * free-string codes keep working (ErrorFactory accepts any string); they
19
+ * just aren't caught by the catalog's uniqueness/orphan checks yet.
20
+ */
21
+ /**
22
+ * Codes used directly by the parser/VM/engine/errors layers themselves
23
+ * confirmed against the current source, not aspirational. Grouped by
24
+ * pipeline stage via the comments, not a naming prefix (these predate any
25
+ * naming convention and renaming them is out of scope for introducing the
26
+ * catalog, only NEW codes need to follow a scoped/prefixed style, see
27
+ * `STACK_UNDERFLOW` etc. below).
28
+ */
29
+ declare const CoreErrorCodes: {
30
+ readonly INVALID_NUMBER_LITERAL: "INVALID_NUMBER_LITERAL";
31
+ readonly NO_PREFIX_PARSELET: "NO_PREFIX_PARSELET";
32
+ readonly UNEXPECTED_END_OF_INPUT: "UNEXPECTED_END_OF_INPUT";
33
+ readonly UNEXPECTED_TOKEN_TYPE: "UNEXPECTED_TOKEN_TYPE";
34
+ readonly NESTING_DEPTH_EXCEEDED: "NESTING_DEPTH_EXCEEDED";
35
+ readonly UNEXPECTED_END: "UNEXPECTED_END";
36
+ readonly UNEXPECTED_TRAILING_TOKEN: "UNEXPECTED_TRAILING_TOKEN";
37
+ readonly PARSE_ERROR: "PARSE_ERROR";
38
+ readonly TOO_MANY_NUMERIC_CONSTANTS: "TOO_MANY_NUMERIC_CONSTANTS";
39
+ readonly TOO_MANY_STRING_CONSTANTS: "TOO_MANY_STRING_CONSTANTS";
40
+ readonly NO_MATCHING_PHRASE_ALTERNATIVE: "NO_MATCHING_PHRASE_ALTERNATIVE";
41
+ readonly INVALID_PHRASE_PATTERN: "INVALID_PHRASE_PATTERN";
42
+ readonly PHRASE_KEYWORD_MISMATCH: "PHRASE_KEYWORD_MISMATCH";
43
+ /** User-defined-function definition parsing (`f(x, y) = ...`), an invalid token where a parameter name was expected. */
44
+ readonly USER_FUNCTION_INVALID_PARAM_NAME: "USER_FUNCTION_INVALID_PARAM_NAME";
45
+ /** `f() = ...` with zero parameters, indistinguishable from a plain no-arg function call, so rejected at definition time. */
46
+ readonly USER_FUNCTION_NO_PARAMS: "USER_FUNCTION_NO_PARAMS";
47
+ /** A user-defined function body calling an async plugin (weather/stocks/currency/...), rejected at definition time; v1 scope excludes async function bodies. */
48
+ readonly FUNCTION_BODY_MUST_BE_SYNCHRONOUS: "FUNCTION_BODY_MUST_BE_SYNCHRONOUS";
49
+ /** `BytecodeBuilder`'s `userFunctionBodies` side-table exceeding its capacity. Same class as `TOO_MANY_NUMERIC_CONSTANTS`/`TOO_MANY_STRING_CONSTANTS` below. */
50
+ readonly TOO_MANY_FUNCTION_DEFINITIONS: "TOO_MANY_FUNCTION_DEFINITIONS";
51
+ /** `BytecodeBuilder`'s `anonymousBodies` side-table (map/reduce inline transform bodies) exceeding its capacity. Same class as `TOO_MANY_FUNCTION_DEFINITIONS` above. */
52
+ readonly TOO_MANY_ANONYMOUS_BODIES: "TOO_MANY_ANONYMOUS_BODIES";
53
+ readonly EVALUATION_ERROR: "EVALUATION_ERROR";
54
+ readonly INSTRUCTION_LIMIT_EXCEEDED: "INSTRUCTION_LIMIT_EXCEEDED";
55
+ readonly STACK_LIMIT_EXCEEDED: "STACK_LIMIT_EXCEEDED";
56
+ /** New this phase. See `VM.ts`'s `safePop()`: a stack-underflow (corrupted bytecode, a buggy plugin) is now a controlled EngineError instead of a raw TypeError. Always `recoverable: false` (internal invariant violation). */
57
+ readonly STACK_UNDERFLOW: "STACK_UNDERFLOW";
58
+ readonly UNDEFINED_VARIABLE: "UNDEFINED_VARIABLE";
59
+ /** New this phase, the Tier-2/`LOAD_GLOBAL_VAR` hardening: a global variable read before its async preflight resolved, surfaced as a controlled error instead of pushing `undefined`. */
60
+ readonly GLOBAL_VARIABLE_NOT_RESOLVED: "GLOBAL_VARIABLE_NOT_RESOLVED";
61
+ readonly UNKNOWN_FUNCTION: "UNKNOWN_FUNCTION";
62
+ /** `unwrapEvalResult()`'s pending-when-expecting-value case, a caller-contract violation, not user-input. */
63
+ readonly UNEXPECTED_PENDING_RESULT: "UNEXPECTED_PENDING_RESULT";
64
+ /** User-defined-function call/definition errors (`CALL_USER_FUNCTION`/`DEFINE_USER_FUNCTION` opcodes), calling a name with no matching definition, calling with the wrong argument count, and the deliberate v1 restriction that a function body can't itself contain async work. */
65
+ readonly UNDEFINED_FUNCTION: "UNDEFINED_FUNCTION";
66
+ readonly FUNCTION_ARITY_MISMATCH: "FUNCTION_ARITY_MISMATCH";
67
+ readonly USER_FUNCTION_ASYNC_UNSUPPORTED: "USER_FUNCTION_ASYNC_UNSUPPORTED";
68
+ /** A map/reduce transform body (inline expression or user-defined function) calling an async plugin. Same v1 scope restriction as `USER_FUNCTION_ASYNC_UNSUPPORTED` above, enforced both at parse time (`MAP_REDUCE_TRANSFORM_MUST_BE_SYNCHRONOUS`, packages/mapreduce/) and as a defense-in-depth runtime backstop here. */
69
+ readonly MAP_REDUCE_ASYNC_UNSUPPORTED: "MAP_REDUCE_ASYNC_UNSUPPORTED";
70
+ /** `pushCallFrame()`'s recursion guard, a nested `CALL_USER_FUNCTION` re-enters `executeBytecode()`, so `maxInstructions` alone can't catch e.g. `f(x) = f(x)`; this is the dedicated backstop. `recoverable: true` (the default for `.execution()`), ordinary user-written infinite recursion, not an engine bug; the guard exists precisely so it surfaces as a clear error instead of overflowing the native call stack uncatchably. */
71
+ readonly FUNCTION_RECURSION_LIMIT_EXCEEDED: "FUNCTION_RECURSION_LIMIT_EXCEEDED";
72
+ /** `DEFINE_USER_FUNCTION`'s body-index lookup failing, a compiler/VM invariant violation (the opcode stream referenced a `userFunctionBodies` slot that doesn't exist), never a user-input error. */
73
+ readonly INTERNAL_MISSING_FUNCTION_BODY: "INTERNAL_MISSING_FUNCTION_BODY";
74
+ /** `MAP_INVOKE`/`REDUCE_INVOKE`'s anonymous-body-index lookup failing. Same class as `INTERNAL_MISSING_FUNCTION_BODY` above, for the `anonymousBodies` side-table instead of `userFunctionBodies`. */
75
+ readonly INTERNAL_MISSING_ANONYMOUS_BODY: "INTERNAL_MISSING_ANONYMOUS_BODY";
76
+ /** A coefficient grew past `RATIONAL_MAX_BITS`, e.g. repeated exact elimination multiplying denominators together. */
77
+ readonly SYMBOLIC_RATIONAL_OVERFLOW: "SYMBOLIC_RATIONAL_OVERFLOW";
78
+ /** `NaN` or `±Infinity` reaching a symbolic expression, neither of which has an exact rational value. */
79
+ readonly SYMBOLIC_NONFINITE_OPERAND: "SYMBOLIC_NONFINITE_OPERAND";
80
+ /** Division by an exactly-zero rational. Exact, unlike the double comparison it replaced, which could not distinguish a true zero from `5.551e-17`. */
81
+ readonly SYMBOLIC_DIVISION_BY_ZERO: "SYMBOLIC_DIVISION_BY_ZERO";
82
+ /** A tree exceeding `SYMBOLIC_MAX_NODES` entering the simplifier. */
83
+ readonly SYMBOLIC_NODE_LIMIT_EXCEEDED: "SYMBOLIC_NODE_LIMIT_EXCEEDED";
84
+ /** A builtin with no symbolic reading (`min`, `random`, the finance block, ...) applied to an expression still containing an unknown. Returned rather than computing against `toNumber()`'s placeholder zero. */
85
+ readonly SYMBOLIC_UNSUPPORTED_FUNCTION: "SYMBOLIC_UNSUPPORTED_FUNCTION";
86
+ /** The rational-root search exceeding `FACTOR_MAX_ROOT_CANDIDATES`. The candidate set is the product of two divisor sets, so a highly-composite coefficient escapes quickly. */
87
+ readonly SYMBOLIC_FACTOR_LIMIT_EXCEEDED: "SYMBOLIC_FACTOR_LIMIT_EXCEEDED";
88
+ /** An equation outside what the solver attempts: not a polynomial, above the degree ceiling, or non-linear in the unknown while another unknown is present. */
89
+ readonly SYMBOLIC_SOLVE_UNSUPPORTED: "SYMBOLIC_SOLVE_UNSUPPORTED";
90
+ /** `solve`'s second argument not being a bare name. */
91
+ readonly SOLVE_REQUIRES_VARIABLE_NAME: "SOLVE_REQUIRES_VARIABLE_NAME";
92
+ /** A derivative order outside 0..`DERIVATIVE_MAX_ORDER`. */
93
+ readonly SYMBOLIC_DERIVATIVE_ORDER_LIMIT: "SYMBOLIC_DERIVATIVE_ORDER_LIMIT";
94
+ /** An expression with no known elementary antiderivative. Reported rather than approximated, since a wrong integral is indistinguishable from a right one at the point of use. */
95
+ readonly SYMBOLIC_INTEGRAL_UNSUPPORTED: "SYMBOLIC_INTEGRAL_UNSUPPORTED";
96
+ /** A Taylor degree outside 0..`TAYLOR_MAX_DEGREE`. */
97
+ readonly SYMBOLIC_TAYLOR_DEGREE_LIMIT: "SYMBOLIC_TAYLOR_DEGREE_LIMIT";
98
+ /** A Taylor coefficient that does not reduce to an exact number at the expansion point. */
99
+ readonly SYMBOLIC_TAYLOR_INEXACT: "SYMBOLIC_TAYLOR_INEXACT";
100
+ /** An algebra verb's variable-name argument not being a bare name. */
101
+ readonly SYMBOLIC_REQUIRES_VARIABLE_NAME: "SYMBOLIC_REQUIRES_VARIABLE_NAME";
102
+ /** `jacobian` called with expressions containing no unknown to differentiate against. */
103
+ readonly SYMBOLIC_JACOBIAN_NO_VARIABLES: "SYMBOLIC_JACOBIAN_NO_VARIABLES";
104
+ /** A finite number whose decimal form could not be read back, which the regex covering every `Number.prototype.toString` output should make unreachable. */
105
+ readonly INTERNAL_RATIONAL_PARSE: "INTERNAL_RATIONAL_PARSE";
106
+ readonly EXPRESSION_TOO_LONG: "EXPRESSION_TOO_LONG";
107
+ readonly EXPRESSION_TOO_COMPLEX: "EXPRESSION_TOO_COMPLEX";
108
+ readonly NORMALIZED_TOKEN_LIMIT_EXCEEDED: "NORMALIZED_TOKEN_LIMIT_EXCEEDED";
109
+ /** `"=>"` with nothing before it, needs an expression or variable name to solve/simplify. */
110
+ readonly THEREFORE_REQUIRES_EXPRESSION: "THEREFORE_REQUIRES_EXPRESSION";
111
+ /** A `"=>"`-triggered expression called an async plugin (weather/stocks/currency). Same v1 scope restriction as user-function/map-reduce bodies. */
112
+ readonly THEREFORE_ASYNC_UNSUPPORTED: "THEREFORE_ASYNC_UNSUPPORTED";
113
+ readonly CONFIG_PATH_NOT_FOUND: "CONFIG_PATH_NOT_FOUND";
114
+ readonly INVALID_CONFIG_PATH: "INVALID_CONFIG_PATH";
115
+ readonly CONFIG_SECTION_NOT_FOUND: "CONFIG_SECTION_NOT_FOUND";
116
+ readonly CONFIG_PROPERTY_NOT_FOUND: "CONFIG_PROPERTY_NOT_FOUND";
117
+ readonly PLUGIN_OPERATOR_COLLISION: "PLUGIN_OPERATOR_COLLISION";
118
+ readonly PLUGIN_KEYWORD_COLLISION: "PLUGIN_KEYWORD_COLLISION";
119
+ readonly PLUGIN_UNIT_COLLISION: "PLUGIN_UNIT_COLLISION";
120
+ /** A package's declared `IEnginePackage.engineVersion` semver range doesn't satisfy the running engine's ENGINE_VERSION. See api/EngineVersionCompatibility.ts. */
121
+ readonly PACKAGE_ENGINE_VERSION_MISMATCH: "PACKAGE_ENGINE_VERSION_MISMATCH";
122
+ /** A package's declared `IEnginePackage.engineVersion` isn't a parseable semver range at all (a typo in the package's own descriptor). */
123
+ readonly PACKAGE_ENGINE_VERSION_INVALID_RANGE: "PACKAGE_ENGINE_VERSION_INVALID_RANGE";
124
+ /** `OpRegistry.allocateOpcode()`'s dynamic opcode pool (started at 201) exhausted, too many packages calling it. */
125
+ readonly OPCODE_POOL_EXHAUSTED: "OPCODE_POOL_EXHAUSTED";
126
+ /** `VMBuiltins.allocatePluginFunctionIndex()`'s 0-255 index pool (a single opcode-stream byte) exhausted. */
127
+ readonly PLUGIN_FUNCTION_INDEX_POOL_EXHAUSTED: "PLUGIN_FUNCTION_INDEX_POOL_EXHAUSTED";
128
+ readonly INVALID_RATE_UNIT: "INVALID_RATE_UNIT";
129
+ readonly INVALID_TIMECODE_UNIT: "INVALID_TIMECODE_UNIT";
130
+ readonly UNEXPECTED_ERROR: "UNEXPECTED_ERROR";
131
+ readonly UNKNOWN_ERROR: "UNKNOWN_ERROR";
132
+ };
133
+ /** Every error code the engine's own layers can produce, from {@link CoreErrorCodes}. */
134
+ type CoreErrorCode = (typeof CoreErrorCodes)[keyof typeof CoreErrorCodes];
135
+ /**
136
+ * The aggregated catalog type. Currently just `CoreErrorCode`, union in
137
+ * each package's own code-object type here as Phase 5 converts it, e.g.
138
+ * `CoreErrorCode | WeatherErrorCode | StocksErrorCode | ...`.
139
+ */
140
+ type ErrorCode = CoreErrorCode;
141
+
142
+ /**
143
+ * The engine's structured error type, the "Rust/Go-style, verbose, easy to
144
+ * tell the issue" half of the error-handling redesign (the other half is
145
+ * `Result.ts`).
146
+ *
147
+ * Historical note: an earlier version of this class (`UnifiedErrorFramework.ts`,
148
+ * still the import path most of the codebase uses. See that file, now a
149
+ * pure re-export barrel) had a much larger field set (`severity`,
150
+ * `recovery`, a 5-value enum, `ErrorRecoveryManager`) that was almost
151
+ * entirely dead: nothing downstream ever read `.severity`/`.recovery`,
152
+ * only `.message` reliably survived to a caller. This version is smaller
153
+ * and deliberately keeps only fields something actually consumes.
154
+ */
155
+
156
+ /** A character-offset (and optional line/col) span into the original expression text, for a future "underline the offending token" UI, not yet wired to one. */
157
+ interface SourceSpan {
158
+ start: number;
159
+ end: number;
160
+ line?: number;
161
+ col?: number;
162
+ }
163
+ /**
164
+ * Error classification, kept from the original framework, now actually
165
+ * consulted: it's the `format()` header and lets host code group errors
166
+ * by pipeline stage without string-matching `.code`.
167
+ */
168
+ declare enum ErrorCategory {
169
+ /** Errors during expression parsing. */
170
+ PARSING = "PARSING",
171
+ /** Errors during bytecode execution. */
172
+ EXECUTION = "EXECUTION",
173
+ /** Errors from input validation (safety limits, config). */
174
+ VALIDATION = "VALIDATION",
175
+ /** Errors from external services/APIs (currency rates, weather, stocks). */
176
+ EXTERNAL = "EXTERNAL",
177
+ /** Internal engine invariant violations. See `recoverable`'s doc comment. */
178
+ INTERNAL = "INTERNAL",
179
+ /** Configuration errors. */
180
+ CONFIG = "CONFIG"
181
+ }
182
+ /** Fields accepted when constructing an {@link EngineError}. */
183
+ interface EngineErrorInit {
184
+ /** Catalog code. See `errors/ErrorCode.ts`. Not a free string: every code used by a BUILT-IN package should be registered there so `ErrorCodeCatalog.spec.ts` can catch collisions/typos. Third-party packages may still use any string here, `EngineError.code`'s runtime type is `string`. */
185
+ code: ErrorCode | (string & {});
186
+ /** Short, single-line, `Error.message`-compatible. Existing `.toThrow(/pattern/)`/`.message` assertions keep working against this field, richer detail goes in `expected`/`found`/`suggestion`, not crammed into this string. */
187
+ message: string;
188
+ /** What the parser/validator/VM expected to see, in plain words, e.g. "a city name", "a 4-digit year", "end of expression". */
189
+ expected?: string;
190
+ /** What was actually found instead, e.g. "end of expression", `NUMBER "5"`, the offending token's literal text. */
191
+ found?: string;
192
+ /** An actionable, worked-example fix, e.g. `e.g. "weather in London"`. Mirrors this codebase's best existing messages (`WEATHER_EXPECTED_CITY`, `AS_CONVERTER_EXPECTED_NAME`). */
193
+ suggestion?: string;
194
+ /**
195
+ * `true` (the default) for every EXPECTED failure mode of user input or
196
+ * environment, bad syntax, an unknown variable/function, a safety limit
197
+ * exceeded, an external API being down. `false` is reserved for genuine
198
+ * ENGINE-INTERNAL invariant violations (corrupted bytecode, a stack
199
+ * underflow from a buggy plugin, an "impossible" state)
200
+ * `ErrorFactory.internal()`/`.config()` default to `false`, every other
201
+ * factory method defaults to `true`.
202
+ *
203
+ * This does NOT gate "does evaluation of the rest of the document
204
+ * continue", with this engine's per-line containment, it always does
205
+ * even for a `recoverable: false` error (see `ARCHITECTURE.md`'s
206
+ * async-batcher/Tier-2 hardening notes). It gates MESSAGE FRAMING and
207
+ * telemetry: "fix your syntax" vs. "this is an engine bug, worth
208
+ * reporting". See `EngineError.isFatal()`.
209
+ */
210
+ recoverable?: boolean;
211
+ /** Character-offset span into the source expression, when available. Not yet threaded through every call site, populate opportunistically, don't block on retrofitting every existing throw site. */
212
+ span?: SourceSpan;
213
+ /** Free-form structured context. The one field the pre-existing framework's real consumer (`ThreeTierEvaluator.ts`'s DAG-preservation-on-compile-error path) actually reads, kept name- and shape-compatible on purpose. */
214
+ context?: Record<string, unknown>;
215
+ /** The underlying error this one wraps, if any, passed straight through to native `Error.cause` (ES2022), so Node's default printer, most loggers, and `instanceof Error` tooling understand the chain for free. */
216
+ cause?: unknown;
217
+ }
218
+ /**
219
+ * The engine's structured error type. Still a real `Error` subclass (so
220
+ * `throw`/`catch`/`instanceof Error` all keep working exactly as before),
221
+ * but now every field except the removed `severity`/`recovery` pair is
222
+ * something real code reads.
223
+ */
224
+ declare class EngineError extends Error {
225
+ readonly category: ErrorCategory;
226
+ readonly code: string;
227
+ readonly expected?: string;
228
+ readonly found?: string;
229
+ readonly suggestion?: string;
230
+ readonly recoverable: boolean;
231
+ readonly span?: SourceSpan;
232
+ readonly context?: Record<string, unknown>;
233
+ readonly timestamp: Date;
234
+ /**
235
+ * Set explicitly (not via `super(message, {cause})`). This repo's
236
+ * `tsconfig.json` targets ES6/ES5-ES7 lib, which predates TypeScript's
237
+ * ES2022 `Error` constructor `cause`-option overload. `Error.prototype.cause`
238
+ * is still a real runtime feature in every target this engine actually
239
+ * runs in (Node 16.9+, all evergreen browsers, Electron/Obsidian's
240
+ * bundled Chromium) regardless of the TS lib target used to type-check
241
+ * against it, assigning it directly gets the same Node-printer/logger
242
+ * interop with no build-config change needed.
243
+ */
244
+ readonly cause?: unknown;
245
+ constructor(category: ErrorCategory, init: EngineErrorInit);
246
+ /** `!recoverable`. See `EngineErrorInit.recoverable`'s doc comment for what this actually gates (message framing/telemetry, not whether evaluation continues). */
247
+ isFatal(): boolean;
248
+ /** Walk `.cause` repeatedly, collecting the full chain (this error first). */
249
+ causeChain(): unknown[];
250
+ /**
251
+ * Rust/Go-style multi-line renderer, the NEW thing a host/CLI/test
252
+ * reaches for when it wants the full, verbose picture, as distinct from
253
+ * `.message` (kept short and stable for existing assertions). Example:
254
+ *
255
+ * ```
256
+ * error[WEATHER_EXPECTED_CITY]: Expected a city name after "weather in"
257
+ * expected: a city name
258
+ * found: end of expression
259
+ * suggestion: e.g. "weather in London"
260
+ * ```
261
+ */
262
+ format(): string;
263
+ toJSON(): Record<string, unknown>;
264
+ }
265
+ /**
266
+ * Factory for creating classified `EngineError`s. Every method accepts
267
+ * EITHER the original, minimal 3-arg shape (`code, message, context?`
268
+ * every existing call site across the codebase keeps compiling unchanged)
269
+ * OR the richer `EngineErrorInit` object (for `expected`/`found`/
270
+ * `suggestion`/`recoverable`/`span`/`cause`), upgrade a call site to the
271
+ * richer form only when you're already touching it, no separate churn
272
+ * pass required.
273
+ */
274
+ declare class ErrorFactory {
275
+ private static build;
276
+ static validation(code: string, message: string, context?: Record<string, unknown>): EngineError;
277
+ static validation(init: EngineErrorInit): EngineError;
278
+ static parsing(code: string, message: string, context?: Record<string, unknown>): EngineError;
279
+ static parsing(init: EngineErrorInit): EngineError;
280
+ static execution(code: string, message: string, context?: Record<string, unknown>): EngineError;
281
+ static execution(init: EngineErrorInit): EngineError;
282
+ static external(code: string, message: string, context?: Record<string, unknown>): EngineError;
283
+ static external(init: EngineErrorInit): EngineError;
284
+ /** Defaults `recoverable: false`, reserve for genuine engine-internal invariant violations, not user-input errors. */
285
+ static internal(code: string, message: string, context?: Record<string, unknown>): EngineError;
286
+ static internal(init: EngineErrorInit): EngineError;
287
+ /** Defaults `recoverable: false`, a bad config is an environment-setup problem, not a per-line user-input error. */
288
+ static config(code: string, message: string, context?: Record<string, unknown>): EngineError;
289
+ static config(init: EngineErrorInit): EngineError;
290
+ }
291
+ /**
292
+ * Normalize any thrown value into an `EngineError`, an `EngineError`
293
+ * passes through as-is; a plain `Error` gets wrapped (message preserved,
294
+ * original attached via `cause`); anything else becomes a generic
295
+ * "unknown error" wrapping the stringified value. Used at every
296
+ * throw-space/Result-space boundary (`Result.tryCatch`'s default
297
+ * `normalize`, the VM's outer execution try/catch, `AsyncResolutionBatcher`'s
298
+ * per-line containment) so a raw `TypeError` from a genuine engine bug
299
+ * still surfaces as a structured, catalogued error instead of an opaque
300
+ * uncaught exception.
301
+ */
302
+ declare function normalizeUnknownError(error: unknown): EngineError;
303
+
304
+ export { type CoreErrorCode as C, EngineError as E, type SourceSpan as S, CoreErrorCodes as a, type EngineErrorInit as b, ErrorCategory as c, type ErrorCode as d, ErrorFactory as e, normalizeUnknownError as n };