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
@@ -6,31 +6,31 @@ module Hecks
6
6
  # This used to be one hand-written branch per category, and the cost of that
7
7
  # shape was fourteen verbs the language declared and the judge never offered
8
8
  # — among them `Command.Argument` and `ValueObject.Field`, so a command's own
9
- # arguments and a value object's own fields were NEVER judged. Every rule
9
+ # arguments and a value object's own fields were never judged. Every rule
10
10
  # hanging off them was decoration. Nothing went red, because a branch that
11
11
  # does not exist cannot fail.
12
12
  #
13
- # So there are no branches. The judge WALKS: it reads the plan the language
13
+ # So there are no branches. The judge walks: it reads the plan the language
14
14
  # makes of itself (Plan), and for each node offers the creating command, then
15
15
  # each list through the command that appends to it, then each child. A verb
16
16
  # in the plan with no offer is now impossible — there is no branch left in
17
17
  # which to forget one, and spec/judge_coverage_spec holds it to that.
18
18
  #
19
- # What is NOT uniform lives in Readings, and only where the IR's SHAPE
19
+ # What is not uniform lives in Readings, and only where the IR's shape
20
20
  # differs from the language's. Naming differences do not appear at all: the
21
21
  # language spells its fields as the IR spells them.
22
22
  #
23
- # Only the DISPATCH half of the round trip lives here. Reconstruction is the
23
+ # Only the dispatch half of the round trip lives here. Reconstruction is the
24
24
  # experiment's business ; judging does not need it.
25
25
  class Judge
26
26
  include Readings
27
27
 
28
- # Children offered BEFORE the parent's own lists, IN THIS ORDER. An
28
+ # Children offered before the parent's own lists, in this order. An
29
29
  # attribute's type is offered as the id of the thing it names, so the
30
30
  # value objects have to exist before anything that can name one — an
31
- # aggregate's own attributes, AND an entity's own (M13: an entity is its
31
+ # aggregate's own attributes, and an entity's own (M13: an entity is its
32
32
  # own root, repeating the aggregate's whole shape one level down, so its
33
- # attributes resolve against the SAME value-object pool). ValueObject
33
+ # attributes resolve against the same value-object pool). ValueObject
34
34
  # first, Entity second, so an entity's own attributes are never offered
35
35
  # before the value objects they may reference exist — a self-hosting
36
36
  # casualty found live: the meta-grammar's own Handler/Dispatch/Member/
@@ -43,7 +43,7 @@ module Hecks
43
43
  # see `detail_node`'s own use of this constant, below.
44
44
  EAGER_CHILDREN = { "Aggregate" => %w[ValueObject Entity] }.freeze
45
45
 
46
- # Categories an ENTITY declares as well as an aggregate. The IR reuses
46
+ # Categories an entity declares as well as an aggregate. The IR reuses
47
47
  # Command and Query for a piece's own commands and queries, so the
48
48
  # language reuses Command and Query — and the plan cannot express a second
49
49
  # parent, because a category's parent is derived from the one `*_id` argument
@@ -52,9 +52,9 @@ module Hecks
52
52
 
53
53
  attr_reader :refusals
54
54
 
55
- # THE RECORDS SURVIVE THE VERDICT.
55
+ # **The records survive the verdict**.
56
56
  #
57
- # Judging a bluebook and HOLDING one differ by exactly this: whether anyone
57
+ # Judging a bluebook and holding one differ by exactly this: whether anyone
58
58
  # keeps the runtime the declarations were dispatched into. Nobody did, so
59
59
  # `spec/round_trip_spec` reached the records by `Judge.allocate` and four
60
60
  # `instance_variable_set` calls. Reading the chapter back is the point now,
@@ -71,7 +71,7 @@ module Hecks
71
71
 
72
72
  private
73
73
 
74
- # ABSENT is not EMPTY. The rules read "if you declare it, declare
74
+ # Absent is not empty. The rules read "if you declare it, declare
75
75
  # something" — a description never given is legal. Passing "" for a nil
76
76
  # turns every one of them into "you must declare it".
77
77
  #
@@ -85,7 +85,7 @@ module Hecks
85
85
  { value: text.to_s }
86
86
  end
87
87
 
88
- # A REFERENCE IS AN ID, AND AN ID IS A SCALAR.
88
+ # A reference is an ID, and an ID is a scalar.
89
89
  #
90
90
  # Every other field goes to the meta-domain as a one-field value object,
91
91
  # because that is what it is. A reference is not: it carries the id of a
@@ -105,16 +105,52 @@ module Hecks
105
105
  yield
106
106
  rescue Runtime::GivenNotMet, Runtime::InvariantViolation,
107
107
  Runtime::TypeMismatch, Runtime::NotFound => e
108
- # NotFound is a VERDICT, not noise. An attribute's type is a reference to
109
- # its value object, so "no ValueObject with id …" IS the rule `attributes
108
+ # NotFound is a verdict, not noise. An attribute's type is a reference to
109
+ # its value object, so "no ValueObject with id …" is the rule `attributes
110
110
  # must use value-object types` refusing.
111
111
  @refusals << "#{label}: #{e.message}"
112
112
  rescue Runtime::UnknownVerb
113
113
  nil
114
114
  end
115
115
 
116
+ # QualityControl BUG#125 — every dispatch the judge makes into the
117
+ # meta-domain goes through here, and only here, so this is the one
118
+ # place `Runtime::Value.judge_bootstrapping` needs to wrap: it tells
119
+ # `Value::Coercion#check_scalar_shapes` this construction is the
120
+ # language's own self-hosted grammar walk, not a real domain's
121
+ # command, so a String-typed meta-grammar field (`Normalise`'s
122
+ # `position`, a `RuleText` — `appends`' generic walk-index handling
123
+ # collides with that field's own name, see the flag's own comment
124
+ # in coercion.rb) may still arrive as the raw Integer `appends`
125
+ # hands it. Scoped to exactly this method: nothing outside a judge's
126
+ # own dispatch ever runs inside it, so an ordinary domain command
127
+ # (a real caller's own PieceId, Money, …) is never affected.
116
128
  def send_to(verb, label, to: nil, **payload)
117
- offer(label) { @runtime.dispatch(verb, to: to, with: args(payload)) }
129
+ Runtime::Value.judge_bootstrapping do
130
+ offer(label) { @runtime.dispatch(verb, to: to, with: args(payload)) }
131
+ end
132
+ end
133
+
134
+ # The receiver, spelled the way a real caller addresses it.
135
+ #
136
+ # `receiver` is an internal accumulator — it tracks the aggregate this
137
+ # walk is inside and, once it crosses into a real entity-owned category
138
+ # (Member/Handler/Dispatch — S17, ADR 0026), every entity hop on top of
139
+ # it. But `Routing.envelope`/`parse_envelope_hash` do not want that
140
+ # shape restated when there is no entity to route to: a plain aggregate
141
+ # command is addressed by its bare id (`Facade::Handle#dispatch` — "to:
142
+ # @id" — and `CommandRequest`'s own header: "aggregate command: { to:
143
+ # "record-id", ... }"), never `{aggregate:, entities: []}` — that hash
144
+ # is the entity route's own shape, degenerate with nothing in it.
145
+ #
146
+ # So this is the one place `receiver` turns into a `to:` value: bare
147
+ # when there is no entity hop (the overwhelming common case — every
148
+ # category but those three), the full envelope only when there
149
+ # genuinely is one.
150
+ def address(receiver)
151
+ return receiver[:aggregate] if receiver[:entities].empty?
152
+
153
+ receiver
118
154
  end
119
155
 
120
156
  def judge!
@@ -122,19 +158,19 @@ module Hecks
122
158
  detail_node("Bluebook", @bluebook, nil, 0)
123
159
  end
124
160
 
125
- # DECLARED BEFORE DETAILED, for every set of siblings.
161
+ # Declared before detailed, for every set of siblings.
126
162
  #
127
163
  # A node used to be offered whole — declared, then its lists, then its
128
164
  # children — one sibling at a time. Which means an aggregate's attributes
129
165
  # were offered before its later siblings existed, and an attribute that
130
- # POINTS AT another aggregate could only resolve if that aggregate happened
166
+ # points at another aggregate could only resolve if that aggregate happened
131
167
  # to be declared earlier in the file. Banking survives on luck: Customer is
132
168
  # written above Account.
133
169
  #
134
170
  # So siblings are declared in one pass and detailed in a second. It is the
135
171
  # same ordering the walk already used one level down — value objects before
136
172
  # the attributes that name them — lifted to the level above, and it is what
137
- # lets a reference be a REFERENCE rather than a string nobody can check.
173
+ # lets a reference be a reference rather than a string nobody can check.
138
174
  def declare_node(category, node, parent_id, index, extra = {}, receiver: nil)
139
175
  plan = @plan.category(category)
140
176
  return unless plan
@@ -147,34 +183,34 @@ module Hecks
147
183
  return unless plan
148
184
 
149
185
  id = identify(category, parent_id, node, index)
150
- # `extra` is the CUMULATIVE identity of every entity-owned
151
- # ancestor above this node (Handler's own `event_type` AND
186
+ # `extra` is the cumulative identity of every entity-owned
187
+ # ancestor above this node (Handler's own `event_type` and
152
188
  # ProcessManager's own `bluebook`/`name`, by the time Dispatch
153
189
  # is reached — S17, ADR 0026's two-level chain). `identity`
154
- # adds THIS node's own on top — computed for EVERY category,
190
+ # adds this node's own on top — computed for every category,
155
191
  # entity-owned or not, because a node need not be entity-owned
156
- # itself to OWN one (ValueObject isn't, and Member still needs
157
- # its `aggregate:`/`name:`) — it is simply what THIS node's own
192
+ # itself to own one (ValueObject isn't, and Member still needs
193
+ # its `aggregate:`/`name:`) — it is simply what this node's own
158
194
  # `identified_by` resolves to, the same fields `identify` two
159
- # lines up already derives the joined id FROM.
195
+ # lines up already derives the joined id from.
160
196
  #
161
- # `own` is the SUBSET actually spent on a dispatch payload —
162
- # only when THIS category is itself entity-owned, since an
197
+ # `own` is the subset actually spent on a dispatch payload —
198
+ # only when this category is itself entity-owned, since an
163
199
  # ordinary category (Command's own "Rule"/"Argument", offered
164
- # through the SAME `extra` SLOT for a DIFFERENT reason, see
200
+ # through the same `extra` slot for a different reason, see
165
201
  # `within_entity` below) locates the record it attaches to
166
202
  # through the parent id `id:` already carries, and merging
167
- # unrecognized `aggregate:`/`entity_id:` into THEIR payload
203
+ # unrecognized `aggregate:`/`entity_id:` into their payload
168
204
  # would have the runtime refuse them for an argument they
169
205
  # never declared.
170
206
  identity = extra.merge(node_identity(plan, category, node, index, parent_id))
171
207
  receiver ||= { aggregate: id, entities: [] }
172
208
  eager, later = children_of(category).partition { |child| eager?(category, child) }
173
- # ORDERED AS `EAGER_CHILDREN` DECLARES, not as `children_of` happens to
209
+ # Ordered as `EAGER_CHILDREN` declares, not as `children_of` happens to
174
210
  # list them — `children_of` reads `@plan.names`, whose own order is an
175
211
  # accident of which .bluebook file registered which category first,
176
212
  # never a promise about which of two eager children exists before the
177
- # other. `EAGER_CHILDREN`'s own array IS that promise (ValueObject
213
+ # other. `EAGER_CHILDREN`'s own array is that promise (ValueObject
178
214
  # before Entity), so the walk keeps only what this parent actually
179
215
  # has, in the order the constant states — see that constant's own
180
216
  # comment for the bug this exact reordering fixes.
@@ -182,12 +218,12 @@ module Hecks
182
218
 
183
219
  eager.each { |child| walk_all(child, node, id, entity_child_extra(child, identity), receiver: receiver) }
184
220
  setters(plan, category, node, receiver)
185
- # BEFORE `appends`, not after — the same reason `EAGER_CHILDREN`
186
- # walks an aggregate's OWN entities before its OWN attributes
221
+ # Before `appends`, not after — the same reason `EAGER_CHILDREN`
222
+ # walks an aggregate's own entities before its own attributes
187
223
  # (M13): a piece nested inside a piece (Handler's own
188
224
  # `dispatches, list_of(Dispatch)` — S17, ADR 0026) must exist
189
225
  # before this piece's own attribute list can reference it as a
190
- # HELD entity, the same way `Account#ledger` needs Account's own
226
+ # held entity, the same way `Account#ledger` needs Account's own
191
227
  # entities walked eagerly. `nest_entities` is a no-op for every
192
228
  # category but "Entity" (its own early return), so reordering it
193
229
  # ahead of `appends` costs nothing for anything else that walks
@@ -199,11 +235,11 @@ module Hecks
199
235
  sealers(plan, category, receiver)
200
236
  end
201
237
 
202
- # WHAT A CHILD'S OWN `extra` STARTS FROM. An entity-owned child's
203
- # own dotted dispatch needs every ANCESTOR's identity, which is
238
+ # What a child's own `extra` starts from. An entity-owned child's
239
+ # own dotted dispatch needs every ancestor's identity, which is
204
240
  # exactly `identity` — already accumulated one level at a time by
205
241
  # `detail_node` itself (regardless of whether each ancestor is
206
- # ITSELF entity-owned — ValueObject contributes its own `aggregate:
242
+ # itself entity-owned — ValueObject contributes its own `aggregate:
207
243
  # `/`name:` to Member's payload despite being an ordinary top-
208
244
  # level category), so there is nothing left to re-derive here. An
209
245
  # ordinary child (one with a real top-level aggregate of its own
@@ -212,15 +248,15 @@ module Hecks
212
248
  @plan.category(child)&.entity_owned ? identity : {}
213
249
  end
214
250
 
215
- # ONE NODE'S OWN IDENTITY, read off its own declaration — S17,
251
+ # One node's own identity, read off its own declaration — S17,
216
252
  # ADR 0026. Three cases, the same three `identify`/`identity_part`
217
253
  # already resolve one level up, unified here because a chain now
218
254
  # walks more than one level (Handler -> Dispatch) and each level
219
- # needs the SAME three answered about itself, not just the first:
255
+ # needs the same three answered about itself, not just the first:
220
256
  #
221
257
  # the parent link (plan.parent_key) -> `parent_id`, the id
222
258
  # the walk already carries in from one level up
223
- # a walk-minted one (POSITION) -> the walk INDEX itself ;
259
+ # a walk-minted one (POSITION) -> the walk index itself ;
224
260
  # never a stored field (Member's own header:
225
261
  # "position is not a mint — it is read straight
226
262
  # out of the source file")
@@ -249,9 +285,9 @@ module Hecks
249
285
  end
250
286
  end
251
287
 
252
- # THE FULL DOTTED PREFIX a category's own verbs hang off — the
288
+ # The full dotted prefix a category's own verbs hang off — the
253
289
  # plain name for an ordinary category (its own top-level
254
- # aggregate reaches every verb bare), or its PARENT's own prefix
290
+ # aggregate reaches every verb bare), or its parent's own prefix
255
291
  # with this category's name appended, for an entity-owned one.
256
292
  # Dispatch's own parent, Handler, is itself entity-owned (S17,
257
293
  # ADR 0026's two-level chain — `ProcessManager.Handler.Dispatch`),
@@ -262,9 +298,9 @@ module Hecks
262
298
  "#{dotted_prefix(@plan.category(plan.parent))}.#{plan.name}"
263
299
  end
264
300
 
265
- # ENTITY-OWNED categories have no top-level aggregate for the runtime
301
+ # Entity-owned categories have no top-level aggregate for the runtime
266
302
  # to route a bare verb into any more — `Member`'s own "Pair" reaches
267
- # the runtime as `ValueObject.Member.Pair`, and a NESTED one
303
+ # the runtime as `ValueObject.Member.Pair`, and a nested one
268
304
  # (`Dispatch`, inside `Handler`) reaches it as `ProcessManager.
269
305
  # Handler.Dispatch.Bind` — the dotted shape `EntityInterpreter#call`
270
306
  # already splits any real entity's own verb into, one hop per
@@ -290,12 +326,12 @@ module Hecks
290
326
  end
291
327
  end
292
328
 
293
- # A piece's commands and queries, addressed under the PIECE so two commands
329
+ # A piece's commands and queries, addressed under the piece so two commands
294
330
  # of the same name on an aggregate and on one of its entities cannot collide,
295
331
  # while `aggregate` still names the aggregate the reference resolves
296
332
  # against and `entity_id` says which piece declared it. `entity_id`
297
- # keeps its own `_id` — an EXPLICIT `as:` on `reference_to Entity`,
298
- # never touched by ADR 0025's rename (only the DEFAULT, un-aliased
333
+ # keeps its own `_id` — an explicit `as:` on `reference_to Entity`,
334
+ # never touched by ADR 0025's rename (only the default, un-aliased
299
335
  # mint dropped the suffix; `aggregate` did precisely because
300
336
  # `Command#reference_to Aggregate`/`Query#reference_to Aggregate`
301
337
  # carry no `as:` of their own).
@@ -311,26 +347,26 @@ module Hecks
311
347
  end
312
348
  end
313
349
 
314
- # AN ENTITY MAY NEST FURTHER ENTITIES — S17, ADR 0026's own words:
350
+ # An entity may nest further entities — S17, ADR 0026's own words:
315
351
  # "That is what `entity` is for, and `entity` is declared by the
316
352
  # language and used zero times in it." `Dispatch`, inside
317
- # `Handler`, is the first real use. The GENERIC "Entity" category
353
+ # `Handler`, is the first real use. The generic "Entity" category
318
354
  # cannot express this through `children_of`/`EAGER_CHILDREN` the
319
355
  # way Aggregate's own entities/value_objects can — there is only
320
- # ONE "Entity" Plan category, describing what ANY entity looks
356
+ # one "Entity" Plan category, describing what any entity looks
321
357
  # like, not one per nesting level — so this recurses by hand,
322
358
  # the same special case `within_entity` (above) already is for
323
359
  # Command/Query.
324
360
  #
325
361
  # `owner` is the field this repurposes — `entity.bluebook`
326
362
  # declares it (`attribute :owner, EntityText`) and it has held
327
- # exactly one value since ADR 0025's rename: the SAME id
328
- # `aggregate` already carries, kept as a wrapped-text COPY,
363
+ # exactly one value since ADR 0025's rename: the same id
364
+ # `aggregate` already carries, kept as a wrapped-text copy,
329
365
  # never read back anywhere else in this codebase (grep finds no
330
- # second reference). For a NESTED entity, the two finally
331
- # diverge — `aggregate` stays the ROOT (Dispatch resolves
366
+ # second reference). For a nested entity, the two finally
367
+ # diverge — `aggregate` stays the root (Dispatch resolves
332
368
  # exactly the way any other Entity record does, by its root
333
- # aggregate), and `owner` becomes THIS entity's own DIRECT
369
+ # aggregate), and `owner` becomes this entity's own direct
334
370
  # parent (Handler, not ProcessManager) — which is exactly the
335
371
  # fact `Reconstruction#direct_entities` needs to tell a
336
372
  # root-level entity apart from a nested one sharing the same
@@ -345,13 +381,13 @@ module Hecks
345
381
  })
346
382
  end
347
383
 
348
- # WHERE IT SITS AMONG ITS SIBLINGS IS A FACT ABOUT THE WALK, not about the
384
+ # Where it sits among its siblings is a fact about the walk, not about the
349
385
  # node : a command does not know it is the third command on its aggregate.
350
386
  # The walk knows, so the walk supplies it, and every other field still
351
387
  # comes from the node. Declaration order used to survive only because the
352
388
  # meta store happened to iterate in insertion order — an accident that an
353
389
  # ask ordered any other way would have taken away, and Reconstruction is
354
- # the one reader that must have the SOURCE'S order rather than a stable one.
390
+ # the one reader that must have the source's order rather than a stable one.
355
391
  # `private` above has no effect on a constant; kept here anyway,
356
392
  # beside the method that reads it, for the narrative.
357
393
  # rubocop:disable-next Lint/UselessConstantScoping
@@ -384,7 +420,7 @@ module Hecks
384
420
  end
385
421
  next if payload.values.all?(&:nil?)
386
422
 
387
- send_to("Bluebook::#{verb_for(plan, setter.verb)}", receiver[:aggregate], to: receiver, **payload)
423
+ send_to("Bluebook::#{verb_for(plan, setter.verb)}", receiver[:aggregate], to: address(receiver), **payload)
388
424
  end
389
425
  end
390
426
 
@@ -394,7 +430,7 @@ module Hecks
394
430
  plan.appends.each do |list_name, append|
395
431
  rows_for(category, list_name, node).each_with_index do |row, index|
396
432
  chosen = append_for(category, list_name, append, row, node)
397
- # `position` IS THE WALK INDEX here exactly as it is in `declare` —
433
+ # `position` is the walk index here exactly as it is in `declare` —
398
434
  # an appended element that names its position (ValueObject.Member,
399
435
  # S17) is ordered by where the walk found it, never by a field the
400
436
  # row happens to hold.
@@ -409,20 +445,20 @@ module Hecks
409
445
  end
410
446
 
411
447
  send_to("Bluebook::#{verb_for(plan, chosen.verb)}", "#{id}##{list_name}[#{index}]",
412
- to: receiver, **payload)
448
+ to: address(receiver), **payload)
413
449
  end
414
450
  end
415
451
  end
416
452
 
417
- # WHICH AGGREGATE OWNS THE VALUE OBJECTS an attribute's TYPE may
453
+ # Which aggregate owns the value objects an attribute's type may
418
454
  # resolve against. An aggregate owns its own — `id` already names
419
455
  # it. An entity never has value objects of its own (Entity
420
456
  # deliberately never answers `value_object` — see entity.rb's own
421
- # comment on why); its attributes read the SAME pool its
457
+ # comment on why); its attributes read the same pool its
422
458
  # enclosing aggregate declares, one level up the construct tree
423
459
  # no matter how many entities deep this attribute is nested —
424
460
  # `parent_id` names it because `detail_node`/`nest_entities`
425
- # thread the ROOT aggregate's id down as `parent_id` at every
461
+ # thread the root aggregate's id down as `parent_id` at every
426
462
  # entity level, never the direct (possibly entity) parent.
427
463
  def owning_aggregate_ref(category, id, parent_id)
428
464
  category == "Entity" ? parent_id : id
@@ -430,33 +466,33 @@ module Hecks
430
466
 
431
467
  def sealers(plan, _category, receiver)
432
468
  id = receiver[:entities].last || receiver[:aggregate]
433
- plan.sealers.each { |verb| send_to("Bluebook::#{verb_for(plan, verb)}", id, to: receiver) }
469
+ plan.sealers.each { |verb| send_to("Bluebook::#{verb_for(plan, verb)}", id, to: address(receiver)) }
434
470
  end
435
471
 
436
- # An aggregate's or an entity's attribute names its value object by TYPE,
472
+ # An aggregate's or an entity's attribute names its value object by type,
437
473
  # and the language models that as a reference — so the type is offered as
438
474
  # the value object's own id. This is the rule "attributes must use
439
475
  # value-object types", enforced by reference resolution rather than by a
440
- # predicate — for a HEAD's own attributes, aggregate or entity alike: an
476
+ # predicate — for a head's own attributes, aggregate or entity alike: an
441
477
  # entity is its own root, repeating the aggregate's whole shape one level
442
478
  # down (entity.rb's own words), and an undeclared type on an entity's
443
479
  # attribute must fail the same reference resolution an aggregate's own
444
480
  # does, not go unchecked because only "Aggregate.attributes" was ever
445
481
  # asked.
446
- # An attribute's type is offered as the ID OF THE THING IT NAMES, so the
482
+ # An attribute's type is offered as the ID of the thing it names, so the
447
483
  # language resolves it as a reference and "the type is declared" costs no
448
484
  # predicate. Three kinds, three ids: a value object and an entity both hang
449
485
  # off this aggregate, so they share its prefix; another aggregate's head
450
486
  # hangs off the chapter.
451
487
  def cell(category, list_name, row, field, id, append, aggregate_id)
452
488
  value = row_value(row, field)
453
- # A default keeps its TYPE by being written as a literal — 0.0 rather than
489
+ # A default keeps its type by being written as a literal — 0.0 rather than
454
490
  # "0.0" — because the language holds it as text and text alone forgets.
455
491
  return encode_literal(value) if field == :default
456
492
  return value unless field == :type
457
- # A REFERENCE names another head WHEREVER it is written — on a head, on
493
+ # A reference names another head wherever it is written — on a head, on
458
494
  # a command, on a piece, on an ask — so it is offered as that head's
459
- # id in all four. Only a HEAD's own attributes additionally qualify
495
+ # id in all four. Only a head's own attributes additionally qualify
460
496
  # an ordinary type into a value object's id ; a command argument's
461
497
  # type is text and stays text.
462
498
  return points_at(row, id) if append.verb == "Reference"
@@ -465,7 +501,7 @@ module Hecks
465
501
  Naming.identity([owning_aggregate_id(aggregate_id, value), value])
466
502
  end
467
503
 
468
- # A HEAD'S OWN ATTRIBUTES — an aggregate's, or an entity's (its own root,
504
+ # A head's own attributes — an aggregate's, or an entity's (its own root,
469
505
  # one level down). Every other "attributes" list belongs to something that
470
506
  # is not a head at all (a command's arguments, a value object's own
471
507
  # fields), and a type written there is a name, not a reference — the same
@@ -474,27 +510,27 @@ module Hecks
474
510
  list_name.to_s == "attributes" && %w[Aggregate Entity].include?(category)
475
511
  end
476
512
 
477
- # `id` NAMES THE ATTRIBUTE'S OWN AGGREGATE, not necessarily the
513
+ # `id` names the attribute's own aggregate, not necessarily the
478
514
  # value object's — Wave 7's own translation.bluebook/translation_
479
515
  # aggregate.bluebook split proved the difference live:
480
516
  # TranslationAggregate's own `was`/every rename-rule's own `from`/
481
- # `to`/... all deliberately reuse the SIBLING "Translation"
517
+ # `to`/... all deliberately reuse the sibling "Translation"
482
518
  # aggregate's own `TranslationName` (that file's own header:
483
519
  # "the shared TranslationName every non-identity field below
484
520
  # uses"), a real, intentional cross-aggregate reuse — not the
485
- # local-only ownership every OTHER real domain in this corpus
521
+ # local-only ownership every other real domain in this corpus
486
522
  # happens to have used until now.
487
523
  #
488
524
  # `id` (already `Naming.identity([chapter, aggregate])`-joined)
489
- # only ever composes with the LOCAL aggregate for real, non-
525
+ # only ever composes with the local aggregate for real, non-
490
526
  # entity-owned attributes — an entity's own `id` never matches
491
- # any TOP-LEVEL aggregate here, so `local` stays nil and this
527
+ # any top-level aggregate here, so `local` stays nil and this
492
528
  # returns `id` unchanged, exactly the prior behavior. Same for
493
- # every attribute whose type IS locally declared (the overwhelming
529
+ # every attribute whose type is locally declared (the overwhelming
494
530
  # common case, Banking's own Customer/Account included) — this
495
- # only ever changes the answer when the local aggregate does NOT
531
+ # only ever changes the answer when the local aggregate does not
496
532
  # declare `value` itself, falling back to the first (declaration-
497
- # order) OTHER aggregate in the SAME chapter that does.
533
+ # order) other aggregate in the same chapter that does.
498
534
  def owning_aggregate_id(id, value)
499
535
  local = @bluebook.aggregates.find { |aggregate| Naming.identity([@bluebook.name, aggregate.name]) == id }
500
536
  return id unless local
@@ -527,13 +563,13 @@ module Hecks
527
563
  # Reference its type is Reference<X>, another aggregate's head
528
564
  # Holds its type names an entity this aggregate declares
529
565
  #
530
- # NOTHING IS SKIPPED any more. Reference and Holds did not exist, so the
566
+ # Nothing is skipped any more. Reference and Holds did not exist, so the
531
567
  # walk dropped both kinds and the meta-domain silently did not contain
532
568
  # Account#customer_id or Account#ledger.
533
- # Each alternate carries its OWN map, read from the language. Borrowing the
569
+ # Each alternate carries its own map, read from the language. Borrowing the
534
570
  # primary's map dispatched `type:` where Reference declares `points_at:`,
535
571
  # and the payload gate caught it — which is the gate paying for itself.
536
- # `reference_to` can be written in FOUR places — on a head, a command, a
572
+ # `reference_to` can be written in four places — on a head, a command, a
537
573
  # piece, an ask — and each keeps its own list of attributes, so each
538
574
  # needs the Reference alternate. Only a head can hold a piece, so Holds
539
575
  # stays where it was.
@@ -551,7 +587,7 @@ module Hecks
551
587
 
552
588
  def reference_row?(row) = row.respond_to?(:reference?) && row.reference?
553
589
 
554
- # Only a HEAD declares pieces, and now that every attribute list reaches
590
+ # Only a head declares pieces, and now that every attribute list reaches
555
591
  # this, the node may be a command, a piece or an ask — none of which
556
592
  # answer `entities` at all.
557
593
  def entity_row?(row, node)
@@ -560,7 +596,7 @@ module Hecks
560
596
  Array(node.entities).any? { |entity| entity.hecks_name == row.type.to_s }
561
597
  end
562
598
 
563
- # A RECORD'S ID IS ITS DECLARED IDENTITY, JOINED — the same join the runtime
599
+ # A record's ID is its declared identity, joined — the same join the runtime
564
600
  # does, off the same declaration, because there is only one way to name a
565
601
  # thing and it should be written once.
566
602
  #
@@ -580,14 +616,14 @@ module Hecks
580
616
  Naming.identity(plan.identity_paths.map { |path| identity_part(plan, path, parent_id, node, index, category) })
581
617
  end
582
618
 
583
- # "owner_id" is a SECOND reserved head, beside `position` : it names
584
- # whichever record is walking THIS one right now, aggregate or entity
619
+ # "owner_id" is a second reserved head, beside `position` : it names
620
+ # whichever record is walking this one right now, aggregate or entity
585
621
  # alike, without saying which — Command and Query read it so an
586
622
  # entity's verbs are the entity's own. It is never a declared
587
623
  # attribute (declaring one for a field that names two different types
588
624
  # would be a lie about which), so it cannot be read through
589
625
  # `field_value` ; it is read the same way `plan.parent_key` already is,
590
- # because it IS that fact, spelled for the walk's immediate parent
626
+ # because it is that fact, spelled for the walk's immediate parent
591
627
  # rather than for one specific kind of one.
592
628
  # `private` above has no effect on a constant; kept here anyway,
593
629
  # beside the method that reads it, for the narrative.