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