hecks 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (355) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hecks/adapters/driven/claude_code.rb +7 -7
  3. data/lib/hecks/adapters/driven/d1.rb +187 -23
  4. data/lib/hecks/adapters/driven/folder.rb +10 -10
  5. data/lib/hecks/adapters/driven/google_authentication.rb +8 -8
  6. data/lib/hecks/adapters/driven/governance_authorization.rb +31 -13
  7. data/lib/hecks/adapters/driven/heki/journal.rb +5 -4
  8. data/lib/hecks/adapters/driven/heki/saga_store.rb +5 -5
  9. data/lib/hecks/adapters/driven/heki.rb +13 -7
  10. data/lib/hecks/adapters/driven/identity_registry.rb +2 -2
  11. data/lib/hecks/adapters/driven/in_memory_ordering.rb +3 -3
  12. data/lib/hecks/adapters/driven/lambda/client.rb +34 -9
  13. data/lib/hecks/adapters/driven/lambda.rb +39 -33
  14. data/lib/hecks/adapters/driven/local_storage.rb +17 -10
  15. data/lib/hecks/adapters/driven/memory.rb +205 -9
  16. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +1 -1
  17. data/lib/hecks/adapters/driven/postgres/codec.rb +27 -11
  18. data/lib/hecks/adapters/driven/postgres/outbox.rb +40 -2
  19. data/lib/hecks/adapters/driven/postgres/reconnect.rb +23 -7
  20. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +14 -14
  21. data/lib/hecks/adapters/driven/postgres.rb +175 -28
  22. data/lib/hecks/adapters/driven/prism.rb +4 -4
  23. data/lib/hecks/adapters/driven/sql_query_builder.rb +34 -22
  24. data/lib/hecks/adapters/driven/sqlite/codec.rb +38 -10
  25. data/lib/hecks/adapters/driven/sqlite/projection.rb +60 -32
  26. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +12 -12
  27. data/lib/hecks/adapters/driven/sqlite.rb +181 -21
  28. data/lib/hecks/adapters/driven.rb +4 -4
  29. data/lib/hecks/adapters/driving/github_webhook.rb +18 -18
  30. data/lib/hecks/behaviors/dsl.rb +2 -2
  31. data/lib/hecks/behaviors/expectations.rb +23 -23
  32. data/lib/hecks/behaviors/ir.rb +1 -1
  33. data/lib/hecks/behaviors/rspec.rb +1 -1
  34. data/lib/hecks/behaviors/runner.rb +2 -2
  35. data/lib/hecks/behaviors.rb +1 -1
  36. data/lib/hecks/bluebook/aggregate.rb +13 -13
  37. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +10 -10
  38. data/lib/hecks/bluebook/assembly/build.rb +1 -1
  39. data/lib/hecks/bluebook/assembly/contract.rb +39 -16
  40. data/lib/hecks/bluebook/assembly/contracts.rb +40 -38
  41. data/lib/hecks/bluebook/assembly/marks.rb +18 -18
  42. data/lib/hecks/bluebook/assembly/specializer.rb +19 -21
  43. data/lib/hecks/bluebook/assembly.rb +9 -9
  44. data/lib/hecks/bluebook/attribute.rb +9 -9
  45. data/lib/hecks/bluebook/behaviour/aggregate.rb +11 -11
  46. data/lib/hecks/bluebook/behaviour/attribute.rb +5 -5
  47. data/lib/hecks/bluebook/behaviour/chapter.rb +23 -5
  48. data/lib/hecks/bluebook/behaviour/command.rb +23 -23
  49. data/lib/hecks/bluebook/behaviour/domain_port.rb +7 -7
  50. data/lib/hecks/bluebook/behaviour/entity.rb +8 -8
  51. data/lib/hecks/bluebook/behaviour/hexagon.rb +4 -4
  52. data/lib/hecks/bluebook/behaviour/lifecycle.rb +5 -5
  53. data/lib/hecks/bluebook/behaviour/policy.rb +12 -12
  54. data/lib/hecks/bluebook/behaviour/process_manager.rb +7 -7
  55. data/lib/hecks/bluebook/behaviour/query.rb +1 -1
  56. data/lib/hecks/bluebook/behaviour/read_model.rb +8 -8
  57. data/lib/hecks/bluebook/behaviour/traits.rb +12 -12
  58. data/lib/hecks/bluebook/behaviour/value_object.rb +6 -6
  59. data/lib/hecks/bluebook/capabilities.rb +27 -0
  60. data/lib/hecks/bluebook/chapter.rb +28 -9
  61. data/lib/hecks/bluebook/command.rb +12 -12
  62. data/lib/hecks/bluebook/domain_port.rb +9 -9
  63. data/lib/hecks/bluebook/dsl/adapter_builder.rb +24 -0
  64. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +49 -49
  65. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +96 -96
  66. data/lib/hecks/bluebook/dsl/attribute_collector.rb +41 -41
  67. data/lib/hecks/bluebook/dsl/binding_proxy.rb +22 -2
  68. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +111 -74
  69. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +48 -30
  70. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +116 -0
  71. data/lib/hecks/bluebook/dsl/command_builder.rb +103 -103
  72. data/lib/hecks/bluebook/dsl/const_shim.rb +46 -15
  73. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +90 -25
  74. data/lib/hecks/bluebook/dsl/entity_builder.rb +56 -56
  75. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +148 -132
  76. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +89 -30
  77. data/lib/hecks/bluebook/dsl/identity_declaration.rb +17 -17
  78. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +27 -4
  79. data/lib/hecks/bluebook/dsl/policy_builder.rb +30 -21
  80. data/lib/hecks/bluebook/dsl/port_builder.rb +38 -7
  81. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +56 -22
  82. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +35 -35
  83. data/lib/hecks/bluebook/dsl/query_builder.rb +5 -5
  84. data/lib/hecks/bluebook/dsl/read_model_builder.rb +34 -34
  85. data/lib/hecks/bluebook/dsl/rule_reference.rb +41 -39
  86. data/lib/hecks/bluebook/dsl/translation_builder.rb +9 -9
  87. data/lib/hecks/bluebook/dsl/value_object_builder.rb +16 -16
  88. data/lib/hecks/bluebook/dsl/word_gate.rb +59 -53
  89. data/lib/hecks/bluebook/dsl/world_builder.rb +51 -8
  90. data/lib/hecks/bluebook/entity.rb +11 -11
  91. data/lib/hecks/bluebook/expression/ast_json.rb +20 -20
  92. data/lib/hecks/bluebook/expression/ast_reader.rb +3 -3
  93. data/lib/hecks/bluebook/expression/canonical_form.rb +9 -9
  94. data/lib/hecks/bluebook/expression/evaluator.rb +18 -18
  95. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +18 -18
  96. data/lib/hecks/bluebook/expression/resolver.rb +60 -62
  97. data/lib/hecks/bluebook/hexagon.rb +1 -1
  98. data/lib/hecks/bluebook/lifecycle.rb +1 -1
  99. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -1
  100. data/lib/hecks/bluebook/meta_validator/judge.rb +101 -87
  101. data/lib/hecks/bluebook/meta_validator/plan.rb +39 -39
  102. data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -2
  103. data/lib/hecks/bluebook/meta_validator/readings.rb +43 -43
  104. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +44 -37
  105. data/lib/hecks/bluebook/meta_validator/shapes.rb +25 -21
  106. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +145 -31
  107. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +6 -6
  108. data/lib/hecks/bluebook/meta_validator/world_judge.rb +5 -5
  109. data/lib/hecks/bluebook/meta_validator.rb +70 -70
  110. data/lib/hecks/bluebook/model_check.rb +170 -84
  111. data/lib/hecks/bluebook/pattern_subset.rb +9 -9
  112. data/lib/hecks/bluebook/policy.rb +15 -13
  113. data/lib/hecks/bluebook/process_manager.rb +14 -14
  114. data/lib/hecks/bluebook/project_register.rb +6 -6
  115. data/lib/hecks/bluebook/query.rb +4 -4
  116. data/lib/hecks/bluebook/read_model.rb +14 -14
  117. data/lib/hecks/bluebook/reference.rb +8 -8
  118. data/lib/hecks/bluebook/smoke_test.rb +19 -19
  119. data/lib/hecks/bluebook/synthesizer.rb +12 -12
  120. data/lib/hecks/bluebook/translation.rb +4 -4
  121. data/lib/hecks/bluebook/value_object.rb +6 -6
  122. data/lib/hecks/bluebook.rb +2 -2
  123. data/lib/hecks/codemod/legacy_dispatch_args.rb +299 -0
  124. data/lib/hecks/codemod/legacy_dispatch_recorder.rb +186 -0
  125. data/lib/hecks/codemod.rb +36 -35
  126. data/lib/hecks/construct.rb +6 -6
  127. data/lib/hecks/corpus.rb +317 -0
  128. data/lib/hecks/deprecation.rb +95 -0
  129. data/lib/hecks/doc/reference.rb +19 -19
  130. data/lib/hecks/embryonaut_bluebook.rb +11 -11
  131. data/lib/hecks/facade/cli_door.rb +69 -10
  132. data/lib/hecks/facade/cli_runner.rb +105 -24
  133. data/lib/hecks/facade/command_request.rb +23 -0
  134. data/lib/hecks/facade/handle.rb +79 -32
  135. data/lib/hecks/facade/json_door.rb +106 -25
  136. data/lib/hecks/facade/surface/aggregate_door.rb +42 -27
  137. data/lib/hecks/facade/surface/chapter.rb +26 -17
  138. data/lib/hecks/facade/surface.rb +16 -3
  139. data/lib/hecks/facade.rb +15 -4
  140. data/lib/hecks/forms/app.rb +46 -30
  141. data/lib/hecks/forms/command_form_renderer.rb +70 -9
  142. data/lib/hecks/forms/field_renderer.rb +142 -6
  143. data/lib/hecks/forms/field_shape.rb +180 -19
  144. data/lib/hecks/forms/html.rb +51 -7
  145. data/lib/hecks/forms/index_renderer.rb +14 -2
  146. data/lib/hecks/forms/params.rb +120 -23
  147. data/lib/hecks/forms/port_argument.rb +2 -2
  148. data/lib/hecks/forms/query_form_renderer.rb +2 -2
  149. data/lib/hecks/forms/record_renderer.rb +2 -2
  150. data/lib/hecks/forms/record_table.rb +1 -1
  151. data/lib/hecks/forms/value_object_shape.rb +3 -3
  152. data/lib/hecks/forms.rb +24 -4
  153. data/lib/hecks/fqn.rb +1 -1
  154. data/lib/hecks/framework/bluebook/governance.bluebook +9 -0
  155. data/lib/hecks/framework.rb +48 -17
  156. data/lib/hecks/freezer.rb +11 -11
  157. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +90 -90
  158. data/lib/hecks/fuzzing/combination_miner.rb +119 -0
  159. data/lib/hecks/fuzzing/concurrent_dispatch.rb +140 -45
  160. data/lib/hecks/fuzzing/coverage_campaign.rb +118 -0
  161. data/lib/hecks/fuzzing/differential.rb +158 -0
  162. data/lib/hecks/fuzzing/domain_generator.rb +694 -0
  163. data/lib/hecks/fuzzing/era_boundary.rb +37 -18
  164. data/lib/hecks/fuzzing/form_census.rb +35 -20
  165. data/lib/hecks/fuzzing/generated_domain_check.rb +95 -0
  166. data/lib/hecks/fuzzing/invalid_value_generator.rb +6 -6
  167. data/lib/hecks/fuzzing/isolated_boot.rb +62 -62
  168. data/lib/hecks/fuzzing/nondeterministic.rb +67 -0
  169. data/lib/hecks/fuzzing/persistence_parity.rb +19 -21
  170. data/lib/hecks/fuzzing/properties/corrections.rb +9 -9
  171. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +154 -49
  172. data/lib/hecks/fuzzing/properties/guards.rb +42 -42
  173. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +32 -32
  174. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +22 -35
  175. data/lib/hecks/fuzzing/properties/outbox.rb +24 -24
  176. data/lib/hecks/fuzzing/properties/querying.rb +17 -17
  177. data/lib/hecks/fuzzing/properties.rb +64 -40
  178. data/lib/hecks/fuzzing/qa_settings.rb +152 -0
  179. data/lib/hecks/fuzzing/replay.rb +114 -114
  180. data/lib/hecks/fuzzing/rotation_priority.rb +10 -10
  181. data/lib/hecks/fuzzing/rust_gap_manifest.rb +113 -0
  182. data/lib/hecks/fuzzing/self_consistency.rb +141 -112
  183. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +35 -35
  184. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +18 -11
  185. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +13 -12
  186. data/lib/hecks/fuzzing/sequence_generator/picker.rb +21 -12
  187. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +58 -31
  188. data/lib/hecks/fuzzing/sequence_generator.rb +111 -23
  189. data/lib/hecks/fuzzing/shrinker.rb +197 -0
  190. data/lib/hecks/fuzzing/structural_skips.rb +23 -130
  191. data/lib/hecks/fuzzing/sweep_depth.rb +4 -4
  192. data/lib/hecks/fuzzing/target_capabilities.rb +49 -18
  193. data/lib/hecks/fuzzing/value_generator.rb +14 -14
  194. data/lib/hecks/fuzzing.rb +5 -0
  195. data/lib/hecks/grammar/evolve.rb +10 -10
  196. data/lib/hecks/grammar.rb +7 -7
  197. data/lib/hecks/ir.rb +13 -13
  198. data/lib/hecks/language/bluebook/bluebook.bluebook +41 -0
  199. data/lib/hecks/language/bluebook/policy.bluebook +11 -1
  200. data/lib/hecks/language/bluebook/vocabulary.bluebook +348 -13
  201. data/lib/hecks/language/oidc.json +5 -0
  202. data/lib/hecks/literal.rb +9 -9
  203. data/lib/hecks/naming.rb +25 -25
  204. data/lib/hecks/ports/access_control.rb +58 -2
  205. data/lib/hecks/ports/agent/answers.rb +83 -6
  206. data/lib/hecks/ports/agent.rb +119 -35
  207. data/lib/hecks/ports/authentication.rb +44 -4
  208. data/lib/hecks/ports/authorization.rb +53 -11
  209. data/lib/hecks/ports/clock.rb +42 -23
  210. data/lib/hecks/ports/extraction.rb +16 -0
  211. data/lib/hecks/ports/identity_assignment.rb +24 -2
  212. data/lib/hecks/ports/identity_generation.rb +17 -3
  213. data/lib/hecks/ports/identity_resolution.rb +18 -1
  214. data/lib/hecks/ports/loading.rb +4 -0
  215. data/lib/hecks/ports/persistence/append_only.rb +172 -8
  216. data/lib/hecks/ports/persistence/binding_policy.rb +34 -0
  217. data/lib/hecks/ports/persistence/codec_boundary.rb +178 -0
  218. data/lib/hecks/ports/persistence/execution.rb +4 -0
  219. data/lib/hecks/ports/persistence/null_saga_store.rb +12 -1
  220. data/lib/hecks/ports/persistence/plugin.rb +42 -4
  221. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +218 -25
  222. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +77 -9
  223. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +81 -24
  224. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +29 -18
  225. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +144 -60
  226. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +103 -8
  227. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +98 -23
  228. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +282 -109
  229. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +63 -25
  230. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +118 -66
  231. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +51 -28
  232. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +28 -5
  233. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +25 -12
  234. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +129 -34
  235. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +51 -6
  236. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +33 -9
  237. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +16 -0
  238. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +57 -4
  239. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +25 -2
  240. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +314 -90
  241. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +68 -10
  242. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +9 -3
  243. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +9 -2
  244. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +42 -8
  245. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -1
  246. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +36 -5
  247. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +23 -3
  248. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -19
  249. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +5 -5
  250. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +1 -1
  251. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -2
  252. data/lib/hecks/ports/persistence/plugins/era.rb +12 -2
  253. data/lib/hecks/ports/persistence/remote_runtime.rb +9 -2
  254. data/lib/hecks/ports/persistence/repository_factory.rb +23 -3
  255. data/lib/hecks/ports/persistence/state_codec.rb +319 -0
  256. data/lib/hecks/ports/persistence.rb +36 -1
  257. data/lib/hecks/ports/projection.rb +61 -7
  258. data/lib/hecks/ports/query/in_memory.rb +3 -3
  259. data/lib/hecks/ports/query/ordering.rb +6 -6
  260. data/lib/hecks/ports/query.rb +35 -0
  261. data/lib/hecks/projections/bootstrap_table.rb +112 -0
  262. data/lib/hecks/projections/diagrams.rb +75 -75
  263. data/lib/hecks/projections/glossary/html.rb +3 -3
  264. data/lib/hecks/projections/glossary/markdown.rb +3 -3
  265. data/lib/hecks/projections/glossary/mermaid.rb +1 -1
  266. data/lib/hecks/projections/glossary/sections.rb +1 -1
  267. data/lib/hecks/projections/glossary/sentences.rb +5 -5
  268. data/lib/hecks/projections/glossary.rb +15 -15
  269. data/lib/hecks/projections/ir.rb +1 -1
  270. data/lib/hecks/projections/model/deviations.rb +18 -17
  271. data/lib/hecks/projections/model.rb +25 -21
  272. data/lib/hecks/projections/oidc.rb +7 -7
  273. data/lib/hecks/projections/parser_table.rb +5 -5
  274. data/lib/hecks/projections/reference.rb +3 -3
  275. data/lib/hecks/projections/rust_vocabulary.rb +443 -0
  276. data/lib/hecks/projections/shape.rb +2 -2
  277. data/lib/hecks/projections/statements.rb +11 -11
  278. data/lib/hecks/projections/vocabulary.rb +9 -9
  279. data/lib/hecks/projections.rb +5 -3
  280. data/lib/hecks/projector/cli_projector.rb +29 -29
  281. data/lib/hecks/projector/docs_projector.rb +13 -13
  282. data/lib/hecks/projector/exporter.rb +42 -21
  283. data/lib/hecks/projector/ir_projector.rb +1 -1
  284. data/lib/hecks/projector/narrate_projector.rb +11 -11
  285. data/lib/hecks/projector/target.rb +13 -13
  286. data/lib/hecks/projector.rb +15 -15
  287. data/lib/hecks/query_ir.rb +47 -47
  288. data/lib/hecks/query_specification/common/comparators.rb +19 -3
  289. data/lib/hecks/query_specification/common/comparison.rb +109 -27
  290. data/lib/hecks/query_specification/common/dsl.rb +65 -9
  291. data/lib/hecks/query_specification/common/null_policy.rb +57 -13
  292. data/lib/hecks/query_specification/common/null_semantics.rb +4 -0
  293. data/lib/hecks/query_specification/common/options.rb +25 -0
  294. data/lib/hecks/query_specification/field_path.rb +69 -15
  295. data/lib/hecks/query_specification/hop_path.rb +57 -20
  296. data/lib/hecks/query_specification/read_model/specification.rb +4 -0
  297. data/lib/hecks/rendering.rb +3 -3
  298. data/lib/hecks/router/namespace_installer.rb +3 -3
  299. data/lib/hecks/router.rb +1 -1
  300. data/lib/hecks/runtime/aggregate_lock.rb +11 -11
  301. data/lib/hecks/runtime/boot_gates.rb +3 -3
  302. data/lib/hecks/runtime/caller.rb +8 -8
  303. data/lib/hecks/runtime/capability_graph.rb +2 -2
  304. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +22 -25
  305. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +42 -63
  306. data/lib/hecks/runtime/command_interpreter.rb +159 -102
  307. data/lib/hecks/runtime/command_rules/admissibility.rb +69 -69
  308. data/lib/hecks/runtime/command_rules/arithmetic.rb +137 -91
  309. data/lib/hecks/runtime/command_rules/authorization.rb +38 -17
  310. data/lib/hecks/runtime/command_rules/emission.rb +18 -1
  311. data/lib/hecks/runtime/command_rules/references.rb +35 -35
  312. data/lib/hecks/runtime/command_rules.rb +3 -0
  313. data/lib/hecks/runtime/dependency_planning.rb +11 -11
  314. data/lib/hecks/runtime/dispatcher.rb +283 -90
  315. data/lib/hecks/runtime/entity_element.rb +151 -67
  316. data/lib/hecks/runtime/entity_interpreter.rb +108 -82
  317. data/lib/hecks/runtime/errors.rb +19 -19
  318. data/lib/hecks/runtime/event.rb +6 -6
  319. data/lib/hecks/runtime/identity.rb +22 -22
  320. data/lib/hecks/runtime/instance.rb +39 -14
  321. data/lib/hecks/runtime/interpreting.rb +12 -12
  322. data/lib/hecks/runtime/invocation.rb +276 -0
  323. data/lib/hecks/runtime/loader.rb +14 -14
  324. data/lib/hecks/runtime/outbox.rb +23 -23
  325. data/lib/hecks/runtime/policy_interpreter.rb +54 -54
  326. data/lib/hecks/runtime/port_operation_interpreter.rb +22 -19
  327. data/lib/hecks/runtime/query_interpreter.rb +55 -64
  328. data/lib/hecks/runtime/reaction_invocation.rb +20 -20
  329. data/lib/hecks/runtime/read_model_interpreter.rb +40 -40
  330. data/lib/hecks/runtime/rebuild_sweep.rb +4 -4
  331. data/lib/hecks/runtime/reference_hop.rb +6 -6
  332. data/lib/hecks/runtime/refusal_wording.rb +92 -115
  333. data/lib/hecks/runtime/registry/saga_persistence.rb +21 -21
  334. data/lib/hecks/runtime/registry/verification.rb +36 -26
  335. data/lib/hecks/runtime/registry.rb +45 -28
  336. data/lib/hecks/runtime/remote_dispatcher.rb +38 -23
  337. data/lib/hecks/runtime/routing.rb +10 -153
  338. data/lib/hecks/runtime/saga_interpreter/correlation.rb +17 -17
  339. data/lib/hecks/runtime/saga_interpreter.rb +64 -64
  340. data/lib/hecks/runtime/saga_pending_dispatch.rb +12 -12
  341. data/lib/hecks/runtime/tenant_check.rb +9 -9
  342. data/lib/hecks/runtime/tenant_scope.rb +5 -5
  343. data/lib/hecks/runtime/value/admission.rb +75 -30
  344. data/lib/hecks/runtime/value/coercion.rb +318 -127
  345. data/lib/hecks/runtime/value/entity_list_coercion.rb +34 -34
  346. data/lib/hecks/runtime/value.rb +21 -21
  347. data/lib/hecks/runtime.rb +7 -7
  348. data/lib/hecks/storehouse.rb +64 -64
  349. data/lib/hecks/version.rb +3 -3
  350. data/lib/hecks/vocabulary.rb +205 -4
  351. data/lib/hecks.rb +13 -11
  352. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +11 -11
  353. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +14 -12
  354. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +11 -11
  355. metadata +22 -2
@@ -0,0 +1,27 @@
1
+ module Hecks
2
+ module Bluebook
3
+ # What a chapter may declare it provides, and what each capability
4
+ # must name. A chapter that `provides "authorization"` is trusted in
5
+ # place of a check for the literal name "Governance" — by the role
6
+ # check at dispatch, the ungoverned-role refusal at boot, the
7
+ # authorization adapter and the fuzzer — so the declaration has to be
8
+ # complete and point at real verbs. `BluebookBuilder::Validation
9
+ # #validate_provisions!` holds every `provides` to this table.
10
+ #
11
+ # key => :command | :query the kind of verb that key must name
12
+ module Capabilities
13
+ AUTHORIZATION = "authorization".freeze
14
+
15
+ CONTRACTS = {
16
+ AUTHORIZATION => {
17
+ # every assignment an actor holds, current or historical
18
+ assignments: :query,
19
+ # the command that grants an actor a role
20
+ grant: :command,
21
+ # every grant of one role acting as another
22
+ transitions: :query
23
+ }.freeze
24
+ }.freeze
25
+ end
26
+ end
27
+ end
@@ -1,29 +1,30 @@
1
1
  require_relative "behaviour/chapter"
2
+ require_relative "capabilities"
2
3
  require_relative "../ir"
3
4
 
4
5
  module Hecks
5
6
  module Bluebook
6
- # THE CHAPTER, and no longer the namespace it lives in.
7
+ # The chapter, and no longer the namespace it lives in.
7
8
  #
8
- # `Hecks::Bluebook` was briefly a CLASS, because dropping the
9
+ # `Hecks::Bluebook` was briefly a class, because dropping the
9
10
  # old `IR::` segment would otherwise have produced
10
11
  # `Bluebook::Bluebook` — a class shadowing its own enclosing module.
11
12
  # Naming the construct what the code already called it everywhere
12
13
  # (a chapter; this file was already chapter.rb) removes the clash
13
14
  # at the source, so the namespace goes back to being a module.
14
15
  #
15
- # Measured before changing: `Bluebook` was used AS a class in five
16
+ # Measured before changing: `Bluebook` was used as a class in five
16
17
  # places and as a namespace in seventy-seven files.
17
18
  class Chapter
18
19
  include Construct
19
20
  include Behaviour::Chapter
20
21
  include Hecks::IR
21
22
 
22
- # THE SCHEMA'S OWN VERSION — not a domain's `version:` (Banking's
23
- # "v1", a business fact the AUTHOR chose), but the shape `to_h`
23
+ # **The schema's own version** — not a domain's `version:` (Banking's
24
+ # "v1", a business fact the author chose), but the shape `to_h`
24
25
  # itself emits. A consumer reading exported IR with no Ruby DSL to
25
26
  # cross-check against (a build-time generator, a stored snapshot)
26
- # needs to know WHICH shape it's holding before it can safely
27
+ # needs to know which shape it's holding before it can safely
27
28
  # interpret any of the rest of it. Bump this when `to_h`'s own
28
29
  # shape changes in a way a consumer would need to know about —
29
30
  # not when a domain's own declarations change.
@@ -40,7 +41,7 @@ module Hecks
40
41
  # `bluebook.formerly_known_as` off the live Ruby object) and the
41
42
  # meta-validator's cache key is `SHA256(JSON(bluebook.to_h))` — so
42
43
  # a fact this method didn't spell was a fact two chapters
43
- # differing ONLY by their old name could hash identically on,
44
+ # differing only by their old name could hash identically on,
44
45
  # same as read-model filters before them. Spelled here for the
45
46
  # same reason `version`/`vision` are: a plain field, present
46
47
  # (possibly nil) rather than silently absent.
@@ -50,15 +51,32 @@ module Hecks
50
51
  policies: many(:policies),
51
52
  process_managers: many(:process_managers),
52
53
  attaches_to: :attaches_to,
54
+ # A capability this chapter answers (`provides "authorization",
55
+ # grant: "RoleAssignment.Assign", ...`), one row per key, in the
56
+ # order written. Present (possibly empty) on every chapter, the
57
+ # same reading `attaches_to` beside it gives.
58
+ provides: -> { provides.map(&:to_h) },
53
59
  canonical_form: -> { Expression::CanonicalForm.table }
54
60
  )
55
61
 
62
+ # **One row of a declared capability** — `verb` is chapter-local
63
+ # ("RoleAssignment.Assign"); `Behaviour::Chapter#provided_verb`
64
+ # qualifies it with the chapter's own name.
65
+ Provision = Struct.new(:capability, :key, :verb, keyword_init: true) do
66
+ def self.from(row)
67
+ return row if row.is_a?(self)
68
+
69
+ fields = row.to_h.transform_keys(&:to_sym)
70
+ new(capability: fields[:capability].to_s, key: fields[:key].to_s, verb: fields[:verb].to_s)
71
+ end
72
+ end
73
+
56
74
  attr_reader :name, :version, :vision, :aggregates, :policies, :process_managers,
57
- :classification, :read_models, :ports, :formerly_known_as, :attaches_to
75
+ :classification, :read_models, :ports, :formerly_known_as, :attaches_to, :provides
58
76
 
59
77
  def initialize(name:, version: nil, vision: nil, aggregates: [], policies: [],
60
78
  process_managers: [], classification: nil, read_models: [], formerly_known_as: nil,
61
- attaches_to: [])
79
+ attaches_to: [], provides: [])
62
80
  @policies = policies
63
81
  @process_managers = process_managers
64
82
  @name = name.to_s
@@ -71,6 +89,7 @@ module Hecks
71
89
  @classification = classification&.to_s
72
90
  @formerly_known_as = formerly_known_as&.to_s
73
91
  @attaches_to = Array(attaches_to).map(&:to_s)
92
+ @provides = Array(provides).map { |row| Provision.from(row) }
74
93
  settle
75
94
  end
76
95
  end
@@ -12,12 +12,12 @@ module Hecks
12
12
 
13
13
  # `sign:` — item #5 of the whole-project table-unification survey.
14
14
  # `increment`/`decrement`'s own +1/-1 used to be re-derived from the
15
- # op NAME by two independent Rust codegen scripts (rust/project/
15
+ # op name by two independent Rust codegen scripts (rust/project/
16
16
  # mutations.rb, rust/codegen/src/mutations.rs — a ternary on
17
17
  # `op == "increment"` in each), even though the fact was already
18
18
  # table-driven on the Ruby runtime side
19
- # (Runtime::CommandRules::Arithmetic::MUTATION_OPS, held equal to
20
- # Vocabulary::MutationOp by spec/vocabulary_conformance_spec.rb).
19
+ # (Runtime::CommandRules::Arithmetic::MUTATION_OPS, itself read off
20
+ # the same generated Vocabulary::MutationOp table).
21
21
  # Reads `Vocabulary::MutationOp` directly (plain data, no framework
22
22
  # dependency — safe during parsing, same reason `RuleReference`'s
23
23
  # own bootstrap concerns don't apply here) rather than requiring
@@ -31,8 +31,8 @@ module Hecks
31
31
 
32
32
  emits_ir(target: :target, op: :op, sign: -> { Mutation.sign_for(op) })
33
33
 
34
- # THE ONE GENUINELY BRANCHING EMISSION in the model: an append (or a
35
- # DELEGATE — `CommandBuilder#delegates_to`'s own comment gives the
34
+ # The one genuinely branching emission in the model: an append (or a
35
+ # delegate — `CommandBuilder#delegates_to`'s own comment gives the
36
36
  # full reasoning for reusing this exact wire shape rather than
37
37
  # inventing a parallel one) binds several fields at once and carries
38
38
  # `fields:`, everything else carries a single `source:`. Declared
@@ -46,9 +46,9 @@ module Hecks
46
46
  end
47
47
  end
48
48
 
49
- # A command, as a RUBY CLASS.
49
+ # A command, as a Ruby class.
50
50
  #
51
- # NOT nested as a constant, and that is a finding rather than a shortcut. A
51
+ # Not nested as a constant, and that is a finding rather than a shortcut. A
52
52
  # command and a value object may legitimately share a name inside one
53
53
  # aggregate — the language does it six times, and means it: the command
54
54
  # `Argument` is the verb that appends to the `arguments` list whose element
@@ -56,10 +56,10 @@ module Hecks
56
56
  # So `Bluebook::Command::Argument` cannot be both, and a single constant
57
57
  # namespace cannot index a kind-ambiguous name. The same follows for
58
58
  # `hecks_fqn` : `Bluebook::Command.Argument` names both, which is why the judge's
59
- # ids only work per-category, each in its own repository. IDENTITY IS
60
- # (KIND, FQN), not fqn.
59
+ # ids only work per-category, each in its own repository. Identity is
60
+ # (kind, FQN), not fqn.
61
61
  #
62
- # It is a declaration holder anyway, because that is where the EDGES live.
62
+ # It is a declaration holder anyway, because that is where the edges live.
63
63
  # `acts_on` answers with the owning construct itself — the Aggregate,
64
64
  # or the entity holder for a piece's verb — rather than the name of one.
65
65
  # The invocation door (`pizza.add_topping`) is the facade's business, a
@@ -79,8 +79,8 @@ module Hecks
79
79
  ensures: -> { ensures.map { |rule| Expression::AstJson.rule_row(rule) } },
80
80
  mutations: many(:mutations),
81
81
  emits: :emits,
82
- # THE LIFECYCLE STATE THIS COMMAND IS ADMISSIBLE FROM (S10, ADR
83
- # 0025 — "lifecycle state becomes a command guard") — a GUARD,
82
+ # The lifecycle state this command is admissible from (S10, ADR
83
+ # 0025 — "lifecycle state becomes a command guard") — a guard,
84
84
  # not a transition: `command "Debit", from: "open"` replaces
85
85
  # `given("account is open") { status == "open" }`, checked
86
86
  # against the owning construct's own lifecycle field the same
@@ -2,8 +2,8 @@ require_relative "behaviour/domain_port"
2
2
 
3
3
  module Hecks
4
4
  module Bluebook
5
- # THE PRIMARY/DRIVING HALF OF HEXAGONAL ARCHITECTURE (Cockburn) — called
6
- # BY an adapter living outside the bluebook entirely, never by the
5
+ # The primary/driving half of hexagonal architecture (Cockburn) — called
6
+ # by an adapter living outside the bluebook entirely, never by the
7
7
  # domain calling out. That is already `Hecks.port` (persistence,
8
8
  # projection, extraction, loading) plus `Ports::*` : the secondary/
9
9
  # driven half, unchanged by this.
@@ -21,7 +21,7 @@ module Hecks
21
21
 
22
22
  attr_reader :hecks_name, :attributes, :emits, :direction, :answers, :refuses, :to
23
23
 
24
- # TWO DIRECTIONS THROUGH ONE DOOR.
24
+ # Two directions through one door.
25
25
  #
26
26
  # `:inbound` is what this class has always been — `tells`, spelled
27
27
  # `operation` before it had a twin: an external fact arriving, turned
@@ -29,7 +29,7 @@ module Hecks
29
29
  # channel back to whoever called.
30
30
  #
31
31
  # `:outbound` is `asks` — the domain wanting something from outside
32
- # and having to live with either answer. It names BOTH: `answers` for
32
+ # and having to live with either answer. It names both: `answers` for
33
33
  # what the adapter came back with, `refuses` for what it said instead.
34
34
  # Naming only the happy one would put the failure somewhere the model
35
35
  # cannot see, which is the whole reason a boundary is worth modelling.
@@ -48,15 +48,15 @@ module Hecks
48
48
  def inbound? = @direction == :inbound
49
49
 
50
50
  # No root reference of its own — unlike a command, every attribute
51
- # EQUALLY describes the payload, including whichever one identifies
51
+ # equally describes the payload, including whichever one identifies
52
52
  # the record its emitted event belongs to. Kept only so
53
53
  # CommandInterpreter::ArgumentGate's `reference_key` can ask for it
54
54
  # without learning this isn't a command.
55
55
 
56
- # `direction`/`answers`/`refuses` are deliberately OUTSIDE `emits_ir`'s
56
+ # `direction`/`answers`/`refuses` are deliberately outside `emits_ir`'s
57
57
  # declared shape and added here only for an outbound operation — an
58
58
  # ordinary inbound one (`tells`, still spelled `operation` everywhere
59
- # in the existing corpus) keeps the EXACT prior IR shape, byte for
59
+ # in the existing corpus) keeps the exact prior IR shape, byte for
60
60
  # byte. Pizzas' `PaymentGateway` port is inbound-only and is checked
61
61
  # against `hecks-parse`'s own Rust output for byte-identity
62
62
  # (parser_parity_spec.rb) — the Rust side has no notion of `asks` yet,
@@ -64,12 +64,12 @@ module Hecks
64
64
  # domain that never asked for the feature. Only a chapter that
65
65
  # actually declares `asks` (this extraction's own QualityControl
66
66
  # ledger, not yet in any Rust-parity corpus) pays for it.
67
- # `to` — SAME "deliberately outside emits_ir, merged in only when
67
+ # `to` — same "deliberately outside emits_ir, merged in only when
68
68
  # present" treatment as direction/answers/refuses just above, and
69
69
  # for the identical reason: an operation still spelled the old way
70
70
  # (`reference_to` inside the block, shadow-parsing only — see
71
71
  # reference_to_impl's own comment) or one that simply hasn't
72
- # migrated yet keeps the EXACT prior IR shape, byte for byte,
72
+ # migrated yet keeps the exact prior IR shape, byte for byte,
73
73
  # instead of an unconditional new key breaking parser_parity_spec
74
74
  # for every domain that never touched this.
75
75
  def to_h
@@ -10,22 +10,46 @@ module Hecks
10
10
 
11
11
  include WordGate
12
12
 
13
+ # @param name [String] the adapter's name, as written after `Hecks.adapter`
13
14
  def initialize(name)
14
15
  @name = name
15
16
  @fields = []
16
17
  @secrets = []
17
18
  end
18
19
 
20
+ # Names the port this adapter implements; a repeated call replaces the earlier name.
21
+ #
22
+ # @param value [String, Symbol] the port's name, such as `"CI"` or `"agent"`
23
+ # @return [String] the port name as stored
19
24
  def port(value) = @port = value.to_s
20
25
 
26
+ # Declares one plain setting a `.world` file may supply for this adapter.
27
+ #
28
+ # @param name [Symbol, String] the setting's name, such as `:database`
29
+ # @return [Array<Symbol>] every field declared so far, this one last
21
30
  def field(name) = @fields << name.to_sym
22
31
 
32
+ # Declares one setting whose value is a secret, such as an API token.
33
+ #
34
+ # @param name [Symbol, String] the secret's name, such as `:api_token`
35
+ # @return [Array<Symbol>] every secret declared so far, this one last
23
36
  def secret(name) = @secrets << name.to_sym
24
37
 
38
+ # Assembles the collected port, fields and secrets, judged by the adapter language.
39
+ #
40
+ # @return [Bluebook::Adapter] the adapter, returned once the language accepts it
41
+ # @raise [Bluebook::DSL::Malformed] if the adapter language refuses the declaration
25
42
  def build
26
43
  MetaValidator.call_adapter(Adapter.new(name: @name, port: @port, fields: @fields, secrets: @secrets))
27
44
  end
28
45
 
46
+ # Evaluates an `Hecks.adapter` block against a fresh builder and returns what it built.
47
+ #
48
+ # @param name [String] the adapter's name
49
+ # @yield the adapter body, evaluated with the builder as `self`; may be omitted
50
+ # @return [Bluebook::Adapter] the judged adapter
51
+ # @raise [Bluebook::DSL::Malformed] if the adapter language refuses the declaration, or
52
+ # the block uses a word the `Adapter` grammar does not admit
29
53
  def self.build(name, &block)
30
54
  builder = new(name)
31
55
  builder.instance_eval(&block) if block
@@ -2,17 +2,17 @@ module Hecks
2
2
  module Bluebook
3
3
  module DSL
4
4
  class AggregateBuilder
5
- # THE "SEAL_*" PASS — everything `#build` runs once every
5
+ # **The "SEAL_*" pass** — everything `#build` runs once every
6
6
  # declaration (attributes, entities, commands, queries, the
7
7
  # lifecycle) is otherwise in place, checking that what a command,
8
- # query, or default NAMES actually exists elsewhere on the
8
+ # query, or default names actually exists elsewhere on the
9
9
  # aggregate. Split out of aggregate_builder.rb (which keeps the
10
10
  # DSL surface itself — attribute/command/query/policy declaration
11
11
  # — and the smaller drain_pending!/identity bookkeeping) because
12
12
  # this cluster is one cohesive concern: cross-field validation
13
13
  # that can only run after every declaration is real, the same
14
14
  # relationship BluebookBuilder's own `self.validate_*` cluster has
15
- # to ITS chapter (see that file's own header for the parallel).
15
+ # to its chapter (see that file's own header for the parallel).
16
16
  # `include`d back into AggregateBuilder, same pattern as
17
17
  # `Runtime::Registry`'s own `include Verification` /
18
18
  # `include SagaPersistence` — same class, its private instance
@@ -23,10 +23,10 @@ module Hecks
23
23
  # Every reference is told which Aggregate declares it, so it can
24
24
  # find the chapter and resolve its target.
25
25
  #
26
- # Stamped HERE, at build, rather than at `reference_to`, because a command
26
+ # Stamped here, at build, rather than at `reference_to`, because a command
27
27
  # builder does not hold the aggregate and should not learn to. And
28
28
  # deliberately across every list that can carry one — a reference the walk
29
- # missed would resolve to nil, and `resolve_references` SKIPS a nil target,
29
+ # missed would resolve to nil, and `resolve_references` skips a nil target,
30
30
  # so the guarantee would go quiet instead of going red. That is the exact
31
31
  # shape of the bug that let an Account belong to an unregistered customer
32
32
  # fourteen times over.
@@ -34,8 +34,8 @@ module Hecks
34
34
  reference_bearing_attributes.each { |attribute| attribute.type.declared_in = aggregate }
35
35
  end
36
36
 
37
- # AN OWNED PIECE'S OWN `reference_to` IS AN EDGE THIS AGGREGATE
38
- # POINTS ACROSS TOO (S9, ADR 0025 — "entity/aggregate shared
37
+ # An owned piece's own `reference_to` is an edge this aggregate
38
+ # points across too (S9, ADR 0025 — "entity/aggregate shared
39
39
  # vocabulary") — a ring closing through a contained piece (Board
40
40
  # -> Board::Card -> Product -> Board) is the same "no boundary
41
41
  # anyone can reason about alone" `validate_no_bidirectional_
@@ -43,7 +43,7 @@ module Hecks
43
43
  # aggregate ring; it was invisible before this because only
44
44
  # `AggregateBuilder#reference_to` ever fed `@reference_targets`,
45
45
  # never `EntityBuilder#reference_to`. Command/query reference
46
- # ARGUMENTS are deliberately excluded — they are data flowing
46
+ # arguments are deliberately excluded — they are data flowing
47
47
  # through a dispatch, not persisted state the graph a cycle
48
48
  # means anything over.
49
49
  def entity_reference_targets
@@ -61,12 +61,12 @@ module Hecks
61
61
  lists.flatten.select(&:reference?)
62
62
  end
63
63
 
64
- # A mutation must name a field the aggregate actually HAS.
64
+ # A mutation must name a field the aggregate actually has.
65
65
  #
66
- # NOT moved to the language, and deliberately so. The language says only
66
+ # Not moved to the language, and deliberately so. The language says only
67
67
  # `given("a mutation names a target") { !target.value.to_s.empty? }` —
68
68
  # non-emptiness — because saying more means reaching a list that lives on
69
- # a DIFFERENT root : a command's changes hang off Command, the fields they
69
+ # a different root : a command's changes hang off Command, the fields they
70
70
  # name hang off Aggregate, and a given is a closed predicate over its own
71
71
  # state. Aggregate.Seal is the right shape and cannot see commands ; the
72
72
  # reference trick that rescued "attributes use value-object types" needs a
@@ -78,10 +78,10 @@ module Hecks
78
78
  # So it lives here, at build, where every declaration is present. Found by
79
79
  # writing `then_set :disputed_by` on CardPayment before the field existed :
80
80
  # it wrote into nothing, refused nothing, and every check stayed green.
81
- # A DEFAULT FILLS THE SHAPE IT IS DECLARED ON, or it fills nothing.
81
+ # A default fills the shape it is declared on, or it fills nothing.
82
82
  #
83
83
  # `attribute :cover, one_of("covered", "open"), default: "open"` builds
84
- # cleanly and then refuses EVERY create at dispatch — "cover is a Cover,
84
+ # cleanly and then refuses every create at dispatch — "cover is a Cover,
85
85
  # pass its fields as an object" — because the value object wants its
86
86
  # fields and got a bare string. The bluebook is wrong at the line where
87
87
  # it is written and says so nowhere near it.
@@ -91,12 +91,12 @@ module Hecks
91
91
  # consistency about nothing. `till.bluebook` has always had the right shape
92
92
  # — `default: { cents: 0 }`.
93
93
  #
94
- # A PRIMITIVE takes a scalar and a VALUE OBJECT takes its fields, so the
94
+ # A primitive takes a scalar and a value object takes its fields, so the
95
95
  # test is simply which one the type names. Nothing here guesses at the
96
96
  # keys: a default that is a Hash is left to `Value.for_attribute`, which
97
- # is where a wrong FIELD belongs.
97
+ # is where a wrong field belongs.
98
98
  def seal_defaults
99
- # `closed_sets` TOO, not only `@value_objects` — the exact gap
99
+ # `closed_sets` too, not only `@value_objects` — the exact gap
100
100
  # this method's own comment names: an inline `one_of(...)`
101
101
  # synthesises its value object through `closed_sets`
102
102
  # (AttributeCollector#synthesise_closed_set), never installed
@@ -120,7 +120,7 @@ module Hecks
120
120
  end
121
121
 
122
122
  # A command's `from:` guard needs a lifecycle field to check
123
- # against — declared at BUILD time (S10, ADR 0025), the same
123
+ # against — declared at build time (S10, ADR 0025), the same
124
124
  # point every other "does this actually resolve" check in this
125
125
  # file runs, rather than left to crash `enforce_lifecycle_
126
126
  # guard` the first time such a command is ever dispatched.
@@ -137,12 +137,12 @@ module Hecks
137
137
  end
138
138
  end
139
139
 
140
- # `projects`'s OWN half of "does this actually resolve" (S12,
141
- # ADR 0025) — the LOCAL half only: `reference` must name a real
140
+ # `projects`'s own half of "does this actually resolve" (S12,
141
+ # ADR 0025) — the local half only: `reference` must name a real
142
142
  # reference-typed attribute this aggregate declares, and
143
143
  # `name` must not collide with an attribute already declared
144
144
  # (a projected field is its own kind of field, never a second
145
- # spelling of one that already exists). The TARGET aggregate's
145
+ # spelling of one that already exists). The target aggregate's
146
146
  # own field is checked separately, once every aggregate in the
147
147
  # chapter is real — see BluebookBuilder#validate_projected_
148
148
  # fields!'s own comment for why that half cannot happen here.
@@ -173,23 +173,23 @@ module Hecks
173
173
  @commands.each do |command|
174
174
  command.mutations.each do |mutation|
175
175
  # `:delegate` — CommandBuilder#delegates_to's own comment —
176
- # targets no field of THIS aggregate at all; its `target`
176
+ # targets no field of this aggregate at all; its `target`
177
177
  # names an "Entity.Command" pair instead, checked when the
178
178
  # command builds (`delegates_to`'s own `rpartition` guard)
179
179
  # and again at dispatch time (`CommandInterpreter
180
180
  # #step_delegate_to_entity`, which refuses a real one that
181
- # names no such entity or command). Sealing THIS check
181
+ # names no such entity or command). Sealing this check
182
182
  # against it would refuse every delegating command outright.
183
183
  # `:corrects` — CommandBuilder#corrects_impl's own comment —
184
- # targets an EVENT name, not a field either; checked instead
184
+ # targets an event name, not a field either; checked instead
185
185
  # by `seal_correction_targets`, below.
186
186
  next if [:delegate, :corrects].include?(mutation.op)
187
187
 
188
188
  # C5.3 (docs/semantics/bluebook-semantics.md) — the
189
- # lifecycle field moves ONLY by transition; a `sets` on it
189
+ # lifecycle field moves only by transition; a `sets` on it
190
190
  # would be overwritten by any transition and bypass the
191
191
  # state machine otherwise. Refused at build — except for
192
- # FROZEN ERA TEXT (`MetaValidator.shadow_parsing?`), which
192
+ # frozen era text (`MetaValidator.shadow_parsing?`), which
193
193
  # is history and must keep parsing as the language tightens.
194
194
  if @lifecycle && mutation.target.to_sym == @lifecycle.field.to_sym && !MetaValidator.shadow_parsing?
195
195
  raise Malformed,
@@ -212,26 +212,26 @@ module Hecks
212
212
  # itself — a command cannot see its own siblings' `emits` while
213
213
  # it is still being built). Two things are checked:
214
214
  #
215
- # 1. The named event must be something a SIBLING command here
215
+ # 1. The named event must be something a sibling command here
216
216
  # actually `emits` — naming an event nothing in this aggregate
217
217
  # ever announces is a build-time authoring error. (Whether
218
- # THIS record has actually emitted it YET is the dispatch-time
218
+ # this record has actually emitted it yet is the dispatch-time
219
219
  # half — CommandRules::Admissibility#enforce_correction_target.)
220
220
  #
221
221
  # 2. `reverses: true` derives the corrective `sets` from the
222
- # ORIGINAL command's own mutations, rather than the author
222
+ # original command's own mutations, rather than the author
223
223
  # writing them — but only when every one of those mutations is
224
- # STRUCTURALLY invertible with no runtime data: increment/
224
+ # structurally invertible with no runtime data: increment/
225
225
  # decrement, same argument, opposite verb (`sign_for`'s own
226
226
  # +1/-1 pair — CommandRules::Arithmetic applies `current +
227
- # sign * amount`, so the SAME source with the OPPOSITE sign
227
+ # sign * amount`, so the same source with the opposite sign
228
228
  # undoes it exactly). Nothing else qualifies today: `set` has
229
- # no such rule at all — inverting it needs the SPECIFIC prior
229
+ # no such rule at all — inverting it needs the specific prior
230
230
  # value at the moment the original fired, which is per-
231
231
  # instance runtime data no build-time derivation can have;
232
232
  # `multiply`/`clamp` are lossy by design (a clamped value's
233
233
  # own pre-clamp magnitude is not recoverable from the mutation
234
- # at all); `append`/`remove` LOOK symmetric but are not
234
+ # at all); `append`/`remove` look symmetric but are not
235
235
  # reliably so — `append`'s source is a per-field binding hash
236
236
  # (`append: { name: :name, amount: :amount }`), `remove`'s is
237
237
  # a single resolved value to match by equality
@@ -243,9 +243,9 @@ module Hecks
243
243
  # — see docs/decisions/ for the ADR that draws this exact
244
244
  # line.
245
245
  # One closed cluster of `corrects`/`reverses: true` rules, run
246
- # in sequence against ONE command at a time (emission exists,
246
+ # in sequence against one command at a time (emission exists,
247
247
  # reverses/own-sets conflict, invertibility, then the actual
248
- # derivation) — each `raise` gates the next check for THAT
248
+ # derivation) — each `raise` gates the next check for that
249
249
  # command, and `inverse_op`/`emitted_by` are shared read-only
250
250
  # lookups built once up front. Splitting the per-command body
251
251
  # out would still need all of `command`/`event`/`sources`/
@@ -299,11 +299,11 @@ module Hecks
299
299
  end
300
300
  end
301
301
 
302
- # A query must ask about a field the aggregate actually HAS — the same
302
+ # A query must ask about a field the aggregate actually has — the same
303
303
  # seal `then_set` gets, closing the same silence: a where over a field
304
304
  # nothing declares matches nothing and refuses nothing, forever, on
305
305
  # every adapter. Three more silences close with it. A dotted path may
306
- # reach through the value-object graph but must LAND on a scalar
306
+ # reach through the value-object graph but must land on a scalar
307
307
  # member (QuerySpecification::FieldPath is the one walk every engine
308
308
  # now shares) — landing on a value object hands SQL a JSON object
309
309
  # where the reference interpreter unwraps a hash. An ordered
@@ -339,13 +339,13 @@ module Hecks
339
339
  @entities.map { |entity| ["#{@name}::#{entity.hecks_name}", entity.attributes, entity.lifecycle, entity.queries] }
340
340
  end
341
341
 
342
- # `/` CROSSES INTO ANOTHER RECORD, `.` WALKS FIELDS INSIDE THIS
343
- # ONE (ADR 0025, "References") — the operator answers which
342
+ # `/` crosses into another record, `.` walks fields inside this
343
+ # one (ADR 0025, "References") — the operator answers which
344
344
  # kind of path this is now, not a name collision to arbitrate,
345
345
  # so a hop is routed to its own method before any `.`-splitting
346
346
  # runs at all; `seal_query_hop` below never sees a field this
347
347
  # one would also have tried to resolve as a local dotted walk.
348
- # A closed decision tree over where ONE field can resolve —
348
+ # A closed decision tree over where one field can resolve —
349
349
  # hop, local scalar, lifecycle field, value object (refused),
350
350
  # or nothing (refused) — see the doc comment above (and the
351
351
  # method-level comments on the hop/ordering split) for why each
@@ -378,18 +378,18 @@ module Hecks
378
378
  "matches nothing and refuses nothing"
379
379
  end
380
380
 
381
- # ORDER BY refuses a hop OUTRIGHT, right here — unlike a WHERE
381
+ # ORDER BY refuses a hop outright, right here — unlike a WHERE
382
382
  # hop (deferred below), this doesn't need the target's shape to
383
383
  # answer: an ask is ordered by what its own answering rows
384
384
  # hold, and a hop answers with a candidate set, not a sort key
385
385
  # (see Runtime::ReferenceHop).
386
386
  #
387
- # A WHERE hop is only RECOGNISED here, and CHECKED LATER. The
387
+ # A where hop is only recognised here, and checked later. The
388
388
  # head names one of this aggregate's own references, which is
389
389
  # answerable now — a Reference knows its own target_name at
390
- # declaration. What it points AT is not: stamp_references has
390
+ # declaration. What it points at is not: stamp_references has
391
391
  # already run by this point, but the chapter (Bluebook, and the
392
- # owning aggregate's OWN place in it) does not exist yet, so
392
+ # owning aggregate's own place in it) does not exist yet, so
393
393
  # Reference#resolve would answer nil for every target in the
394
394
  # file, including ones declared above this one. The tail, and
395
395
  # whether the target even exists, are BluebookBuilder's
@@ -416,14 +416,14 @@ module Hecks
416
416
  def seal_ordered_comparator(owner, query, fields, clause)
417
417
  return unless ORDERED_COMPARATORS.include?(clause.op.to_s.to_sym)
418
418
 
419
- # A WHERE clause hopping through a reference with an ordered
419
+ # A where clause hopping through a reference with an ordered
420
420
  # comparator is legitimate ("client whose balance > 500") —
421
421
  # unlike ORDER BY (refused outright in seal_query_field, see
422
422
  # its own comment), a where-clause hop answers a real
423
423
  # candidate set either way, ordered or not. Deferred for the
424
424
  # same reason any other hop is: whether the tail is even
425
425
  # numeric is BluebookBuilder#validate_query_hops!'s question
426
- # to ask of the TARGET's shape, not this aggregate's own.
426
+ # to ask of the target's shape, not this aggregate's own.
427
427
  return if clause.field.to_s.include?("/") && QuerySpecification::HopPath.hop_head?(clause.field, fields)
428
428
 
429
429
  name, *nested = clause.field.to_s.split(".")
@@ -473,17 +473,17 @@ module Hecks
473
473
  query.attributes << leaf if leaf
474
474
  end
475
475
 
476
- # A BARE FIELD NAMING A VALUE OBJECT HAS TO SAY WHICH MEMBER IT
477
- # MEANS, when more than one could answer. The dotted case above
476
+ # A bare field naming a value object has to say which member it
477
+ # means, when more than one could answer. The dotted case above
478
478
  # already refuses a path that lands on a value object rather than
479
479
  # a scalar; a bare name was returning unconditionally, so
480
480
  # `where(frequency: ...)` against a StatementFrequency
481
481
  # (cadence, retention_months, paper_fee_cents) compiled — and the
482
482
  # engines then disagreed about which member it meant, one taking
483
- # the FIRST numeric and another declining to unwrap at all.
483
+ # the first numeric and another declining to unwrap at all.
484
484
  #
485
485
  # Unambiguous is: exactly one member, whatever its type, or
486
- # exactly one NUMERIC member among several (Money's `cents`
486
+ # exactly one numeric member among several (Money's `cents`
487
487
  # beside its `currency` — the reading every engine already
488
488
  # shared, and what the corpus relies on). Anything else names
489
489
  # its member with a dotted path, which already works.