@rcrsr/rill 0.5.0 → 0.6.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 (240) hide show
  1. package/dist/generated/introspection-data.d.ts +1 -1
  2. package/dist/generated/introspection-data.d.ts.map +1 -1
  3. package/dist/generated/introspection-data.js +107 -186
  4. package/dist/generated/introspection-data.js.map +1 -1
  5. package/dist/generated/version-data.d.ts +1 -1
  6. package/dist/generated/version-data.js +3 -3
  7. package/dist/generated/version-data.js.map +1 -1
  8. package/dist/highlight-map.d.ts +4 -0
  9. package/dist/highlight-map.d.ts.map +1 -0
  10. package/dist/highlight-map.js +71 -0
  11. package/dist/highlight-map.js.map +1 -0
  12. package/dist/index.d.ts +2 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +5 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/lexer/errors.d.ts.map +1 -1
  17. package/dist/lexer/errors.js +9 -3
  18. package/dist/lexer/errors.js.map +1 -1
  19. package/dist/lexer/operators.js +1 -1
  20. package/dist/lexer/tokenizer.d.ts.map +1 -1
  21. package/dist/lexer/tokenizer.js +0 -14
  22. package/dist/lexer/tokenizer.js.map +1 -1
  23. package/dist/parser/helpers.d.ts +8 -0
  24. package/dist/parser/helpers.d.ts.map +1 -1
  25. package/dist/parser/helpers.js +4 -4
  26. package/dist/parser/helpers.js.map +1 -1
  27. package/dist/parser/index.d.ts.map +1 -1
  28. package/dist/parser/index.js +1 -1
  29. package/dist/parser/index.js.map +1 -1
  30. package/dist/parser/parser-collect.js +1 -1
  31. package/dist/parser/parser-collect.js.map +1 -1
  32. package/dist/parser/parser-control.js +4 -4
  33. package/dist/parser/parser-control.js.map +1 -1
  34. package/dist/parser/parser-expr.js +32 -10
  35. package/dist/parser/parser-expr.js.map +1 -1
  36. package/dist/parser/parser-extract.js +7 -3
  37. package/dist/parser/parser-extract.js.map +1 -1
  38. package/dist/parser/parser-functions.d.ts.map +1 -1
  39. package/dist/parser/parser-functions.js +7 -18
  40. package/dist/parser/parser-functions.js.map +1 -1
  41. package/dist/parser/parser-literals.js +15 -15
  42. package/dist/parser/parser-literals.js.map +1 -1
  43. package/dist/parser/parser-script.js +3 -3
  44. package/dist/parser/parser-script.js.map +1 -1
  45. package/dist/parser/parser-variables.js +4 -4
  46. package/dist/parser/parser-variables.js.map +1 -1
  47. package/dist/parser/state.d.ts +1 -1
  48. package/dist/parser/state.d.ts.map +1 -1
  49. package/dist/parser/state.js +2 -2
  50. package/dist/parser/state.js.map +1 -1
  51. package/dist/runtime/core/callable.d.ts +20 -0
  52. package/dist/runtime/core/callable.d.ts.map +1 -1
  53. package/dist/runtime/core/callable.js +30 -7
  54. package/dist/runtime/core/callable.js.map +1 -1
  55. package/dist/runtime/core/context.d.ts +21 -0
  56. package/dist/runtime/core/context.d.ts.map +1 -1
  57. package/dist/runtime/core/context.js +75 -4
  58. package/dist/runtime/core/context.js.map +1 -1
  59. package/dist/runtime/core/eval/base.d.ts.map +1 -1
  60. package/dist/runtime/core/eval/base.js +3 -3
  61. package/dist/runtime/core/eval/base.js.map +1 -1
  62. package/dist/runtime/core/eval/index.d.ts.map +1 -1
  63. package/dist/runtime/core/eval/index.js +2 -0
  64. package/dist/runtime/core/eval/index.js.map +1 -1
  65. package/dist/runtime/core/eval/mixins/annotations.js +3 -3
  66. package/dist/runtime/core/eval/mixins/annotations.js.map +1 -1
  67. package/dist/runtime/core/eval/mixins/closures.d.ts.map +1 -1
  68. package/dist/runtime/core/eval/mixins/closures.js +69 -40
  69. package/dist/runtime/core/eval/mixins/closures.js.map +1 -1
  70. package/dist/runtime/core/eval/mixins/collections.js +15 -15
  71. package/dist/runtime/core/eval/mixins/collections.js.map +1 -1
  72. package/dist/runtime/core/eval/mixins/control-flow.d.ts.map +1 -1
  73. package/dist/runtime/core/eval/mixins/control-flow.js +12 -12
  74. package/dist/runtime/core/eval/mixins/control-flow.js.map +1 -1
  75. package/dist/runtime/core/eval/mixins/core.d.ts.map +1 -1
  76. package/dist/runtime/core/eval/mixins/core.js +12 -13
  77. package/dist/runtime/core/eval/mixins/core.js.map +1 -1
  78. package/dist/runtime/core/eval/mixins/expressions.js +9 -9
  79. package/dist/runtime/core/eval/mixins/expressions.js.map +1 -1
  80. package/dist/runtime/core/eval/mixins/extraction.d.ts.map +1 -1
  81. package/dist/runtime/core/eval/mixins/extraction.js +15 -15
  82. package/dist/runtime/core/eval/mixins/extraction.js.map +1 -1
  83. package/dist/runtime/core/eval/mixins/literals.js +22 -22
  84. package/dist/runtime/core/eval/mixins/literals.js.map +1 -1
  85. package/dist/runtime/core/eval/mixins/types.js +4 -4
  86. package/dist/runtime/core/eval/mixins/types.js.map +1 -1
  87. package/dist/runtime/core/eval/mixins/variables.js +34 -34
  88. package/dist/runtime/core/eval/mixins/variables.js.map +1 -1
  89. package/dist/runtime/core/execute.js +3 -3
  90. package/dist/runtime/core/execute.js.map +1 -1
  91. package/dist/runtime/core/introspection.d.ts +30 -1
  92. package/dist/runtime/core/introspection.d.ts.map +1 -1
  93. package/dist/runtime/core/introspection.js +47 -1
  94. package/dist/runtime/core/introspection.js.map +1 -1
  95. package/dist/runtime/core/types.d.ts +11 -0
  96. package/dist/runtime/core/types.d.ts.map +1 -1
  97. package/dist/runtime/core/types.js.map +1 -1
  98. package/dist/runtime/ext/builtins.js +22 -22
  99. package/dist/runtime/ext/builtins.js.map +1 -1
  100. package/dist/runtime/ext/extensions.d.ts +1 -1
  101. package/dist/runtime/ext/extensions.d.ts.map +1 -1
  102. package/dist/runtime/ext/extensions.js +4 -5
  103. package/dist/runtime/ext/extensions.js.map +1 -1
  104. package/dist/runtime/index.d.ts +6 -4
  105. package/dist/runtime/index.d.ts.map +1 -1
  106. package/dist/runtime/index.js +3 -2
  107. package/dist/runtime/index.js.map +1 -1
  108. package/dist/types.d.ts +36 -37
  109. package/dist/types.d.ts.map +1 -1
  110. package/dist/types.js +440 -120
  111. package/dist/types.js.map +1 -1
  112. package/package.json +7 -66
  113. package/README.md +0 -223
  114. package/dist/check/config.d.ts +0 -20
  115. package/dist/check/config.d.ts.map +0 -1
  116. package/dist/check/config.js +0 -151
  117. package/dist/check/config.js.map +0 -1
  118. package/dist/check/fixer.d.ts +0 -39
  119. package/dist/check/fixer.d.ts.map +0 -1
  120. package/dist/check/fixer.js +0 -119
  121. package/dist/check/fixer.js.map +0 -1
  122. package/dist/check/index.d.ts +0 -10
  123. package/dist/check/index.d.ts.map +0 -1
  124. package/dist/check/index.js +0 -21
  125. package/dist/check/index.js.map +0 -1
  126. package/dist/check/rules/anti-patterns.d.ts +0 -65
  127. package/dist/check/rules/anti-patterns.d.ts.map +0 -1
  128. package/dist/check/rules/anti-patterns.js +0 -481
  129. package/dist/check/rules/anti-patterns.js.map +0 -1
  130. package/dist/check/rules/closures.d.ts +0 -66
  131. package/dist/check/rules/closures.d.ts.map +0 -1
  132. package/dist/check/rules/closures.js +0 -370
  133. package/dist/check/rules/closures.js.map +0 -1
  134. package/dist/check/rules/collections.d.ts +0 -90
  135. package/dist/check/rules/collections.d.ts.map +0 -1
  136. package/dist/check/rules/collections.js +0 -373
  137. package/dist/check/rules/collections.js.map +0 -1
  138. package/dist/check/rules/conditionals.d.ts +0 -41
  139. package/dist/check/rules/conditionals.d.ts.map +0 -1
  140. package/dist/check/rules/conditionals.js +0 -134
  141. package/dist/check/rules/conditionals.js.map +0 -1
  142. package/dist/check/rules/flow.d.ts +0 -46
  143. package/dist/check/rules/flow.d.ts.map +0 -1
  144. package/dist/check/rules/flow.js +0 -206
  145. package/dist/check/rules/flow.js.map +0 -1
  146. package/dist/check/rules/formatting.d.ts +0 -133
  147. package/dist/check/rules/formatting.d.ts.map +0 -1
  148. package/dist/check/rules/formatting.js +0 -648
  149. package/dist/check/rules/formatting.js.map +0 -1
  150. package/dist/check/rules/helpers.d.ts +0 -26
  151. package/dist/check/rules/helpers.d.ts.map +0 -1
  152. package/dist/check/rules/helpers.js +0 -66
  153. package/dist/check/rules/helpers.js.map +0 -1
  154. package/dist/check/rules/index.d.ts +0 -21
  155. package/dist/check/rules/index.d.ts.map +0 -1
  156. package/dist/check/rules/index.js +0 -78
  157. package/dist/check/rules/index.js.map +0 -1
  158. package/dist/check/rules/loops.d.ts +0 -77
  159. package/dist/check/rules/loops.d.ts.map +0 -1
  160. package/dist/check/rules/loops.js +0 -310
  161. package/dist/check/rules/loops.js.map +0 -1
  162. package/dist/check/rules/naming.d.ts +0 -21
  163. package/dist/check/rules/naming.d.ts.map +0 -1
  164. package/dist/check/rules/naming.js +0 -174
  165. package/dist/check/rules/naming.js.map +0 -1
  166. package/dist/check/rules/strings.d.ts +0 -28
  167. package/dist/check/rules/strings.d.ts.map +0 -1
  168. package/dist/check/rules/strings.js +0 -79
  169. package/dist/check/rules/strings.js.map +0 -1
  170. package/dist/check/rules/types.d.ts +0 -41
  171. package/dist/check/rules/types.d.ts.map +0 -1
  172. package/dist/check/rules/types.js +0 -167
  173. package/dist/check/rules/types.js.map +0 -1
  174. package/dist/check/types.d.ts +0 -112
  175. package/dist/check/types.d.ts.map +0 -1
  176. package/dist/check/types.js +0 -6
  177. package/dist/check/types.js.map +0 -1
  178. package/dist/check/validator.d.ts +0 -18
  179. package/dist/check/validator.d.ts.map +0 -1
  180. package/dist/check/validator.js +0 -110
  181. package/dist/check/validator.js.map +0 -1
  182. package/dist/check/visitor.d.ts +0 -33
  183. package/dist/check/visitor.d.ts.map +0 -1
  184. package/dist/check/visitor.js +0 -259
  185. package/dist/check/visitor.js.map +0 -1
  186. package/dist/cli-check.d.ts +0 -43
  187. package/dist/cli-check.d.ts.map +0 -1
  188. package/dist/cli-check.js +0 -368
  189. package/dist/cli-check.js.map +0 -1
  190. package/dist/cli-eval.d.ts +0 -15
  191. package/dist/cli-eval.d.ts.map +0 -1
  192. package/dist/cli-eval.js +0 -116
  193. package/dist/cli-eval.js.map +0 -1
  194. package/dist/cli-exec.d.ts +0 -49
  195. package/dist/cli-exec.d.ts.map +0 -1
  196. package/dist/cli-exec.js +0 -183
  197. package/dist/cli-exec.js.map +0 -1
  198. package/dist/cli-module-loader.d.ts +0 -19
  199. package/dist/cli-module-loader.d.ts.map +0 -1
  200. package/dist/cli-module-loader.js +0 -83
  201. package/dist/cli-module-loader.js.map +0 -1
  202. package/dist/cli-shared.d.ts +0 -44
  203. package/dist/cli-shared.d.ts.map +0 -1
  204. package/dist/cli-shared.js +0 -108
  205. package/dist/cli-shared.js.map +0 -1
  206. package/dist/cli.d.ts +0 -13
  207. package/dist/cli.d.ts.map +0 -1
  208. package/dist/cli.js +0 -62
  209. package/dist/cli.js.map +0 -1
  210. package/dist/runtime/core/introspection-data.d.ts +0 -2
  211. package/dist/runtime/core/introspection-data.d.ts.map +0 -1
  212. package/dist/runtime/core/introspection-data.js +0 -618
  213. package/dist/runtime/core/introspection-data.js.map +0 -1
  214. package/dist/runtime/core/version-data.d.ts +0 -18
  215. package/dist/runtime/core/version-data.d.ts.map +0 -1
  216. package/dist/runtime/core/version-data.js +0 -16
  217. package/dist/runtime/core/version-data.js.map +0 -1
  218. package/docs/00_INDEX.md +0 -67
  219. package/docs/01_guide.md +0 -390
  220. package/docs/02_types.md +0 -504
  221. package/docs/03_variables.md +0 -324
  222. package/docs/04_operators.md +0 -629
  223. package/docs/05_control-flow.md +0 -692
  224. package/docs/06_closures.md +0 -787
  225. package/docs/07_collections.md +0 -688
  226. package/docs/08_iterators.md +0 -330
  227. package/docs/09_strings.md +0 -205
  228. package/docs/10_parsing.md +0 -366
  229. package/docs/11_reference.md +0 -600
  230. package/docs/12_examples.md +0 -748
  231. package/docs/13_modules.md +0 -519
  232. package/docs/14_host-integration.md +0 -985
  233. package/docs/15_grammar.ebnf +0 -773
  234. package/docs/16_conventions.md +0 -695
  235. package/docs/17_cli-tools.md +0 -184
  236. package/docs/18_design-principles.md +0 -247
  237. package/docs/19_cookbook.md +0 -628
  238. package/docs/88_errors.md +0 -902
  239. package/docs/99_llm-reference.txt +0 -614
  240. package/docs/assets/logo.png +0 -0
package/dist/types.js CHANGED
@@ -3,55 +3,18 @@
3
3
  * Based on docs/grammar.ebnf
4
4
  */
5
5
  import { VERSION } from './generated/version-data.js';
6
- // ============================================================
7
- // ERROR HIERARCHY
8
- // ============================================================
9
- /** Error codes for programmatic handling */
10
- export const RILL_ERROR_CODES = {
11
- // Parse errors
12
- PARSE_UNEXPECTED_TOKEN: 'PARSE_UNEXPECTED_TOKEN',
13
- PARSE_INVALID_SYNTAX: 'PARSE_INVALID_SYNTAX',
14
- PARSE_INVALID_TYPE: 'PARSE_INVALID_TYPE',
15
- // Runtime errors
16
- RUNTIME_UNDEFINED_VARIABLE: 'RUNTIME_UNDEFINED_VARIABLE',
17
- RUNTIME_UNDEFINED_FUNCTION: 'RUNTIME_UNDEFINED_FUNCTION',
18
- RUNTIME_UNDEFINED_METHOD: 'RUNTIME_UNDEFINED_METHOD',
19
- RUNTIME_UNDEFINED_ANNOTATION: 'RUNTIME_UNDEFINED_ANNOTATION',
20
- RUNTIME_TYPE_ERROR: 'RUNTIME_TYPE_ERROR',
21
- RUNTIME_TIMEOUT: 'RUNTIME_TIMEOUT',
22
- RUNTIME_INVALID_PATTERN: 'RUNTIME_INVALID_PATTERN',
23
- RUNTIME_AUTO_EXCEPTION: 'RUNTIME_AUTO_EXCEPTION',
24
- RUNTIME_ABORTED: 'RUNTIME_ABORTED',
25
- RUNTIME_PROPERTY_NOT_FOUND: 'RUNTIME_PROPERTY_NOT_FOUND',
26
- RUNTIME_LIMIT_EXCEEDED: 'RUNTIME_LIMIT_EXCEEDED',
27
- RUNTIME_ASSERTION_FAILED: 'RUNTIME_ASSERTION_FAILED',
28
- RUNTIME_ERROR_RAISED: 'RUNTIME_ERROR_RAISED',
29
- // Check errors
30
- CHECK_FILE_NOT_FOUND: 'CHECK_FILE_NOT_FOUND',
31
- CHECK_FILE_UNREADABLE: 'CHECK_FILE_UNREADABLE',
32
- CHECK_INVALID_CONFIG: 'CHECK_INVALID_CONFIG',
33
- CHECK_FIX_COLLISION: 'CHECK_FIX_COLLISION',
34
- };
35
6
  class ErrorRegistryImpl {
36
7
  byId;
37
- byLegacyCode;
38
8
  constructor(definitions) {
39
9
  const idMap = new Map();
40
- const codeMap = new Map();
41
10
  for (const def of definitions) {
42
11
  idMap.set(def.errorId, def);
43
- const existing = codeMap.get(def.legacyCode) ?? [];
44
- codeMap.set(def.legacyCode, [...existing, def]);
45
12
  }
46
13
  this.byId = idMap;
47
- this.byLegacyCode = codeMap;
48
14
  }
49
15
  get(errorId) {
50
16
  return this.byId.get(errorId);
51
17
  }
52
- getByLegacyCode(code) {
53
- return this.byLegacyCode.get(code) ?? [];
54
- }
55
18
  has(errorId) {
56
19
  return this.byId.has(errorId);
57
20
  }
@@ -67,216 +30,576 @@ const ERROR_DEFINITIONS = [
67
30
  // Lexer Errors (RILL-L0xx)
68
31
  {
69
32
  errorId: 'RILL-L001',
70
- legacyCode: RILL_ERROR_CODES.PARSE_INVALID_SYNTAX,
71
33
  category: 'lexer',
72
34
  description: 'Unterminated string literal',
73
35
  messageTemplate: 'Unterminated string literal at {location}',
36
+ cause: 'String opened with quote but never closed before end of line or file.',
37
+ resolution: 'Add closing quote to complete the string, or use multiline strings with triple quotes (""") for multi-line content.',
38
+ examples: [
39
+ {
40
+ description: 'Missing closing quote on single line',
41
+ code: '"hello',
42
+ },
43
+ {
44
+ description: 'Newline inside single-quoted string',
45
+ code: '"hello\nworld"',
46
+ },
47
+ ],
74
48
  },
75
49
  {
76
50
  errorId: 'RILL-L002',
77
- legacyCode: RILL_ERROR_CODES.PARSE_INVALID_SYNTAX,
78
51
  category: 'lexer',
79
52
  description: 'Invalid character',
80
53
  messageTemplate: 'Invalid character {char} at {location}',
54
+ cause: 'Character not recognized by the lexer (not part of Rill syntax).',
55
+ resolution: 'Remove or replace the invalid character. Common causes: unicode characters in identifiers, unsupported operators, or copy-paste artifacts.',
56
+ examples: [
57
+ {
58
+ description: 'Unicode character in code',
59
+ code: '$x → "value" # → is not valid, use ->',
60
+ },
61
+ {
62
+ description: 'Backtick instead of quote',
63
+ code: '`hello` # Use "hello" instead',
64
+ },
65
+ ],
81
66
  },
82
67
  {
83
68
  errorId: 'RILL-L003',
84
- legacyCode: RILL_ERROR_CODES.PARSE_INVALID_SYNTAX,
85
69
  category: 'lexer',
86
70
  description: 'Invalid number format',
87
71
  messageTemplate: 'Invalid number format: {value}',
72
+ cause: 'Number contains invalid characters, multiple decimal points, or unsupported notation.',
73
+ resolution: 'Use valid number format: integers (123), decimals (1.5), or scientific notation (1e5). No underscores, trailing dots, or multiple decimals allowed.',
74
+ examples: [
75
+ {
76
+ description: 'Multiple decimal points',
77
+ code: '1.2.3',
78
+ },
79
+ {
80
+ description: 'Trailing decimal point',
81
+ code: '123.',
82
+ },
83
+ {
84
+ description: 'Leading zeros (octal notation not supported)',
85
+ code: '0123',
86
+ },
87
+ ],
88
88
  },
89
89
  {
90
90
  errorId: 'RILL-L004',
91
- legacyCode: RILL_ERROR_CODES.PARSE_INVALID_SYNTAX,
92
91
  category: 'lexer',
93
92
  description: 'Unterminated multiline string',
94
93
  messageTemplate: 'Unterminated multiline string starting at {location}',
94
+ cause: 'Multiline string opened with triple quotes (""") but never closed.',
95
+ resolution: 'Add closing triple quotes (""") to complete the multiline string.',
96
+ examples: [
97
+ {
98
+ description: 'Missing closing triple quotes',
99
+ code: '"""hello\nworld',
100
+ },
101
+ {
102
+ description: 'Only two closing quotes instead of three',
103
+ code: '"""content""',
104
+ },
105
+ ],
95
106
  },
96
107
  {
97
108
  errorId: 'RILL-L005',
98
- legacyCode: RILL_ERROR_CODES.PARSE_INVALID_SYNTAX,
99
109
  category: 'lexer',
100
110
  description: 'Invalid escape sequence',
101
111
  messageTemplate: 'Invalid escape sequence {sequence} at {location}',
112
+ cause: 'Backslash followed by unsupported character in string literal.',
113
+ resolution: 'Use valid escape sequences: \\n (newline), \\t (tab), \\\\ (backslash), \\" (quote), \\{ (brace). For literal backslash, use \\\\.',
114
+ examples: [
115
+ {
116
+ description: 'Invalid escape character',
117
+ code: '"hello\\xworld" # \\x not supported',
118
+ },
119
+ {
120
+ description: 'Incomplete escape at end',
121
+ code: '"path\\',
122
+ },
123
+ ],
102
124
  },
103
125
  // Parse Errors (RILL-P0xx)
104
126
  {
105
127
  errorId: 'RILL-P001',
106
- legacyCode: RILL_ERROR_CODES.PARSE_UNEXPECTED_TOKEN,
107
128
  category: 'parse',
108
129
  description: 'Unexpected token',
109
130
  messageTemplate: 'Unexpected token {token}, expected {expected}',
131
+ cause: 'Token appears in invalid position according to grammar rules.',
132
+ resolution: 'Check syntax at the indicated position. Common causes: missing operators, mismatched delimiters, or keywords in wrong context.',
133
+ examples: [
134
+ {
135
+ description: 'Missing pipe operator between expressions',
136
+ code: '"hello" "world" # Missing -> between',
137
+ },
138
+ {
139
+ description: 'Statement starting with operator',
140
+ code: '-> "value" # Missing left side',
141
+ },
142
+ {
143
+ description: 'Unexpected closing brace',
144
+ code: '{ "value" }} # Extra closing brace',
145
+ },
146
+ ],
110
147
  },
111
148
  {
112
149
  errorId: 'RILL-P002',
113
- legacyCode: RILL_ERROR_CODES.PARSE_INVALID_SYNTAX,
114
150
  category: 'parse',
115
151
  description: 'Unexpected end of input',
116
152
  messageTemplate: 'Unexpected end of input, expected {expected}',
153
+ cause: 'File or block ended while parser expected more tokens (incomplete expression or statement).',
154
+ resolution: 'Complete the incomplete construct. Common causes: unclosed blocks, incomplete pipe chains, or missing expression after operator.',
155
+ examples: [
156
+ {
157
+ description: 'Unclosed block',
158
+ code: '{ "value"',
159
+ },
160
+ {
161
+ description: 'Pipe with no target',
162
+ code: '"hello" ->',
163
+ },
164
+ {
165
+ description: 'Incomplete conditional',
166
+ code: '?($x > 0) "yes" # Missing else branch',
167
+ },
168
+ ],
117
169
  },
118
170
  {
119
171
  errorId: 'RILL-P003',
120
- legacyCode: RILL_ERROR_CODES.PARSE_INVALID_TYPE,
121
172
  category: 'parse',
122
173
  description: 'Invalid type annotation',
123
174
  messageTemplate: 'Invalid type annotation: {type}',
175
+ cause: 'Type name not recognized. Rill supports: string, number, bool, closure, list, dict, tuple.',
176
+ resolution: 'Use valid type name from supported set. Check spelling and casing (types are lowercase).',
177
+ examples: [
178
+ {
179
+ description: 'Uppercase type name',
180
+ code: '$x => String # Use "string" not "String"',
181
+ },
182
+ {
183
+ description: 'Invalid type name',
184
+ code: '$x => int # Use "number" for all numeric types',
185
+ },
186
+ {
187
+ description: 'Generic type syntax not supported',
188
+ code: '$x => list<string> # Use "list" only',
189
+ },
190
+ ],
124
191
  },
125
192
  {
126
193
  errorId: 'RILL-P004',
127
- legacyCode: RILL_ERROR_CODES.PARSE_INVALID_SYNTAX,
128
194
  category: 'parse',
129
195
  description: 'Invalid expression',
130
196
  messageTemplate: 'Invalid expression: {details}',
197
+ cause: 'Expression structure violates grammar rules or contains unsupported constructs.',
198
+ resolution: 'Check expression syntax. Common causes: invalid operator combinations, malformed literals, or unsupported language features.',
199
+ examples: [
200
+ {
201
+ description: 'Double operators',
202
+ code: '$x + + $y',
203
+ },
204
+ {
205
+ description: 'Assignment operator (not supported)',
206
+ code: '$x = 5 # Use "5 => $x" instead',
207
+ },
208
+ ],
131
209
  },
132
210
  {
133
211
  errorId: 'RILL-P005',
134
- legacyCode: RILL_ERROR_CODES.PARSE_INVALID_SYNTAX,
135
212
  category: 'parse',
136
213
  description: 'Missing delimiter',
137
214
  messageTemplate: 'Missing {delimiter}, found {found}',
215
+ cause: 'Expected closing delimiter (parenthesis, bracket, brace) not found.',
216
+ resolution: 'Add the missing delimiter. Check for proper nesting and matching pairs.',
217
+ examples: [
218
+ {
219
+ description: 'Missing closing parenthesis',
220
+ code: 'func($a, $b',
221
+ },
222
+ {
223
+ description: 'Missing closing bracket in tuple',
224
+ code: '[1, 2, 3',
225
+ },
226
+ {
227
+ description: 'Mismatched delimiters',
228
+ code: '{ "value"] # Opened with { but closed with ]',
229
+ },
230
+ ],
231
+ },
232
+ {
233
+ errorId: 'RILL-P006',
234
+ category: 'parse',
235
+ description: 'Deprecated capture arrow syntax',
236
+ messageTemplate: 'The capture arrow syntax changed from :> to =>',
237
+ cause: 'Code uses old capture arrow syntax (:>) instead of current syntax (=>).',
238
+ resolution: 'Replace :> with => for all variable captures. This change was made in version 0.4.0.',
239
+ examples: [
240
+ {
241
+ description: 'Old capture syntax',
242
+ code: '"value" :> $x # Change to "value" => $x',
243
+ },
244
+ {
245
+ description: 'Old typed capture',
246
+ code: '5 :> $x:number # Change to 5 => $x:number',
247
+ },
248
+ ],
138
249
  },
139
250
  // Runtime Errors (RILL-R0xx)
140
251
  {
141
252
  errorId: 'RILL-R001',
142
- legacyCode: RILL_ERROR_CODES.RUNTIME_TYPE_ERROR,
143
253
  category: 'runtime',
144
254
  description: 'Parameter type mismatch',
145
255
  messageTemplate: 'Function {function} expects parameter {param} (position {position}) to be {expected}, got {actual}',
256
+ cause: 'Argument passed to function does not match declared parameter type.',
257
+ resolution: 'Pass value of correct type, or convert the value before passing. Check function signature for expected types.',
258
+ examples: [
259
+ {
260
+ description: 'String passed to number parameter',
261
+ code: '|x: number| $x * 2\n"5" -> $()',
262
+ },
263
+ {
264
+ description: 'Number passed to string method',
265
+ code: '123 -> .split(",") # split expects string',
266
+ },
267
+ ],
146
268
  },
147
269
  {
148
270
  errorId: 'RILL-R002',
149
- legacyCode: RILL_ERROR_CODES.RUNTIME_TYPE_ERROR,
150
271
  category: 'runtime',
151
272
  description: 'Operator type mismatch',
152
273
  messageTemplate: 'Operator {operator} cannot be applied to {leftType} and {rightType}',
274
+ cause: 'Binary operator applied to incompatible types. Rill does not perform implicit type coercion.',
275
+ resolution: 'Ensure both operands are compatible types. Convert values explicitly if needed using type-specific methods.',
276
+ examples: [
277
+ {
278
+ description: 'Adding string and number',
279
+ code: '"5" + 1 # Error: no implicit coercion',
280
+ },
281
+ {
282
+ description: 'Comparing different types',
283
+ code: '"10" == 10 # Always false, no coercion',
284
+ },
285
+ {
286
+ description: 'Arithmetic on non-numbers',
287
+ code: '"hello" * 2',
288
+ },
289
+ ],
153
290
  },
154
291
  {
155
292
  errorId: 'RILL-R003',
156
- legacyCode: RILL_ERROR_CODES.RUNTIME_TYPE_ERROR,
157
293
  category: 'runtime',
158
294
  description: 'Method receiver type mismatch',
159
295
  messageTemplate: 'Method {method} cannot be called on {type}',
296
+ cause: 'Method called on value of wrong type. String methods require strings, list methods require lists, etc.',
297
+ resolution: 'Call method on correct type, or convert value before calling. Check method documentation for receiver type.',
298
+ examples: [
299
+ {
300
+ description: 'String method on number',
301
+ code: '123 -> .upper() # upper() is string method',
302
+ },
303
+ {
304
+ description: 'List method on string',
305
+ code: '"hello" -> .first() # first() is list method',
306
+ },
307
+ ],
160
308
  },
161
309
  {
162
310
  errorId: 'RILL-R004',
163
- legacyCode: RILL_ERROR_CODES.RUNTIME_TYPE_ERROR,
164
311
  category: 'runtime',
165
312
  description: 'Type conversion failure',
166
313
  messageTemplate: 'Cannot convert {value} to {targetType}',
314
+ cause: 'Value cannot be converted to target type (invalid format or incompatible types).',
315
+ resolution: 'Ensure value has valid format for target type. For string-to-number: check numeric format. For parse operations: validate input structure.',
316
+ examples: [
317
+ {
318
+ description: 'Invalid number string',
319
+ code: '"abc" -> to_number() # Not a valid number',
320
+ },
321
+ {
322
+ description: 'Invalid JSON',
323
+ code: '"{bad json}" -> parse_json()',
324
+ },
325
+ ],
167
326
  },
168
327
  {
169
328
  errorId: 'RILL-R005',
170
- legacyCode: RILL_ERROR_CODES.RUNTIME_UNDEFINED_VARIABLE,
171
329
  category: 'runtime',
172
330
  description: 'Undefined variable',
173
331
  messageTemplate: 'Variable {name} is not defined',
332
+ cause: 'Variable referenced before assignment, or variable name misspelled.',
333
+ resolution: 'Assign value to variable before use (value => $var), or check spelling. Variables must be captured before reference.',
334
+ examples: [
335
+ {
336
+ description: 'Variable used before assignment',
337
+ code: '$count + 1 # $count never assigned',
338
+ },
339
+ {
340
+ description: 'Typo in variable name',
341
+ code: '"hi" => $mesage\n$message # Typo: mesage vs message',
342
+ },
343
+ {
344
+ description: 'Variable out of scope',
345
+ code: '{ "local" => $x }\n$x # $x only exists inside block',
346
+ },
347
+ ],
174
348
  },
175
349
  {
176
350
  errorId: 'RILL-R006',
177
- legacyCode: RILL_ERROR_CODES.RUNTIME_UNDEFINED_FUNCTION,
178
351
  category: 'runtime',
179
352
  description: 'Undefined function',
180
353
  messageTemplate: 'Function {name} is not defined',
354
+ cause: 'Function name not found in runtime context (not a built-in or host-provided function).',
355
+ resolution: 'Check function name spelling, ensure function is provided by host application, or verify module imports.',
356
+ examples: [
357
+ {
358
+ description: 'Misspelled function name',
359
+ code: 'leng("hello") # Should be length()',
360
+ },
361
+ {
362
+ description: 'Missing host function',
363
+ code: 'app::fetch($url) # Host must provide app::fetch',
364
+ },
365
+ ],
181
366
  },
182
367
  {
183
368
  errorId: 'RILL-R007',
184
- legacyCode: RILL_ERROR_CODES.RUNTIME_UNDEFINED_METHOD,
185
369
  category: 'runtime',
186
370
  description: 'Undefined method',
187
371
  messageTemplate: 'Method {method} is not defined on {type}',
372
+ cause: 'Method name not supported for the given type, or method name misspelled.',
373
+ resolution: 'Check method documentation for the type. Verify method name spelling and that it exists for this type.',
374
+ examples: [
375
+ {
376
+ description: 'Method not available on type',
377
+ code: '123 -> .trim() # trim() only on strings',
378
+ },
379
+ {
380
+ description: 'Misspelled method name',
381
+ code: '"hello" -> .upcase() # Should be .upper()',
382
+ },
383
+ ],
188
384
  },
189
385
  {
190
386
  errorId: 'RILL-R008',
191
- legacyCode: RILL_ERROR_CODES.RUNTIME_UNDEFINED_ANNOTATION,
192
387
  category: 'runtime',
193
388
  description: 'Undefined annotation',
194
389
  messageTemplate: 'Annotation {key} is not defined',
390
+ cause: 'Annotation key accessed but not set on statement or parameter.',
391
+ resolution: 'Set annotation before accessing (^(key: value)), or check annotation key spelling.',
392
+ examples: [
393
+ {
394
+ description: 'Accessing undefined annotation',
395
+ code: '$stmt.^timeout # No ^(timeout: ...) set',
396
+ },
397
+ ],
195
398
  },
196
399
  {
197
400
  errorId: 'RILL-R009',
198
- legacyCode: RILL_ERROR_CODES.RUNTIME_PROPERTY_NOT_FOUND,
199
401
  category: 'runtime',
200
402
  description: 'Property not found',
201
403
  messageTemplate: 'Property {property} not found on {type}',
404
+ cause: 'Dict key or tuple index does not exist in the value.',
405
+ resolution: 'Check property name spelling, verify the property exists, or use null-coalescing (??) to provide default. For safe access, use .? operator.',
406
+ examples: [
407
+ {
408
+ description: 'Missing dict key',
409
+ code: '[name: "x"] -> .age # age key not in dict',
410
+ },
411
+ {
412
+ description: 'Index out of bounds',
413
+ code: '[1, 2, 3] -> [5] # Only 3 elements (0-2)',
414
+ },
415
+ {
416
+ description: 'Safe alternative',
417
+ code: '[name: "x"] -> .age ?? 0 # Returns 0 if missing',
418
+ },
419
+ ],
202
420
  },
203
421
  {
204
422
  errorId: 'RILL-R010',
205
- legacyCode: RILL_ERROR_CODES.RUNTIME_LIMIT_EXCEEDED,
206
423
  category: 'runtime',
207
424
  description: 'Iteration limit exceeded',
208
425
  messageTemplate: 'Iteration limit of {limit} exceeded',
426
+ cause: 'Loop or collection operation exceeded configured iteration limit (prevents infinite loops).',
427
+ resolution: 'Reduce data size, adjust iteration limit via RuntimeOptions, or check for infinite loop conditions.',
428
+ examples: [
429
+ {
430
+ description: 'Infinite loop without termination',
431
+ code: '(true) @ { "looping" } # Never terminates',
432
+ },
433
+ {
434
+ description: 'Large collection with default limit',
435
+ code: 'range(0, 1000000) -> each |x| $x # May exceed default limit',
436
+ },
437
+ ],
209
438
  },
210
439
  {
211
440
  errorId: 'RILL-R011',
212
- legacyCode: RILL_ERROR_CODES.RUNTIME_INVALID_PATTERN,
213
441
  category: 'runtime',
214
442
  description: 'Invalid regex pattern',
215
443
  messageTemplate: 'Invalid regex pattern: {pattern}',
444
+ cause: 'Regular expression pattern has invalid syntax or unsupported features.',
445
+ resolution: 'Fix regex syntax errors. Check for unescaped special characters, unclosed groups, or invalid quantifiers.',
446
+ examples: [
447
+ {
448
+ description: 'Unclosed group',
449
+ code: '"test" -> .match("(abc") # Missing closing )',
450
+ },
451
+ {
452
+ description: 'Invalid quantifier',
453
+ code: '"test" -> .match("a{,5}") # Empty min in range',
454
+ },
455
+ ],
216
456
  },
217
457
  {
218
458
  errorId: 'RILL-R012',
219
- legacyCode: RILL_ERROR_CODES.RUNTIME_TIMEOUT,
220
459
  category: 'runtime',
221
460
  description: 'Operation timeout',
222
461
  messageTemplate: 'Operation timed out after {timeout}ms',
462
+ cause: 'Function execution exceeded configured timeout duration.',
463
+ resolution: 'Increase timeout via RuntimeOptions, optimize slow operations, or add ^(timeout: ms) annotation to specific calls.',
464
+ examples: [
465
+ {
466
+ description: 'Slow host function',
467
+ code: 'app::slow_api() # Times out if exceeds limit',
468
+ },
469
+ {
470
+ description: 'Setting higher timeout',
471
+ code: '^(timeout: 30000) app::slow_api() # 30 seconds',
472
+ },
473
+ ],
223
474
  },
224
475
  {
225
476
  errorId: 'RILL-R013',
226
- legacyCode: RILL_ERROR_CODES.RUNTIME_ABORTED,
227
477
  category: 'runtime',
228
478
  description: 'Execution aborted',
229
479
  messageTemplate: 'Execution aborted by signal',
480
+ cause: 'Host application cancelled execution via AbortSignal.',
481
+ resolution: 'This is intentional cancellation, not an error. If unexpected, check host abort signal logic.',
482
+ examples: [
483
+ {
484
+ description: 'User cancellation in UI',
485
+ code: '# Long-running script cancelled by user',
486
+ },
487
+ ],
230
488
  },
231
489
  {
232
490
  errorId: 'RILL-R014',
233
- legacyCode: RILL_ERROR_CODES.RUNTIME_AUTO_EXCEPTION,
234
491
  category: 'runtime',
235
492
  description: 'Auto-exception triggered',
236
493
  messageTemplate: 'Auto-exception triggered: pattern {pattern} matched',
494
+ cause: 'Value matched auto-exception pattern (configured to halt on specific error patterns in output).',
495
+ resolution: 'Handle error condition that produced the matched pattern, or adjust auto-exception configuration.',
496
+ examples: [
497
+ {
498
+ description: 'API error response',
499
+ code: '# API returned "ERROR:" prefix, auto-exception configured to catch this',
500
+ },
501
+ ],
237
502
  },
238
503
  {
239
504
  errorId: 'RILL-R015',
240
- legacyCode: RILL_ERROR_CODES.RUNTIME_ASSERTION_FAILED,
241
505
  category: 'runtime',
242
506
  description: 'Assertion failed',
243
507
  messageTemplate: 'Assertion failed: {condition}',
508
+ cause: 'Assertion statement evaluated to false.',
509
+ resolution: 'Fix the condition causing assertion failure, or remove/adjust assertion if condition is incorrect.',
510
+ examples: [
511
+ {
512
+ description: 'Basic assertion',
513
+ code: 'assert $count > 0 # Fails if $count <= 0',
514
+ },
515
+ {
516
+ description: 'Assertion with message',
517
+ code: 'assert $age >= 18 "Must be adult"',
518
+ },
519
+ ],
244
520
  },
245
521
  {
246
522
  errorId: 'RILL-R016',
247
- legacyCode: RILL_ERROR_CODES.RUNTIME_ERROR_RAISED,
248
523
  category: 'runtime',
249
524
  description: 'Error statement executed',
250
525
  messageTemplate: 'Error raised: {message}',
526
+ cause: 'Error statement executed explicitly in code.',
527
+ resolution: 'This is intentional error raising. Fix the condition that triggers the error statement, or handle the error case differently.',
528
+ examples: [
529
+ {
530
+ description: 'Explicit error',
531
+ code: 'error "Invalid configuration"',
532
+ },
533
+ {
534
+ description: 'Conditional error',
535
+ code: '($status == "failed") ? { error "Process failed" } ! "ok"',
536
+ },
537
+ ],
251
538
  },
252
539
  // Check Errors (RILL-C0xx)
253
540
  {
254
541
  errorId: 'RILL-C001',
255
- legacyCode: RILL_ERROR_CODES.CHECK_FILE_NOT_FOUND,
256
542
  category: 'check',
257
543
  description: 'File not found',
258
544
  messageTemplate: 'File not found: {path}',
545
+ cause: 'Specified file path does not exist in filesystem.',
546
+ resolution: 'Verify file path is correct, check file exists, or create the file if it should exist.',
547
+ examples: [
548
+ {
549
+ description: 'Nonexistent file',
550
+ code: 'rill-check missing.rill',
551
+ },
552
+ {
553
+ description: 'Wrong file extension',
554
+ code: 'rill-check script.txt # Should be script.rill',
555
+ },
556
+ ],
259
557
  },
260
558
  {
261
559
  errorId: 'RILL-C002',
262
- legacyCode: RILL_ERROR_CODES.CHECK_FILE_UNREADABLE,
263
560
  category: 'check',
264
561
  description: 'File unreadable',
265
562
  messageTemplate: 'File unreadable: {path}',
563
+ cause: 'File exists but cannot be read (permission denied or IO error).',
564
+ resolution: 'Check file permissions, ensure read access, or verify file is not locked by another process.',
565
+ examples: [
566
+ {
567
+ description: 'Permission denied',
568
+ code: 'rill-check protected.rill # File exists but no read permission',
569
+ },
570
+ ],
266
571
  },
267
572
  {
268
573
  errorId: 'RILL-C003',
269
- legacyCode: RILL_ERROR_CODES.CHECK_INVALID_CONFIG,
270
574
  category: 'check',
271
575
  description: 'Invalid configuration',
272
576
  messageTemplate: 'Invalid configuration: {details}',
577
+ cause: 'Configuration file or options contain invalid values or structure.',
578
+ resolution: 'Fix configuration syntax, ensure all required fields are present, and values are of correct type.',
579
+ examples: [
580
+ {
581
+ description: 'Invalid JSON in config',
582
+ code: '# .rillrc.json contains malformed JSON',
583
+ },
584
+ {
585
+ description: 'Unknown config option',
586
+ code: '# Config contains unsupported option key',
587
+ },
588
+ ],
273
589
  },
274
590
  {
275
591
  errorId: 'RILL-C004',
276
- legacyCode: RILL_ERROR_CODES.CHECK_FIX_COLLISION,
277
592
  category: 'check',
278
593
  description: 'Fix collision detected',
279
594
  messageTemplate: 'Fix collision detected for {location}',
595
+ cause: 'Multiple auto-fix rules attempt to modify the same source location.',
596
+ resolution: 'Apply fixes one at a time, or disable conflicting lint rules. Some fixes may need manual resolution.',
597
+ examples: [
598
+ {
599
+ description: 'Overlapping fix ranges',
600
+ code: '# Two rules try to fix same code section',
601
+ },
602
+ ],
280
603
  },
281
604
  ];
282
605
  /**
@@ -356,7 +679,7 @@ export function renderMessage(template, context) {
356
679
  /**
357
680
  * Generates documentation URL for an error ID.
358
681
  *
359
- * Format: https://github.com/rcrsr/rill/blob/v{version}/docs/88_errors.md#{errorId}
682
+ * Format: https://github.com/rcrsr/rill/blob/v{version}/docs/ref-errors.md#{errorId}
360
683
  * Error ID is lowercased in anchor.
361
684
  *
362
685
  * @param errorId - Error identifier (format: RILL-{category}{3-digit}, e.g., RILL-R001)
@@ -365,7 +688,7 @@ export function renderMessage(template, context) {
365
688
  *
366
689
  * @example
367
690
  * getHelpUrl("RILL-R001", "0.4.1")
368
- * // Returns: "https://github.com/rcrsr/rill/blob/v0.4.1/docs/88_errors.md#rill-r001"
691
+ * // Returns: "https://github.com/rcrsr/rill/blob/v0.4.1/docs/ref-errors.md#rill-r001"
369
692
  *
370
693
  * @example
371
694
  * getHelpUrl("invalid", "0.4.1")
@@ -385,7 +708,7 @@ export function getHelpUrl(errorId, version) {
385
708
  }
386
709
  // Build URL with lowercased errorId in anchor
387
710
  const anchor = errorId.toLowerCase();
388
- return `https://github.com/rcrsr/rill/blob/v${version}/docs/88_errors.md#${anchor}`;
711
+ return `https://github.com/rcrsr/rill/blob/v${version}/docs/ref-errors.md#${anchor}`;
389
712
  }
390
713
  // ============================================================
391
714
  // ERROR FACTORY
@@ -426,9 +749,8 @@ export function createError(errorId, context, location) {
426
749
  // This is acceptable per spec - the error is still created, just without complete location info
427
750
  // Compute helpUrl from errorId using VERSION constant
428
751
  const helpUrl = getHelpUrl(errorId, VERSION);
429
- // Create RillError with errorId, helpUrl, legacy code, and rendered message
752
+ // Create RillError with errorId, helpUrl, and rendered message
430
753
  return new RillError({
431
- code: definition.legacyCode,
432
754
  errorId,
433
755
  helpUrl: helpUrl || undefined, // Convert empty string to undefined
434
756
  message,
@@ -441,18 +763,24 @@ export function createError(errorId, context, location) {
441
763
  * Provides structured data for host applications to format as needed.
442
764
  */
443
765
  export class RillError extends Error {
444
- code;
445
766
  errorId;
446
767
  helpUrl;
447
768
  location;
448
769
  context;
449
770
  constructor(data) {
771
+ // EC-3: Missing errorId
772
+ if (!data.errorId) {
773
+ throw new TypeError('errorId is required');
774
+ }
775
+ // EC-4: Unknown errorId
776
+ if (!ERROR_REGISTRY.has(data.errorId)) {
777
+ throw new TypeError(`Unknown error ID: ${data.errorId}`);
778
+ }
450
779
  const locationStr = data.location
451
780
  ? ` at ${data.location.line}:${data.location.column}`
452
781
  : '';
453
782
  super(`${data.message}${locationStr}`);
454
783
  this.name = 'RillError';
455
- this.code = data.code;
456
784
  this.errorId = data.errorId;
457
785
  this.helpUrl = data.helpUrl;
458
786
  this.location = data.location;
@@ -461,7 +789,6 @@ export class RillError extends Error {
461
789
  /** Get structured error data for custom formatting */
462
790
  toData() {
463
791
  return {
464
- code: this.code,
465
792
  errorId: this.errorId,
466
793
  helpUrl: this.helpUrl,
467
794
  message: this.message.replace(/ at \d+:\d+$/, ''), // Strip location suffix
@@ -478,59 +805,52 @@ export class RillError extends Error {
478
805
  }
479
806
  /** Parse-time errors */
480
807
  export class ParseError extends RillError {
481
- constructor(message, location, context, errorId) {
482
- // When errorId provided, look up definition and derive legacyCode
483
- if (errorId) {
484
- const definition = ERROR_REGISTRY.get(errorId);
485
- if (!definition) {
486
- throw new TypeError(`Unknown error ID: ${errorId}`);
487
- }
488
- super({
489
- code: definition.legacyCode,
490
- errorId,
491
- message,
492
- location,
493
- context,
494
- });
808
+ constructor(errorId, message, location, context) {
809
+ // EC-7: Unknown errorId
810
+ const definition = ERROR_REGISTRY.get(errorId);
811
+ if (!definition) {
812
+ throw new TypeError(`Unknown error ID: ${errorId}`);
495
813
  }
496
- else {
497
- // Backward compatible: use default PARSE_INVALID_SYNTAX code
498
- super({
499
- code: RILL_ERROR_CODES.PARSE_INVALID_SYNTAX,
500
- message,
501
- location,
502
- context,
503
- });
814
+ // EC-8: Wrong category
815
+ if (definition.category !== 'parse') {
816
+ throw new TypeError(`Expected parse error ID, got: ${errorId}`);
504
817
  }
818
+ const helpUrl = getHelpUrl(errorId, VERSION);
819
+ super({
820
+ errorId,
821
+ helpUrl: helpUrl || undefined,
822
+ message,
823
+ location,
824
+ context,
825
+ });
505
826
  this.name = 'ParseError';
506
827
  }
507
828
  }
508
829
  /** Runtime execution errors */
509
830
  export class RuntimeError extends RillError {
510
- constructor(code, message, location, context, errorId) {
511
- // When errorId provided, look up definition and derive legacyCode
512
- if (errorId) {
513
- const definition = ERROR_REGISTRY.get(errorId);
514
- if (!definition) {
515
- throw new TypeError(`Unknown error ID: ${errorId}`);
516
- }
517
- super({
518
- code: definition.legacyCode,
519
- errorId,
520
- message,
521
- location,
522
- context,
523
- });
831
+ constructor(errorId, message, location, context) {
832
+ // Validate errorId exists in registry
833
+ const definition = ERROR_REGISTRY.get(errorId);
834
+ if (!definition) {
835
+ throw new TypeError(`Unknown error ID: ${errorId}`);
524
836
  }
525
- else {
526
- // Backward compatible: use provided code directly
527
- super({ code, message, location, context });
837
+ // Validate errorId is a runtime error
838
+ if (definition.category !== 'runtime') {
839
+ throw new TypeError(`Expected runtime error ID, got: ${errorId}`);
528
840
  }
841
+ const helpUrl = getHelpUrl(errorId, VERSION);
842
+ super({
843
+ errorId,
844
+ helpUrl: helpUrl || undefined,
845
+ message,
846
+ location,
847
+ context,
848
+ });
529
849
  this.name = 'RuntimeError';
530
850
  }
531
851
  /** Create from an AST node */
532
- static fromNode(code, message, node, context, errorId) {
533
- return new RuntimeError(code, message, node?.span.start, context, errorId);
852
+ static fromNode(errorId, message, node, context) {
853
+ return new RuntimeError(errorId, message, node?.span.start, context);
534
854
  }
535
855
  }
536
856
  /** Timeout errors */
@@ -538,7 +858,7 @@ export class TimeoutError extends RuntimeError {
538
858
  functionName;
539
859
  timeoutMs;
540
860
  constructor(functionName, timeoutMs, location) {
541
- super(RILL_ERROR_CODES.RUNTIME_TIMEOUT, `Function '${functionName}' timed out after ${timeoutMs}ms`, location, { functionName, timeoutMs });
861
+ super('RILL-R012', `Function '${functionName}' timed out after ${timeoutMs}ms`, location, { functionName, timeoutMs });
542
862
  this.name = 'TimeoutError';
543
863
  this.functionName = functionName;
544
864
  this.timeoutMs = timeoutMs;
@@ -549,7 +869,7 @@ export class AutoExceptionError extends RuntimeError {
549
869
  pattern;
550
870
  matchedValue;
551
871
  constructor(pattern, matchedValue, location) {
552
- super(RILL_ERROR_CODES.RUNTIME_AUTO_EXCEPTION, `Auto-exception triggered: pattern '${pattern}' matched`, location, { pattern, matchedValue });
872
+ super('RILL-R014', `Auto-exception triggered: pattern '${pattern}' matched`, location, { pattern, matchedValue });
553
873
  this.name = 'AutoExceptionError';
554
874
  this.pattern = pattern;
555
875
  this.matchedValue = matchedValue;
@@ -558,7 +878,7 @@ export class AutoExceptionError extends RuntimeError {
558
878
  /** Abort errors (when execution is cancelled via AbortSignal) */
559
879
  export class AbortError extends RuntimeError {
560
880
  constructor(location) {
561
- super(RILL_ERROR_CODES.RUNTIME_ABORTED, 'Execution aborted', location, {});
881
+ super('RILL-R013', 'Execution aborted', location, {});
562
882
  this.name = 'AbortError';
563
883
  }
564
884
  }
@@ -578,7 +898,7 @@ export const TOKEN_TYPES = {
578
898
  PIPE_VAR: 'PIPE_VAR', // $ (lone dollar sign)
579
899
  // Operators
580
900
  ARROW: 'ARROW', // ->
581
- CAPTURE_ARROW: 'CAPTURE_ARROW', // :>
901
+ CAPTURE_ARROW: 'CAPTURE_ARROW', // =>
582
902
  DOT: 'DOT', // .
583
903
  QUESTION: 'QUESTION', // ?
584
904
  AT: 'AT', // @