hecks 1.2.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 (358) 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 +60 -2
  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/postgres_era.adapter +5 -0
  23. data/lib/hecks/adapters/driven/prism.rb +4 -4
  24. data/lib/hecks/adapters/driven/sql_query_builder.rb +34 -22
  25. data/lib/hecks/adapters/driven/sqlite/codec.rb +38 -10
  26. data/lib/hecks/adapters/driven/sqlite/projection.rb +60 -32
  27. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +12 -12
  28. data/lib/hecks/adapters/driven/sqlite.rb +181 -21
  29. data/lib/hecks/adapters/driven.rb +4 -4
  30. data/lib/hecks/adapters/driving/github_webhook.rb +145 -0
  31. data/lib/hecks/behaviors/dsl.rb +2 -2
  32. data/lib/hecks/behaviors/expectations.rb +51 -23
  33. data/lib/hecks/behaviors/ir.rb +1 -1
  34. data/lib/hecks/behaviors/rspec.rb +1 -1
  35. data/lib/hecks/behaviors/runner.rb +2 -2
  36. data/lib/hecks/behaviors.rb +1 -1
  37. data/lib/hecks/bluebook/aggregate.rb +13 -13
  38. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +10 -10
  39. data/lib/hecks/bluebook/assembly/build.rb +1 -1
  40. data/lib/hecks/bluebook/assembly/contract.rb +39 -16
  41. data/lib/hecks/bluebook/assembly/contracts.rb +40 -38
  42. data/lib/hecks/bluebook/assembly/marks.rb +18 -18
  43. data/lib/hecks/bluebook/assembly/specializer.rb +19 -21
  44. data/lib/hecks/bluebook/assembly.rb +9 -9
  45. data/lib/hecks/bluebook/attribute.rb +9 -9
  46. data/lib/hecks/bluebook/behaviour/aggregate.rb +11 -11
  47. data/lib/hecks/bluebook/behaviour/attribute.rb +5 -5
  48. data/lib/hecks/bluebook/behaviour/chapter.rb +23 -5
  49. data/lib/hecks/bluebook/behaviour/command.rb +23 -23
  50. data/lib/hecks/bluebook/behaviour/domain_port.rb +27 -3
  51. data/lib/hecks/bluebook/behaviour/entity.rb +8 -8
  52. data/lib/hecks/bluebook/behaviour/hexagon.rb +4 -4
  53. data/lib/hecks/bluebook/behaviour/lifecycle.rb +5 -5
  54. data/lib/hecks/bluebook/behaviour/policy.rb +12 -12
  55. data/lib/hecks/bluebook/behaviour/process_manager.rb +7 -7
  56. data/lib/hecks/bluebook/behaviour/query.rb +1 -1
  57. data/lib/hecks/bluebook/behaviour/read_model.rb +8 -8
  58. data/lib/hecks/bluebook/behaviour/traits.rb +12 -12
  59. data/lib/hecks/bluebook/behaviour/value_object.rb +6 -6
  60. data/lib/hecks/bluebook/capabilities.rb +27 -0
  61. data/lib/hecks/bluebook/chapter.rb +28 -9
  62. data/lib/hecks/bluebook/command.rb +12 -12
  63. data/lib/hecks/bluebook/domain_port.rb +9 -9
  64. data/lib/hecks/bluebook/dsl/adapter_builder.rb +24 -0
  65. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +49 -49
  66. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +96 -96
  67. data/lib/hecks/bluebook/dsl/attribute_collector.rb +41 -41
  68. data/lib/hecks/bluebook/dsl/binding_proxy.rb +22 -2
  69. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +111 -74
  70. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +48 -30
  71. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +116 -0
  72. data/lib/hecks/bluebook/dsl/command_builder.rb +103 -103
  73. data/lib/hecks/bluebook/dsl/const_shim.rb +46 -15
  74. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +90 -25
  75. data/lib/hecks/bluebook/dsl/entity_builder.rb +56 -56
  76. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +148 -132
  77. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +89 -30
  78. data/lib/hecks/bluebook/dsl/identity_declaration.rb +17 -17
  79. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +27 -4
  80. data/lib/hecks/bluebook/dsl/policy_builder.rb +30 -21
  81. data/lib/hecks/bluebook/dsl/port_builder.rb +38 -7
  82. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +56 -22
  83. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +35 -35
  84. data/lib/hecks/bluebook/dsl/query_builder.rb +5 -5
  85. data/lib/hecks/bluebook/dsl/read_model_builder.rb +34 -34
  86. data/lib/hecks/bluebook/dsl/rule_reference.rb +41 -39
  87. data/lib/hecks/bluebook/dsl/translation_builder.rb +9 -9
  88. data/lib/hecks/bluebook/dsl/value_object_builder.rb +16 -16
  89. data/lib/hecks/bluebook/dsl/word_gate.rb +59 -53
  90. data/lib/hecks/bluebook/dsl/world_builder.rb +51 -8
  91. data/lib/hecks/bluebook/entity.rb +11 -11
  92. data/lib/hecks/bluebook/expression/ast_json.rb +20 -20
  93. data/lib/hecks/bluebook/expression/ast_reader.rb +3 -3
  94. data/lib/hecks/bluebook/expression/canonical_form.rb +9 -9
  95. data/lib/hecks/bluebook/expression/evaluator.rb +18 -18
  96. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +18 -18
  97. data/lib/hecks/bluebook/expression/resolver.rb +60 -62
  98. data/lib/hecks/bluebook/hexagon.rb +1 -1
  99. data/lib/hecks/bluebook/lifecycle.rb +1 -1
  100. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -1
  101. data/lib/hecks/bluebook/meta_validator/judge.rb +122 -86
  102. data/lib/hecks/bluebook/meta_validator/plan.rb +39 -39
  103. data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -2
  104. data/lib/hecks/bluebook/meta_validator/readings.rb +43 -43
  105. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +44 -37
  106. data/lib/hecks/bluebook/meta_validator/shapes.rb +25 -21
  107. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +145 -31
  108. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +6 -6
  109. data/lib/hecks/bluebook/meta_validator/world_judge.rb +5 -5
  110. data/lib/hecks/bluebook/meta_validator.rb +70 -70
  111. data/lib/hecks/bluebook/model_check.rb +301 -84
  112. data/lib/hecks/bluebook/pattern_subset.rb +9 -9
  113. data/lib/hecks/bluebook/policy.rb +15 -13
  114. data/lib/hecks/bluebook/process_manager.rb +14 -14
  115. data/lib/hecks/bluebook/project_register.rb +6 -6
  116. data/lib/hecks/bluebook/query.rb +4 -4
  117. data/lib/hecks/bluebook/read_model.rb +14 -14
  118. data/lib/hecks/bluebook/reference.rb +8 -8
  119. data/lib/hecks/bluebook/smoke_test.rb +19 -19
  120. data/lib/hecks/bluebook/synthesizer.rb +12 -12
  121. data/lib/hecks/bluebook/translation.rb +4 -4
  122. data/lib/hecks/bluebook/value_object.rb +6 -6
  123. data/lib/hecks/bluebook.rb +2 -2
  124. data/lib/hecks/codemod/legacy_dispatch_args.rb +299 -0
  125. data/lib/hecks/codemod/legacy_dispatch_recorder.rb +186 -0
  126. data/lib/hecks/codemod.rb +36 -35
  127. data/lib/hecks/construct.rb +6 -6
  128. data/lib/hecks/corpus.rb +317 -0
  129. data/lib/hecks/deprecation.rb +95 -0
  130. data/lib/hecks/doc/reference.rb +19 -19
  131. data/lib/hecks/embryonaut_bluebook.rb +11 -11
  132. data/lib/hecks/facade/cli_door.rb +69 -10
  133. data/lib/hecks/facade/cli_runner.rb +105 -24
  134. data/lib/hecks/facade/command_request.rb +23 -0
  135. data/lib/hecks/facade/handle.rb +79 -32
  136. data/lib/hecks/facade/json_door.rb +106 -25
  137. data/lib/hecks/facade/surface/aggregate_door.rb +42 -27
  138. data/lib/hecks/facade/surface/chapter.rb +26 -17
  139. data/lib/hecks/facade/surface.rb +16 -3
  140. data/lib/hecks/facade.rb +15 -4
  141. data/lib/hecks/forms/app.rb +46 -30
  142. data/lib/hecks/forms/command_form_renderer.rb +70 -9
  143. data/lib/hecks/forms/field_renderer.rb +142 -6
  144. data/lib/hecks/forms/field_shape.rb +183 -20
  145. data/lib/hecks/forms/html.rb +51 -7
  146. data/lib/hecks/forms/index_renderer.rb +14 -2
  147. data/lib/hecks/forms/params.rb +120 -23
  148. data/lib/hecks/forms/port_argument.rb +2 -2
  149. data/lib/hecks/forms/query_form_renderer.rb +2 -2
  150. data/lib/hecks/forms/record_renderer.rb +2 -2
  151. data/lib/hecks/forms/record_table.rb +1 -1
  152. data/lib/hecks/forms/value_object_shape.rb +3 -3
  153. data/lib/hecks/forms.rb +24 -4
  154. data/lib/hecks/fqn.rb +1 -1
  155. data/lib/hecks/framework/bluebook/governance.bluebook +9 -0
  156. data/lib/hecks/framework.rb +48 -17
  157. data/lib/hecks/freezer.rb +11 -11
  158. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +90 -90
  159. data/lib/hecks/fuzzing/combination_miner.rb +119 -0
  160. data/lib/hecks/fuzzing/concurrent_dispatch.rb +361 -0
  161. data/lib/hecks/fuzzing/coverage_campaign.rb +118 -0
  162. data/lib/hecks/fuzzing/differential.rb +158 -0
  163. data/lib/hecks/fuzzing/domain_generator.rb +694 -0
  164. data/lib/hecks/fuzzing/era_boundary.rb +124 -0
  165. data/lib/hecks/fuzzing/form_census.rb +199 -0
  166. data/lib/hecks/fuzzing/generated_domain_check.rb +95 -0
  167. data/lib/hecks/fuzzing/invalid_value_generator.rb +6 -6
  168. data/lib/hecks/fuzzing/isolated_boot.rb +226 -38
  169. data/lib/hecks/fuzzing/nondeterministic.rb +67 -0
  170. data/lib/hecks/fuzzing/persistence_parity.rb +161 -0
  171. data/lib/hecks/fuzzing/properties/corrections.rb +100 -0
  172. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +321 -41
  173. data/lib/hecks/fuzzing/properties/guards.rb +129 -26
  174. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +32 -32
  175. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +31 -11
  176. data/lib/hecks/fuzzing/properties/outbox.rb +142 -0
  177. data/lib/hecks/fuzzing/properties/querying.rb +17 -17
  178. data/lib/hecks/fuzzing/properties.rb +84 -39
  179. data/lib/hecks/fuzzing/qa_settings.rb +152 -0
  180. data/lib/hecks/fuzzing/replay.rb +224 -114
  181. data/lib/hecks/fuzzing/rotation_priority.rb +94 -0
  182. data/lib/hecks/fuzzing/rust_gap_manifest.rb +113 -0
  183. data/lib/hecks/fuzzing/self_consistency.rb +676 -0
  184. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +526 -0
  185. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +101 -30
  186. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +55 -8
  187. data/lib/hecks/fuzzing/sequence_generator/picker.rb +31 -11
  188. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +123 -32
  189. data/lib/hecks/fuzzing/sequence_generator.rb +152 -31
  190. data/lib/hecks/fuzzing/shrinker.rb +197 -0
  191. data/lib/hecks/fuzzing/structural_skips.rb +39 -0
  192. data/lib/hecks/fuzzing/sweep_depth.rb +53 -0
  193. data/lib/hecks/fuzzing/target_capabilities.rb +180 -0
  194. data/lib/hecks/fuzzing/value_generator.rb +66 -14
  195. data/lib/hecks/fuzzing.rb +11 -0
  196. data/lib/hecks/grammar/evolve.rb +10 -10
  197. data/lib/hecks/grammar.rb +7 -7
  198. data/lib/hecks/ir.rb +13 -13
  199. data/lib/hecks/language/bluebook/bluebook.bluebook +41 -0
  200. data/lib/hecks/language/bluebook/policy.bluebook +11 -1
  201. data/lib/hecks/language/bluebook/vocabulary.bluebook +365 -15
  202. data/lib/hecks/language/oidc.json +5 -0
  203. data/lib/hecks/literal.rb +9 -9
  204. data/lib/hecks/naming.rb +89 -21
  205. data/lib/hecks/ports/access_control.rb +58 -2
  206. data/lib/hecks/ports/agent/answers.rb +83 -6
  207. data/lib/hecks/ports/agent.rb +119 -35
  208. data/lib/hecks/ports/authentication.rb +44 -4
  209. data/lib/hecks/ports/authorization.rb +53 -11
  210. data/lib/hecks/ports/clock.rb +42 -23
  211. data/lib/hecks/ports/extraction.rb +16 -0
  212. data/lib/hecks/ports/identity_assignment.rb +24 -2
  213. data/lib/hecks/ports/identity_generation.rb +17 -3
  214. data/lib/hecks/ports/identity_resolution.rb +18 -1
  215. data/lib/hecks/ports/loading.rb +4 -0
  216. data/lib/hecks/ports/persistence/append_only.rb +172 -8
  217. data/lib/hecks/ports/persistence/binding_policy.rb +34 -0
  218. data/lib/hecks/ports/persistence/codec_boundary.rb +178 -0
  219. data/lib/hecks/ports/persistence/execution.rb +4 -0
  220. data/lib/hecks/ports/persistence/null_saga_store.rb +12 -1
  221. data/lib/hecks/ports/persistence/plugin.rb +42 -4
  222. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +218 -25
  223. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +77 -9
  224. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +81 -24
  225. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +29 -18
  226. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +144 -60
  227. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +103 -8
  228. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +98 -23
  229. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +282 -109
  230. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +63 -25
  231. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +160 -58
  232. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +51 -28
  233. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +28 -5
  234. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +25 -12
  235. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +129 -34
  236. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +51 -6
  237. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +44 -6
  238. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +16 -0
  239. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +57 -4
  240. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +25 -2
  241. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +338 -83
  242. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +68 -10
  243. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +9 -3
  244. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +9 -2
  245. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +42 -8
  246. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -1
  247. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +36 -5
  248. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +23 -3
  249. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -19
  250. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +5 -5
  251. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +1 -1
  252. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -2
  253. data/lib/hecks/ports/persistence/plugins/era.rb +12 -2
  254. data/lib/hecks/ports/persistence/remote_runtime.rb +9 -2
  255. data/lib/hecks/ports/persistence/repository_factory.rb +29 -6
  256. data/lib/hecks/ports/persistence/state_codec.rb +319 -0
  257. data/lib/hecks/ports/persistence.rb +36 -1
  258. data/lib/hecks/ports/projection.rb +61 -7
  259. data/lib/hecks/ports/query/in_memory.rb +3 -3
  260. data/lib/hecks/ports/query/ordering.rb +6 -6
  261. data/lib/hecks/ports/query.rb +35 -0
  262. data/lib/hecks/projections/bootstrap_table.rb +112 -0
  263. data/lib/hecks/projections/diagrams.rb +75 -75
  264. data/lib/hecks/projections/glossary/html.rb +250 -0
  265. data/lib/hecks/projections/glossary/markdown.rb +105 -0
  266. data/lib/hecks/projections/glossary/mermaid.rb +110 -0
  267. data/lib/hecks/projections/glossary/page.css +271 -0
  268. data/lib/hecks/projections/glossary/page.js +72 -0
  269. data/lib/hecks/projections/glossary/sections.rb +17 -0
  270. data/lib/hecks/projections/glossary/sentences.rb +205 -0
  271. data/lib/hecks/projections/glossary.rb +214 -286
  272. data/lib/hecks/projections/ir.rb +1 -1
  273. data/lib/hecks/projections/model/deviations.rb +18 -17
  274. data/lib/hecks/projections/model.rb +25 -21
  275. data/lib/hecks/projections/oidc.rb +7 -7
  276. data/lib/hecks/projections/parser_table.rb +5 -5
  277. data/lib/hecks/projections/reference.rb +3 -3
  278. data/lib/hecks/projections/rust_vocabulary.rb +443 -0
  279. data/lib/hecks/projections/shape.rb +2 -2
  280. data/lib/hecks/projections/statements.rb +11 -11
  281. data/lib/hecks/projections/vocabulary.rb +9 -9
  282. data/lib/hecks/projections.rb +5 -3
  283. data/lib/hecks/projector/cli_projector.rb +29 -29
  284. data/lib/hecks/projector/docs_projector.rb +13 -13
  285. data/lib/hecks/projector/exporter.rb +42 -21
  286. data/lib/hecks/projector/ir_projector.rb +1 -1
  287. data/lib/hecks/projector/narrate_projector.rb +15 -22
  288. data/lib/hecks/projector/target.rb +13 -13
  289. data/lib/hecks/projector.rb +15 -15
  290. data/lib/hecks/query_ir.rb +47 -47
  291. data/lib/hecks/query_specification/common/comparators.rb +19 -3
  292. data/lib/hecks/query_specification/common/comparison.rb +132 -24
  293. data/lib/hecks/query_specification/common/dsl.rb +65 -9
  294. data/lib/hecks/query_specification/common/null_policy.rb +57 -13
  295. data/lib/hecks/query_specification/common/null_semantics.rb +4 -0
  296. data/lib/hecks/query_specification/common/options.rb +25 -0
  297. data/lib/hecks/query_specification/field_path.rb +69 -15
  298. data/lib/hecks/query_specification/hop_path.rb +57 -20
  299. data/lib/hecks/query_specification/read_model/specification.rb +4 -0
  300. data/lib/hecks/rendering.rb +3 -3
  301. data/lib/hecks/router/namespace_installer.rb +3 -3
  302. data/lib/hecks/router.rb +1 -1
  303. data/lib/hecks/runtime/aggregate_lock.rb +11 -11
  304. data/lib/hecks/runtime/boot_gates.rb +3 -3
  305. data/lib/hecks/runtime/caller.rb +8 -8
  306. data/lib/hecks/runtime/capability_graph.rb +2 -2
  307. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +22 -25
  308. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +64 -67
  309. data/lib/hecks/runtime/command_interpreter.rb +159 -102
  310. data/lib/hecks/runtime/command_rules/admissibility.rb +69 -69
  311. data/lib/hecks/runtime/command_rules/arithmetic.rb +137 -91
  312. data/lib/hecks/runtime/command_rules/authorization.rb +38 -17
  313. data/lib/hecks/runtime/command_rules/emission.rb +18 -1
  314. data/lib/hecks/runtime/command_rules/references.rb +94 -19
  315. data/lib/hecks/runtime/command_rules.rb +3 -0
  316. data/lib/hecks/runtime/dependency_planning.rb +11 -11
  317. data/lib/hecks/runtime/dispatcher.rb +283 -90
  318. data/lib/hecks/runtime/entity_element.rb +282 -46
  319. data/lib/hecks/runtime/entity_interpreter.rb +160 -69
  320. data/lib/hecks/runtime/errors.rb +19 -19
  321. data/lib/hecks/runtime/event.rb +6 -6
  322. data/lib/hecks/runtime/identity.rb +22 -22
  323. data/lib/hecks/runtime/instance.rb +39 -14
  324. data/lib/hecks/runtime/interpreting.rb +12 -12
  325. data/lib/hecks/runtime/invocation.rb +276 -0
  326. data/lib/hecks/runtime/loader.rb +14 -14
  327. data/lib/hecks/runtime/outbox.rb +23 -23
  328. data/lib/hecks/runtime/policy_interpreter.rb +54 -54
  329. data/lib/hecks/runtime/port_operation_interpreter.rb +22 -19
  330. data/lib/hecks/runtime/query_interpreter.rb +111 -56
  331. data/lib/hecks/runtime/reaction_invocation.rb +76 -9
  332. data/lib/hecks/runtime/read_model_interpreter.rb +40 -40
  333. data/lib/hecks/runtime/rebuild_sweep.rb +4 -4
  334. data/lib/hecks/runtime/reference_hop.rb +6 -6
  335. data/lib/hecks/runtime/refusal_wording.rb +92 -112
  336. data/lib/hecks/runtime/registry/saga_persistence.rb +21 -21
  337. data/lib/hecks/runtime/registry/verification.rb +36 -26
  338. data/lib/hecks/runtime/registry.rb +56 -27
  339. data/lib/hecks/runtime/remote_dispatcher.rb +38 -23
  340. data/lib/hecks/runtime/routing.rb +10 -88
  341. data/lib/hecks/runtime/saga_interpreter/correlation.rb +17 -17
  342. data/lib/hecks/runtime/saga_interpreter.rb +93 -56
  343. data/lib/hecks/runtime/saga_pending_dispatch.rb +12 -12
  344. data/lib/hecks/runtime/tenant_check.rb +9 -9
  345. data/lib/hecks/runtime/tenant_scope.rb +5 -5
  346. data/lib/hecks/runtime/value/admission.rb +75 -30
  347. data/lib/hecks/runtime/value/coercion.rb +379 -226
  348. data/lib/hecks/runtime/value/entity_list_coercion.rb +248 -0
  349. data/lib/hecks/runtime/value.rb +28 -23
  350. data/lib/hecks/runtime.rb +7 -7
  351. data/lib/hecks/storehouse.rb +64 -64
  352. data/lib/hecks/version.rb +3 -3
  353. data/lib/hecks/vocabulary.rb +207 -5
  354. data/lib/hecks.rb +13 -11
  355. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +11 -11
  356. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +14 -12
  357. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +11 -11
  358. metadata +43 -2
@@ -19,7 +19,7 @@ module Hecks
19
19
  # `Widget::Item.Add(...)` sugar. A caller that only ever dispatches
20
20
  # by FQN string (`SmokeTest`, the one caller so far) can pass
21
21
  # `false` to skip it: `Facade::Surface.install` puts a bare global
22
- # Ruby constant on `Object` per domain AND per aggregate name, with
22
+ # Ruby constant on `Object` per domain and per aggregate name, with
23
23
  # no scoping and no cleanup hook, so a tool booting arbitrary
24
24
  # throwaway domains under generic names ("Widget", "Item", "Tag")
25
25
  # would otherwise leak those names into the rest of the process —
@@ -55,7 +55,7 @@ module Hecks
55
55
  install_facade ? bind_runtime(dispatcher) : dispatcher
56
56
  end
57
57
 
58
- # THE OUTBOX'S BOOT-TIME RECONCILIATION — after the dispatcher
58
+ # The outbox's boot-time reconciliation — after the dispatcher
59
59
  # exists (a row's consumer runs through its interpreters, so this
60
60
  # cannot be a plain registry gate the way saga rehydration is) and
61
61
  # after saga rehydration (a redriven row may advance a saga, which
@@ -69,7 +69,7 @@ module Hecks
69
69
  dispatcher.outbox.redrive!
70
70
  end
71
71
 
72
- # THE EXPLICIT-FILE FORM — `paths` names the exact bluebook/hecksagon/
72
+ # The explicit-file form — `paths` names the exact bluebook/hecksagon/
73
73
  # world files to boot, in place, wherever they actually live. `boot`
74
74
  # above only ever takes a directory and globs it; that is the right
75
75
  # shape for a real deployment (`examples/banking`, a domain someone
@@ -79,16 +79,16 @@ module Hecks
79
79
  # (`Hecks::Behaviors`), but this carries no behaviors-specific
80
80
  # logic and is not gated behind requiring that module.
81
81
  #
82
- # NO COPYING, NO TEMP DIRECTORY. A prior port of this same idea
82
+ # No copying, no temp directory. A prior port of this same idea
83
83
  # (vendored into a downstream consumer, read before writing this)
84
84
  # scoped a per-test boot by copying files into `Dir.mktmpdir` — which
85
85
  # destroys real relative paths, and worse, makes a `persisted_by`
86
- # path resolve against the TEMP copy's root instead of the project's
86
+ # path resolve against the temp copy's root instead of the project's
87
87
  # own (confirmed there: a file adapter kept reading and writing the
88
88
  # same deterministic tmp copy across an entire session, because
89
89
  # `Hecks.boot`'s own `root` is always `File.dirname` of whatever
90
90
  # directory it was handed). `directory` here is `File.dirname` of the
91
- # FIRST real path in `paths` — genuinely on disk, not a copy — so
91
+ # first real path in `paths` — genuinely on disk, not a copy — so
92
92
  # every downstream path (`EraCheck`, `persisted_by`, `shared_root`)
93
93
  # resolves exactly as an ordinary directory boot's would.
94
94
  def self.boot_files(paths, shared: nil, install_facade: true, environment: nil)
@@ -110,7 +110,7 @@ module Hecks
110
110
  end
111
111
 
112
112
  # ADR 0031 — replaces two previously-hardcoded, unconditional calls
113
- # with a per-boot `BootGates` instance holding exactly the gates THIS
113
+ # with a per-boot `BootGates` instance holding exactly the gates this
114
114
  # registry's own bound adapters have a capability for. Ordering is
115
115
  # preserved: era-checking (when a persistence plugin contributes one)
116
116
  # still runs before `verify!`, saga rehydration still runs after
@@ -118,7 +118,7 @@ module Hecks
118
118
  # comment).
119
119
  #
120
120
  # ADR 0033 — this loader no longer names `EraCheck`, or any other
121
- # era-specific class, at all. Every LOADED persistence plugin
121
+ # era-specific class, at all. Every loaded persistence plugin
122
122
  # (`Ports::Persistence.each_plugin` — nothing here if nothing was
123
123
  # ever `require`d) is asked to contribute its own `:pre_verify`/
124
124
  # `:post_verify` gates generically; `:saga_rehydration` is the one
@@ -144,7 +144,7 @@ module Hecks
144
144
  # `TranslationCompute`/`TranslationRekey` data (`bluebook/
145
145
  # translation.rb`, core, no era-specific class involved), so this
146
146
  # needs nothing plugin-specific to ask "does anything declare a
147
- # compute/rekey rule at all." A LOADED persistence plugin (e.g. the
147
+ # compute/rekey rule at all." A loaded persistence plugin (e.g. the
148
148
  # era plugin's own `:era_compute_rules` gate, registered above) runs
149
149
  # the real, adapter-aware version of this check and refuses by name
150
150
  # ("...is bound to Memory") long before this ever would; this only
@@ -165,7 +165,7 @@ module Hecks
165
165
  end
166
166
 
167
167
  # `RemoteDispatcher` for a domain routed through Lambda,
168
- # `Dispatcher` otherwise — the ONE place this decision gets
168
+ # `Dispatcher` otherwise — the one place this decision gets
169
169
  # made, so everything built on top (`Handle`, `AggregateDoor`,
170
170
  # `Facade::Surface`) never has to know which class it's holding.
171
171
  # `registry.bluebooks.keys.first` is the just-booted domain's own
@@ -173,7 +173,7 @@ module Hecks
173
173
  # any `uses_framework` chapter, `bin/project_rust`'s own header
174
174
  # draws the identical distinction), not a directory basename.
175
175
  #
176
- # `dispatched_by("Lambda")` is its OWN, EXPLICIT verb — NOT
176
+ # `dispatched_by("Lambda")` is its own, explicit verb — not
177
177
  # inferred from `deployed_to("AwsLambda")`'s mere presence. Both
178
178
  # Banking's and Embryonaut's `.world` files already declare
179
179
  # `deployed_to("AwsLambda")` (it only means "a deploy target
@@ -188,13 +188,13 @@ module Hecks
188
188
  settings = registry.world(domain)&.for_verb("dispatched_by") || {}
189
189
  return Dispatcher.new(registry) unless settings[:adapter] == "Lambda"
190
190
 
191
- RemoteDispatcher.new(registry, region: settings.fetch(:region, "us-east-1"))
191
+ RemoteDispatcher.new(registry, region: settings.fetch(:region, "us-east-1"), function: settings[:function])
192
192
  end
193
193
 
194
- # THE DOOR IS INSTALLED HERE, NOT STAMPED. This used to write the
194
+ # The door is installed here, not stamped. This used to write the
195
195
  # dispatcher onto every aggregate's class (`ruby_class.runtime =`) — the
196
196
  # class-level global that made two boots in one process share one
197
- # name. The facade's modules close over THIS dispatcher instead, so the
197
+ # name. The facade's modules close over this dispatcher instead, so the
198
198
  # binding lives in the surface a boot installs, not on anything shared.
199
199
  def self.bind_runtime(dispatcher)
200
200
  Facade::Surface.install(dispatcher)
@@ -6,25 +6,25 @@ require_relative "../naming"
6
6
 
7
7
  module Hecks
8
8
  module Runtime
9
- # THE TRANSACTIONAL OUTBOX — the durable hand-off between "a command
9
+ # **The transactional outbox** — the durable hand-off between "a command
10
10
  # committed" and "everything that was owed because it committed":
11
11
  # the policies that react to its events, the process managers that
12
12
  # advance on them, and (through a policy whose trigger is an
13
13
  # outbound port operation) the external effects those reactions
14
14
  # cause. `future-features.md` item 8, built.
15
15
  #
16
- # THE SHAPE. One row per (event, consumer). A consumer is a named
16
+ # **The shape**. One row per (event, consumer). A consumer is a named
17
17
  # policy or process manager that would react to the event — resolved
18
- # at ENQUEUE time from the registry (`Fanout`), so the outbox records
19
- # WHO was owed what, not just that an event happened. Rows move
18
+ # at enqueue time from the registry (`Fanout`), so the outbox records
19
+ # who was owed what, not just that an event happened. Rows move
20
20
  # `pending → claimed → delivered | failed`:
21
21
  #
22
- # pending written in the SAME adapter transaction as the
22
+ # pending written in the same adapter transaction as the
23
23
  # aggregate save (`Interpreting#run_dispatch_order`
24
24
  # wraps `save` + `emit` + enqueue in `repository.
25
25
  # transaction`), so a row exists iff the state change
26
26
  # it reacts to committed — never one without the other.
27
- # claimed the relay is about to run this consumer. Set BEFORE
27
+ # claimed the relay is about to run this consumer. Set before
28
28
  # the reaction (a policy's `reenter`, a saga leg's
29
29
  # dispatch, an adapter call) runs.
30
30
  # delivered the consumer ran to completion — including the
@@ -33,7 +33,7 @@ module Hecks
33
33
  # tracks delivery, not the domain's answer.
34
34
  # failed the consumer raised a defect (non-refusal error).
35
35
  #
36
- # DELIVERY IS INLINE BY DEFAULT — the dispatcher drains the rows it
36
+ # **Delivery is inline by default** — the dispatcher drains the rows it
37
37
  # just wrote, in the same call, in the order C10.2 fixes (per event
38
38
  # in `emits` order: that event's policy rows, then its saga rows —
39
39
  # the emitting domain's own policies before other domains'). Nothing about the
@@ -44,20 +44,20 @@ module Hecks
44
44
  # `Relay#redrive!` — run at boot by `Loader.run_boot_gates!` —
45
45
  # finds it.
46
46
  #
47
- # WHAT REDRIVE DOES, AND DELIBERATELY DOESN'T. A `pending` row is
48
- # REDRIVEN: its consumer provably never started (claiming is the
47
+ # **What redrive does, and deliberately doesn't**. A `pending` row is
48
+ # redriven: its consumer provably never started (claiming is the
49
49
  # first thing delivery does), so running it now is exactly-once by
50
- # construction. A `claimed` row is NOT auto-redriven: the consumer
50
+ # construction. A `claimed` row is not auto-redriven: the consumer
51
51
  # started and the crash hid its outcome — the same reasoning
52
52
  # `saga_pending_dispatch.rb` gives (a stalled transfer is a better
53
53
  # defect than a double-credited one). It is surfaced loudly
54
54
  # (`warn`, and a `stalled: true` entry in `Relay#log`) and left for
55
55
  # `Relay#redrive!(claimed: true)` — an explicit operator decision,
56
56
  # never a boot-time default. `delivery_id` (event uid + consumer) is
57
- # UNIQUE per store, so a re-enqueue of the same fact to the same
57
+ # unique per store, so a re-enqueue of the same fact to the same
58
58
  # consumer is a no-op rather than a second row.
59
59
  #
60
- # WHICH ADAPTERS. Memory (in-process rows — visible to specs,
60
+ # **Which adapters**. Memory (in-process rows — visible to specs,
61
61
  # gone with the process, exactly like everything else Memory holds),
62
62
  # Sqlite and Postgres (a `hecks_outbox` table in the aggregate's own
63
63
  # database — the only way the enqueue can share the save's
@@ -93,7 +93,7 @@ module Hecks
93
93
  event.to_h.merge(correlation: event.correlation)
94
94
  end
95
95
 
96
- # THE EMITTING DOMAIN'S OWN BLUEBOOK FIRST, then the rest in load
96
+ # The emitting domain's own bluebook first, then the rest in load
97
97
  # order (C10.2) — the one policy ordering both `PolicyInterpreter#
98
98
  # policies_for` and `Fanout.policies` read.
99
99
  def bluebooks_home_first(registry, domain)
@@ -121,7 +121,7 @@ module Hecks
121
121
  end
122
122
  end
123
123
 
124
- # WHO IS OWED WHAT — the same selection `PolicyInterpreter#policies_for`
124
+ # **Who is owed what** — the same selection `PolicyInterpreter#policies_for`
125
125
  # and `SagaInterpreter#advance` make at delivery time, made once at
126
126
  # enqueue time so the row names its consumer. Policy rows first,
127
127
  # then saga rows, event order preserved within each: exactly the
@@ -129,13 +129,13 @@ module Hecks
129
129
  module Fanout
130
130
  module_function
131
131
 
132
- # ONE UID PER EVENT for this enqueue — the Event struct is
132
+ # One UID per event for this enqueue — the Event struct is
133
133
  # frozen after `emit!`, so the uid lives on the rows rather than
134
134
  # on it (and stays off `Event#to_h`, whose shape the golden and
135
135
  # parity specs pin). Policy and saga rows for the same event
136
136
  # share it, which is what makes `delivery_id` mean "this fact,
137
137
  # this consumer".
138
- # ROW ORDER IS DELIVERY ORDER (C10.2): per event, in `emits`
138
+ # Row order is delivery order (C10.2): per event, in `emits`
139
139
  # order — that event's policy rows, then its saga rows.
140
140
  def rows_for(registry, events, domain)
141
141
  uids = events.to_h { |event| [event, SecureRandom.uuid] }
@@ -194,13 +194,13 @@ module Hecks
194
194
  end
195
195
  end
196
196
 
197
- # THE RELAY — one per `Dispatcher`. Enqueues into a repository's
197
+ # **The relay** — one per `Dispatcher`. Enqueues into a repository's
198
198
  # store, drains rows inline, and redrives what a previous process
199
199
  # left behind.
200
200
  class Relay
201
201
  attr_reader :registry, :log
202
202
 
203
- # NOT `saga_log`/`reaction_log` — those are ported byte-for-byte
203
+ # Not `saga_log`/`reaction_log` — those are ported byte-for-byte
204
204
  # by the Rust kernel (`spec/rust_conformance_spec.rb`); this is
205
205
  # an additive, Ruby-only log, the same rule `saga_dispatch_log`
206
206
  # and `policy_dispatch_log` already follow.
@@ -213,7 +213,7 @@ module Hecks
213
213
  # through (`Dispatcher#initialize`). Until then this relay can
214
214
  # enqueue (that needs only the registry) but not deliver — and
215
215
  # nothing can dispatch without a dispatcher, so nothing asks it
216
- # to. The registry holds ONE relay for its lifetime; a second
216
+ # to. The registry holds one relay for its lifetime; a second
217
217
  # dispatcher fronting the same registry re-attaches, which is
218
218
  # fine because both dispatchers share every log and store.
219
219
  def attach(policies:, sagas:)
@@ -224,7 +224,7 @@ module Hecks
224
224
 
225
225
  def attached? = !@policies.nil?
226
226
 
227
- # Called INSIDE the save transaction by `Interpreting` for the
227
+ # Called inside the save transaction by `Interpreting` for the
228
228
  # command/entity paths, and outside one by `Dispatcher` for port
229
229
  # operations (which save nothing, so there is no transaction to
230
230
  # share). Returns the rows as stored (ids assigned), or nil when
@@ -243,7 +243,7 @@ module Hecks
243
243
  # outbox here" — react directly, the pre-outbox path.
244
244
  def deliver(rows, events, domain, repository)
245
245
  if rows.nil?
246
- # PER EVENT, in `emits` order — its policies, then its sagas
246
+ # Per event, in `emits` order — its policies, then its sagas
247
247
  # (C10.2, docs/semantics/bluebook-semantics.md); the same
248
248
  # order `Fanout.rows_for` lays the outbox rows in.
249
249
  events.each do |event|
@@ -287,9 +287,9 @@ module Hecks
287
287
  stores.flat_map { |repository| repository.outbox_rows(status: status) }
288
288
  end
289
289
 
290
- # BOOT-TIME RECONCILIATION. Redrives `pending` rows (never
290
+ # **Boot-time reconciliation**. Redrives `pending` rows (never
291
291
  # claimed — safe by construction); surfaces `claimed` rows and
292
- # redrives them ONLY when told to (`claimed: true`).
292
+ # redrives them only when told to (`claimed: true`).
293
293
  def redrive!(claimed: false)
294
294
  redriven = []
295
295
  stores.each do |repository|
@@ -22,13 +22,13 @@ module Hecks
22
22
  end
23
23
 
24
24
  # `deliver` returns `nil` for a policy whose `where` did not hold —
25
- # SILENTLY, the same as a policy `policies_for` never selected at all
25
+ # silently, the same as a policy `policies_for` never selected at all
26
26
  # (an `event_qualifier` miss carries no reaction_log entry either) —
27
- # so nothing is appended for it. A `for_each` policy answers an ARRAY
27
+ # so nothing is appended for it. A `for_each` policy answers an array
28
28
  # (one record per matched row) rather than one record ; `Array(...)`
29
29
  # is wrong here (it would explode a plain record Hash into its own
30
30
  # key/value pairs), so the two shapes are told apart explicitly.
31
- # `only:` — ONE `[policy, home_domain]` pair, the outbox relay's
31
+ # `only:` — one `[policy, home_domain]` pair, the outbox relay's
32
32
  # way of running exactly the consumer a row names (`Runtime::
33
33
  # Outbox::Relay#run_consumer`) instead of every policy that
34
34
  # matches the event. Selection is otherwise identical.
@@ -44,13 +44,13 @@ module Hecks
44
44
 
45
45
  private
46
46
 
47
- # SCANS EVERY LOADED BLUEBOOK, not just the emitting command's own —
48
- # a policy commonly lives in the CONSUMER's bluebook, reacting
47
+ # Scans every loaded bluebook, not just the emitting command's own —
48
+ # a policy commonly lives in the consumer's bluebook, reacting
49
49
  # passively to an event a different domain's aggregate emits (the
50
50
  # corpus-standard shape : `world/conception/bluebook/domain_cell.bluebook`'s
51
51
  # ConceiveOnAbsorption reacts `on "DomainAbsorbed"`, an event
52
52
  # `body/organs/bluebook/gut.bluebook`'s Gut.Absorb emits — two
53
- # different bluebooks, joined only by the event's NAME). Restricting
53
+ # different bluebooks, joined only by the event's name). Restricting
54
54
  # the scan to the emitting domain's own bluebook (the previous
55
55
  # shape) silently drops every cross-domain reaction : the policy is
56
56
  # never even a candidate, no refusal, no log entry, nothing —
@@ -58,12 +58,12 @@ module Hecks
58
58
  # which encode this exact cross-bluebook cascade as their contract.
59
59
  #
60
60
  # Returns [policy, home_domain] pairs rather than bare policies —
61
- # `deliver`/`deliver_for_each` fall back to the REACTING policy's
62
- # OWN domain (not the emitting one) when a trigger or for_each route
61
+ # `deliver`/`deliver_for_each` fall back to the reacting policy's
62
+ # own domain (not the emitting one) when a trigger or for_each route
63
63
  # is bare, and that fallback has to travel with each match now that
64
64
  # a single event can surface policies from several different homes.
65
65
  #
66
- # THE EMITTING DOMAIN'S OWN POLICIES FIRST, in declaration order,
66
+ # The emitting domain's own policies first, in declaration order,
67
67
  # then other bluebooks' in load order (C10.2) — the same order the
68
68
  # outbox lays its rows in (`Outbox::Fanout.policies`) and the Rust
69
69
  # kernel runs (`react_policies`: its own table, then cross-domain).
@@ -79,7 +79,7 @@ module Hecks
79
79
  end
80
80
  end
81
81
 
82
- # THE GUARD, evaluated against the triggering event's own payload —
82
+ # The guard, evaluated against the triggering event's own payload —
83
83
  # a policy has no aggregate instance of its own to read state from,
84
84
  # so `state` is empty and every bare name a `where` resolves comes
85
85
  # from `attrs` (Expression::Resolver#fetch checks `attrs` before
@@ -88,7 +88,7 @@ module Hecks
88
88
  # policy simply has none of). Called from inside `deliver`'s own
89
89
  # rescue-guarded body (both callers, below) — never guarded here —
90
90
  # so an EvaluationError (an unresolvable field, a bad comparison) is
91
- # caught the SAME way any other reaction defect is, not swallowed as
91
+ # caught the same way any other reaction defect is, not swallowed as
92
92
  # though the policy had merely declined to fire.
93
93
  def where_holds?(policy, event)
94
94
  return true if policy.where.to_s.empty?
@@ -97,7 +97,7 @@ module Hecks
97
97
  end
98
98
 
99
99
  def deliver(policy, event, domain)
100
- # `record` ASSIGNED BEFORE ANY BRANCH THAT CAN RAISE, same reason
100
+ # `record` assigned before any branch that can raise, same reason
101
101
  # `deliver_for_each`'s own header gives : both rescue clauses below
102
102
  # call `.merge` on it, and a defect raised before it existed would
103
103
  # be caught here only to raise a second, different NoMethodError
@@ -121,7 +121,7 @@ module Hecks
121
121
  # fatal to the command that emitted the event.
122
122
  record.merge(delivered: false, reason: e.message)
123
123
  rescue StandardError => e
124
- # A DEFECT, not a refusal — a NoMethodError in an interpreter, a
124
+ # A defect, not a refusal — a NoMethodError in an interpreter, a
125
125
  # NameError from a missing constant, a TypeError from a bad
126
126
  # assumption : exactly the class of thing DOMAIN_REFUSALS
127
127
  # (errors.rb, see the comment above that constant) deliberately
@@ -129,19 +129,19 @@ module Hecks
129
129
  # folding a crash into the same `delivered: false` shape as an
130
130
  # ordinary refusal makes a broken runtime read as normal operation
131
131
  # in the log. This clause does not reopen that hole: it is a
132
- # SECOND, narrower rescue, tried only once the first one above has
132
+ # second, narrower rescue, tried only once the first one above has
133
133
  # already declined to match, so a legitimate refusal still takes
134
134
  # the branch above and a defect always takes this one.
135
135
  #
136
- # Catching it HERE is safe for a fact this method's caller cannot
136
+ # Catching it here is safe for a fact this method's caller cannot
137
137
  # see from where it sits: by the time `react` runs, the command
138
- # that EMITTED `event` has already succeeded and PERSISTED
138
+ # that emitted `event` has already succeeded and persisted
139
139
  # `Dispatcher#dispatch` calls `@policies.react` only after its own
140
140
  # `announced` events are already in hand. Letting this exception
141
141
  # keep propagating would not undo that command (nothing here is
142
142
  # transactional across aggregates) — it would only blow up the
143
- # ORIGINAL caller's `dispatch` call for a failure that happened in
144
- # a DIFFERENT command, one the caller never asked to run and has no
143
+ # original caller's `dispatch` call for a failure that happened in
144
+ # a different command, one the caller never asked to run and has no
145
145
  # way to compensate for. So the defect is recorded, distinguishably
146
146
  # (`defect: true`, plus the error's own class — nothing here is
147
147
  # allowed to read like an ordinary refusal), warned to STDERR so it
@@ -152,19 +152,19 @@ module Hecks
152
152
  record.merge(delivered: false, reason: e.message, defect: true, error_class: e.class.name)
153
153
  end
154
154
 
155
- # THE FAN-OUT — `policy.for_each` names a query ; this runs it
155
+ # **The fan-out** — `policy.for_each` names a query ; this runs it
156
156
  # against the triggering event's own payload (the same source
157
157
  # `deliver`'s own ordinary path forwards to `trigger` wholesale) and
158
158
  # fires `trigger` once per row, merging each row's own id into the
159
- # forwarded payload under whichever key THE TARGET COMMAND ITSELF
159
+ # forwarded payload under whichever key the target command itself
160
160
  # expects to be addressed by (`Behaviour::Command#addressing_key_for`
161
161
  # — never a guessed, one-size mint: `Account.Freeze`, addressed by
162
- # `account` because it is declared ON Account and self-references
162
+ # `account` because it is declared on Account and self-references
163
163
  # it, refused every dispatch for as long as this hardcoded
164
164
  # `<aggregate>_id` instead — a real bug, found wiring `for_each`
165
165
  # into a real domain for the first time, not a hypothetical). A
166
166
  # refusal is recorded per row and the fan-out continues ; a crash
167
- # resolving the QUERY ITSELF, or the TARGET COMMAND'S OWN inability
167
+ # resolving the query itself, or the target command's own inability
168
168
  # to address this aggregate at all (`addressing_key_for` answering
169
169
  # `nil` — a domain-authoring mistake, not a data problem), is a
170
170
  # single top-level defect for the policy, the same shape `deliver`'s
@@ -174,9 +174,9 @@ module Hecks
174
174
 
175
175
  query_domain, aggregate_name, query_name = policy.for_each_route(domain)
176
176
  aggregate = resolve_query_aggregate(query_domain, aggregate_name, policy.for_each)
177
- # THE QUERY READS THE EVENT, never the projection — `with:` says
178
- # what the TRIGGER is given, and the fan-out's query is asking a
179
- # different question (WHICH rows) in the event's own vocabulary.
177
+ # The query reads the event, never the projection — `with:` says
178
+ # what the trigger is given, and the fan-out's query is asking a
179
+ # different question (which rows) in the event's own vocabulary.
180
180
  query_args = for_each_query_args(aggregate.query(query_name), event)
181
181
  rows = QueryInterpreter.new(@registry).call(query_domain, aggregate, query_name, query_args)
182
182
  reference_key = addressing_key_for(target, aggregate_name)
@@ -192,20 +192,20 @@ module Hecks
192
192
  record.merge(delivered: false, reason: e.message, defect: true, error_class: e.class.name)
193
193
  end
194
194
 
195
- # THE EVENT'S OWN IDENTITY IS A FACT TOO, not only its payload. A
196
- # for_each query commonly filters by the EMITTING record's own
195
+ # The event's own identity is a fact too, not only its payload. A
196
+ # for_each query commonly filters by the emitting record's own
197
197
  # identity (`OpenForCustomer`'s own `reference:`, scoping by the
198
198
  # very customer who was just suspended) — which used to arrive for
199
- # free because LEGACY dispatch left the self-addressing key riding
199
+ # free because legacy dispatch left the self-addressing key riding
200
200
  # along in `event.payload` unfiltered. Routing separated from
201
201
  # payload (`to:`/`with:`, what the facade's own bang-methods always
202
202
  # use) correctly stopped carrying it there, which left this query
203
- # silently seeing NEITHER the field it needs NOR any error saying
203
+ # silently seeing neither the field it needs nor any error saying
204
204
  # why — an empty result read as "nothing to freeze" instead of "the
205
205
  # customer" the whole reaction exists to catch.
206
206
  #
207
- # Merged in ONLY when the query declares an argument by that exact
208
- # name AND the emitting aggregate's own identity is genuinely what
207
+ # Merged in only when the query declares an argument by that exact
208
+ # name and the emitting aggregate's own identity is genuinely what
209
209
  # that name means (`construct.identity_heads`) — the same guard
210
210
  # `SagaInterpreter::Correlation#self_identified?` uses for the
211
211
  # identical shape one call away, so an unrelated aggregate sharing
@@ -229,22 +229,22 @@ module Hecks
229
229
  args
230
230
  end
231
231
 
232
- # WHAT THE TRIGGER IS GIVEN. Undeclared, the event's whole payload
232
+ # **What the trigger is given**. Undeclared, the event's whole payload
233
233
  # forwards verbatim — the behaviour every policy had before `with:`
234
234
  # existed, and still the right default for a trigger shaped like
235
235
  # its event.
236
236
  #
237
237
  # Declared, it is the same reading a saga's own `dispatch ...,
238
238
  # with:` gets (`SagaInterpreter#dispatch_args`): a Symbol names a
239
- # field on the SOURCE below, anything else is a literal the policy
239
+ # field on the source below, anything else is a literal the policy
240
240
  # supplies itself. A saga additionally resolves against its own
241
241
  # memory and correlation key; a policy has neither — it holds
242
242
  # nothing between events — so the source is the event, plus:
243
243
  #
244
- # `extra` is a FAN-OUT'S ROW KEY, merged into the source BEFORE the
244
+ # `extra` is a fan-out's row key, merged into the source before the
245
245
  # projection rather than after it. That is what lets a `for_each`
246
246
  # policy name the row it is acting on — `with: { account: :account }`
247
- # — and therefore what lets one send the row and NOTHING ELSE. A
247
+ # — and therefore what lets one send the row and nothing else. A
248
248
  # trigger needing only which record to act on is the ordinary case
249
249
  # for a fan-out, and before this it could not be written: the whole
250
250
  # event rode along, and the target had to declare every field of it
@@ -261,26 +261,26 @@ module Hecks
261
261
  label: "#{policy.name}'s trigger"
262
262
  )
263
263
 
264
- # THE RAW INPUTS `args` WAS RESOLVED FROM — same additive,
264
+ # **The raw inputs `args` was resolved from** — same additive,
265
265
  # Ruby-only shape SagaInterpreter#deliver_saga_dispatch's own
266
266
  # saga_dispatch_log gets, for Properties.dispatch_binding_
267
267
  # fidelity's own independent re-derivation of Policy#with_spec's
268
268
  # 2-branch resolution (Symbol → payload lookup, anything else →
269
269
  # literal — a policy holds no correlation and no memory, so
270
270
  # `payload` — the merged event-payload-plus-fan-out-row source —
271
- # is the WHOLE source, unlike a saga's own 4-branch one).
271
+ # is the whole source, unlike a saga's own 4-branch one).
272
272
  @registry.policy_dispatch_log << { policy: policy.name, on: event.name, payload: payload,
273
273
  with_spec: policy.with_spec, args: args }
274
274
  args
275
275
  end
276
276
 
277
- # THE EMITTING RECORD'S OWN IDENTITY IS A FACT A PROJECTION MAY READ
277
+ # The emitting record's own identity is a fact a projection may read
278
278
  # — the same reasoning `for_each_query_args` gives one method up,
279
- # extended from the fan-out's QUERY to the trigger's own `with:`.
279
+ # extended from the fan-out's query to the trigger's own `with:`.
280
280
  # Routing separated from payload (`to:`/`with:`) stopped carrying
281
281
  # the emitting aggregate's identity in the payload, which is right
282
282
  # for the event (a KnightCaptured is a fact about a knight, not a
283
- # re-statement of which game) but left a CROSS-aggregate reaction
283
+ # re-statement of which game) but left a cross-aggregate reaction
284
284
  # with no way to say which record to address: chess's Graveyard is
285
285
  # one-per-game, fed by policy from every piece's own Captured
286
286
  # event, and its burials had no way to name the game — the
@@ -288,10 +288,10 @@ module Hecks
288
288
  # graveyard's identity and refused every one ("no Graveyard with
289
289
  # label.value \"bb\""). Same-aggregate targets were already covered
290
290
  # (`ReactionInvocation.source_receiver_for` lifts Event.id), so
291
- # this is the OTHER aggregate's half of that.
291
+ # this is the other aggregate's half of that.
292
292
  #
293
293
  # Offered under the emitting aggregate's own identity heads, only
294
- # to an EXPLICIT projection (a legacy wholesale forward keeps its
294
+ # to an explicit projection (a legacy wholesale forward keeps its
295
295
  # exact old payload), and never over a value the payload itself
296
296
  # carries. `event.id` is the scalar the identity resolves to, so a
297
297
  # projection naming it as the target's own identity head routes it
@@ -309,9 +309,9 @@ module Hecks
309
309
  construct.identity_heads.to_h { |head| [head.to_sym, event.id] }
310
310
  end
311
311
 
312
- # RESOLVES `target` ("Domain::Aggregate.Command", the same shape
313
- # `deliver`'s own caller already built) back to its OWN declared
314
- # command, then asks IT how it expects to be addressed by a row of
312
+ # Resolves `target` ("Domain::Aggregate.Command", the same shape
313
+ # `deliver`'s own caller already built) back to its own declared
314
+ # command, then asks it how it expects to be addressed by a row of
315
315
  # `aggregate_name` — see `Behaviour::Command#addressing_key_for`'s
316
316
  # own comment for the two shapes that answers. Raises (caught by
317
317
  # `deliver_for_each`'s own outer `rescue StandardError`, the same
@@ -342,8 +342,8 @@ module Hecks
342
342
  reason: "reaction depth #{@door.max_reaction_depth} reached")
343
343
  end
344
344
 
345
- # ALREADY MERGED, by `trigger_args` — the row key belongs in the
346
- # source a `with:` projection reads FROM, not bolted onto its
345
+ # Already merged, by `trigger_args` — the row key belongs in the
346
+ # source a `with:` projection reads from, not bolted onto its
347
347
  # result, or a projection could never name the row it acts on.
348
348
  @door.reenter(target, **reaction_invocation(target, args, policy, event))
349
349
  row_record.merge(delivered: true)
@@ -361,20 +361,20 @@ module Hecks
361
361
  )
362
362
  end
363
363
 
364
- # `for_each`'s own QUERY route moved onto the Policy itself
364
+ # `for_each`'s own query route moved onto the Policy itself
365
365
  # (Behaviour::Policy#for_each_route) — one reading the interpreter
366
366
  # and the fuzzer's fan-out property both call, rather than the
367
- # same split spelled twice. The reference-KEY the dispatch itself
368
- # uses is `addressing_key_for`, above — a property of the TARGET
369
- # COMMAND, not of the policy, so it lives on `Behaviour::Command`
367
+ # same split spelled twice. The reference-key the dispatch itself
368
+ # uses is `addressing_key_for`, above — a property of the target
369
+ # command, not of the policy, so it lives on `Behaviour::Command`
370
370
  # instead.
371
371
 
372
372
  def resolve_query_aggregate(domain, aggregate_name, verb)
373
373
  bluebook = @registry.bluebook(domain) ||
374
- raise(UnknownVerb, RefusalWording.render("UnknownVerb", "no_domain", domain: domain.inspect, verb: verb))
374
+ raise(UnknownVerb, RefusalWording.render_site("UnknownVerb", "no_domain", domain: domain, verb: verb))
375
375
  bluebook.aggregate(aggregate_name) ||
376
- raise(UnknownVerb, RefusalWording.render("UnknownVerb", "no_aggregate",
377
- domain: domain, aggregate: aggregate_name.inspect))
376
+ raise(UnknownVerb, RefusalWording.render_site("UnknownVerb", "no_aggregate",
377
+ domain: domain, aggregate: aggregate_name))
378
378
  end
379
379
  end
380
380
  end