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
@@ -1,23 +1,23 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # WHAT AN ATTRIBUTE DOES. The declared half — name, type, list,
4
+ # **What an attribute does**. The declared half — name, type, list,
5
5
  # default, optional, pattern, admits — is what the language states
6
6
  # in `aggregate.bluebook`'s own `Field`. These are the questions
7
- # readers ask ABOUT that shape, which no declaration states.
7
+ # readers ask about that shape, which no declaration states.
8
8
  module Attribute
9
9
  def list? = @list
10
10
  def scalar? = !@list
11
11
  def reference? = @type.is_a?(Reference)
12
12
 
13
- # MAY THIS FACT BE LEFT OUT?
13
+ # May this fact be left out?
14
14
  #
15
15
  # Required is the default and by far the common case — a command takes
16
- # the arguments it declares, and all of them — so the EXCEPTION is what
16
+ # the arguments it declares, and all of them — so the exception is what
17
17
  # gets marked. Marking the other way would annotate almost every
18
18
  # attribute in the corpus to say nothing.
19
19
  #
20
- # Only a COMMAND enforces this. An aggregate's own attributes are filled
20
+ # Only a command enforces this. An aggregate's own attributes are filled
21
21
  # by the commands that set them, and a value object's by its
22
22
  # constructor ; neither is a payload anyone hands in.
23
23
  def optional? = @optional
@@ -3,17 +3,17 @@ require_relative "traits"
3
3
  module Hecks
4
4
  module Bluebook
5
5
  module Behaviour
6
- # WHAT A CHAPTER DOES. The declared half is the roll-call of what a
6
+ # **What a chapter does**. The declared half is the roll-call of what a
7
7
  # bluebook holds; these are the finders over it, plus `verbs` — the
8
8
  # chapter's own list of every dispatchable name, which is derived
9
9
  # from the aggregates rather than declared anywhere.
10
10
  module Chapter
11
11
  include Owns
12
12
 
13
- # THE HOOK THE GENERATED CONSTRUCTOR CALLS. Three things a
14
- # declaration does not state: that a chapter is the ROOT of the
13
+ # The hook the generated constructor calls. Three things a
14
+ # declaration does not state: that a chapter is the root of the
15
15
  # owner chain (nothing declares it, it is what having no owner
16
- # MEANS), the ports table — which a `.hecksagon` fills later, so
16
+ # means), the ports table — which a `.hecksagon` fills later, so
17
17
  # the bluebook cannot declare it — and stamping its own children,
18
18
  # the same act an Aggregate performs one level down.
19
19
  def settle
@@ -28,7 +28,25 @@ module Hecks
28
28
  def read_model(named) = @read_models.find { |model| model.name == named.to_s || model.query_name == named.to_s }
29
29
  def port(named) = @ports_by_name[named.to_s]
30
30
 
31
- # A PORT IS DECLARED IN THE HECKSAGON, not the bluebook so it
31
+ # What this chapter declared it provides `{ key => local verb }`
32
+ # for one capability, or nil when it declares none. Read by
33
+ # everything that used to recognise the Governance chapter by its
34
+ # name (`Registry#authorization_provider_for`).
35
+ def provision(capability)
36
+ rows = @provides.select { |row| row.capability == capability.to_s }
37
+ rows.empty? ? nil : rows.to_h { |row| [row.key.to_sym, row.verb] }
38
+ end
39
+
40
+ def provides?(capability) = !provision(capability).nil?
41
+
42
+ # The declared verb for `key`, qualified with this chapter's own
43
+ # name — the spelling `Dispatcher#dispatch`/`#query` take.
44
+ def provided_verb(capability, key)
45
+ local = provision(capability)&.fetch(key.to_sym, nil)
46
+ local && "#{name}::#{local}"
47
+ end
48
+
49
+ # A port is declared in the hecksagon, not the bluebook — so it
32
50
  # attaches after the chapter already exists, the same way an
33
51
  # aggregate's own ports do.
34
52
  def add_port(port)
@@ -3,8 +3,8 @@ require_relative "traits"
3
3
  module Hecks
4
4
  module Bluebook
5
5
  module Behaviour
6
- # WHAT A COMMAND DOES. EXTENDED, not included — a command is a
7
- # CLASS, one per declared verb.
6
+ # **What a command does**. Extended, not included — a command is a
7
+ # class, one per declared verb.
8
8
  module Command
9
9
  include Indexed
10
10
 
@@ -17,8 +17,8 @@ module Hecks
17
17
 
18
18
  # The construct this verb acts upon — the construct itself, not its name.
19
19
  #
20
- # A verb declared on an ENTITY always acts on that piece. It never
21
- # self-references, because an element is addressed THROUGH its parent —
20
+ # A verb declared on an entity always acts on that piece. It never
21
+ # self-references, because an element is addressed through its parent —
22
22
  # which means `creates?` answers true for every one of them, and reading
23
23
  # `acts_on` off `creates?` alone would report that `LedgerEntry.Amend`
24
24
  # brings a ledger entry into being. Three of banking's commands were
@@ -27,9 +27,9 @@ module Hecks
27
27
  # On an aggregate, a creating command acts on no existing root, so nil is
28
28
  # the truth: there is nothing there yet.
29
29
  def acts_on
30
- # FULLY QUALIFIED, and it has to be: inside `module Behaviour`
30
+ # Fully qualified, and it has to be: inside `module Behaviour`
31
31
  # the bare name `Entity` resolves to Behaviour::Entity — this
32
- # module's SIBLING — not to the construct. Comparing a Class to
32
+ # module's sibling — not to the construct. Comparing a Class to
33
33
  # a Module answers nil, so the guard silently fell through and
34
34
  # every entity verb reported acting on nothing.
35
35
  return hecks_owner if hecks_owner.is_a?(Class) && hecks_owner < Bluebook::Entity
@@ -39,8 +39,8 @@ module Hecks
39
39
 
40
40
  def creates? = @references.nil?
41
41
 
42
- # EVERY REASON THIS VERB CAN REFUSE ON A RULE — the descriptions of
43
- # its givens AND its ensures, the exact text the runtime quotes
42
+ # Every reason this verb can refuse on a rule — the descriptions of
43
+ # its givens and its ensures, the exact text the runtime quotes
44
44
  # after "refused — " when a guard is not met (see
45
45
  # command_rules/admissibility.rb's GivenNotMet/EnsuresNotMet). A
46
46
  # property that asks "did the runtime only ever refuse for a rule
@@ -49,8 +49,8 @@ module Hecks
49
49
  # (behavior.bluebook's Rule) and an unnamed one quotes nothing.
50
50
  def guard_descriptions = (@givens + @ensures).map(&:description).compact
51
51
 
52
- # THE ARGUMENT NAME THAT ADDRESSES an instance of `aggregate_name`
53
- # for THIS command — the one fact `PolicyInterpreter`'s own
52
+ # The argument name that addresses an instance of `aggregate_name`
53
+ # for this command — the one fact `PolicyInterpreter`'s own
54
54
  # `for_each` fan-out needs and, until this reading existed, had
55
55
  # to guess at (see git blame: `Behaviour::Policy
56
56
  # #fan_out_reference_key`, which hardcoded `<aggregate>_id`
@@ -58,28 +58,28 @@ module Hecks
58
58
  # addressing command as a result — `Account.Freeze`, addressed
59
59
  # by `number`/`account`, not `account_id`).
60
60
  #
61
- # TWO SHAPES, the same two `CommandBuilder#reference_to` already
61
+ # Two shapes, the same two `CommandBuilder#reference_to` already
62
62
  # tells apart at declare time (command_builder.rb's own comment
63
- # on `cross_reference` — "`as:` MEANS a named attribute... a
64
- # command can point at another instance of its OWN kind"):
63
+ # on `cross_reference` — "`as:` means a named attribute... a
64
+ # command can point at another instance of its own kind"):
65
65
  #
66
- # SELF-ADDRESSING — `references == aggregate_name` (this verb
67
- # is declared ON the very aggregate it acts on, `reference_to
66
+ # self-addressing — `references == aggregate_name` (this verb
67
+ # is declared on the very aggregate it acts on, `reference_to
68
68
  # Account` on a command Account itself owns). No attribute was
69
- # minted for it at all; the SAME bare key
69
+ # minted for it at all; the same bare key
70
70
  # `CommandInterpreter::ArgumentGate#reference_key` already
71
71
  # accepts as "addressing, not describing" is reused here
72
72
  # rather than re-derived — one door, not two.
73
73
  #
74
- # CROSS-REFERENCING — a real, declared reference-typed
75
- # attribute whose OWN target is `aggregate_name` (`customer_id`
76
- # on `Account.Open`, or whatever `as:` named it). Its NAME is
74
+ # cross-referencing — a real, declared reference-typed
75
+ # attribute whose own target is `aggregate_name` (`customer_id`
76
+ # on `Account.Open`, or whatever `as:` named it). Its name is
77
77
  # the key, exactly as declared — never re-derived from the
78
78
  # target's name, because an `as:` reference's name and its
79
79
  # target's snake case can legitimately differ (`Transfer`'s own
80
80
  # `source`/`destination`, both `Reference<Account>`).
81
81
  #
82
- # `nil` when neither shape matches — a CREATING command (nothing
82
+ # `nil` when neither shape matches — a creating command (nothing
83
83
  # to address yet) or one that simply never references this
84
84
  # aggregate at all. A caller minting a fan-out dispatch is
85
85
  # expected to treat `nil` as "this command cannot be addressed by
@@ -92,11 +92,11 @@ module Hecks
92
92
  end
93
93
  end
94
94
 
95
- # A MUTATION'S OWN READINGS. Included (not extended) — Mutation is
95
+ # **A mutation's own readings**. Included (not extended) — Mutation is
96
96
  # a Struct, so these are instance methods.
97
97
  module Mutation
98
- # An APPEND binds several fields at once, each from either a command
99
- # ARGUMENT (a Symbol) or a LITERAL. It used to spell the Symbol bare
98
+ # An append binds several fields at once, each from either a command
99
+ # argument (a Symbol) or a literal. It used to spell the Symbol bare
100
100
  # and inspect the rest, which is the opposite of what a where-clause
101
101
  # did with the same two kinds — see Hecks::Literal.
102
102
  def appended_fields = source.transform_values { |value| Literal.render(value) }
@@ -3,17 +3,17 @@ require_relative "traits"
3
3
  module Hecks
4
4
  module Bluebook
5
5
  module Behaviour
6
- # WHAT ONE PORT OPERATION DOES.
6
+ # **What one port operation does**.
7
7
  module PortOperation
8
8
  include Indexed
9
9
 
10
- # An operation declares no reference of its own — the OWNER is
10
+ # An operation declares no reference of its own — the owner is
11
11
  # what it acts for, and `identity_attribute` is how that is found.
12
12
  def references = nil
13
13
 
14
- # NEVER a creating command — a port operation always acts on an
14
+ # Never a creating command — a port operation always acts on an
15
15
  # aggregate that already exists (`operation.to`/`identity_attribute`
16
- # both name where its RECEIVER comes from, never a birth). Answered
16
+ # both name where its receiver comes from, never a birth). Answered
17
17
  # explicitly, not derived from `references` the way `Command
18
18
  # #creates?` is (`references.nil?` would read every operation as
19
19
  # creating, since `references` above is unconditionally nil) —
@@ -27,10 +27,10 @@ module Hecks
27
27
  @attributes.find { |attribute| attribute.reference? && attribute.type.target_name == owner_name.to_s }
28
28
  end
29
29
 
30
- # THE SAME READING `Command#addressing_key_for` gives, minus its
30
+ # The same reading `Command#addressing_key_for` gives, minus its
31
31
  # self-addressing branch — a port operation's `references` is
32
32
  # unconditionally nil (above), so it never means "this verb is
33
- # declared ON the very aggregate it acts on" the way a command's
33
+ # declared on the very aggregate it acts on" the way a command's
34
34
  # does; a port operation's only path back to its owner is a real,
35
35
  # declared reference-typed attribute, which is exactly what
36
36
  # `identity_attribute` already finds. Needed for the identical
@@ -40,7 +40,7 @@ module Hecks
40
40
  def addressing_key_for(aggregate_name) = identity_attribute(aggregate_name)&.name
41
41
  end
42
42
 
43
- # WHAT A PORT DOES — one finder over its declared operations.
43
+ # **What a port does** — one finder over its declared operations.
44
44
  module DomainPort
45
45
  def operation(named) = @operations.find { |op| op.hecks_name == named.to_s }
46
46
  end
@@ -3,8 +3,8 @@ require_relative "traits"
3
3
  module Hecks
4
4
  module Bluebook
5
5
  module Behaviour
6
- # WHAT AN ENTITY DOES. EXTENDED, not included — an entity is a
7
- # CLASS, so this is singleton behaviour.
6
+ # **What an entity does**. Extended, not included — an entity is a
7
+ # class, so this is singleton behaviour.
8
8
  #
9
9
  # `settle` is the same seam an Aggregate has, reached from `absorb`
10
10
  # rather than from a constructor because a declared entity is built
@@ -29,26 +29,26 @@ module Hecks
29
29
  @queries_by_name = index_by_hecks_name(@queries)
30
30
  end
31
31
 
32
- # S17, ADR 0026 — `@entities`, now genuinely NESTED entities
32
+ # S17, ADR 0026 — `@entities`, now genuinely nested entities
33
33
  # (Dispatch, inside Handler) rather than always `[]`. Kept as a
34
34
  # real reader rather than a hardcoded empty list for two
35
35
  # reasons at once: `Value::Coercion#for_attribute` calls
36
- # `.entities` on WHATEVER OWNER it is handed — an aggregate's or
37
- # an entity's own — the moment it meets ANY `list_of(...)`
36
+ # `.entities` on whatever owner it is handed — an aggregate's or
37
+ # an entity's own — the moment it meets any `list_of(...)`
38
38
  # attribute (entity-typed or not — `hydrate_entity_list`'s own
39
39
  # fallback, `return value unless entity`, only runs once
40
40
  # `.entities` has already answered) ; and `EntityInterpreter`
41
- # now walks a DOTTED chain of entities one level at a time
41
+ # now walks a dotted chain of entities one level at a time
42
42
  # (`walk_entity_chain`) exactly the way an aggregate's own
43
43
  # `.entities` is walked for its direct children. Entity's own
44
44
  # header comment already promises it stays "structurally
45
45
  # interchangeable with an aggregate" for exactly this reason.
46
46
  def entities = @entities || []
47
47
 
48
- # A piece OWNS the verbs declared on it, so they can state an
48
+ # A piece owns the verbs declared on it, so they can state an
49
49
  # identity — `Banking::Account.Ledger.Deposit` rather than a
50
50
  # command that cannot say what it belongs to. Separate from
51
- # `settle` because `declare` stamps AFTER absorbing, once the
51
+ # `settle` because `declare` stamps after absorbing, once the
52
52
  # subclass that will own them exists. `@entities` too now
53
53
  # (S17, ADR 0026) — a nested entity states its own owner chain
54
54
  # exactly the way a nested command does.
@@ -1,7 +1,7 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # WHAT A HECKSAGON DOES — the lookups over its declared binds.
4
+ # **What a hecksagon does** — the lookups over its declared binds.
5
5
  module Hecksagon
6
6
  # Aggregate-specific bind wins when one was declared; otherwise
7
7
  # falls back to a domain-level default (`b.aggregate.nil?` — see
@@ -21,7 +21,7 @@ module Hecks
21
21
  end
22
22
  end
23
23
 
24
- # WHAT A WORLD DOES — settings lookup, with the adapter-specific
24
+ # **What a world does** — settings lookup, with the adapter-specific
25
25
  # entry falling back to the verb's own.
26
26
  module World
27
27
  def for_verb(verb) = @settings.fetch(verb.to_s, {})
@@ -30,13 +30,13 @@ module Hecks
30
30
  # end`) only answers for the adapter it actually names — falling
31
31
  # back to it unconditionally applies one adapter's settings to an
32
32
  # unrelated one. Real, corpus-caught bug: a hecksagon binding two
33
- # aggregates to two different adapters under the SAME verb (one to
33
+ # aggregates to two different adapters under the same verb (one to
34
34
  # Heki, one to Memory) sent Memory's lookup down Heki's generic
35
35
  # entry, then failed `check_settings` with "Memory does not
36
36
  # declare :dir" — the generic entry's own `settings[:adapter]`
37
37
  # names Heki, not Memory, so the fallback was never actually for
38
38
  # this bind. `{}` is exactly right when nothing was configured for
39
- # THIS adapter — Memory, which takes no values at all.
39
+ # this adapter — Memory, which takes no values at all.
40
40
  def for_binding(verb, adapter)
41
41
  qualified = @settings["#{verb}:#{adapter.to_s.downcase}"]
42
42
  return qualified if qualified
@@ -1,8 +1,8 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # WHAT A LIFECYCLE DOES. Its declared half is a field, a starting
5
- # state and a transition list. Everything here READS that — which
4
+ # **What a lifecycle does**. Its declared half is a field, a starting
5
+ # state and a transition list. Everything here reads that — which
6
6
  # states exist, which transition a command takes, and how one
7
7
  # declared transition expands into the several rows the emission
8
8
  # carries when `from` names more than one source state.
@@ -21,7 +21,7 @@ module Hecks
21
21
 
22
22
  private
23
23
 
24
- # ONE DECLARED TRANSITION IS SEVERAL ROWS when `from` names more
24
+ # One declared transition is several rows when `from` names more
25
25
  # than one source state — the emission carries them flat, so the
26
26
  # fan-out happens here rather than in whatever reads it.
27
27
  def expand(command, transition)
@@ -37,8 +37,8 @@ module Hecks
37
37
  return nil if matches.empty?
38
38
  return matches.first unless current_state
39
39
 
40
- # NOT `|| matches.first` — that used to silently hand back an
41
- # ARBITRARY declared transition for `command` whenever none of
40
+ # Not `|| matches.first` — that used to silently hand back an
41
+ # arbitrary declared transition for `command` whenever none of
42
42
  # them actually admitted `current_state`, picking a `target`
43
43
  # that command dispatch would in fact have refused (that
44
44
  # refusal is `CommandRules::Admissibility#admissible_transition`'s
@@ -1,10 +1,10 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # WHAT A POLICY DOES. Its declared half is four plain fields; these
4
+ # **What a policy does**. Its declared half is four plain fields; these
5
5
  # are the readings taken off them.
6
6
  module Policy
7
- # The BLUEBOOK's name for this construct, asked the same way of a class
7
+ # The bluebook's name for this construct, asked the same way of a class
8
8
  # that has crossed over and of an IR object that has not. Collapses into
9
9
  # Construct when this one crosses.
10
10
  def hecks_name = @name
@@ -13,18 +13,18 @@ module Hecks
13
13
 
14
14
  def event_name = Naming.unqualified(@on_event)
15
15
 
16
- # WHETHER THIS POLICY FANS OUT — `for_each` names a query, and a
16
+ # Whether this policy fans out — `for_each` names a query, and a
17
17
  # non-empty one turns a single reaction into one dispatch per row
18
18
  # the query answers. Read by the interpreter that runs the fan-out
19
19
  # and by the property that checks it dispatched once per row.
20
20
  def fans_out? = !@for_each.to_s.empty?
21
21
 
22
- # WHETHER THIS POLICY IS GUARDED — a non-empty `where` decides
22
+ # Whether this policy is guarded — a non-empty `where` decides
23
23
  # whether the policy fires at all, read against the triggering
24
24
  # event's own payload.
25
25
  def guarded? = !@where.to_s.empty?
26
26
 
27
- # THE STRUCTURED FORM OF `where`, derived once — the same tree
27
+ # The structured form of `where`, derived once — the same tree
28
28
  # `AstJson.emit_predicate` spells for every rule row, memoized
29
29
  # here because a policy is consulted once per event, not once per
30
30
  # boot. Nil when there is no `where`, exactly as the wire carries
@@ -42,9 +42,9 @@ module Hecks
42
42
  # it; an unmet where is a silent skip).
43
43
  def where_rule = @where_rule ||= Given.new(description: nil, canonical: @where, ast: where_ast)
44
44
 
45
- # THE FAN-OUT QUERY'S ROUTE, split the way the runtime runs it:
45
+ # The fan-out query's route, split the way the runtime runs it:
46
46
  # `[query_domain, aggregate_name, query_name]`. The query runs
47
- # against the triggering event's OWN domain unless `for_each`
47
+ # against the triggering event's own domain unless `for_each`
48
48
  # names one ("Domain::Aggregate.query"). Deliberately independent
49
49
  # of `across`/`target_domain`, which name where `trigger` fires,
50
50
  # not where the fan-out's own query runs.
@@ -54,13 +54,13 @@ module Hecks
54
54
  [domain, aggregate, query_name]
55
55
  end
56
56
 
57
- # THE ARGUMENT NAME A FAN-OUT DISPATCH mints each matched row's id
58
- # under used to be minted HERE, unconditionally, as `<aggregate>
59
- # _id` — a real bug: a target command declared ON the very
57
+ # The argument name a fan-out dispatch mints each matched row's id
58
+ # under used to be minted here, unconditionally, as `<aggregate>
59
+ # _id` — a real bug: a target command declared on the very
60
60
  # aggregate it self-references (`Account.Freeze`) is addressed by
61
- # its OWN identity field's name, not a synthetic foreign key, and
61
+ # its own identity field's name, not a synthetic foreign key, and
62
62
  # every such dispatch refused. That question is not this policy's
63
- # to answer at all — it depends on the TARGET COMMAND'S OWN
63
+ # to answer at all — it depends on the target command's own
64
64
  # declared shape, not on the aggregate name alone — so it now
65
65
  # lives on `Behaviour::Command#addressing_key_for`, asked of the
66
66
  # resolved target command by `PolicyInterpreter#addressing_key_for`.
@@ -1,13 +1,13 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # WHAT A PROCESS MANAGER DOES. Its declared half is the trigger,
4
+ # **What a process manager does**. Its declared half is the trigger,
5
5
  # the states and the handlers; the compensation half — `saga` — is
6
- # DERIVED from the handler that answers a refusal, not declared.
6
+ # derived from the handler that answers a refusal, not declared.
7
7
  module ProcessManager
8
8
  def hecks_name = @name
9
9
 
10
- # THE LEG THAT ANSWERS — selected by (event, current state), C10.3
10
+ # The leg that answers — selected by (event, current state), C10.3
11
11
  # (docs/semantics/bluebook-semantics.md). Two legs may answer the
12
12
  # same event from different states; which one runs is decided by
13
13
  # the state the instance is in, never by declaration order. With
@@ -25,7 +25,7 @@ module Hecks
25
25
 
26
26
  def handles?(event) = @handlers.any? { |h| h.event_type == event.to_s }
27
27
 
28
- # WHETHER A STATE IS ONE THIS PROCEDURE DECLARES — asked of a value
28
+ # Whether a state is one this procedure declares — asked of a value
29
29
  # a real run left a saga instance holding (its live or rehydrated
30
30
  # state), the way `Lifecycle#states` is asked of an aggregate's
31
31
  # resting field. A rehydrated instance in a state no handler could
@@ -43,13 +43,13 @@ module Hecks
43
43
  leg = handler_for(Bluebook::ProcessManager::REFUSED)
44
44
  return nil unless leg
45
45
 
46
- # `compensations` — a STATIC PREVIEW, declaration order, not
46
+ # `compensations` — a static preview, declaration order, not
47
47
  # one instance's own runtime history (which legs a given
48
48
  # instance actually completed is per-instance state,
49
49
  # `SagaInterpreter`'s own `completed_compensations`, not a
50
50
  # fact `Saga` — a pure declaration reading — could ever hold).
51
- # Every `compensates` ANY handler's own dispatch declares,
52
- # forward declaration order, THEN whatever this leg's own
51
+ # Every `compensates` any handler's own dispatch declares,
52
+ # forward declaration order, then whatever this leg's own
53
53
  # hand-written body still lists — coexistence, not replacement
54
54
  # (`ProcessManagerBuilder::HandlerBuilder#dispatch_impl`'s own
55
55
  # comment): a saga can derive some of its compensation and
@@ -1,7 +1,7 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # WHAT A QUERY DOES beyond holding its declared shape.
4
+ # What a query does beyond holding its declared shape.
5
5
  module Query
6
6
  def attribute(named) = @attributes.find { |a| a.name == named.to_sym }
7
7
  end
@@ -1,7 +1,7 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # WHAT A READ MODEL DOES. Its declared half is the gathered heads
4
+ # **What a read model does**. Its declared half is the gathered heads
5
5
  # and the query shape; these are readings taken off them.
6
6
  module ReadModel
7
7
  def group_by_fields = @group_by.map { |row| row[:field].to_sym }
@@ -14,11 +14,11 @@ module Hecks
14
14
 
15
15
  def query_name = Naming.snake(@name)
16
16
 
17
- # WHICH GATHERED HEADS THE FILTERING APPLIES TO (ADR 0055) — plural,
17
+ # Which gathered heads the filtering applies to (ADR 0055) — plural,
18
18
  # since `where`/`order_by`/`limit`/`offset` can now each independently
19
19
  # name a many-side head via `on:` once there's more than one. A read
20
20
  # model with a single many-side head keeps the old reading: every
21
- # UNTARGETED option (plus `group_by`/`count`/`median`, still
21
+ # untargeted option (plus `group_by`/`count`/`median`, still
22
22
  # single-head-only — ADR 0055) applies to it, same as before `on:`
23
23
  # existed. With several many-side heads, only the ones actually named
24
24
  # by a targeted option are eligible.
@@ -33,7 +33,7 @@ module Hecks
33
33
  end
34
34
 
35
35
  # The pre-`on:` reading (ADR 0055), unchanged: with exactly one
36
- # many-side head, every UNTARGETED option (plus `group_by`/`count`/
36
+ # many-side head, every untargeted option (plus `group_by`/`count`/
37
37
  # `median`, still single-head-only) applies to it — split out only
38
38
  # to keep `filtered_head_names` itself under this file's own
39
39
  # complexity budget, not because the two questions differ in kind.
@@ -43,13 +43,13 @@ module Hecks
43
43
  declared ? [many.first[:as]] : []
44
44
  end
45
45
 
46
- # THE where/order_by/limit/offset THAT APPLY TO ONE ELIGIBLE HEAD
46
+ # The where/order_by/limit/offset that apply to one eligible head
47
47
  # (ADR 0055) — a small view `Ports::Query::InMemory.execute` reads
48
48
  # exactly the way it already reads a whole `Query`/`ReadModel`
49
49
  # (`.wheres`/`.order_by`/`.limit`/`.offset`/`.null_semantics`), scoped
50
- # to `head_as`'s own aggregate: an UNTARGETED option applies when
51
- # `head_as` is the read model's ONE many-side head (the pre-`on:`
52
- # reading, unchanged) ; a TARGETED one applies when its `target`
50
+ # to `head_as`'s own aggregate: an untargeted option applies when
51
+ # `head_as` is the read model's one many-side head (the pre-`on:`
52
+ # reading, unchanged) ; a targeted one applies when its `target`
53
53
  # resolves to `head_as`'s own aggregate.
54
54
  FilteredOptions = Struct.new(:wheres, :order_by, :limit, :offset, :null_semantics)
55
55
 
@@ -1,7 +1,7 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # THE BEHAVIOUR MORE THAN ONE CONSTRUCT SHARES.
4
+ # The behaviour more than one construct shares.
5
5
  #
6
6
  # None of this is new duplication. `attribute(named)` was written
7
7
  # out four separate times — on Aggregate, Entity, Command and
@@ -11,20 +11,20 @@ module Hecks
11
11
  # files reads as four methods, and the same method in four modules
12
12
  # named `Behaviour::*` reads as one repeated.
13
13
  #
14
- # Written to work whether the construct is INCLUDED into (an
15
- # ordinary object like Aggregate) or EXTENDED into (a class-shaped
14
+ # Written to work whether the construct is included into (an
15
+ # ordinary object like Aggregate) or extended into (a class-shaped
16
16
  # one like Command), because every one of them reads instance
17
17
  # variables and nothing else.
18
18
 
19
- # A CONSTRUCT WHOSE IDENTITY IS A JOIN OF DECLARED PATHS.
19
+ # A construct whose identity is a join of declared paths.
20
20
  #
21
- # THE PATHS, IN DECLARATION ORDER, because the identity IS their join.
21
+ # The paths, in declaration order, because the identity is their join.
22
22
  # "number.value" says which field carries the identity ; several paths
23
23
  # say the identity is made of several facts, which is what anything
24
24
  # named beneath another thing needs. `identity_heads` are the attributes
25
25
  # those paths start at — what every reader that looks up or coerces an
26
26
  # attribute actually wants — and `identified_by` is the single head,
27
- # offered ONLY when there is one path to have a head of. A composite has
27
+ # offered only when there is one path to have a head of. A composite has
28
28
  # no single head, and answering with the first would be a guess ; the
29
29
  # readers that need all of them ask for `identity_heads`.
30
30
  module Identified
@@ -35,7 +35,7 @@ module Hecks
35
35
  end
36
36
  end
37
37
 
38
- # A CONSTRUCT THAT ANSWERS FOR ITS OWN DECLARATIONS BY NAME.
38
+ # A construct that answers for its own declarations by name.
39
39
  #
40
40
  # Indexed once, since the declarations are final by the time the
41
41
  # construct exists — every dispatch asks these finders by name, and a
@@ -43,19 +43,19 @@ module Hecks
43
43
  # had already settled at boot.
44
44
  #
45
45
  # `index_by_name` takes the collections to index rather than naming
46
- # them, because WHICH collections a construct has is exactly the part
46
+ # them, because which collections a construct has is exactly the part
47
47
  # that differs: an aggregate has five, an entity three, a command one.
48
48
  module Indexed
49
- # Keyed by SYMBOL — an attribute is asked for by its declared
49
+ # Keyed by symbol — an attribute is asked for by its declared
50
50
  # symbol name everywhere in the runtime.
51
51
  def index_attributes(attributes)
52
52
  @attributes_by_name = attributes.to_h { |held| [held.name, held] }
53
53
  end
54
54
 
55
- # Keyed by STRING and by `hecks_name` — a command, query or value
55
+ # Keyed by string and by `hecks_name` — a command, query or value
56
56
  # object is a construct whose Ruby `name` is something else
57
57
  # entirely (a constant path, or nothing at all for an anonymous
58
- # class), so the DECLARED name is the only one worth indexing.
58
+ # class), so the declared name is the only one worth indexing.
59
59
  def index_by_hecks_name(collection)
60
60
  collection.to_h { |held| [held.hecks_name, held] }
61
61
  end
@@ -65,7 +65,7 @@ module Hecks
65
65
  def query(named) = @queries_by_name[named.to_s]
66
66
  end
67
67
 
68
- # A CONSTRUCT THAT OWNS WHAT IT DECLARES.
68
+ # A construct that owns what it declares.
69
69
  #
70
70
  # Owner links are only ever read lazily — hecks_fqn at ask time,
71
71
  # Reference#resolve at dispatch time — so the moment the construct
@@ -1,29 +1,29 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module Behaviour
4
- # WHAT A VALUE OBJECT DOES. EXTENDED, not included — a value object
5
- # is a CLASS (`Class.new(self)`, one per declared shape), so its
4
+ # **What a value object does**. Extended, not included — a value object
5
+ # is a class (`Class.new(self)`, one per declared shape), so its
6
6
  # behaviour is singleton behaviour, and the holding half's `absorb`
7
7
  # is what a generated constructor would be.
8
8
  module ValueObject
9
- # A one_of DECLARED but left empty used to be indistinguishable from no
9
+ # A one_of declared but left empty used to be indistinguishable from no
10
10
  # one_of at all — both are `members: []` — so the rule about it could
11
11
  # only live in the builder. Recording the declaration lets the language
12
- # judge it, the same way an empty attribute NAME survives into the IR
12
+ # judge it, the same way an empty attribute name survives into the IR
13
13
  # and is judged there.
14
14
  def closed_set? = @closed_set
15
15
 
16
16
  def attribute(named) = attributes.find { |held| held.name == named.to_sym }
17
17
 
18
18
  # A single-attribute value object (EmailAddress{address},
19
- # CustomerNumber{value}) is a NAME for a scalar, not a genuine
19
+ # CustomerNumber{value}) is a name for a scalar, not a genuine
20
20
  # group — [[feedback_name_the_scalar_field]]. `adapters/driven/
21
21
  # sql_query_builder.rb` and `fuzzing/invalid_value_generator.rb`
22
22
  # now read through this rather than inlining the check.
23
23
  #
24
24
  # `forms/field_shape.rb`'s own two `attributes.first.name` sites
25
25
  # (`closed_set_options`/`closed_set_field`) look identical but are
26
- # NOT the same question — they pick a closed set's DISCRIMINANT
26
+ # not the same question — they pick a closed set's discriminant
27
27
  # column, and a closed set can be genuinely multi-attribute
28
28
  # (`Runtime::Value::Admission#member_matches?`'s own comment
29
29
  # names a real one: `StatementFrequency`'s `cadence`/