ibex 0.2.0 → 0.3.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 (437) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +95 -272
  3. data/docs/architecture.md +187 -35
  4. data/docs/bison-import.md +103 -0
  5. data/docs/comparison-policy.md +127 -0
  6. data/docs/configuration-model.md +59 -0
  7. data/docs/configuration-report.md +28 -0
  8. data/docs/conflict-explanation-reviews/v1/records/README.md +28 -0
  9. data/docs/conflict-explanation-study.md +62 -0
  10. data/docs/construction-profiling.md +157 -0
  11. data/docs/cst-migration.md +3 -4
  12. data/docs/cst.md +24 -0
  13. data/docs/decisions/0000-template.md +24 -0
  14. data/docs/decisions/0001-separate-ir-pipeline.md +34 -0
  15. data/docs/decisions/0002-opaque-user-code-boundary.md +32 -0
  16. data/docs/decisions/0003-self-hosted-grammar-frontend.md +32 -0
  17. data/docs/decisions/0004-shared-semantic-and-lossless-source-model.md +33 -0
  18. data/docs/decisions/0005-contained-grammar-composition.md +34 -0
  19. data/docs/decisions/0006-bounded-structural-grammar-lowering.md +32 -0
  20. data/docs/decisions/0007-shared-parser-construction-pipeline.md +33 -0
  21. data/docs/decisions/0008-versioned-runtime-package-boundary.md +36 -0
  22. data/docs/decisions/0009-isolated-parser-sessions.md +34 -0
  23. data/docs/decisions/0010-committed-runtime-observation.md +34 -0
  24. data/docs/decisions/0011-versioned-semantic-action-boundary.md +37 -0
  25. data/docs/decisions/0012-bounded-nonexecuting-analysis.md +37 -0
  26. data/docs/decisions/0013-transactional-generation-publication.md +37 -0
  27. data/docs/decisions/0014-versioned-generated-lexer.md +35 -0
  28. data/docs/decisions/0015-worker-isolated-browser-analysis.md +32 -0
  29. data/docs/decisions/0016-red-green-concrete-syntax.md +34 -0
  30. data/docs/decisions/0017-persistent-syntax-artifacts.md +35 -0
  31. data/docs/decisions/0018-conservative-incremental-syntax-reuse.md +38 -0
  32. data/docs/decisions/0019-runtime-syntax-session-boundary.md +51 -0
  33. data/docs/decisions/0020-grammar-ir-parser-contract.md +65 -0
  34. data/docs/decisions/0021-data-only-parser-table-sidecar.md +50 -0
  35. data/docs/decisions/0022-manifest-bound-verification-report.md +77 -0
  36. data/docs/decisions/0023-syntax-only-repair-results.md +48 -0
  37. data/docs/decisions/0024-direct-ielr-construction.md +42 -0
  38. data/docs/decisions/README.md +74 -0
  39. data/docs/declarative-configuration.md +262 -0
  40. data/docs/development.md +179 -2
  41. data/docs/direct-ielr-decision.md +120 -0
  42. data/docs/direct-multi-entry-decision.md +82 -0
  43. data/docs/editor-setup.md +2 -1
  44. data/docs/error-ux-review-rubric-v1.md +117 -0
  45. data/docs/error-ux-reviews/v1/records/README.md +22 -0
  46. data/docs/error-ux-round2-review-status-v1.json +27 -0
  47. data/docs/error-ux-round2-reviews/v1/records/README.md +30 -0
  48. data/docs/error-ux-round2-v1.json +1581 -0
  49. data/docs/error-ux-round2.md +111 -0
  50. data/docs/error-ux.md +54 -0
  51. data/docs/getting-started.md +80 -0
  52. data/docs/grammar-reference.md +184 -13
  53. data/docs/ielr-design.md +43 -0
  54. data/docs/ielr.md +92 -0
  55. data/docs/ja/bison-import.md +51 -0
  56. data/docs/ja/stable-api.md +53 -0
  57. data/docs/lexer-construction-profile.md +109 -0
  58. data/docs/lexer-migration.md +5 -0
  59. data/docs/maturity.md +128 -0
  60. data/docs/project-site-strategy.md +54 -0
  61. data/docs/racc-migration-evidence.md +45 -0
  62. data/docs/racc-migration.md +11 -0
  63. data/docs/release-readiness.md +126 -68
  64. data/docs/repair-semantics.md +123 -0
  65. data/docs/runtime-abi-evolution.md +307 -0
  66. data/docs/stability.md +144 -34
  67. data/docs/status.md +43 -0
  68. data/docs/syntax-sessions.md +183 -0
  69. data/docs/table-artifact.md +125 -0
  70. data/docs/test-interactions.md +219 -0
  71. data/docs/verification-report.md +137 -0
  72. data/docs/verifier-trust-boundary.md +199 -0
  73. data/docs/workloads.md +132 -0
  74. data/lib/ibex/analysis/digraph.rb +128 -0
  75. data/lib/ibex/analysis.rb +1 -0
  76. data/lib/ibex/bison_import/importer.rb +516 -0
  77. data/lib/ibex/bison_import/tokenizer.rb +260 -0
  78. data/lib/ibex/bison_import.rb +200 -0
  79. data/lib/ibex/bounded_subprocess.rb +171 -0
  80. data/lib/ibex/cli/ambiguity.rb +14 -5
  81. data/lib/ibex/cli/analysis.rb +134 -0
  82. data/lib/ibex/cli/bison_import.rb +121 -0
  83. data/lib/ibex/cli/config.rb +128 -0
  84. data/lib/ibex/cli/diagnostics.rb +31 -11
  85. data/lib/ibex/cli/documentation.rb +11 -8
  86. data/lib/ibex/cli/equiv.rb +169 -0
  87. data/lib/ibex/cli/error_messages.rb +11 -4
  88. data/lib/ibex/cli/explain.rb +14 -5
  89. data/lib/ibex/cli/fix.rb +203 -0
  90. data/lib/ibex/cli/formatting.rb +11 -10
  91. data/lib/ibex/cli/fuzz.rb +200 -0
  92. data/lib/ibex/cli/fuzz_regressions.rb +145 -0
  93. data/lib/ibex/cli/generation_artifacts.rb +53 -2
  94. data/lib/ibex/cli/generation_error_messages.rb +1 -1
  95. data/lib/ibex/cli/grammar_tests.rb +32 -14
  96. data/lib/ibex/cli/ir_tools.rb +5 -61
  97. data/lib/ibex/cli/outputs.rb +60 -33
  98. data/lib/ibex/cli/reduce.rb +202 -0
  99. data/lib/ibex/cli/reduce_reporting.rb +71 -0
  100. data/lib/ibex/cli/samples.rb +49 -23
  101. data/lib/ibex/cli/verify.rb +116 -0
  102. data/lib/ibex/cli/watch.rb +6 -5
  103. data/lib/ibex/cli.rb +357 -56
  104. data/lib/ibex/codegen/action_locations.rb +1 -1
  105. data/lib/ibex/codegen/action_method_source.rb +5 -6
  106. data/lib/ibex/codegen/action_source.rb +3 -2
  107. data/lib/ibex/codegen/ambiguity.rb +5 -4
  108. data/lib/ibex/codegen/explain.rb +123 -55
  109. data/lib/ibex/codegen/generated_action_abi.rb +10 -5
  110. data/lib/ibex/codegen/rbs.rb +15 -7
  111. data/lib/ibex/codegen/report.rb +25 -13
  112. data/lib/ibex/codegen/ruby.rb +28 -64
  113. data/lib/ibex/codegen/ruby_actions.rb +9 -6
  114. data/lib/ibex/codegen/ruby_syntax.rb +15 -9
  115. data/lib/ibex/configuration/analysis_grammar.rb +35 -0
  116. data/lib/ibex/configuration/explanation.rb +421 -0
  117. data/lib/ibex/configuration/inspector.rb +232 -0
  118. data/lib/ibex/configuration.rb +580 -0
  119. data/lib/ibex/coverage/collector.rb +21 -11
  120. data/lib/ibex/coverage/event_stream.rb +13 -7
  121. data/lib/ibex/coverage/report.rb +26 -18
  122. data/lib/ibex/coverage/runtime_event_validator.rb +30 -21
  123. data/lib/ibex/delta_reducer.rb +99 -0
  124. data/lib/ibex/diff.rb +140 -0
  125. data/lib/ibex/equiv/machine.rb +135 -0
  126. data/lib/ibex/equiv.rb +373 -0
  127. data/lib/ibex/fix.rb +557 -0
  128. data/lib/ibex/frontend/ast.rb +22 -2
  129. data/lib/ibex/frontend/bootstrap_parser.rb +6 -13
  130. data/lib/ibex/frontend/diagnostic.rb +1 -1
  131. data/lib/ibex/frontend/formatter.rb +72 -26
  132. data/lib/ibex/frontend/generated_parser.rb +147 -117
  133. data/lib/ibex/frontend/generated_parser_base.rb +7 -3
  134. data/lib/ibex/frontend/generated_parser_includes.rb +1 -11
  135. data/lib/ibex/frontend/generation.rb +1 -1
  136. data/lib/ibex/frontend/parser/declarations.rb +17 -2
  137. data/lib/ibex/frontend/parser_configuration_support.rb +56 -0
  138. data/lib/ibex/frontend/regenerator.rb +1 -0
  139. data/lib/ibex/frontend/resolution.rb +2 -1
  140. data/lib/ibex/frontend/resolver.rb +1 -1
  141. data/lib/ibex/frontend/rule_documentation.rb +2 -1
  142. data/lib/ibex/frontend/source_cursor.rb +2 -2
  143. data/lib/ibex/frontend/source_span.rb +9 -1
  144. data/lib/ibex/frontend/token_adapter/declaration_state.rb +38 -6
  145. data/lib/ibex/frontend/token_adapter.rb +10 -0
  146. data/lib/ibex/frontend.rb +1 -0
  147. data/lib/ibex/fuzz.rb +219 -0
  148. data/lib/ibex/generation_input.rb +1 -1
  149. data/lib/ibex/generation_manifest.rb +36 -25
  150. data/lib/ibex/generation_transaction.rb +1 -1
  151. data/lib/ibex/generation_transaction_recovery.rb +4 -4
  152. data/lib/ibex/generation_transaction_validation.rb +2 -2
  153. data/lib/ibex/grammar_tests.rb +1 -1
  154. data/lib/ibex/ir/automaton_ir.rb +61 -19
  155. data/lib/ibex/ir/grammar_ir.rb +76 -45
  156. data/lib/ibex/ir/lexer_ir.rb +5 -5
  157. data/lib/ibex/ir/parser_contract.rb +135 -0
  158. data/lib/ibex/ir/serialize.rb +203 -76
  159. data/lib/ibex/ir/validator/automaton.rb +64 -34
  160. data/lib/ibex/ir/validator/base.rb +51 -33
  161. data/lib/ibex/ir/validator/grammar.rb +113 -83
  162. data/lib/ibex/ir/validator/lexer.rb +2 -2
  163. data/lib/ibex/ir/validator.rb +2 -1
  164. data/lib/ibex/ir.rb +16 -3
  165. data/lib/ibex/lalr/build_metrics.rb +50 -2
  166. data/lib/ibex/lalr/builder.rb +191 -56
  167. data/lib/ibex/lalr/conflict_search.rb +15 -4
  168. data/lib/ibex/lalr/counterexample.rb +19 -14
  169. data/lib/ibex/lalr/direct_lookaheads.rb +110 -57
  170. data/lib/ibex/lalr/goto_follows.rb +229 -0
  171. data/lib/ibex/lalr/ielr/annotator.rb +214 -0
  172. data/lib/ibex/lalr/ielr/bits.rb +28 -0
  173. data/lib/ibex/lalr/ielr/inadequacy.rb +47 -0
  174. data/lib/ibex/lalr/ielr/item_lookaheads.rb +78 -0
  175. data/lib/ibex/lalr/ielr/pipeline.rb +75 -0
  176. data/lib/ibex/lalr/ielr/split_stability.rb +78 -0
  177. data/lib/ibex/lalr/ielr/split_state.rb +20 -0
  178. data/lib/ibex/lalr/ielr/state_splitter.rb +258 -0
  179. data/lib/ibex/lalr/ielr_partition.rb +22 -8
  180. data/lib/ibex/lalr/inadequacy_report.rb +50 -0
  181. data/lib/ibex/lalr/lookahead_propagation.rb +111 -0
  182. data/lib/ibex/lalr/lr0_collection.rb +121 -0
  183. data/lib/ibex/lalr/unreachable_states.rb +80 -0
  184. data/lib/ibex/lalr.rb +52 -1
  185. data/lib/ibex/location.rb +3 -3
  186. data/lib/ibex/lsp/document_handlers.rb +9 -7
  187. data/lib/ibex/lsp/initialization_handlers.rb +9 -7
  188. data/lib/ibex/lsp/navigation_handlers.rb +25 -11
  189. data/lib/ibex/lsp/parser_configuration_assistance.rb +149 -0
  190. data/lib/ibex/lsp/position_codec.rb +6 -2
  191. data/lib/ibex/lsp/request_handlers.rb +3 -2
  192. data/lib/ibex/lsp/request_support.rb +14 -7
  193. data/lib/ibex/lsp/server.rb +13 -11
  194. data/lib/ibex/lsp/symbol_index.rb +13 -13
  195. data/lib/ibex/lsp/symbol_index_builder.rb +30 -20
  196. data/lib/ibex/lsp/symbol_occurrence.rb +8 -2
  197. data/lib/ibex/lsp/transport.rb +13 -3
  198. data/lib/ibex/lsp/workspace.rb +5 -4
  199. data/lib/ibex/lsp/workspace_analyzer.rb +1 -1
  200. data/lib/ibex/lsp.rb +1 -0
  201. data/lib/ibex/messages/en.yml +28 -0
  202. data/lib/ibex/messages/ja.yml +28 -0
  203. data/lib/ibex/messages.rb +68 -0
  204. data/lib/ibex/metrics.rb +175 -0
  205. data/lib/ibex/normalize/declarations.rb +2 -0
  206. data/lib/ibex/normalize/diagnostics.rb +63 -38
  207. data/lib/ibex/normalize/expander.rb +5 -4
  208. data/lib/ibex/normalize/expression.rb +8 -6
  209. data/lib/ibex/normalize/grammar_builder.rb +26 -0
  210. data/lib/ibex/normalize/inline_expansion.rb +100 -49
  211. data/lib/ibex/normalize/lexer.rb +3 -3
  212. data/lib/ibex/normalize/parameter_ebnf_lowering.rb +11 -10
  213. data/lib/ibex/normalize/parameter_lowering.rb +40 -23
  214. data/lib/ibex/normalize/parameters.rb +31 -4
  215. data/lib/ibex/normalize/parser_configuration.rb +70 -0
  216. data/lib/ibex/normalize.rb +10 -20
  217. data/lib/ibex/racc_migration/report.rb +6 -3
  218. data/lib/ibex/rake_task.rb +1 -1
  219. data/lib/ibex/samples.rb +43 -13
  220. data/lib/ibex/table_artifact/builder.rb +266 -0
  221. data/lib/ibex/table_artifact/cst_projection.rb +70 -0
  222. data/lib/ibex/table_artifact/document.rb +39 -0
  223. data/lib/ibex/table_artifact/executor.rb +187 -0
  224. data/lib/ibex/table_artifact/serializer.rb +57 -0
  225. data/lib/ibex/table_artifact/validator/metadata.rb +179 -0
  226. data/lib/ibex/table_artifact/validator/support.rb +86 -0
  227. data/lib/ibex/table_artifact/validator/tables.rb +238 -0
  228. data/lib/ibex/table_artifact/validator.rb +253 -0
  229. data/lib/ibex/table_artifact.rb +88 -0
  230. data/lib/ibex/table_simulation/result.rb +6 -2
  231. data/lib/ibex/table_simulation/step.rb +3 -1
  232. data/lib/ibex/tables.rb +14 -0
  233. data/lib/ibex/verifiable_generation_bundle.rb +86 -0
  234. data/lib/ibex/verification_report/builder.rb +159 -0
  235. data/lib/ibex/verification_report/canonical_ir.rb +123 -0
  236. data/lib/ibex/verification_report/logical_path.rb +68 -0
  237. data/lib/ibex/verification_report/validator.rb +329 -0
  238. data/lib/ibex/verification_report.rb +69 -0
  239. data/lib/ibex/verify/action_correspondence.rb +138 -0
  240. data/lib/ibex/verify/language_witness.rb +295 -0
  241. data/lib/ibex/verify/reference_collection.rb +190 -0
  242. data/lib/ibex/verify/result.rb +73 -0
  243. data/lib/ibex/verify/verifier.rb +598 -0
  244. data/lib/ibex/verify.rb +15 -0
  245. data/lib/ibex/version.rb +1 -1
  246. data/lib/ibex/watch/runner.rb +10 -1
  247. data/lib/ibex/watch/source_snapshot.rb +13 -8
  248. data/lib/ibex.rb +10 -0
  249. data/schema/{automaton-ir-v1.schema.json → automaton-ir-definitions.schema.json} +6 -6
  250. data/schema/{automaton-ir-v2.schema.json → automaton-ir.schema.json} +14 -7
  251. data/schema/bison-import-v1.schema.json +106 -0
  252. data/schema/conflict-explanation-review-v1.schema.json +196 -0
  253. data/schema/conflict-explanation-study-v1.schema.json +528 -0
  254. data/schema/construction-profile-v1.schema.json +779 -0
  255. data/schema/diff-v1.schema.json +41 -0
  256. data/schema/direct-ielr-decision-v1.schema.json +200 -0
  257. data/schema/equiv-v1.schema.json +64 -0
  258. data/schema/error-ux-review-v1.schema.json +609 -0
  259. data/schema/error-ux-round2-review-v1.schema.json +191 -0
  260. data/schema/error-ux-round2-v1.schema.json +519 -0
  261. data/schema/explain-v1.schema.json +63 -1
  262. data/schema/fix-v1.schema.json +64 -0
  263. data/schema/fix-v2.schema.json +66 -0
  264. data/schema/fix-v3.schema.json +101 -0
  265. data/schema/fuzz-regression-v1.schema.json +79 -0
  266. data/schema/fuzz-v1.schema.json +114 -0
  267. data/schema/{grammar-ir-v2.schema.json → grammar-ir-extensions.schema.json} +20 -65
  268. data/schema/{grammar-ir-v1.schema.json → grammar-ir-foundation.schema.json} +3 -3
  269. data/schema/grammar-ir.schema.json +271 -0
  270. data/schema/ielr-benchmark-v1.schema.json +85 -0
  271. data/schema/lexer-profile-v1.schema.json +491 -0
  272. data/schema/metrics-v1.schema.json +60 -0
  273. data/schema/reduce-v1.schema.json +22 -0
  274. data/schema/reduce-v2.schema.json +63 -0
  275. data/schema/table-artifact-v1.schema.json +377 -0
  276. data/schema/verification-report-v1.schema.json +222 -0
  277. data/schema/verify-v1.schema.json +42 -0
  278. data/sig/ibex/analysis/digraph.rbs +19 -0
  279. data/sig/ibex/bison_import/importer.rbs +140 -0
  280. data/sig/ibex/bison_import/tokenizer.rbs +91 -0
  281. data/sig/ibex/bison_import.rbs +95 -0
  282. data/sig/ibex/bounded_subprocess.rbs +76 -0
  283. data/sig/ibex/cli/ambiguity.rbs +6 -0
  284. data/sig/ibex/cli/analysis.rbs +43 -0
  285. data/sig/ibex/cli/bison_import.rbs +32 -0
  286. data/sig/ibex/cli/config.rbs +35 -0
  287. data/sig/ibex/cli/diagnostics.rbs +16 -3
  288. data/sig/ibex/cli/documentation.rbs +5 -1
  289. data/sig/ibex/cli/equiv.rbs +49 -0
  290. data/sig/ibex/cli/error_messages.rbs +6 -0
  291. data/sig/ibex/cli/explain.rbs +6 -0
  292. data/sig/ibex/cli/fix.rbs +53 -0
  293. data/sig/ibex/cli/formatting.rbs +5 -1
  294. data/sig/ibex/cli/fuzz.rbs +47 -0
  295. data/sig/ibex/cli/fuzz_regressions.rbs +40 -0
  296. data/sig/ibex/cli/generation_artifacts.rbs +21 -2
  297. data/sig/ibex/cli/generation_error_messages.rbs +2 -2
  298. data/sig/ibex/cli/grammar_tests.rbs +15 -3
  299. data/sig/ibex/cli/ir_tools.rbs +7 -19
  300. data/sig/ibex/cli/outputs.rbs +9 -3
  301. data/sig/ibex/cli/reduce.rbs +60 -0
  302. data/sig/ibex/cli/reduce_reporting.rbs +27 -0
  303. data/sig/ibex/cli/samples.rbs +8 -0
  304. data/sig/ibex/cli/verify.rbs +28 -0
  305. data/sig/ibex/cli/watch.rbs +2 -2
  306. data/sig/ibex/cli.rbs +79 -5
  307. data/sig/ibex/codegen/action_method_source.rbs +4 -4
  308. data/sig/ibex/codegen/explain.rbs +45 -25
  309. data/sig/ibex/codegen/generated_action_abi.rbs +14 -10
  310. data/sig/ibex/codegen/rbs.rbs +12 -10
  311. data/sig/ibex/codegen/report.rbs +12 -12
  312. data/sig/ibex/codegen/ruby.rbs +18 -15
  313. data/sig/ibex/codegen/ruby_actions.rbs +6 -6
  314. data/sig/ibex/codegen/ruby_syntax.rbs +10 -8
  315. data/sig/ibex/configuration/analysis_grammar.rbs +13 -0
  316. data/sig/ibex/configuration/explanation.rbs +195 -0
  317. data/sig/ibex/configuration/inspector.rbs +53 -0
  318. data/sig/ibex/configuration.rbs +242 -0
  319. data/sig/ibex/coverage/collector.rbs +16 -14
  320. data/sig/ibex/coverage/event_stream.rbs +12 -10
  321. data/sig/ibex/coverage/report.rbs +20 -18
  322. data/sig/ibex/coverage/runtime_event_validator.rbs +38 -36
  323. data/sig/ibex/delta_reducer.rbs +38 -0
  324. data/sig/ibex/diff.rbs +47 -0
  325. data/sig/ibex/equiv/machine.rbs +54 -0
  326. data/sig/ibex/equiv.rbs +129 -0
  327. data/sig/ibex/fix.rbs +138 -0
  328. data/sig/ibex/frontend/ast.rbs +33 -7
  329. data/sig/ibex/frontend/bootstrap_parser.rbs +2 -0
  330. data/sig/ibex/frontend/diagnostic.rbs +2 -2
  331. data/sig/ibex/frontend/formatter.rbs +38 -30
  332. data/sig/ibex/frontend/generated_parser.rbs +87 -77
  333. data/sig/ibex/frontend/generated_parser_base.rbs +4 -2
  334. data/sig/ibex/frontend/parser/declarations.rbs +3 -0
  335. data/sig/ibex/frontend/parser_configuration_support.rbs +27 -0
  336. data/sig/ibex/frontend/resolution.rbs +3 -2
  337. data/sig/ibex/frontend/source_cursor.rbs +2 -2
  338. data/sig/ibex/frontend/source_span.rbs +5 -2
  339. data/sig/ibex/frontend/token_adapter/declaration_state.rbs +13 -1
  340. data/sig/ibex/frontend/token_adapter.rbs +6 -0
  341. data/sig/ibex/fuzz.rbs +71 -0
  342. data/sig/ibex/generation_input.rbs +2 -2
  343. data/sig/ibex/generation_manifest.rbs +35 -32
  344. data/sig/ibex/generation_transaction_recovery.rbs +2 -2
  345. data/sig/ibex/generation_transaction_validation.rbs +2 -2
  346. data/sig/ibex/grammar_tests.rbs +2 -2
  347. data/sig/ibex/ir/automaton_ir.rbs +30 -11
  348. data/sig/ibex/ir/grammar_ir.rbs +41 -27
  349. data/sig/ibex/ir/lexer_ir.rbs +8 -8
  350. data/sig/ibex/ir/parser_contract.rbs +69 -0
  351. data/sig/ibex/ir/serialize.rbs +63 -28
  352. data/sig/ibex/ir/validator/automaton.rbs +47 -44
  353. data/sig/ibex/ir/validator/base.rbs +35 -31
  354. data/sig/ibex/ir/validator/grammar.rbs +78 -67
  355. data/sig/ibex/ir/validator/lexer.rbs +4 -4
  356. data/sig/ibex/ir.rbs +9 -3
  357. data/sig/ibex/lalr/build_metrics.rbs +42 -2
  358. data/sig/ibex/lalr/builder.rbs +75 -24
  359. data/sig/ibex/lalr/conflict_search.rbs +5 -2
  360. data/sig/ibex/lalr/counterexample.rbs +17 -14
  361. data/sig/ibex/lalr/direct_lookaheads.rbs +35 -28
  362. data/sig/ibex/lalr/goto_follows.rbs +89 -0
  363. data/sig/ibex/lalr/ielr/annotator.rbs +67 -0
  364. data/sig/ibex/lalr/ielr/bits.rbs +14 -0
  365. data/sig/ibex/lalr/ielr/inadequacy.rbs +24 -0
  366. data/sig/ibex/lalr/ielr/item_lookaheads.rbs +35 -0
  367. data/sig/ibex/lalr/ielr/pipeline.rbs +17 -0
  368. data/sig/ibex/lalr/ielr/split_stability.rbs +27 -0
  369. data/sig/ibex/lalr/ielr/split_state.rbs +14 -0
  370. data/sig/ibex/lalr/ielr/state_splitter.rbs +76 -0
  371. data/sig/ibex/lalr/ielr_partition.rbs +17 -5
  372. data/sig/ibex/lalr/inadequacy_report.rbs +21 -0
  373. data/sig/ibex/lalr/lookahead_propagation.rbs +38 -0
  374. data/sig/ibex/lalr/lr0_collection.rbs +50 -0
  375. data/sig/ibex/lalr/unreachable_states.rbs +25 -0
  376. data/sig/ibex/lalr.rbs +11 -1
  377. data/sig/ibex/location.rbs +6 -6
  378. data/sig/ibex/lsp/document_handlers.rbs +8 -8
  379. data/sig/ibex/lsp/initialization_handlers.rbs +12 -12
  380. data/sig/ibex/lsp/navigation_handlers.rbs +15 -12
  381. data/sig/ibex/lsp/parser_configuration_assistance.rbs +49 -0
  382. data/sig/ibex/lsp/position_codec.rbs +8 -4
  383. data/sig/ibex/lsp/request_handlers.rbs +4 -4
  384. data/sig/ibex/lsp/request_support.rbs +8 -8
  385. data/sig/ibex/lsp/server.rbs +16 -16
  386. data/sig/ibex/lsp/symbol_index.rbs +20 -21
  387. data/sig/ibex/lsp/symbol_index_builder.rbs +9 -8
  388. data/sig/ibex/lsp/symbol_occurrence.rbs +11 -5
  389. data/sig/ibex/lsp/transport.rbs +18 -6
  390. data/sig/ibex/lsp/workspace.rbs +3 -2
  391. data/sig/ibex/lsp/workspace_analyzer.rbs +1 -1
  392. data/sig/ibex/messages.rbs +26 -0
  393. data/sig/ibex/metrics.rbs +50 -0
  394. data/sig/ibex/normalize/diagnostics.rbs +4 -4
  395. data/sig/ibex/normalize/expander.rbs +2 -2
  396. data/sig/ibex/normalize/expression.rbs +10 -8
  397. data/sig/ibex/normalize/grammar_builder.rbs +11 -0
  398. data/sig/ibex/normalize/inline_expansion.rbs +59 -50
  399. data/sig/ibex/normalize/lexer.rbs +4 -4
  400. data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +15 -14
  401. data/sig/ibex/normalize/parameter_lowering.rbs +18 -18
  402. data/sig/ibex/normalize/parameters.rbs +13 -8
  403. data/sig/ibex/normalize/parser_configuration.rbs +23 -0
  404. data/sig/ibex/normalize.rbs +11 -5
  405. data/sig/ibex/racc_migration/report.rbs +8 -6
  406. data/sig/ibex/rake_task.rbs +1 -1
  407. data/sig/ibex/samples.rbs +13 -4
  408. data/sig/ibex/table_artifact/builder.rbs +93 -0
  409. data/sig/ibex/table_artifact/cst_projection.rbs +20 -0
  410. data/sig/ibex/table_artifact/document.rbs +27 -0
  411. data/sig/ibex/table_artifact/executor.rbs +66 -0
  412. data/sig/ibex/table_artifact/serializer.rbs +25 -0
  413. data/sig/ibex/table_artifact/validator/metadata.rbs +52 -0
  414. data/sig/ibex/table_artifact/validator/support.rbs +46 -0
  415. data/sig/ibex/table_artifact/validator/tables.rbs +63 -0
  416. data/sig/ibex/table_artifact/validator.rbs +66 -0
  417. data/sig/ibex/table_artifact.rbs +32 -0
  418. data/sig/ibex/table_simulation/result.rbs +8 -4
  419. data/sig/ibex/table_simulation/step.rbs +4 -2
  420. data/sig/ibex/tables.rbs +10 -9
  421. data/sig/ibex/verifiable_generation_bundle.rbs +24 -0
  422. data/sig/ibex/verification_report/builder.rbs +53 -0
  423. data/sig/ibex/verification_report/canonical_ir.rbs +41 -0
  424. data/sig/ibex/verification_report/logical_path.rbs +34 -0
  425. data/sig/ibex/verification_report/validator.rbs +114 -0
  426. data/sig/ibex/verification_report.rbs +44 -0
  427. data/sig/ibex/verify/action_correspondence.rbs +50 -0
  428. data/sig/ibex/verify/language_witness.rbs +112 -0
  429. data/sig/ibex/verify/reference_collection.rbs +63 -0
  430. data/sig/ibex/verify/result.rbs +52 -0
  431. data/sig/ibex/verify/verifier.rbs +170 -0
  432. data/sig/ibex/verify.rbs +6 -0
  433. data/sig/ibex/watch/runner.rbs +12 -2
  434. data/sig/ibex/watch/source_snapshot.rbs +13 -9
  435. metadata +232 -12
  436. data/lib/ibex/ir/migration.rb +0 -120
  437. data/sig/ibex/ir/migration.rbs +0 -34
@@ -0,0 +1,111 @@
1
+ # Error UX evidence round 2
2
+
3
+ H003 expands repository-owned diagnostic and repair evidence beyond R001's ten
4
+ JSON cases. The machine-readable result is
5
+ [`error-ux-round2-v1.json`](error-ux-round2-v1.json), validated by
6
+ [`error-ux-round2-v1.schema.json`](../schema/error-ux-round2-v1.schema.json).
7
+ It does not replace or revise the R001 snapshot, rubric, review records, or
8
+ release gate.
9
+
10
+ ## Status and authority
11
+
12
+ The deterministic repository capture is **complete**. The external subjective
13
+ gate is separately **HOLD**: there are no external review records, and every
14
+ case has `status: pending` with an empty label list. Repository observations
15
+ cannot be promoted into external `useful`, `misleading`, `unsafe`, or `unclear`
16
+ labels.
17
+
18
+ The immutable machine capture intentionally has no slot for later subjective
19
+ labels. H003's separate
20
+ [`review status registry`](error-ux-round2-review-status-v1.json) and
21
+ [`review schema`](../schema/error-ux-round2-review-v1.schema.json) provide that
22
+ pathway without rewriting the capture. The registry binds the exact capture
23
+ SHA-256 and required case inventory. It remains `HOLD` with `records: []`.
24
+
25
+ The fixed corpus covers these distinct dimensions:
26
+
27
+ | Case | Shape | Observation | Fresh reparse |
28
+ | --- | --- | --- | --- |
29
+ | `H003-DELIMITER-01` | nested delimiter-heavy calls | mismatched closer | accepted |
30
+ | `H003-STATEMENT-01` | assignment statement | missing semantic value | accepted |
31
+ | `H003-STATEFUL-01` | stateful string lexer | EOF in the string state | accepted |
32
+ | `H003-EOF-01` | delimiter EOF | missing closer | progress; the proposed edit over-closes |
33
+ | `H003-MULTI-01` | synchronized statements | two errors at distinct offsets, then continuation | accepted |
34
+ | `H003-UNKNOWN-01` | external token adapter | unknown token after a complete word | accepted |
35
+ | `H003-LEXER-01` | generated lexer | no matching lexer rule | accepted |
36
+
37
+ Indentation-sensitive input is explicitly `excluded-unimplemented`. Ibex has
38
+ no indentation-tokenization contract, so the corpus does not simulate one.
39
+
40
+ ## Capture semantics
41
+
42
+ Each case binds the grammar and input digests, exact runtime expected tokens,
43
+ full diagnostic message, source line and caret, bounded repair result, a
44
+ repository-authored byte-range edit, the outcome of applying that edit and
45
+ parsing with a fresh parser, semantic-value risk, and external-review state.
46
+ The capture also binds the exact frontend, normalization, code generator,
47
+ runtime parser, generated lexer, repair implementation, and H003 generator
48
+ source bytes used to produce those observations.
49
+
50
+ Parser expected-token arrays come directly from the existing runtime API. A
51
+ generated-lexer failure occurs before a parser state exists, so its exact array
52
+ is empty with the closed reason
53
+ `lexer-failure-precedes-parser-state`; it is not presented as a parser
54
+ prediction. Runtime repairs remain distinct from proposed source edits.
55
+ Insertion can supply nil, replacement retains the original runtime value, and
56
+ deletion can discard intent. A successful fresh parse establishes syntax only,
57
+ not that an invented literal, deleted token, or replacement matches the user's
58
+ intended semantics.
59
+
60
+ The multi-error case overrides the normal error hook only to record the same
61
+ runtime token, expected-token, state, and location fields while allowing the
62
+ grammar's explicit `error ';'` synchronization path to continue. The committed
63
+ capture requires at least two diagnostics at strictly increasing byte offsets
64
+ and a non-nil result after recovery; it cannot be satisfied by duplicating one
65
+ error.
66
+
67
+ ## Trust boundary
68
+
69
+ The capture compiles and executes generated lexer and parser action code.
70
+ Execution is allowlisted to the four repository-owned fixtures under
71
+ `test/fixtures/error_ux_round2/`. It does not download or execute external
72
+ grammars, reviewer payloads, or user-supplied code. These fixtures are trusted
73
+ test programs, not a sandbox claim.
74
+
75
+ The existing R001 normative snapshot is bound to its unchanged SHA-256. H003
76
+ generation fails if those bytes change. H003 uses its own corpus, schema,
77
+ evidence ID, generator, and quality gate so comparative R001 evidence and this
78
+ repository study cannot silently become duplicate authorities.
79
+
80
+ ## Limits and kill conditions
81
+
82
+ This evidence has no external workloads or reviewers, observes one bounded
83
+ repair plan rather than every equal-cost plan, and does not infer intent from
84
+ acceptance. It must fail closed when fixture/corpus bytes drift, a required
85
+ dimension disappears, R001 changes, review state is overstated, synchronized
86
+ diagnostics collapse, or the committed fresh-reparse outcome changes.
87
+
88
+ The same quality gate validates the external registry fail-closed. `PASS`
89
+ requires at least two complete, independent, external records from
90
+ reviewers whose names remain distinct after Unicode NFKC normalization, full
91
+ case folding, trimming, and whitespace collapse. Every record must assess all seven cases with a
92
+ label, rationale, and semantic-value risk assessment. If reviewer labels
93
+ differ, every reviewer-pair disagreement must remain explicit rather than
94
+ being reduced to a majority conclusion. See the
95
+ [`records workflow`](error-ux-round2-reviews/v1/records/README.md).
96
+
97
+ Independence and identity remain human attestations: schema validation can
98
+ require the declarations and reject duplicate normalized names, but cannot
99
+ prove who authored a review. A record must never be added merely to clear the
100
+ gate. Evidence drift, incomplete case coverage, duplicate reviewer identity,
101
+ or missing disagreement entries kills `PASS`.
102
+
103
+ Regenerate only after reviewing intentional parser, lexer, diagnostic, or
104
+ repair changes:
105
+
106
+ ```sh
107
+ bundle exec ruby tool/error_ux_round2.rb --write
108
+ bundle exec rake quality:error_ux_round2
109
+ ```
110
+
111
+ The ordinary quality command never writes evidence.
data/docs/error-ux.md CHANGED
@@ -1,3 +1,8 @@
1
+ ---
2
+ title: Error experience evidence
3
+ description: Bounded diagnostics, repair behavior, and the evidence boundary for parser errors.
4
+ ---
5
+
1
6
  # JSON error UX evidence
2
7
 
3
8
  This report fixes the Phase 14 error-experience baseline against ten malformed
@@ -12,8 +17,56 @@ Use `--write` only after reviewing a deliberate diagnostic, parser-table, racc,
12
17
  or repair-policy change. CI regenerates the evidence and requires byte-for-byte
13
18
  equality.
14
19
 
20
+ ## Independent review gate
21
+
22
+ The fixed observations include a maintainer repair assessment. They do not
23
+ include an independent diagnostic or repair assessment.
24
+
25
+ <!-- r001-review-status:start -->
26
+ R001: `HOLD` — [`awaiting_independent_review`](error-ux-review-status-v1.json).
27
+ <!-- r001-review-status:end -->
28
+
29
+ Third-party reviewers use the versioned
30
+ [`rubric`](error-ux-review-rubric-v1.md) and closed
31
+ [`review-record schema`](../schema/error-ux-review-v1.schema.json). Run:
32
+
33
+ ```sh
34
+ bundle exec rake quality:error_ux_review_kit
35
+ bundle exec rake quality:error_ux_review_status
36
+ bundle exec ruby tool/error_ux_review.rb template review.json
37
+ ```
38
+
39
+ The generated payload contains the reviewer identity, reviewed maintainer
40
+ roster, structured consent, labels, rationales, and disagreements, but no
41
+ permalink. Publication metadata is kept separately in the status registry so a
42
+ reviewer can commit the final payload without a self-referential SHA. The first
43
+ command verifies the immutable snapshot, corpus identities, schema, local
44
+ byte/digest bindings, reports, claims, and truthful status entirely offline
45
+ while allowing the expected HOLD in ordinary CI.
46
+
47
+ `bundle exec rake release:error_ux_review` is the separate promotion gate and
48
+ returns nonzero until a valid published external payload exists. When PASS is
49
+ claimed, it additionally fetches the full-SHA blob without redirects, compares
50
+ the exact imported bytes, and requires the source repository owner, GitHub
51
+ commit API author, status publisher login, and reviewer login to agree
52
+ case-insensitively. This verifies control of the named GitHub namespace and
53
+ GitHub account metadata, not a cryptographic identity or signature. Network or
54
+ account-metadata uncertainty fails closed. Neither path changes the normative
55
+ observation fixture.
56
+
15
57
  ## Comparison method
16
58
 
59
+ <!-- comparative-evidence:racc-error-ux-json-v1:start -->
60
+ At Ibex revision cc20c5eb799cc218ebea665df64261f10d030f75, on ten fixed malformed
61
+ JSON inputs with the Ruby, OS, CPU, kernel, processor-count, and YJIT environment unrecorded,
62
+ the committed result artifact records Ibex diagnostics,
63
+ Racc 1.8.1's public on_error callback values, and a maintainer assessment of ten bounded repairs;
64
+ independent subjective review is pending, so this is not a completed comparative UX claim.
65
+
66
+ Evidence record ID: `racc-error-ux-json-v1`. The observations and assessment
67
+ are registered in [`claims.yml`](claims.yml), including every unrecorded
68
+ environment field and the still-pending independent review.
69
+
17
70
  Ibex uses [`examples/json.y`](../examples/json.y), including its generated
18
71
  lexer locations. The migration from its previous handwritten lexer is guarded
19
72
  by exact location and error-snapshot tests. The comparison uses the self-authored compatible grammar
@@ -58,3 +111,4 @@ SP-4 is **go** for the existing opt-in bounded single-plan repair described by
58
111
  experimental: a selected edit can require a nil semantic value, and the search
59
112
  does not enumerate every equal-cost CPCT+ repair. The stable default answer
60
113
  remains exact expected tokens plus explicit yacc/synchronization recovery.
114
+ <!-- comparative-evidence:racc-error-ux-json-v1:end -->
@@ -0,0 +1,80 @@
1
+ ---
2
+ title: Getting started
3
+ description: Install Ibex, generate a first parser, and choose a grammar mode.
4
+ ---
5
+
6
+ # Getting started
7
+
8
+ Ibex turns a racc-compatible grammar into a Pure Ruby LR parser. This guide
9
+ gets from an installed gem to a working parser before explaining the optional
10
+ extended surface.
11
+
12
+ ## Install the generator
13
+
14
+ ```sh
15
+ gem install ibex
16
+ ```
17
+
18
+ For an application that only runs generated parsers, install `ibex-runtime`
19
+ instead. A project can add either dependency with `bundle add ibex` or
20
+ `bundle add ibex-runtime`.
21
+
22
+ ## Generate a calculator
23
+
24
+ Create `calculator.y` with a class, token declaration, rules, and a small
25
+ handwritten pull lexer:
26
+
27
+ ```text
28
+ class Calculator
29
+ token NUM
30
+ preclow
31
+ left '+'
32
+ left '*'
33
+ prechigh
34
+ rule
35
+ expr : expr '+' expr { result = val[0] + val[2] }
36
+ | expr '*' expr { result = val[0] * val[2] }
37
+ | NUM { result = val[0] }
38
+ end
39
+ ---- inner
40
+ def parse_tokens(tokens)
41
+ @tokens = tokens
42
+ do_parse
43
+ end
44
+
45
+ def next_token
46
+ @tokens.shift
47
+ end
48
+ ---- footer
49
+ if $PROGRAM_NAME == __FILE__
50
+ tokens = [[:NUM, 2], ['+', nil], [:NUM, 3], ['*', nil], [:NUM, 4]]
51
+ puts Calculator.new.parse_tokens(tokens)
52
+ end
53
+ ```
54
+
55
+ Generate and run it:
56
+
57
+ ```sh
58
+ ibex -o calculator.rb calculator.y
59
+ ruby calculator.rb
60
+ # 14
61
+ ```
62
+
63
+ Run `ibex --check -o calculator.rb calculator.y` in CI. It compares the
64
+ reproducible output without rewriting the committed file.
65
+
66
+ ## Choose a mode
67
+
68
+ The default mode is the conservative racc migration surface. Add
69
+ `pragma extended` immediately after the class header, or pass
70
+ `--mode=extended`, when the grammar needs EBNF groups, imports, generated
71
+ lexers, typed trees, or other opt-in features. The [grammar reference](grammar-reference.md)
72
+ lists the exact syntax and the [maturity audit](maturity.md) records support
73
+ level per API.
74
+
75
+ ## Next steps
76
+
77
+ - [Migrate an existing racc grammar](racc-migration.md).
78
+ - [Configure grammar-owned and invocation-owned settings](configuration-model.md).
79
+ - [Inspect a grammar locally in the Playground](https://ydah.github.io/ibex/playground/).
80
+ - [Read the runtime and grammar reference](grammar-reference.md).
@@ -1,5 +1,12 @@
1
+ ---
2
+ title: Grammar reference
3
+ description: Write compatible and extended Ibex grammars and understand their generated contracts.
4
+ ---
5
+
1
6
  # Grammar reference
2
7
 
8
+ <!-- stable:compatible-parser:v2 -->
9
+
3
10
  Ibex's `default` mode accepts the compatible grammar described here. `--mode=extended` or an explicit grammar-file
4
11
  `pragma extended` adds the marked syntax; extensions are never inferred from a production.
5
12
 
@@ -64,8 +71,8 @@ lossless segment spans rather than rescanning raw text. Documentation works in r
64
71
  `AST::Rule`.
65
72
 
66
73
  For repeated definitions, every normalized user production keeps its definition's documentation. The nonterminal symbol uses
67
- the first nonnil text; a different later nonnil text is a positioned error, while the same text is accepted. Grammar IR v2
68
- serializes `doc` on symbols and productions. Version 1 omits those fields.
74
+ the first nonnil text; a different later nonnil text is a positioned error, while the same text is accepted. The current
75
+ Grammar IR serializes `doc` on symbols and productions.
69
76
 
70
77
  `ibex doc [--format=markdown|html|railroad] [-o FILE] [--mode=MODE] grammar.y` renders the canonical resolved grammar. Output
71
78
  defaults to Markdown on stdout. HTML is accessible and self-contained, railroad output includes visible wrapped descriptions,
@@ -106,16 +113,37 @@ includes and emits the first cross-file security, missing-target, cycle, or frag
106
113
  `frontend.resolution_error`; cross-file recovery is intentionally bounded to that one record. Permission and other actual
107
114
  filesystem read failures remain CLI invocation errors on stderr and do not produce a JSON envelope.
108
115
 
116
+ ## Generated parser execution boundary
117
+
118
+ Static frontend, formatting, LSP, documentation, IR, and analysis operations
119
+ treat parser actions, generated lexer actions, and user-code sections as opaque
120
+ data and do not execute them. Every semantic parse executes parser production
121
+ actions. Generated lexer actions additionally execute for `parse(source)`,
122
+ generated-lexer `lex(source).do_parse`, and generated-lexer
123
+ `parse_with_syntax(source)`. A handwritten `next_token` used by `do_parse` or
124
+ no-argument `parse_with_syntax` does not invoke generated lexer actions, nor do
125
+ the caller-fed `yyparse` and `push` / `finish` APIs.
126
+
127
+ Loading the generated file may execute `header`, `inner`, and `footer` code on
128
+ all of these paths. Generated runtime execution is trusted application code,
129
+ not a sandbox.
130
+
131
+ Generated `parse_syntax` and `incremental_session` are syntax-only: they
132
+ suppress parser production actions but still execute generated lexer actions.
133
+ They may also inherit side effects from loading user sections. A future
134
+ nonexecuting syntax profile would require a declarative built-in-only lexer and
135
+ no user-code sections; the current generated parser API is not that profile.
136
+
109
137
  ## Declarations
110
138
 
111
139
  - `pragma extended` enables extended syntax for this grammar even when the CLI uses its default or explicit `--mode=default`.
112
140
  It must immediately follow the class header, before every ordinary declaration. Unknown, duplicate, and misplaced pragmas
113
- are positioned errors. The frontend records the effective mode on the root AST, and Grammar IR v2 records extended mode
141
+ are positioned errors. The frontend records the effective mode on the root AST, and the current Grammar IR records extended mode
114
142
  additively so downstream generators preserve its runtime behavior.
115
143
  - `pragma cst` enables extended syntax and builds a pure-syntax Red/Green tree
116
144
  in parallel with the ordinary semantic value stack. Distinct pragmas may be
117
145
  combined in the class header; repeating either one is an error. Grammar IR
118
- v2 stores the optional `cst: true` setting.
146
+ The current Grammar IR stores the optional `cst: true` setting.
119
147
  - `import "relative/path.y"` inserts one explicit fragment through the canonical resolver. `include` is an accepted
120
148
  compatibility spelling. Imports are available only in extended mode. Parsing source text alone performs no filesystem
121
149
  access; path-based callers use `Frontend::Resolver` to resolve the import graph.
@@ -133,6 +161,15 @@ filesystem read failures remain CLI invocation errors on stderr and do not produ
133
161
  retained in Automaton IR but are not counted.
134
162
  - Extended `%expect-rr N` records the expected reduce/reduce count. Under `--warnings=error`, generation succeeds only when
135
163
  both declared counts match.
164
+ - Extended roots accept one `parser ... end` block before `rule`. `algorithm`
165
+ accepts exactly `slr`, `lalr`, `ielr`, or `lr1`; `entries` accepts exactly
166
+ `shared` or `isolated`. Keys may appear in either order, but duplicate blocks,
167
+ duplicate keys, unknown keys or values, and `algorithm auto` are positioned
168
+ errors. `entries isolated` requires at least two declared start symbols.
169
+ Fragments cannot own parser-wide construction. During canonical generation a
170
+ matching `--algorithm` or `--entry-isolation` is accepted and a conflicting
171
+ request is rejected. Analysis and `ibex test` may explicitly choose another
172
+ algorithm and report the declared and selected values as noncanonical.
136
173
  - `start name` overrides the first rule as the start symbol. Extended mode accepts an ordered list such as
137
174
  `start program expression`. The first name remains the primary entry for `do_parse`; generated parsers also expose
138
175
  `parse_program` and `parse_expression`. Shared construction attributes each conflict to its reachable entries and marks a
@@ -155,8 +192,8 @@ filesystem read failures remain CLI invocation errors on stderr and do not produ
155
192
  each later declaration has higher priority. A uniquely highest-priority completed production fills only table cells that
156
193
  would otherwise be errors, so explicit shifts, reductions, accepts, and conflict decisions remain authoritative.
157
194
  - Extended roots accept ordered `%test accept "source"` and `%test reject "source"` declarations. Sources must use
158
- double-quoted Ruby literals and exact duplicate expectation/source pairs are rejected. Grammar IR v2 retains their decoded
159
- source and location; ordinary generated parser tables do not.
195
+ double-quoted Ruby literals and exact duplicate expectation/source pairs are rejected. The current Grammar IR retains their
196
+ decoded source and location; ordinary generated parser tables do not.
160
197
 
161
198
  ## Generated lexer (extended mode)
162
199
 
@@ -333,8 +370,8 @@ helper and production order while avoiding dependence on the Ruby stack. The def
333
370
  1,000 distinct specializations; programmatic callers can configure the positive-Integer
334
371
  `max_parameter_specializations:`. Argument-changing recursive instantiation is rejected by structural cycle detection rather
335
372
  than an arbitrary depth boundary. Specialized productions retain template actions,
336
- precedence, types, documentation, locations, and include chains. Grammar IR v2 records
337
- `expansion.parameter {rule, arguments}`; v1 output omits the expansion record.
373
+ precedence, types, documentation, locations, and include chains. The current Grammar IR records
374
+ `expansion.parameter {rule, arguments}`.
338
375
 
339
376
  ### Inline rules (extended mode)
340
377
 
@@ -362,10 +399,9 @@ grammar nesting is independent of the Ruby call stack.
362
399
 
363
400
  Eliminated reductions still run their explicit or implicit actions in logical post-order. Named references, `val`, `_values`,
364
401
  `@N`, `@$`, empty spans, middle actions, `result`/`no_result_var`, and parser instance methods retain their logical rule view.
365
- Grammar IR v2 serializes the executable sequence in `action.composition.plan` and records
402
+ The current Grammar IR serializes the executable sequence in `action.composition.plan` and records
366
403
  `expansion.inline {rule}`; dump/load followed by code generation preserves it. `yyaccept` and `yyerror` stop the remaining
367
- logical fragments and caller after the current fragment completes, and `yyerrok` does not erase that `yyerror`. Version 1 omits
368
- both metadata families.
404
+ logical fragments and caller after the current fragment completes, and `yyerrok` does not erase that `yyerror`.
369
405
 
370
406
  The action scanner handles nested braces, quoted/backtick strings and interpolation, `%q/%Q/%w/%W/%i/%I/%x/%r/%s`, regular
371
407
  expressions, comments, character literals, and unquoted, single-quoted, double-quoted, or backtick heredocs. Indented, squiggly,
@@ -399,8 +435,8 @@ For external tooling, `observe { |event| ... }` registers an ordered observer an
399
435
  `unobserve`. Events are immutable, sequence-numbered per parse session, and cover `start`, `shift`, `reduce`, `error`, `recover`,
400
436
  `discard`, `accept`, and `reject`. Semantic values and locations are bounded JSON summaries rather than live objects.
401
437
  `Ibex::Runtime::EventJSONLTracer.attach(parser, io:)` writes the versioned schema at
402
- `schema/runtime-event-v1.schema.json`; write and serialization failures propagate. This API is separate from the legacy
403
- hook-shaped `Runtime::JSONLTracer`. See [ADR 0010](decisions/0010-committed-runtime-observation.md).
438
+ `schema/runtime-event-v1.schema.json`; write and serialization failures propagate. See
439
+ [ADR 0010](decisions/0010-committed-runtime-observation.md).
404
440
 
405
441
  Every parser instance owns immutable `Runtime::ResourceLimits`. The defaults allow a 10,000-entry LR state stack and 100
406
442
  recovery entries per parse. Pass `resource_limits:` to the generated parser constructor or replace it while the instance is
@@ -494,6 +530,10 @@ the manifest without rewriting them. `Ibex::GenerationManifest.validate_file(pat
494
530
  artifact bytes. For coherent concurrent reads, read the manifest, verify every entry, and retry from a newly read manifest if
495
531
  anything is missing or mismatched.
496
532
 
533
+ The version-1 `options` object is the existing open map for additive generation evidence. It now always records the effective
534
+ `cst_trivia` value: an omitted option uses the built-in `leading` default, and the compatibility spelling `attach` is recorded
535
+ canonically as `leading`. Adding this entry changes neither the manifest's required root shape nor its schema version.
536
+
497
537
  `--watch` repeatedly applies the same transaction to Ruby file generation. It observes the root, the latest successful include
498
538
  closure, unresolved include attempts, an optional messages file, and repairable output paths. Failed candidates leave the last
499
539
  successful generation intact; an unchanged failure is reported once. Source changes during render or publication retry after
@@ -533,6 +573,137 @@ error is rejected with an instruction to run the updater.
533
573
 
534
574
  ## Analysis and visualizations
535
575
 
576
+ `ibex samples grammar.y` emits JSON token arrays derived from Grammar IR.
577
+ `--strategy=random|coverage` selects random alternatives or least-covered
578
+ production paths; `--path-length=1|2`, token, depth, expansion, count, and seed
579
+ options make the search finite and reproducible.
580
+
581
+ `ibex fuzz grammar.y` without `--against` feeds bounded generated sentences and
582
+ single-token insert/delete/replace mutations to SLR, LALR, IELR, and LR(1)
583
+ table simulators. It does not execute production actions. `--coverage-guided`
584
+ selects uncovered production paths. The JSON report records every effective
585
+ bound and returns 0 when no difference is found within those bounds, 1 with a
586
+ concrete differential witness, and 2 when a budget prevents completion.
587
+ `--format=text` renders the same result and bounds for a terminal; JSON remains
588
+ the default versioned contract.
589
+ `--against=COMMAND` is an explicit unsafe opt-in that sends each token array as
590
+ JSON to the supplied subprocess. It executes arbitrary application code with
591
+ the invoking user's host permissions and is not a sandbox. The command is
592
+ split into an executable and arguments without an implicit shell, but the
593
+ selected executable can itself access the filesystem, network, environment,
594
+ and other processes. Exit 0 means accepted and exit 1 means rejected. It
595
+ requires `--against-runtime=DESCRIPTION`, and the report records that target
596
+ runtime, the exact command, and the Ibex host runtime. Each invocation is
597
+ bounded by `--against-timeout=SECONDS` (default 10) and
598
+ `--against-max-output=N` (default 1,048,576 bytes); either limit exits 2
599
+ instead of treating a stuck or noisy target as a language result. These limits
600
+ and process-group cleanup bound resources but do not confine side effects. On
601
+ process-group platforms, descendants are terminated with the target. A
602
+ difference is automatically delta-minimized while preserving its mismatch kind
603
+ and outcomes, then written atomically to `test/fuzz/regressions` with its seed
604
+ and effective bounds.
605
+ `--max-reduction-trials=N` bounds that work, `--regression-dir=DIR` selects
606
+ another destination, and `--no-save-regression` disables persistence. An
607
+ incomplete minimization remains a concrete difference and records
608
+ `complete: false`; it is never described as minimal.
609
+
610
+ `ibex reduce --command=COMMAND input` is an explicit unsafe opt-in that
611
+ repeatedly executes the supplied checker to perform trial-bounded delta
612
+ debugging. The checker may run arbitrary application code with the invoking
613
+ user's host permissions; it is not sandboxed. As with external fuzzing,
614
+ resource limits and process cleanup do not confine filesystem, network,
615
+ process, or other side effects.
616
+ Input mode is `tokens` (a JSON string array), `lines`, or `bytes`. A nonzero
617
+ normal subprocess exit means the failure persists; a signal is an invocation
618
+ error rather than evidence. The version-2 report contains the reduced
619
+ sequence, trial count, original/final sizes, every effective limit, and whether
620
+ the configured trial budget allowed completion. A trial-limited result is
621
+ reported as `incomplete`, never as `minimized`. The checker timeout
622
+ (default 10 seconds), checker output (default 1,048,576 bytes), and input
623
+ (default 10 MiB) are bounded by `--timeout`, `--max-output-bytes`, and
624
+ `--max-input-bytes`. Exceeding any configured budget exits 2 with a distinct
625
+ reason. Report v1 remains the prior read-only contract.
626
+ `--format=text` selects a human-readable report; JSON remains the default.
627
+
628
+ `ibex verify automaton.json` validates table semantics by independently
629
+ deriving the relevant LR item collection from the embedded Grammar IR. Default
630
+ checks cover soundness, lookaheads, default reductions and explicit error
631
+ masks, reachability/productivity, epsilon termination, and conflict
632
+ resolution consistency. Both modes rebuild and compare plain/compact rows;
633
+ `--strict` adds complete collection checks and reports row mismatches under
634
+ the strict V5 identifier. `--max-states` and `--max-items` bound only the
635
+ reference derivation. JSON is the default report format; exit 0 means valid, 1
636
+ means a concrete violation, and 2 means the reference budget was exhausted.
637
+ Opaque semantic actions are never executed. See the
638
+ [verifier trust boundary](verifier-trust-boundary.md) for the exact TCB,
639
+ algorithm-specific strength, resource non-goals, and generated-artifact
640
+ boundary.
641
+
642
+ `ibex equiv LEFT RIGHT` accepts grammar source, Grammar IR, or Automaton IR.
643
+ It combines normalized structural comparison, deterministic samples generated
644
+ in both directions, and a breadth-first product search over the two LR state
645
+ stacks. A difference returns 1 with a shortest token witness found within
646
+ `--max-tokens` and `--max-configurations`; an incomplete search returns 2.
647
+ `--samples`, `--seed`, `--max-actions`, and `--max-stack` expose the remaining
648
+ bounds. `--map=old_rule=new_rule` requests reduction-tree comparison for a
649
+ declared one-to-one rule correspondence. Without a map, only language
650
+ acceptance is compared. A successful bounded search is explicitly not a proof
651
+ of equivalence.
652
+
653
+ `ibex diff OLD NEW` accepts the same three input forms and classifies symbols,
654
+ rules, conflicts, and normalization warnings into `added`, `removed`, and
655
+ `changed`. It also reports before/after/delta counts for states, productions,
656
+ warnings, and unresolved conflicts. Conflict identities use token and
657
+ production shapes rather than unstable state numbers.
658
+
659
+ `ibex metrics GRAMMAR` reports normalized rule and alternative counts, average
660
+ and maximum branching, epsilon productions, recursive nonterminals, the
661
+ longest dependency path after collapsing mutually recursive components, and
662
+ deterministic Automaton IR cell/conflict counts. The metric is deliberately
663
+ structural; it contains no timing or memory threshold. Both commands default
664
+ to their closed version-1 JSON schemas and support `--format=text`.
665
+
666
+ `ibex fix GRAMMAR` selects an unresolved conflict and searches a finite set of
667
+ precedence declarations and overrides, algorithm changes, and `%inline`
668
+ rewrites. Rewrites that would move opaque semantic actions, including
669
+ recursion reversal and source factoring, are deliberately excluded. A repair
670
+ proposal is emitted only if the target disappears, no other conflict fingerprint
671
+ increases, the resulting table passes the independent verifier, and bounded
672
+ language plus mapped reduction-tree comparison finds no difference. `%expect`
673
+ and recovery-quality suggestions are reported separately as non-repair advice;
674
+ they never enter the verified proposal or `--apply` path because they do not
675
+ eliminate the selected conflict. The JSON
676
+ report includes the exact bounds, unified diff, eliminated fingerprint, state
677
+ delta, and rejection reasons. `--messages=FILE` measures newly moved,
678
+ uncovered, and unreachable message-catalog entries against the original table.
679
+ `--apply[=FXNNN]` transactionally applies a source proposal and refuses
680
+ symlinks or files with multiple hard links. Candidate, independent-verifier,
681
+ or equivalence budget exhaustion exits 2. `--verify-max-states` and
682
+ `--verify-max-items` bound the independent collection used for every
683
+ candidate. The advice/repair separation and independent-verifier bounds are
684
+ reported by the closed `schema/fix-v3.schema.json`; versions 1 and 2 remain
685
+ available as prior report contracts. Every successful report states that
686
+ bounded search is not a proof of equivalence.
687
+
688
+ `ibex import bison [--format=source|json] [-o FILE] grammar.y` performs a
689
+ one-way, analysis-only conversion. C actions are mechanically reference-mapped
690
+ but remain opaque, and Ruby generation is refused. Unsupported directives are
691
+ reported at every source position; structural gaps are distinguished from
692
+ generator-only controls, and `fix` refuses structurally incomplete imports.
693
+ Input bytes, structural tokens, rule groups, and actions have independent
694
+ positive budgets. Read-only grammar analysis commands auto-detect two Bison
695
+ `%%` section markers. The complete directive, naming, external-corpus, and
696
+ CRuby `parse.y` contracts are in the
697
+ [Bison import guide](bison-import.md).
698
+
699
+ All CLI forms accept `--lang=LANG`; `IBEX_LANG` supplies the default. Built-in
700
+ diagnostic catalogs ship for `en` and `ja`. Locale suffixes such as
701
+ `ja_JP.UTF-8` select their base language, while unavailable translations fall
702
+ back to English silently. Stable machine-readable diagnostic codes and report
703
+ schemas do not change with the display language. The built-in
704
+ `diagnostic.*`, `warning.*`, `conflict.*`, and `note.*` IDs are an internal
705
+ translation namespace and never overlap the user-owned `E00xx` message IDs.
706
+
536
707
  `--emit=sets` writes deterministic JSON containing nullable nonterminals and their FIRST and FOLLOW sets. `--dot=FILE` and
537
708
  `--mermaid=FILE` write automaton graphs. `--html=FILE` writes a self-contained report with state search, conflict highlighting,
538
709
  and a filter that keeps a selected conflict state and its one-hop neighbors. All three visualizations can be produced while
@@ -0,0 +1,43 @@
1
+ # Direct IELR(1) implementation design
2
+
3
+ This document is the maintained implementation summary for the paper-derived
4
+ IELR(1) pipeline. The Japanese work order in `.idea/ielr1-implementation-design-ja.md`
5
+ contains the full definition and fixture tables; this public copy records the
6
+ decisions that are part of the shipped implementation.
7
+
8
+ ## Contract
9
+
10
+ Direct IELR starts from an LR(0) collection, computes DeRemer–Pennello
11
+ successor/internal/includes and goto-follow closures, annotates grammar-relative
12
+ inadequacies, splits incompatible isocores, and reruns item lookahead
13
+ propagation. Conflict resolution, error reductions, default reductions, and
14
+ Automaton IR serialization are shared with the existing builder. Canonical LR(1)
15
+ is not constructed on the normal direct path.
16
+
17
+ The implementation is divided into `LR0Collection`, `GotoFollows`,
18
+ `IELR::Annotator`, `IELR::StateSplitter`, and `LookaheadPropagation`.
19
+ Integer bitsets are used for terminal and kernel-item sets. `--remove-unreachable`
20
+ is an explicit, default-off post-resolution compaction because state numbers are
21
+ part of diagnostics and generated artifacts.
22
+
23
+ ## Verification and limits
24
+
25
+ `GotoFollows#reduction_lookaheads` is cross-checked against the existing direct
26
+ item propagator. Paper fixtures cover the split and no-split cases, and the
27
+ acceptance matrix checks direct IELR against LALR for the four conflict examples.
28
+ The independent verifier still uses its canonical reference collection for V1/V2;
29
+ strict IELR verification additionally runs the bounded V9 acceptance witness.
30
+ `Verify::ActionCorrespondence` and `LALR::InadequacyReport` remain bounded
31
+ diagnostic tools, not a scale-independent proof. Global minimum state merging and
32
+ remergeable state optimization are intentionally out of scope.
33
+
34
+ ## Operational decision
35
+
36
+ `ielr_strategy: :partition` remains the default. `:direct` is an experimental,
37
+ explicit strategy exposed by `--ielr-strategy=direct`; no state-count or release
38
+ readiness claim is made. The decision and provenance boundary are recorded in
39
+ [ADR 0024](decisions/0024-direct-ielr-construction.md) and the direct-IELR dossier.
40
+
41
+ The implementation is independently derived from the published IELR and
42
+ DeRemer–Pennello papers and repository parser specifications. GPL implementation
43
+ source is not a design input.