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
@@ -1,41 +1,47 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module MetaValidator
4
- # A bluebook rebuilt FROM the meta-domain, in the shape the builder produces.
4
+ # A bluebook rebuilt from the meta-domain, in the shape the builder produces.
5
5
  #
6
6
  # This is the second half of the claim at the top of bluebook.bluebook —
7
7
  # "loading a domain becomes dispatching commands into this meta-domain ; the
8
8
  # IR it stores must equal the IR the DSL builder produces". The judge is the
9
9
  # first half. This reads the records back and assembles `to_h`.
10
10
  #
11
- # It is the INVERSE OF THE WALK and shares its plan: the walk reads a node's
11
+ # ## One table, both directions
12
+ #
13
+ # It is the inverse of the walk and shares its plan: the walk reads a node's
12
14
  # lists through the command that appends to each, and this reads them back out
13
15
  # of the rows those commands wrote. The retired `experiment/replay.rb` needed
14
16
  # 420 hand-written lines because the dispatch half was hand-written too; there
15
17
  # is nothing to hand-write when both directions are one table.
16
18
  #
17
- # This file is the TRAVERSAL. The hashes at its tips, and the encodings they
19
+ # This file is the traversal. The hashes at its tips, and the encodings they
18
20
  # undo, are in Shapes.
19
21
  #
20
- # IT READS LEVEL BY LEVEL, THROUGH `DeclaredIn`, AND NOT THROUGH THE READ
21
- # MODEL — which is the difference between a reconstruction that can be the
22
- # SOURCE and one that can only be a check.
22
+ # The parent key of every level is read from the language's own plan, the same
23
+ # Plan the walk dispatches from — so the two directions really are one table,
24
+ # which is what the header above has always claimed.
25
+ #
26
+ # ## Reads level by level, not through the read model
27
+ #
28
+ # It reads level by level, through `DeclaredIn`, and not through the read
29
+ # model — which is the difference between a reconstruction that can be the
30
+ # source and one that can only be a check.
23
31
  #
24
32
  # `Meta.whole_bluebook` gathers a chapter in a single read, and it sorts:
25
33
  # `ReadModelInterpreter#matching` ends `.sort_by(&:id)` deliberately, because
26
34
  # a store's iteration order is an accident, and a read model returning store
27
35
  # order would let that accident leak into an answer.
28
36
  # Right for a read model, fatal here — the order a bluebook declares its
29
- # commands in is a FACT ABOUT THE SOURCE, and the IR is a contract field for
37
+ # commands in is a fact about the source, and the IR is a contract field for
30
38
  # field and index for index ; the export carries that order verbatim.
31
39
  # `DeclaredIn` preserves it (spec/executes_spec says so), so this asks each
32
40
  # level for its own children rather than filtering one sorted gather.
33
41
  #
34
- # The parent key of every level is read from the language's own plan, the same
35
- # Plan the walk dispatches from — so the two directions really are one table,
36
- # which is what the header above has always claimed.
42
+ # ## What it cannot rebuild
37
43
  #
38
- # WHAT IT CANNOT REBUILD matters as much as what it can, and
44
+ # What it cannot rebuild matters as much as what it can, and
39
45
  # spec/round_trip_spec pins the difference as an exact set: a field the language
40
46
  # does not hold appears there as a named gap, and a field it stops holding
41
47
  # appears as a failure.
@@ -43,13 +49,27 @@ module Hecks
43
49
  include Readings
44
50
  include Shapes
45
51
 
52
+ # Reads one judged chapter back out of `runtime` and assembles it.
53
+ #
54
+ # @param runtime [Runtime::Dispatcher] the dispatcher holding the
55
+ # judge's own records
56
+ # @param chapter [String] the chapter's own `hecks_name`
57
+ # @return [Hash{Symbol => Object}] the reconstructed IR, in the
58
+ # shape the DSL builder's own `to_h` produces
59
+ # @raise [Runtime::NotFound] if `runtime` holds no bluebook named
60
+ # `chapter`
46
61
  def self.of(runtime, chapter) = new(runtime, chapter).to_h
47
62
 
63
+ # @param runtime [Runtime::Dispatcher] the dispatcher holding the
64
+ # judge's own records
65
+ # @param chapter [String] the chapter's own `hecks_name`
66
+ # @raise [Runtime::NotFound] if `runtime` holds no bluebook named
67
+ # `chapter`
48
68
  def initialize(runtime, chapter)
49
69
  @runtime = runtime
50
70
  @plan = Plan.for(MetaValidator.grammar_registry)
51
71
  @chapter = runtime.query("Bluebook::Bluebook.Called", name: { value: chapter }).first or
52
- raise NotFound, "the meta-domain holds no bluebook called #{chapter.inspect}"
72
+ raise Runtime::NotFound, "the meta-domain holds no bluebook called #{chapter.inspect}"
53
73
  end
54
74
 
55
75
  def to_h
@@ -60,6 +80,7 @@ module Hecks
60
80
  classification: text(@chapter[:classification]),
61
81
  formerly_known_as: text(@chapter[:formerly_known_as]),
62
82
  attaches_to: attached_contexts(@chapter),
83
+ provides: provisions(@chapter),
63
84
  aggregates: declared("Aggregate", chapter_id).map { |row| aggregate(row) },
64
85
  read_models: declared("ReadModel", chapter_id).map { |row| read_model(row) },
65
86
  policies: declared("Policy", chapter_id).map { |row| policy(row) },
@@ -71,14 +92,14 @@ module Hecks
71
92
 
72
93
  def chapter_id = @chapter[:id].to_s
73
94
 
74
- # Everything DECLARED IN one parent, in the order it was declared. The key
95
+ # Everything declared in one parent, in the order it was declared. The key
75
96
  # is the one the language's own creating command carries, read from Plan.
76
97
  def declared(category, parent_id)
77
98
  key = @plan.category(category).parent_key
78
99
  @runtime.query("Bluebook::#{category}.DeclaredIn", key.to_sym => { value: parent_id.to_s })
79
100
  end
80
101
 
81
- # ONE DECLARATION, BUILT FROM THE CONTRACT.
102
+ # One declaration, built from the contract.
82
103
  #
83
104
  # There were eleven methods here, one per category, each spelling out the same
84
105
  # keys `Assembly::Contracts` already names — which is the shape the judge used
@@ -126,14 +147,20 @@ module Hecks
126
147
 
127
148
  def pairs(with) = Array(with).map { |binding| [text(binding[:key]), text(binding[:value])] }
128
149
 
129
- # THE PARTS, IN THE ORDER THEY WENT IN, because the identity is their join
150
+ # The parts, in the order they went in, because the identity is their join
130
151
  # and a join read out of order names a different record.
131
152
  def identity_paths(row) = Array(row[:identified_by]).map { |part| text(part[:value]).to_s }
132
153
 
133
- # THE CONTEXTS ONE CHAPTER NAMES ITSELF ONTO, in the order they were
154
+ # The contexts one chapter names itself onto, in the order they were
134
155
  # attached — same shape identity_paths reads back, one level up.
135
156
  def attached_contexts(row) = Array(row[:attaches_to]).map { |part| text(part[:value]).to_s }
136
157
 
158
+ def provisions(row)
159
+ Array(row[:provides]).map do |part|
160
+ { capability: text(part[:capability]).to_s, key: text(part[:key]).to_s, verb: text(part[:verb]).to_s }
161
+ end
162
+ end
163
+
137
164
  # Every cell of the meta-domain is a single-field value object, so a row
138
165
  # arrives holding Values rather than Strings.
139
166
  def text(cell)
@@ -143,19 +170,19 @@ module Hecks
143
170
  cell
144
171
  end
145
172
 
146
- # An aggregate's OWN verbs and asks — the ones no entity declared. Both carry
173
+ # An aggregate's own verbs and asks — the ones no entity declared. Both carry
147
174
  # the parent link either way, because that is the head the reference resolves
148
175
  # against, so the entity ones have to be told apart by `entity_id`. Rejecting
149
- # from an ORDERED read keeps the order.
176
+ # from an ordered read keeps the order.
150
177
  def own(category, aggregate_id)
151
178
  declared(category, aggregate_id).select { |row| text(row[:entity_id]).to_s == "" }
152
179
  end
153
180
 
154
181
  # A piece's own verbs and asks. There is no `DeclaredIn` keyed by entity, so
155
182
  # this reads the aggregate's — in declaration order — and keeps the ones that
156
- # name this piece. `row[:aggregate]` — an ENTITY row's own `reference_to
183
+ # name this piece. `row[:aggregate]` — an entity row's own `reference_to
157
184
  # Aggregate` (bare, no `_id` since ADR 0025) — not `entity_id`, which
158
- # STAYS suffixed below : that one is Command/Query's own EXPLICIT `as:`,
185
+ # stays suffixed below : that one is Command/Query's own explicit `as:`,
159
186
  # never touched by the rename.
160
187
  def within(category, row)
161
188
  declared(category, text(row[:aggregate]))
@@ -172,7 +199,7 @@ module Hecks
172
199
  attributes: Array(row[:attributes]).map { |field| attribute(field, id) },
173
200
  value_objects: declared("ValueObject", id).map { |shape| value_object(shape) },
174
201
  commands: own("Command", id).map { |verb| command(verb) },
175
- # THE AGGREGATE BOUNDARY, and the precondition a command may
202
+ # The aggregate boundary, and the precondition a command may
176
203
  # reference by name (S10, ADR 0025 — "Rules") — the same
177
204
  # `rule` reader `command`'s own givens/ensures already use
178
205
  # (Assembly::Contracts' generic `declaration()` path), read
@@ -195,19 +222,19 @@ module Hecks
195
222
  def closed_set_of(row) = !text(row[:rows]).nil?
196
223
 
197
224
  # A closed set's admitted rows. S17, ADR 0026 — Member is a genuine
198
- # ENTITY now (`entity "Member" do ... end`, nested under
225
+ # entity now (`entity "Member" do ... end`, nested under
199
226
  # ValueObject), created by `ValueObject.Member` (an ordinary append,
200
227
  # the same way `Account.LogEntry` creates a LedgerEntry) and mutated
201
228
  # by its own dotted `ValueObject.Member.Pair`. Its data therefore
202
- # lives INLINE on the value object's own dispatched state — same as
229
+ # lives inline on the value object's own dispatched state — same as
203
230
  # any other entity list — not behind a separate `DeclaredIn` query:
204
231
  # there is no such query any more, because there is no top-level
205
- # "Member" aggregate left to hold one. Pairs are still an OPEN MAP,
232
+ # "Member" aggregate left to hold one. Pairs are still an open map,
206
233
  # which no value object can hold, so they still come back one pair
207
234
  # at a time.
208
235
  def members_row(row) = members_of(row)
209
236
 
210
- # THE KEY IS STRINGIFIED, NEVER THE VALUE — the same split
237
+ # The key is stringified, never the value — the same split
211
238
  # `Bluebook::ValueObject#to_h`'s own `members:` emission makes
212
239
  # (lib/hecks/bluebook/value_object.rb, L7 docs/audits/
213
240
  # 2026-08-11-bug-triage.md). `Pair.value` is declared `String`
@@ -219,7 +246,7 @@ module Hecks
219
246
  # on the side spec/round_trip_spec.rb compares straight against a
220
247
  # fresh raw load (`Reconstruction.of` directly, no Assembly in
221
248
  # between): `declared 84, read back "84"` the moment `to_h` stopped
222
- # erasing it on the OTHER side and this one kept erasing it alone.
249
+ # erasing it on the other side and this one kept erasing it alone.
223
250
  def members_of(value_object_row)
224
251
  Array(value_object_row[:members]).map do |member|
225
252
  Array(member[:pairs]).map { |pair| [text(pair[:key]).to_s, text(pair[:value])] }
@@ -230,15 +257,15 @@ module Hecks
230
257
 
231
258
  def query(row) = declaration("Query", row).merge(options_of(row))
232
259
 
233
- # EVERY DIRECT ENTITY OF ONE OWNER — S17, ADR 0026. `declared
234
- # ("Entity", root_id)` returns EVERY entity sharing the same
235
- # ROOT aggregate, nested or not (Dispatch and Handler both carry
260
+ # Every direct entity of one owner — S17, ADR 0026. `declared
261
+ # ("Entity", root_id)` returns every entity sharing the same
262
+ # root aggregate, nested or not (Dispatch and Handler both carry
236
263
  # `aggregate: process_manager_id`) — `owner` is the field that
237
264
  # actually tells them apart : `Judge#nest_entities`'s own
238
265
  # comment explains why it is the one to repurpose. Called with
239
266
  # `owner_id == root_id` for an aggregate's own direct entities
240
267
  # (Handler), and with `owner_id == some entity's own id` for
241
- # THAT entity's own nested ones (Dispatch, owned by Handler).
268
+ # that entity's own nested ones (Dispatch, owned by Handler).
242
269
  def direct_entities(root_id, owner_id)
243
270
  declared("Entity", root_id).select { |held| text(held[:owner]).to_s == owner_id.to_s }
244
271
  end
@@ -251,25 +278,25 @@ module Hecks
251
278
  # Symbol there — the IR was not uniform about it, and only a round trip
252
279
  # ever said so.
253
280
  identified_by: identity_paths(row),
254
- # `text(row[:aggregate])` — the OWNING aggregate, the same one
281
+ # `text(row[:aggregate])` — the owning aggregate, the same one
255
282
  # `Judge#owning_aggregate_ref` resolved this piece's own
256
283
  # attribute types against on the way in, so reconstruction reads
257
284
  # a value-object-typed attribute back the identical way an
258
285
  # aggregate's own is (`Shapes#shape_field`'s own comment).
259
286
  attributes: Array(row[:attributes]).map { |field| shape_field(field, text(row[:aggregate])) },
260
- # ADR 0028 — the SAME shape `aggregate(row)`'s own
287
+ # ADR 0028 — the same shape `aggregate(row)`'s own
261
288
  # `preconditions:` reads two hand-typed methods up, read by
262
289
  # hand for the identical reason: `entity(row)` is hand-typed
263
290
  # too, unlike `command`/`value_object`/`query`.
264
291
  preconditions: Array(row[:preconditions]).map { |held| rule(held) },
265
- # Round 7 — the SAME shape `aggregate(row)`'s own
292
+ # Round 7 — the same shape `aggregate(row)`'s own
266
293
  # `invariants:` reads, one level down: a piece's own shape
267
294
  # rule, checked against every instance of this piece.
268
295
  invariants: Array(row[:invariants]).map { |held| rule(held) },
269
296
  commands: within("Command", row).map { |verb| command(verb) },
270
297
  queries: within("Query", row).map { |ask| query(ask) },
271
298
  # S17, ADR 0026 — Dispatch, inside Handler : an entity's own
272
- # NESTED entities, found the same way its own direct ones
299
+ # nested entities, found the same way its own direct ones
273
300
  # were one level up.
274
301
  entities: direct_entities(text(row[:aggregate]), row[:id]).map { |piece| entity(piece) },
275
302
  # An entity has its own state machine, and the language has held it all
@@ -301,7 +328,7 @@ module Hecks
301
328
  # ordinary append, the same way `Account.LogEntry` creates a
302
329
  # LedgerEntry) and mutated by its own dotted `ProcessManager.
303
330
  # Handler.Dispatch`/`...Dispatch.Bind`. Its data therefore lives
304
- # INLINE on the process manager's own dispatched state — same as
331
+ # inline on the process manager's own dispatched state — same as
305
332
  # any other entity list — not behind a separate `DeclaredIn`
306
333
  # query : there is no such query any more, the same fix
307
334
  # `Reconstruction#members_of` already made for Member.
@@ -311,25 +338,25 @@ module Hecks
311
338
  end
312
339
 
313
340
  # S17, ADR 0026 — Dispatch, one level further in : nested under
314
- # Handler, its data lives inline on the HANDLER row this method
315
- # was just handed (`row` here IS one element of `handlers`,
341
+ # Handler, its data lives inline on the handler row this method
342
+ # was just handed (`row` here is one element of `handlers`,
316
343
  # above), not behind any query either.
317
344
  def handler(row)
318
345
  declaration("Handler", row,
319
346
  dispatches: Array(row[:dispatches]).map { |leg| dispatch(leg) })
320
347
  end
321
348
 
322
- # `compensates` — TWO FLAT FIELDS on this same row
349
+ # `compensates` — two flat fields on this same row
323
350
  # (`process_manager.bluebook`'s own comment on `Dispatch` for
324
- # why), assembled BY HAND into the shape its own field actually
351
+ # why), assembled by hand into the shape its own field actually
325
352
  # is — `declaration()`'s generic per-field hash-build has no
326
353
  # way to turn two cells into a second object, so this reads
327
354
  # them directly and passes the result through `extra:`, the
328
355
  # same seam `handler`/`process_manager` already use for a
329
356
  # `:children` shape a flat Contract cannot describe.
330
357
  # `compensates_command_name` absent means no compensation at
331
- # all — a plain dispatch with nothing to undo. A PLAIN HASH, the
332
- # SAME declaration shape `to_h` spells for everything else in
358
+ # all — a plain dispatch with nothing to undo. A plain hash, the
359
+ # same declaration shape `to_h` spells for everything else in
333
360
  # this file (this file's own top comment) — never a real
334
361
  # `DispatchSpec` here; `Assembly#dispatch` is the one place a
335
362
  # declaration hash becomes the real object, and building it