hecks 1.3.0 → 1.4.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 (355) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hecks/adapters/driven/claude_code.rb +7 -7
  3. data/lib/hecks/adapters/driven/d1.rb +187 -23
  4. data/lib/hecks/adapters/driven/folder.rb +10 -10
  5. data/lib/hecks/adapters/driven/google_authentication.rb +8 -8
  6. data/lib/hecks/adapters/driven/governance_authorization.rb +31 -13
  7. data/lib/hecks/adapters/driven/heki/journal.rb +5 -4
  8. data/lib/hecks/adapters/driven/heki/saga_store.rb +5 -5
  9. data/lib/hecks/adapters/driven/heki.rb +13 -7
  10. data/lib/hecks/adapters/driven/identity_registry.rb +2 -2
  11. data/lib/hecks/adapters/driven/in_memory_ordering.rb +3 -3
  12. data/lib/hecks/adapters/driven/lambda/client.rb +34 -9
  13. data/lib/hecks/adapters/driven/lambda.rb +39 -33
  14. data/lib/hecks/adapters/driven/local_storage.rb +17 -10
  15. data/lib/hecks/adapters/driven/memory.rb +205 -9
  16. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +1 -1
  17. data/lib/hecks/adapters/driven/postgres/codec.rb +27 -11
  18. data/lib/hecks/adapters/driven/postgres/outbox.rb +40 -2
  19. data/lib/hecks/adapters/driven/postgres/reconnect.rb +23 -7
  20. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +14 -14
  21. data/lib/hecks/adapters/driven/postgres.rb +175 -28
  22. data/lib/hecks/adapters/driven/prism.rb +4 -4
  23. data/lib/hecks/adapters/driven/sql_query_builder.rb +34 -22
  24. data/lib/hecks/adapters/driven/sqlite/codec.rb +38 -10
  25. data/lib/hecks/adapters/driven/sqlite/projection.rb +60 -32
  26. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +12 -12
  27. data/lib/hecks/adapters/driven/sqlite.rb +181 -21
  28. data/lib/hecks/adapters/driven.rb +4 -4
  29. data/lib/hecks/adapters/driving/github_webhook.rb +18 -18
  30. data/lib/hecks/behaviors/dsl.rb +2 -2
  31. data/lib/hecks/behaviors/expectations.rb +23 -23
  32. data/lib/hecks/behaviors/ir.rb +1 -1
  33. data/lib/hecks/behaviors/rspec.rb +1 -1
  34. data/lib/hecks/behaviors/runner.rb +2 -2
  35. data/lib/hecks/behaviors.rb +1 -1
  36. data/lib/hecks/bluebook/aggregate.rb +13 -13
  37. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +10 -10
  38. data/lib/hecks/bluebook/assembly/build.rb +1 -1
  39. data/lib/hecks/bluebook/assembly/contract.rb +39 -16
  40. data/lib/hecks/bluebook/assembly/contracts.rb +40 -38
  41. data/lib/hecks/bluebook/assembly/marks.rb +18 -18
  42. data/lib/hecks/bluebook/assembly/specializer.rb +19 -21
  43. data/lib/hecks/bluebook/assembly.rb +9 -9
  44. data/lib/hecks/bluebook/attribute.rb +9 -9
  45. data/lib/hecks/bluebook/behaviour/aggregate.rb +11 -11
  46. data/lib/hecks/bluebook/behaviour/attribute.rb +5 -5
  47. data/lib/hecks/bluebook/behaviour/chapter.rb +23 -5
  48. data/lib/hecks/bluebook/behaviour/command.rb +23 -23
  49. data/lib/hecks/bluebook/behaviour/domain_port.rb +7 -7
  50. data/lib/hecks/bluebook/behaviour/entity.rb +8 -8
  51. data/lib/hecks/bluebook/behaviour/hexagon.rb +4 -4
  52. data/lib/hecks/bluebook/behaviour/lifecycle.rb +5 -5
  53. data/lib/hecks/bluebook/behaviour/policy.rb +12 -12
  54. data/lib/hecks/bluebook/behaviour/process_manager.rb +7 -7
  55. data/lib/hecks/bluebook/behaviour/query.rb +1 -1
  56. data/lib/hecks/bluebook/behaviour/read_model.rb +8 -8
  57. data/lib/hecks/bluebook/behaviour/traits.rb +12 -12
  58. data/lib/hecks/bluebook/behaviour/value_object.rb +6 -6
  59. data/lib/hecks/bluebook/capabilities.rb +27 -0
  60. data/lib/hecks/bluebook/chapter.rb +28 -9
  61. data/lib/hecks/bluebook/command.rb +12 -12
  62. data/lib/hecks/bluebook/domain_port.rb +9 -9
  63. data/lib/hecks/bluebook/dsl/adapter_builder.rb +24 -0
  64. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +49 -49
  65. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +96 -96
  66. data/lib/hecks/bluebook/dsl/attribute_collector.rb +41 -41
  67. data/lib/hecks/bluebook/dsl/binding_proxy.rb +22 -2
  68. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +111 -74
  69. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +48 -30
  70. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +116 -0
  71. data/lib/hecks/bluebook/dsl/command_builder.rb +103 -103
  72. data/lib/hecks/bluebook/dsl/const_shim.rb +46 -15
  73. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +90 -25
  74. data/lib/hecks/bluebook/dsl/entity_builder.rb +56 -56
  75. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +148 -132
  76. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +89 -30
  77. data/lib/hecks/bluebook/dsl/identity_declaration.rb +17 -17
  78. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +27 -4
  79. data/lib/hecks/bluebook/dsl/policy_builder.rb +30 -21
  80. data/lib/hecks/bluebook/dsl/port_builder.rb +38 -7
  81. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +56 -22
  82. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +35 -35
  83. data/lib/hecks/bluebook/dsl/query_builder.rb +5 -5
  84. data/lib/hecks/bluebook/dsl/read_model_builder.rb +34 -34
  85. data/lib/hecks/bluebook/dsl/rule_reference.rb +41 -39
  86. data/lib/hecks/bluebook/dsl/translation_builder.rb +9 -9
  87. data/lib/hecks/bluebook/dsl/value_object_builder.rb +16 -16
  88. data/lib/hecks/bluebook/dsl/word_gate.rb +59 -53
  89. data/lib/hecks/bluebook/dsl/world_builder.rb +51 -8
  90. data/lib/hecks/bluebook/entity.rb +11 -11
  91. data/lib/hecks/bluebook/expression/ast_json.rb +20 -20
  92. data/lib/hecks/bluebook/expression/ast_reader.rb +3 -3
  93. data/lib/hecks/bluebook/expression/canonical_form.rb +9 -9
  94. data/lib/hecks/bluebook/expression/evaluator.rb +18 -18
  95. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +18 -18
  96. data/lib/hecks/bluebook/expression/resolver.rb +60 -62
  97. data/lib/hecks/bluebook/hexagon.rb +1 -1
  98. data/lib/hecks/bluebook/lifecycle.rb +1 -1
  99. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -1
  100. data/lib/hecks/bluebook/meta_validator/judge.rb +101 -87
  101. data/lib/hecks/bluebook/meta_validator/plan.rb +39 -39
  102. data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -2
  103. data/lib/hecks/bluebook/meta_validator/readings.rb +43 -43
  104. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +44 -37
  105. data/lib/hecks/bluebook/meta_validator/shapes.rb +25 -21
  106. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +145 -31
  107. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +6 -6
  108. data/lib/hecks/bluebook/meta_validator/world_judge.rb +5 -5
  109. data/lib/hecks/bluebook/meta_validator.rb +70 -70
  110. data/lib/hecks/bluebook/model_check.rb +170 -84
  111. data/lib/hecks/bluebook/pattern_subset.rb +9 -9
  112. data/lib/hecks/bluebook/policy.rb +15 -13
  113. data/lib/hecks/bluebook/process_manager.rb +14 -14
  114. data/lib/hecks/bluebook/project_register.rb +6 -6
  115. data/lib/hecks/bluebook/query.rb +4 -4
  116. data/lib/hecks/bluebook/read_model.rb +14 -14
  117. data/lib/hecks/bluebook/reference.rb +8 -8
  118. data/lib/hecks/bluebook/smoke_test.rb +19 -19
  119. data/lib/hecks/bluebook/synthesizer.rb +12 -12
  120. data/lib/hecks/bluebook/translation.rb +4 -4
  121. data/lib/hecks/bluebook/value_object.rb +6 -6
  122. data/lib/hecks/bluebook.rb +2 -2
  123. data/lib/hecks/codemod/legacy_dispatch_args.rb +299 -0
  124. data/lib/hecks/codemod/legacy_dispatch_recorder.rb +186 -0
  125. data/lib/hecks/codemod.rb +36 -35
  126. data/lib/hecks/construct.rb +6 -6
  127. data/lib/hecks/corpus.rb +317 -0
  128. data/lib/hecks/deprecation.rb +95 -0
  129. data/lib/hecks/doc/reference.rb +19 -19
  130. data/lib/hecks/embryonaut_bluebook.rb +11 -11
  131. data/lib/hecks/facade/cli_door.rb +69 -10
  132. data/lib/hecks/facade/cli_runner.rb +105 -24
  133. data/lib/hecks/facade/command_request.rb +23 -0
  134. data/lib/hecks/facade/handle.rb +79 -32
  135. data/lib/hecks/facade/json_door.rb +106 -25
  136. data/lib/hecks/facade/surface/aggregate_door.rb +42 -27
  137. data/lib/hecks/facade/surface/chapter.rb +26 -17
  138. data/lib/hecks/facade/surface.rb +16 -3
  139. data/lib/hecks/facade.rb +15 -4
  140. data/lib/hecks/forms/app.rb +46 -30
  141. data/lib/hecks/forms/command_form_renderer.rb +70 -9
  142. data/lib/hecks/forms/field_renderer.rb +142 -6
  143. data/lib/hecks/forms/field_shape.rb +180 -19
  144. data/lib/hecks/forms/html.rb +51 -7
  145. data/lib/hecks/forms/index_renderer.rb +14 -2
  146. data/lib/hecks/forms/params.rb +120 -23
  147. data/lib/hecks/forms/port_argument.rb +2 -2
  148. data/lib/hecks/forms/query_form_renderer.rb +2 -2
  149. data/lib/hecks/forms/record_renderer.rb +2 -2
  150. data/lib/hecks/forms/record_table.rb +1 -1
  151. data/lib/hecks/forms/value_object_shape.rb +3 -3
  152. data/lib/hecks/forms.rb +24 -4
  153. data/lib/hecks/fqn.rb +1 -1
  154. data/lib/hecks/framework/bluebook/governance.bluebook +9 -0
  155. data/lib/hecks/framework.rb +48 -17
  156. data/lib/hecks/freezer.rb +11 -11
  157. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +90 -90
  158. data/lib/hecks/fuzzing/combination_miner.rb +119 -0
  159. data/lib/hecks/fuzzing/concurrent_dispatch.rb +140 -45
  160. data/lib/hecks/fuzzing/coverage_campaign.rb +118 -0
  161. data/lib/hecks/fuzzing/differential.rb +158 -0
  162. data/lib/hecks/fuzzing/domain_generator.rb +694 -0
  163. data/lib/hecks/fuzzing/era_boundary.rb +37 -18
  164. data/lib/hecks/fuzzing/form_census.rb +35 -20
  165. data/lib/hecks/fuzzing/generated_domain_check.rb +95 -0
  166. data/lib/hecks/fuzzing/invalid_value_generator.rb +6 -6
  167. data/lib/hecks/fuzzing/isolated_boot.rb +62 -62
  168. data/lib/hecks/fuzzing/nondeterministic.rb +67 -0
  169. data/lib/hecks/fuzzing/persistence_parity.rb +19 -21
  170. data/lib/hecks/fuzzing/properties/corrections.rb +9 -9
  171. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +154 -49
  172. data/lib/hecks/fuzzing/properties/guards.rb +42 -42
  173. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +32 -32
  174. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +22 -35
  175. data/lib/hecks/fuzzing/properties/outbox.rb +24 -24
  176. data/lib/hecks/fuzzing/properties/querying.rb +17 -17
  177. data/lib/hecks/fuzzing/properties.rb +64 -40
  178. data/lib/hecks/fuzzing/qa_settings.rb +152 -0
  179. data/lib/hecks/fuzzing/replay.rb +114 -114
  180. data/lib/hecks/fuzzing/rotation_priority.rb +10 -10
  181. data/lib/hecks/fuzzing/rust_gap_manifest.rb +113 -0
  182. data/lib/hecks/fuzzing/self_consistency.rb +141 -112
  183. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +35 -35
  184. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +18 -11
  185. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +13 -12
  186. data/lib/hecks/fuzzing/sequence_generator/picker.rb +21 -12
  187. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +58 -31
  188. data/lib/hecks/fuzzing/sequence_generator.rb +111 -23
  189. data/lib/hecks/fuzzing/shrinker.rb +197 -0
  190. data/lib/hecks/fuzzing/structural_skips.rb +23 -130
  191. data/lib/hecks/fuzzing/sweep_depth.rb +4 -4
  192. data/lib/hecks/fuzzing/target_capabilities.rb +49 -18
  193. data/lib/hecks/fuzzing/value_generator.rb +14 -14
  194. data/lib/hecks/fuzzing.rb +5 -0
  195. data/lib/hecks/grammar/evolve.rb +10 -10
  196. data/lib/hecks/grammar.rb +7 -7
  197. data/lib/hecks/ir.rb +13 -13
  198. data/lib/hecks/language/bluebook/bluebook.bluebook +41 -0
  199. data/lib/hecks/language/bluebook/policy.bluebook +11 -1
  200. data/lib/hecks/language/bluebook/vocabulary.bluebook +348 -13
  201. data/lib/hecks/language/oidc.json +5 -0
  202. data/lib/hecks/literal.rb +9 -9
  203. data/lib/hecks/naming.rb +25 -25
  204. data/lib/hecks/ports/access_control.rb +58 -2
  205. data/lib/hecks/ports/agent/answers.rb +83 -6
  206. data/lib/hecks/ports/agent.rb +119 -35
  207. data/lib/hecks/ports/authentication.rb +44 -4
  208. data/lib/hecks/ports/authorization.rb +53 -11
  209. data/lib/hecks/ports/clock.rb +42 -23
  210. data/lib/hecks/ports/extraction.rb +16 -0
  211. data/lib/hecks/ports/identity_assignment.rb +24 -2
  212. data/lib/hecks/ports/identity_generation.rb +17 -3
  213. data/lib/hecks/ports/identity_resolution.rb +18 -1
  214. data/lib/hecks/ports/loading.rb +4 -0
  215. data/lib/hecks/ports/persistence/append_only.rb +172 -8
  216. data/lib/hecks/ports/persistence/binding_policy.rb +34 -0
  217. data/lib/hecks/ports/persistence/codec_boundary.rb +178 -0
  218. data/lib/hecks/ports/persistence/execution.rb +4 -0
  219. data/lib/hecks/ports/persistence/null_saga_store.rb +12 -1
  220. data/lib/hecks/ports/persistence/plugin.rb +42 -4
  221. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +218 -25
  222. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +77 -9
  223. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +81 -24
  224. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +29 -18
  225. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +144 -60
  226. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +103 -8
  227. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +98 -23
  228. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +282 -109
  229. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +63 -25
  230. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +118 -66
  231. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +51 -28
  232. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +28 -5
  233. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +25 -12
  234. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +129 -34
  235. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +51 -6
  236. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +33 -9
  237. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +16 -0
  238. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +57 -4
  239. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +25 -2
  240. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +314 -90
  241. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +68 -10
  242. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +9 -3
  243. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +9 -2
  244. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +42 -8
  245. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -1
  246. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +36 -5
  247. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +23 -3
  248. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -19
  249. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +5 -5
  250. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +1 -1
  251. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -2
  252. data/lib/hecks/ports/persistence/plugins/era.rb +12 -2
  253. data/lib/hecks/ports/persistence/remote_runtime.rb +9 -2
  254. data/lib/hecks/ports/persistence/repository_factory.rb +23 -3
  255. data/lib/hecks/ports/persistence/state_codec.rb +319 -0
  256. data/lib/hecks/ports/persistence.rb +36 -1
  257. data/lib/hecks/ports/projection.rb +61 -7
  258. data/lib/hecks/ports/query/in_memory.rb +3 -3
  259. data/lib/hecks/ports/query/ordering.rb +6 -6
  260. data/lib/hecks/ports/query.rb +35 -0
  261. data/lib/hecks/projections/bootstrap_table.rb +112 -0
  262. data/lib/hecks/projections/diagrams.rb +75 -75
  263. data/lib/hecks/projections/glossary/html.rb +3 -3
  264. data/lib/hecks/projections/glossary/markdown.rb +3 -3
  265. data/lib/hecks/projections/glossary/mermaid.rb +1 -1
  266. data/lib/hecks/projections/glossary/sections.rb +1 -1
  267. data/lib/hecks/projections/glossary/sentences.rb +5 -5
  268. data/lib/hecks/projections/glossary.rb +15 -15
  269. data/lib/hecks/projections/ir.rb +1 -1
  270. data/lib/hecks/projections/model/deviations.rb +18 -17
  271. data/lib/hecks/projections/model.rb +25 -21
  272. data/lib/hecks/projections/oidc.rb +7 -7
  273. data/lib/hecks/projections/parser_table.rb +5 -5
  274. data/lib/hecks/projections/reference.rb +3 -3
  275. data/lib/hecks/projections/rust_vocabulary.rb +443 -0
  276. data/lib/hecks/projections/shape.rb +2 -2
  277. data/lib/hecks/projections/statements.rb +11 -11
  278. data/lib/hecks/projections/vocabulary.rb +9 -9
  279. data/lib/hecks/projections.rb +5 -3
  280. data/lib/hecks/projector/cli_projector.rb +29 -29
  281. data/lib/hecks/projector/docs_projector.rb +13 -13
  282. data/lib/hecks/projector/exporter.rb +42 -21
  283. data/lib/hecks/projector/ir_projector.rb +1 -1
  284. data/lib/hecks/projector/narrate_projector.rb +11 -11
  285. data/lib/hecks/projector/target.rb +13 -13
  286. data/lib/hecks/projector.rb +15 -15
  287. data/lib/hecks/query_ir.rb +47 -47
  288. data/lib/hecks/query_specification/common/comparators.rb +19 -3
  289. data/lib/hecks/query_specification/common/comparison.rb +109 -27
  290. data/lib/hecks/query_specification/common/dsl.rb +65 -9
  291. data/lib/hecks/query_specification/common/null_policy.rb +57 -13
  292. data/lib/hecks/query_specification/common/null_semantics.rb +4 -0
  293. data/lib/hecks/query_specification/common/options.rb +25 -0
  294. data/lib/hecks/query_specification/field_path.rb +69 -15
  295. data/lib/hecks/query_specification/hop_path.rb +57 -20
  296. data/lib/hecks/query_specification/read_model/specification.rb +4 -0
  297. data/lib/hecks/rendering.rb +3 -3
  298. data/lib/hecks/router/namespace_installer.rb +3 -3
  299. data/lib/hecks/router.rb +1 -1
  300. data/lib/hecks/runtime/aggregate_lock.rb +11 -11
  301. data/lib/hecks/runtime/boot_gates.rb +3 -3
  302. data/lib/hecks/runtime/caller.rb +8 -8
  303. data/lib/hecks/runtime/capability_graph.rb +2 -2
  304. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +22 -25
  305. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +42 -63
  306. data/lib/hecks/runtime/command_interpreter.rb +159 -102
  307. data/lib/hecks/runtime/command_rules/admissibility.rb +69 -69
  308. data/lib/hecks/runtime/command_rules/arithmetic.rb +137 -91
  309. data/lib/hecks/runtime/command_rules/authorization.rb +38 -17
  310. data/lib/hecks/runtime/command_rules/emission.rb +18 -1
  311. data/lib/hecks/runtime/command_rules/references.rb +35 -35
  312. data/lib/hecks/runtime/command_rules.rb +3 -0
  313. data/lib/hecks/runtime/dependency_planning.rb +11 -11
  314. data/lib/hecks/runtime/dispatcher.rb +283 -90
  315. data/lib/hecks/runtime/entity_element.rb +151 -67
  316. data/lib/hecks/runtime/entity_interpreter.rb +108 -82
  317. data/lib/hecks/runtime/errors.rb +19 -19
  318. data/lib/hecks/runtime/event.rb +6 -6
  319. data/lib/hecks/runtime/identity.rb +22 -22
  320. data/lib/hecks/runtime/instance.rb +39 -14
  321. data/lib/hecks/runtime/interpreting.rb +12 -12
  322. data/lib/hecks/runtime/invocation.rb +276 -0
  323. data/lib/hecks/runtime/loader.rb +14 -14
  324. data/lib/hecks/runtime/outbox.rb +23 -23
  325. data/lib/hecks/runtime/policy_interpreter.rb +54 -54
  326. data/lib/hecks/runtime/port_operation_interpreter.rb +22 -19
  327. data/lib/hecks/runtime/query_interpreter.rb +55 -64
  328. data/lib/hecks/runtime/reaction_invocation.rb +20 -20
  329. data/lib/hecks/runtime/read_model_interpreter.rb +40 -40
  330. data/lib/hecks/runtime/rebuild_sweep.rb +4 -4
  331. data/lib/hecks/runtime/reference_hop.rb +6 -6
  332. data/lib/hecks/runtime/refusal_wording.rb +92 -115
  333. data/lib/hecks/runtime/registry/saga_persistence.rb +21 -21
  334. data/lib/hecks/runtime/registry/verification.rb +36 -26
  335. data/lib/hecks/runtime/registry.rb +45 -28
  336. data/lib/hecks/runtime/remote_dispatcher.rb +38 -23
  337. data/lib/hecks/runtime/routing.rb +10 -153
  338. data/lib/hecks/runtime/saga_interpreter/correlation.rb +17 -17
  339. data/lib/hecks/runtime/saga_interpreter.rb +64 -64
  340. data/lib/hecks/runtime/saga_pending_dispatch.rb +12 -12
  341. data/lib/hecks/runtime/tenant_check.rb +9 -9
  342. data/lib/hecks/runtime/tenant_scope.rb +5 -5
  343. data/lib/hecks/runtime/value/admission.rb +75 -30
  344. data/lib/hecks/runtime/value/coercion.rb +318 -127
  345. data/lib/hecks/runtime/value/entity_list_coercion.rb +34 -34
  346. data/lib/hecks/runtime/value.rb +21 -21
  347. data/lib/hecks/runtime.rb +7 -7
  348. data/lib/hecks/storehouse.rb +64 -64
  349. data/lib/hecks/version.rb +3 -3
  350. data/lib/hecks/vocabulary.rb +205 -4
  351. data/lib/hecks.rb +13 -11
  352. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +11 -11
  353. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +14 -12
  354. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +11 -11
  355. metadata +22 -2
@@ -8,6 +8,7 @@ module Hecks
8
8
  # vocabulary of its own; `WorldBuilder#record_binding` reads `#to_h`
9
9
  # back out.
10
10
  class SettingsCollector
11
+ # Starts with no settings recorded.
11
12
  def initialize = @values = {}
12
13
 
13
14
  def method_missing(key, *args, &)
@@ -19,9 +20,9 @@ module Hecks
19
20
  def to_h = @values
20
21
  end
21
22
 
22
- # THE AGGREGATE-QUALIFIED MIRROR (#143) — a `.world` file's own
23
+ # The aggregate-qualified mirror (#143) — a `.world` file's own
23
24
  # `Pizzas::Order.charged_by("Stripe") do ... end` visually mirrors the
24
- # SAME bind line the sibling `.hecksagon` file already writes
25
+ # same bind line the sibling `.hecksagon` file already writes
25
26
  # (`HecksagonBuilder`'s own `BindingProxy`), but `IR::World#for_verb`/
26
27
  # `#for_binding` key purely by verb and adapter name — the aggregate
27
28
  # qualifier is never read back out, it exists only for that visual
@@ -30,12 +31,19 @@ module Hecks
30
31
  # not, has to land in the exact same `@settings` write path
31
32
  # (`WorldBuilder#record_binding`).
32
33
  class WorldConstProxy
34
+ # Mints the stand-in module a bare domain constant resolves to inside a `.world` block.
35
+ #
36
+ # @param builder [Bluebook::DSL::WorldBuilder] the builder every verb called through the
37
+ # module's proxies records its settings on
38
+ # @return [Module] an anonymous module whose `const_missing` answers a `WorldConstProxy`,
39
+ # whatever aggregate name follows `::`
33
40
  def self.namespace(builder)
34
41
  Module.new do
35
42
  define_singleton_method(:const_missing) { |_aggregate| WorldConstProxy.new(builder) }
36
43
  end
37
44
  end
38
45
 
46
+ # @param builder [Bluebook::DSL::WorldBuilder] the builder verb calls are recorded on
39
47
  def initialize(builder) = @builder = builder
40
48
 
41
49
  def method_missing(verb, *args, **kwargs, &block) = @builder.record_binding(verb, args, kwargs, block)
@@ -45,7 +53,7 @@ module Hecks
45
53
 
46
54
  # Parses a `.world` file's top-level DSL block into a `World` — a
47
55
  # domain's own `realm`/`latest` version markers plus its adapter bind
48
- # SETTINGS, one entry per `verb("Adapter") do ... end` call (whether
56
+ # settings, one entry per `verb("Adapter") do ... end` call (whether
49
57
  # written bare or aggregate-qualified through `WorldConstProxy`'s
50
58
  # visual mirror of a sibling `.hecksagon` file's own bind).
51
59
  class WorldBuilder
@@ -53,23 +61,37 @@ module Hecks
53
61
 
54
62
  include WordGate
55
63
 
64
+ # @param domain [String] name of the domain whose world this is
56
65
  def initialize(domain)
57
66
  @domain = domain
58
67
  @settings = {}
59
68
  end
60
69
 
61
- # RENAMED FROM `realm`/`latest` item #13's full metaprogrammed
62
- # dispatch (slice 5). Neither bootstrap-reachable (checked
63
- # directly). Reached through `WordGate#method_missing`'s new
70
+ # Names the realm this world belongs to, such as `"Examples"` or `"QA"`.
71
+ #
72
+ # `realm_impl`/`latest_impl` answer the `realm`/`latest` words
73
+ # through the table's `calls:` column — item #13's full
74
+ # metaprogrammed dispatch (slice 5). Neither bootstrap-reachable
75
+ # (checked directly). Reached through `WordGate`'s
64
76
  # `word_gate_dispatch`, called explicitly below since
65
77
  # `WorldBuilder`'s own class-level `method_missing` (the
66
78
  # open-verb catch-all beneath this) always wins over the
67
79
  # module's — see `word_gate.rb`'s own header for the full
68
80
  # mechanism.
81
+ #
82
+ # @param value [String, Symbol] the realm's name; blankness is judged by the world
83
+ # language at `build`, not here
84
+ # @return [String] the realm as stored
69
85
  def realm_impl(value)
70
86
  @realm = required(value, "realm")
71
87
  end
72
88
 
89
+ # Names the bluebook version this world treats as latest, which `ProjectRegister` compares
90
+ # with the bluebook's own declared `version`.
91
+ #
92
+ # @param value [String, Symbol, Numeric] the version marker; blankness is judged by the
93
+ # world language at `build`, not here
94
+ # @return [String] the version as stored
73
95
  def latest_impl(value)
74
96
  @latest = required(value, "latest version")
75
97
  end
@@ -83,11 +105,20 @@ module Hecks
83
105
 
84
106
  def respond_to_missing?(_name, _include_private = false) = true
85
107
 
86
- # EXTRACTED from the old `method_missing` body (#143) so
108
+ # Records one bind's settings under both its verb and its `verb:adapter` key.
109
+ #
110
+ # A method of its own, apart from `method_missing` (#143), so
87
111
  # `WorldConstProxy`'s own aggregate-qualified verb calls
88
112
  # (`Pizzas::Order.charged_by(...)`) write into the exact same
89
113
  # place the bare top-level spelling (`charged_by(...)`) already
90
114
  # does — one write path, two spellings.
115
+ #
116
+ # @param verb [Symbol, String] the bind verb, such as `:persisted_by`
117
+ # @param args [Array<Object>] the call's positional arguments; the first names the adapter
118
+ # @param kwargs [Hash{Symbol => Object}] settings given inline as keyword arguments
119
+ # @param block [Proc, nil] a settings block, evaluated against a `SettingsCollector`
120
+ # @return [Hash{Symbol => Object}] the settings just recorded: `:adapter` (a String),
121
+ # then the keyword arguments, then the block's settings, later ones winning
91
122
  def record_binding(verb, args, kwargs, block)
92
123
  collector = SettingsCollector.new
93
124
  collector.instance_eval(&block) if block
@@ -96,18 +127,30 @@ module Hecks
96
127
  @settings["#{verb}:#{args.first.to_s.downcase}"] = value
97
128
  end
98
129
 
130
+ # Assembles the realm, version marker and bind settings, judged by the world language.
131
+ #
132
+ # @return [Bluebook::World] the world, returned once the language accepts it
133
+ # @raise [Bluebook::DSL::Malformed] if the world language refuses the declaration, such
134
+ # as a blank `realm`
99
135
  def build
100
136
  MetaValidator.call_world(
101
137
  World.new(domain: @domain, realm: @realm, latest: @latest, settings: @settings)
102
138
  )
103
139
  end
104
140
 
141
+ # Evaluates a `Hecks.world` block against a fresh builder and returns the world it declared.
142
+ #
105
143
  # `ConstShim`'s resolver, the same bridge `HecksagonBuilder`/
106
144
  # `BluebookBuilder` already wrap their own `instance_eval` in
107
- # (#143) — without it, `Pizzas::Order.charged_by(...)` raised
145
+ # (#143) — without it, `Pizzas::Order.charged_by(...)` raises
108
146
  # `NameError: uninitialized constant Pizzas` for every `.world`
109
147
  # file using the aggregate-qualified mirror form, since a bare
110
148
  # `Pizzas` has no real constant to resolve to.
149
+ #
150
+ # @param domain [String] name of the domain whose world this is
151
+ # @yield the world body, evaluated with the builder as `self`; may be omitted
152
+ # @return [Bluebook::World] the judged world
153
+ # @raise [Bluebook::DSL::Malformed] if the world language refuses the declaration
111
154
  def self.build(domain, &block)
112
155
  builder = new(domain)
113
156
  resolver = ->(_domain) { WorldConstProxy.namespace(builder) }
@@ -3,10 +3,10 @@ require_relative "expression/ast_json"
3
3
 
4
4
  module Hecks
5
5
  module Bluebook
6
- # An entity, as a RUBY CLASS — a piece of an aggregate that has an identity
6
+ # An entity, as a Ruby class — a piece of an aggregate that has an identity
7
7
  # of its own.
8
8
  #
9
- # Crossing over closes the OWNER CHAIN. An entity declares commands, and
9
+ # Crossing over closes the owner chain. An entity declares commands, and
10
10
  # until now those commands had no owner that could state an identity: an
11
11
  # entity was an IR object, not a construct, so `Construct#hecks_fqn` refused
12
12
  # rather than answering "Deposit" and looking right. Four of banking's
@@ -14,15 +14,15 @@ module Hecks
14
14
  # `Banking::Account.Ledger.Deposit` — which is the id the judge already mints
15
15
  # for them.
16
16
  #
17
- # NOT const_set, for the same reason a command is not: a name inside one
17
+ # Not const_set, for the same reason a command is not: a name inside one
18
18
  # aggregate can denote more than one kind of thing, so the constant tree
19
19
  # cannot index it.
20
20
  #
21
- # It must stay STRUCTURALLY INTERCHANGEABLE with an aggregate — the runtime
21
+ # It must stay structurally interchangeable with an aggregate — the runtime
22
22
  # builds `Instance.new(aggregate: entity)` and `CommandRules` takes either as
23
23
  # `declaring` — so it answers `hecks_name`, `attributes`, `attribute`,
24
24
  # `identified_by` and `lifecycle` exactly as an aggregate does. And it must
25
- # keep NOT answering `value_object`: `Value.for_attribute` sniffs for that
25
+ # keep not answering `value_object`: `Value.for_attribute` sniffs for that
26
26
  # method to tell a piece from a head.
27
27
  class Entity
28
28
  extend Construct
@@ -39,26 +39,26 @@ module Hecks
39
39
  # S17, ADR 0026 — "That is what `entity` is for, and `entity` is
40
40
  # declared by the language and used zero times in it" (the ADR's
41
41
  # own words). Dispatch nests inside Handler, so an entity's own
42
- # NESTED entities are part of its wire shape now, the same way
42
+ # nested entities are part of its wire shape now, the same way
43
43
  # an aggregate's always were — the field the ADR names as
44
44
  # declared-but-unused until this slice.
45
45
  entities: many(:entities),
46
- # ADR 0028 — a piece's own `given`, the SAME shape
46
+ # ADR 0028 — a piece's own `given`, the same shape
47
47
  # `Aggregate#preconditions` already carries (its own `emits_ir`
48
48
  # row, identical). A precondition shared across this piece's own
49
49
  # commands, declared once — a command references it back by
50
- # name; the resolved text still lands on EACH referencing
50
+ # name; the resolved text still lands on each referencing
51
51
  # command's own `givens` either way, so this field is read-only
52
52
  # documentation of what the piece itself declared, the same
53
53
  # relationship `Aggregate.preconditions` already has to its own
54
54
  # commands.
55
55
  preconditions: -> { preconditions.map { |rule| Expression::AstJson.rule_row(rule) } },
56
- # A piece's OWN shape rule, checked against EVERY instance of
56
+ # A piece's own shape rule, checked against every instance of
57
57
  # this piece the aggregate holds (Admissibility#enforce_
58
- # invariants' own recursive walk) — the SAME relationship
58
+ # invariants' own recursive walk) — the same relationship
59
59
  # `ValueObject#invariants` already has to its own instances,
60
60
  # one level up the construct tree. Not a separate enforcement
61
- # boundary; still checked at the SAME two points (after every
61
+ # boundary; still checked at the same two points (after every
62
62
  # mutation, before save) the aggregate's own invariants always
63
63
  # were — see that method's own comment for why this does not
64
64
  # contradict "there is no separate entity invariant."
@@ -4,17 +4,17 @@ require_relative "resolver"
4
4
  module Hecks
5
5
  module Bluebook
6
6
  module Expression
7
- # ── AST → JSON — walks the REAL Evaluator/Resolver AST (the same
7
+ # ── AST → JSON — walks the real Evaluator/Resolver AST (the same
8
8
  # objects a live dispatch parses `given`/`ensures`/invariant text
9
9
  # into — see docs/implemented/guides/running-a-runtime.md's "The
10
10
  # expression grammar") and emits plain, JSON-serializable Ruby
11
11
  # Hashes, tagged by `"op"`.
12
12
  #
13
- # THE SAME TWO-METHOD WALK `rust/project/expr_emitter.rb`'s own
14
- # `emit_bool`/`emit_resolver` already do, over the SAME AST — that
15
- # file's own methods build RUST SOURCE-CODE STRINGS for `rust/
13
+ # The same two-method walk `rust/project/expr_emitter.rb`'s own
14
+ # `emit_bool`/`emit_resolver` already do, over the same AST — that
15
+ # file's own methods build Rust source-code strings for `rust/
16
16
  # project`'s codegen (`rust/src/kernel::expr::Expr` literals, baked
17
- # into a generated domain's own compiled binary); this builds DATA
17
+ # into a generated domain's own compiled binary); this builds data
18
18
  # instead, for a genuinely different consumer with a genuinely
19
19
  # different constraint: `rust/host` can never link the `rust`
20
20
  # (kernel) crate at all (a real, load-bearing build constraint —
@@ -22,25 +22,25 @@ module Hecks
22
22
  # path dependency would statically bake every domain's generated
23
23
  # dispatch code into every Lambda binary), so a value object's own
24
24
  # `invariant` predicate has to travel as something `rust/host` can
25
- # deserialize and interpret itself, at RUNTIME, from `ir.json` — the
25
+ # deserialize and interpret itself, at runtime, from `ir.json` — the
26
26
  # exact same relationship `rust/project`'s own `Expr` literals
27
27
  # already have to the compiled kernel, one layer further out.
28
28
  #
29
- # LIVES IN CORE `lib/hecks`, NOT `rust/project/` — `rust/project.rb`
29
+ # Lives in core `lib/hecks`, not `rust/project/` — `rust/project.rb`
30
30
  # is a separate, downstream toolchain
31
31
  # (`lib/hecks/projector.rb`'s own header: "a whole separate Ruby
32
32
  # program"), never `require`d by core `lib/hecks/bluebook/*.rb`
33
33
  # files (confirmed: no core file does). `value_object.rb`'s own
34
- # `invariants:` IR emission needs this for EVERY domain's ordinary
34
+ # `invariants:` IR emission needs this for every domain's ordinary
35
35
  # `to_h`/`ir.json` export — golden fixtures, `hecks-parse`'s parity
36
36
  # comparisons, and any deploy artifact, not only a `bin/project_rust`
37
37
  # run — so it belongs beside `Evaluator`/`Resolver` themselves, not
38
38
  # bolted onto a tool that only sometimes runs.
39
39
  #
40
- # COMPLETE, not corpus-scoped: every node this grammar admits gets
40
+ # Complete, not corpus-scoped: every node this grammar admits gets
41
41
  # a real arm, the identical "raise, don't silently drop" discipline
42
42
  # `expr_emitter.rb`'s own `emit_bool`/`emit_resolver` already hold
43
- # to — even though, as of this writing, no real corpus VALUE OBJECT
43
+ # to — even though, as of this writing, no real corpus value object
44
44
  # invariant exercises `Include`/`Modulo`/`BlockPredicate`/`Find`/
45
45
  # `Array`/`MatchesRegex`/`Presence`/`Assignment`/`Split`/`StartsWith`/
46
46
  # `EndsWith`/`First`/`Last` (only `given`/`ensures` clauses do, elsewhere in
@@ -48,15 +48,15 @@ module Hecks
48
48
  # `rust/host/src/expr_json.rs`'s own header names exactly which of
49
49
  # these its interpreter evaluates for real today versus refuses
50
50
  # cleanly — a narrower, deliberate, documented boundary on the
51
- # INTERPRETING side, not on this EMITTING side: an author is free
52
- # to write ANY real expression in a value object's own `invariant`,
51
+ # interpreting side, not on this emitting side: an author is free
52
+ # to write any real expression in a value object's own `invariant`,
53
53
  # and this always emits it faithfully; whether `rust/host` can yet
54
- # CHECK it at mint time is that file's own question to answer, not
54
+ # check it at mint time is that file's own question to answer, not
55
55
  # this one's to pre-empt by refusing to even try.
56
56
  module AstJson
57
57
  module_function
58
58
 
59
- # THE CLOSED OP ROSTER — every `"op"` tag the walkers below can
59
+ # **The closed op roster** — every `"op"` tag the walkers below can
60
60
  # emit, pinned so a reader (or a spec) can refuse a tag it does
61
61
  # not know instead of guessing. A new node kind is a new entry
62
62
  # here, a new arm below, and a new arm in every reader.
@@ -68,7 +68,7 @@ module Hecks
68
68
  matches_regex presence assignment split starts_with ends_with
69
69
  ].freeze
70
70
 
71
- # ONE RULE ROW, THE WAY EVERY RULE SITE EMITS IT — description and
71
+ # One rule row, the way every rule site emits it — description and
72
72
  # canonical text (what every reader has always had) plus the
73
73
  # structured form, derived from the same text. `ast` is a pure
74
74
  # function of `canonical`: the IR carries both so a reader that
@@ -149,9 +149,9 @@ module Hecks
149
149
 
150
150
  # The JSON-target sibling of `expr_emitter.rb`'s own
151
151
  # `emit_include` — see that method's own comment for the full
152
- # reasoning (a LITERAL array haystack has no `Expr::Include`-
153
- # representable shape on EITHER target, kernel or host, so both
154
- # rewrite it identically into an OR-of-equalities at emission
152
+ # reasoning (a literal array haystack has no `Expr::Include`-
153
+ # representable shape on either target, kernel or host, so both
154
+ # rewrite it identically into an or-of-equalities at emission
155
155
  # time rather than carrying a shape neither interpreter could
156
156
  # evaluate). A non-literal haystack still emits `include`
157
157
  # unchanged.
@@ -172,7 +172,7 @@ module Hecks
172
172
  end
173
173
 
174
174
  # One case arm per Resolver node type — the class header above is
175
- # explicit that this dispatch must stay COMPLETE and in one place
175
+ # explicit that this dispatch must stay complete and in one place
176
176
  # ("every node this grammar admits gets a real arm"); splitting it
177
177
  # into several methods would hide whether the set is still
178
178
  # exhaustive instead of making that visible at a glance.
@@ -184,7 +184,7 @@ module Hecks
184
184
  when Resolver::StringLiteral then { "op" => "str", "value" => node.value }
185
185
  when Resolver::BoolLiteral then { "op" => "bool", "value" => node.value }
186
186
  when Resolver::NilLiteral then { "op" => "nil" }
187
- # `path` is the SAME shape `find.path` already has — segments, not
187
+ # `path` is the same shape `find.path` already has — segments, not
188
188
  # a dotted string a reader would have to split by its own rule.
189
189
  when Resolver::Lookup then { "op" => "lookup", "path" => node.path.split(".") }
190
190
  when Resolver::Addition then { "op" => "add", "left" => emit_resolver(node.left), "right" => emit_resolver(node.right) }
@@ -4,8 +4,8 @@ require_relative "resolver"
4
4
  module Hecks
5
5
  module Bluebook
6
6
  module Expression
7
- # THE INVERSE OF `AstJson` — reads the `"op"`-tagged JSON a rule row
8
- # carries as `ast` back into the SAME `Evaluator`/`Resolver` node
7
+ # The inverse of `AstJson` — reads the `"op"`-tagged JSON a rule row
8
+ # carries as `ast` back into the same `Evaluator`/`Resolver` node
9
9
  # Structs `Evaluator.parse` builds from `canonical`. This is how the
10
10
  # runtime evaluates a rule without re-parsing its text: the one
11
11
  # parse happened at DSL-build time, behind `AstJson`; dispatch walks
@@ -19,7 +19,7 @@ module Hecks
19
19
  # the spec proved the round trip first, then the runtime adopted it.
20
20
  #
21
21
  # One deliberate asymmetry, inherited: `AstJson` rewrites a
22
- # LITERAL-array `.include?` into an OR of equalities (see
22
+ # literal-array `.include?` into an or of equalities (see
23
23
  # `emit_include`), so reading never produces an `Include` over an
24
24
  # `ArrayLiteral`. Evaluation is unchanged by that rewrite, which is
25
25
  # exactly what the equivalence spec pins.
@@ -4,7 +4,7 @@ require_relative "../../vocabulary"
4
4
  module Hecks
5
5
  module Bluebook
6
6
  module Expression
7
- # Rewrites a predicate's SOURCE TEXT into one canonical spelling
7
+ # Rewrites a predicate's source text into one canonical spelling
8
8
  # before it's ever parsed or hashed — collapsing whitespace and
9
9
  # folding admitted synonyms (e.g. `.length` → `.size`) via the
10
10
  # `RULES` table projected from the grammar chapter, so two byte-
@@ -16,7 +16,7 @@ module Hecks
16
16
 
17
17
  STRATEGIES = Hecks::Vocabulary.fetch("NormalisationStrategy")
18
18
 
19
- # READ, NOT RESTATED — the admitted normalisation rules, projected
19
+ # **Read, not restated** — the admitted normalisation rules, projected
20
20
  # from the grammar chapter by bin/expression_projection exactly as
21
21
  # the evaluator's operator table is. See Evaluator::PROJECTION for
22
22
  # why a projection rather than a boot.
@@ -61,7 +61,7 @@ module Hecks
61
61
  end
62
62
  end
63
63
 
64
- # Applies a normalisation rule to the text OUTSIDE quoted string
64
+ # Applies a normalisation rule to the text outside quoted string
65
65
  # literals only, copying every quoted run through byte-for-byte.
66
66
  # Every rule here (collapse_whitespace, the `.length`→`.size` fold)
67
67
  # used to run quote-blind — `"a b"` collapsed to `"a b"` and
@@ -69,7 +69,7 @@ module Hecks
69
69
  # source outside the quotes, silently rewriting what a predicate
70
70
  # compares a string attribute against, not merely how the
71
71
  # predicate itself is spelled. A canonical string literal's
72
- # CONTENTS are data, never syntax to normalise.
72
+ # contents are data, never syntax to normalise.
73
73
  #
74
74
  # Handles both `"` and `'` delimiters (this grammar's own
75
75
  # `Resolver.quoted?` admits either), quote-aware exactly the way
@@ -93,9 +93,9 @@ module Hecks
93
93
  result << yield(buffer)
94
94
  # `char.dup`, not `char.to_s` (a no-op on a String — always
95
95
  # returns self, never a copy) and not `+char` either
96
- # (`String#+@` only dups a FROZEN receiver; `each_char`'s
96
+ # (`String#+@` only dups a frozen receiver; `each_char`'s
97
97
  # yielded strings aren't frozen, so `+char` is just as
98
- # much a no-op here). Without a REAL copy, `buffer` and
98
+ # much a no-op here). Without a real copy, `buffer` and
99
99
  # `quote` alias the same mutable object: the very next
100
100
  # `buffer << char` grows `quote` right along with it, so
101
101
  # `char == quote` can only ever compare a single character
@@ -103,12 +103,12 @@ module Hecks
103
103
  # literal — everything after a predicate's first quoted
104
104
  # string silently skipped normalisation for the rest of
105
105
  # the text, undetected because passing text through
106
- # unnormalised is silent. MASKED by every existing spec
107
- # here, which only checks that quoted CONTENTS survive
106
+ # unnormalised is silent. Masked by every existing spec
107
+ # here, which only checks that quoted contents survive
108
108
  # untouched (the M7 fix this method exists for) — that
109
109
  # still holds by accident once the bug makes the "outside"
110
110
  # branch unreachable. Found live: a multi-line `given`/
111
- # `ensures` block whose ONLY quoted literal closes before a
111
+ # `ensures` block whose only quoted literal closes before a
112
112
  # later line — the newline and that later line's own
113
113
  # indentation went uncollapsed, diverging from
114
114
  # `hecks-parse`'s own (correct) single-space join.
@@ -16,9 +16,9 @@ module Hecks
16
16
 
17
17
  # Six operators, reduced to two primitives (less_than, equal) combined
18
18
  # with a small boolean algebra: compares_less_than/compares_equal choose
19
- # which primitive(s) OR together, negated inverts the result.
19
+ # which primitive(s) or together, negated inverts the result.
20
20
  #
21
- # READ, NOT RESTATED. This table is the checked-in projection of the
21
+ # **Read, not restated**. This table is the checked-in projection of the
22
22
  # grammar chapter's admitted set (bin/expression_projection), joined with
23
23
  # the algebra Vocabulary::Comparison declares. The evaluator cannot
24
24
  # boot the chapter that configures it — the Prism adapter normalises
@@ -65,8 +65,8 @@ module Hecks
65
65
  interpret(ast_cache[expr] ||= parse(expr), state, attrs)
66
66
  end
67
67
 
68
- # THE RULE-SHAPED ENTRY — evaluates a Given/Invariant (anything
69
- # answering `canonical` and `ast`) by walking its STRUCTURED form,
68
+ # The rule-shaped entry — evaluates a Given/Invariant (anything
69
+ # answering `canonical` and `ast`) by walking its structured form,
70
70
  # never re-parsing the text: the one parse happened at DSL-build
71
71
  # time behind `AstJson`, and `AstReader` turns that tree back into
72
72
  # the same nodes `parse` would have built (the equivalence is
@@ -87,18 +87,18 @@ module Hecks
87
87
  rule.ast ? AstReader.read_predicate(rule.ast) : parse(rule.canonical)
88
88
  end
89
89
 
90
- # A refused `given`/`ensures`/`invariant` names its own DESCRIPTION
90
+ # A refused `given`/`ensures`/`invariant` names its own description
91
91
  # ("not already superseded") but, on its own, not what the block
92
92
  # actually evaluated to — the difference between "the rule is right
93
93
  # and my data is wrong" and "the rule is subtly wrong" is often just
94
94
  # seeing the two operands. Scoped to the single shape that has one
95
- # honest answer: `expr`'s own TOP-LEVEL node is a bare `Compare` —
95
+ # honest answer: `expr`'s own top-level node is a bare `Compare` —
96
96
  # not `Or`/`And`/`Not` (which of several sub-comparisons would even
97
97
  # be "the" one at fault is genuinely ambiguous), `Include` (no
98
98
  # left/right to show), or `Resolve` (a bare boolean read, nothing to
99
99
  # compare against). Values are rendered with `Rendering.describe`,
100
100
  # the same house style every other refusal already prints a value
101
- # through. Returns `nil` — not raised — on anything else, INCLUDING
101
+ # through. Returns `nil` — not raised — on anything else, including
102
102
  # an operand that itself fails to resolve (`EvaluationError`): a
103
103
  # missing diagnostic is a worse debugging experience than none, a
104
104
  # crash while building one is worse still.
@@ -122,8 +122,8 @@ module Hecks
122
122
  left, right = split_top_level(expr, "&&")
123
123
  return And.new(left: parse(left), right: parse(right)) if left
124
124
 
125
- # Tried BEFORE `.include?`/comparisons, not after — `!` negates
126
- # the WHOLE boolean expression that follows it (`!names.include?(x)`
125
+ # Tried before `.include?`/comparisons, not after — `!` negates
126
+ # the whole boolean expression that follows it (`!names.include?(x)`
127
127
  # means `!(names.include?(x))`, never "call .include? on the negated
128
128
  # receiver"), so the leading marker has to be stripped and the
129
129
  # remainder re-parsed before anything downstream gets a chance to
@@ -181,7 +181,7 @@ module Hecks
181
181
 
182
182
  # The algebra itself, on values already resolved — split out so a sign
183
183
  # test (SignTest#compares_via names an Operator symbol) can apply the
184
- # SAME primitives compare() uses against the literal 0, rather than
184
+ # same primitives compare() uses against the literal 0, rather than
185
185
  # re-deriving positive?/negative?/zero? by hand a second time.
186
186
  def apply(comparator, lhs, rhs)
187
187
  result = (comparator.compares_less_than && less_than(lhs, rhs)) ||
@@ -215,13 +215,13 @@ module Hecks
215
215
  value.nil? ? "nil" : value.class.name
216
216
  end
217
217
 
218
- # THE SAME MIS-SPLIT `Resolver.match_call` had (its own comment
218
+ # The same mis-split `Resolver.match_call` had (its own comment
219
219
  # has the full story), found here too by the same generator: a
220
- # `.include?` needle can itself be — or contain — ANOTHER
220
+ # `.include?` needle can itself be — or contain — another
221
221
  # `.include?` call (`"".include?(arr.all? { |el| "".include?("")
222
222
  # }.to_s)`, a String built via `.to_s` off a block predicate
223
223
  # whose own body happens to include one) — `rindex` finds the
224
- # INNERMOST occurrence, not the outermost this split actually
224
+ # innermost occurrence, not the outermost this split actually
225
225
  # needs. Fixed identically: try each occurrence left to right,
226
226
  # keep the first whose own balanced-paren match reaches the
227
227
  # string's last character — `Resolver.matching_paren` is reused
@@ -311,13 +311,13 @@ module Hecks
311
311
  # `{`/`}` depth -- vendored addition, not (yet) upstream
312
312
  # hecks (migration plan task 9): this method already
313
313
  # treats `(`/`)` as a grouping construct so an operator
314
- # INSIDE a call's parens is never mistaken for a top-level
314
+ # inside a call's parens is never mistaken for a top-level
315
315
  # split point ; `{`/`}` needed the identical treatment the
316
316
  # moment `Bluebook::Expression::Resolver` grew block-taking
317
317
  # `.all?`/`.any?`/`.none? { |s| PREDICATE }` support (see
318
318
  # resolver.rb's own `BlockPredicate` addition) -- without
319
- # this, an operator INSIDE the block's own predicate (e.g.
320
- # `s.length > 0`) reads as a top-level split of the WHOLE
319
+ # this, an operator inside the block's own predicate (e.g.
320
+ # `s.length > 0`) reads as a top-level split of the whole
321
321
  # `value.split("::").all? { |s| s.length > 0 }` expression,
322
322
  # confirmed live via `Lexicon::Lexicon.Lookup`/`Query::Query.
323
323
  # Run` (the exact `Phrase` invariant this gap was found
@@ -329,7 +329,7 @@ module Hecks
329
329
  # a quoted literal either, so this sits beside the existing
330
330
  # paren-depth branch, not instead of it.
331
331
  #
332
- # `[`/`]` -- the identical lesson a THIRD time (found live via
332
+ # `[`/`]` -- the identical lesson a third time (found live via
333
333
  # the type-directed bounded-exhaustive expression generator,
334
334
  # Phase 7 of the equivalence-gap plan): `Resolver::ArrayLiteral`
335
335
  # (`[a, b]`) can appear as a general sub-expression, not only
@@ -337,7 +337,7 @@ module Hecks
337
337
  # attribute or a synthesized literal is embedded anywhere else
338
338
  # -- and an element containing a top-level `+`/comparison of
339
339
  # its own (`[0, 0 + 0]`) used to read as a split point for
340
- # THIS expression's own boolean/comparison grammar, exactly
340
+ # this expression's own boolean/comparison grammar, exactly
341
341
  # the way an un-tracked `{`/`}` once did for block predicates.
342
342
  elsif ["(", "{", "["].include?(char)
343
343
  depth += 1
@@ -1,7 +1,7 @@
1
- # HAND-WRITTEN — the block-predicate/find family of the leaf grammar
1
+ # **Hand-written** — the block-predicate/find family of the leaf grammar
2
2
  # (`Bluebook::Expression::Resolver`'s own `.all?`/`.any?`/`.none?`/
3
3
  # `.find` suffixes), split into this sibling file to keep resolver.rb
4
- # under Metrics/ModuleLength (350) : this reopens the SAME `Resolver`
4
+ # under Metrics/ModuleLength (350) : this reopens the same `Resolver`
5
5
  # module resolver.rb defines, the long nested `module A; module B; ...`
6
6
  # form (not the compact `A::B` form) so bare constant/method lookups
7
7
  # here (`EvaluationError`, `Evaluator`, `describe`, `unwrap_scalar`,
@@ -12,7 +12,7 @@
12
12
  module Hecks
13
13
  module Bluebook
14
14
  module Expression
15
- # Reopens the SAME `Resolver` module resolver.rb defines — see this
15
+ # Reopens the same `Resolver` module resolver.rb defines — see this
16
16
  # file's own header comment above for why the block-predicate/find
17
17
  # family lives here rather than in resolver.rb itself.
18
18
  module Resolver
@@ -23,12 +23,12 @@ module Hecks
23
23
  # (`value.split("::").all? { |s| s.length > 0 }`). Structurally
24
24
  # different from every other addition in this file: every prior
25
25
  # suffix is a flat receiver -> scalar transform, but a block
26
- # predicate needs to evaluate its own sub-expression ONCE PER
27
- # ELEMENT with the block parameter bound to that element. Kept
26
+ # predicate needs to evaluate its own sub-expression once per
27
+ # element with the block parameter bound to that element. Kept
28
28
  # minimal per the migration plan's own instruction -- no
29
29
  # persistent iteration-variable concept added to Resolver's
30
30
  # state model at all ; `predicate` below is a fully-parsed
31
- # EVALUATOR ast (not a Resolver ast -- the predicate is a
31
+ # evaluator ast (not a Resolver ast -- the predicate is a
32
32
  # boolean/comparison expression like `s.length > 0`, exactly the
33
33
  # grammar `Bluebook::Expression::Evaluator` owns, not this
34
34
  # module's own leaf grammar), parsed once at `parse`-time same as
@@ -78,7 +78,7 @@ module Hecks
78
78
 
79
79
  # Every suffix that opens a `{ |x| ... }` block, `.find` included
80
80
  # -- shared by `parse_block_opener` below, and by nothing else
81
- # (this is NOT `BLOCK_PREDICATE_MODES` — `.find` isn't a mode
81
+ # (this is not `BLOCK_PREDICATE_MODES` — `.find` isn't a mode
82
82
  # `evaluate_block_predicate` aggregates through, it builds a
83
83
  # `Find` node instead, see below).
84
84
  BLOCK_OPENER_SUFFIXES = (BLOCK_PREDICATE_MODES.keys + ["find"]).freeze
@@ -88,27 +88,27 @@ module Hecks
88
88
  # last among the suffix rules (right before the `Lookup`
89
89
  # catch-all) since a block's own predicate text can itself
90
90
  # contain almost anything a leaf expression can, including
91
- # ANOTHER block-opening suffix -- letting every more specific
91
+ # another block-opening suffix -- letting every more specific
92
92
  # rule above try first avoids this one accidentally swallowing a
93
93
  # receiver another rule was meant to parse.
94
94
  #
95
- # ONE combined header regex over ALL FOUR suffixes together,
95
+ # One combined header regex over all four suffixes together,
96
96
  # not `.find` and `.all?/any?/none?` scanned separately (that
97
97
  # was this file's own first cut, and it broke the moment a
98
- # block predicate's own predicate text contained a DIFFERENT
98
+ # block predicate's own predicate text contained a different
99
99
  # kind of block-opener than the one being scanned for --
100
100
  # `legs.any? { |leg| ... legs.find { |o| ... } ... }` : scanning
101
- # for `.find` FIRST found the INNER `.find`, not the outer
101
+ # for `.find` first found the inner `.find`, not the outer
102
102
  # `.any?`, because a non-greedy receiver capture only guarantees
103
- # the FIRST occurrence of ITS OWN suffix, not the first
104
- # occurrence of ANY block-opening suffix -- confirmed live via
103
+ # the first occurrence of its own suffix, not the first
104
+ # occurrence of any block-opening suffix -- confirmed live via
105
105
  # the shipping domain's own re-routing rules, the same
106
106
  # "no implicit conversion of Symbol into Integer" signature the
107
107
  # original nested-`.any?` bug had, not inferred). Scanning for
108
- # all four AT ONCE and letting the regex engine's own leftmost
109
- # match win fixes both directions (`.find` nested in `.any?` OR
110
- # `.any?` nested in `.find`) with the SAME one rule, since the
111
- # true receiver never itself contains ANY of these four words
108
+ # all four at once and letting the regex engine's own leftmost
109
+ # match win fixes both directions (`.find` nested in `.any?` or
110
+ # `.any?` nested in `.find`) with the same one rule, since the
111
+ # true receiver never itself contains any of these four words
112
112
  # followed by `{`.
113
113
  #
114
114
  # `matching_brace` walks forward counting `{`/`}` depth from
@@ -210,7 +210,7 @@ module Hecks
210
210
  # comment above. Reuses `interpret_with_element` unchanged
211
211
  # (below, shared with `BlockPredicate` — both bind `node.param`
212
212
  # to one element and interpret `node.predicate` against it) to
213
- # find the FIRST element the predicate accepts, then projects
213
+ # find the first element the predicate accepts, then projects
214
214
  # `node.path` through it via `walk_path`, the same dotted-
215
215
  # segment walk `lookup` uses for a plain attribute path. `nil`
216
216
  # (no matching element, or a `path` segment that doesn't