hecks 3.13.0 → 4.0.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 (440) hide show
  1. checksums.yaml +4 -4
  2. data/examples/pizzas/adapters/fake_processor.rb +34 -0
  3. data/examples/pizzas/adapters/payment_signature.rb +66 -0
  4. data/examples/pizzas/adapters/payment_webhook.rb +87 -0
  5. data/examples/pizzas/bluebook/pizzas.behaviors +33 -0
  6. data/examples/pizzas/bluebook/pizzas.bluebook +4 -4
  7. data/examples/pizzas/bluebook/pizzas.hecksagon +5 -3
  8. data/examples/pizzas/config.ru +22 -0
  9. data/lib/hecks/adapters/driven/prism.rb +0 -2
  10. data/lib/hecks/adapters/driven.rb +0 -2
  11. data/lib/hecks/adapters/driving/json.rb +1 -7
  12. data/lib/hecks/bluebook/dsl/attribute_collector.rb +15 -5
  13. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -2
  14. data/lib/hecks/bluebook/dsl/derivation_words.rb +58 -0
  15. data/lib/hecks/bluebook/dsl/translation_builder.rb +6 -37
  16. data/lib/hecks/bluebook/expression/ast_json.rb +0 -9
  17. data/lib/hecks/bluebook/hecksagon.rb +1 -1
  18. data/lib/hecks/bluebook/meta_validator/translation_judge/rules.rb +7 -10
  19. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +4 -8
  20. data/lib/hecks/bluebook/meta_validator.rb +0 -11
  21. data/lib/hecks/bluebook/named_pattern.rb +33 -0
  22. data/lib/hecks/bluebook/translation.rb +18 -10
  23. data/lib/hecks/bluebook/translation_expression/evaluator.rb +63 -0
  24. data/lib/hecks/bluebook/translation_expression/parser.rb +127 -0
  25. data/lib/hecks/bluebook/translation_expression.rb +39 -0
  26. data/lib/hecks/bluebook/translation_plan.rb +70 -0
  27. data/lib/hecks/bluebook.rb +3 -0
  28. data/lib/hecks/chapters.rb +3 -3
  29. data/lib/hecks/cli/domain_stub.rb +1 -1
  30. data/lib/hecks/cli/interview_aggregate.rb +4 -4
  31. data/lib/hecks/composer/adapters/claude_composer.adapter +3 -0
  32. data/lib/hecks/composer/adapters/claude_composer.rb +83 -0
  33. data/lib/hecks/composer/adapters/fake_agent.adapter +3 -0
  34. data/lib/hecks/composer/adapters/fake_agent.rb +55 -0
  35. data/lib/hecks/composer/adapters/jev.adapter +3 -0
  36. data/lib/hecks/composer/adapters/jev.rb +66 -0
  37. data/lib/hecks/composer/agent.rb +113 -0
  38. data/lib/hecks/composer/assistant.rb +110 -0
  39. data/lib/hecks/composer/behavior_run.rb +53 -0
  40. data/lib/hecks/composer/bluebook/composer.bluebook +178 -0
  41. data/lib/hecks/composer/bluebook/composer.hecksagon +16 -0
  42. data/lib/hecks/composer/board.rb +65 -0
  43. data/lib/hecks/composer/board_edit/command_text.rb +39 -0
  44. data/lib/hecks/composer/board_edit/source.rb +84 -0
  45. data/lib/hecks/composer/board_edit.rb +144 -0
  46. data/lib/hecks/composer/check.rb +89 -0
  47. data/lib/hecks/composer/domains.rb +81 -0
  48. data/lib/hecks/composer/jobs.rb +134 -0
  49. data/lib/hecks/composer/layout.rb +37 -0
  50. data/lib/hecks/composer/live.rb +150 -0
  51. data/lib/hecks/composer/outline.rb +48 -0
  52. data/lib/hecks/composer/page.html +989 -0
  53. data/lib/hecks/composer/panels.rb +142 -0
  54. data/lib/hecks/composer/parse.rb +83 -0
  55. data/lib/hecks/composer/plain.rb +28 -0
  56. data/lib/hecks/composer/ports/composer_agent.port +7 -0
  57. data/lib/hecks/composer/session.rb +141 -0
  58. data/lib/hecks/composer/toolbox.rb +166 -0
  59. data/lib/hecks/composer/web.rb +156 -0
  60. data/lib/hecks/composer/workbench.rb +51 -0
  61. data/lib/hecks/composer/workspace.rb +81 -0
  62. data/lib/hecks/composer.rb +17 -0
  63. data/lib/hecks/corpus/adapters.rb +22 -0
  64. data/lib/hecks/corpus/rust.rb +1 -1
  65. data/lib/hecks/corpus/worlds.rb +19 -0
  66. data/lib/hecks/corpus.rb +5 -0
  67. data/lib/hecks/deploy/bluebook/deploy.bluebook +34 -34
  68. data/lib/hecks/forms/app/commands.rb +2 -3
  69. data/lib/hecks/forms/app/queries.rb +2 -3
  70. data/lib/hecks/forms/app/records.rb +17 -5
  71. data/lib/hecks/forms/command_form_renderer.rb +42 -16
  72. data/lib/hecks/forms/field_controls.rb +2 -2
  73. data/lib/hecks/forms/field_renderer.rb +1 -1
  74. data/lib/hecks/forms/field_shape.rb +36 -17
  75. data/lib/hecks/forms/index_renderer.rb +2 -1
  76. data/lib/hecks/forms/page.rb +1 -1
  77. data/lib/hecks/forms/params.rb +0 -13
  78. data/lib/hecks/forms/query_form_renderer.rb +7 -6
  79. data/lib/hecks/forms/record_renderer.rb +11 -7
  80. data/lib/hecks/forms/rule_words.rb +100 -0
  81. data/lib/hecks/forms/value_object_shape.rb +2 -1
  82. data/lib/hecks/framework/bluebook/change.bluebook +2 -2
  83. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -3
  84. data/lib/hecks/fuzzing/domain_generator/block_rendering.rb +1 -1
  85. data/lib/hecks/fuzzing/isolated_boot/worlds.rb +3 -6
  86. data/lib/hecks/fuzzing/replay/filters.rb +2 -6
  87. data/lib/hecks/gate/stages.yml +25 -0
  88. data/lib/hecks/grammar/evolve/seeds.rb +0 -6
  89. data/lib/hecks/grammar/evolve.rb +0 -3
  90. data/lib/hecks/grammar/translation.bluebook +1 -1
  91. data/lib/hecks/hecks/adapters/codebase/composing.rb +56 -0
  92. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +3 -1
  93. data/lib/hecks/hecks/adapters/journal_store/changes.rb +0 -26
  94. data/lib/hecks/hecks/adapters/journal_store/examination.rb +2 -23
  95. data/lib/hecks/hecks/adapters/journal_store/readings.rb +3 -11
  96. data/lib/hecks/hecks/adapters/journal_store.rb +0 -11
  97. data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +4 -11
  98. data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +0 -9
  99. data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +0 -4
  100. data/lib/hecks/hecks/codebase.behaviors +6 -0
  101. data/lib/hecks/hecks/codebase.bluebook +58 -37
  102. data/lib/hecks/hecks/composer.behaviors +68 -0
  103. data/lib/hecks/hecks/context_map.hecksagon +1 -1
  104. data/lib/hecks/hecks/custodian.behaviors +0 -6
  105. data/lib/hecks/hecks/custodian.bluebook +15 -92
  106. data/lib/hecks/hecks/hecks.bluebook +2 -2
  107. data/lib/hecks/hecks/hecks.hecksagon +2 -2
  108. data/lib/hecks/hecks/hecks.world +1 -1
  109. data/lib/hecks/hecks/rehearsal.bluebook +10 -16
  110. data/lib/hecks/hecks/tooling.bluebook +22 -22
  111. data/lib/hecks/kernel_capabilities/templates.rb +4 -4
  112. data/lib/hecks/kernel_capabilities.rb +1 -1
  113. data/lib/hecks/language/bluebook/aggregate.bluebook +1 -0
  114. data/lib/hecks/language/bluebook/command.bluebook +1 -0
  115. data/lib/hecks/language/bluebook/entity.bluebook +1 -0
  116. data/lib/hecks/language/bluebook/query.bluebook +1 -0
  117. data/lib/hecks/language/bluebook/shape.bluebook +8 -7
  118. data/lib/hecks/language/bluebook/vocabulary.bluebook +2 -3
  119. data/lib/hecks/language/hecksagon/port_operation.bluebook +1 -0
  120. data/lib/hecks/language/translation/translation_aggregate.bluebook +21 -24
  121. data/lib/hecks/ports/access_control.rb +2 -2
  122. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +3 -41
  123. data/lib/hecks/ports/persistence/plugins/era/lineage/coverage.rb +7 -7
  124. data/lib/hecks/ports/persistence/plugins/era/lineage/rewrite.rb +25 -2
  125. data/lib/hecks/ports/persistence/plugins/era/lineage/rules.rb +4 -4
  126. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +17 -25
  127. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/base_sql.rb +0 -12
  128. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/domain_rename.rb +1 -1
  129. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +2 -22
  130. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +0 -1
  131. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +9 -3
  132. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +3 -29
  133. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/refusals.rb +2 -26
  134. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +6 -33
  135. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -3
  136. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +2 -4
  137. data/lib/hecks/ports/persistence/plugins/era/translation/expression_sql.rb +52 -0
  138. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +23 -29
  139. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +1 -1
  140. data/lib/hecks/ports/persistence/plugins/era/translation.rb +0 -1
  141. data/lib/hecks/ports/persistence/plugins/era.rb +3 -6
  142. data/lib/hecks/ports.rb +0 -1
  143. data/lib/hecks/projection_files.rb +3 -1
  144. data/lib/hecks/projections/deploy/templates/lambda/nat_comment_oauth.tmpl +1 -1
  145. data/lib/hecks/projections/glossary/entries.rb +10 -4
  146. data/lib/hecks/projections/glossary/groups.rb +42 -0
  147. data/lib/hecks/projections/glossary/html/page.rb +7 -2
  148. data/lib/hecks/projections/glossary/html/parser.rb +1 -1
  149. data/lib/hecks/projections/glossary/html/sections.rb +31 -11
  150. data/lib/hecks/projections/glossary/html.rb +1 -2
  151. data/lib/hecks/projections/glossary/markdown.rb +31 -28
  152. data/lib/hecks/projections/glossary/mermaid.rb +3 -0
  153. data/lib/hecks/projections/glossary/page.css +143 -153
  154. data/lib/hecks/projections/glossary/page.js +63 -3
  155. data/lib/hecks/projections/glossary/sentences/actions.rb +88 -0
  156. data/lib/hecks/projections/glossary/sentences/paths.rb +77 -0
  157. data/lib/hecks/projections/glossary/sentences/queries.rb +90 -0
  158. data/lib/hecks/projections/glossary/sentences/value_objects.rb +32 -5
  159. data/lib/hecks/projections/glossary/sentences.rb +13 -3
  160. data/lib/hecks/projections/glossary/slugs.rb +4 -1
  161. data/lib/hecks/projections/glossary.rb +2 -1
  162. data/lib/hecks/projections/plain_english.rb +97 -0
  163. data/lib/hecks/projections/rust_vocabulary/arguments.rb +2 -2
  164. data/lib/hecks/projections/rust_vocabulary/enum_body.rb +20 -25
  165. data/lib/hecks/projections/rust_vocabulary/tests.rb +2 -2
  166. data/lib/hecks/projections/rust_vocabulary.rb +14 -6
  167. data/lib/hecks/projections/site/cms_editor/color.rb +0 -6
  168. data/lib/hecks/projections/statements/actions.rb +99 -0
  169. data/lib/hecks/projections/statements/relationships.rb +86 -0
  170. data/lib/hecks/projections/statements.rb +15 -24
  171. data/lib/hecks/projector/exporter/adapters.rb +112 -0
  172. data/lib/hecks/projector/exporter/translations.rb +18 -35
  173. data/lib/hecks/projector/exporter/worlds.rb +103 -0
  174. data/lib/hecks/projector/exporter.rb +5 -1
  175. data/lib/hecks/quality_control/adapters/agent.rb +6 -7
  176. data/lib/hecks/quality_control/adapters/agent_profile.rb +16 -114
  177. data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +1 -1
  178. data/lib/hecks/quality_control/quality_control.bluebook +51 -51
  179. data/lib/hecks/runtime/loader/boot_steps.rb +0 -20
  180. data/lib/hecks/runtime/outbox.rb +2 -9
  181. data/lib/hecks/runtime/port_operation_interpreter.rb +1 -9
  182. data/lib/hecks/runtime/remote_dispatcher.rb +2 -2
  183. data/lib/hecks/runtime/value.rb +13 -0
  184. data/lib/hecks/rust_build/project_rust/target_ir.rb +23 -4
  185. data/lib/hecks/rust_build/wasm.rb +0 -12
  186. data/lib/hecks/rust_build/write_if_changed.rb +12 -12
  187. data/lib/hecks/rust_format.rb +77 -0
  188. data/lib/hecks/site/bluebook/site.bluebook +5 -5
  189. data/lib/hecks/sme/bluebook/sme.bluebook +12 -12
  190. data/lib/hecks/tickets/bluebook/tickets.bluebook +3 -3
  191. data/lib/hecks/tools/fuzz_sweep/findings.rb +3 -9
  192. data/lib/hecks/tools/fuzz_sweep.rb +1 -3
  193. data/lib/hecks/tools/translation_audit/verdicts.rb +3 -28
  194. data/lib/hecks/tools/translation_audit.rb +8 -10
  195. data/lib/hecks/tools/translation_scaffold/reporting.rb +1 -1
  196. data/lib/hecks/version.rb +1 -1
  197. data/lib/hecks/vocabulary.rb +2 -1
  198. data/lib/hecks.rb +3 -0
  199. data/prebuilt/{58208399bada10b0db99928c48e38789288fc58f7b71a72b21bfa386680e32ed.marshal → 02c09c73b272c1fb5a9ae6d87bb5e5e529208e00f6b4b597dc2c0fd70a9c0964.marshal} +0 -0
  200. data/prebuilt/{2b59737fbdbd5f44edda0fddce2611f45d76087b3a7c782d1f1a17ea58c77948.marshal → bb84a835cf6a15136bad5ca03aa5bf93a5b92f5f72444618d3ef2412b987fb32.marshal} +0 -0
  201. data/prebuilt/verdicts-f1f10da14c8e8f01b4c9b7e3e2d74be8cd2bf4676364ed17fa16975d2a076d75.json +1 -0
  202. data/rust/Cargo.toml +40 -0
  203. data/rust/build/Cargo.toml +36 -0
  204. data/rust/build/clippy.toml +4 -0
  205. data/rust/build/src/adapters_pass.rs +196 -0
  206. data/rust/build/src/binding_pass.rs +54 -13
  207. data/rust/build/src/build_artifact.rs +23 -5
  208. data/rust/build/src/cargo_sync.rs +69 -26
  209. data/rust/build/src/lineage_pass.rs +101 -87
  210. data/rust/build/src/main.rs +11 -2
  211. data/rust/build/src/pipeline.rs +80 -19
  212. data/rust/build/src/reserved_names.rs +6 -50
  213. data/rust/build/src/resolve.rs +82 -35
  214. data/rust/build/src/rustfmt.rs +100 -0
  215. data/rust/build/src/seams_pass.rs +85 -16
  216. data/rust/build/src/subprocess.rs +30 -6
  217. data/rust/build/src/tmp.rs +5 -2
  218. data/rust/build/src/translation_pass.rs +72 -22
  219. data/rust/build/src/world_pass.rs +109 -0
  220. data/rust/clippy.toml +4 -0
  221. data/rust/codegen/Cargo.toml +36 -0
  222. data/rust/codegen/clippy.toml +4 -0
  223. data/rust/codegen/src/asks.rs +40 -14
  224. data/rust/codegen/src/attr.rs +2 -2
  225. data/rust/codegen/src/bridging.rs +676 -117
  226. data/rust/codegen/src/commands.rs +979 -373
  227. data/rust/codegen/src/constraints.rs +88 -25
  228. data/rust/codegen/src/dependency_planning.rs +128 -34
  229. data/rust/codegen/src/domain_generator.rs +300 -170
  230. data/rust/codegen/src/exemplar.rs +87 -32
  231. data/rust/codegen/src/expr_emitter.rs +54 -6
  232. data/rust/codegen/src/fielded.rs +193 -41
  233. data/rust/codegen/src/hecks_naming.rs +124 -16
  234. data/rust/codegen/src/hecks_naming_tests.rs +81 -0
  235. data/rust/codegen/src/json.rs +80 -44
  236. data/rust/codegen/src/json_codec.rs +585 -149
  237. data/rust/codegen/src/literal.rs +104 -138
  238. data/rust/codegen/src/main.rs +145 -52
  239. data/rust/codegen/src/manifest.rs +76 -14
  240. data/rust/codegen/src/mutations.rs +1212 -239
  241. data/rust/codegen/src/naming.rs +111 -60
  242. data/rust/codegen/src/optional_pass.rs +90 -28
  243. data/rust/codegen/src/ports.rs +5 -4
  244. data/rust/codegen/src/prelude.rs +139 -49
  245. data/rust/codegen/src/queries.rs +601 -226
  246. data/rust/codegen/src/reactions.rs +268 -74
  247. data/rust/codegen/src/read_models.rs +606 -205
  248. data/rust/codegen/src/reference_specs.rs +16 -3
  249. data/rust/codegen/src/registry.rs +128 -79
  250. data/rust/codegen/src/reserved_names.rs +6 -50
  251. data/rust/codegen/src/shared.rs +71 -22
  252. data/rust/codegen/src/sidecars.rs +15 -5
  253. data/rust/codegen/src/skip_reason.rs +8 -2
  254. data/rust/codegen/src/types.rs +306 -108
  255. data/rust/host/Cargo.lock +1 -0
  256. data/rust/host/Cargo.toml +40 -4
  257. data/rust/host/HECKS_RELEASE +1 -1
  258. data/rust/host/clippy.toml +4 -0
  259. data/rust/host/src/api.rs +698 -218
  260. data/rust/host/src/auth.rs +491 -214
  261. data/rust/host/src/b64.rs +91 -0
  262. data/rust/host/src/bin/expr_harness.rs +6 -2
  263. data/rust/host/src/bin/lineage_harness.rs +47 -11
  264. data/rust/host/src/bin/mint_harness.rs +70 -37
  265. data/rust/host/src/bin/validate_harness.rs +16 -8
  266. data/rust/host/src/boot.rs +144 -68
  267. data/rust/host/src/boundary_fuzz/api.rs +130 -32
  268. data/rust/host/src/boundary_fuzz/auth.rs +108 -23
  269. data/rust/host/src/boundary_fuzz/expr_json.rs +85 -11
  270. data/rust/host/src/boundary_fuzz/ir.rs +164 -12
  271. data/rust/host/src/boundary_fuzz/server.rs +283 -36
  272. data/rust/host/src/boundary_fuzz/web.rs +56 -8
  273. data/rust/host/src/checkout.rs +78 -32
  274. data/rust/host/src/clock.rs +8 -0
  275. data/rust/host/src/commerce_ir.rs +333 -95
  276. data/rust/host/src/crypto.rs +33 -0
  277. data/rust/host/src/dispatch.rs +990 -331
  278. data/rust/host/src/expr_json.rs +1021 -273
  279. data/rust/host/src/extension.rs +24 -4
  280. data/rust/host/src/field_hints.rs +11 -7
  281. data/rust/host/src/fuzz_support.rs +85 -13
  282. data/rust/host/src/host.rs +100 -0
  283. data/rust/host/src/http.rs +22 -0
  284. data/rust/host/src/ir.rs +326 -16
  285. data/rust/host/src/journal.rs +277 -176
  286. data/rust/host/src/lambda_client.rs +219 -53
  287. data/rust/host/src/lib.rs +16 -4
  288. data/rust/host/src/log.rs +62 -11
  289. data/rust/host/src/mint.rs +1153 -326
  290. data/rust/host/src/needs.rs +185 -44
  291. data/rust/host/src/payments/keystore.rs +197 -45
  292. data/rust/host/src/payments/roles.rs +191 -0
  293. data/rust/host/src/payments/tests.rs +1445 -275
  294. data/rust/host/src/payments.rs +409 -121
  295. data/rust/host/src/platform_signin/attack_tests.rs +5 -5
  296. data/rust/host/src/platform_signin/config.rs +11 -11
  297. data/rust/host/src/platform_signin/cookie.rs +2 -2
  298. data/rust/host/src/platform_signin/extension.rs +2 -1
  299. data/rust/host/src/platform_signin/handler.rs +9 -8
  300. data/rust/host/src/platform_signin/jti.rs +4 -2
  301. data/rust/host/src/platform_signin/jwks.rs +2 -1
  302. data/rust/host/src/platform_signin/jws.rs +2 -37
  303. data/rust/host/src/platform_signin/known_answer_tests.rs +5 -1
  304. data/rust/host/src/platform_signin/mode_tests.rs +5 -3
  305. data/rust/host/src/platform_signin/pages.rs +20 -20
  306. data/rust/host/src/platform_signin/session.rs +8 -1
  307. data/rust/host/src/platform_signin/settings.rs +6 -6
  308. data/rust/host/src/platform_signin/strict_json.rs +12 -9
  309. data/rust/host/src/platform_signin/verify.rs +41 -41
  310. data/rust/host/src/platform_signin/wiring_support.rs +13 -18
  311. data/rust/host/src/presentation.rs +207 -63
  312. data/rust/host/src/presentation_write.rs +502 -187
  313. data/rust/host/src/query_step.rs +69 -18
  314. data/rust/host/src/rate_limit.rs +541 -142
  315. data/rust/host/src/reference_transform.rs +77 -25
  316. data/rust/host/src/reference_validate.rs +443 -104
  317. data/rust/host/src/resend.rs +190 -55
  318. data/rust/host/src/secrets.rs +116 -21
  319. data/rust/host/src/server.rs +483 -104
  320. data/rust/host/src/storage_shape.rs +88 -21
  321. data/rust/host/src/test_pg.rs +17 -7
  322. data/rust/host/src/ui_schema.rs +495 -207
  323. data/rust/host/src/wasm_runner.rs +21 -6
  324. data/rust/host/src/web/commerce.rs +101 -23
  325. data/rust/host/src/web/newsletter/cooldown.rs +10 -3
  326. data/rust/host/src/web/newsletter/template.rs +26 -7
  327. data/rust/host/src/web/newsletter/tests.rs +112 -23
  328. data/rust/host/src/web/newsletter.rs +209 -59
  329. data/rust/host/src/web/newsletter_send.rs +251 -79
  330. data/rust/host/src/web/registration_receipt/tests.rs +16 -4
  331. data/rust/host/src/web/registration_receipt.rs +100 -24
  332. data/rust/host/src/web/registrations.rs +1384 -332
  333. data/rust/host/src/web/resend_webhook.rs +138 -80
  334. data/rust/host/src/web.rs +2416 -508
  335. data/rust/lsp/Cargo.toml +36 -0
  336. data/rust/lsp/clippy.toml +4 -0
  337. data/rust/lsp/src/json.rs +29 -22
  338. data/rust/lsp/src/main.rs +81 -31
  339. data/rust/lsp/src/outline.rs +23 -7
  340. data/rust/lsp/src/rpc.rs +17 -4
  341. data/rust/parser/Cargo.toml +36 -0
  342. data/rust/parser/clippy.toml +4 -0
  343. data/rust/parser/src/build/closed_sets.rs +6 -1
  344. data/rust/parser/src/build/identity.rs +4 -3
  345. data/rust/parser/src/build/mod.rs +1 -0
  346. data/rust/parser/src/build/named_pattern.rs +26 -0
  347. data/rust/parser/src/build/naming.rs +2 -80
  348. data/rust/parser/src/build/pattern_subset.rs +6 -8
  349. data/rust/parser/src/build/query_derive.rs +3 -1
  350. data/rust/parser/src/build/query_inference.rs +14 -5
  351. data/rust/parser/src/build/read_model.rs +4 -1
  352. data/rust/parser/src/build/references.rs +4 -3
  353. data/rust/parser/src/canonical.rs +34 -15
  354. data/rust/parser/src/emit.rs +187 -105
  355. data/rust/parser/src/expr/ast_json.rs +134 -42
  356. data/rust/parser/src/expr/evaluator.rs +27 -9
  357. data/rust/parser/src/expr/mod.rs +54 -13
  358. data/rust/parser/src/expr/resolver.rs +299 -92
  359. data/rust/parser/src/ir.rs +35 -3
  360. data/rust/parser/src/keywords.rs +7168 -510
  361. data/rust/parser/src/lex.rs +11 -25
  362. data/rust/parser/src/lib.rs +1 -0
  363. data/rust/parser/src/main.rs +65 -6
  364. data/rust/parser/src/parse/adapter.rs +157 -0
  365. data/rust/parser/src/parse/aggregate.rs +19 -10
  366. data/rust/parser/src/parse/chapter.rs +16 -17
  367. data/rust/parser/src/parse/command.rs +35 -16
  368. data/rust/parser/src/parse/domain_port.rs +4 -7
  369. data/rust/parser/src/parse/entity.rs +21 -11
  370. data/rust/parser/src/parse/hecksagon.rs +10 -4
  371. data/rust/parser/src/parse/lifecycle.rs +9 -5
  372. data/rust/parser/src/parse/mod.rs +43 -91
  373. data/rust/parser/src/parse/needs.rs +21 -12
  374. data/rust/parser/src/parse/policy.rs +2 -2
  375. data/rust/parser/src/parse/process_manager.rs +9 -11
  376. data/rust/parser/src/parse/query.rs +8 -4
  377. data/rust/parser/src/parse/read_model.rs +57 -16
  378. data/rust/parser/src/parse/value_object.rs +7 -2
  379. data/rust/parser/src/parse/world.rs +322 -0
  380. data/rust/parser/src/ruby_value.rs +7 -6
  381. data/rust/src/exemplar/json.rs +4 -4
  382. data/rust/src/exemplar/mutations.rs +18 -0
  383. data/rust/src/exemplar/read_models.rs +1 -10
  384. data/rust/src/kernel/attribute_shapes/composite.rs +54 -14
  385. data/rust/src/kernel/attribute_shapes/list.rs +2 -2
  386. data/rust/src/kernel/attribute_shapes/mod.rs +8 -8
  387. data/rust/src/kernel/attribute_shapes/scalar.rs +2 -2
  388. data/rust/src/kernel/cli.rs +229 -112
  389. data/rust/src/kernel/dispatch.rs +323 -115
  390. data/rust/src/kernel/dispatch_guard_tests.rs +327 -65
  391. data/rust/src/kernel/expr.rs +203 -86
  392. data/rust/src/kernel/expression_operators/arithmetic.rs +138 -25
  393. data/rust/src/kernel/expression_operators/comparison.rs +87 -2
  394. data/rust/src/kernel/expression_operators/enumeration.rs +106 -22
  395. data/rust/src/kernel/expression_operators/logical.rs +9 -3
  396. data/rust/src/kernel/expression_operators/membership.rs +3 -1
  397. data/rust/src/kernel/expression_operators/mod.rs +34 -21
  398. data/rust/src/kernel/expression_operators/pattern_match.rs +46 -11
  399. data/rust/src/kernel/expression_operators/positional.rs +84 -30
  400. data/rust/src/kernel/expression_operators/presence.rs +52 -13
  401. data/rust/src/kernel/expression_operators/sign_test.rs +3 -1
  402. data/rust/src/kernel/expression_operators/sized.rs +24 -8
  403. data/rust/src/kernel/expression_operators/text.rs +120 -27
  404. data/rust/src/kernel/expression_operators/to_string.rs +10 -4
  405. data/rust/src/kernel/json.rs +230 -148
  406. data/rust/src/kernel/mod.rs +46 -33
  407. data/rust/src/kernel/named_query.rs +63 -15
  408. data/rust/src/kernel/needs.rs +112 -25
  409. data/rust/src/kernel/orchestrate.rs +980 -581
  410. data/rust/src/kernel/orchestrate_guard_tests.rs +538 -140
  411. data/rust/src/kernel/pattern.rs +107 -34
  412. data/rust/src/kernel/query_comparators.rs +118 -41
  413. data/rust/src/kernel/query_ordering.rs +13 -5
  414. data/rust/src/kernel/read_model.rs +479 -181
  415. data/rust/src/kernel/reference_lookup.rs +122 -26
  416. data/rust/src/kernel/repository.rs +293 -66
  417. data/rust/src/kernel/routing.rs +58 -42
  418. data/rust/src/kernel/ruby_float.rs +139 -0
  419. data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +57 -57
  420. data/rust/src/kernel/vocab/entity_dispatch_order.rs +54 -54
  421. data/rust/src/kernel/vocab/field_hint.rs +19 -25
  422. data/rust/src/kernel/vocab/mod.rs +6 -6
  423. data/rust/src/kernel/vocab/query_comparator.rs +23 -24
  424. data/rust/src/kernel/vocab/refusal_template.rs +501 -297
  425. data/rust/src/lib.rs +50 -0
  426. data/rust/src/main.rs +4 -1
  427. data/rust/web/Cargo.toml +36 -0
  428. data/rust/web/clippy.toml +4 -0
  429. metadata +85 -15
  430. data/examples/pizzas/bluebook/hecksagon/mock_stripe_payment_adapter.rb +0 -36
  431. data/lib/hecks/adapters/driven/google_authentication.adapter +0 -3
  432. data/lib/hecks/adapters/driven/google_authentication.rb +0 -99
  433. data/lib/hecks/adapters/driven/mock_stripe_adapter.adapter +0 -3
  434. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +0 -32
  435. data/lib/hecks/ports/authentication.port +0 -6
  436. data/lib/hecks/ports/authentication.rb +0 -67
  437. data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +0 -255
  438. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +0 -22
  439. data/prebuilt/verdicts-48318ca172edd21443b1ad02801c697fff100b746e828f09db987647641a5df2.json +0 -1
  440. data/rust/host/src/approval.rs +0 -652
@@ -102,6 +102,16 @@ impl RoutingEnvelope {
102
102
  }
103
103
  }
104
104
 
105
+ /// Step-envelope keys (`verb`, `role`, ...) are not facts, so `with:` may sit beside them.
106
+ const STEP_ENVELOPE_KEYS: [&str; 6] = [
107
+ "verb",
108
+ "role",
109
+ "actor_id",
110
+ "occurred_at",
111
+ "dry_run",
112
+ "query",
113
+ ];
114
+
105
115
  #[derive(Debug, Clone, PartialEq)]
106
116
  pub struct CommandInvocation {
107
117
  route: Option<RoutingEnvelope>,
@@ -121,15 +131,14 @@ impl CommandInvocation {
121
131
  /// The facts source depends on `with:` alone, never on `to:`.
122
132
  pub fn from_json(value: &Json) -> Result<Self, Refusal> {
123
133
  let target = non_null(value.get("to"));
124
- let explicit_facts = non_null(value.get("with"));
125
- if explicit_facts.is_none() {
134
+ let Some(explicit_facts) = non_null(value.get("with")) else {
126
135
  let route = target.map(RoutingEnvelope::from_json).transpose()?;
127
136
  return Ok(Self {
128
137
  route,
129
138
  facts: strip_routing_keys(value),
130
139
  explicit: false,
131
140
  });
132
- }
141
+ };
133
142
 
134
143
  if value.get("args").is_some() {
135
144
  return Err(routing_refusal("cannot combine to/with with legacy args"));
@@ -137,42 +146,40 @@ impl CommandInvocation {
137
146
 
138
147
  // `with:` beside a loose fact is refused, as Ruby's `Routing.payload` refuses it.
139
148
  // Step-envelope keys (`verb`, `role`, ...) are not facts and are exempt.
140
- const STEP_ENVELOPE_KEYS: [&str; 6] =
141
- ["verb", "role", "actor_id", "occurred_at", "dry_run", "query"];
142
- if explicit_facts.is_some() {
143
- if let Json::Object(fields) = value {
144
- let extra = fields
145
- .iter()
146
- .any(|(key, _)| key != "to" && key != "with" && !STEP_ENVELOPE_KEYS.contains(&key.as_str()));
147
- if extra {
148
- return Err(routing_refusal(
149
- "with: takes command facts, not both with: and loose keyword arguments",
150
- ));
151
- }
149
+ if let Json::Object(fields) = value {
150
+ let extra = fields.iter().any(|(key, _)| {
151
+ key != "to" && key != "with" && !STEP_ENVELOPE_KEYS.contains(&key.as_str())
152
+ });
153
+ if extra {
154
+ return Err(routing_refusal(
155
+ "with: takes command facts, not both with: and loose keyword arguments",
156
+ ));
152
157
  }
153
158
  }
154
159
 
155
160
  let route = target.map(RoutingEnvelope::from_json).transpose()?;
156
- let facts = explicit_facts
157
- .cloned()
158
- .expect("explicit_facts checked Some above");
161
+ let facts = explicit_facts.clone();
159
162
  if !matches!(facts, Json::Object(_)) {
160
163
  return Err(routing_refusal("with must be an object of command facts"));
161
164
  }
162
165
 
163
- Ok(Self { route, facts, explicit: true })
166
+ Ok(Self {
167
+ route,
168
+ facts,
169
+ explicit: true,
170
+ })
164
171
  }
165
172
 
166
- pub fn route(&self) -> Option<&RoutingEnvelope> {
173
+ pub const fn route(&self) -> Option<&RoutingEnvelope> {
167
174
  self.route.as_ref()
168
175
  }
169
176
 
170
- pub fn facts(&self) -> &Json {
177
+ pub const fn facts(&self) -> &Json {
171
178
  &self.facts
172
179
  }
173
180
 
174
181
  /// True when this call used the explicit `with:` shape, false for flat facts.
175
- pub fn explicit_with(&self) -> bool {
182
+ pub const fn explicit_with(&self) -> bool {
176
183
  self.explicit
177
184
  }
178
185
 
@@ -358,21 +365,24 @@ mod tests {
358
365
  assert_eq!(invocation.route(), None);
359
366
  assert_eq!(
360
367
  invocation.facts(),
361
- &Json::obj(vec![("name", Json::obj(vec![("value", Json::str("golf"))]))])
368
+ &Json::obj(vec![(
369
+ "name",
370
+ Json::obj(vec![("value", Json::str("golf"))])
371
+ )])
362
372
  );
363
373
  }
364
374
 
365
375
  // Same for a null `with`: read as the no-`to:` shape; the null key is dropped from the facts.
366
376
  #[test]
367
377
  fn null_with_and_no_to_key_is_read_as_legacy_shape_not_explicit_facts() {
368
- let input = Json::obj(vec![
369
- ("with", Json::Null),
370
- ("amount", Json::int(20)),
371
- ]);
378
+ let input = Json::obj(vec![("with", Json::Null), ("amount", Json::int(20))]);
372
379
 
373
380
  let invocation = CommandInvocation::from_json(&input).unwrap();
374
381
  assert_eq!(invocation.route(), None);
375
- assert_eq!(invocation.facts(), &Json::obj(vec![("amount", Json::int(20))]));
382
+ assert_eq!(
383
+ invocation.facts(),
384
+ &Json::obj(vec![("amount", Json::int(20))])
385
+ );
376
386
  }
377
387
 
378
388
  // A non-null `to` is always parsed as a route, even when a domain fact is named `to`.
@@ -381,7 +391,9 @@ mod tests {
381
391
  let input = Json::obj(vec![("to", Json::obj(vec![("value", Json::int(282))]))]);
382
392
 
383
393
  let err = CommandInvocation::from_json(&input).unwrap_err();
384
- assert!(err.to_string().contains("entity route requires a scalar aggregate identity"));
394
+ assert!(err
395
+ .to_string()
396
+ .contains("entity route requires a scalar aggregate identity"));
385
397
  }
386
398
 
387
399
  // A real `to:` with flat facts and no `with:` must keep the facts; only `with:` selects them.
@@ -396,7 +408,10 @@ mod tests {
396
408
  let route = invocation.route().unwrap();
397
409
  route.require_depth(0).unwrap();
398
410
  assert_eq!(route.aggregate(), "ORDER-7");
399
- assert_eq!(invocation.facts(), &Json::obj(vec![("quantity", Json::int(3))]));
411
+ assert_eq!(
412
+ invocation.facts(),
413
+ &Json::obj(vec![("quantity", Json::int(3))])
414
+ );
400
415
  }
401
416
 
402
417
  // Same, with an entity route as `to:`.
@@ -427,14 +442,14 @@ mod tests {
427
442
  // Same, with `to: null` beside real facts.
428
443
  #[test]
429
444
  fn null_to_alongside_real_facts_keeps_the_flat_facts() {
430
- let input = Json::obj(vec![
431
- ("to", Json::Null),
432
- ("quantity", Json::int(3)),
433
- ]);
445
+ let input = Json::obj(vec![("to", Json::Null), ("quantity", Json::int(3))]);
434
446
 
435
447
  let invocation = CommandInvocation::from_json(&input).unwrap();
436
448
  assert_eq!(invocation.route(), None);
437
- assert_eq!(invocation.facts(), &Json::obj(vec![("quantity", Json::int(3))]));
449
+ assert_eq!(
450
+ invocation.facts(),
451
+ &Json::obj(vec![("quantity", Json::int(3))])
452
+ );
438
453
  }
439
454
 
440
455
  // `explicit_with()` is true only when the explicit `with:` branch was taken.
@@ -461,11 +476,8 @@ mod tests {
461
476
  .unwrap();
462
477
  assert!(!legacy_with_to.explicit_with());
463
478
 
464
- let legacy_no_to = CommandInvocation::from_json(&Json::obj(vec![(
465
- "amount",
466
- Json::int(20),
467
- )]))
468
- .unwrap();
479
+ let legacy_no_to =
480
+ CommandInvocation::from_json(&Json::obj(vec![("amount", Json::int(20))])).unwrap();
469
481
  assert!(!legacy_no_to.explicit_with());
470
482
 
471
483
  let legacy_null_with = CommandInvocation::from_json(&Json::obj(vec![
@@ -499,7 +511,9 @@ mod tests {
499
511
  ),
500
512
  ]))
501
513
  .unwrap();
502
- let (receiver, facts) = explicit.split_aggregate_receiver(Some("order"), None).unwrap();
514
+ let (receiver, facts) = explicit
515
+ .split_aggregate_receiver(Some("order"), None)
516
+ .unwrap();
503
517
  assert_eq!(receiver, "ORDER-7");
504
518
  assert_eq!(facts, Json::obj(vec![("amount", Json::int(20))]));
505
519
 
@@ -508,7 +522,9 @@ mod tests {
508
522
  ("amount", Json::int(30)),
509
523
  ]))
510
524
  .unwrap();
511
- let (receiver, facts) = legacy.split_aggregate_receiver(Some("order"), None).unwrap();
525
+ let (receiver, facts) = legacy
526
+ .split_aggregate_receiver(Some("order"), None)
527
+ .unwrap();
512
528
  assert_eq!(receiver, "ORDER-8");
513
529
  assert_eq!(facts, Json::obj(vec![("amount", Json::int(30))]));
514
530
 
@@ -0,0 +1,139 @@
1
+ //! Ruby-style `Float#to_s` and the finite-result check shared by float arithmetic.
2
+ //!
3
+ //! Fault wording quotes operands the way Ruby prints them (`1.0e+308`, not Rust's 309-digit
4
+ //! expansion), so a Fault from either runtime reads the same.
5
+
6
+ use crate::kernel::Refusal;
7
+
8
+ // Ruby switches to scientific notation when the decimal point sits left of 1e-4 or right of 1e16.
9
+ const FIXED_MIN_EXPONENT: i32 = -4;
10
+ const FIXED_MAX_EXPONENT: i32 = 15;
11
+
12
+ /// `Float#to_s`: shortest round-trip digits, fixed notation for `1e-4 <= |n| < 1e16`, else `d.ddde+XX`.
13
+ pub fn to_s(n: f64) -> String {
14
+ if n.is_nan() {
15
+ return "NaN".to_string();
16
+ }
17
+ if n.is_infinite() {
18
+ return if n < 0.0 { "-Infinity" } else { "Infinity" }.to_string();
19
+ }
20
+ let sign = if n.is_sign_negative() { "-" } else { "" };
21
+ if n == 0.0 {
22
+ return format!("{sign}0.0");
23
+ }
24
+ // `{:e}` yields the shortest round-trip digits as `d.ddde<exp>`.
25
+ let scientific = format!("{:e}", n.abs());
26
+ let (mantissa, exponent) = scientific.split_once('e').unwrap_or((&scientific, "0"));
27
+ let exponent: i32 = exponent.parse().unwrap_or(0);
28
+ let digits: String = mantissa.chars().filter(char::is_ascii_digit).collect();
29
+ if (FIXED_MIN_EXPONENT..=FIXED_MAX_EXPONENT).contains(&exponent) {
30
+ return format!("{sign}{}", fixed(&digits, exponent));
31
+ }
32
+ let (head, tail) = digits.split_at(1);
33
+ let tail = if tail.is_empty() { "0" } else { tail };
34
+ let exponent_sign = if exponent < 0 { '-' } else { '+' };
35
+ format!("{sign}{head}.{tail}e{exponent_sign}{:02}", exponent.abs())
36
+ }
37
+
38
+ // Places the decimal point `exponent` digits after the first digit, padding zeros as needed.
39
+ fn fixed(digits: &str, exponent: i32) -> String {
40
+ if exponent < 0 {
41
+ let zeros = "0".repeat(exponent.unsigned_abs() as usize - 1);
42
+ return format!("0.{zeros}{digits}");
43
+ }
44
+ let whole_len = exponent as usize + 1;
45
+ if digits.len() <= whole_len {
46
+ let zeros = "0".repeat(whole_len - digits.len());
47
+ return format!("{digits}{zeros}.0");
48
+ }
49
+ let (whole, fraction) = digits.split_at(whole_len);
50
+ format!("{whole}.{fraction}")
51
+ }
52
+
53
+ /// Passes a float arithmetic `result` through only if finite; else the C3.4 Fault.
54
+ ///
55
+ /// Ruby quotes the right operand by absolute value, so a decrement still reads `a - |b|`.
56
+ pub fn finite_or_fault(
57
+ op: &str,
58
+ symbol: &str,
59
+ lhs: f64,
60
+ rhs: f64,
61
+ result: f64,
62
+ ) -> Result<f64, Refusal> {
63
+ if result.is_finite() {
64
+ return Ok(result);
65
+ }
66
+ Err(Refusal::Fault(format!(
67
+ "{op} overflowed: {} {symbol} {} is not a finite number",
68
+ to_s(lhs),
69
+ to_s(rhs.abs())
70
+ )))
71
+ }
72
+
73
+ #[cfg(test)]
74
+ mod tests {
75
+ use super::*;
76
+
77
+ #[test]
78
+ fn whole_numbers_keep_a_decimal_point() {
79
+ assert_eq!(to_s(1.0), "1.0");
80
+ assert_eq!(to_s(-250.0), "-250.0");
81
+ assert_eq!(to_s(0.0), "0.0");
82
+ }
83
+
84
+ #[test]
85
+ fn fractions_print_shortest_round_trip_digits() {
86
+ assert_eq!(to_s(0.1), "0.1");
87
+ assert_eq!(to_s(1.5), "1.5");
88
+ assert_eq!(to_s(0.0001), "0.0001");
89
+ assert_eq!(to_s(123_456.789), "123456.789");
90
+ }
91
+
92
+ #[test]
93
+ fn large_magnitudes_switch_to_scientific_at_1e16() {
94
+ assert_eq!(to_s(1.0e15), "1000000000000000.0");
95
+ assert_eq!(to_s(1.0e16), "1.0e+16");
96
+ assert_eq!(to_s(1.0e308), "1.0e+308");
97
+ assert_eq!(to_s(1.5e20), "1.5e+20");
98
+ }
99
+
100
+ #[test]
101
+ fn small_magnitudes_switch_to_scientific_below_1e_4() {
102
+ assert_eq!(to_s(0.00001), "1.0e-05");
103
+ assert_eq!(to_s(1.25e-7), "1.25e-07");
104
+ }
105
+
106
+ #[test]
107
+ fn non_finite_values_use_rubys_names() {
108
+ assert_eq!(to_s(f64::INFINITY), "Infinity");
109
+ assert_eq!(to_s(f64::NEG_INFINITY), "-Infinity");
110
+ assert_eq!(to_s(f64::NAN), "NaN");
111
+ }
112
+
113
+ #[test]
114
+ fn an_infinite_result_faults_with_rubys_wording() {
115
+ let fault = finite_or_fault("increment", "+", 1.0e308, 1.0e308, f64::INFINITY);
116
+ assert_eq!(
117
+ fault,
118
+ Err(Refusal::Fault(
119
+ "increment overflowed: 1.0e+308 + 1.0e+308 is not a finite number".to_string()
120
+ ))
121
+ );
122
+ }
123
+
124
+ #[test]
125
+ fn a_decrement_quotes_the_amount_by_absolute_value() {
126
+ let fault = finite_or_fault("decrement", "-", -1.0e308, -1.0e308, f64::NEG_INFINITY);
127
+ assert_eq!(
128
+ fault,
129
+ Err(Refusal::Fault(
130
+ "decrement overflowed: -1.0e+308 - 1.0e+308 is not a finite number".to_string()
131
+ ))
132
+ );
133
+ }
134
+
135
+ #[test]
136
+ fn a_finite_result_passes_through() {
137
+ assert_eq!(finite_or_fault("multiply", "*", 2.0, 3.0, 6.0), Ok(6.0));
138
+ }
139
+ }
@@ -26,74 +26,74 @@ pub enum AggregateStep {
26
26
 
27
27
  impl AggregateStep {
28
28
  /// The declared step order, first to last.
29
- pub const ORDER: [AggregateStep; 17] = [
30
- AggregateStep::DecodeArguments,
31
- AggregateStep::RefuseUnknownArguments,
32
- AggregateStep::RefuseAbsentArguments,
33
- AggregateStep::NormalizeArgs,
34
- AggregateStep::RefuseRoleMismatch,
35
- AggregateStep::ResolveReferences,
36
- AggregateStep::Hydrate,
37
- AggregateStep::EnforceGivens,
38
- AggregateStep::AdmissibleTransition,
39
- AggregateStep::AssignCreationAttributes,
40
- AggregateStep::ApplyMutations,
41
- AggregateStep::AdvanceLifecycle,
42
- AggregateStep::DelegateToEntity,
43
- AggregateStep::EnforceEnsures,
44
- AggregateStep::EnforceInvariants,
45
- AggregateStep::Save,
46
- AggregateStep::Emit,
29
+ pub const ORDER: [Self; 17] = [
30
+ Self::DecodeArguments,
31
+ Self::RefuseUnknownArguments,
32
+ Self::RefuseAbsentArguments,
33
+ Self::NormalizeArgs,
34
+ Self::RefuseRoleMismatch,
35
+ Self::ResolveReferences,
36
+ Self::Hydrate,
37
+ Self::EnforceGivens,
38
+ Self::AdmissibleTransition,
39
+ Self::AssignCreationAttributes,
40
+ Self::ApplyMutations,
41
+ Self::AdvanceLifecycle,
42
+ Self::DelegateToEntity,
43
+ Self::EnforceEnsures,
44
+ Self::EnforceInvariants,
45
+ Self::Save,
46
+ Self::Emit,
47
47
  ];
48
48
 
49
49
  /// The row's declared `step`.
50
- pub fn step(&self) -> &'static str {
50
+ pub const fn step(&self) -> &'static str {
51
51
  match self {
52
- AggregateStep::DecodeArguments => "decode_arguments",
53
- AggregateStep::RefuseUnknownArguments => "refuse_unknown_arguments",
54
- AggregateStep::RefuseAbsentArguments => "refuse_absent_arguments",
55
- AggregateStep::NormalizeArgs => "normalize_args",
56
- AggregateStep::RefuseRoleMismatch => "refuse_role_mismatch",
57
- AggregateStep::ResolveReferences => "resolve_references",
58
- AggregateStep::Hydrate => "hydrate",
59
- AggregateStep::EnforceGivens => "enforce_givens",
60
- AggregateStep::AdmissibleTransition => "admissible_transition",
61
- AggregateStep::AssignCreationAttributes => "assign_creation_attributes",
62
- AggregateStep::ApplyMutations => "apply_mutations",
63
- AggregateStep::AdvanceLifecycle => "advance_lifecycle",
64
- AggregateStep::DelegateToEntity => "delegate_to_entity",
65
- AggregateStep::EnforceEnsures => "enforce_ensures",
66
- AggregateStep::EnforceInvariants => "enforce_invariants",
67
- AggregateStep::Save => "save",
68
- AggregateStep::Emit => "emit",
52
+ Self::DecodeArguments => "decode_arguments",
53
+ Self::RefuseUnknownArguments => "refuse_unknown_arguments",
54
+ Self::RefuseAbsentArguments => "refuse_absent_arguments",
55
+ Self::NormalizeArgs => "normalize_args",
56
+ Self::RefuseRoleMismatch => "refuse_role_mismatch",
57
+ Self::ResolveReferences => "resolve_references",
58
+ Self::Hydrate => "hydrate",
59
+ Self::EnforceGivens => "enforce_givens",
60
+ Self::AdmissibleTransition => "admissible_transition",
61
+ Self::AssignCreationAttributes => "assign_creation_attributes",
62
+ Self::ApplyMutations => "apply_mutations",
63
+ Self::AdvanceLifecycle => "advance_lifecycle",
64
+ Self::DelegateToEntity => "delegate_to_entity",
65
+ Self::EnforceEnsures => "enforce_ensures",
66
+ Self::EnforceInvariants => "enforce_invariants",
67
+ Self::Save => "save",
68
+ Self::Emit => "emit",
69
69
  }
70
70
  }
71
71
 
72
72
  /// The row whose `step` is `name`, if any.
73
- pub fn from_name(name: &str) -> Option<AggregateStep> {
74
- AggregateStep::ORDER.iter().copied().find(|row| row.step() == name)
73
+ pub fn from_name(name: &str) -> Option<Self> {
74
+ Self::ORDER.iter().copied().find(|row| row.step() == name)
75
75
  }
76
76
 
77
77
  /// This step's index in `ORDER`.
78
- pub fn position(&self) -> usize {
78
+ pub const fn position(&self) -> usize {
79
79
  match self {
80
- AggregateStep::DecodeArguments => 0,
81
- AggregateStep::RefuseUnknownArguments => 1,
82
- AggregateStep::RefuseAbsentArguments => 2,
83
- AggregateStep::NormalizeArgs => 3,
84
- AggregateStep::RefuseRoleMismatch => 4,
85
- AggregateStep::ResolveReferences => 5,
86
- AggregateStep::Hydrate => 6,
87
- AggregateStep::EnforceGivens => 7,
88
- AggregateStep::AdmissibleTransition => 8,
89
- AggregateStep::AssignCreationAttributes => 9,
90
- AggregateStep::ApplyMutations => 10,
91
- AggregateStep::AdvanceLifecycle => 11,
92
- AggregateStep::DelegateToEntity => 12,
93
- AggregateStep::EnforceEnsures => 13,
94
- AggregateStep::EnforceInvariants => 14,
95
- AggregateStep::Save => 15,
96
- AggregateStep::Emit => 16,
80
+ Self::DecodeArguments => 0,
81
+ Self::RefuseUnknownArguments => 1,
82
+ Self::RefuseAbsentArguments => 2,
83
+ Self::NormalizeArgs => 3,
84
+ Self::RefuseRoleMismatch => 4,
85
+ Self::ResolveReferences => 5,
86
+ Self::Hydrate => 6,
87
+ Self::EnforceGivens => 7,
88
+ Self::AdmissibleTransition => 8,
89
+ Self::AssignCreationAttributes => 9,
90
+ Self::ApplyMutations => 10,
91
+ Self::AdvanceLifecycle => 11,
92
+ Self::DelegateToEntity => 12,
93
+ Self::EnforceEnsures => 13,
94
+ Self::EnforceInvariants => 14,
95
+ Self::Save => 15,
96
+ Self::Emit => 16,
97
97
  }
98
98
  }
99
99
  }
@@ -104,7 +104,7 @@ mod tests {
104
104
 
105
105
  #[test]
106
106
  fn every_row_is_found_by_its_own_name() {
107
- for row in AggregateStep::ORDER.iter() {
107
+ for row in &AggregateStep::ORDER {
108
108
  assert_eq!(AggregateStep::from_name(row.step()), Some(*row));
109
109
  }
110
110
  }
@@ -25,71 +25,71 @@ pub enum EntityStep {
25
25
 
26
26
  impl EntityStep {
27
27
  /// The declared step order, first to last.
28
- pub const ORDER: [EntityStep; 16] = [
29
- EntityStep::DecodeArguments,
30
- EntityStep::RefuseUnknownArguments,
31
- EntityStep::RefuseAbsentArguments,
32
- EntityStep::NormalizeArgs,
33
- EntityStep::RefuseRoleMismatch,
34
- EntityStep::ResolveReferences,
35
- EntityStep::HydrateParent,
36
- EntityStep::LocateElement,
37
- EntityStep::EnforceGivens,
38
- EntityStep::AdmissibleTransition,
39
- EntityStep::ApplyMutations,
40
- EntityStep::AdvanceLifecycle,
41
- EntityStep::EnforceEnsures,
42
- EntityStep::EnforceInvariants,
43
- EntityStep::Save,
44
- EntityStep::Emit,
28
+ pub const ORDER: [Self; 16] = [
29
+ Self::DecodeArguments,
30
+ Self::RefuseUnknownArguments,
31
+ Self::RefuseAbsentArguments,
32
+ Self::NormalizeArgs,
33
+ Self::RefuseRoleMismatch,
34
+ Self::ResolveReferences,
35
+ Self::HydrateParent,
36
+ Self::LocateElement,
37
+ Self::EnforceGivens,
38
+ Self::AdmissibleTransition,
39
+ Self::ApplyMutations,
40
+ Self::AdvanceLifecycle,
41
+ Self::EnforceEnsures,
42
+ Self::EnforceInvariants,
43
+ Self::Save,
44
+ Self::Emit,
45
45
  ];
46
46
 
47
47
  /// The row's declared `step`.
48
- pub fn step(&self) -> &'static str {
48
+ pub const fn step(&self) -> &'static str {
49
49
  match self {
50
- EntityStep::DecodeArguments => "decode_arguments",
51
- EntityStep::RefuseUnknownArguments => "refuse_unknown_arguments",
52
- EntityStep::RefuseAbsentArguments => "refuse_absent_arguments",
53
- EntityStep::NormalizeArgs => "normalize_args",
54
- EntityStep::RefuseRoleMismatch => "refuse_role_mismatch",
55
- EntityStep::ResolveReferences => "resolve_references",
56
- EntityStep::HydrateParent => "hydrate_parent",
57
- EntityStep::LocateElement => "locate_element",
58
- EntityStep::EnforceGivens => "enforce_givens",
59
- EntityStep::AdmissibleTransition => "admissible_transition",
60
- EntityStep::ApplyMutations => "apply_mutations",
61
- EntityStep::AdvanceLifecycle => "advance_lifecycle",
62
- EntityStep::EnforceEnsures => "enforce_ensures",
63
- EntityStep::EnforceInvariants => "enforce_invariants",
64
- EntityStep::Save => "save",
65
- EntityStep::Emit => "emit",
50
+ Self::DecodeArguments => "decode_arguments",
51
+ Self::RefuseUnknownArguments => "refuse_unknown_arguments",
52
+ Self::RefuseAbsentArguments => "refuse_absent_arguments",
53
+ Self::NormalizeArgs => "normalize_args",
54
+ Self::RefuseRoleMismatch => "refuse_role_mismatch",
55
+ Self::ResolveReferences => "resolve_references",
56
+ Self::HydrateParent => "hydrate_parent",
57
+ Self::LocateElement => "locate_element",
58
+ Self::EnforceGivens => "enforce_givens",
59
+ Self::AdmissibleTransition => "admissible_transition",
60
+ Self::ApplyMutations => "apply_mutations",
61
+ Self::AdvanceLifecycle => "advance_lifecycle",
62
+ Self::EnforceEnsures => "enforce_ensures",
63
+ Self::EnforceInvariants => "enforce_invariants",
64
+ Self::Save => "save",
65
+ Self::Emit => "emit",
66
66
  }
67
67
  }
68
68
 
69
69
  /// The row whose `step` is `name`, if any.
70
- pub fn from_name(name: &str) -> Option<EntityStep> {
71
- EntityStep::ORDER.iter().copied().find(|row| row.step() == name)
70
+ pub fn from_name(name: &str) -> Option<Self> {
71
+ Self::ORDER.iter().copied().find(|row| row.step() == name)
72
72
  }
73
73
 
74
74
  /// This step's index in `ORDER`.
75
- pub fn position(&self) -> usize {
75
+ pub const fn position(&self) -> usize {
76
76
  match self {
77
- EntityStep::DecodeArguments => 0,
78
- EntityStep::RefuseUnknownArguments => 1,
79
- EntityStep::RefuseAbsentArguments => 2,
80
- EntityStep::NormalizeArgs => 3,
81
- EntityStep::RefuseRoleMismatch => 4,
82
- EntityStep::ResolveReferences => 5,
83
- EntityStep::HydrateParent => 6,
84
- EntityStep::LocateElement => 7,
85
- EntityStep::EnforceGivens => 8,
86
- EntityStep::AdmissibleTransition => 9,
87
- EntityStep::ApplyMutations => 10,
88
- EntityStep::AdvanceLifecycle => 11,
89
- EntityStep::EnforceEnsures => 12,
90
- EntityStep::EnforceInvariants => 13,
91
- EntityStep::Save => 14,
92
- EntityStep::Emit => 15,
77
+ Self::DecodeArguments => 0,
78
+ Self::RefuseUnknownArguments => 1,
79
+ Self::RefuseAbsentArguments => 2,
80
+ Self::NormalizeArgs => 3,
81
+ Self::RefuseRoleMismatch => 4,
82
+ Self::ResolveReferences => 5,
83
+ Self::HydrateParent => 6,
84
+ Self::LocateElement => 7,
85
+ Self::EnforceGivens => 8,
86
+ Self::AdmissibleTransition => 9,
87
+ Self::ApplyMutations => 10,
88
+ Self::AdvanceLifecycle => 11,
89
+ Self::EnforceEnsures => 12,
90
+ Self::EnforceInvariants => 13,
91
+ Self::Save => 14,
92
+ Self::Emit => 15,
93
93
  }
94
94
  }
95
95
  }
@@ -100,7 +100,7 @@ mod tests {
100
100
 
101
101
  #[test]
102
102
  fn every_row_is_found_by_its_own_name() {
103
- for row in EntityStep::ORDER.iter() {
103
+ for row in &EntityStep::ORDER {
104
104
  assert_eq!(EntityStep::from_name(row.step()), Some(*row));
105
105
  }
106
106
  }