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
@@ -7,7 +7,7 @@ require_relative "../../ports/query/in_memory"
7
7
  module Hecks
8
8
  module Runtime
9
9
  class CommandRules
10
- # A reference must point at something that EXISTS.
10
+ # A reference must point at something that exists.
11
11
  #
12
12
  # `reference_to Customer` is the one guarantee an aggregate reference is
13
13
  # for, and it was declared 14 times across banking and enforced nowhere :
@@ -16,7 +16,7 @@ module Hecks
16
16
  # no corpus step ever passed a dangling reference.
17
17
  module References
18
18
  # Resolved here rather than in coercion because coercion is pure — it
19
- # holds no repository. A reference INTO ANOTHER DOMAIN is left alone : a
19
+ # holds no repository. A reference into another domain is left alone : a
20
20
  # cross-domain target may legitimately not be loaded, which is the same
21
21
  # reading `across` policies already get.
22
22
  #
@@ -83,7 +83,7 @@ module Hecks
83
83
  "#{attribute.type.target_name} identity, got nil"
84
84
  end
85
85
 
86
- # The reference RESOLVES itself — through the chapter's own IR, so the
86
+ # The reference resolves itself — through the chapter's own IR, so the
87
87
  # bluebook's declared heads are the index. This used to regex the target's
88
88
  # name out of "Reference<Customer>" and then search
89
89
  # `registry.bluebook(domain).aggregates` for it — and later reached the
@@ -101,33 +101,33 @@ module Hecks
101
101
  next if @registry.repository(domain, target).find(key)
102
102
 
103
103
  raise NotFound,
104
- RefusalWording.render("NotFound", "reference_target_missing",
105
- target: target.name, heads: target.identity_heads.join(", "),
106
- key: key.inspect)
104
+ RefusalWording.render_site("NotFound", "reference_target_missing",
105
+ target: target.name, heads: target.identity_heads.join(", "),
106
+ key: key)
107
107
  end
108
108
  end
109
109
 
110
- # ANGLE-8's OWN WRITE-SIDE HALF of `TenantScope.apply` (runtime/
111
- # tenant_scope.rb) — the QUERY-side mechanism this mirrors. That
110
+ # Angle-8's own write-side half of `TenantScope.apply` (runtime/
111
+ # tenant_scope.rb) — the query-side mechanism this mirrors. That
112
112
  # module turns a declared `authorize policy, tenant: :field` into a
113
- # synthetic where-clause checked against the CALLER's own supplied
113
+ # synthetic where-clause checked against the caller's own supplied
114
114
  # tenant argument; there is no caller-identity/session system this
115
- # runtime has to check a WRITE's caller against (TenantScope's own
115
+ # runtime has to check a write's caller against (TenantScope's own
116
116
  # header names that as a separate, still-open gap), so this checks
117
- # the one thing that IS available without one: whether the record
117
+ # the one thing that is available without one: whether the record
118
118
  # being written and the record it references agree about which
119
119
  # tenant they belong to. `lib/hecks/fuzzing/properties/guards.rb`'s
120
120
  # `commands_respect_tenant_scope` states the identical claim,
121
121
  # read off `history[:instances]` after the fact — this is what
122
- # makes that claim hold BY CONSTRUCTION (a refused write is never
122
+ # makes that claim hold by construction (a refused write is never
123
123
  # stored) rather than merely checked for regression.
124
124
  #
125
125
  # Hooked into `resolve_state_references` rather than a new
126
126
  # DISPATCH_ORDER step deliberately: that method already walks
127
- # every `reference_to`-typed attribute against the SETTLED,
127
+ # every `reference_to`-typed attribute against the settled,
128
128
  # post-mutation state (the same moment `commands_respect_tenant_
129
129
  # scope` itself inspects), already resolves the referenced record
130
- # through the repository right above, and already runs from BOTH
130
+ # through the repository right above, and already runs from both
131
131
  # `CommandInterpreter#step_save` and `EntityInterpreter#step_save`
132
132
  # — one change, both interpreters covered, no new vocabulary step
133
133
  # to keep in sync with `Vocabulary::AggregateDispatchOrder`/
@@ -152,20 +152,20 @@ module Hecks
152
152
  next if target_tenant == own_tenant
153
153
 
154
154
  raise Unauthorized,
155
- RefusalWording.render("Unauthorized", "cross_tenant_reference",
156
- aggregate: construct.hecks_name, field: own_tenant_field,
157
- tenant: Rendering.describe(state[own_tenant_field]),
158
- attribute: attribute.name, target: target.name,
159
- target_field: target_tenant_field,
160
- other: Rendering.describe(record.state[target_tenant_field]))
155
+ RefusalWording.render_site("Unauthorized", "cross_tenant_reference",
156
+ aggregate: construct.hecks_name, field: own_tenant_field,
157
+ tenant: Rendering.describe(state[own_tenant_field]),
158
+ attribute: attribute.name, target: target.name,
159
+ target_field: target_tenant_field,
160
+ other: Rendering.describe(record.state[target_tenant_field]))
161
161
  end
162
162
  end
163
163
 
164
- # THE FIELD AN AGGREGATE'S OWN QUERY NAMES AS TENANT-SCOPING — the
164
+ # The field an aggregate's own query names as tenant-scoping — the
165
165
  # exact same lookup `Fuzzing::Properties::Guards#tenant_field_for`
166
166
  # already established for the property that found this gap, reused
167
167
  # here rather than reinvented: an aggregate's own declared tenant
168
- # field is whichever field ONE OF ITS OWN queries names in
168
+ # field is whichever field one of its own queries names in
169
169
  # `authorize policy, tenant: :field`. `nil` for a construct that
170
170
  # declares no such query — not every aggregate is tenant-scoped,
171
171
  # and an entity never declares a query of its own at all today
@@ -177,25 +177,25 @@ module Hecks
177
177
  authorization&.tenant&.to_sym
178
178
  end
179
179
 
180
- # `value` is the referenced record's own id, EXACTLY as `Identity.of`
180
+ # `value` is the referenced record's own id, exactly as `Identity.of`
181
181
  # would build it for that record — a bare scalar for a single-field
182
182
  # identity (the overwhelming common case; Banking's own plain
183
183
  # `reference_to Customer` holds one already, so `Value.
184
184
  # materialize_unwrapped` is a no-op passthrough here), or a
185
185
  # `Naming.identity`-joined string for a compound one
186
186
  # (`belongs_to Translation, as: :translation_ref` — Translation's
187
- # own `identified_by :domain, :from, :to`, THREE fields). Before
187
+ # own `identified_by :domain, :from, :to`, three fields). Before
188
188
  # this, plain `value.to_s` on that compound case's own coerced
189
189
  # Value hit Ruby's default `Object#to_s` (a raw, run-to-run-random
190
190
  # memory address) instead of joining the record's real id — found
191
191
  # live via bin/fuzz on the self-hosted "translation" domain
192
- # (replay_is_deterministic), the SAME class of gap `Identity.from`
192
+ # (replay_is_deterministic), the same class of gap `Identity.from`
193
193
  # already had for a compound `identified_by`'s own bare (undotted)
194
194
  # attribute paths. `materialize_unwrapped` recurses a multi-
195
195
  # attribute value object to a plain Hash keyed by attribute name,
196
196
  # in declaration order — `Naming.identity` on `.values` reproduces
197
197
  # the identical join `Identity.of` itself would produce for the
198
- # SAME fields.
198
+ # same fields.
199
199
  def reference_key(value)
200
200
  unwrapped = Value.materialize_unwrapped(value)
201
201
  return Naming.identity(unwrapped.values).to_s if unwrapped.is_a?(Hash)
@@ -203,35 +203,35 @@ module Hecks
203
203
  unwrapped.to_s
204
204
  end
205
205
 
206
- # A COMMAND ARGUMENT's own related record, reachable by name from
206
+ # A command argument's own related record, reachable by name from
207
207
  # `given`/`ensures` — `disputed_by.status`, say, `CardPayment
208
208
  # .Dispute`'s own fresh `Reference<Customer>` argument — without
209
209
  # teaching the pure expression evaluator anything about
210
- # repositories. The lookup happens HERE, once, before evaluation;
210
+ # repositories. The lookup happens here, once, before evaluation;
211
211
  # `Resolver#lookup` just digs into a plain Hash exactly as it
212
212
  # always has.
213
213
  #
214
- # `owner` NARROWED TO `command` ONLY (S12, ADR 0025 — "rules
214
+ # `owner` narrowed to `command` only (S12, ADR 0025 — "rules
215
215
  # confined to their own aggregate boundary"): dereferencing the
216
- # DECLARING aggregate/entity's own STORED `reference_to` used to
216
+ # declaring aggregate/entity's own stored `reference_to` used to
217
217
  # be the other half of this method's job — a live query against
218
218
  # another aggregate's own repository, every time a `given`/
219
219
  # `ensures`/`invariant` ran. That half is gone; a cross-aggregate
220
- # fact a rule needs now has to be a `projects`-maintained LOCAL
220
+ # fact a rule needs now has to be a `projects`-maintained local
221
221
  # field (`AggregateBuilder#projects_impl`'s own comment), already
222
222
  # present in `subject`'s own state, no hydration needed. A
223
- # reference-typed COMMAND ARGUMENT stays in bounds, though — the
223
+ # reference-typed command argument stays in bounds, though — the
224
224
  # ADR's own boundary list names "its command arguments" as
225
225
  # readable, and nothing is stored yet for a fresh argument to
226
- # project from; resolving it once here, synchronous with THIS
226
+ # project from; resolving it once here, synchronous with this
227
227
  # command's own admission, is a different shape from a live query
228
- # against an ALREADY-PERSISTED reference. `enforce_givens`/
228
+ # against an already-persisted reference. `enforce_givens`/
229
229
  # `enforce_ensures` are this method's only two remaining callers,
230
230
  # both passing `command`/`args`, never a `subject`'s own
231
231
  # aggregate — verified before this comment was written, not
232
232
  # assumed.
233
233
  #
234
- # RECURSES into what it finds, so a chain deeper than one hop
234
+ # Recurses into what it finds, so a chain deeper than one hop
235
235
  # still resolves in one pass. Depth-bounded rather than cycle-
236
236
  # detected — nothing in this corpus dots more than two hops on a
237
237
  # fresh argument, and a bound is simpler than tracking visited
@@ -20,6 +20,9 @@ module Hecks
20
20
 
21
21
  attr_reader :registry
22
22
 
23
+ # @param registry [Runtime::Registry, nil] the booted registry the rules read bluebooks,
24
+ # repositories and the event log from; nil serves only the rules that read no
25
+ # registry, such as `sign_of`
23
26
  def initialize(registry)
24
27
  @registry = registry
25
28
  end
@@ -74,12 +74,12 @@ module Hecks
74
74
  STATEFUL_MUTATIONS = %i[append increment decrement multiply clamp remove].freeze
75
75
 
76
76
  # `root_aggregate:` — Wave 8's own audit surfaced a real bug here,
77
- # not merely a missing feature: for an ENTITY-owned command,
77
+ # not merely a missing feature: for an entity-owned command,
78
78
  # `EntityInterpreter` calls this with `aggregate:` set to the
79
- # ENTITY itself (`element_interpreter.rb`'s own `Analyzer.call
79
+ # entity itself (`element_interpreter.rb`'s own `Analyzer.call
80
80
  # (aggregate: entity, command:)`), so `owner_fields` was always
81
81
  # the entity's own attribute set. A `given`/`ensures` reading
82
- # `parent.X` legitimately means the ROOT aggregate's own field —
82
+ # `parent.X` legitimately means the root aggregate's own field —
83
83
  # a genuinely different owner — but `classify_path`'s `:parent`
84
84
  # branch checked that read against `owner_fields` (the entity's),
85
85
  # which can never contain a root-level field, so every entity
@@ -96,10 +96,10 @@ module Hecks
96
96
  @owner_fields << aggregate.lifecycle.field.to_sym if aggregate.lifecycle
97
97
  @root_owner_fields = root_aggregate.attributes.to_set(&:name)
98
98
  @root_owner_fields << root_aggregate.lifecycle.field.to_sym if root_aggregate.lifecycle
99
- # `projects` FIELDS (S12, ADR 0025) ARE OWNER STATE TOO — a
99
+ # `projects` fields (S12, ADR 0025) are owner state too — a
100
100
  # `given`/`ensures` reading one (e.g. `customer_status ==
101
101
  # "active"`) is reading this record's own stored field, same
102
- # as any attribute, even though nothing here WRITES it via a
102
+ # as any attribute, even though nothing here writes it via a
103
103
  # declared mutation (`CommandInterpreter#seed_projected_fields`
104
104
  # populates it outside this analysis entirely). Left out of
105
105
  # `known_writes` deliberately: `add_preservation_reads` then
@@ -107,7 +107,7 @@ module Hecks
107
107
  # a partial mutation, which is exactly right — a projected
108
108
  # field's freshness comes from the interpreter reseeding it on
109
109
  # save, not from anything a caller-supplied write set carries.
110
- # Applies to BOTH `owner_fields` and `root_owner_fields` — an
110
+ # Applies to both `owner_fields` and `root_owner_fields` — an
111
111
  # entity's own `parent.*` read can name the root aggregate's
112
112
  # projected field just as easily as one of its real attributes
113
113
  # (`Banking::Withdrawal.Dispute`'s own `parent.account_customer_
@@ -237,7 +237,7 @@ module Hecks
237
237
  end
238
238
  end
239
239
 
240
- # KNOWN, HARMLESS GAP: `corrects ..., as: :name`'s bound name
240
+ # Known, harmless gap: `corrects ..., as: :name`'s bound name
241
241
  # (admissibility.rb's `enforce_correction_target`/`enforce_givens`/
242
242
  # `enforce_ensures`) isn't special-cased here the way `:old`/
243
243
  # `:parent` are — a given/ensures referencing it falls through to
@@ -247,7 +247,7 @@ module Hecks
247
247
  # `hydrate_existing` path instead of the `ATOMIC_PUT` fast path.
248
248
  # Not a correctness bug — `as:`'s runtime binding (a plain `attrs`
249
249
  # merge, exactly like `old:`'s) resolves and evaluates correctly
250
- # regardless of what this STATIC analysis concludes — just a real,
250
+ # regardless of what this static analysis concludes — just a real,
251
251
  # deliberately-left optimization gap: closing it would mean
252
252
  # threading "which names this command declares as correction
253
253
  # bindings" into the Analyzer, which doesn't have that per-command
@@ -258,9 +258,9 @@ module Hecks
258
258
  name = head.to_sym
259
259
 
260
260
  if name == :parent
261
- # `root_owner_fields` — NOT `owner_fields`. For an entity-owned
262
- # command `owner_fields` is the ENTITY's own attribute set;
263
- # `parent.X` always means the ROOT aggregate's own field, a
261
+ # `root_owner_fields` — not `owner_fields`. For an entity-owned
262
+ # command `owner_fields` is the entity's own attribute set;
263
+ # `parent.X` always means the root aggregate's own field, a
264
264
  # genuinely different owner (`root_aggregate:`'s own header,
265
265
  # above, has the full bug this fixes). Identical for a plain
266
266
  # aggregate command, where root_aggregate defaults to aggregate