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
@@ -5,12 +5,15 @@ module Hecks
5
5
  module Adapters
6
6
  class PostgresEra
7
7
  module LineageManager
8
- # The boot-time resolution: which era IS this checkout? First
8
+ # The boot-time resolution: which era is this checkout? First
9
9
  # boot holds era 1; a quiet reboot changes nothing; a
10
10
  # held-but-superseded shape boots read-only-toward-the-fence; an
11
11
  # unheld shape goes to the minter.
12
12
  module EraResolver
13
13
  # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
14
+ # Resolves which era this boot is and records it on the registry, holding era 1
15
+ # on a first boot and minting the next era when the shape is one no era holds.
16
+ #
14
17
  # A single order-dependent dispatch over a closed set of four
15
18
  # boot scenarios (first boot / quiet reboot / held-but-superseded
16
19
  # / unheld-shape-goes-to-minter), each already explained by its
@@ -18,11 +21,32 @@ module Hecks
18
21
  # `ensure`. Splitting the branches into separate methods would
19
22
  # turn each `return` (which exits `check!`, closing `db`) into a
20
23
  # sentinel value threaded back up, obscuring the mutual
21
- # exclusivity that IS the method's whole point.
24
+ # exclusivity that is the method's whole point.
25
+ #
26
+ # @param registry [Runtime::Registry] the booting registry; `resolved_eras` gets
27
+ # this domain's ordinal on every path but a first boot (where the adapter
28
+ # self-resolves to era 1), and `superseded_eras` gets the newest ordinal when
29
+ # this checkout's shape is held but superseded
30
+ # @param bluebook [Bluebook::Chapter] the domain being booted
31
+ # @param current_text [String] the domain's bluebook source as it stands on disk,
32
+ # held verbatim as the new era's text on a first boot or a mint
33
+ # @param settings [Hash{Symbol, String => Object}] the world's persistence settings
34
+ # for this binding; `database` is required, `schema`, `role` (a Postgres role to
35
+ # grant this era's privileges to) and `allow_superuser` are honored
36
+ # @param directory [String, nil] the domain's bluebook directory, where
37
+ # `HECKS_SCAFFOLD=1` writes a translation edge; nil disables scaffolding
38
+ # @return [Integer, nil] the ordinal of the era this boot minted, or nil when it
39
+ # minted nothing (first boot, quiet reboot, or a held-but-superseded shape)
40
+ # @raise [Runtime::WiringError] if the database cannot be reached, the connection
41
+ # is a superuser or has BYPASSRLS without `allow_superuser`, a declared
42
+ # `formerly_known_as` rename cannot be applied, a held text fails its integrity
43
+ # check, or the shape is unheld and `mint!` refuses
44
+ # @raise [Bluebook::DSL::Malformed] if a held era's text parses under neither the
45
+ # current nor the legacy grammar
22
46
  def check!(registry:, bluebook:, current_text:, settings:, directory: nil)
23
47
  db = PostgresEra.connect_for(bluebook.name, settings)
24
48
  lineage = Lineage.new(db, bluebook.name, formerly_known_as: bluebook.formerly_known_as)
25
- # FIRST, before ensure_base! provisions or verifies anything —
49
+ # First, before ensure_base! provisions or verifies anything —
26
50
  # the one point every PostgresEra boot passes through, and the
27
51
  # earliest at which the connection's own role is known. See
28
52
  # check_fence_applies!'s own header (BUG#24) for why a
@@ -39,7 +63,7 @@ module Hecks
39
63
  lineage.hold_first!(current_text, projection: Runtime::StorageShape.project(bluebook))
40
64
  bluebook.aggregates.each { |aggregate| lineage.ensure_first_head!(aggregate.storage_name) }
41
65
  # hold_first! already established era 1 as current for
42
- # EVERY role; this one just needs its own privileges.
66
+ # every role; this one just needs its own privileges.
43
67
  lineage.grant_role!(role, aggregates: bluebook.aggregates, era: 1) if role
44
68
  return
45
69
  end
@@ -52,7 +76,7 @@ module Hecks
52
76
  # is permanently the old one — the frozen text is authentic
53
77
  # record ("this domain really was called that, at the
54
78
  # time") and must never be rewritten. Only the in-memory
55
- # shape used for THIS comparison is normalized, and only
79
+ # shape used for this comparison is normalized, and only
56
80
  # where it exactly matches the declared old name, so an
57
81
  # unrelated domain that happens to shape-match some other
58
82
  # domain's history still shows up as a real mismatch.
@@ -74,9 +98,9 @@ module Hecks
74
98
  matched, = shapes.find { |_, shape| shape == current_shape }
75
99
  if matched
76
100
  # A held-but-superseded era — an old checkout still running.
77
- # It may keep BOOTING and READING (PostgresEra is the one
101
+ # It may keep booting and reading (PostgresEra is the one
78
102
  # adapter that recognizes this rather than refusing), but it
79
- # may not keep WRITING: the shared era fence was already
103
+ # may not keep writing: the shared era fence was already
80
104
  # advanced past this ordinal by whichever mint superseded
81
105
  # it, and nothing here may roll that back. Granting only
82
106
  # this role's privileges, never advance_era!, is what keeps
@@ -84,11 +108,11 @@ module Hecks
84
108
  # called with a superseded ordinal.
85
109
  lineage.grant_role!(role, aggregates: bluebook.aggregates, era: matched[:ordinal]) if role
86
110
  registry.resolved_eras[bluebook.name] = matched[:ordinal]
87
- # ...and the boot REMEMBERS that it is superseded, not only
111
+ # ...and the boot remembers that it is superseded, not only
88
112
  # which era it is: `RepositoryFactory.build` hands this to
89
113
  # the adapter as `superseded_by:`, and `PostgresEra#append`
90
114
  # refuses on it before issuing the INSERT. That is the
91
- # in-process half of "may not keep WRITING" — the half that
115
+ # in-process half of "may not keep writing" — the half that
92
116
  # holds even for a connection the RLS fence cannot bite
93
117
  # (a superuser under allow_superuser; BUG#24).
94
118
  registry.superseded_eras[bluebook.name] = latest[:ordinal]
@@ -10,6 +10,22 @@ module Hecks
10
10
  # world's post-cut writes into the head by their recorded global
11
11
  # ordinals, under the full audit, in one transaction.
12
12
  module MergeCoordinator
13
+ # Merges the writes old checkouts made after the last mint into the current
14
+ # era's head, on a connection of its own that it closes afterwards.
15
+ #
16
+ # @param registry [Runtime::Registry] the loaded registry; supplies the
17
+ # translation edges the chain is built from
18
+ # @param bluebook [Bluebook::Chapter] the domain whose tail is merged
19
+ # @param settings [Hash{Symbol, String => Object}] the world's persistence
20
+ # settings for this binding; `database` is required
21
+ # @param winners [Hash{String => String}] record id to `"old"` or `"new"`, naming
22
+ # which world's whole record wins for each id both worlds touched since the cut
23
+ # @return [true] when the merge committed
24
+ # @raise [Runtime::WiringError] if the database cannot be reached, the domain
25
+ # stands at era 1, the edge chain is broken, a record touched by both worlds
26
+ # has no named winner, the post-merge audit reports violations, another mint
27
+ # or merge holds the domain lock for 10 seconds, or Postgres refuses a
28
+ # statement; every refusal rolls the merge back
13
29
  def merge!(registry:, bluebook:, settings:, winners: {})
14
30
  db = PostgresEra.connect_for(bluebook.name, settings)
15
31
  lineage = Lineage.new(db, bluebook.name, formerly_known_as: bluebook.formerly_known_as)
@@ -12,6 +12,29 @@ module Hecks
12
12
  # reviewed, check coverage, audit the live chain, and mint — or
13
13
  # refuse toward the authoring loop by name.
14
14
  module Minter
15
+ # Mints the next era for a drifted shape in one transaction, after proving the
16
+ # edge is present, current, approved where it must be, covering, and audited.
17
+ #
18
+ # @param registry [Runtime::Registry] the booting registry; supplies the loaded
19
+ # translation edges
20
+ # @param bluebook [Bluebook::Chapter] the domain as currently declared
21
+ # @param current_text [String] the domain's bluebook source, held verbatim as the
22
+ # new era's text
23
+ # @param lineage [Adapters::PostgresEra::Lineage] the domain's lineage, on an open
24
+ # connection
25
+ # @param latest [Hash{Symbol => Object}] the newest held era, as `Lineage#eras`
26
+ # returns it (`:ordinal`, `:hash`, `:label`, `:held_text`, `:watermark`)
27
+ # @param role [String, nil] a Postgres role to grant the new era's privileges to;
28
+ # nil grants nothing
29
+ # @param directory [String, nil] the domain's bluebook directory, where
30
+ # `HECKS_SCAFFOLD=1` writes a missing edge; nil disables scaffolding
31
+ # @return [Integer] the ordinal of the era just minted
32
+ # @raise [Runtime::WiringError] if no edge leaves the latest era, more than one
33
+ # does, the edge targets another shape, a compute or rekey edge lacks a current
34
+ # approval, the edge leaves drift uncovered, the chain is broken, the audit
35
+ # reports violations, or the mint transaction itself fails
36
+ # @raise [Bluebook::DSL::Malformed] if the latest held text parses under neither
37
+ # the current nor the legacy grammar
15
38
  def mint!(registry, bluebook, current_text, lineage, latest, role: nil, directory: nil)
16
39
  ensure_named!(lineage, latest)
17
40
  latest = lineage.eras.last
@@ -34,12 +57,28 @@ module Hecks
34
57
  ordinal
35
58
  end
36
59
 
37
- # Find the one translation edge that leaves the held era, and
38
- # validate it: exactly one edge must leave (eras fork
60
+ # Finds the one translation edge that leaves the held era, and
61
+ # validates it: exactly one edge must leave (eras fork
39
62
  # mechanically — a second edge from the same source is a wiring
40
63
  # mistake, not a merge to resolve automatically), and it must
41
64
  # target the current shape's label (otherwise the edge is stale
42
65
  # and boot must not silently mint past it).
66
+ #
67
+ # @param registry [Runtime::Registry] the registry whose loaded `translations`
68
+ # are searched
69
+ # @param bluebook [Bluebook::Chapter] the domain as currently declared
70
+ # @param lineage [Adapters::PostgresEra::Lineage] the domain's lineage, used only
71
+ # when scaffolding a missing edge
72
+ # @param latest [Hash{Symbol => Object}] the newest held era, already named;
73
+ # `:label` is the edge's required source and `:ordinal` appears in refusals
74
+ # @param label [String] the current shape's label, the edge's required target
75
+ # @param ordinal [Integer] the ordinal of the era about to be minted
76
+ # @param directory [String, nil] where `HECKS_SCAFFOLD=1` writes a missing edge;
77
+ # nil disables scaffolding
78
+ # @return [Bluebook::Translation] the single edge from `latest[:label]` to `label`
79
+ # @raise [Runtime::WiringError] if no edge leaves the latest era (naming the
80
+ # scaffold it wrote, when it wrote one), more than one does, or the one edge
81
+ # targets a label other than `label`
43
82
  def resolve_edge!(registry, bluebook, lineage, latest, label, ordinal, directory)
44
83
  edges = registry.translations.select { |t| t.domain == bluebook.name && t.from == latest[:label] }
45
84
  refuse_toward_the_scaffold!(registry, bluebook, lineage, latest, ordinal, directory) if edges.empty?
@@ -58,15 +97,29 @@ module Hecks
58
97
  edge
59
98
  end
60
99
 
100
+ # Refuses a mint whose edge carries a compute or rekey rule without a recorded
101
+ # approval that still matches the edge and the journal.
102
+ #
61
103
  # A compute's (and, the same way, a rekey's) only verification
62
104
  # is the audit's human-approved sample — mint stays
63
105
  # non-interactive by requiring the approval to already exist,
64
- # recorded IN THIS DATABASE by `bin/translation_audit …
106
+ # recorded in this database by `bin/translation_audit …
65
107
  # --approve` and bound to what was actually reviewed: this
66
108
  # edge's parsed content, and the journal as it stood when the
67
109
  # samples were read. A journal that has advanced past the
68
110
  # review invalidates it — the approved samples no longer cover
69
111
  # the data.
112
+ #
113
+ # @param bluebook [Bluebook::Chapter] the domain, named in the refusal
114
+ # @param lineage [Adapters::PostgresEra::Lineage] the domain's lineage, which holds
115
+ # the recorded approvals and the journal's last ordinal
116
+ # @param edge [Bluebook::Translation] the edge about to be minted through
117
+ # @param ordinal [Integer] the ordinal of the era about to be minted
118
+ # @return [nil] when the edge has no compute or rekey rule, or its approval is
119
+ # current
120
+ # @raise [Runtime::WiringError] if no approval is recorded for this shape pair, the
121
+ # approval's edge digest differs from this edge's, or the journal has advanced
122
+ # past the reviewed ordinal
70
123
  def ensure_compute_rekey_approved!(bluebook, lineage, edge, ordinal)
71
124
  return unless edge.aggregates.any? { |declared| !declared.computes.empty? || !declared.rekeys.empty? }
72
125
 
@@ -88,7 +141,7 @@ module Hecks
88
141
 
89
142
  # No edge yet: the boot refuses toward the authoring loop —
90
143
  # naming both tools and the era ordinal. With HECKS_SCAFFOLD=1
91
- # the boot RUNS the scaffold first (an explicit flag, never a
144
+ # the boot runs the scaffold first (an explicit flag, never a
92
145
  # silent side-effect) and the refusal names the file it wrote.
93
146
  def refuse_toward_the_scaffold!(registry, bluebook, lineage, latest, ordinal, directory)
94
147
  if ENV["HECKS_SCAFFOLD"] == "1" && directory
@@ -12,7 +12,7 @@ module Hecks
12
12
  class PostgresEra
13
13
  # The PostgresEra side of the boot-time era gate. Where every other
14
14
  # adapter's era check can only hold texts and refuse, this one
15
- # ACTS: a drifted shape whose translation edge exists, matches by
15
+ # acts: a drifted shape whose translation edge exists, matches by
16
16
  # shape label, covers the whole diff, and passes the audit mints
17
17
  # the next era — one transaction — and boots into it. Everything
18
18
  # else refuses, as loudly and as specifically as the situation
@@ -38,10 +38,24 @@ module Hecks
38
38
 
39
39
  module_function
40
40
 
41
- # The FULL chain, one edge per step in original mint order
41
+ # Collects the translation edge for every step from era 1 to the current shape.
42
+ #
43
+ # The full chain, one edge per step in original mint order —
42
44
  # never flattened. Each step is found by its stored labels;
43
45
  # every mint required its own edge, so a break in the chain is a
44
46
  # deleted file, and deserves its own refusal.
47
+ #
48
+ # @param registry [Runtime::Registry] the registry whose loaded `translations`
49
+ # are searched
50
+ # @param bluebook [Bluebook::Chapter] the domain; only edges declared for its
51
+ # name are considered
52
+ # @param eras [Array<Hash{Symbol => Object}>] the ancestor eras in ordinal order,
53
+ # as `Lineage#eras` returns them; only `:label` is read
54
+ # @param current_label [String] the shape label the last step must lead to
55
+ # @return [Array<Hash{Symbol => Bluebook::Translation}>] one `{ translation: edge }`
56
+ # per step, in mint order; `[]` when `eras` is empty
57
+ # @raise [Runtime::WiringError] if no loaded translation leads one label to the
58
+ # next
45
59
  def edge_chain(registry, bluebook, eras, current_label)
46
60
  labels = eras.map { |era| era[:label] } + [current_label]
47
61
  (0...(labels.size - 1)).map do |index|
@@ -57,9 +71,18 @@ module Hecks
57
71
  end
58
72
  end
59
73
 
74
+ # Parses a held era's bluebook text into a throwaway registry, leaving the live
75
+ # one untouched.
76
+ #
60
77
  # Held texts live in rows, not files, but the predicate
61
78
  # extractor reads source from disk at the eval path — so a
62
79
  # shadow parse writes the text to a scratch file first.
80
+ #
81
+ # @param source [String] bluebook source text, as held in `hecks_eras.held_text`
82
+ # @return [Bluebook::Chapter, nil] the first bluebook the text declares, or nil
83
+ # when it declares none
84
+ # @raise [Bluebook::DSL::Malformed] if the text parses under neither the current
85
+ # grammar nor the legacy shadow-parse fallback
63
86
  def shadow(source)
64
87
  file = Tempfile.new(["hecks-era-", ".bluebook"])
65
88
  file.write(source)