hecks 3.5.0 → 3.7.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 (1156) hide show
  1. checksums.yaml +4 -4
  2. data/examples/pizzas/bluebook/hecksagon/mock_stripe_payment_adapter.rb +1 -1
  3. data/lib/hecks/adapters/driven/claude_code.rb +11 -7
  4. data/lib/hecks/adapters/driven/d1/connection.rb +90 -0
  5. data/lib/hecks/adapters/driven/d1.rb +48 -314
  6. data/lib/hecks/adapters/driven/folder.rb +20 -10
  7. data/lib/hecks/adapters/driven/google_authentication.rb +18 -4
  8. data/lib/hecks/adapters/driven/governance_authorization.rb +2 -2
  9. data/lib/hecks/adapters/driven/heki/journal.rb +11 -10
  10. data/lib/hecks/adapters/driven/heki/saga_store.rb +4 -6
  11. data/lib/hecks/adapters/driven/heki/sagas.rb +55 -0
  12. data/lib/hecks/adapters/driven/heki.rb +21 -66
  13. data/lib/hecks/adapters/driven/in_memory_ordering.rb +37 -12
  14. data/lib/hecks/adapters/driven/lambda/client.rb +1 -1
  15. data/lib/hecks/adapters/driven/lambda.rb +1 -8
  16. data/lib/hecks/adapters/driven/memory/outbox_rows.rb +76 -0
  17. data/lib/hecks/adapters/driven/memory/shared_elements/values.rb +117 -0
  18. data/lib/hecks/adapters/driven/memory/shared_elements.rb +10 -97
  19. data/lib/hecks/adapters/driven/memory.rb +3 -65
  20. data/lib/hecks/adapters/driven/postgres/codec.rb +29 -26
  21. data/lib/hecks/adapters/driven/postgres/ddl.rb +50 -0
  22. data/lib/hecks/adapters/driven/postgres/dialect.rb +93 -0
  23. data/lib/hecks/adapters/driven/postgres/events.rb +57 -0
  24. data/lib/hecks/adapters/driven/postgres/journal.rb +127 -0
  25. data/lib/hecks/adapters/driven/postgres/outbox.rb +39 -31
  26. data/lib/hecks/adapters/driven/postgres/repository.rb +190 -0
  27. data/lib/hecks/adapters/driven/postgres/sagas.rb +72 -0
  28. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +13 -41
  29. data/lib/hecks/adapters/driven/postgres.rb +61 -528
  30. data/lib/hecks/adapters/driven/prism.rb +1 -1
  31. data/lib/hecks/adapters/driven/sql_query_builder.rb +45 -53
  32. data/lib/hecks/adapters/driven/sql_value_members.rb +57 -0
  33. data/lib/hecks/adapters/driven/sqlite/codec.rb +32 -29
  34. data/lib/hecks/adapters/driven/sqlite/ddl.rb +68 -0
  35. data/lib/hecks/adapters/driven/sqlite/dialect.rb +55 -0
  36. data/lib/hecks/adapters/driven/sqlite/events.rb +61 -0
  37. data/lib/hecks/adapters/driven/sqlite/journal.rb +125 -0
  38. data/lib/hecks/adapters/driven/sqlite/outbox.rb +98 -0
  39. data/lib/hecks/adapters/driven/sqlite/projection.rb +82 -63
  40. data/lib/hecks/adapters/driven/sqlite/repository.rb +146 -0
  41. data/lib/hecks/adapters/driven/sqlite/sagas.rb +69 -0
  42. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +8 -55
  43. data/lib/hecks/adapters/driven/sqlite.rb +36 -513
  44. data/lib/hecks/adapters/driven/tenant_provisioner.rb +13 -7
  45. data/lib/hecks/adapters/driving/github_webhook.rb +11 -8
  46. data/lib/hecks/behaviors/dsl.rb +17 -12
  47. data/lib/hecks/behaviors/expectations/boot.rb +81 -0
  48. data/lib/hecks/behaviors/expectations/checks.rb +178 -0
  49. data/lib/hecks/behaviors/expectations/dispatching.rb +93 -0
  50. data/lib/hecks/behaviors/expectations/qualify.rb +81 -0
  51. data/lib/hecks/behaviors/expectations.rb +39 -355
  52. data/lib/hecks/behaviors/rspec.rb +12 -12
  53. data/lib/hecks/behaviors/runner.rb +20 -11
  54. data/lib/hecks/bench/cli.rb +16 -13
  55. data/lib/hecks/bench/environment.rb +1 -1
  56. data/lib/hecks/bench/report.rb +11 -7
  57. data/lib/hecks/bench/ruby_runner.rb +13 -8
  58. data/lib/hecks/bench/rust_runner.rb +19 -11
  59. data/lib/hecks/bench/suite.rb +48 -20
  60. data/lib/hecks/bench/workload.rb +42 -31
  61. data/lib/hecks/bluebook/aggregate.rb +15 -21
  62. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +18 -21
  63. data/lib/hecks/bluebook/assembly/build.rb +12 -7
  64. data/lib/hecks/bluebook/assembly/contracts/read_models.rb +70 -0
  65. data/lib/hecks/bluebook/assembly/contracts/rules.rb +84 -0
  66. data/lib/hecks/bluebook/assembly/contracts/sagas.rb +109 -0
  67. data/lib/hecks/bluebook/assembly/contracts/structure.rb +91 -0
  68. data/lib/hecks/bluebook/assembly/contracts.rb +9 -319
  69. data/lib/hecks/bluebook/assembly/marks.rb +9 -8
  70. data/lib/hecks/bluebook/attribute.rb +13 -10
  71. data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -3
  72. data/lib/hecks/bluebook/behaviour/read_model.rb +26 -13
  73. data/lib/hecks/bluebook/chapter.rb +22 -14
  74. data/lib/hecks/bluebook/command.rb +14 -18
  75. data/lib/hecks/bluebook/domain_port.rb +11 -8
  76. data/lib/hecks/bluebook/dsl/aggregate_builder/correction_sealing.rb +78 -0
  77. data/lib/hecks/bluebook/dsl/aggregate_builder/draining.rb +74 -0
  78. data/lib/hecks/bluebook/dsl/aggregate_builder/query_field_sealing.rb +105 -0
  79. data/lib/hecks/bluebook/dsl/aggregate_builder/query_sealing.rb +121 -0
  80. data/lib/hecks/bluebook/dsl/aggregate_builder/relationships.rb +128 -0
  81. data/lib/hecks/bluebook/dsl/aggregate_builder/rules.rb +84 -0
  82. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +61 -249
  83. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +51 -285
  84. data/lib/hecks/bluebook/dsl/attribute_collector/identity_resolution.rb +113 -0
  85. data/lib/hecks/bluebook/dsl/attribute_collector.rb +58 -117
  86. data/lib/hecks/bluebook/dsl/binding_proxy.rb +24 -19
  87. data/lib/hecks/bluebook/dsl/bluebook_builder/pending_givens.rb +109 -0
  88. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/correlation_keys.rb +105 -0
  89. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/event_shapes.rb +126 -0
  90. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/hop_tails.rb +79 -0
  91. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/projected_fields.rb +76 -0
  92. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/provisions.rb +65 -0
  93. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/query_hops.rb +123 -0
  94. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/references.rb +112 -0
  95. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/with_projections.rb +126 -0
  96. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +34 -595
  97. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +18 -107
  98. data/lib/hecks/bluebook/dsl/command_builder/implicit_attributes.rb +132 -0
  99. data/lib/hecks/bluebook/dsl/command_builder/mutations.rb +190 -0
  100. data/lib/hecks/bluebook/dsl/command_builder/owner.rb +22 -0
  101. data/lib/hecks/bluebook/dsl/command_builder/rules.rb +57 -0
  102. data/lib/hecks/bluebook/dsl/command_builder.rb +60 -360
  103. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +19 -13
  104. data/lib/hecks/bluebook/dsl/entity_builder/rules.rb +96 -0
  105. data/lib/hecks/bluebook/dsl/entity_builder/scope.rb +25 -0
  106. data/lib/hecks/bluebook/dsl/entity_builder/sealing.rb +94 -0
  107. data/lib/hecks/bluebook/dsl/entity_builder.rb +35 -169
  108. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +53 -24
  109. data/lib/hecks/bluebook/dsl/hecksagon_builder/chapter_scope.rb +133 -0
  110. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +3 -97
  111. data/lib/hecks/bluebook/dsl/identity_declaration.rb +73 -73
  112. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +7 -3
  113. data/lib/hecks/bluebook/dsl/need_word.rb +1 -1
  114. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +34 -29
  115. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +57 -41
  116. data/lib/hecks/bluebook/dsl/query_builder.rb +12 -15
  117. data/lib/hecks/bluebook/dsl/read_model_builder/sealing.rb +116 -0
  118. data/lib/hecks/bluebook/dsl/read_model_builder.rb +25 -102
  119. data/lib/hecks/bluebook/dsl/rule_reference.rb +26 -12
  120. data/lib/hecks/bluebook/dsl/translation_builder.rb +24 -14
  121. data/lib/hecks/bluebook/dsl/value_object_builder.rb +29 -19
  122. data/lib/hecks/bluebook/dsl/word_gate.rb +34 -27
  123. data/lib/hecks/bluebook/entity.rb +13 -17
  124. data/lib/hecks/bluebook/expression/ast_json/emitters.rb +93 -0
  125. data/lib/hecks/bluebook/expression/ast_json/emitters.rb-e +88 -0
  126. data/lib/hecks/bluebook/expression/ast_json.rb +49 -76
  127. data/lib/hecks/bluebook/expression/ast_reader.rb +95 -28
  128. data/lib/hecks/bluebook/expression/canonical_form.rb +6 -26
  129. data/lib/hecks/bluebook/expression/evaluator/parser.rb +62 -0
  130. data/lib/hecks/bluebook/expression/evaluator/scanning.rb +122 -0
  131. data/lib/hecks/bluebook/expression/evaluator.rb +11 -111
  132. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +28 -44
  133. data/lib/hecks/bluebook/expression/resolver/lookups.rb +77 -0
  134. data/lib/hecks/bluebook/expression/resolver/operations.rb +78 -0
  135. data/lib/hecks/bluebook/expression/resolver/parsing.rb +110 -0
  136. data/lib/hecks/bluebook/expression/resolver/scanning.rb +139 -0
  137. data/lib/hecks/bluebook/expression/resolver/values.rb +115 -0
  138. data/lib/hecks/bluebook/expression/resolver.rb +16 -414
  139. data/lib/hecks/bluebook/{hexagon.rb → hecksagon.rb} +22 -14
  140. data/lib/hecks/bluebook/keyword_fields.rb +42 -0
  141. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +7 -6
  142. data/lib/hecks/bluebook/meta_validator/judge/cells.rb +99 -0
  143. data/lib/hecks/bluebook/meta_validator/judge/dispatching.rb +111 -0
  144. data/lib/hecks/bluebook/meta_validator/judge/identity.rb +108 -0
  145. data/lib/hecks/bluebook/meta_validator/judge/walking.rb +141 -0
  146. data/lib/hecks/bluebook/meta_validator/judge.rb +31 -376
  147. data/lib/hecks/bluebook/meta_validator/modes.rb +137 -0
  148. data/lib/hecks/bluebook/meta_validator/plan/category.rb +44 -0
  149. data/lib/hecks/bluebook/meta_validator/plan/verbs.rb +73 -0
  150. data/lib/hecks/bluebook/meta_validator/plan.rb +38 -122
  151. data/lib/hecks/bluebook/meta_validator/readings/fields.rb +100 -0
  152. data/lib/hecks/bluebook/meta_validator/readings.rb +10 -95
  153. data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +89 -0
  154. data/lib/hecks/bluebook/meta_validator/reconstruction/reading.rb +96 -0
  155. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -151
  156. data/lib/hecks/bluebook/meta_validator/shapes/helpers.rb +83 -0
  157. data/lib/hecks/bluebook/meta_validator/shapes.rb +8 -75
  158. data/lib/hecks/bluebook/meta_validator/syntax_boot/disk_cache.rb +102 -0
  159. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +31 -95
  160. data/lib/hecks/bluebook/meta_validator/translation_judge/rules.rb +74 -0
  161. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +15 -65
  162. data/lib/hecks/bluebook/meta_validator/verdict_cache/prebuilt.rb +44 -0
  163. data/lib/hecks/bluebook/meta_validator/verdict_cache/tagging.rb +63 -0
  164. data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +25 -60
  165. data/lib/hecks/bluebook/meta_validator/world_judge.rb +8 -4
  166. data/lib/hecks/bluebook/meta_validator.rb +59 -175
  167. data/lib/hecks/bluebook/model_check/lifecycle_checks.rb +122 -0
  168. data/lib/hecks/bluebook/model_check/policy_checks.rb +129 -0
  169. data/lib/hecks/bluebook/model_check/saga_checks.rb +134 -0
  170. data/lib/hecks/bluebook/model_check/verbs.rb +69 -0
  171. data/lib/hecks/bluebook/model_check.rb +73 -413
  172. data/lib/hecks/bluebook/pattern_subset/refusals.rb +54 -0
  173. data/lib/hecks/bluebook/pattern_subset/scan.rb +58 -0
  174. data/lib/hecks/bluebook/pattern_subset.rb +93 -134
  175. data/lib/hecks/bluebook/process_manager.rb +10 -9
  176. data/lib/hecks/bluebook/project_discovery.rb +10 -7
  177. data/lib/hecks/bluebook/project_register.rb +42 -41
  178. data/lib/hecks/bluebook/query.rb +19 -12
  179. data/lib/hecks/bluebook/read_model.rb +41 -39
  180. data/lib/hecks/bluebook/smoke_test.rb +51 -36
  181. data/lib/hecks/bluebook/synthesizer.rb +13 -5
  182. data/lib/hecks/bluebook/translation.rb +12 -12
  183. data/lib/hecks/bluebook.rb +1 -1
  184. data/lib/hecks/cache_dir.rb +10 -0
  185. data/lib/hecks/chapters.rb +32 -16
  186. data/lib/hecks/cli/behaviors.rb +22 -15
  187. data/lib/hecks/cli/check_era.rb +2 -2
  188. data/lib/hecks/cli/command_table.rb +72 -0
  189. data/lib/hecks/cli/console.rb +10 -7
  190. data/lib/hecks/cli/deploy_template_diff.rb +22 -9
  191. data/lib/hecks/cli/document.rb +14 -10
  192. data/lib/hecks/cli/domain_stub.rb +1 -1
  193. data/lib/hecks/cli/domain_writer.rb +1 -1
  194. data/lib/hecks/cli/expression_projection.rb +8 -6
  195. data/lib/hecks/cli/follow.rb +10 -4
  196. data/lib/hecks/cli/interview_aggregate.rb +132 -0
  197. data/lib/hecks/cli/interview_draft.rb +16 -200
  198. data/lib/hecks/cli/interview_record.rb +130 -0
  199. data/lib/hecks/cli/interview_run.rb +19 -8
  200. data/lib/hecks/cli/interview_session/agent_state.rb +70 -0
  201. data/lib/hecks/cli/interview_session/catalog.rb +76 -0
  202. data/lib/hecks/cli/interview_session/manual_findings.rb +48 -0
  203. data/lib/hecks/cli/interview_session/proposals.rb +90 -0
  204. data/lib/hecks/cli/interview_session.rb +8 -205
  205. data/lib/hecks/cli/interview_shape.rb +13 -6
  206. data/lib/hecks/cli/ir.rb +8 -11
  207. data/lib/hecks/cli/launcher_words.rb +168 -0
  208. data/lib/hecks/cli/model_check/examination.rb +93 -0
  209. data/lib/hecks/cli/model_check/sources.rb +57 -0
  210. data/lib/hecks/cli/model_check.rb +28 -134
  211. data/lib/hecks/cli/project_cli/launcher_source.rb +177 -0
  212. data/lib/hecks/cli/project_cli/templates.rb +106 -0
  213. data/lib/hecks/cli/project_cli.rb +57 -236
  214. data/lib/hecks/cli/project_diagrams.rb +26 -4
  215. data/lib/hecks/cli/project_glossary.rb +19 -9
  216. data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +29 -13
  217. data/lib/hecks/cli/release.rb +29 -22
  218. data/lib/hecks/cli/release_gem.rb +12 -6
  219. data/lib/hecks/cli/rspec_io_parallel_files.rb +87 -30
  220. data/lib/hecks/cli/rspec_shard_files.rb +24 -9
  221. data/lib/hecks/cli/run.rb +25 -44
  222. data/lib/hecks/cli/run_expectations.rb +63 -0
  223. data/lib/hecks/cli/seed_semantics_corpus.rb +37 -17
  224. data/lib/hecks/cli/smoke_http/checks.rb +66 -0
  225. data/lib/hecks/cli/smoke_http/settings.rb +63 -0
  226. data/lib/hecks/cli/smoke_http/transport.rb +45 -0
  227. data/lib/hecks/cli/smoke_http.rb +8 -142
  228. data/lib/hecks/cli/smoke_test.rb +18 -4
  229. data/lib/hecks/cli/stores.rb +7 -4
  230. data/lib/hecks/cli/stress_concurrency_specs/reporting.rb +44 -0
  231. data/lib/hecks/cli/stress_concurrency_specs/usage.rb +28 -0
  232. data/lib/hecks/cli/stress_concurrency_specs.rb +82 -80
  233. data/lib/hecks/cli.rb +32 -208
  234. data/lib/hecks/codemod/runner.rb +92 -0
  235. data/lib/hecks/codemod/sweep.rb +94 -0
  236. data/lib/hecks/codemod.rb +22 -165
  237. data/lib/hecks/corpus/routes.rb +34 -0
  238. data/lib/hecks/corpus/rust.rb +193 -0
  239. data/lib/hecks/corpus/sources.rb +46 -0
  240. data/lib/hecks/corpus.rb +28 -265
  241. data/lib/hecks/deploy/bluebook/deploy.bluebook +109 -0
  242. data/lib/hecks/deploy/oidc.json +10 -0
  243. data/lib/hecks/doc/reference/coverage.rb +70 -0
  244. data/lib/hecks/doc/reference/harvester.rb +55 -0
  245. data/lib/hecks/doc/reference/readme.rb +89 -0
  246. data/lib/hecks/doc/reference/rendering.rb +149 -0
  247. data/lib/hecks/doc/reference.rb +14 -273
  248. data/lib/hecks/doors/cli_door/nesting.rb +34 -0
  249. data/lib/hecks/doors/cli_door/shorthand.rb +85 -0
  250. data/lib/hecks/doors/cli_door.rb +23 -95
  251. data/lib/hecks/doors/cli_runner/answers.rb +138 -0
  252. data/lib/hecks/doors/cli_runner/resolution.rb +146 -0
  253. data/lib/hecks/doors/cli_runner/settling.rb +115 -0
  254. data/lib/hecks/doors/cli_runner/streaming.rb +90 -0
  255. data/lib/hecks/doors/cli_runner/suggestions.rb +43 -0
  256. data/lib/hecks/doors/cli_runner.rb +12 -336
  257. data/lib/hecks/doors/command_request.rb +42 -31
  258. data/lib/hecks/doors/handle.rb +32 -30
  259. data/lib/hecks/doors/launcher_options.rb +62 -7
  260. data/lib/hecks/doors/mcp_door/properties.rb +47 -0
  261. data/lib/hecks/doors/mcp_door/tool_calls.rb +113 -0
  262. data/lib/hecks/doors/mcp_door/tool_definitions/auditing.rb +51 -0
  263. data/lib/hecks/doors/mcp_door/tool_definitions/calling.rb +69 -0
  264. data/lib/hecks/doors/mcp_door/tool_definitions/reading.rb +97 -0
  265. data/lib/hecks/doors/mcp_door/tool_definitions.rb +15 -0
  266. data/lib/hecks/doors/mcp_door.rb +55 -301
  267. data/lib/hecks/doors/mcp_door_scope/argument_policy.rb +92 -0
  268. data/lib/hecks/doors/mcp_door_scope/env_problems.rb +55 -0
  269. data/lib/hecks/doors/mcp_door_scope/presenter.rb +78 -0
  270. data/lib/hecks/doors/mcp_door_scope.rb +16 -172
  271. data/lib/hecks/doors/ruby_door/aggregate_door.rb +1 -1
  272. data/lib/hecks/doors/ruby_door/chapter.rb +33 -16
  273. data/lib/hecks/doors/ruby_door.rb +14 -11
  274. data/lib/hecks/doors/usage_cache.rb +32 -16
  275. data/lib/hecks/doors.rb +10 -4
  276. data/lib/hecks/embryonaut_bluebook/manifest.rb +11 -3
  277. data/lib/hecks/embryonaut_bluebook/registry/changelog.rb +26 -0
  278. data/lib/hecks/embryonaut_bluebook/registry/versions.rb +27 -0
  279. data/lib/hecks/embryonaut_bluebook/registry.rb +27 -37
  280. data/lib/hecks/embryonaut_bluebook/vendor/acceptance.rb +37 -0
  281. data/lib/hecks/embryonaut_bluebook/vendor.rb +22 -36
  282. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +9 -6
  283. data/lib/hecks/embryonaut_bluebook.rb +16 -11
  284. data/lib/hecks/engine_agreement.rb +24 -17
  285. data/lib/hecks/forms/app/commands.rb +98 -0
  286. data/lib/hecks/forms/app/queries.rb +62 -0
  287. data/lib/hecks/forms/app/records.rb +67 -0
  288. data/lib/hecks/forms/app/responses.rb +46 -0
  289. data/lib/hecks/forms/app.rb +33 -221
  290. data/lib/hecks/forms/banking_presentation.rb +5 -0
  291. data/lib/hecks/forms/command_form_renderer.rb +55 -14
  292. data/lib/hecks/forms/field_controls.rb +95 -0
  293. data/lib/hecks/forms/field_renderer.rb +34 -88
  294. data/lib/hecks/forms/field_shape.rb +9 -34
  295. data/lib/hecks/forms/html.rb +1 -1
  296. data/lib/hecks/forms/index_renderer.rb +14 -9
  297. data/lib/hecks/forms/page.rb +2 -106
  298. data/lib/hecks/forms/page_assets.rb +88 -0
  299. data/lib/hecks/forms/page_script.rb +28 -0
  300. data/lib/hecks/forms/params.rb +17 -8
  301. data/lib/hecks/forms/query_form_renderer.rb +11 -7
  302. data/lib/hecks/forms/record_renderer.rb +28 -19
  303. data/lib/hecks/forms/reference_options.rb +1 -1
  304. data/lib/hecks/forms/text_shape.rb +40 -0
  305. data/lib/hecks/fqn.rb +64 -32
  306. data/lib/hecks/framework.rb +10 -3
  307. data/lib/hecks/freezer.rb +10 -1
  308. data/lib/hecks/fuzzing/bounded_exhaustive_expressions/fragments.rb +61 -0
  309. data/lib/hecks/fuzzing/bounded_exhaustive_expressions/productions.rb +217 -0
  310. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +5 -194
  311. data/lib/hecks/fuzzing/combination_miner.rb +23 -12
  312. data/lib/hecks/fuzzing/concurrent_dispatch/racing.rb +64 -0
  313. data/lib/hecks/fuzzing/concurrent_dispatch/world_copy.rb +66 -0
  314. data/lib/hecks/fuzzing/concurrent_dispatch.rb +31 -107
  315. data/lib/hecks/fuzzing/coverage_campaign.rb +49 -24
  316. data/lib/hecks/fuzzing/differential/wire_comparison.rb +74 -0
  317. data/lib/hecks/fuzzing/differential.rb +59 -84
  318. data/lib/hecks/fuzzing/domain_generator/block_rendering.rb +70 -0
  319. data/lib/hecks/fuzzing/domain_generator/builder/attribute_shapes.rb +105 -0
  320. data/lib/hecks/fuzzing/domain_generator/builder/shapes.rb +97 -0
  321. data/lib/hecks/fuzzing/domain_generator/builder/wiring.rb +128 -0
  322. data/lib/hecks/fuzzing/domain_generator/builder.rb +105 -0
  323. data/lib/hecks/fuzzing/domain_generator/pruning.rb +90 -0
  324. data/lib/hecks/fuzzing/domain_generator/removals.rb +62 -0
  325. data/lib/hecks/fuzzing/domain_generator/rendering.rb +94 -0
  326. data/lib/hecks/fuzzing/domain_generator/tokens.rb +38 -0
  327. data/lib/hecks/fuzzing/domain_generator.rb +7 -555
  328. data/lib/hecks/fuzzing/era_boundary.rb +34 -24
  329. data/lib/hecks/fuzzing/failure_triage.rb +80 -0
  330. data/lib/hecks/fuzzing/form_census/chapter_forms.rb +38 -0
  331. data/lib/hecks/fuzzing/form_census/reference_forms.rb +49 -0
  332. data/lib/hecks/fuzzing/form_census.rb +44 -58
  333. data/lib/hecks/fuzzing/generated_domain_check.rb +23 -11
  334. data/lib/hecks/fuzzing/isolated_boot/copying.rb +62 -0
  335. data/lib/hecks/fuzzing/isolated_boot/postgres_scratch.rb +148 -0
  336. data/lib/hecks/fuzzing/isolated_boot/scratch_schema.rb +27 -0
  337. data/lib/hecks/fuzzing/isolated_boot/worlds.rb +102 -0
  338. data/lib/hecks/fuzzing/isolated_boot.rb +29 -252
  339. data/lib/hecks/fuzzing/mutation/checks.rb +76 -0
  340. data/lib/hecks/fuzzing/mutation/finders.rb +136 -0
  341. data/lib/hecks/fuzzing/mutation/judge.rb +94 -0
  342. data/lib/hecks/fuzzing/mutation/observation.rb +38 -0
  343. data/lib/hecks/fuzzing/mutation/operators.rb +52 -0
  344. data/lib/hecks/fuzzing/mutation/report.rb +78 -0
  345. data/lib/hecks/fuzzing/mutation/run.rb +99 -0
  346. data/lib/hecks/fuzzing/mutation/selection.rb +32 -0
  347. data/lib/hecks/fuzzing/mutation/site.rb +21 -0
  348. data/lib/hecks/fuzzing/mutation/source_map.rb +59 -0
  349. data/lib/hecks/fuzzing/mutation.rb +12 -0
  350. data/lib/hecks/fuzzing/persistence_parity.rb +5 -5
  351. data/lib/hecks/fuzzing/properties/aggregation_recompute.rb +121 -0
  352. data/lib/hecks/fuzzing/properties/catalog.rb +89 -0
  353. data/lib/hecks/fuzzing/properties/corrections.rb +23 -20
  354. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +64 -185
  355. data/lib/hecks/fuzzing/properties/group_by_recompute.rb +69 -0
  356. data/lib/hecks/fuzzing/properties/guaranteed_by_construction.rb +63 -0
  357. data/lib/hecks/fuzzing/properties/guards.rb +76 -108
  358. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +66 -227
  359. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +46 -35
  360. data/lib/hecks/fuzzing/properties/mutation_recompute.rb +162 -0
  361. data/lib/hecks/fuzzing/properties/outbox.rb +41 -24
  362. data/lib/hecks/fuzzing/properties/piece_invariants.rb +61 -0
  363. data/lib/hecks/fuzzing/properties/policy_wiring.rb +140 -0
  364. data/lib/hecks/fuzzing/properties/query_rows.rb +67 -0
  365. data/lib/hecks/fuzzing/properties/querying.rb +69 -90
  366. data/lib/hecks/fuzzing/properties/read_model_names.rb +50 -0
  367. data/lib/hecks/fuzzing/properties/read_models.rb +138 -0
  368. data/lib/hecks/fuzzing/properties/references.rb +100 -0
  369. data/lib/hecks/fuzzing/properties/role_checks.rb +50 -0
  370. data/lib/hecks/fuzzing/properties/tenant_scope.rb +84 -0
  371. data/lib/hecks/fuzzing/properties.rb +13 -119
  372. data/lib/hecks/fuzzing/qa_settings.rb +23 -17
  373. data/lib/hecks/fuzzing/replay/fan_out.rb +78 -0
  374. data/lib/hecks/fuzzing/replay/filters.rb +72 -0
  375. data/lib/hecks/fuzzing/replay/guard_check.rb +88 -0
  376. data/lib/hecks/fuzzing/replay/mutation_trace.rb +117 -0
  377. data/lib/hecks/fuzzing/replay/observation.rb +60 -0
  378. data/lib/hecks/fuzzing/replay/read_only_steps.rb +84 -0
  379. data/lib/hecks/fuzzing/replay/role_check.rb +49 -0
  380. data/lib/hecks/fuzzing/replay/session.rb +167 -0
  381. data/lib/hecks/fuzzing/replay.rb +36 -442
  382. data/lib/hecks/fuzzing/runtime_coverage.rb +70 -0
  383. data/lib/hecks/fuzzing/rust_gap_manifest.rb +3 -4
  384. data/lib/hecks/fuzzing/self_consistency/saga_redelivery.rb +133 -0
  385. data/lib/hecks/fuzzing/self_consistency/sagas.rb +93 -0
  386. data/lib/hecks/fuzzing/self_consistency/value_objects.rb +87 -0
  387. data/lib/hecks/fuzzing/self_consistency.rb +8 -213
  388. data/lib/hecks/fuzzing/sequence_generator/adversary/argument_mutations.rb +116 -0
  389. data/lib/hecks/fuzzing/sequence_generator/adversary/caller_draw.rb +68 -0
  390. data/lib/hecks/fuzzing/sequence_generator/adversary/identity_mutations.rb +62 -0
  391. data/lib/hecks/fuzzing/sequence_generator/adversary/precedence_mutations.rb +126 -0
  392. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +23 -283
  393. data/lib/hecks/fuzzing/sequence_generator/argument_drawing.rb +78 -0
  394. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +69 -53
  395. data/lib/hecks/fuzzing/sequence_generator/identity_shaping.rb +85 -0
  396. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +20 -16
  397. data/lib/hecks/fuzzing/sequence_generator/picker.rb +12 -6
  398. data/lib/hecks/fuzzing/sequence_generator/prefixing.rb +45 -0
  399. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +19 -8
  400. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +43 -144
  401. data/lib/hecks/fuzzing/sequence_generator.rb +65 -63
  402. data/lib/hecks/fuzzing/shrinker/value_simplification.rb +64 -0
  403. data/lib/hecks/fuzzing/shrinker.rb +36 -29
  404. data/lib/hecks/fuzzing/target_capabilities.rb +10 -4
  405. data/lib/hecks/fuzzing/value_generator.rb +27 -17
  406. data/lib/hecks/fuzzing.rb +3 -0
  407. data/lib/hecks/gate/stages.yml +11 -1
  408. data/lib/hecks/grammar/evolve/arguments.rb +90 -0
  409. data/lib/hecks/grammar/evolve/keywords.rb +81 -0
  410. data/lib/hecks/grammar/evolve/seeds.rb +172 -0
  411. data/lib/hecks/grammar/evolve.rb +22 -263
  412. data/lib/hecks/grammar/operators.rb +111 -0
  413. data/lib/hecks/grammar.rb +53 -126
  414. data/lib/hecks/hecks/adapters/bluebook_report.rb +6 -6
  415. data/lib/hecks/hecks/adapters/codebase/codemods.rb +1 -1
  416. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +23 -9
  417. data/lib/hecks/hecks/adapters/codebase/language/edits.rb +75 -0
  418. data/lib/hecks/hecks/adapters/codebase/language.rb +30 -72
  419. data/lib/hecks/hecks/adapters/codebase/promotion/candidates.rb +54 -0
  420. data/lib/hecks/hecks/adapters/codebase/promotion/gate.rb +50 -0
  421. data/lib/hecks/hecks/adapters/codebase/promotion/move.rb +70 -0
  422. data/lib/hecks/hecks/adapters/codebase/promotion/standing.rb +88 -0
  423. data/lib/hecks/hecks/adapters/codebase/promotion/watch.rb +83 -0
  424. data/lib/hecks/hecks/adapters/codebase/promotion.rb +115 -0
  425. data/lib/hecks/hecks/adapters/codebase/publishing.rb +31 -12
  426. data/lib/hecks/hecks/adapters/codebase/regeneration.rb +43 -6
  427. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +16 -5
  428. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +9 -1
  429. data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +1 -1
  430. data/lib/hecks/hecks/adapters/codebase/style.rb +1 -1
  431. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +11 -5
  432. data/lib/hecks/hecks/adapters/codebase/test_suite.rb +27 -8
  433. data/lib/hecks/hecks/adapters/console_capture.rb +21 -17
  434. data/lib/hecks/hecks/adapters/cost_explorer.rb +11 -6
  435. data/lib/hecks/hecks/adapters/deploy_plans.rb +3 -3
  436. data/lib/hecks/hecks/adapters/deploy_toolchain/answers.rb +142 -0
  437. data/lib/hecks/hecks/adapters/deploy_toolchain/scripts.rb +95 -0
  438. data/lib/hecks/hecks/adapters/deploy_toolchain/statuses.rb +74 -0
  439. data/lib/hecks/hecks/adapters/deploy_toolchain.rb +21 -239
  440. data/lib/hecks/hecks/adapters/finding_github.rb +2 -2
  441. data/lib/hecks/hecks/adapters/first_admin.rb +22 -8
  442. data/lib/hecks/hecks/adapters/git.rb +18 -5
  443. data/lib/hecks/hecks/adapters/git_refs.rb +144 -0
  444. data/lib/hecks/hecks/adapters/github_rulesets.rb +128 -0
  445. data/lib/hecks/hecks/adapters/host_http.rb +16 -6
  446. data/lib/hecks/hecks/adapters/in_process_boot.rb +9 -5
  447. data/lib/hecks/hecks/adapters/in_process_operations/tailing.rb +61 -0
  448. data/lib/hecks/hecks/adapters/in_process_operations.rb +33 -35
  449. data/lib/hecks/hecks/adapters/journal_store/changes.rb +21 -15
  450. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +29 -12
  451. data/lib/hecks/hecks/adapters/journal_store/readings/attestation.rb +52 -0
  452. data/lib/hecks/hecks/adapters/journal_store/readings/scaffolding.rb +52 -0
  453. data/lib/hecks/hecks/adapters/journal_store/readings.rb +5 -62
  454. data/lib/hecks/hecks/adapters/local_files.rb +27 -10
  455. data/lib/hecks/hecks/adapters/pg_admin/ownership.rb +115 -0
  456. data/lib/hecks/hecks/adapters/pg_admin.rb +14 -87
  457. data/lib/hecks/hecks/adapters/process_pool.rb +75 -21
  458. data/lib/hecks/hecks/adapters/rust_toolchain.rb +12 -4
  459. data/lib/hecks/hecks/adapters/site_toolchain.rb +16 -7
  460. data/lib/hecks/hecks/adapters/terminal.rb +13 -9
  461. data/lib/hecks/hecks/codebase.bluebook +322 -5
  462. data/lib/hecks/hecks/custodian.behaviors +6 -0
  463. data/lib/hecks/hecks/custodian.bluebook +37 -0
  464. data/lib/hecks/hecks/hecks.hecksagon +22 -0
  465. data/lib/hecks/hecks/hecks.world +10 -2
  466. data/lib/hecks/kernel_capabilities/templates.rb +92 -0
  467. data/lib/hecks/kernel_capabilities.rb +18 -85
  468. data/lib/hecks/language/bluebook/vocabulary.bluebook +46 -1
  469. data/lib/hecks/literal/item_splitter.rb +50 -0
  470. data/lib/hecks/literal.rb +29 -38
  471. data/lib/hecks/mcp_stdio_guard.rb +8 -8
  472. data/lib/hecks/naming.rb +9 -3
  473. data/lib/hecks/persistence_legacy_fixture/postgres_stores.rb +81 -0
  474. data/lib/hecks/persistence_legacy_fixture/regenerate.rb +26 -66
  475. data/lib/hecks/persistence_legacy_fixture.rb +13 -10
  476. data/lib/hecks/ports/access_control.rb +13 -10
  477. data/lib/hecks/ports/agent/answers.rb +2 -2
  478. data/lib/hecks/ports/agent.rb +13 -10
  479. data/lib/hecks/ports/authentication.rb +13 -10
  480. data/lib/hecks/ports/authorization.rb +13 -10
  481. data/lib/hecks/ports/clock.rb +13 -10
  482. data/lib/hecks/ports/extraction.rb +13 -12
  483. data/lib/hecks/ports/identity_assignment.rb +13 -10
  484. data/lib/hecks/ports/identity_generation.rb +13 -10
  485. data/lib/hecks/ports/identity_resolution.rb +13 -10
  486. data/lib/hecks/ports/key_vault.rb +13 -10
  487. data/lib/hecks/ports/persistence/append_only.rb +5 -5
  488. data/lib/hecks/ports/persistence/binding_policy.rb +33 -9
  489. data/lib/hecks/ports/persistence/codec_boundary.rb +22 -11
  490. data/lib/hecks/ports/persistence/constants.rb +10 -0
  491. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +18 -16
  492. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +27 -18
  493. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +52 -23
  494. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +14 -8
  495. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +17 -6
  496. data/lib/hecks/ports/persistence/plugins/era/lineage/coverage.rb +58 -0
  497. data/lib/hecks/ports/persistence/plugins/era/lineage/rewrite.rb +130 -0
  498. data/lib/hecks/ports/persistence/plugins/era/lineage/rules.rb +25 -0
  499. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +20 -180
  500. data/lib/hecks/ports/persistence/plugins/era/postgres_era/boot.rb +41 -0
  501. data/lib/hecks/ports/persistence/plugins/era/postgres_era/class_methods.rb +105 -0
  502. data/lib/hecks/ports/persistence/plugins/era/postgres_era/dialect.rb +137 -0
  503. data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +25 -28
  504. data/lib/hecks/ports/persistence/plugins/era/postgres_era/head_writes.rb +62 -0
  505. data/lib/hecks/ports/persistence/plugins/era/postgres_era/journal.rb +128 -0
  506. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/base_sql.rb +74 -0
  507. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/chain_sql.rb +169 -0
  508. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/domain_rename.rb +91 -0
  509. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_integrity.rb +99 -0
  510. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +0 -73
  511. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +55 -39
  512. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +51 -222
  513. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/merge_writes.rb +120 -0
  514. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +85 -60
  515. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +97 -181
  516. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +19 -19
  517. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/sql_templates.rb +88 -0
  518. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +77 -118
  519. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +3 -117
  520. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_sql.rb +116 -0
  521. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +3 -1
  522. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/context.rb +38 -0
  523. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +43 -25
  524. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +62 -38
  525. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +21 -16
  526. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +66 -86
  527. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/refusals.rb +75 -0
  528. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +27 -9
  529. data/lib/hecks/ports/persistence/plugins/era/postgres_era/query_phases.rb +63 -0
  530. data/lib/hecks/ports/persistence/plugins/era/postgres_era/sagas.rb +78 -0
  531. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +28 -482
  532. data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +40 -12
  533. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +22 -15
  534. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +39 -19
  535. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -16
  536. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +48 -25
  537. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +60 -99
  538. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/path_diff.rb +57 -0
  539. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +21 -11
  540. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +13 -4
  541. data/lib/hecks/ports/persistence/postgres_dump/connection.rb +4 -2
  542. data/lib/hecks/ports/persistence/postgres_dump.rb +13 -7
  543. data/lib/hecks/ports/persistence/repository_factory.rb +35 -11
  544. data/lib/hecks/ports/persistence/state_codec.rb +10 -0
  545. data/lib/hecks/ports/persistence.rb +1 -10
  546. data/lib/hecks/ports/projection.rb +34 -21
  547. data/lib/hecks/ports/query/in_memory.rb +16 -8
  548. data/lib/hecks/projection_files/expression_tables.rb +64 -0
  549. data/lib/hecks/projection_files/texts.rb +67 -0
  550. data/lib/hecks/projection_files.rb +19 -103
  551. data/lib/hecks/projections/bootstrap_table.rb +43 -29
  552. data/lib/hecks/projections/deploy/bastion_lines.rb +32 -0
  553. data/lib/hecks/projections/deploy/box/access.rb +73 -0
  554. data/lib/hecks/projections/deploy/box/caddy.rb +87 -0
  555. data/lib/hecks/projections/deploy/box/compose.rb +70 -0
  556. data/lib/hecks/projections/deploy/box/hosting.rb +4 -105
  557. data/lib/hecks/projections/deploy/box/hosting_parts.rb +97 -0
  558. data/lib/hecks/projections/deploy/box/hosting_settings.rb +1 -1
  559. data/lib/hecks/projections/deploy/box/roll_recipe.rb +1 -1
  560. data/lib/hecks/projections/deploy/box/roll_scripts.rb +137 -0
  561. data/lib/hecks/projections/deploy/box/settings/checks.rb +38 -0
  562. data/lib/hecks/projections/deploy/box/settings/containers.rb +123 -0
  563. data/lib/hecks/projections/deploy/box/settings/origin.rb +56 -0
  564. data/lib/hecks/projections/deploy/box/settings/patterns.rb +47 -0
  565. data/lib/hecks/projections/deploy/box/settings/types.rb +76 -0
  566. data/lib/hecks/projections/deploy/box/settings.rb +76 -263
  567. data/lib/hecks/projections/deploy/box/shared_database.rb +69 -0
  568. data/lib/hecks/projections/deploy/box/stack_yaml.rb +107 -0
  569. data/lib/hecks/projections/deploy/box/templates/MIGRATION.md.tmpl +39 -0
  570. data/lib/hecks/projections/deploy/box/templates/Makefile.tmpl +23 -0
  571. data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +42 -2
  572. data/lib/hecks/projections/deploy/box/templates/deploy-service.services-roll.part +2 -1
  573. data/lib/hecks/projections/deploy/box/templates/deploy-service.taskdef-roll.part +2 -1
  574. data/lib/hecks/projections/deploy/box/templates/deploy-usage-services.tmpl +4 -0
  575. data/lib/hecks/projections/deploy/box/templates/deploy-usage-taskdef.tmpl +5 -0
  576. data/lib/hecks/projections/deploy/box/templates/ecr-repository.yaml.tmpl +9 -0
  577. data/lib/hecks/projections/deploy/box/templates/mode-summary-services.tmpl +2 -0
  578. data/lib/hecks/projections/deploy/box/templates/mode-summary-taskdef.tmpl +4 -0
  579. data/lib/hecks/projections/deploy/box/templates/provision-database.sh.tmpl +97 -0
  580. data/lib/hecks/projections/deploy/box/templates/restore-to-rds.sh.tmpl +4 -2
  581. data/lib/hecks/projections/deploy/box/templates/services-block.tmpl +9 -0
  582. data/lib/hecks/projections/deploy/box/templates/tunnel-egress.yaml.tmpl +11 -0
  583. data/lib/hecks/projections/deploy/box/templates/verify-copy.sh.tmpl +2 -1
  584. data/lib/hecks/projections/deploy/box/templates/writable-secrets.yaml.tmpl +7 -0
  585. data/lib/hecks/projections/deploy/box.rb +43 -491
  586. data/lib/hecks/projections/deploy/fargate/assembly.rb +13 -142
  587. data/lib/hecks/projections/deploy/fargate/cdn/behaviors.rb +76 -0
  588. data/lib/hecks/projections/deploy/fargate/cdn/lines.rb +112 -0
  589. data/lib/hecks/projections/deploy/fargate/cdn/options.rb +85 -0
  590. data/lib/hecks/projections/deploy/fargate/cdn.rb +23 -215
  591. data/lib/hecks/projections/deploy/fargate/check.rb +16 -6
  592. data/lib/hecks/projections/deploy/fargate/containers/definition_lines.rb +61 -0
  593. data/lib/hecks/projections/deploy/fargate/containers/reading.rb +86 -0
  594. data/lib/hecks/projections/deploy/fargate/containers/rendering.rb +132 -0
  595. data/lib/hecks/projections/deploy/fargate/containers/routing.rb +93 -0
  596. data/lib/hecks/projections/deploy/fargate/containers.rb +10 -286
  597. data/lib/hecks/projections/deploy/fargate/extras/reading.rb +90 -0
  598. data/lib/hecks/projections/deploy/fargate/extras/rendering.rb +81 -0
  599. data/lib/hecks/projections/deploy/fargate/extras.rb +9 -158
  600. data/lib/hecks/projections/deploy/fargate/monitoring/alarms.rb +115 -0
  601. data/lib/hecks/projections/deploy/fargate/monitoring/reading.rb +84 -0
  602. data/lib/hecks/projections/deploy/fargate/monitoring/topic.rb +59 -0
  603. data/lib/hecks/projections/deploy/fargate/monitoring/warmer.rb +90 -0
  604. data/lib/hecks/projections/deploy/fargate/monitoring/warmer_roles.rb +76 -0
  605. data/lib/hecks/projections/deploy/fargate/monitoring.rb +14 -348
  606. data/lib/hecks/projections/deploy/fargate/sections.rb +115 -0
  607. data/lib/hecks/projections/deploy/fargate/settings/ids.rb +55 -0
  608. data/lib/hecks/projections/deploy/fargate/settings/tuning.rb +77 -0
  609. data/lib/hecks/projections/deploy/fargate/settings.rb +17 -104
  610. data/lib/hecks/projections/deploy/fargate/stack/blocks.rb +91 -0
  611. data/lib/hecks/projections/deploy/fargate/stack/readers.rb +87 -0
  612. data/lib/hecks/projections/deploy/fargate/stack/recipes.rb +106 -0
  613. data/lib/hecks/projections/deploy/fargate/stack.rb +146 -0
  614. data/lib/hecks/projections/deploy/fargate/task_sections.rb +56 -0
  615. data/lib/hecks/projections/deploy/fargate/yaml.rb +1 -1
  616. data/lib/hecks/projections/deploy/fargate.rb +51 -756
  617. data/lib/hecks/projections/deploy/lambda/pii.rb +49 -0
  618. data/lib/hecks/projections/deploy/lambda/stack/blocks.rb +118 -0
  619. data/lib/hecks/projections/deploy/lambda/stack/checks.rb +64 -0
  620. data/lib/hecks/projections/deploy/lambda/stack/deploy_chain.rb +119 -0
  621. data/lib/hecks/projections/deploy/lambda/stack/readers.rb +62 -0
  622. data/lib/hecks/projections/deploy/lambda/stack/reading.rb +170 -0
  623. data/lib/hecks/projections/deploy/lambda/stack/reading_web.rb +53 -0
  624. data/lib/hecks/projections/deploy/lambda/stack/recipes.rb +112 -0
  625. data/lib/hecks/projections/deploy/lambda/stack/web.rb +57 -0
  626. data/lib/hecks/projections/deploy/lambda/stack.rb +54 -0
  627. data/lib/hecks/projections/deploy/lambda.rb +77 -1885
  628. data/lib/hecks/projections/deploy/preview/access_yaml.rb +8 -74
  629. data/lib/hecks/projections/deploy/preview/containers.rb +18 -7
  630. data/lib/hecks/projections/deploy/preview/routing_yaml.rb +15 -87
  631. data/lib/hecks/projections/deploy/preview/settings.rb +7 -4
  632. data/lib/hecks/projections/deploy/preview/task_yaml.rb +42 -106
  633. data/lib/hecks/projections/deploy/preview/template.rb +11 -106
  634. data/lib/hecks/projections/deploy/preview/yaml_text.rb +1 -1
  635. data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +1 -1
  636. data/lib/hecks/projections/deploy/scripts/settings.rb +14 -6
  637. data/lib/hecks/projections/deploy/scripts.rb +11 -9
  638. data/lib/hecks/projections/deploy/shared/rows.rb +48 -0
  639. data/lib/hecks/projections/deploy/shared.rb +89 -449
  640. data/lib/hecks/projections/deploy/shared_database_instance/templates/Makefile.tmpl +11 -0
  641. data/lib/hecks/projections/deploy/shared_database_instance/templates/README.md.tmpl +25 -0
  642. data/lib/hecks/projections/deploy/shared_database_instance/templates/rds.yaml.tmpl +180 -0
  643. data/lib/hecks/projections/deploy/shared_database_instance.rb +106 -0
  644. data/lib/hecks/projections/deploy/smoke.rb +15 -10
  645. data/lib/hecks/projections/deploy/template_diff/comparer.rb +21 -147
  646. data/lib/hecks/projections/deploy/template_diff/normalizer.rb +60 -0
  647. data/lib/hecks/projections/deploy/template_diff/value_diff.rb +136 -0
  648. data/lib/hecks/projections/deploy/template_diff.rb +8 -3
  649. data/lib/hecks/projections/deploy/templates/fargate/Dockerfile.tmpl +28 -0
  650. data/lib/hecks/projections/deploy/templates/fargate/Makefile.tmpl +63 -0
  651. data/lib/hecks/projections/deploy/templates/fargate/always_params.tmpl +4 -0
  652. data/lib/hecks/projections/deploy/templates/fargate/deploy_plain.tmpl +1 -0
  653. data/lib/hecks/projections/deploy/templates/fargate/deploy_shared.tmpl +11 -0
  654. data/lib/hecks/projections/deploy/templates/fargate/mint_era_own.tmpl +44 -0
  655. data/lib/hecks/projections/deploy/templates/fargate/mint_era_shared.tmpl +8 -0
  656. data/lib/hecks/projections/deploy/templates/fargate/missing_owner.tmpl +9 -0
  657. data/lib/hecks/projections/deploy/templates/fargate/oauth_params.tmpl +7 -0
  658. data/lib/hecks/projections/deploy/templates/fargate/oauth_task_env.tmpl +4 -0
  659. data/lib/hecks/projections/deploy/templates/fargate/oauth_task_policy.tmpl +7 -0
  660. data/lib/hecks/projections/deploy/templates/fargate/owning_params.tmpl +33 -0
  661. data/lib/hecks/projections/deploy/templates/fargate/template.yaml.tmpl +281 -0
  662. data/lib/hecks/projections/deploy/templates/lambda/Makefile.tmpl +218 -0
  663. data/lib/hecks/projections/deploy/templates/lambda/aurora_depends.tmpl +18 -0
  664. data/lib/hecks/projections/deploy/templates/lambda/build_dispatch_none.tmpl +10 -0
  665. data/lib/hecks/projections/deploy/templates/lambda/build_pg.tmpl +15 -0
  666. data/lib/hecks/projections/deploy/templates/lambda/build_plain.tmpl +2 -0
  667. data/lib/hecks/projections/deploy/templates/lambda/build_web.tmpl +11 -0
  668. data/lib/hecks/projections/deploy/templates/lambda/env_blind_guard.tmpl +4 -0
  669. data/lib/hecks/projections/deploy/templates/lambda/mint_era_own.tmpl +122 -0
  670. data/lib/hecks/projections/deploy/templates/lambda/mint_era_shared.tmpl +47 -0
  671. data/lib/hecks/projections/deploy/templates/lambda/missing_owner.tmpl +9 -0
  672. data/lib/hecks/projections/deploy/templates/lambda/nat_comment_oauth.tmpl +14 -0
  673. data/lib/hecks/projections/deploy/templates/lambda/nat_comment_plain.tmpl +3 -0
  674. data/lib/hecks/projections/deploy/templates/lambda/oauth_note.tmpl +8 -0
  675. data/lib/hecks/projections/deploy/templates/lambda/params_oauth.tmpl +13 -0
  676. data/lib/hecks/projections/deploy/templates/lambda/params_shared.tmpl +33 -0
  677. data/lib/hecks/projections/deploy/templates/lambda/pg_native.tmpl +71 -0
  678. data/lib/hecks/projections/deploy/templates/lambda/pii_oac.tmpl +8 -0
  679. data/lib/hecks/projections/deploy/templates/lambda/pii_permission.tmpl +8 -0
  680. data/lib/hecks/projections/deploy/templates/lambda/pii_resources.tmpl +116 -0
  681. data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge.tmpl +30 -0
  682. data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge_oauth.tmpl +12 -0
  683. data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge_plain.tmpl +7 -0
  684. data/lib/hecks/projections/deploy/templates/lambda/rename_schema_own.tmpl +93 -0
  685. data/lib/hecks/projections/deploy/templates/lambda/rename_schema_shared.tmpl +7 -0
  686. data/lib/hecks/projections/deploy/templates/lambda/rust_oauth_env.tmpl +17 -0
  687. data/lib/hecks/projections/deploy/templates/lambda/rust_oauth_policy.tmpl +16 -0
  688. data/lib/hecks/projections/deploy/templates/lambda/rust_session_secret.tmpl +13 -0
  689. data/lib/hecks/projections/deploy/templates/lambda/samconfig.toml.tmpl +12 -0
  690. data/lib/hecks/projections/deploy/templates/lambda/shared_note.tmpl +6 -0
  691. data/lib/hecks/projections/deploy/templates/lambda/sync_oauth.tmpl +23 -0
  692. data/lib/hecks/projections/deploy/templates/lambda/template.yaml.tmpl +187 -0
  693. data/lib/hecks/projections/deploy/templates/lambda/translation_own.tmpl +46 -0
  694. data/lib/hecks/projections/deploy/templates/lambda/translation_shared.tmpl +2 -0
  695. data/lib/hecks/projections/deploy/templates/lambda/web_function.tmpl +207 -0
  696. data/lib/hecks/projections/deploy/templates/lambda/web_google_oauth_env.tmpl +12 -0
  697. data/lib/hecks/projections/deploy/templates/lambda/web_no_oauth_env.tmpl +7 -0
  698. data/lib/hecks/projections/deploy/templates/lambda/web_oauth_policy.tmpl +4 -0
  699. data/lib/hecks/projections/deploy/templates/lambda/webhook_secret_resource.tmpl +20 -0
  700. data/lib/hecks/projections/deploy/templates/preview/alb.tmpl +8 -0
  701. data/lib/hecks/projections/deploy/templates/preview/alb_security_group.tmpl +11 -0
  702. data/lib/hecks/projections/deploy/templates/preview/assume_role.tmpl +6 -0
  703. data/lib/hecks/projections/deploy/templates/preview/base_parameters.tmpl +24 -0
  704. data/lib/hecks/projections/deploy/templates/preview/cluster.tmpl +4 -0
  705. data/lib/hecks/projections/deploy/templates/preview/container_secret.tmpl +9 -0
  706. data/lib/hecks/projections/deploy/templates/preview/db_init_script.sh.tmpl +23 -0
  707. data/lib/hecks/projections/deploy/templates/preview/db_init_secrets.tmpl +5 -0
  708. data/lib/hecks/projections/deploy/templates/preview/db_init_task.tmpl +39 -0
  709. data/lib/hecks/projections/deploy/templates/preview/desired_count.tmpl +5 -0
  710. data/lib/hecks/projections/deploy/templates/preview/distribution.tmpl +24 -0
  711. data/lib/hecks/projections/deploy/templates/preview/execution_role.tmpl +16 -0
  712. data/lib/hecks/projections/deploy/templates/preview/header.tmpl +16 -0
  713. data/lib/hecks/projections/deploy/templates/preview/ingress.tmpl +8 -0
  714. data/lib/hecks/projections/deploy/templates/preview/listener.tmpl +9 -0
  715. data/lib/hecks/projections/deploy/templates/preview/listener_rule.tmpl +11 -0
  716. data/lib/hecks/projections/deploy/templates/preview/log_group.tmpl +5 -0
  717. data/lib/hecks/projections/deploy/templates/preview/log_options.tmpl +5 -0
  718. data/lib/hecks/projections/deploy/templates/preview/outputs.tmpl +14 -0
  719. data/lib/hecks/projections/deploy/templates/preview/service.tmpl +17 -0
  720. data/lib/hecks/projections/deploy/templates/preview/session_secret.tmpl +11 -0
  721. data/lib/hecks/projections/deploy/templates/preview/target_group.tmpl +9 -0
  722. data/lib/hecks/projections/deploy/templates/preview/task_definition.tmpl +15 -0
  723. data/lib/hecks/projections/deploy/templates/preview/task_role.tmpl +22 -0
  724. data/lib/hecks/projections/deploy/templates/shared/aurora_db.tmpl +52 -0
  725. data/lib/hecks/projections/deploy/templates/shared/bastion.tmpl +74 -0
  726. data/lib/hecks/projections/deploy/templates/shared/bastion_own_public.tmpl +41 -0
  727. data/lib/hecks/projections/deploy/templates/shared/bastion_reuse_public.tmpl +10 -0
  728. data/lib/hecks/projections/deploy/templates/shared/nat_gateway.tmpl +102 -0
  729. data/lib/hecks/projections/deploy/templates/shared/oauth_egress.tmpl +17 -0
  730. data/lib/hecks/projections/deploy/templates/shared/plain_db.tmpl +16 -0
  731. data/lib/hecks/projections/deploy/templates/shared/vpc_and_database.tmpl +67 -0
  732. data/lib/hecks/projections/deploy/text_template.rb +35 -0
  733. data/lib/hecks/projections/deploy/vercel/settings.rb +83 -0
  734. data/lib/hecks/projections/deploy/vercel.rb +134 -0
  735. data/lib/hecks/projections/diagrams/dispatch.rb +114 -0
  736. data/lib/hecks/projections/diagrams/statecharts.rb +59 -0
  737. data/lib/hecks/projections/diagrams/structure.rb +114 -0
  738. data/lib/hecks/projections/diagrams.rb +33 -256
  739. data/lib/hecks/projections/glossary/entries.rb +140 -0
  740. data/lib/hecks/projections/glossary/html/page.rb +96 -0
  741. data/lib/hecks/projections/glossary/html/parser.rb +66 -0
  742. data/lib/hecks/projections/glossary/html/sections.rb +78 -0
  743. data/lib/hecks/projections/glossary/html.rb +7 -179
  744. data/lib/hecks/projections/glossary/index.rb +45 -0
  745. data/lib/hecks/projections/glossary/markdown.rb +22 -11
  746. data/lib/hecks/projections/glossary/mermaid.rb +44 -31
  747. data/lib/hecks/projections/glossary/sensitivity.rb +7 -4
  748. data/lib/hecks/projections/glossary/sentences/value_objects.rb +77 -0
  749. data/lib/hecks/projections/glossary/sentences.rb +42 -81
  750. data/lib/hecks/projections/glossary/slugs.rb +33 -0
  751. data/lib/hecks/projections/glossary.rb +22 -190
  752. data/lib/hecks/projections/model.rb +20 -14
  753. data/lib/hecks/projections/rust_vocabulary/arguments/support.rb +33 -0
  754. data/lib/hecks/projections/rust_vocabulary/arguments.rb +171 -0
  755. data/lib/hecks/projections/rust_vocabulary/enum_body.rb +114 -0
  756. data/lib/hecks/projections/rust_vocabulary/tests.rb +144 -0
  757. data/lib/hecks/projections/rust_vocabulary.rb +24 -293
  758. data/lib/hecks/projections/site/admin.rb +15 -9
  759. data/lib/hecks/projections/site/admin_cms/templates/membership.rb +115 -0
  760. data/lib/hecks/projections/site/admin_cms/templates/session_strategy.rb +90 -0
  761. data/lib/hecks/projections/site/admin_cms/templates/sso.rb +101 -0
  762. data/lib/hecks/projections/site/admin_cms/templates/sso_tail.rb +54 -0
  763. data/lib/hecks/projections/site/admin_cms/templates/users.rb +83 -0
  764. data/lib/hecks/projections/site/admin_cms/templates.rb +14 -369
  765. data/lib/hecks/projections/site/admin_cms.rb +15 -9
  766. data/lib/hecks/projections/site/edge/behaviours.rb +10 -6
  767. data/lib/hecks/projections/site/edge/checks.rb +30 -80
  768. data/lib/hecks/projections/site/edge/findings.rb +28 -0
  769. data/lib/hecks/projections/site/edge/route_checks.rb +110 -0
  770. data/lib/hecks/projections/site/edge/row_reader.rb +52 -0
  771. data/lib/hecks/projections/site/edge/rules.rb +28 -26
  772. data/lib/hecks/projections/site/edge.rb +20 -31
  773. data/lib/hecks/projections/site/live_edge.rb +9 -7
  774. data/lib/hecks/projections/site/payload/fields/definitions.rb +90 -0
  775. data/lib/hecks/projections/site/payload/fields/readers.rb +69 -0
  776. data/lib/hecks/projections/site/payload/fields.rb +14 -111
  777. data/lib/hecks/projections/site/payload/lifecycle/text.rb +84 -0
  778. data/lib/hecks/projections/site/payload/lifecycle/text_tail.rb +106 -0
  779. data/lib/hecks/projections/site/payload/lifecycle.rb +8 -166
  780. data/lib/hecks/projections/site/payload/model.rb +22 -22
  781. data/lib/hecks/projections/site/payload/specs/wire.rb +69 -0
  782. data/lib/hecks/projections/site/payload/specs.rb +24 -68
  783. data/lib/hecks/projections/site/payload_driver.rb +19 -17
  784. data/lib/hecks/projections/site/root_rows.rb +12 -4
  785. data/lib/hecks/projections/site/routes_ts/helpers.rb +79 -0
  786. data/lib/hecks/projections/site/routes_ts/listings.rb +75 -0
  787. data/lib/hecks/projections/site/routes_ts/navigation.rb +79 -0
  788. data/lib/hecks/projections/site/routes_ts.rb +27 -175
  789. data/lib/hecks/projections/site/site_admin/access.rb +104 -0
  790. data/lib/hecks/projections/site/site_admin/session.rb +127 -0
  791. data/lib/hecks/projections/site/site_admin.rb +12 -219
  792. data/lib/hecks/projections/site/site_cdn.rb +12 -7
  793. data/lib/hecks/projections/site/site_host/dockerfile.rb +75 -0
  794. data/lib/hecks/projections/site/site_host/templates.rb +19 -67
  795. data/lib/hecks/projections/site/site_root/workflow.rb +65 -0
  796. data/lib/hecks/projections/site/site_root.rb +3 -54
  797. data/lib/hecks/projections/site/table/checks.rb +28 -57
  798. data/lib/hecks/projections/site/table/link_builder.rb +14 -5
  799. data/lib/hecks/projections/site/table/navigation_checks.rb +75 -0
  800. data/lib/hecks/projections/site/table/row_builder.rb +31 -53
  801. data/lib/hecks/projections/site/table/row_defaults.rb +65 -0
  802. data/lib/hecks/projections/site/table.rb +9 -5
  803. data/lib/hecks/projections/vocabulary.rb +34 -31
  804. data/lib/hecks/projections.rb +2 -0
  805. data/lib/hecks/projector/cli_audience.rb +42 -0
  806. data/lib/hecks/projector/cli_projector/claims.rb +149 -0
  807. data/lib/hecks/projector/cli_projector/command_help.rb +65 -0
  808. data/lib/hecks/projector/cli_projector/command_specs.rb +133 -0
  809. data/lib/hecks/projector/cli_projector/listing.rb +100 -0
  810. data/lib/hecks/projector/cli_projector/option_specs.rb +116 -0
  811. data/lib/hecks/projector/cli_projector/query_specs.rb +67 -0
  812. data/lib/hecks/projector/cli_projector/usage.rb +101 -0
  813. data/lib/hecks/projector/cli_projector.rb +15 -532
  814. data/lib/hecks/projector/docs_projector/attributes.rb +78 -0
  815. data/lib/hecks/projector/docs_projector/behaviour.rb +127 -0
  816. data/lib/hecks/projector/docs_projector/closing.rb +40 -0
  817. data/lib/hecks/projector/docs_projector.rb +58 -192
  818. data/lib/hecks/projector/exporter/bindings.rb +174 -0
  819. data/lib/hecks/projector/exporter/translations.rb +127 -0
  820. data/lib/hecks/projector/exporter.rb +8 -279
  821. data/lib/hecks/projector/narrate_projector/commands.rb +108 -0
  822. data/lib/hecks/projector/narrate_projector/reactions.rb +33 -0
  823. data/lib/hecks/projector/narrate_projector.rb +60 -160
  824. data/lib/hecks/projector.rb +22 -13
  825. data/lib/hecks/quality_control/adapters/agent_profile.rb +25 -16
  826. data/lib/hecks/quality_control/adapters/github_checks.rb +49 -6
  827. data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +1 -1
  828. data/lib/hecks/quality_control/adapters/github_issues.rb +22 -10
  829. data/lib/hecks/quality_control/cli/qa_discover_external_domains/parsing.rb +54 -0
  830. data/lib/hecks/quality_control/cli/qa_discover_external_domains/reporting.rb +44 -0
  831. data/lib/hecks/quality_control/cli/qa_discover_external_domains/scanning.rb +119 -0
  832. data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +28 -155
  833. data/lib/hecks/quality_control/cli/qa_domain_novelty/verdict.rb +76 -0
  834. data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +33 -66
  835. data/lib/hecks/quality_control/cli/qa_generated_domains/arguments.rb +62 -0
  836. data/lib/hecks/quality_control/cli/qa_generated_domains/blueprints.rb +45 -0
  837. data/lib/hecks/quality_control/cli/qa_generated_domains/evaluation.rb +107 -0
  838. data/lib/hecks/quality_control/cli/qa_generated_domains/promotion.rb +107 -0
  839. data/lib/hecks/quality_control/cli/qa_generated_domains/reporting.rb +97 -0
  840. data/lib/hecks/quality_control/cli/qa_generated_domains/shrinking.rb +70 -0
  841. data/lib/hecks/quality_control/cli/qa_generated_domains.rb +43 -327
  842. data/lib/hecks/quality_control/cli/qa_log_bug/arguments.rb +55 -0
  843. data/lib/hecks/quality_control/cli/qa_log_bug/proof.rb +65 -0
  844. data/lib/hecks/quality_control/cli/qa_log_bug.rb +18 -81
  845. data/lib/hecks/quality_control/cli/qa_mine_combinations/arguments.rb +54 -0
  846. data/lib/hecks/quality_control/cli/qa_mine_combinations/booting.rb +96 -0
  847. data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +45 -109
  848. data/lib/hecks/quality_control/cli/qa_open_pr/arguments.rb +55 -0
  849. data/lib/hecks/quality_control/cli/qa_open_pr/recording.rb +79 -0
  850. data/lib/hecks/quality_control/cli/qa_open_pr/rules.rb +122 -0
  851. data/lib/hecks/quality_control/cli/qa_open_pr.rb +41 -200
  852. data/lib/hecks/quality_control/cli/qa_postgres_migrate/copying.rb +45 -0
  853. data/lib/hecks/quality_control/cli/qa_postgres_migrate/reporting.rb +33 -0
  854. data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +37 -63
  855. data/lib/hecks/quality_control/cli/qa_postgres_role/ownership.rb +57 -0
  856. data/lib/hecks/quality_control/cli/qa_postgres_role.rb +66 -71
  857. data/lib/hecks/quality_control/cli/qa_pr_check/checking.rb +118 -0
  858. data/lib/hecks/quality_control/cli/qa_pr_check/reporting.rb +54 -0
  859. data/lib/hecks/quality_control/cli/qa_pr_check.rb +28 -145
  860. data/lib/hecks/quality_control/cli/qa_seed_angles/seed.rb +80 -0
  861. data/lib/hecks/quality_control/cli/qa_seed_angles.rb +13 -86
  862. data/lib/hecks/quality_control/cli/qa_sweep/all_mode/children.rb +80 -0
  863. data/lib/hecks/quality_control/cli/qa_sweep/all_mode/report.rb +125 -0
  864. data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +63 -193
  865. data/lib/hecks/quality_control/cli/qa_sweep/checks/boundary.rb +92 -0
  866. data/lib/hecks/quality_control/cli/qa_sweep/checks/engines.rb +92 -0
  867. data/lib/hecks/quality_control/cli/qa_sweep/checks/seeds.rb +86 -0
  868. data/lib/hecks/quality_control/cli/qa_sweep/checks/shrinking.rb +69 -0
  869. data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +10 -248
  870. data/lib/hecks/quality_control/cli/qa_sweep/conclusion.rb +60 -0
  871. data/lib/hecks/quality_control/cli/qa_sweep/depth.rb +61 -0
  872. data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +27 -13
  873. data/lib/hecks/quality_control/cli/qa_sweep/finding_report/shrunk.rb +42 -0
  874. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +40 -41
  875. data/lib/hecks/quality_control/cli/qa_sweep/parsing/validation.rb +70 -0
  876. data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +35 -65
  877. data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +41 -22
  878. data/lib/hecks/quality_control/cli/qa_sweep/scratch.rb +67 -0
  879. data/lib/hecks/quality_control/cli/qa_sweep/seat.rb +94 -0
  880. data/lib/hecks/quality_control/cli/qa_sweep/seed_loop.rb +157 -0
  881. data/lib/hecks/quality_control/cli/qa_sweep/target_setup.rb +115 -0
  882. data/lib/hecks/quality_control/cli/qa_sweep.rb +22 -445
  883. data/lib/hecks/quality_control/cli/qa_tick/output.rb +107 -0
  884. data/lib/hecks/quality_control/cli/qa_tick/preflight.rb +95 -0
  885. data/lib/hecks/quality_control/cli/qa_tick.rb +42 -175
  886. data/lib/hecks/query_ir/formatting.rb +86 -0
  887. data/lib/hecks/query_ir/rules.rb +132 -0
  888. data/lib/hecks/query_ir/touchpoints.rb +104 -0
  889. data/lib/hecks/query_ir.rb +33 -281
  890. data/lib/hecks/query_ir_mcp/tools.rb +68 -0
  891. data/lib/hecks/query_ir_mcp.rb +27 -71
  892. data/lib/hecks/query_specification/common/comparison.rb +25 -5
  893. data/lib/hecks/query_specification/common/dsl.rb +1 -1
  894. data/lib/hecks/query_specification/common/null_policy.rb +9 -6
  895. data/lib/hecks/query_specification/common/options.rb +21 -14
  896. data/lib/hecks/query_specification/field_path.rb +5 -2
  897. data/lib/hecks/query_specification/hop_path.rb +15 -18
  898. data/lib/hecks/release/lane.rb +22 -0
  899. data/lib/hecks/release/runner/clean_tree.rb +2 -2
  900. data/lib/hecks/release/runner/commands.rb +1 -1
  901. data/lib/hecks/release/runner/options.rb +82 -0
  902. data/lib/hecks/release/runner/preflight.rb +12 -7
  903. data/lib/hecks/release/runner/publishing.rb +86 -0
  904. data/lib/hecks/release/runner/tagger.rb +8 -3
  905. data/lib/hecks/release/runner.rb +40 -156
  906. data/lib/hecks/rendering.rb +13 -9
  907. data/lib/hecks/router/door.rb +37 -0
  908. data/lib/hecks/router/namespace_installer.rb +45 -83
  909. data/lib/hecks/router/options_proxy.rb +44 -0
  910. data/lib/hecks/runtime/adapter_lookup.rb +45 -24
  911. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -8
  912. data/lib/hecks/runtime/command_interpreter/delegation.rb +116 -0
  913. data/lib/hecks/runtime/command_interpreter/enforcement.rb +38 -0
  914. data/lib/hecks/runtime/command_interpreter/hydration.rb +139 -0
  915. data/lib/hecks/runtime/command_interpreter/list_mutations.rb +98 -0
  916. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +67 -114
  917. data/lib/hecks/runtime/command_interpreter/persisting.rb +96 -0
  918. data/lib/hecks/runtime/command_interpreter.rb +57 -352
  919. data/lib/hecks/runtime/command_rules/admissibility.rb +64 -147
  920. data/lib/hecks/runtime/command_rules/arithmetic.rb +13 -72
  921. data/lib/hecks/runtime/command_rules/authorization.rb +9 -9
  922. data/lib/hecks/runtime/command_rules/emission.rb +13 -14
  923. data/lib/hecks/runtime/command_rules/guard_state.rb +49 -0
  924. data/lib/hecks/runtime/command_rules/invariants.rb +84 -0
  925. data/lib/hecks/runtime/command_rules/operands.rb +88 -0
  926. data/lib/hecks/runtime/command_rules/references.rb +59 -57
  927. data/lib/hecks/runtime/command_rules/tenant_boundary.rb +69 -0
  928. data/lib/hecks/runtime/dependency_planning/analyzer.rb +90 -0
  929. data/lib/hecks/runtime/dependency_planning/expression_reads.rb +73 -0
  930. data/lib/hecks/runtime/dependency_planning/mutation_analysis.rb +89 -0
  931. data/lib/hecks/runtime/dependency_planning/rule_analysis.rb +82 -0
  932. data/lib/hecks/runtime/dependency_planning.rb +3 -250
  933. data/lib/hecks/runtime/dispatcher/queries.rb +62 -0
  934. data/lib/hecks/runtime/dispatcher/result.rb +55 -0
  935. data/lib/hecks/runtime/dispatcher/routing.rb +107 -0
  936. data/lib/hecks/runtime/dispatcher.rb +64 -209
  937. data/lib/hecks/runtime/entity_element/location.rb +124 -0
  938. data/lib/hecks/runtime/entity_element/mutations.rb +150 -0
  939. data/lib/hecks/runtime/entity_element.rb +5 -177
  940. data/lib/hecks/runtime/entity_interpreter/enforcement.rb +51 -0
  941. data/lib/hecks/runtime/entity_interpreter/locating.rb +62 -0
  942. data/lib/hecks/runtime/entity_interpreter/resolution.rb +42 -0
  943. data/lib/hecks/runtime/entity_interpreter/saving.rb +49 -0
  944. data/lib/hecks/runtime/entity_interpreter.rb +45 -164
  945. data/lib/hecks/runtime/identity.rb +15 -9
  946. data/lib/hecks/runtime/instance.rb +11 -7
  947. data/lib/hecks/runtime/interpreting.rb +16 -8
  948. data/lib/hecks/runtime/invocation.rb +3 -155
  949. data/lib/hecks/runtime/invocation_builder.rb +132 -0
  950. data/lib/hecks/runtime/invocation_facts.rb +87 -0
  951. data/lib/hecks/runtime/loader/boot_steps.rb +96 -0
  952. data/lib/hecks/runtime/loader/described.rb +27 -0
  953. data/lib/hecks/runtime/loader.rb +27 -114
  954. data/lib/hecks/runtime/outbox/consumer_runner.rb +40 -0
  955. data/lib/hecks/runtime/outbox/fanout.rb +82 -0
  956. data/lib/hecks/runtime/outbox/relay.rb +149 -0
  957. data/lib/hecks/runtime/outbox.rb +3 -214
  958. data/lib/hecks/runtime/policy_interpreter/arguments.rb +67 -0
  959. data/lib/hecks/runtime/policy_interpreter/fan_out.rb +96 -0
  960. data/lib/hecks/runtime/policy_interpreter.rb +22 -137
  961. data/lib/hecks/runtime/port_operation_interpreter.rb +18 -17
  962. data/lib/hecks/runtime/query_interpreter/arguments.rb +51 -0
  963. data/lib/hecks/runtime/query_interpreter/entity_rows.rb +82 -0
  964. data/lib/hecks/runtime/query_interpreter/outside_answer.rb +89 -0
  965. data/lib/hecks/runtime/query_interpreter.rb +43 -191
  966. data/lib/hecks/runtime/reaction_invocation/identities.rb +92 -0
  967. data/lib/hecks/runtime/reaction_invocation/target_resolution.rb +88 -0
  968. data/lib/hecks/runtime/reaction_invocation.rb +66 -183
  969. data/lib/hecks/runtime/reaction_outcome.rb +7 -3
  970. data/lib/hecks/runtime/read_model_interpreter/head_ordering.rb +49 -0
  971. data/lib/hecks/runtime/read_model_interpreter/reductions.rb +123 -0
  972. data/lib/hecks/runtime/read_model_interpreter/shaping.rb +100 -0
  973. data/lib/hecks/runtime/read_model_interpreter.rb +71 -214
  974. data/lib/hecks/runtime/reference_hop.rb +11 -11
  975. data/lib/hecks/runtime/refusal_wording.rb +11 -8
  976. data/lib/hecks/runtime/registry/chapter_verification.rb +84 -0
  977. data/lib/hecks/runtime/registry/declarations.rb +17 -0
  978. data/lib/hecks/runtime/registry/durability_warnings.rb +71 -0
  979. data/lib/hecks/runtime/registry/hecksagon_rules.rb +124 -0
  980. data/lib/hecks/runtime/registry/merging.rb +49 -0
  981. data/lib/hecks/runtime/registry/providers.rb +139 -0
  982. data/lib/hecks/runtime/registry/query_verification.rb +144 -0
  983. data/lib/hecks/runtime/registry/read_repository.rb +61 -0
  984. data/lib/hecks/runtime/registry/runtime_state.rb +27 -0
  985. data/lib/hecks/runtime/registry/saga_persistence.rb +12 -8
  986. data/lib/hecks/runtime/registry/verification.rb +45 -389
  987. data/lib/hecks/runtime/registry/world_defaults.rb +3 -3
  988. data/lib/hecks/runtime/registry.rb +58 -296
  989. data/lib/hecks/runtime/remote_dispatcher.rb +47 -31
  990. data/lib/hecks/runtime/saga_interpreter/compensation.rb +90 -0
  991. data/lib/hecks/runtime/saga_interpreter/correlation.rb +19 -10
  992. data/lib/hecks/runtime/saga_interpreter/delivery.rb +147 -0
  993. data/lib/hecks/runtime/saga_interpreter/lifecycle.rb +63 -0
  994. data/lib/hecks/runtime/saga_interpreter/transitions.rb +112 -0
  995. data/lib/hecks/runtime/saga_interpreter.rb +41 -320
  996. data/lib/hecks/runtime/tenant_check.rb +14 -9
  997. data/lib/hecks/runtime/value/admission.rb +28 -19
  998. data/lib/hecks/runtime/value/coercion.rb +55 -404
  999. data/lib/hecks/runtime/value/entity_list_coercion.rb +27 -29
  1000. data/lib/hecks/runtime/value/field_checks.rb +57 -100
  1001. data/lib/hecks/runtime/value/flags.rb +65 -0
  1002. data/lib/hecks/runtime/value/identifiers.rb +64 -0
  1003. data/lib/hecks/runtime/value/references.rb +195 -0
  1004. data/lib/hecks/runtime/value/shape_checks.rb +61 -0
  1005. data/lib/hecks/runtime/value/validation.rb +125 -0
  1006. data/lib/hecks/runtime/value.rb +18 -6
  1007. data/lib/hecks/rust_build/conformance/surface.rb +75 -0
  1008. data/lib/hecks/rust_build/conformance.rb +27 -59
  1009. data/lib/hecks/rust_build/conformance_fuzz.rb +26 -15
  1010. data/lib/hecks/rust_build/coverage.rb +32 -104
  1011. data/lib/hecks/rust_build/coverage_parts/expected.rb +68 -0
  1012. data/lib/hecks/rust_build/coverage_parts/printer.rb +75 -0
  1013. data/lib/hecks/rust_build/host.rb +23 -13
  1014. data/lib/hecks/rust_build/kernel_input.rb +19 -12
  1015. data/lib/hecks/rust_build/native_build.rb +48 -16
  1016. data/lib/hecks/rust_build/project_rust/domain_loader.rb +75 -0
  1017. data/lib/hecks/rust_build/project_rust/root_mod/notes.rb +66 -0
  1018. data/lib/hecks/rust_build/project_rust/root_mod.rb +22 -55
  1019. data/lib/hecks/rust_build/project_rust/target_ir.rb +74 -0
  1020. data/lib/hecks/rust_build/project_rust.rb +21 -89
  1021. data/lib/hecks/rust_build/wasm.rb +27 -7
  1022. data/lib/hecks/rust_build/wasm_browser.rb +7 -7
  1023. data/lib/hecks/rust_build/write_if_changed.rb +3 -6
  1024. data/lib/hecks/rust_build.rb +7 -3
  1025. data/lib/hecks/storehouse/audit.rb +106 -0
  1026. data/lib/hecks/storehouse/callers.rb +73 -0
  1027. data/lib/hecks/storehouse/dispatching.rb +149 -0
  1028. data/lib/hecks/storehouse/introspection.rb +145 -0
  1029. data/lib/hecks/storehouse/querying.rb +78 -0
  1030. data/lib/hecks/storehouse.rb +43 -451
  1031. data/lib/hecks/tickets/bluebook/tickets.bluebook +29 -0
  1032. data/lib/hecks/tools/argument_gate_matrix/dispatching.rb +69 -0
  1033. data/lib/hecks/tools/argument_gate_matrix/rows.rb +121 -0
  1034. data/lib/hecks/tools/argument_gate_matrix/violations.rb +108 -0
  1035. data/lib/hecks/tools/argument_gate_matrix.rb +43 -212
  1036. data/lib/hecks/tools/ci_gate_decision.rb +21 -14
  1037. data/lib/hecks/tools/ci_gates.rb +40 -26
  1038. data/lib/hecks/tools/comment_style/baseline.rb +41 -0
  1039. data/lib/hecks/tools/comment_style/caps_words.rb +104 -0
  1040. data/lib/hecks/tools/comment_style/cli.rb +121 -0
  1041. data/lib/hecks/tools/comment_style/dictionary.rb +60 -0
  1042. data/lib/hecks/tools/comment_style/fixing.rb +119 -0
  1043. data/lib/hecks/tools/comment_style/long_blocks.rb +51 -0
  1044. data/lib/hecks/tools/comment_style/masking.rb +94 -0
  1045. data/lib/hecks/tools/comment_style/patterns.rb +61 -0
  1046. data/lib/hecks/tools/comment_style/run.rb +161 -0
  1047. data/lib/hecks/tools/comment_style/signature.rb +59 -0
  1048. data/lib/hecks/tools/comment_style/source_file.rb +105 -0
  1049. data/lib/hecks/tools/comment_style/structure_checks.rb +113 -0
  1050. data/lib/hecks/tools/comment_style/text_checks.rb +67 -0
  1051. data/lib/hecks/tools/comment_style/vocabulary.rb +55 -0
  1052. data/lib/hecks/tools/comment_style/walker.rb +136 -0
  1053. data/lib/hecks/tools/comment_style.rb +17 -1000
  1054. data/lib/hecks/tools/corpus_report.rb +26 -16
  1055. data/lib/hecks/tools/deploy_recipe/generation.rb +59 -0
  1056. data/lib/hecks/tools/deploy_recipe/targets.rb +115 -0
  1057. data/lib/hecks/tools/deploy_recipe/worlds.rb +115 -0
  1058. data/lib/hecks/tools/deploy_recipe.rb +72 -176
  1059. data/lib/hecks/tools/deploy_recipe_lint/checks.rb +78 -0
  1060. data/lib/hecks/tools/deploy_recipe_lint/fixtures.rb +88 -0
  1061. data/lib/hecks/tools/deploy_recipe_lint/makefile.rb +84 -0
  1062. data/lib/hecks/tools/deploy_recipe_lint.rb +29 -192
  1063. data/lib/hecks/tools/drop_implicit_append_fields.rb +20 -12
  1064. data/lib/hecks/tools/era_projection_backfill.rb +50 -33
  1065. data/lib/hecks/tools/era_reattest/reporting.rb +55 -0
  1066. data/lib/hecks/tools/era_reattest.rb +32 -43
  1067. data/lib/hecks/tools/evolve_run/arguments.rb +49 -0
  1068. data/lib/hecks/tools/evolve_run/words.rb +60 -0
  1069. data/lib/hecks/tools/evolve_run.rb +43 -90
  1070. data/lib/hecks/tools/fuzz_sweep/findings.rb +106 -0
  1071. data/lib/hecks/tools/fuzz_sweep/options.rb +80 -0
  1072. data/lib/hecks/tools/fuzz_sweep/pool.rb +74 -0
  1073. data/lib/hecks/tools/fuzz_sweep/reporting.rb +110 -0
  1074. data/lib/hecks/tools/fuzz_sweep.rb +91 -272
  1075. data/lib/hecks/tools/gate.rb +31 -16
  1076. data/lib/hecks/tools/heki_compaction.rb +63 -42
  1077. data/lib/hecks/tools/hoist_local_givens/rewriting.rb +119 -0
  1078. data/lib/hecks/tools/hoist_local_givens.rb +89 -157
  1079. data/lib/hecks/tools/journal_compaction.rb +40 -31
  1080. data/lib/hecks/tools/lanes/files.rb +80 -0
  1081. data/lib/hecks/tools/lanes/live.rb +40 -0
  1082. data/lib/hecks/tools/lanes/rows.rb +45 -0
  1083. data/lib/hecks/tools/lanes/ruleset.rb +66 -0
  1084. data/lib/hecks/tools/lanes/watch_workflow.rb +82 -0
  1085. data/lib/hecks/tools/lanes/workflow.rb +79 -0
  1086. data/lib/hecks/tools/lanes.rb +82 -0
  1087. data/lib/hecks/tools/mutation_run.rb +73 -0
  1088. data/lib/hecks/tools/oidc_manifests.rb +10 -9
  1089. data/lib/hecks/tools/query_ir_run.rb +7 -3
  1090. data/lib/hecks/tools/regeneration_run.rb +40 -26
  1091. data/lib/hecks/tools/rust_comment_style/caps_words.rb +98 -0
  1092. data/lib/hecks/tools/rust_comment_style/fixing.rb +102 -0
  1093. data/lib/hecks/tools/rust_comment_style/masking.rb +85 -0
  1094. data/lib/hecks/tools/rust_comment_style/run.rb +94 -0
  1095. data/lib/hecks/tools/rust_comment_style/source_file.rb +71 -0
  1096. data/lib/hecks/tools/rust_comment_style/structure.rb +79 -0
  1097. data/lib/hecks/tools/rust_comment_style/text_checks.rb +63 -0
  1098. data/lib/hecks/tools/rust_comment_style/tokenizer.rb +102 -0
  1099. data/lib/hecks/tools/rust_comment_style.rb +38 -535
  1100. data/lib/hecks/tools/sequence_script.rb +20 -14
  1101. data/lib/hecks/tools/site_routes/cli.rb +70 -0
  1102. data/lib/hecks/tools/site_routes/root_files.rb +59 -0
  1103. data/lib/hecks/tools/site_routes/templates.rb +77 -0
  1104. data/lib/hecks/tools/site_routes.rb +84 -160
  1105. data/lib/hecks/tools/tail_merge.rb +45 -37
  1106. data/lib/hecks/tools/tenant_provisioning.rb +45 -31
  1107. data/lib/hecks/tools/tools_doc.rb +42 -19
  1108. data/lib/hecks/tools/translation_audit/domain_loading.rb +71 -0
  1109. data/lib/hecks/tools/translation_audit/edges.rb +71 -0
  1110. data/lib/hecks/tools/translation_audit/verdicts.rb +107 -0
  1111. data/lib/hecks/tools/translation_audit.rb +30 -161
  1112. data/lib/hecks/tools/translation_scaffold/reporting.rb +40 -0
  1113. data/lib/hecks/tools/translation_scaffold.rb +77 -60
  1114. data/lib/hecks/tools.rb +2 -0
  1115. data/lib/hecks/vendoring.rb +37 -11
  1116. data/lib/hecks/version.rb +1 -1
  1117. data/lib/hecks/vocabulary.rb +18 -1
  1118. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +7 -9
  1119. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +8 -6
  1120. data/prebuilt/945481eefbdb584649d45f256307053558966a868b9c38dee7ee88f8169610f8.marshal +0 -0
  1121. data/prebuilt/a0818e2de67364dc1ab22868b6cbf869c62da6f8d9b924c778fa5cce2e76ee94.marshal +0 -0
  1122. data/prebuilt/verdicts-be73f0df9eee0abe2f4aadc968321c4b919d19d424a3ccfe1777a71dabf7d9e7.json +1 -0
  1123. data/qa/settings.yml +1 -0
  1124. data/rust/.cargo/mutants.toml +8 -0
  1125. data/rust/host/Cargo.toml +5 -0
  1126. data/rust/host/HECKS_RELEASE +1 -1
  1127. data/rust/host/src/api.rs +28 -5
  1128. data/rust/host/src/auth.rs +43 -1
  1129. data/rust/host/src/boundary_fuzz/api.rs +260 -0
  1130. data/rust/host/src/boundary_fuzz/auth.rs +119 -0
  1131. data/rust/host/src/boundary_fuzz/expr_json.rs +158 -0
  1132. data/rust/host/src/boundary_fuzz/ir.rs +78 -0
  1133. data/rust/host/src/boundary_fuzz/server.rs +227 -0
  1134. data/rust/host/src/boundary_fuzz/web.rs +125 -0
  1135. data/rust/host/src/fuzz_support.rs +165 -0
  1136. data/rust/host/src/ir.rs +4 -0
  1137. data/rust/host/src/main.rs +9 -4
  1138. data/rust/host/src/secrets.rs +44 -0
  1139. data/rust/host/src/server.rs +6 -1
  1140. data/rust/host/src/web.rs +14 -5
  1141. data/rust/parser/fuzz/.gitignore +4 -0
  1142. data/rust/parser/fuzz/Cargo.lock +89 -0
  1143. data/rust/parser/fuzz/Cargo.toml +27 -0
  1144. data/rust/parser/fuzz/README.md +19 -0
  1145. data/rust/parser/fuzz/fuzz_targets/chapter.rs +50 -0
  1146. data/rust/parser/fuzz/fuzz_targets/resolve.rs +35 -0
  1147. data/rust/parser/src/parse/command.rs +14 -2
  1148. data/rust/parser/src/parse/mod.rs +25 -0
  1149. data/rust/parser/src/ruby_value.rs +95 -6
  1150. data/rust/src/kernel/dispatch.rs +4 -0
  1151. data/rust/src/kernel/dispatch_guard_tests.rs +506 -0
  1152. data/rust/src/kernel/json.rs +34 -3
  1153. data/rust/src/kernel/orchestrate.rs +4 -0
  1154. data/rust/src/kernel/orchestrate_guard_tests.rs +708 -0
  1155. metadata +640 -3
  1156. /data/lib/hecks/bluebook/behaviour/{hexagon.rb → hecksagon.rb} +0 -0
@@ -3,6 +3,11 @@ require "json"
3
3
  require_relative "sql_query_builder"
4
4
  require_relative "postgres/schema_builder"
5
5
  require_relative "postgres/codec"
6
+ require_relative "postgres/dialect"
7
+ require_relative "postgres/events"
8
+ require_relative "postgres/journal"
9
+ require_relative "postgres/repository"
10
+ require_relative "postgres/sagas"
6
11
  require_relative "../../ports/persistence/append_only"
7
12
  require_relative "../../query_specification/common/null_policy"
8
13
  require_relative "../../query_specification/common/order_by"
@@ -22,8 +27,13 @@ module Hecks
22
27
  include SqlQueryBuilder
23
28
  include SchemaBuilder
24
29
  include Codec
30
+ include Repository
31
+ include Journal
32
+ include Events
33
+ include Sagas
25
34
  include PostgresOutbox
26
35
  include PostgresReconnect
36
+ include Dialect
27
37
 
28
38
  SQL_TYPES = { "Integer" => "bigint", "Float" => "double precision" }.freeze
29
39
 
@@ -46,39 +56,10 @@ module Hecks
46
56
  # refuses the connection or the `SET` statements
47
57
  # @raise [LoadError] if the `pg` gem is not installed
48
58
  def self.connect_for(name, settings)
49
- # **Lazy, on purpose** — same reasoning as PostgresEra's own
50
- # connect_for: a domain that never wires Postgres should never
51
- # need the gem installed.
52
- begin
53
- require "pg"
54
- rescue LoadError
55
- raise LoadError, "#{name} binds Postgres, which needs the pg gem: add `gem \"pg\"` to the Gemfile"
56
- end
57
-
59
+ require_pg(name)
58
60
  declared = settings.key?(:database) ? settings[:database] : settings["database"]
59
- if declared.to_s.empty?
60
- raise Runtime::WiringError,
61
- "#{name} binds Postgres, which needs a database connection, " \
62
- "but its world declares no \"database\"."
63
- end
64
-
65
- connection =
66
- if declared.start_with?("postgres://", "postgresql://")
67
- PG.connect(declared)
68
- else
69
- PG.connect(dbname: declared)
70
- end
71
-
72
- # A domain with `schema` set shares this Postgres instance, so every
73
- # unqualified reference resolves through search_path.
74
- schema = settings.key?(:schema) ? settings[:schema] : settings["schema"]
75
- connection.exec("SET search_path TO #{connection.quote_ident(schema)}") if schema.to_s != ""
76
-
77
- # **Quiet on purpose** — same reasoning as PostgresEra's own: a
78
- # schema/table that already exists is the ordinary case on every
79
- # boot after the first, not news.
80
- connection.exec("SET client_min_messages = warning")
81
- connection
61
+ refuse_undeclared(name, declared)
62
+ configure(open_connection(declared), settings)
82
63
  rescue StandardError => e
83
64
  # PG is only defined once the gem loads, so the clause cannot name it.
84
65
  raise unless defined?(PG::Error) && e.is_a?(PG::Error)
@@ -87,6 +68,40 @@ module Hecks
87
68
  "cannot bind Postgres at #{declared} for #{name}: #{e.message.strip}"
88
69
  end
89
70
 
71
+ # **Lazy, on purpose** — same reasoning as PostgresEra's own connect_for: a domain that
72
+ # never wires Postgres should never need the gem installed.
73
+ def self.require_pg(name)
74
+ require "pg"
75
+ rescue LoadError
76
+ raise LoadError, "#{name} binds Postgres, which needs the pg gem: add `gem \"pg\"` to the Gemfile"
77
+ end
78
+
79
+ def self.refuse_undeclared(name, declared)
80
+ return unless declared.to_s.empty?
81
+
82
+ raise Runtime::WiringError,
83
+ "#{name} binds Postgres, which needs a database connection, " \
84
+ "but its world declares no \"database\"."
85
+ end
86
+
87
+ def self.open_connection(declared)
88
+ return PG.connect(declared) if declared.start_with?("postgres://", "postgresql://")
89
+
90
+ PG.connect(dbname: declared)
91
+ end
92
+
93
+ # A domain with `schema` set shares this Postgres instance, so every unqualified
94
+ # reference resolves through search_path. Messages stay quiet on purpose, same as
95
+ # PostgresEra's own: a schema/table that already exists is the ordinary case on every
96
+ # boot after the first, not news.
97
+ def self.configure(connection, settings)
98
+ schema = settings.key?(:schema) ? settings[:schema] : settings["schema"]
99
+ connection.exec("SET search_path TO #{connection.quote_ident(schema)}") if schema.to_s != ""
100
+ connection.exec("SET client_min_messages = warning")
101
+ connection
102
+ end
103
+ private_class_method :require_pg, :refuse_undeclared, :open_connection, :configure
104
+
90
105
  # Joins the process's shared connection for the declared database and schema, then
91
106
  # creates the aggregate, journal, event, saga and outbox tables if absent.
92
107
  #
@@ -105,22 +120,8 @@ module Hecks
105
120
  @db = PostgresSharedConnection.for(aggregate.name, settings, connector: self.class)
106
121
  # Scopes saga rows; falls back to the aggregate's storage name when
107
122
  # settings gives no domain (e.g. a directly-instantiated adapter).
108
- @domain = (
109
- if settings.key?(:domain)
110
- settings[:domain]
111
- elsif settings.key?("domain")
112
- settings["domain"]
113
- else
114
- aggregate.storage_name
115
- end
116
- ).to_s
117
-
118
- create_aggregate_table!
119
- create_entry_table!
120
- create_event_table!
121
- create_saga_table!
122
- create_outbox_table!
123
- create_checkpoint_table!
123
+ @domain = setting(settings, :domain, aggregate.storage_name).to_s
124
+ create_tables!
124
125
  end
125
126
 
126
127
  # Names the aggregate's table; the journal table and outbox rows are keyed off it.
@@ -128,492 +129,24 @@ module Hecks
128
129
  # @return [String] the aggregate's snake_case storage name, unquoted
129
130
  def table = @aggregate.storage_name
130
131
 
131
- # Reads the current row for one aggregate identity, stamped with its stored version.
132
- #
133
- # @param id [String, Object] the aggregate identity, bound as `id.to_s`
134
- # @return [Runtime::Instance, nil] the decoded record with `version` set, or nil when
135
- # no row has that id
136
- # @raise [PG::Error] if the statement fails; a `PG::ConnectionBad` also triggers a
137
- # reconnect for the next caller
138
- def find(id)
139
- result = pg_exec_params("SELECT * FROM #{quoted_table} WHERE id = $1", [id.to_s])
140
- return nil if result.ntuples.zero?
141
-
142
- instance_from_row(result[0])
143
- end
144
-
145
- # Lists every stored record, ordered by id unless an ordering attribute is given.
146
- #
147
- # order_by is a runtime value, whitelisted the same way Sqlite#all does.
148
- #
149
- # @param order_by [String, Symbol, nil] attribute (or dotted value-object path) to sort
150
- # by, with id as the tie-break; nil orders by id alone
151
- # @param direction [Symbol, String] `:asc` or `:desc`, case-insensitive; anything else
152
- # sorts ascending
153
- # @return [Array<Runtime::Instance>] the decoded records with `version` set, `[]` when
154
- # the table is empty
155
- # @raise [Runtime::WiringError] if `order_by` names no attribute of the aggregate
156
- # @raise [PG::Error] if the statement fails
157
- def all(order_by: nil, direction: :asc)
158
- order_sql = "ORDER BY id"
159
- if order_by
160
- name = order_by.to_s.split(".").first
161
- unless @aggregate.lifecycle&.field.to_s == name || @aggregate.attribute(name)
162
- raise Runtime::WiringError,
163
- "#{@aggregate.name} has no attribute #{order_by.inspect} to order by"
164
- end
165
-
166
- spec = QuerySpecification::Common::OrderBy.new(field: order_by, direction: direction)
167
- order_sql = "ORDER BY #{order_clause(spec, nil)}"
168
- end
169
-
170
- pg_exec("SELECT * FROM #{quoted_table} #{order_sql}").map { |row| instance_from_row(row) }
171
- end
172
-
173
- # Counts the rows in the aggregate's table, deleted records excluded.
174
- #
175
- # @return [Integer] number of current records
176
- # @raise [PG::Error] if the statement fails
177
- def count = pg_exec("SELECT COUNT(*) FROM #{quoted_table}")[0]["count"].to_i
178
-
179
- # Inserts one journal row, outside any transaction of its own.
180
- #
181
- # Stamps the row's assigned `sequence` onto `entry` in place, so a `project` call right
182
- # after (same object, same transaction) can advance the checkpoint with no extra query.
183
- #
184
- # @param entry [Ports::Persistence::Entry] the save or delete to journal; `state` is
185
- # encoded through the state codec and `mirrors` stored as JSON, or NULL when nil
186
- # @return [Ports::Persistence::Entry] the same `entry`, `sequence` now set
187
- # @raise [PG::Error] if the insert fails
188
- def append(entry)
189
- result = pg_exec_params(
190
- "INSERT INTO #{quoted_entry_table} (aggregate_id, operation, state, mirrors) VALUES ($1, $2, $3, $4) " \
191
- "RETURNING sequence",
192
- # `mirrors` is nullable; an absent hash must bind SQL NULL, not the
193
- # string "null", or a future IS NULL check would never match.
194
- [entry.id, entry.operation, state_json(entry.state), entry.mirrors && JSON.generate(entry.mirrors)]
195
- )
196
- entry.sequence = result[0]["sequence"].to_i
197
- entry
198
- end
199
-
200
- # Upserts or deletes the aggregate's row for one journal entry, bumping its version.
201
- #
202
- # `expected_version` requests optimistic-concurrency CAS; nil back means it didn't match.
203
- #
204
- # @param entry [Ports::Persistence::Entry] the save or delete to materialize
205
- # @param expected_version [Integer, nil] the `hecks_version` the row must still hold for
206
- # an update to apply; nil writes unconditionally. Ignored for a delete
207
- # @return [Runtime::Instance, PG::Result, nil] a new instance with `version` set, nil on
208
- # CAS mismatch, or the `DELETE` statement's `PG::Result`
209
- # @raise [PG::Error] if the statement fails
210
- # rubocop:disable Metrics/AbcSize -- the CAS/plain upsert split is one
211
- # protocol; splitting it would hide the version handshake.
212
- def project(entry, expected_version: nil)
213
- advance_checkpoint!(entry.sequence) if entry.sequence
214
- return pg_exec_params("DELETE FROM #{quoted_table} WHERE id = $1", [entry.id]) if entry.delete?
215
-
216
- instance = Runtime::Instance.new(aggregate: @aggregate, id: entry.id, state: entry.state)
217
- columns = (["id"] + persisted_fields.map { |field| field[:name].to_s } + ["hecks_version"])
218
- values = [instance.id.to_s] + persisted_fields.map { |field| encode_field(field, instance[field[:name]]) } + [1]
219
- updates = persisted_fields.map { |field| "#{quote_ident(field[:name])} = EXCLUDED.#{quote_ident(field[:name])}" } +
220
- ["hecks_version = #{quoted_table}.hecks_version + 1"]
221
-
222
- sql = "INSERT INTO #{quoted_table} (#{columns.map { |c| quote_ident(c) }.join(', ')}) " \
223
- "VALUES (#{(1..columns.size).map { |n| "$#{n}" }.join(', ')}) " \
224
- "ON CONFLICT (id) DO UPDATE SET #{updates.join(', ')}"
225
- if expected_version
226
- values += [expected_version]
227
- sql += " WHERE #{quoted_table}.hecks_version = $#{values.size}"
228
- end
229
- sql += " RETURNING hecks_version"
230
-
231
- result = pg_exec_params(sql, values)
232
- return nil if result.ntuples.zero?
233
-
234
- instance.version = result[0]["hecks_version"].to_i
235
- instance
236
- end
237
- # rubocop:enable Metrics/AbcSize
238
-
239
- # Reads the whole journal back in append order, for `AppendOnly#recover!` to replay.
240
- #
241
- # @return [Array<Ports::Persistence::Entry>] every journalled entry, state decoded
242
- # through the state codec and `mirrors` parsed with String keys (nil when none were
243
- # stored); `[]` when nothing has been appended
244
- # @raise [PG::Error] if the statement fails
245
- # @raise [JSON::ParserError] if a stored `state` or `mirrors` value is not valid JSON
246
- def entries
247
- entries_matching(
248
- "SELECT aggregate_id, operation, state, mirrors, sequence FROM #{quoted_entry_table} ORDER BY sequence"
249
- )
250
- end
251
-
252
- # Reads only the journal rows past a given `sequence`, for `AppendOnly#recover!` to replay
253
- # after a checkpoint instead of the whole journal.
254
- #
255
- # @param sequence [Integer] the highest `sequence` already projected; rows at or below it
256
- # are skipped
257
- # @return [Array<Ports::Persistence::Entry>] the journalled entries past `sequence`, in
258
- # append order, decoded exactly as `entries` decodes them; `[]` when none are newer
259
- # @raise [PG::Error] if the statement fails
260
- # @raise [JSON::ParserError] if a stored `state` or `mirrors` value is not valid JSON
261
- def entries_since(sequence)
262
- entries_matching(
263
- "SELECT aggregate_id, operation, state, mirrors, sequence FROM #{quoted_entry_table} " \
264
- "WHERE sequence > $1 ORDER BY sequence",
265
- [sequence]
266
- )
267
- end
268
-
269
- # Reads the highest journal `sequence` this table has already had projected into it.
270
- #
271
- # @return [Integer] `0` when the table has never been checkpointed (a fresh table, or one
272
- # from before this bookkeeping existed) — `entries_since(0)` then reads the whole journal,
273
- # matching `entries`' own full replay
274
- # @raise [PG::Error] if the statement fails
275
- def checkpoint
276
- result = pg_exec_params("SELECT last_sequence FROM hecks_checkpoints WHERE aggregate_table = $1", [table])
277
- result.ntuples.zero? ? 0 : result[0]["last_sequence"].to_i
278
- end
279
-
280
- # Reads the highest journal `sequence` compaction has already deleted from this table.
281
- #
282
- # @return [Integer] `0` when nothing has ever been compacted
283
- # @raise [PG::Error] if the statement fails
284
- def compacted_through
285
- result = pg_exec_params("SELECT compacted_through FROM hecks_checkpoints WHERE aggregate_table = $1", [table])
286
- result.ntuples.zero? ? 0 : result[0]["compacted_through"].to_i
287
- end
288
-
289
- # Deletes every journal row at or before `through` and records it, so a `:strict`
290
- # projection catch-up can tell whether it still has the history it needs.
291
- #
292
- # Never moves `compacted_through` backwards, and never touches the aggregate's own
293
- # table — only the journal, which a `:refresh` projection rebuild never needs.
294
- #
295
- # @param through [Integer] the highest `sequence` to delete
296
- # @return [Integer] the number of journal rows deleted
297
- # @raise [PG::Error] if a statement fails
298
- def compact_entries!(through:)
299
- removed = pg_exec_params("DELETE FROM #{quoted_entry_table} WHERE sequence <= $1", [through]).cmd_tuples
300
- pg_exec_params(
301
- "INSERT INTO hecks_checkpoints (aggregate_table, compacted_through) VALUES ($1, $2) " \
302
- "ON CONFLICT (aggregate_table) DO UPDATE SET " \
303
- "compacted_through = GREATEST(hecks_checkpoints.compacted_through, excluded.compacted_through)",
304
- [table, through]
305
- )
306
- removed
307
- end
308
-
309
- # Deletes every row of the aggregate's table and its journal; events, saga rows and
310
- # outbox rows are left in place.
311
- #
312
- # @return [Adapters::Postgres] self
313
- # @raise [PG::Error] if a statement fails
314
- def reset!
315
- pg_exec("DELETE FROM #{quoted_table}")
316
- pg_exec("DELETE FROM #{quoted_entry_table}")
317
- self
318
- end
319
-
320
- # Journals and upserts an instance's current state atomically.
321
- #
322
- # One transaction, so a crash between the journal insert and the row upsert
323
- # can never leave the two disagreeing.
324
- #
325
- # @param instance [Runtime::Instance] the instance to store
326
- # @return [Runtime::Instance] a new instance over the saved state, `version` set to the
327
- # row's new `hecks_version`
328
- # @raise [PG::Error] if either statement fails; the transaction is rolled back
329
- def save(instance)
330
- entry = Ports::Persistence::Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup)
331
- transaction do
332
- append(entry)
333
- project(entry)
334
- end
335
- end
336
-
337
- # Stores an entry under a per-identity advisory lock and reports whether it inserted,
338
- # replaced or conflicted, so two concurrent creators of one id cannot both insert.
339
- #
340
- # @param entry [Ports::Persistence::Entry] the save to store
341
- # @param insert_only [Boolean] when true, an existing row is left untouched
342
- # @return [Symbol] `:inserted`, `:replaced`, or `:conflicted` when `insert_only` met an
343
- # existing row and nothing was written
344
- # @raise [PG::Error] if a statement fails; the transaction is rolled back
345
- def atomic_put(entry, insert_only: false)
346
- status = nil
347
- transaction do
348
- pg_exec_params(
349
- "SELECT pg_advisory_xact_lock(" \
350
- "hashtext(current_schema() || ':' || $1), hashtext($2))",
351
- [table, entry.id.to_s]
352
- )
353
- exists = !pg_exec_params(
354
- "SELECT 1 FROM #{quoted_table} WHERE id = $1",
355
- [entry.id.to_s]
356
- ).ntuples.zero?
357
- if insert_only && exists
358
- status = :conflicted
359
- next
360
- end
361
- status = exists ? :replaced : :inserted
362
- append(entry)
363
- project(entry)
364
- end
365
- status
366
- end
367
-
368
- # Journals a delete and removes the row atomically, whether or not a row exists.
369
- #
370
- # @param id [String, Object] the aggregate identity, journalled as `id.to_s`
371
- # @return [Boolean] always true
372
- # @raise [PG::Error] if either statement fails; the transaction is rolled back
373
- def delete(id)
374
- entry = Ports::Persistence::Entry.new(operation: "delete", id: id.to_s, state: nil)
375
- transaction do
376
- append(entry)
377
- project(entry)
378
- end
379
- true
380
- end
381
-
382
- # Inserts an emitted event into the shared `events` table.
383
- #
384
- # @param event [Runtime::Event] the emitted event; `payload` is stored as JSON
385
- # @return [PG::Result] the insert's result; callers ignore it
386
- # @raise [PG::Error] if the insert fails
387
- def record_event(event)
388
- pg_exec_params(
389
- "INSERT INTO events (name, aggregate, aggregate_id, payload, occurred_at) VALUES ($1, $2, $3, $4, $5)",
390
- [event.name, event.aggregate, event.id.to_s, JSON.generate(event.payload), event.occurred_at]
391
- )
392
- end
393
-
394
- # Reads back every recorded event in insertion order — the whole `events` table, not
395
- # only this aggregate's rows.
396
- #
397
- # @return [Array<Runtime::Event>] the stored events, `payload` parsed with Symbol keys
398
- # and `occurred_at` as the String Postgres returns; `[]` when none are recorded
399
- # @raise [PG::Error] if the statement fails
400
- def events
401
- pg_exec("SELECT * FROM events ORDER BY id").map do |row|
402
- Runtime::Event.new(
403
- name: row["name"],
404
- aggregate: row["aggregate"],
405
- id: row["aggregate_id"],
406
- payload: JSON.parse(row["payload"], symbolize_names: true),
407
- occurred_at: row["occurred_at"]
408
- )
409
- end
410
- end
411
-
412
- # Reads back one record's recorded events, oldest first — pushed down as a `WHERE`
413
- # clause (`hecks_events_aggregate_id_idx`) instead of filtering `#events`'s whole-table
414
- # read, since a `corrects` command's history lookup only ever needs this one record.
415
- #
416
- # @param aggregate [String] the `"domain::AggregateName"` key events are stored under
417
- # @param id [String, Object] the record's identity, matched as `id.to_s`
418
- # @return [Array<Runtime::Event>] the record's stored events; `[]` when it has none
419
- # @raise [PG::Error] if the statement fails
420
- def events_for(aggregate:, id:)
421
- pg_exec_params(
422
- "SELECT * FROM events WHERE aggregate = $1 AND aggregate_id = $2 ORDER BY id",
423
- [aggregate, id.to_s]
424
- ).map do |row|
425
- Runtime::Event.new(
426
- name: row["name"],
427
- aggregate: row["aggregate"],
428
- id: row["aggregate_id"],
429
- payload: JSON.parse(row["payload"], symbolize_names: true),
430
- occurred_at: row["occurred_at"]
431
- )
432
- end
433
- end
434
-
435
- # Upserts one saga instance's checkpoint, keyed by domain, process manager and
436
- # correlation.
437
- #
438
- # @param process_manager [String, Symbol] the process manager's name
439
- # @param correlation [String, Object] the instance's correlation value, stored as
440
- # `correlation.to_s`
441
- # @param state [String, Symbol] the saga's current state name
442
- # @param memory [Hash] the saga's memory; must be JSON-serializable
443
- # @param completed_compensations [Array] the ledger of completed compensable legs; must
444
- # be JSON-serializable
445
- # @return [PG::Result] the upsert's result; callers ignore it
446
- # @raise [PG::Error] if the statement fails
447
- def save_saga(process_manager:, correlation:, state:, memory:, completed_compensations: [])
448
- pg_exec_params(
449
- "INSERT INTO hecks_saga_instances (domain, process_manager, correlation, state, memory, completed_compensations) " \
450
- "VALUES ($1, $2, $3, $4, $5, $6) " \
451
- "ON CONFLICT (domain, process_manager, correlation) DO UPDATE " \
452
- "SET state = EXCLUDED.state, memory = EXCLUDED.memory, " \
453
- "completed_compensations = EXCLUDED.completed_compensations, updated_at = now()",
454
- [@domain, process_manager.to_s, correlation.to_s, state.to_s, JSON.generate(memory),
455
- JSON.generate(completed_compensations)]
456
- )
457
- end
458
-
459
- # Removes a finished saga instance's checkpoint; a missing row is not an error.
460
- #
461
- # @param process_manager [String, Symbol] the process manager's name
462
- # @param correlation [String, Object] the instance's correlation value, matched as
463
- # `correlation.to_s`
464
- # @return [PG::Result] the delete's result; callers ignore it
465
- # @raise [PG::Error] if the statement fails
466
- def delete_saga(process_manager:, correlation:)
467
- pg_exec_params(
468
- "DELETE FROM hecks_saga_instances WHERE domain = $1 AND process_manager = $2 AND correlation = $3",
469
- [@domain, process_manager.to_s, correlation.to_s]
470
- )
471
- end
472
-
473
- # Yields every checkpointed saga instance of this adapter's domain, for
474
- # `Registry#rehydrate_sagas!` to restore at boot.
475
- #
476
- # @yieldparam process_manager [String] the process manager's name
477
- # @yieldparam correlation [String] the instance's correlation value
478
- # @yieldparam state [String] the saga's state name
479
- # @yieldparam memory [Hash{Symbol => Object}] the saga's memory, Symbol keys at every depth
480
- # @yieldparam completed_compensations [Array] the completed-compensation ledger, `[]`
481
- # when the column is NULL
482
- # @return [Enumerator, PG::Result] an enumerator over the same five values when no block
483
- # is given; otherwise the query result
484
- # @raise [PG::Error] if the statement fails
485
- def each_saga
486
- return enum_for(:each_saga) unless block_given?
487
-
488
- pg_exec_params(
489
- "SELECT process_manager, correlation, state, memory, completed_compensations " \
490
- "FROM hecks_saga_instances WHERE domain = $1",
491
- [@domain]
492
- ).each do |row|
493
- yield row["process_manager"], row["correlation"], row["state"],
494
- JSON.parse(row["memory"], symbolize_names: true),
495
- JSON.parse(row["completed_compensations"] || "[]", symbolize_names: true)
496
- end
497
- end
498
-
499
132
  private
500
133
 
501
- def select_list = "*"
502
- def from_relation = quoted_table
503
- def dialect_name = "Postgres"
504
- def empty_in_clause = "FALSE"
505
-
506
- def placeholder(binds, value)
507
- binds << value
508
- "$#{binds.size}"
509
- end
510
-
511
- def contains_clause(expression, placeholder)
512
- "position(#{placeholder} in #{expression}) > 0"
513
- end
514
-
515
- # `column` is already a real jsonb column and already the array — no shared
516
- # `state` blob to walk into first, unlike PostgresEra's own version.
517
- def list_contains_clause(column, member, placeholder)
518
- target = member.empty? ? "elem #>> '{}'" : "elem ->> #{text_literal(member)}"
519
- elements = "jsonb_array_elements(#{quote_ident(column)}) AS elem"
520
- "EXISTS (SELECT 1 FROM #{elements} WHERE #{target} = #{placeholder})"
521
- end
522
-
523
- def plain_column(name) = quote_ident(name)
524
-
525
- # The attribute name is the column itself here, not part of the path (unlike
526
- # PostgresEra's shared `state` blob) — the path is whatever follows the column.
527
- def nested_expression(name, path, member)
528
- segments = path.empty? ? [(member || "value").to_s] : path
529
- jsonb_path(name, segments)
530
- end
531
-
532
- # A jsonb-extracted value still comes out as text; cast it to compare/sort
533
- # numerically instead of lexicographically.
534
- def comparable_expression(expression, value)
535
- value.is_a?(Numeric) && jsonb_extraction?(expression) ? "(#{expression})::numeric" : expression
536
- end
537
-
538
- def execute_query(sql, binds)
539
- pg_exec_params(sql, binds).map { |row| instance_from_row(row) }
540
- end
541
-
542
- # Stamps `.version` from `hecks_version` so a later CAS save has something
543
- # to check against.
544
- def instance_from_row(row)
545
- instance = Runtime::Instance.new(aggregate: @aggregate, id: row["id"], state: decode(row))
546
- instance.version = row["hecks_version"].to_i
547
- instance
548
- end
549
-
550
- def quote_ident(name) = PG::Connection.quote_ident(name.to_s)
551
- def quoted_table = quote_ident(table)
552
- def entry_table = "#{table}_entries"
553
- def quoted_entry_table = quote_ident(entry_table)
554
-
555
- def jsonb_extraction?(expression) = expression.include?("#>>")
556
-
557
- def order_expression(field)
558
- expression = query_expression(field)
559
- jsonb_extraction?(expression) && numeric_field?(field) ? "(#{expression})::numeric" : expression
560
- end
561
-
562
- # Overrides Postgres's default NULLS LAST on ASC so every adapter answers
563
- # a declared query's null ordering identically.
564
- def order_clause(order_by, policy)
565
- direction = order_by.direction.to_s.downcase == "desc" ? "DESC" : "ASC"
566
- nulls = case policy&.mode.to_s
567
- when "first" then " NULLS FIRST"
568
- when "last" then " NULLS LAST"
569
- else direction == "DESC" ? " NULLS LAST" : " NULLS FIRST"
570
- end
571
- "#{order_expression(order_by.field)} #{direction}#{nulls}, id #{direction}"
572
- end
573
-
574
- # Same walk PostgresEra's own numeric_field? uses — decides
575
- # numericness at any depth from the declared shape itself, not a
576
- # runtime value.
577
- def numeric_field?(field)
578
- name, *path = field.to_s.split(".")
579
- QuerySpecification::FieldPath.numeric?(@aggregate.attribute(name), path) do |type|
580
- Runtime::Value.value_object_for(@aggregate, type)
581
- end
582
- end
583
-
584
- # Builds an escaped Array[...] literal rather than a hand-rolled '{a,b,c}'
585
- # string, since a segment name isn't guaranteed schema-declared.
586
- def jsonb_path(column, segments)
587
- "#{quote_ident(column)} #>> ARRAY[#{segments.map { |segment| text_literal(segment) }.join(', ')}]::text[]"
134
+ def create_tables!
135
+ create_aggregate_table!
136
+ create_entry_table!
137
+ create_event_table!
138
+ create_saga_table!
139
+ create_outbox_table!
140
+ create_checkpoint_table!
588
141
  end
589
142
 
590
- # Shared decode step for `entries`/`entries_since` — runs a query already selecting
591
- # `aggregate_id, operation, state, mirrors, sequence` and builds one Entry per row.
592
- def entries_matching(sql, binds = [])
593
- pg_exec_params(sql, binds).map do |row|
594
- state = JSON.parse(row["state"])
595
- Ports::Persistence::Entry.new(
596
- operation: row["operation"] || "save",
597
- id: row["aggregate_id"],
598
- state: Ports::Persistence::StateCodec.decode(@aggregate, state),
599
- mirrors: row["mirrors"] && JSON.parse(row["mirrors"]),
600
- sequence: row["sequence"].to_i
601
- )
602
- end
603
- end
143
+ # A setting read under its Symbol key, then its String key, then `default`.
144
+ def setting(settings, key, default)
145
+ return settings[key] if settings.key?(key)
146
+ return settings[key.to_s] if settings.key?(key.to_s)
604
147
 
605
- # Advances this table's checkpoint to `sequence`, never backwards — two overlapping
606
- # `project` calls for out-of-order entries must not let an older sequence win.
607
- def advance_checkpoint!(sequence)
608
- pg_exec_params(
609
- "INSERT INTO hecks_checkpoints (aggregate_table, last_sequence) VALUES ($1, $2) " \
610
- "ON CONFLICT (aggregate_table) DO UPDATE SET " \
611
- "last_sequence = GREATEST(hecks_checkpoints.last_sequence, EXCLUDED.last_sequence)",
612
- [table, sequence]
613
- )
148
+ default
614
149
  end
615
-
616
- def text_literal(text) = "'#{text.to_s.gsub("'", "''")}'"
617
150
  end
618
151
  end
619
152
  end
@@ -123,7 +123,7 @@ module Hecks
123
123
  def walk(node, &visit)
124
124
  return unless node.is_a?(::Prism::Node)
125
125
 
126
- visit.call(node)
126
+ yield(node)
127
127
  node.compact_child_nodes.each { |child| walk(child, &visit) }
128
128
  end
129
129