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
@@ -8,7 +8,7 @@ module Hecks
8
8
  # (attributes, value objects, entities, commands, queries, policies,
9
9
  # invariants, preconditions, projected fields, its lifecycle and
10
10
  # identity) and assembling the final `Aggregate` IR in `#build`.
11
- # `entity`/`command`/`query` only QUEUE a descriptor during
11
+ # `entity`/`command`/`query` only queue a descriptor during
12
12
  # `instance_eval` (`#drain_pending!` builds them, in order, once the
13
13
  # whole block has run) so a later-declared piece can still be
14
14
  # referenced by an earlier line — see `#drain_pending!`'s own header.
@@ -34,23 +34,23 @@ module Hecks
34
34
  @queries = []
35
35
  @policies = []
36
36
  @reference_targets = []
37
- # THE ROOT of the cross-entity given pool — see `#entity`'s own
38
- # comment. ONE hash for the whole aggregate, threaded unchanged
37
+ # The root of the cross-entity given pool — see `#entity`'s own
38
+ # comment. One hash for the whole aggregate, threaded unchanged
39
39
  # into every piece nested under it, however deep.
40
40
  @entity_named_givens = {}
41
- # ONE LEVEL WIDER STILL — the CHAPTER's own pool, threaded in
42
- # from `BluebookBuilder#aggregate`, shared with every OTHER
41
+ # **One level wider still** — the chapter's own pool, threaded in
42
+ # from `BluebookBuilder#aggregate`, shared with every other
43
43
  # aggregate the same chapter builds. See `#given`'s own
44
44
  # comment for what this closes.
45
45
  @chapter_named_givens = chapter_named_givens
46
- # A CHAPTER MAY BE SPLIT ACROSS FILES — threaded in the SAME
46
+ # A chapter may be split across files — threaded in the same
47
47
  # way as `@chapter_named_givens`, one Array shared chapter-wide.
48
48
  # See `#pending_chapter_given`'s own comment for what queues
49
49
  # here and `BluebookBuilder#resolve_pending_chapter_givens!`
50
50
  # for where it drains.
51
51
  @chapter_pending_givens = chapter_pending_givens
52
- # ONE LEVEL WIDER STILL, PAST THE CHAPTER'S OWN AGGREGATE-LEVEL
53
- # POOL — the chapter's own entity-scoped pool, threaded from
52
+ # One level wider still, past the chapter's own aggregate-level
53
+ # pool — the chapter's own entity-scoped pool, threaded from
54
54
  # `BluebookBuilder#aggregate_impl` the same way
55
55
  # `@chapter_named_givens` is, and passed straight through
56
56
  # (unchanged) to every top-level piece this aggregate builds
@@ -58,7 +58,7 @@ module Hecks
58
58
  # comment for what this closes.
59
59
  @chapter_entity_named_givens = chapter_entity_named_givens
60
60
  @chapter_entity_pending_givens = chapter_entity_pending_givens
61
- # DEFERRED CONSTRUCTION — `entity`/`command`/`query` push a
61
+ # **Deferred construction** — `entity`/`command`/`query` push a
62
62
  # pending descriptor here instead of building immediately; see
63
63
  # `#drain_pending!`'s own comment for why.
64
64
  @pending_entities = []
@@ -72,13 +72,13 @@ module Hecks
72
72
  @description = value
73
73
  end
74
74
 
75
- # ORIGIN, not runtime identity — a concept adopted from a canonical
75
+ # Origin, not runtime identity — a concept adopted from a canonical
76
76
  # source (§28) names where it came from without that fact ever
77
77
  # touching `hecks_fqn`/dispatch. Captured raw, the same way
78
78
  # `attribute ..., default: { value: "small" }` captures a literal
79
79
  # Hash untouched — no re-parsing, no structure imposed beyond
80
80
  # "whatever the author wrote."
81
- # RENAMED FROM `provenance`/`projects`/`lifecycle`/`entity`/
81
+ # Renamed from `provenance`/`projects`/`lifecycle`/`entity`/
82
82
  # `query`/`policy`/`command` (all below) — item #13's full
83
83
  # metaprogrammed dispatch (slice 4c). All bootstrap-reachable
84
84
  # (used throughout the core/attached chapters), all in
@@ -92,15 +92,15 @@ module Hecks
92
92
  # forward it to `attribute_impl()`/`relationship_attribute`
93
93
  # even though those already accept it — closed in the same
94
94
  # commit that added this comment (`optional: optional`, below).
95
- # It was a real gap because an aggregate that can point at ONE
96
- # OF several targets (Item's own `personal_list_id`/
95
+ # It was a real gap because an aggregate that can point at one
96
+ # of several targets (Item's own `personal_list_id`/
97
97
  # `camping_list_id`, never both) needs each reference optional
98
98
  # on the aggregate's own persisted schema, not just as a
99
99
  # command's input — real corpus use:
100
100
  # `spec/fixtures/hop_chain.bluebook`'s own `Proposal` aggregate
101
101
  # declares `reference_to Engagement, optional: true` at the
102
102
  # aggregate head.
103
- # RENAMED FROM `reference_to` — item #13's full metaprogrammed
103
+ # Renamed from `reference_to` — item #13's full metaprogrammed
104
104
  # dispatch (slice 4b). Bootstrap-reachable (every core/attached
105
105
  # grammar chapter uses reference_to to describe itself), so also
106
106
  # named in GenericDispatch::BOOTSTRAP_CALLS_FALLBACK.
@@ -111,27 +111,27 @@ module Hecks
111
111
  as || default_reference_name(target), optional: optional)
112
112
  end
113
113
 
114
- # A RULE MAY ONLY READ WITHIN ITS OWN AGGREGATE BOUNDARY (S12,
114
+ # A rule may only read within its own aggregate boundary (S12,
115
115
  # ADR 0025 — "Consistency across aggregate boundaries"). A
116
116
  # `given`/`ensures`/`invariant` used to reach through a
117
- # `reference_to` at RULE-EVALUATION TIME (`References#
117
+ # `reference_to` at rule-evaluation time (`References#
118
118
  # dereference`, a live query against another aggregate's own
119
119
  # repository, unbounded and inconsistent with the "a rule reads
120
120
  # only this record" model everywhere else) — `projects` is what
121
121
  # replaces that: `projects :customer_status, from: :"customer.
122
- # status"` declares that THIS aggregate holds its own copy of
123
- # `Customer`'s own `:status`, kept fresh by a REBUILD SWEEP
122
+ # status"` declares that this aggregate holds its own copy of
123
+ # `Customer`'s own `:status`, kept fresh by a rebuild sweep
124
124
  # (`Runtime::ProjectionRebuild`) rather than read live. A rule
125
125
  # then reads `customer_status` the same way it reads any other
126
126
  # local field — no dot, no reference walk.
127
127
  #
128
- # `from:` NAMES THE LOCAL REFERENCE, not the target aggregate —
129
- # `customer`, the attribute THIS aggregate's own `reference_to
128
+ # `from:` names the local reference, not the target aggregate —
129
+ # `customer`, the attribute this aggregate's own `reference_to
130
130
  # Customer` already minted, not `Customer` the type — so two
131
131
  # references to the same aggregate (aliased differently) can
132
- # each carry their own projection without ambiguity. The TARGET
132
+ # each carry their own projection without ambiguity. The target
133
133
  # field's own existence cannot be checked here: the target
134
- # aggregate does not exist yet while THIS one is still being
134
+ # aggregate does not exist yet while this one is still being
135
135
  # declared (the same reason a query's own hop tail is checked
136
136
  # by `BluebookBuilder#validate_query_hops!`, once every
137
137
  # aggregate in the chapter is real, not by `AggregateBuilder`
@@ -151,9 +151,9 @@ module Hecks
151
151
  remote_field: remote_field.to_sym)
152
152
  end
153
153
 
154
- # `has_many`/`has_one`/`belongs_to` were LEGACY (ADR 0025,
154
+ # `has_many`/`has_one`/`belongs_to` were legacy (ADR 0025,
155
155
  # "References") — sugar over `reference_to` that collapsed to an
156
- # anonymous reference and, for `has_many`, LIED (singularised its
156
+ # anonymous reference and, for `has_many`, lied (singularised its
157
157
  # target and minted one scalar, so `film.backers` read `nil` and
158
158
  # never `[]`). Wave 6 (identity-and-relationships arc) un-deprecates
159
159
  # all three for real: a relationship word now retains the author's
@@ -161,11 +161,11 @@ module Hecks
161
161
  # identities, but no longer collapsed to a bare `reference_to`
162
162
  # during assembly. `MetaValidator.shadow_parsing?` still routes to
163
163
  # `legacy_has_many`/`legacy_has_one` so frozen era text written
164
- # under the OLD (lying/collapsing) meaning still parses the way it
164
+ # under the old (lying/collapsing) meaning still parses the way it
165
165
  # did when it was written — real, if rare corpus: "Combined corpus
166
166
  # uses: one."
167
167
  #
168
- # RENAMED FROM `has_many`/`has_one`/`belongs_to` — item #13's full
168
+ # Renamed from `has_many`/`has_one`/`belongs_to` — item #13's full
169
169
  # metaprogrammed dispatch (slice 4). Each Keyword row's own
170
170
  # `calls:` names the matching `_impl`; not bootstrap-reachable
171
171
  # (no core/attached chapter uses one of these to describe itself),
@@ -208,26 +208,26 @@ module Hecks
208
208
  @lifecycle = LifecycleBuilder.build(field, default: default, &)
209
209
  end
210
210
 
211
- # A piece is declared IN this aggregate — its owner is stamped by
211
+ # A piece is declared in this aggregate — its owner is stamped by
212
212
  # `Aggregate#initialize`, once the aggregate exists. Its own
213
213
  # commands were given the piece as their owner when it was declared,
214
214
  # so the chain closes as chapter -> aggregate -> entity -> command.
215
- # NOT built here — see `#drain_pending!`'s own comment for why
215
+ # Not built here — see `#drain_pending!`'s own comment for why
216
216
  # this only queues a descriptor.
217
217
  #
218
- # A PRECONDITION SHARED ACROSS SIBLING PIECES, DECLARED ONCE — one
218
+ # A precondition shared across sibling pieces, declared once — one
219
219
  # level wider than round 4's own `EntityBuilder#given` (shared
220
- # across ONE piece's own commands): `@entity_named_givens` is the
221
- # SAME hash threaded into EVERY piece this aggregate builds, so a
220
+ # across one piece's own commands): `@entity_named_givens` is the
221
+ # same hash threaded into every piece this aggregate builds, so a
222
222
  # piece's own entity-level `given(desc) { block }` write-throughs
223
- # into it, and any OTHER piece's own command can reference it back
224
- # bare, the identical description/canonical, evaluated in ITS OWN
223
+ # into it, and any other piece's own command can reference it back
224
+ # bare, the identical description/canonical, evaluated in its own
225
225
  # `parent`-relative context. Real, live corpus this closes:
226
- # `SafeDepositBox`'s `Visit`/`KeyIssuance` — two DIFFERENT pieces
226
+ # `SafeDepositBox`'s `Visit`/`KeyIssuance` — two different pieces
227
227
  # under one head, each independently typing `given("customer is
228
228
  # active") { parent.customer.status == "active" }` byte for byte,
229
- # which neither the aggregate's OWN "customer is active" (a
230
- # DIFFERENT canonical — bare `customer.status`, not
229
+ # which neither the aggregate's own "customer is active" (a
230
+ # different canonical — bare `customer.status`, not
231
231
  # `parent.customer.status`, wrong scope for a piece's own command
232
232
  # to evaluate) nor round 4's single-piece `given` could reach.
233
233
  def entity_impl(name, &block)
@@ -244,38 +244,38 @@ module Hecks
244
244
  @policies << reaction
245
245
  end
246
246
 
247
- # `builder.closed_sets` TOO, not only `builder.build` — a REAL,
247
+ # `builder.closed_sets` too, not only `builder.build` — a real,
248
248
  # previously-unreachable gap this exact fix exposed: a
249
- # value_object's own INLINE `attribute :x, one_of(...)` (now legal
249
+ # value_object's own inline `attribute :x, one_of(...)` (now legal
250
250
  # — S3, ADR 0025 removed the wrong-arity collision that used to
251
251
  # make this crash before it could ever matter) synthesises its own
252
- # anonymous value object via the SAME `AttributeCollector#closed_
252
+ # anonymous value object via the same `AttributeCollector#closed_
253
253
  # sets` mechanism an aggregate's own attributes already use — and
254
254
  # nothing installed it anywhere. `Box.attributes` said `size:
255
255
  # "Size"` while no "Size" value object existed in the whole
256
256
  # domain: a dangling type name, not a working closed set. Flattened
257
- # into THIS aggregate's own `@value_objects`, the identical move
257
+ # into this aggregate's own `@value_objects`, the identical move
258
258
  # `@value_objects + closed_sets` already makes for the aggregate's
259
259
  # own direct attributes (see this file's other 5 call sites).
260
- # `type` — THE BARE SHORTHAND (single-attribute value objects):
260
+ # `type` — the bare shorthand (single-attribute value objects):
261
261
  # `value_object :Price, Integer` declares a value object with
262
- # exactly one attribute, NAMED `value`, of that type — pure sugar
262
+ # exactly one attribute, named `value`, of that type — pure sugar
263
263
  # for `value_object("Price") { attribute :value, Integer }`,
264
- # routed through the SAME `attribute_impl` the block form's own
264
+ # routed through the same `attribute_impl` the block form's own
265
265
  # `attribute` line reaches (so the quoted-text-type refusal,
266
266
  # `one_of(...)`/`list_of(...)` synthesis, everything an attribute
267
267
  # line already does, applies unchanged rather than being
268
268
  # re-derived here). The name `value` is not arbitrary: a
269
- # single-attribute value object is a NAME for a scalar, not a
269
+ # single-attribute value object is a name for a scalar, not a
270
270
  # genuine group ([[feedback_name_the_scalar_field]], `Behaviour::
271
271
  # ValueObject#sole_attribute`), and `value` is what the language
272
- # guarantees EVERY sole field answers to at runtime regardless of
272
+ # guarantees every sole field answers to at runtime regardless of
273
273
  # its declared name (`Runtime::Value#method_missing`'s alias) —
274
274
  # so the shorthand simply declares it under the canonical name
275
- # directly. Type AND block together are refused: the block exists
275
+ # directly. Type and block together are refused: the block exists
276
276
  # to say what the fields are, and the type just said it — two
277
277
  # answers to one question is an authoring error, never a merge.
278
- # NEITHER type NOR block keeps its historical behavior untouched
278
+ # Neither type nor block keeps its historical behavior untouched
279
279
  # (an empty attribute list — judged, or not, by the language
280
280
  # downstream, the same as before this parameter existed).
281
281
  def value_object(name, type = nil, &block)
@@ -293,37 +293,37 @@ module Hecks
293
293
  @value_objects.concat(builder.closed_sets)
294
294
  end
295
295
 
296
- # `from:` — LIFECYCLE STATE BECOMES A COMMAND GUARD (S10, ADR
296
+ # `from:` — lifecycle state becomes a command guard (S10, ADR
297
297
  # 0025) — `command "Debit", from: "open"` replaces `given
298
298
  # ("account is open") { status == "open" }`, written 35 times
299
- # in two wordings across the corpus. Checked against THIS
299
+ # in two wordings across the corpus. Checked against this
300
300
  # aggregate's own lifecycle field (`Admissibility#enforce_
301
301
  # lifecycle_guard`) — never a target state, never a transition:
302
302
  # the lifecycle already declares which states exist, so naming
303
303
  # the legal ones is checkable against it, where a free-text
304
304
  # given could drift out of sync with the state machine and did.
305
305
  def command_impl(name, from: nil, &block)
306
- # The verb is declared ON this aggregate — the owner `acts_on` answers
306
+ # The verb is declared on this aggregate — the owner `acts_on` answers
307
307
  # with — stamped by `Aggregate#initialize` once the aggregate
308
- # exists. An ENTITY's commands take the entity as their owner instead,
309
- # at the entity's own declaration. NOT built here — see
308
+ # exists. An entity's commands take the entity as their owner instead,
309
+ # at the entity's own declaration. Not built here — see
310
310
  # `#drain_pending!`'s own comment for why this only queues a
311
311
  # descriptor.
312
312
  @pending_commands << [name, from, block]
313
313
  end
314
314
 
315
- # A PRECONDITION SHARED ACROSS COMMANDS, DECLARED ONCE (S10, ADR
315
+ # A precondition shared across commands, declared once (S10, ADR
316
316
  # 0025) — an aggregate-level `given`, block required, stored by
317
317
  # its own description rather than appended anywhere: a command
318
318
  # names it back (`given("customer is active")`, no block of its
319
319
  # own) rather than re-typing the predicate, so there is one
320
320
  # description and therefore one refusal message no matter which
321
- # command a caller hits. DECLARE BEFORE THE COMMANDS THAT
322
- # REFERENCE IT — resolution happens at the referencing command's
323
- # OWN build time (`CommandBuilder#given`), against whatever this
324
- # aggregate has declared SO FAR, the one ordering constraint this
321
+ # command a caller hits. Declare before the commands that
322
+ # reference it — resolution happens at the referencing command's
323
+ # own build time (`CommandBuilder#given`), against whatever this
324
+ # aggregate has declared so far, the one ordering constraint this
325
325
  # word carries that `identified_by`/`attribute` do not.
326
- # BARENO BLOCKREFERENCES a SIBLING AGGREGATE's own
326
+ # Bareno blockreferences a sibling aggregate's own
327
327
  # already-declared precondition, one level wider than the
328
328
  # existing bare-command-references-its-own-aggregate shape
329
329
  # (`CommandBuilder#reference_named_given`): `SafeDepositBox`/
@@ -333,28 +333,28 @@ module Hecks
333
333
  # — see `BluebookBuilder#aggregate`'s own comment for how that
334
334
  # pool is threaded, and `docs/implemented/resolution-rules/chapter-given.md`
335
335
  # for the full algorithm and its known limitations (a bare
336
- # reference trusts its own author to have verified the SAME
336
+ # reference trusts its own author to have verified the same
337
337
  # canonical predicate applies — this mechanism does not, and
338
338
  # cannot, check that itself; see that doc for which real corpus
339
339
  # cases do and do not qualify).
340
340
  #
341
- # `declared_by:` DISAMBIGUATES the same description meaning TWO
341
+ # `declared_by:` disambiguates the same description meaning two
342
342
  # genuinely different predicates chapter-wide — real, live:
343
343
  # `Account`'s own "customer is active" reads bare
344
- # `customer.status` (a DIRECT `reference_to Customer`); `ATMCard`'s
344
+ # `customer.status` (a direct `reference_to Customer`); `ATMCard`'s
345
345
  # own (shared onward with `CardPayment`/`ExternalTransfer`/
346
346
  # `ScheduledPayment`/`Statement`) reads `account.customer.status`
347
- # (reached THROUGH `Account`) — the identical business fact, a
348
- # genuinely different runtime path, correctly kept as the SAME
347
+ # (reached through `Account`) — the identical business fact, a
348
+ # genuinely different runtime path, correctly kept as the same
349
349
  # domain wording rather than invented a second spelling for "the
350
350
  # same idea, one more hop away" (S10, ADR 0025's own "one idea,
351
351
  # one spelling"). Omit it when the description is unambiguous
352
- # chapter-wide (the common case, and the ONLY case this took
353
- # before this parameter existed) — required only once a SECOND,
352
+ # chapter-wide (the common case, and the only case this took
353
+ # before this parameter existed) — required only once a second,
354
354
  # textually-different canonical registers under the same
355
355
  # description; see `reference_named_chapter_given`'s own
356
356
  # ambiguity error for how that surfaces.
357
- # RENAMED FROM `given` — item #13's full metaprogrammed dispatch
357
+ # Renamed from `given` — item #13's full metaprogrammed dispatch
358
358
  # (slice 4b), same reasoning as reference_to_impl above:
359
359
  # bootstrap-reachable, in BOOTSTRAP_CALLS_FALLBACK.
360
360
  def given_impl(description, declared_by: nil, &predicate)
@@ -363,10 +363,10 @@ module Hecks
363
363
  named = build_rule(Given, description, predicate, owner_name: @name, word: "given",
364
364
  extraction_failure: "its source could not be read, so no other runtime could ever evaluate it")
365
365
  @named_givens[description] = named
366
- # WRITE-THROUGH, first-declared-wins PER OWNER — keyed by
366
+ # Write-through, first-declared-wins per owner — keyed by
367
367
  # [description, this aggregate's own name], not description
368
- # alone: two DIFFERENT aggregates independently declaring the
369
- # SAME description are two DISTINCT candidates a later bare
368
+ # alone: two different aggregates independently declaring the
369
+ # same description are two distinct candidates a later bare
370
370
  # reference chooses between (via `declared_by:` once there is
371
371
  # more than one), never silently merged into one slot the way
372
372
  # a bare description-only key would.
@@ -376,16 +376,16 @@ module Hecks
376
376
 
377
377
  private
378
378
 
379
- # PRIMITIVE 2 (RuleReference#resolve_owner_keyed) — see that
379
+ # Primitive 2 (RuleReference#resolve_owner_keyed) — see that
380
380
  # method's own comment for the pool shape; the three branches
381
381
  # below (exact owner / unambiguous single candidate / ambiguous)
382
- # are this construct's OWN refusal wording, not shared, since
383
- # `declared_by:` only exists here so far. UNRESOLVED (no
382
+ # are this construct's own refusal wording, not shared, since
383
+ # `declared_by:` only exists here so far. Unresolved (no
384
384
  # candidate yet, or `declared_by:` naming an aggregate that
385
385
  # hasn't declared it yet) is no longer a fourth branch that
386
- # raises HERE — see `#pending_chapter_given`, below, for why:
386
+ # raises here — see `#pending_chapter_given`, below, for why:
387
387
  # a chapter split across files can genuinely reference a
388
- # precondition a LATER file declares, and "not found among
388
+ # precondition a later file declares, and "not found among
389
389
  # what's loaded so far" cannot tell that apart from "genuinely
390
390
  # never declared" until every file has.
391
391
  def reference_named_chapter_given(description, declared_by:)
@@ -411,7 +411,7 @@ module Hecks
411
411
  @named_givens[description] = named
412
412
  end
413
413
 
414
- # A CHAPTER MAY BE SPLIT ACROSS FILES — the SAME reason a query
414
+ # A chapter may be split across files — the same reason a query
415
415
  # hop's own cross-file target, a correlation key's own emitting
416
416
  # command, and an event's own declared shape are all resolved
417
417
  # once the whole chapter is assembled rather than refused the
@@ -419,18 +419,18 @@ module Hecks
419
419
  # far (`BluebookBuilder.validate_assembled!`'s own comment).
420
420
  #
421
421
  # Unlike those, though, a chapter-given's resolved value is not
422
- # a pass/fail check on an already-built IR — it IS part of the
422
+ # a pass/fail check on an already-built IR — it is part of the
423
423
  # referencing aggregate's own IR (`preconditions:` below), built
424
- # and handed off the moment THIS aggregate's own file finishes
424
+ # and handed off the moment this aggregate's own file finishes
425
425
  # loading, long before a later file might declare the real
426
- # thing. So this hands back a PLACEHOLDER `Given` — embedded
426
+ # thing. So this hands back a placeholder `Given` — embedded
427
427
  # exactly where the resolved one would be, by Ruby object
428
- # reference, in this aggregate's own `preconditions` AND in any
429
- # command in this SAME aggregate that separately bare-references
428
+ # reference, in this aggregate's own `preconditions` and in any
429
+ # command in this same aggregate that separately bare-references
430
430
  # the same description (`CommandBuilder#given`'s own hash-chain
431
431
  # read of this aggregate's `@named_givens`, the identical key) —
432
432
  # and queues the request in `@chapter_pending_givens`.
433
- # `BluebookBuilder#resolve_pending_chapter_givens!` MUTATES this
433
+ # `BluebookBuilder#resolve_pending_chapter_givens!` mutates this
434
434
  # exact object in place, once every file has loaded, so every
435
435
  # existing reference to it (there is only ever the one object,
436
436
  # never a copy) sees the resolved fields simultaneously. Safe
@@ -448,7 +448,7 @@ module Hecks
448
448
 
449
449
  public
450
450
 
451
- # THE AGGREGATE BOUNDARY IS WHAT AN INVARIANT DEFINES (S10, ADR
451
+ # The aggregate boundary is what an invariant defines (S10, ADR
452
452
  # 0025 — "Rules") — checked after every command, before save,
453
453
  # the same way a value object's already is
454
454
  # (`ValueObjectBuilder#invariant`, whose own shape this mirrors
@@ -458,7 +458,7 @@ module Hecks
458
458
  # texts across banking's six balance-moving commands, and the
459
459
  # four that only increase it said nothing at all — completeness
460
460
  # depended on someone noticing which commands could decrease it.
461
- # RENAMED FROM `invariant` — item #13's full metaprogrammed
461
+ # Renamed from `invariant` — item #13's full metaprogrammed
462
462
  # dispatch (slice 4b), same reasoning as given_impl above.
463
463
  def invariant_impl(description, &predicate)
464
464
  @invariants << build_rule(Invariant, description, predicate, owner_name: @name, word: "invariant",
@@ -493,7 +493,7 @@ module Hecks
493
493
  provenance: @provenance
494
494
  )
495
495
 
496
- # After the IR exists, on purpose : a reference is declared IN the
496
+ # After the IR exists, on purpose : a reference is declared in the
497
497
  # aggregate, and the aggregate the IR graph knows is `ir`, not the
498
498
  # builder.
499
499
  stamp_references(ir)
@@ -511,14 +511,14 @@ module Hecks
511
511
 
512
512
  private
513
513
 
514
- # DEFERRED CONSTRUCTION — `entity`/`command`/`query` used to build
515
- # immediately, INLINE, the moment their own DSL line ran during
514
+ # **Deferred construction** — `entity`/`command`/`query` used to build
515
+ # immediately, inline, the moment their own DSL line ran during
516
516
  # `instance_eval` — meaning a command's own resolution (`sets
517
517
  # :field` importing the owner's own attribute, `given("desc")`
518
518
  # referencing an aggregate-level precondition, a query's own
519
519
  # positional-param resolution) only ever saw whatever `@entities`/
520
- # `attributes`/`@named_givens`/`@value_objects` held AS OF THAT
521
- # EXACT TEXTUAL LINE — never what the aggregate's block would go
520
+ # `attributes`/`@named_givens`/`@value_objects` held as of that
521
+ # exact textual line — never what the aggregate's block would go
522
522
  # on to declare after it. Three real, confirmed cases in the
523
523
  # self-hosted meta-domain violate the "declare before you
524
524
  # reference" convention every other resolution rule relies on
@@ -526,26 +526,26 @@ module Hecks
526
526
  # Member/Dispatch — see docs/resolution-rules/
527
527
  # implicit-append-fields.md's own "Known limitations").
528
528
  #
529
- # This is the SAME move `BluebookBuilder` already makes one level
530
- # UP, at the CHAPTER level — build every aggregate first, THEN run
529
+ # This is the same move `BluebookBuilder` already makes one level
530
+ # up, at the chapter level — build every aggregate first, then run
531
531
  # cross-referential validation (`validate_query_hops!`,
532
532
  # `validate_projected_fields!`, `validate_no_bidirectional_
533
533
  # references!`) once `@aggregates` is fully populated — extended
534
- # one level down: `entity`/`command`/`query` now only QUEUE a
534
+ # one level down: `entity`/`command`/`query` now only queue a
535
535
  # descriptor (`@pending_entities`/`@pending_commands`/
536
536
  # `@pending_queries`, each preserving its own declared order),
537
- # and `#build` drains them here, in this exact order, BEFORE any
537
+ # and `#build` drains them here, in this exact order, before any
538
538
  # of the existing `seal_*` validations (which already assume
539
539
  # `@commands`/`@entities`/`@queries` are the real, final, built
540
- # objects) — entities FIRST and fully, since a command's own
540
+ # objects) — entities first and fully, since a command's own
541
541
  # `sets :list, append: {...}` needs a list's element entity
542
542
  # already built (`.attributes` populated) to resolve against, not
543
543
  # just named.
544
544
  #
545
545
  # `attribute`/`value_object`/`identified_by`/`given` (block form)
546
- # are NOT deferred — they still build eagerly during
546
+ # are not deferred — they still build eagerly during
547
547
  # `instance_eval`, unchanged. Nothing reads `@entities`/
548
- # `@commands`/`@queries` from anywhere OTHER than `#build` and its
548
+ # `@commands`/`@queries` from anywhere other than `#build` and its
549
549
  # own private helpers (checked directly), so nothing else in this
550
550
  # file needed to change for this to be safe.
551
551
  def drain_pending!
@@ -583,7 +583,7 @@ module Hecks
583
583
  @value_objects << value_object
584
584
  end
585
585
 
586
- # LEGACY — see `has_many`/`has_one`/`belongs_to`'s own comment;
586
+ # Legacy — see `has_many`/`has_one`/`belongs_to`'s own comment;
587
587
  # byte-identical to what those three did before this slice.
588
588
  def legacy_has_many(type, as:, optional: false)
589
589
  plural = Naming.demodulise(type)