hecks 1.3.0 → 1.5.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 (373) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hecks/adapters/driven/claude_code.rb +72 -7
  3. data/lib/hecks/adapters/driven/d1.rb +187 -23
  4. data/lib/hecks/adapters/driven/folder.rb +83 -10
  5. data/lib/hecks/adapters/driven/google_authentication.rb +33 -12
  6. data/lib/hecks/adapters/driven/governance_authorization.rb +87 -18
  7. data/lib/hecks/adapters/driven/heki/journal.rb +13 -4
  8. data/lib/hecks/adapters/driven/heki/saga_store.rb +56 -10
  9. data/lib/hecks/adapters/driven/heki/snapshot.rb +1 -1
  10. data/lib/hecks/adapters/driven/heki.rb +106 -9
  11. data/lib/hecks/adapters/driven/identity_registry.rb +12 -2
  12. data/lib/hecks/adapters/driven/in_memory_ordering.rb +25 -3
  13. data/lib/hecks/adapters/driven/in_process_key_vault.adapter +3 -0
  14. data/lib/hecks/adapters/driven/in_process_key_vault.rb +53 -0
  15. data/lib/hecks/adapters/driven/lambda/client.rb +67 -14
  16. data/lib/hecks/adapters/driven/lambda.rb +82 -35
  17. data/lib/hecks/adapters/driven/local_storage.rb +83 -10
  18. data/lib/hecks/adapters/driven/memory.rb +205 -9
  19. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +21 -1
  20. data/lib/hecks/adapters/driven/postgres/codec.rb +27 -11
  21. data/lib/hecks/adapters/driven/postgres/outbox.rb +40 -2
  22. data/lib/hecks/adapters/driven/postgres/reconnect.rb +23 -7
  23. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +14 -14
  24. data/lib/hecks/adapters/driven/postgres.rb +175 -28
  25. data/lib/hecks/adapters/driven/prism.rb +50 -11
  26. data/lib/hecks/adapters/driven/secure_random_identity.rb +3 -0
  27. data/lib/hecks/adapters/driven/sql_query_builder.rb +34 -22
  28. data/lib/hecks/adapters/driven/sqlite/codec.rb +38 -10
  29. data/lib/hecks/adapters/driven/sqlite/projection.rb +60 -32
  30. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +12 -12
  31. data/lib/hecks/adapters/driven/sqlite.rb +181 -21
  32. data/lib/hecks/adapters/driven/system_clock.rb +3 -0
  33. data/lib/hecks/adapters/driven/tenant_provisioner.adapter +3 -0
  34. data/lib/hecks/adapters/driven/tenant_provisioner.rb +66 -0
  35. data/lib/hecks/adapters/driven.rb +6 -4
  36. data/lib/hecks/adapters/driving/github_webhook.rb +31 -18
  37. data/lib/hecks/behaviors/dsl.rb +60 -2
  38. data/lib/hecks/behaviors/expectations.rb +190 -29
  39. data/lib/hecks/behaviors/ir.rb +12 -1
  40. data/lib/hecks/behaviors/rspec.rb +9 -1
  41. data/lib/hecks/behaviors/runner.rb +21 -2
  42. data/lib/hecks/behaviors.rb +9 -1
  43. data/lib/hecks/bluebook/aggregate.rb +43 -13
  44. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +17 -10
  45. data/lib/hecks/bluebook/assembly/build.rb +26 -5
  46. data/lib/hecks/bluebook/assembly/contract.rb +98 -23
  47. data/lib/hecks/bluebook/assembly/contracts.rb +59 -52
  48. data/lib/hecks/bluebook/assembly/marks.rb +159 -30
  49. data/lib/hecks/bluebook/assembly/specializer.rb +38 -21
  50. data/lib/hecks/bluebook/assembly.rb +32 -14
  51. data/lib/hecks/bluebook/attribute.rb +26 -12
  52. data/lib/hecks/bluebook/behaviour/aggregate.rb +43 -11
  53. data/lib/hecks/bluebook/behaviour/attribute.rb +18 -5
  54. data/lib/hecks/bluebook/behaviour/chapter.rb +76 -5
  55. data/lib/hecks/bluebook/behaviour/command.rb +55 -25
  56. data/lib/hecks/bluebook/behaviour/domain_port.rb +27 -7
  57. data/lib/hecks/bluebook/behaviour/entity.rb +20 -8
  58. data/lib/hecks/bluebook/behaviour/hexagon.rb +30 -4
  59. data/lib/hecks/bluebook/behaviour/lifecycle.rb +27 -6
  60. data/lib/hecks/bluebook/behaviour/policy.rb +42 -17
  61. data/lib/hecks/bluebook/behaviour/process_manager.rb +39 -8
  62. data/lib/hecks/bluebook/behaviour/query.rb +6 -1
  63. data/lib/hecks/bluebook/behaviour/read_model.rb +29 -8
  64. data/lib/hecks/bluebook/behaviour/traits.rb +48 -12
  65. data/lib/hecks/bluebook/behaviour/value_object.rb +21 -9
  66. data/lib/hecks/bluebook/capabilities.rb +27 -0
  67. data/lib/hecks/bluebook/chapter.rb +51 -9
  68. data/lib/hecks/bluebook/command.rb +62 -17
  69. data/lib/hecks/bluebook/domain_port.rb +34 -9
  70. data/lib/hecks/bluebook/dsl/adapter_builder.rb +24 -0
  71. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +49 -49
  72. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +282 -123
  73. data/lib/hecks/bluebook/dsl/attribute_collector.rb +112 -75
  74. data/lib/hecks/bluebook/dsl/binding_proxy.rb +81 -2
  75. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +486 -117
  76. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +179 -47
  77. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +116 -0
  78. data/lib/hecks/bluebook/dsl/command_builder.rb +284 -122
  79. data/lib/hecks/bluebook/dsl/const_shim.rb +46 -15
  80. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +90 -25
  81. data/lib/hecks/bluebook/dsl/entity_builder.rb +191 -61
  82. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +148 -132
  83. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +130 -30
  84. data/lib/hecks/bluebook/dsl/identity_declaration.rb +38 -21
  85. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +27 -4
  86. data/lib/hecks/bluebook/dsl/policy_builder.rb +86 -36
  87. data/lib/hecks/bluebook/dsl/port_builder.rb +38 -7
  88. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +56 -22
  89. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +111 -47
  90. data/lib/hecks/bluebook/dsl/query_builder.rb +37 -8
  91. data/lib/hecks/bluebook/dsl/read_model_builder.rb +127 -52
  92. data/lib/hecks/bluebook/dsl/rule_reference.rb +97 -43
  93. data/lib/hecks/bluebook/dsl/translation_builder.rb +150 -44
  94. data/lib/hecks/bluebook/dsl/value_object_builder.rb +68 -20
  95. data/lib/hecks/bluebook/dsl/word_gate.rb +59 -53
  96. data/lib/hecks/bluebook/dsl/world_builder.rb +51 -8
  97. data/lib/hecks/bluebook/entity.rb +40 -11
  98. data/lib/hecks/bluebook/expression/ast_json.rb +128 -36
  99. data/lib/hecks/bluebook/expression/ast_reader.rb +32 -3
  100. data/lib/hecks/bluebook/expression/canonical_form.rb +55 -16
  101. data/lib/hecks/bluebook/expression/evaluator.rb +221 -43
  102. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +54 -18
  103. data/lib/hecks/bluebook/expression/resolver.rb +369 -128
  104. data/lib/hecks/bluebook/hexagon.rb +35 -1
  105. data/lib/hecks/bluebook/lifecycle.rb +12 -1
  106. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +2 -1
  107. data/lib/hecks/bluebook/meta_validator/judge.rb +126 -108
  108. data/lib/hecks/bluebook/meta_validator/plan.rb +81 -46
  109. data/lib/hecks/bluebook/meta_validator/port_judge.rb +3 -2
  110. data/lib/hecks/bluebook/meta_validator/readings.rb +200 -50
  111. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +68 -41
  112. data/lib/hecks/bluebook/meta_validator/shapes.rb +166 -21
  113. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +286 -46
  114. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +11 -10
  115. data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -5
  116. data/lib/hecks/bluebook/meta_validator.rb +235 -139
  117. data/lib/hecks/bluebook/model_check.rb +434 -104
  118. data/lib/hecks/bluebook/pattern_subset.rb +32 -10
  119. data/lib/hecks/bluebook/policy.rb +15 -13
  120. data/lib/hecks/bluebook/process_manager.rb +27 -14
  121. data/lib/hecks/bluebook/project_discovery.rb +5 -0
  122. data/lib/hecks/bluebook/project_loader.rb +40 -0
  123. data/lib/hecks/bluebook/project_register.rb +50 -6
  124. data/lib/hecks/bluebook/query.rb +31 -4
  125. data/lib/hecks/bluebook/read_model.rb +35 -15
  126. data/lib/hecks/bluebook/reference.rb +26 -13
  127. data/lib/hecks/bluebook/smoke_test.rb +46 -23
  128. data/lib/hecks/bluebook/synthesizer.rb +46 -12
  129. data/lib/hecks/bluebook/translation.rb +34 -5
  130. data/lib/hecks/bluebook/value_object.rb +29 -11
  131. data/lib/hecks/bluebook.rb +5 -6
  132. data/lib/hecks/codemod.rb +138 -50
  133. data/lib/hecks/construct.rb +21 -7
  134. data/lib/hecks/corpus.rb +438 -0
  135. data/lib/hecks/deploy/bluebook/deploy.hecksagon +19 -0
  136. data/lib/hecks/doc/reference.rb +200 -31
  137. data/lib/hecks/embryonaut_bluebook.rb +38 -15
  138. data/lib/hecks/facade/cli_door.rb +69 -10
  139. data/lib/hecks/facade/cli_runner.rb +105 -24
  140. data/lib/hecks/facade/command_request.rb +23 -0
  141. data/lib/hecks/facade/handle.rb +155 -35
  142. data/lib/hecks/facade/json_door.rb +106 -25
  143. data/lib/hecks/facade/surface/aggregate_door.rb +50 -27
  144. data/lib/hecks/facade/surface/chapter.rb +26 -17
  145. data/lib/hecks/facade/surface.rb +16 -3
  146. data/lib/hecks/facade.rb +15 -4
  147. data/lib/hecks/forms/app.rb +46 -30
  148. data/lib/hecks/forms/command_form_renderer.rb +70 -9
  149. data/lib/hecks/forms/field_renderer.rb +142 -6
  150. data/lib/hecks/forms/field_shape.rb +183 -19
  151. data/lib/hecks/forms/html.rb +51 -7
  152. data/lib/hecks/forms/index_renderer.rb +14 -2
  153. data/lib/hecks/forms/page.rb +14 -0
  154. data/lib/hecks/forms/params.rb +120 -23
  155. data/lib/hecks/forms/port_argument.rb +14 -2
  156. data/lib/hecks/forms/query_form_renderer.rb +65 -2
  157. data/lib/hecks/forms/record_renderer.rb +60 -2
  158. data/lib/hecks/forms/record_table.rb +28 -1
  159. data/lib/hecks/forms/reference_options.rb +24 -0
  160. data/lib/hecks/forms/value_object_shape.rb +13 -3
  161. data/lib/hecks/forms.rb +24 -4
  162. data/lib/hecks/fqn.rb +59 -1
  163. data/lib/hecks/framework/bluebook/governance.bluebook +9 -0
  164. data/lib/hecks/framework/bluebook/privacy.bluebook +155 -0
  165. data/lib/hecks/framework/oidc.json +15 -0
  166. data/lib/hecks/framework.rb +79 -25
  167. data/lib/hecks/freezer.rb +27 -11
  168. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +241 -106
  169. data/lib/hecks/fuzzing/combination_miner.rb +178 -0
  170. data/lib/hecks/fuzzing/concurrent_dispatch.rb +241 -45
  171. data/lib/hecks/fuzzing/coverage_campaign.rb +161 -0
  172. data/lib/hecks/fuzzing/differential.rb +192 -0
  173. data/lib/hecks/fuzzing/domain_generator.rb +871 -0
  174. data/lib/hecks/fuzzing/era_boundary.rb +68 -19
  175. data/lib/hecks/fuzzing/form_census.rb +121 -20
  176. data/lib/hecks/fuzzing/generated_domain_check.rb +171 -0
  177. data/lib/hecks/fuzzing/invalid_value_generator.rb +45 -6
  178. data/lib/hecks/fuzzing/isolated_boot.rb +137 -80
  179. data/lib/hecks/fuzzing/nondeterministic.rb +79 -0
  180. data/lib/hecks/fuzzing/persistence_parity.rb +111 -21
  181. data/lib/hecks/fuzzing/properties/corrections.rb +34 -9
  182. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +300 -51
  183. data/lib/hecks/fuzzing/properties/guards.rb +86 -42
  184. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +80 -32
  185. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +40 -35
  186. data/lib/hecks/fuzzing/properties/outbox.rb +70 -32
  187. data/lib/hecks/fuzzing/properties/querying.rb +82 -28
  188. data/lib/hecks/fuzzing/properties.rb +84 -51
  189. data/lib/hecks/fuzzing/qa_settings.rb +164 -0
  190. data/lib/hecks/fuzzing/replay.rb +241 -133
  191. data/lib/hecks/fuzzing/rotation_priority.rb +48 -28
  192. data/lib/hecks/fuzzing/rust_gap_manifest.rb +139 -0
  193. data/lib/hecks/fuzzing/self_consistency.rb +315 -137
  194. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +46 -40
  195. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +18 -11
  196. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +13 -12
  197. data/lib/hecks/fuzzing/sequence_generator/picker.rb +21 -12
  198. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +59 -32
  199. data/lib/hecks/fuzzing/sequence_generator.rb +158 -23
  200. data/lib/hecks/fuzzing/shrinker.rb +309 -0
  201. data/lib/hecks/fuzzing/structural_skips.rb +37 -130
  202. data/lib/hecks/fuzzing/sweep_depth.rb +12 -4
  203. data/lib/hecks/fuzzing/target_capabilities.rb +107 -29
  204. data/lib/hecks/fuzzing/value_generator.rb +110 -22
  205. data/lib/hecks/fuzzing.rb +5 -0
  206. data/lib/hecks/grammar/evolve.rb +188 -12
  207. data/lib/hecks/grammar.rb +53 -7
  208. data/lib/hecks/ir.rb +51 -20
  209. data/lib/hecks/language/bluebook/bluebook.bluebook +41 -0
  210. data/lib/hecks/language/bluebook/policy.bluebook +11 -1
  211. data/lib/hecks/language/bluebook/vocabulary.bluebook +348 -13
  212. data/lib/hecks/language/hecksagon/hecksagon.bluebook +11 -0
  213. data/lib/hecks/language/oidc.json +5 -0
  214. data/lib/hecks/literal.rb +41 -9
  215. data/lib/hecks/naming.rb +112 -31
  216. data/lib/hecks/ports/access_control.rb +53 -2
  217. data/lib/hecks/ports/agent/answers.rb +83 -6
  218. data/lib/hecks/ports/agent.rb +119 -35
  219. data/lib/hecks/ports/authentication.rb +44 -4
  220. data/lib/hecks/ports/authorization.rb +50 -11
  221. data/lib/hecks/ports/clock.rb +42 -23
  222. data/lib/hecks/ports/extraction.rb +16 -0
  223. data/lib/hecks/ports/identity_assignment.rb +23 -2
  224. data/lib/hecks/ports/identity_generation.rb +17 -3
  225. data/lib/hecks/ports/identity_resolution.rb +17 -1
  226. data/lib/hecks/ports/key_vault.port +6 -0
  227. data/lib/hecks/ports/key_vault.rb +58 -0
  228. data/lib/hecks/ports/loading.rb +4 -0
  229. data/lib/hecks/ports/persistence/append_only.rb +172 -8
  230. data/lib/hecks/ports/persistence/binding_policy.rb +34 -0
  231. data/lib/hecks/ports/persistence/codec_boundary.rb +178 -0
  232. data/lib/hecks/ports/persistence/execution.rb +4 -0
  233. data/lib/hecks/ports/persistence/null_saga_store.rb +12 -1
  234. data/lib/hecks/ports/persistence/plugin.rb +42 -4
  235. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +218 -25
  236. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +77 -9
  237. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +81 -24
  238. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +29 -18
  239. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +144 -60
  240. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +103 -8
  241. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +98 -23
  242. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +282 -109
  243. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +63 -25
  244. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +118 -66
  245. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +51 -28
  246. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +34 -5
  247. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +25 -12
  248. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +129 -34
  249. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +51 -6
  250. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +33 -9
  251. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +16 -0
  252. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +95 -6
  253. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +25 -2
  254. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +314 -90
  255. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +68 -10
  256. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +9 -3
  257. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +9 -2
  258. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +48 -8
  259. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -1
  260. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +36 -5
  261. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +23 -3
  262. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +58 -19
  263. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +96 -5
  264. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +15 -0
  265. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +9 -1
  266. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -2
  267. data/lib/hecks/ports/persistence/plugins/era.rb +12 -2
  268. data/lib/hecks/ports/persistence/remote_runtime.rb +9 -2
  269. data/lib/hecks/ports/persistence/repository_factory.rb +23 -3
  270. data/lib/hecks/ports/persistence/state_codec.rb +319 -0
  271. data/lib/hecks/ports/persistence.rb +36 -1
  272. data/lib/hecks/ports/projection.rb +61 -7
  273. data/lib/hecks/ports/query/in_memory.rb +41 -8
  274. data/lib/hecks/ports/query/ordering.rb +21 -6
  275. data/lib/hecks/ports/query.rb +35 -0
  276. data/lib/hecks/ports.rb +1 -0
  277. data/lib/hecks/projections/bootstrap_table.rb +147 -0
  278. data/lib/hecks/projections/diagrams.rb +315 -79
  279. data/lib/hecks/projections/glossary/html.rb +91 -3
  280. data/lib/hecks/projections/glossary/markdown.rb +50 -3
  281. data/lib/hecks/projections/glossary/mermaid.rb +49 -1
  282. data/lib/hecks/projections/glossary/sections.rb +1 -1
  283. data/lib/hecks/projections/glossary/sentences.rb +110 -5
  284. data/lib/hecks/projections/glossary.rb +173 -31
  285. data/lib/hecks/projections/ir.rb +1 -1
  286. data/lib/hecks/projections/model/deviations.rb +62 -17
  287. data/lib/hecks/projections/model.rb +75 -21
  288. data/lib/hecks/projections/oidc.rb +45 -8
  289. data/lib/hecks/projections/parser_table.rb +53 -12
  290. data/lib/hecks/projections/reference.rb +15 -3
  291. data/lib/hecks/projections/rust_vocabulary.rb +646 -0
  292. data/lib/hecks/projections/shape.rb +10 -2
  293. data/lib/hecks/projections/statements.rb +69 -22
  294. data/lib/hecks/projections/vocabulary.rb +26 -9
  295. data/lib/hecks/projections.rb +5 -3
  296. data/lib/hecks/projector/cli_projector.rb +245 -37
  297. data/lib/hecks/projector/docs_projector.rb +154 -28
  298. data/lib/hecks/projector/exporter.rb +104 -29
  299. data/lib/hecks/projector/ir_projector.rb +7 -1
  300. data/lib/hecks/projector/narrate_projector.rb +144 -23
  301. data/lib/hecks/projector/target.rb +42 -18
  302. data/lib/hecks/projector.rb +86 -18
  303. data/lib/hecks/query_ir.rb +94 -47
  304. data/lib/hecks/query_specification/common/comparators.rb +19 -3
  305. data/lib/hecks/query_specification/common/comparison.rb +109 -27
  306. data/lib/hecks/query_specification/common/dsl.rb +65 -9
  307. data/lib/hecks/query_specification/common/null_policy.rb +61 -15
  308. data/lib/hecks/query_specification/common/null_semantics.rb +4 -0
  309. data/lib/hecks/query_specification/common/options.rb +25 -0
  310. data/lib/hecks/query_specification/field_path.rb +69 -15
  311. data/lib/hecks/query_specification/hop_path.rb +57 -20
  312. data/lib/hecks/query_specification/read_model/specification.rb +4 -0
  313. data/lib/hecks/rendering.rb +9 -3
  314. data/lib/hecks/router/namespace_installer.rb +16 -3
  315. data/lib/hecks/router.rb +56 -1
  316. data/lib/hecks/runtime/aggregate_lock.rb +20 -11
  317. data/lib/hecks/runtime/boot_gates.rb +21 -3
  318. data/lib/hecks/runtime/caller.rb +40 -8
  319. data/lib/hecks/runtime/capability_graph.rb +13 -2
  320. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +40 -41
  321. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +45 -67
  322. data/lib/hecks/runtime/command_interpreter.rb +195 -113
  323. data/lib/hecks/runtime/command_rules/admissibility.rb +231 -80
  324. data/lib/hecks/runtime/command_rules/arithmetic.rb +154 -96
  325. data/lib/hecks/runtime/command_rules/authorization.rb +38 -17
  326. data/lib/hecks/runtime/command_rules/emission.rb +18 -1
  327. data/lib/hecks/runtime/command_rules/references.rb +145 -55
  328. data/lib/hecks/runtime/command_rules.rb +3 -0
  329. data/lib/hecks/runtime/dependency_planning.rb +56 -11
  330. data/lib/hecks/runtime/dispatcher.rb +263 -92
  331. data/lib/hecks/runtime/entity_element.rb +304 -67
  332. data/lib/hecks/runtime/entity_interpreter.rb +149 -88
  333. data/lib/hecks/runtime/errors.rb +37 -23
  334. data/lib/hecks/runtime/event.rb +15 -10
  335. data/lib/hecks/runtime/identity.rb +91 -23
  336. data/lib/hecks/runtime/instance.rb +103 -18
  337. data/lib/hecks/runtime/interpreting.rb +24 -16
  338. data/lib/hecks/runtime/invocation.rb +358 -0
  339. data/lib/hecks/runtime/loader.rb +105 -19
  340. data/lib/hecks/runtime/outbox.rb +164 -26
  341. data/lib/hecks/runtime/policy_interpreter.rb +73 -60
  342. data/lib/hecks/runtime/port_operation_interpreter.rb +42 -19
  343. data/lib/hecks/runtime/query_interpreter.rb +93 -74
  344. data/lib/hecks/runtime/reaction_invocation.rb +73 -28
  345. data/lib/hecks/runtime/read_model_interpreter.rb +60 -44
  346. data/lib/hecks/runtime/rebuild_sweep.rb +32 -4
  347. data/lib/hecks/runtime/reference_hop.rb +48 -6
  348. data/lib/hecks/runtime/refusal_wording.rb +142 -115
  349. data/lib/hecks/runtime/registry/saga_persistence.rb +32 -21
  350. data/lib/hecks/runtime/registry/verification.rb +153 -28
  351. data/lib/hecks/runtime/registry.rb +202 -32
  352. data/lib/hecks/runtime/remote_dispatcher.rb +125 -24
  353. data/lib/hecks/runtime/routing.rb +36 -154
  354. data/lib/hecks/runtime/saga_interpreter/correlation.rb +25 -27
  355. data/lib/hecks/runtime/saga_interpreter.rb +90 -76
  356. data/lib/hecks/runtime/saga_pending_dispatch.rb +12 -12
  357. data/lib/hecks/runtime/tenant_check.rb +33 -13
  358. data/lib/hecks/runtime/tenant_scope.rb +23 -5
  359. data/lib/hecks/runtime/value/admission.rb +75 -30
  360. data/lib/hecks/runtime/value/coercion.rb +555 -142
  361. data/lib/hecks/runtime/value/entity_list_coercion.rb +132 -60
  362. data/lib/hecks/runtime/value.rb +71 -21
  363. data/lib/hecks/runtime.rb +39 -7
  364. data/lib/hecks/storehouse.rb +368 -72
  365. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +130 -0
  366. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +32 -0
  367. data/lib/hecks/version.rb +3 -3
  368. data/lib/hecks/vocabulary.rb +205 -4
  369. data/lib/hecks.rb +91 -11
  370. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +19 -11
  371. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +24 -12
  372. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +38 -14
  373. metadata +28 -2
@@ -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,10 +29,23 @@ 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.
36
+ #
37
+ # @param name [String, Symbol] the operation's declared name
38
+ # @param attributes [Array<Bluebook::Attribute>] the operation's declared payload
39
+ # fields
40
+ # @param emits [Array<String>] the events an inbound operation declares it records
41
+ # @param direction [Symbol, String] `:inbound` for a `tells`/`operation`, `:outbound`
42
+ # for an `asks`
43
+ # @param answers [String, nil] an outbound operation's declared event for what the
44
+ # adapter came back with
45
+ # @param refuses [String, nil] an outbound operation's declared event for what the
46
+ # adapter said instead
47
+ # @param to [String, nil] the aggregate this operation routes to, or `nil` if it
48
+ # declares no routing target
36
49
  def initialize(name:, attributes: [], emits: [], direction: :inbound, answers: nil, refuses: nil, to: nil)
37
50
  @hecks_name = name.to_s
38
51
  @attributes = attributes
@@ -44,19 +57,26 @@ module Hecks
44
57
  @attributes_by_name = attributes.to_h { |attribute| [attribute.name, attribute] }
45
58
  end
46
59
 
60
+ # Says whether this operation is the domain asking something of an adapter.
61
+ #
62
+ # @return [Boolean] whether this operation is an `asks`
47
63
  def outbound? = @direction == :outbound
64
+
65
+ # Says whether this operation is an adapter telling the domain something.
66
+ #
67
+ # @return [Boolean] whether this operation is a `tells`/`operation`
48
68
  def inbound? = @direction == :inbound
49
69
 
50
70
  # No root reference of its own — unlike a command, every attribute
51
- # EQUALLY describes the payload, including whichever one identifies
71
+ # equally describes the payload, including whichever one identifies
52
72
  # the record its emitted event belongs to. Kept only so
53
73
  # CommandInterpreter::ArgumentGate's `reference_key` can ask for it
54
74
  # without learning this isn't a command.
55
75
 
56
- # `direction`/`answers`/`refuses` are deliberately OUTSIDE `emits_ir`'s
76
+ # `direction`/`answers`/`refuses` are deliberately outside `emits_ir`'s
57
77
  # declared shape and added here only for an outbound operation — an
58
78
  # ordinary inbound one (`tells`, still spelled `operation` everywhere
59
- # in the existing corpus) keeps the EXACT prior IR shape, byte for
79
+ # in the existing corpus) keeps the exact prior IR shape, byte for
60
80
  # byte. Pizzas' `PaymentGateway` port is inbound-only and is checked
61
81
  # against `hecks-parse`'s own Rust output for byte-identity
62
82
  # (parser_parity_spec.rb) — the Rust side has no notion of `asks` yet,
@@ -64,14 +84,17 @@ module Hecks
64
84
  # domain that never asked for the feature. Only a chapter that
65
85
  # actually declares `asks` (this extraction's own QualityControl
66
86
  # ledger, not yet in any Rust-parity corpus) pays for it.
67
- # `to` — SAME "deliberately outside emits_ir, merged in only when
87
+ # `to` — same "deliberately outside emits_ir, merged in only when
68
88
  # present" treatment as direction/answers/refuses just above, and
69
89
  # for the identical reason: an operation still spelled the old way
70
90
  # (`reference_to` inside the block, shadow-parsing only — see
71
91
  # reference_to_impl's own comment) or one that simply hasn't
72
- # migrated yet keeps the EXACT prior IR shape, byte for byte,
92
+ # migrated yet keeps the exact prior IR shape, byte for byte,
73
93
  # instead of an unconditional new key breaking parser_parity_spec
74
94
  # for every domain that never touched this.
95
+ #
96
+ # @return [Hash] the declared emission, plus `direction`/`answers`/`refuses` for an
97
+ # outbound operation and `to` when a routing target is declared
75
98
  def to_h
76
99
  shape = super
77
100
  shape = shape.merge(direction: @direction.to_s, answers: @answers, refuses: @refuses) unless inbound?
@@ -93,6 +116,8 @@ module Hecks
93
116
 
94
117
  attr_reader :name, :operations
95
118
 
119
+ # @param name [String, Symbol] the port's declared name
120
+ # @param operations [Array<Bluebook::PortOperation>] the port's declared operations
96
121
  def initialize(name:, operations: [])
97
122
  @name = name.to_s
98
123
  @operations = operations
@@ -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.