hecks 3.5.0 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1156) hide show
  1. checksums.yaml +4 -4
  2. data/examples/pizzas/bluebook/hecksagon/mock_stripe_payment_adapter.rb +1 -1
  3. data/lib/hecks/adapters/driven/claude_code.rb +11 -7
  4. data/lib/hecks/adapters/driven/d1/connection.rb +90 -0
  5. data/lib/hecks/adapters/driven/d1.rb +48 -314
  6. data/lib/hecks/adapters/driven/folder.rb +20 -10
  7. data/lib/hecks/adapters/driven/google_authentication.rb +18 -4
  8. data/lib/hecks/adapters/driven/governance_authorization.rb +2 -2
  9. data/lib/hecks/adapters/driven/heki/journal.rb +11 -10
  10. data/lib/hecks/adapters/driven/heki/saga_store.rb +4 -6
  11. data/lib/hecks/adapters/driven/heki/sagas.rb +55 -0
  12. data/lib/hecks/adapters/driven/heki.rb +21 -66
  13. data/lib/hecks/adapters/driven/in_memory_ordering.rb +37 -12
  14. data/lib/hecks/adapters/driven/lambda/client.rb +1 -1
  15. data/lib/hecks/adapters/driven/lambda.rb +1 -8
  16. data/lib/hecks/adapters/driven/memory/outbox_rows.rb +76 -0
  17. data/lib/hecks/adapters/driven/memory/shared_elements/values.rb +117 -0
  18. data/lib/hecks/adapters/driven/memory/shared_elements.rb +10 -97
  19. data/lib/hecks/adapters/driven/memory.rb +3 -65
  20. data/lib/hecks/adapters/driven/postgres/codec.rb +29 -26
  21. data/lib/hecks/adapters/driven/postgres/ddl.rb +50 -0
  22. data/lib/hecks/adapters/driven/postgres/dialect.rb +93 -0
  23. data/lib/hecks/adapters/driven/postgres/events.rb +57 -0
  24. data/lib/hecks/adapters/driven/postgres/journal.rb +127 -0
  25. data/lib/hecks/adapters/driven/postgres/outbox.rb +39 -31
  26. data/lib/hecks/adapters/driven/postgres/repository.rb +190 -0
  27. data/lib/hecks/adapters/driven/postgres/sagas.rb +72 -0
  28. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +13 -41
  29. data/lib/hecks/adapters/driven/postgres.rb +61 -528
  30. data/lib/hecks/adapters/driven/prism.rb +1 -1
  31. data/lib/hecks/adapters/driven/sql_query_builder.rb +45 -53
  32. data/lib/hecks/adapters/driven/sql_value_members.rb +57 -0
  33. data/lib/hecks/adapters/driven/sqlite/codec.rb +32 -29
  34. data/lib/hecks/adapters/driven/sqlite/ddl.rb +68 -0
  35. data/lib/hecks/adapters/driven/sqlite/dialect.rb +55 -0
  36. data/lib/hecks/adapters/driven/sqlite/events.rb +61 -0
  37. data/lib/hecks/adapters/driven/sqlite/journal.rb +125 -0
  38. data/lib/hecks/adapters/driven/sqlite/outbox.rb +98 -0
  39. data/lib/hecks/adapters/driven/sqlite/projection.rb +82 -63
  40. data/lib/hecks/adapters/driven/sqlite/repository.rb +146 -0
  41. data/lib/hecks/adapters/driven/sqlite/sagas.rb +69 -0
  42. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +8 -55
  43. data/lib/hecks/adapters/driven/sqlite.rb +36 -513
  44. data/lib/hecks/adapters/driven/tenant_provisioner.rb +13 -7
  45. data/lib/hecks/adapters/driving/github_webhook.rb +11 -8
  46. data/lib/hecks/behaviors/dsl.rb +17 -12
  47. data/lib/hecks/behaviors/expectations/boot.rb +81 -0
  48. data/lib/hecks/behaviors/expectations/checks.rb +178 -0
  49. data/lib/hecks/behaviors/expectations/dispatching.rb +93 -0
  50. data/lib/hecks/behaviors/expectations/qualify.rb +81 -0
  51. data/lib/hecks/behaviors/expectations.rb +39 -355
  52. data/lib/hecks/behaviors/rspec.rb +12 -12
  53. data/lib/hecks/behaviors/runner.rb +20 -11
  54. data/lib/hecks/bench/cli.rb +16 -13
  55. data/lib/hecks/bench/environment.rb +1 -1
  56. data/lib/hecks/bench/report.rb +11 -7
  57. data/lib/hecks/bench/ruby_runner.rb +13 -8
  58. data/lib/hecks/bench/rust_runner.rb +19 -11
  59. data/lib/hecks/bench/suite.rb +48 -20
  60. data/lib/hecks/bench/workload.rb +42 -31
  61. data/lib/hecks/bluebook/aggregate.rb +15 -21
  62. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +18 -21
  63. data/lib/hecks/bluebook/assembly/build.rb +12 -7
  64. data/lib/hecks/bluebook/assembly/contracts/read_models.rb +70 -0
  65. data/lib/hecks/bluebook/assembly/contracts/rules.rb +84 -0
  66. data/lib/hecks/bluebook/assembly/contracts/sagas.rb +109 -0
  67. data/lib/hecks/bluebook/assembly/contracts/structure.rb +91 -0
  68. data/lib/hecks/bluebook/assembly/contracts.rb +9 -319
  69. data/lib/hecks/bluebook/assembly/marks.rb +9 -8
  70. data/lib/hecks/bluebook/attribute.rb +13 -10
  71. data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -3
  72. data/lib/hecks/bluebook/behaviour/read_model.rb +26 -13
  73. data/lib/hecks/bluebook/chapter.rb +22 -14
  74. data/lib/hecks/bluebook/command.rb +14 -18
  75. data/lib/hecks/bluebook/domain_port.rb +11 -8
  76. data/lib/hecks/bluebook/dsl/aggregate_builder/correction_sealing.rb +78 -0
  77. data/lib/hecks/bluebook/dsl/aggregate_builder/draining.rb +74 -0
  78. data/lib/hecks/bluebook/dsl/aggregate_builder/query_field_sealing.rb +105 -0
  79. data/lib/hecks/bluebook/dsl/aggregate_builder/query_sealing.rb +121 -0
  80. data/lib/hecks/bluebook/dsl/aggregate_builder/relationships.rb +128 -0
  81. data/lib/hecks/bluebook/dsl/aggregate_builder/rules.rb +84 -0
  82. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +61 -249
  83. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +51 -285
  84. data/lib/hecks/bluebook/dsl/attribute_collector/identity_resolution.rb +113 -0
  85. data/lib/hecks/bluebook/dsl/attribute_collector.rb +58 -117
  86. data/lib/hecks/bluebook/dsl/binding_proxy.rb +24 -19
  87. data/lib/hecks/bluebook/dsl/bluebook_builder/pending_givens.rb +109 -0
  88. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/correlation_keys.rb +105 -0
  89. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/event_shapes.rb +126 -0
  90. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/hop_tails.rb +79 -0
  91. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/projected_fields.rb +76 -0
  92. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/provisions.rb +65 -0
  93. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/query_hops.rb +123 -0
  94. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/references.rb +112 -0
  95. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/with_projections.rb +126 -0
  96. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +34 -595
  97. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +18 -107
  98. data/lib/hecks/bluebook/dsl/command_builder/implicit_attributes.rb +132 -0
  99. data/lib/hecks/bluebook/dsl/command_builder/mutations.rb +190 -0
  100. data/lib/hecks/bluebook/dsl/command_builder/owner.rb +22 -0
  101. data/lib/hecks/bluebook/dsl/command_builder/rules.rb +57 -0
  102. data/lib/hecks/bluebook/dsl/command_builder.rb +60 -360
  103. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +19 -13
  104. data/lib/hecks/bluebook/dsl/entity_builder/rules.rb +96 -0
  105. data/lib/hecks/bluebook/dsl/entity_builder/scope.rb +25 -0
  106. data/lib/hecks/bluebook/dsl/entity_builder/sealing.rb +94 -0
  107. data/lib/hecks/bluebook/dsl/entity_builder.rb +35 -169
  108. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +53 -24
  109. data/lib/hecks/bluebook/dsl/hecksagon_builder/chapter_scope.rb +133 -0
  110. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +3 -97
  111. data/lib/hecks/bluebook/dsl/identity_declaration.rb +73 -73
  112. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +7 -3
  113. data/lib/hecks/bluebook/dsl/need_word.rb +1 -1
  114. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +34 -29
  115. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +57 -41
  116. data/lib/hecks/bluebook/dsl/query_builder.rb +12 -15
  117. data/lib/hecks/bluebook/dsl/read_model_builder/sealing.rb +116 -0
  118. data/lib/hecks/bluebook/dsl/read_model_builder.rb +25 -102
  119. data/lib/hecks/bluebook/dsl/rule_reference.rb +26 -12
  120. data/lib/hecks/bluebook/dsl/translation_builder.rb +24 -14
  121. data/lib/hecks/bluebook/dsl/value_object_builder.rb +29 -19
  122. data/lib/hecks/bluebook/dsl/word_gate.rb +34 -27
  123. data/lib/hecks/bluebook/entity.rb +13 -17
  124. data/lib/hecks/bluebook/expression/ast_json/emitters.rb +93 -0
  125. data/lib/hecks/bluebook/expression/ast_json/emitters.rb-e +88 -0
  126. data/lib/hecks/bluebook/expression/ast_json.rb +49 -76
  127. data/lib/hecks/bluebook/expression/ast_reader.rb +95 -28
  128. data/lib/hecks/bluebook/expression/canonical_form.rb +6 -26
  129. data/lib/hecks/bluebook/expression/evaluator/parser.rb +62 -0
  130. data/lib/hecks/bluebook/expression/evaluator/scanning.rb +122 -0
  131. data/lib/hecks/bluebook/expression/evaluator.rb +11 -111
  132. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +28 -44
  133. data/lib/hecks/bluebook/expression/resolver/lookups.rb +77 -0
  134. data/lib/hecks/bluebook/expression/resolver/operations.rb +78 -0
  135. data/lib/hecks/bluebook/expression/resolver/parsing.rb +110 -0
  136. data/lib/hecks/bluebook/expression/resolver/scanning.rb +139 -0
  137. data/lib/hecks/bluebook/expression/resolver/values.rb +115 -0
  138. data/lib/hecks/bluebook/expression/resolver.rb +16 -414
  139. data/lib/hecks/bluebook/{hexagon.rb → hecksagon.rb} +22 -14
  140. data/lib/hecks/bluebook/keyword_fields.rb +42 -0
  141. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +7 -6
  142. data/lib/hecks/bluebook/meta_validator/judge/cells.rb +99 -0
  143. data/lib/hecks/bluebook/meta_validator/judge/dispatching.rb +111 -0
  144. data/lib/hecks/bluebook/meta_validator/judge/identity.rb +108 -0
  145. data/lib/hecks/bluebook/meta_validator/judge/walking.rb +141 -0
  146. data/lib/hecks/bluebook/meta_validator/judge.rb +31 -376
  147. data/lib/hecks/bluebook/meta_validator/modes.rb +137 -0
  148. data/lib/hecks/bluebook/meta_validator/plan/category.rb +44 -0
  149. data/lib/hecks/bluebook/meta_validator/plan/verbs.rb +73 -0
  150. data/lib/hecks/bluebook/meta_validator/plan.rb +38 -122
  151. data/lib/hecks/bluebook/meta_validator/readings/fields.rb +100 -0
  152. data/lib/hecks/bluebook/meta_validator/readings.rb +10 -95
  153. data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +89 -0
  154. data/lib/hecks/bluebook/meta_validator/reconstruction/reading.rb +96 -0
  155. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -151
  156. data/lib/hecks/bluebook/meta_validator/shapes/helpers.rb +83 -0
  157. data/lib/hecks/bluebook/meta_validator/shapes.rb +8 -75
  158. data/lib/hecks/bluebook/meta_validator/syntax_boot/disk_cache.rb +102 -0
  159. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +31 -95
  160. data/lib/hecks/bluebook/meta_validator/translation_judge/rules.rb +74 -0
  161. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +15 -65
  162. data/lib/hecks/bluebook/meta_validator/verdict_cache/prebuilt.rb +44 -0
  163. data/lib/hecks/bluebook/meta_validator/verdict_cache/tagging.rb +63 -0
  164. data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +25 -60
  165. data/lib/hecks/bluebook/meta_validator/world_judge.rb +8 -4
  166. data/lib/hecks/bluebook/meta_validator.rb +59 -175
  167. data/lib/hecks/bluebook/model_check/lifecycle_checks.rb +122 -0
  168. data/lib/hecks/bluebook/model_check/policy_checks.rb +129 -0
  169. data/lib/hecks/bluebook/model_check/saga_checks.rb +134 -0
  170. data/lib/hecks/bluebook/model_check/verbs.rb +69 -0
  171. data/lib/hecks/bluebook/model_check.rb +73 -413
  172. data/lib/hecks/bluebook/pattern_subset/refusals.rb +54 -0
  173. data/lib/hecks/bluebook/pattern_subset/scan.rb +58 -0
  174. data/lib/hecks/bluebook/pattern_subset.rb +93 -134
  175. data/lib/hecks/bluebook/process_manager.rb +10 -9
  176. data/lib/hecks/bluebook/project_discovery.rb +10 -7
  177. data/lib/hecks/bluebook/project_register.rb +42 -41
  178. data/lib/hecks/bluebook/query.rb +19 -12
  179. data/lib/hecks/bluebook/read_model.rb +41 -39
  180. data/lib/hecks/bluebook/smoke_test.rb +51 -36
  181. data/lib/hecks/bluebook/synthesizer.rb +13 -5
  182. data/lib/hecks/bluebook/translation.rb +12 -12
  183. data/lib/hecks/bluebook.rb +1 -1
  184. data/lib/hecks/cache_dir.rb +10 -0
  185. data/lib/hecks/chapters.rb +32 -16
  186. data/lib/hecks/cli/behaviors.rb +22 -15
  187. data/lib/hecks/cli/check_era.rb +2 -2
  188. data/lib/hecks/cli/command_table.rb +72 -0
  189. data/lib/hecks/cli/console.rb +10 -7
  190. data/lib/hecks/cli/deploy_template_diff.rb +22 -9
  191. data/lib/hecks/cli/document.rb +14 -10
  192. data/lib/hecks/cli/domain_stub.rb +1 -1
  193. data/lib/hecks/cli/domain_writer.rb +1 -1
  194. data/lib/hecks/cli/expression_projection.rb +8 -6
  195. data/lib/hecks/cli/follow.rb +10 -4
  196. data/lib/hecks/cli/interview_aggregate.rb +132 -0
  197. data/lib/hecks/cli/interview_draft.rb +16 -200
  198. data/lib/hecks/cli/interview_record.rb +130 -0
  199. data/lib/hecks/cli/interview_run.rb +19 -8
  200. data/lib/hecks/cli/interview_session/agent_state.rb +70 -0
  201. data/lib/hecks/cli/interview_session/catalog.rb +76 -0
  202. data/lib/hecks/cli/interview_session/manual_findings.rb +48 -0
  203. data/lib/hecks/cli/interview_session/proposals.rb +90 -0
  204. data/lib/hecks/cli/interview_session.rb +8 -205
  205. data/lib/hecks/cli/interview_shape.rb +13 -6
  206. data/lib/hecks/cli/ir.rb +8 -11
  207. data/lib/hecks/cli/launcher_words.rb +168 -0
  208. data/lib/hecks/cli/model_check/examination.rb +93 -0
  209. data/lib/hecks/cli/model_check/sources.rb +57 -0
  210. data/lib/hecks/cli/model_check.rb +28 -134
  211. data/lib/hecks/cli/project_cli/launcher_source.rb +177 -0
  212. data/lib/hecks/cli/project_cli/templates.rb +106 -0
  213. data/lib/hecks/cli/project_cli.rb +57 -236
  214. data/lib/hecks/cli/project_diagrams.rb +26 -4
  215. data/lib/hecks/cli/project_glossary.rb +19 -9
  216. data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +29 -13
  217. data/lib/hecks/cli/release.rb +29 -22
  218. data/lib/hecks/cli/release_gem.rb +12 -6
  219. data/lib/hecks/cli/rspec_io_parallel_files.rb +87 -30
  220. data/lib/hecks/cli/rspec_shard_files.rb +24 -9
  221. data/lib/hecks/cli/run.rb +25 -44
  222. data/lib/hecks/cli/run_expectations.rb +63 -0
  223. data/lib/hecks/cli/seed_semantics_corpus.rb +37 -17
  224. data/lib/hecks/cli/smoke_http/checks.rb +66 -0
  225. data/lib/hecks/cli/smoke_http/settings.rb +63 -0
  226. data/lib/hecks/cli/smoke_http/transport.rb +45 -0
  227. data/lib/hecks/cli/smoke_http.rb +8 -142
  228. data/lib/hecks/cli/smoke_test.rb +18 -4
  229. data/lib/hecks/cli/stores.rb +7 -4
  230. data/lib/hecks/cli/stress_concurrency_specs/reporting.rb +44 -0
  231. data/lib/hecks/cli/stress_concurrency_specs/usage.rb +28 -0
  232. data/lib/hecks/cli/stress_concurrency_specs.rb +82 -80
  233. data/lib/hecks/cli.rb +32 -208
  234. data/lib/hecks/codemod/runner.rb +92 -0
  235. data/lib/hecks/codemod/sweep.rb +94 -0
  236. data/lib/hecks/codemod.rb +22 -165
  237. data/lib/hecks/corpus/routes.rb +34 -0
  238. data/lib/hecks/corpus/rust.rb +193 -0
  239. data/lib/hecks/corpus/sources.rb +46 -0
  240. data/lib/hecks/corpus.rb +28 -265
  241. data/lib/hecks/deploy/bluebook/deploy.bluebook +109 -0
  242. data/lib/hecks/deploy/oidc.json +10 -0
  243. data/lib/hecks/doc/reference/coverage.rb +70 -0
  244. data/lib/hecks/doc/reference/harvester.rb +55 -0
  245. data/lib/hecks/doc/reference/readme.rb +89 -0
  246. data/lib/hecks/doc/reference/rendering.rb +149 -0
  247. data/lib/hecks/doc/reference.rb +14 -273
  248. data/lib/hecks/doors/cli_door/nesting.rb +34 -0
  249. data/lib/hecks/doors/cli_door/shorthand.rb +85 -0
  250. data/lib/hecks/doors/cli_door.rb +23 -95
  251. data/lib/hecks/doors/cli_runner/answers.rb +138 -0
  252. data/lib/hecks/doors/cli_runner/resolution.rb +146 -0
  253. data/lib/hecks/doors/cli_runner/settling.rb +115 -0
  254. data/lib/hecks/doors/cli_runner/streaming.rb +90 -0
  255. data/lib/hecks/doors/cli_runner/suggestions.rb +43 -0
  256. data/lib/hecks/doors/cli_runner.rb +12 -336
  257. data/lib/hecks/doors/command_request.rb +42 -31
  258. data/lib/hecks/doors/handle.rb +32 -30
  259. data/lib/hecks/doors/launcher_options.rb +62 -7
  260. data/lib/hecks/doors/mcp_door/properties.rb +47 -0
  261. data/lib/hecks/doors/mcp_door/tool_calls.rb +113 -0
  262. data/lib/hecks/doors/mcp_door/tool_definitions/auditing.rb +51 -0
  263. data/lib/hecks/doors/mcp_door/tool_definitions/calling.rb +69 -0
  264. data/lib/hecks/doors/mcp_door/tool_definitions/reading.rb +97 -0
  265. data/lib/hecks/doors/mcp_door/tool_definitions.rb +15 -0
  266. data/lib/hecks/doors/mcp_door.rb +55 -301
  267. data/lib/hecks/doors/mcp_door_scope/argument_policy.rb +92 -0
  268. data/lib/hecks/doors/mcp_door_scope/env_problems.rb +55 -0
  269. data/lib/hecks/doors/mcp_door_scope/presenter.rb +78 -0
  270. data/lib/hecks/doors/mcp_door_scope.rb +16 -172
  271. data/lib/hecks/doors/ruby_door/aggregate_door.rb +1 -1
  272. data/lib/hecks/doors/ruby_door/chapter.rb +33 -16
  273. data/lib/hecks/doors/ruby_door.rb +14 -11
  274. data/lib/hecks/doors/usage_cache.rb +32 -16
  275. data/lib/hecks/doors.rb +10 -4
  276. data/lib/hecks/embryonaut_bluebook/manifest.rb +11 -3
  277. data/lib/hecks/embryonaut_bluebook/registry/changelog.rb +26 -0
  278. data/lib/hecks/embryonaut_bluebook/registry/versions.rb +27 -0
  279. data/lib/hecks/embryonaut_bluebook/registry.rb +27 -37
  280. data/lib/hecks/embryonaut_bluebook/vendor/acceptance.rb +37 -0
  281. data/lib/hecks/embryonaut_bluebook/vendor.rb +22 -36
  282. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +9 -6
  283. data/lib/hecks/embryonaut_bluebook.rb +16 -11
  284. data/lib/hecks/engine_agreement.rb +24 -17
  285. data/lib/hecks/forms/app/commands.rb +98 -0
  286. data/lib/hecks/forms/app/queries.rb +62 -0
  287. data/lib/hecks/forms/app/records.rb +67 -0
  288. data/lib/hecks/forms/app/responses.rb +46 -0
  289. data/lib/hecks/forms/app.rb +33 -221
  290. data/lib/hecks/forms/banking_presentation.rb +5 -0
  291. data/lib/hecks/forms/command_form_renderer.rb +55 -14
  292. data/lib/hecks/forms/field_controls.rb +95 -0
  293. data/lib/hecks/forms/field_renderer.rb +34 -88
  294. data/lib/hecks/forms/field_shape.rb +9 -34
  295. data/lib/hecks/forms/html.rb +1 -1
  296. data/lib/hecks/forms/index_renderer.rb +14 -9
  297. data/lib/hecks/forms/page.rb +2 -106
  298. data/lib/hecks/forms/page_assets.rb +88 -0
  299. data/lib/hecks/forms/page_script.rb +28 -0
  300. data/lib/hecks/forms/params.rb +17 -8
  301. data/lib/hecks/forms/query_form_renderer.rb +11 -7
  302. data/lib/hecks/forms/record_renderer.rb +28 -19
  303. data/lib/hecks/forms/reference_options.rb +1 -1
  304. data/lib/hecks/forms/text_shape.rb +40 -0
  305. data/lib/hecks/fqn.rb +64 -32
  306. data/lib/hecks/framework.rb +10 -3
  307. data/lib/hecks/freezer.rb +10 -1
  308. data/lib/hecks/fuzzing/bounded_exhaustive_expressions/fragments.rb +61 -0
  309. data/lib/hecks/fuzzing/bounded_exhaustive_expressions/productions.rb +217 -0
  310. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +5 -194
  311. data/lib/hecks/fuzzing/combination_miner.rb +23 -12
  312. data/lib/hecks/fuzzing/concurrent_dispatch/racing.rb +64 -0
  313. data/lib/hecks/fuzzing/concurrent_dispatch/world_copy.rb +66 -0
  314. data/lib/hecks/fuzzing/concurrent_dispatch.rb +31 -107
  315. data/lib/hecks/fuzzing/coverage_campaign.rb +49 -24
  316. data/lib/hecks/fuzzing/differential/wire_comparison.rb +74 -0
  317. data/lib/hecks/fuzzing/differential.rb +59 -84
  318. data/lib/hecks/fuzzing/domain_generator/block_rendering.rb +70 -0
  319. data/lib/hecks/fuzzing/domain_generator/builder/attribute_shapes.rb +105 -0
  320. data/lib/hecks/fuzzing/domain_generator/builder/shapes.rb +97 -0
  321. data/lib/hecks/fuzzing/domain_generator/builder/wiring.rb +128 -0
  322. data/lib/hecks/fuzzing/domain_generator/builder.rb +105 -0
  323. data/lib/hecks/fuzzing/domain_generator/pruning.rb +90 -0
  324. data/lib/hecks/fuzzing/domain_generator/removals.rb +62 -0
  325. data/lib/hecks/fuzzing/domain_generator/rendering.rb +94 -0
  326. data/lib/hecks/fuzzing/domain_generator/tokens.rb +38 -0
  327. data/lib/hecks/fuzzing/domain_generator.rb +7 -555
  328. data/lib/hecks/fuzzing/era_boundary.rb +34 -24
  329. data/lib/hecks/fuzzing/failure_triage.rb +80 -0
  330. data/lib/hecks/fuzzing/form_census/chapter_forms.rb +38 -0
  331. data/lib/hecks/fuzzing/form_census/reference_forms.rb +49 -0
  332. data/lib/hecks/fuzzing/form_census.rb +44 -58
  333. data/lib/hecks/fuzzing/generated_domain_check.rb +23 -11
  334. data/lib/hecks/fuzzing/isolated_boot/copying.rb +62 -0
  335. data/lib/hecks/fuzzing/isolated_boot/postgres_scratch.rb +148 -0
  336. data/lib/hecks/fuzzing/isolated_boot/scratch_schema.rb +27 -0
  337. data/lib/hecks/fuzzing/isolated_boot/worlds.rb +102 -0
  338. data/lib/hecks/fuzzing/isolated_boot.rb +29 -252
  339. data/lib/hecks/fuzzing/mutation/checks.rb +76 -0
  340. data/lib/hecks/fuzzing/mutation/finders.rb +136 -0
  341. data/lib/hecks/fuzzing/mutation/judge.rb +94 -0
  342. data/lib/hecks/fuzzing/mutation/observation.rb +38 -0
  343. data/lib/hecks/fuzzing/mutation/operators.rb +52 -0
  344. data/lib/hecks/fuzzing/mutation/report.rb +78 -0
  345. data/lib/hecks/fuzzing/mutation/run.rb +99 -0
  346. data/lib/hecks/fuzzing/mutation/selection.rb +32 -0
  347. data/lib/hecks/fuzzing/mutation/site.rb +21 -0
  348. data/lib/hecks/fuzzing/mutation/source_map.rb +59 -0
  349. data/lib/hecks/fuzzing/mutation.rb +12 -0
  350. data/lib/hecks/fuzzing/persistence_parity.rb +5 -5
  351. data/lib/hecks/fuzzing/properties/aggregation_recompute.rb +121 -0
  352. data/lib/hecks/fuzzing/properties/catalog.rb +89 -0
  353. data/lib/hecks/fuzzing/properties/corrections.rb +23 -20
  354. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +64 -185
  355. data/lib/hecks/fuzzing/properties/group_by_recompute.rb +69 -0
  356. data/lib/hecks/fuzzing/properties/guaranteed_by_construction.rb +63 -0
  357. data/lib/hecks/fuzzing/properties/guards.rb +76 -108
  358. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +66 -227
  359. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +46 -35
  360. data/lib/hecks/fuzzing/properties/mutation_recompute.rb +162 -0
  361. data/lib/hecks/fuzzing/properties/outbox.rb +41 -24
  362. data/lib/hecks/fuzzing/properties/piece_invariants.rb +61 -0
  363. data/lib/hecks/fuzzing/properties/policy_wiring.rb +140 -0
  364. data/lib/hecks/fuzzing/properties/query_rows.rb +67 -0
  365. data/lib/hecks/fuzzing/properties/querying.rb +69 -90
  366. data/lib/hecks/fuzzing/properties/read_model_names.rb +50 -0
  367. data/lib/hecks/fuzzing/properties/read_models.rb +138 -0
  368. data/lib/hecks/fuzzing/properties/references.rb +100 -0
  369. data/lib/hecks/fuzzing/properties/role_checks.rb +50 -0
  370. data/lib/hecks/fuzzing/properties/tenant_scope.rb +84 -0
  371. data/lib/hecks/fuzzing/properties.rb +13 -119
  372. data/lib/hecks/fuzzing/qa_settings.rb +23 -17
  373. data/lib/hecks/fuzzing/replay/fan_out.rb +78 -0
  374. data/lib/hecks/fuzzing/replay/filters.rb +72 -0
  375. data/lib/hecks/fuzzing/replay/guard_check.rb +88 -0
  376. data/lib/hecks/fuzzing/replay/mutation_trace.rb +117 -0
  377. data/lib/hecks/fuzzing/replay/observation.rb +60 -0
  378. data/lib/hecks/fuzzing/replay/read_only_steps.rb +84 -0
  379. data/lib/hecks/fuzzing/replay/role_check.rb +49 -0
  380. data/lib/hecks/fuzzing/replay/session.rb +167 -0
  381. data/lib/hecks/fuzzing/replay.rb +36 -442
  382. data/lib/hecks/fuzzing/runtime_coverage.rb +70 -0
  383. data/lib/hecks/fuzzing/rust_gap_manifest.rb +3 -4
  384. data/lib/hecks/fuzzing/self_consistency/saga_redelivery.rb +133 -0
  385. data/lib/hecks/fuzzing/self_consistency/sagas.rb +93 -0
  386. data/lib/hecks/fuzzing/self_consistency/value_objects.rb +87 -0
  387. data/lib/hecks/fuzzing/self_consistency.rb +8 -213
  388. data/lib/hecks/fuzzing/sequence_generator/adversary/argument_mutations.rb +116 -0
  389. data/lib/hecks/fuzzing/sequence_generator/adversary/caller_draw.rb +68 -0
  390. data/lib/hecks/fuzzing/sequence_generator/adversary/identity_mutations.rb +62 -0
  391. data/lib/hecks/fuzzing/sequence_generator/adversary/precedence_mutations.rb +126 -0
  392. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +23 -283
  393. data/lib/hecks/fuzzing/sequence_generator/argument_drawing.rb +78 -0
  394. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +69 -53
  395. data/lib/hecks/fuzzing/sequence_generator/identity_shaping.rb +85 -0
  396. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +20 -16
  397. data/lib/hecks/fuzzing/sequence_generator/picker.rb +12 -6
  398. data/lib/hecks/fuzzing/sequence_generator/prefixing.rb +45 -0
  399. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +19 -8
  400. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +43 -144
  401. data/lib/hecks/fuzzing/sequence_generator.rb +65 -63
  402. data/lib/hecks/fuzzing/shrinker/value_simplification.rb +64 -0
  403. data/lib/hecks/fuzzing/shrinker.rb +36 -29
  404. data/lib/hecks/fuzzing/target_capabilities.rb +10 -4
  405. data/lib/hecks/fuzzing/value_generator.rb +27 -17
  406. data/lib/hecks/fuzzing.rb +3 -0
  407. data/lib/hecks/gate/stages.yml +11 -1
  408. data/lib/hecks/grammar/evolve/arguments.rb +90 -0
  409. data/lib/hecks/grammar/evolve/keywords.rb +81 -0
  410. data/lib/hecks/grammar/evolve/seeds.rb +172 -0
  411. data/lib/hecks/grammar/evolve.rb +22 -263
  412. data/lib/hecks/grammar/operators.rb +111 -0
  413. data/lib/hecks/grammar.rb +53 -126
  414. data/lib/hecks/hecks/adapters/bluebook_report.rb +6 -6
  415. data/lib/hecks/hecks/adapters/codebase/codemods.rb +1 -1
  416. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +23 -9
  417. data/lib/hecks/hecks/adapters/codebase/language/edits.rb +75 -0
  418. data/lib/hecks/hecks/adapters/codebase/language.rb +30 -72
  419. data/lib/hecks/hecks/adapters/codebase/promotion/candidates.rb +54 -0
  420. data/lib/hecks/hecks/adapters/codebase/promotion/gate.rb +50 -0
  421. data/lib/hecks/hecks/adapters/codebase/promotion/move.rb +70 -0
  422. data/lib/hecks/hecks/adapters/codebase/promotion/standing.rb +88 -0
  423. data/lib/hecks/hecks/adapters/codebase/promotion/watch.rb +83 -0
  424. data/lib/hecks/hecks/adapters/codebase/promotion.rb +115 -0
  425. data/lib/hecks/hecks/adapters/codebase/publishing.rb +31 -12
  426. data/lib/hecks/hecks/adapters/codebase/regeneration.rb +43 -6
  427. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +16 -5
  428. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +9 -1
  429. data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +1 -1
  430. data/lib/hecks/hecks/adapters/codebase/style.rb +1 -1
  431. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +11 -5
  432. data/lib/hecks/hecks/adapters/codebase/test_suite.rb +27 -8
  433. data/lib/hecks/hecks/adapters/console_capture.rb +21 -17
  434. data/lib/hecks/hecks/adapters/cost_explorer.rb +11 -6
  435. data/lib/hecks/hecks/adapters/deploy_plans.rb +3 -3
  436. data/lib/hecks/hecks/adapters/deploy_toolchain/answers.rb +142 -0
  437. data/lib/hecks/hecks/adapters/deploy_toolchain/scripts.rb +95 -0
  438. data/lib/hecks/hecks/adapters/deploy_toolchain/statuses.rb +74 -0
  439. data/lib/hecks/hecks/adapters/deploy_toolchain.rb +21 -239
  440. data/lib/hecks/hecks/adapters/finding_github.rb +2 -2
  441. data/lib/hecks/hecks/adapters/first_admin.rb +22 -8
  442. data/lib/hecks/hecks/adapters/git.rb +18 -5
  443. data/lib/hecks/hecks/adapters/git_refs.rb +144 -0
  444. data/lib/hecks/hecks/adapters/github_rulesets.rb +128 -0
  445. data/lib/hecks/hecks/adapters/host_http.rb +16 -6
  446. data/lib/hecks/hecks/adapters/in_process_boot.rb +9 -5
  447. data/lib/hecks/hecks/adapters/in_process_operations/tailing.rb +61 -0
  448. data/lib/hecks/hecks/adapters/in_process_operations.rb +33 -35
  449. data/lib/hecks/hecks/adapters/journal_store/changes.rb +21 -15
  450. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +29 -12
  451. data/lib/hecks/hecks/adapters/journal_store/readings/attestation.rb +52 -0
  452. data/lib/hecks/hecks/adapters/journal_store/readings/scaffolding.rb +52 -0
  453. data/lib/hecks/hecks/adapters/journal_store/readings.rb +5 -62
  454. data/lib/hecks/hecks/adapters/local_files.rb +27 -10
  455. data/lib/hecks/hecks/adapters/pg_admin/ownership.rb +115 -0
  456. data/lib/hecks/hecks/adapters/pg_admin.rb +14 -87
  457. data/lib/hecks/hecks/adapters/process_pool.rb +75 -21
  458. data/lib/hecks/hecks/adapters/rust_toolchain.rb +12 -4
  459. data/lib/hecks/hecks/adapters/site_toolchain.rb +16 -7
  460. data/lib/hecks/hecks/adapters/terminal.rb +13 -9
  461. data/lib/hecks/hecks/codebase.bluebook +322 -5
  462. data/lib/hecks/hecks/custodian.behaviors +6 -0
  463. data/lib/hecks/hecks/custodian.bluebook +37 -0
  464. data/lib/hecks/hecks/hecks.hecksagon +22 -0
  465. data/lib/hecks/hecks/hecks.world +10 -2
  466. data/lib/hecks/kernel_capabilities/templates.rb +92 -0
  467. data/lib/hecks/kernel_capabilities.rb +18 -85
  468. data/lib/hecks/language/bluebook/vocabulary.bluebook +46 -1
  469. data/lib/hecks/literal/item_splitter.rb +50 -0
  470. data/lib/hecks/literal.rb +29 -38
  471. data/lib/hecks/mcp_stdio_guard.rb +8 -8
  472. data/lib/hecks/naming.rb +9 -3
  473. data/lib/hecks/persistence_legacy_fixture/postgres_stores.rb +81 -0
  474. data/lib/hecks/persistence_legacy_fixture/regenerate.rb +26 -66
  475. data/lib/hecks/persistence_legacy_fixture.rb +13 -10
  476. data/lib/hecks/ports/access_control.rb +13 -10
  477. data/lib/hecks/ports/agent/answers.rb +2 -2
  478. data/lib/hecks/ports/agent.rb +13 -10
  479. data/lib/hecks/ports/authentication.rb +13 -10
  480. data/lib/hecks/ports/authorization.rb +13 -10
  481. data/lib/hecks/ports/clock.rb +13 -10
  482. data/lib/hecks/ports/extraction.rb +13 -12
  483. data/lib/hecks/ports/identity_assignment.rb +13 -10
  484. data/lib/hecks/ports/identity_generation.rb +13 -10
  485. data/lib/hecks/ports/identity_resolution.rb +13 -10
  486. data/lib/hecks/ports/key_vault.rb +13 -10
  487. data/lib/hecks/ports/persistence/append_only.rb +5 -5
  488. data/lib/hecks/ports/persistence/binding_policy.rb +33 -9
  489. data/lib/hecks/ports/persistence/codec_boundary.rb +22 -11
  490. data/lib/hecks/ports/persistence/constants.rb +10 -0
  491. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +18 -16
  492. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +27 -18
  493. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +52 -23
  494. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +14 -8
  495. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +17 -6
  496. data/lib/hecks/ports/persistence/plugins/era/lineage/coverage.rb +58 -0
  497. data/lib/hecks/ports/persistence/plugins/era/lineage/rewrite.rb +130 -0
  498. data/lib/hecks/ports/persistence/plugins/era/lineage/rules.rb +25 -0
  499. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +20 -180
  500. data/lib/hecks/ports/persistence/plugins/era/postgres_era/boot.rb +41 -0
  501. data/lib/hecks/ports/persistence/plugins/era/postgres_era/class_methods.rb +105 -0
  502. data/lib/hecks/ports/persistence/plugins/era/postgres_era/dialect.rb +137 -0
  503. data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +25 -28
  504. data/lib/hecks/ports/persistence/plugins/era/postgres_era/head_writes.rb +62 -0
  505. data/lib/hecks/ports/persistence/plugins/era/postgres_era/journal.rb +128 -0
  506. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/base_sql.rb +74 -0
  507. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/chain_sql.rb +169 -0
  508. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/domain_rename.rb +91 -0
  509. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_integrity.rb +99 -0
  510. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +0 -73
  511. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +55 -39
  512. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +51 -222
  513. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/merge_writes.rb +120 -0
  514. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +85 -60
  515. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +97 -181
  516. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +19 -19
  517. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/sql_templates.rb +88 -0
  518. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +77 -118
  519. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +3 -117
  520. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_sql.rb +116 -0
  521. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +3 -1
  522. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/context.rb +38 -0
  523. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +43 -25
  524. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +62 -38
  525. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +21 -16
  526. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +66 -86
  527. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/refusals.rb +75 -0
  528. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +27 -9
  529. data/lib/hecks/ports/persistence/plugins/era/postgres_era/query_phases.rb +63 -0
  530. data/lib/hecks/ports/persistence/plugins/era/postgres_era/sagas.rb +78 -0
  531. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +28 -482
  532. data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +40 -12
  533. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +22 -15
  534. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +39 -19
  535. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -16
  536. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +48 -25
  537. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +60 -99
  538. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/path_diff.rb +57 -0
  539. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +21 -11
  540. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +13 -4
  541. data/lib/hecks/ports/persistence/postgres_dump/connection.rb +4 -2
  542. data/lib/hecks/ports/persistence/postgres_dump.rb +13 -7
  543. data/lib/hecks/ports/persistence/repository_factory.rb +35 -11
  544. data/lib/hecks/ports/persistence/state_codec.rb +10 -0
  545. data/lib/hecks/ports/persistence.rb +1 -10
  546. data/lib/hecks/ports/projection.rb +34 -21
  547. data/lib/hecks/ports/query/in_memory.rb +16 -8
  548. data/lib/hecks/projection_files/expression_tables.rb +64 -0
  549. data/lib/hecks/projection_files/texts.rb +67 -0
  550. data/lib/hecks/projection_files.rb +19 -103
  551. data/lib/hecks/projections/bootstrap_table.rb +43 -29
  552. data/lib/hecks/projections/deploy/bastion_lines.rb +32 -0
  553. data/lib/hecks/projections/deploy/box/access.rb +73 -0
  554. data/lib/hecks/projections/deploy/box/caddy.rb +87 -0
  555. data/lib/hecks/projections/deploy/box/compose.rb +70 -0
  556. data/lib/hecks/projections/deploy/box/hosting.rb +4 -105
  557. data/lib/hecks/projections/deploy/box/hosting_parts.rb +97 -0
  558. data/lib/hecks/projections/deploy/box/hosting_settings.rb +1 -1
  559. data/lib/hecks/projections/deploy/box/roll_recipe.rb +1 -1
  560. data/lib/hecks/projections/deploy/box/roll_scripts.rb +137 -0
  561. data/lib/hecks/projections/deploy/box/settings/checks.rb +38 -0
  562. data/lib/hecks/projections/deploy/box/settings/containers.rb +123 -0
  563. data/lib/hecks/projections/deploy/box/settings/origin.rb +56 -0
  564. data/lib/hecks/projections/deploy/box/settings/patterns.rb +47 -0
  565. data/lib/hecks/projections/deploy/box/settings/types.rb +76 -0
  566. data/lib/hecks/projections/deploy/box/settings.rb +76 -263
  567. data/lib/hecks/projections/deploy/box/shared_database.rb +69 -0
  568. data/lib/hecks/projections/deploy/box/stack_yaml.rb +107 -0
  569. data/lib/hecks/projections/deploy/box/templates/MIGRATION.md.tmpl +39 -0
  570. data/lib/hecks/projections/deploy/box/templates/Makefile.tmpl +23 -0
  571. data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +42 -2
  572. data/lib/hecks/projections/deploy/box/templates/deploy-service.services-roll.part +2 -1
  573. data/lib/hecks/projections/deploy/box/templates/deploy-service.taskdef-roll.part +2 -1
  574. data/lib/hecks/projections/deploy/box/templates/deploy-usage-services.tmpl +4 -0
  575. data/lib/hecks/projections/deploy/box/templates/deploy-usage-taskdef.tmpl +5 -0
  576. data/lib/hecks/projections/deploy/box/templates/ecr-repository.yaml.tmpl +9 -0
  577. data/lib/hecks/projections/deploy/box/templates/mode-summary-services.tmpl +2 -0
  578. data/lib/hecks/projections/deploy/box/templates/mode-summary-taskdef.tmpl +4 -0
  579. data/lib/hecks/projections/deploy/box/templates/provision-database.sh.tmpl +97 -0
  580. data/lib/hecks/projections/deploy/box/templates/restore-to-rds.sh.tmpl +4 -2
  581. data/lib/hecks/projections/deploy/box/templates/services-block.tmpl +9 -0
  582. data/lib/hecks/projections/deploy/box/templates/tunnel-egress.yaml.tmpl +11 -0
  583. data/lib/hecks/projections/deploy/box/templates/verify-copy.sh.tmpl +2 -1
  584. data/lib/hecks/projections/deploy/box/templates/writable-secrets.yaml.tmpl +7 -0
  585. data/lib/hecks/projections/deploy/box.rb +43 -491
  586. data/lib/hecks/projections/deploy/fargate/assembly.rb +13 -142
  587. data/lib/hecks/projections/deploy/fargate/cdn/behaviors.rb +76 -0
  588. data/lib/hecks/projections/deploy/fargate/cdn/lines.rb +112 -0
  589. data/lib/hecks/projections/deploy/fargate/cdn/options.rb +85 -0
  590. data/lib/hecks/projections/deploy/fargate/cdn.rb +23 -215
  591. data/lib/hecks/projections/deploy/fargate/check.rb +16 -6
  592. data/lib/hecks/projections/deploy/fargate/containers/definition_lines.rb +61 -0
  593. data/lib/hecks/projections/deploy/fargate/containers/reading.rb +86 -0
  594. data/lib/hecks/projections/deploy/fargate/containers/rendering.rb +132 -0
  595. data/lib/hecks/projections/deploy/fargate/containers/routing.rb +93 -0
  596. data/lib/hecks/projections/deploy/fargate/containers.rb +10 -286
  597. data/lib/hecks/projections/deploy/fargate/extras/reading.rb +90 -0
  598. data/lib/hecks/projections/deploy/fargate/extras/rendering.rb +81 -0
  599. data/lib/hecks/projections/deploy/fargate/extras.rb +9 -158
  600. data/lib/hecks/projections/deploy/fargate/monitoring/alarms.rb +115 -0
  601. data/lib/hecks/projections/deploy/fargate/monitoring/reading.rb +84 -0
  602. data/lib/hecks/projections/deploy/fargate/monitoring/topic.rb +59 -0
  603. data/lib/hecks/projections/deploy/fargate/monitoring/warmer.rb +90 -0
  604. data/lib/hecks/projections/deploy/fargate/monitoring/warmer_roles.rb +76 -0
  605. data/lib/hecks/projections/deploy/fargate/monitoring.rb +14 -348
  606. data/lib/hecks/projections/deploy/fargate/sections.rb +115 -0
  607. data/lib/hecks/projections/deploy/fargate/settings/ids.rb +55 -0
  608. data/lib/hecks/projections/deploy/fargate/settings/tuning.rb +77 -0
  609. data/lib/hecks/projections/deploy/fargate/settings.rb +17 -104
  610. data/lib/hecks/projections/deploy/fargate/stack/blocks.rb +91 -0
  611. data/lib/hecks/projections/deploy/fargate/stack/readers.rb +87 -0
  612. data/lib/hecks/projections/deploy/fargate/stack/recipes.rb +106 -0
  613. data/lib/hecks/projections/deploy/fargate/stack.rb +146 -0
  614. data/lib/hecks/projections/deploy/fargate/task_sections.rb +56 -0
  615. data/lib/hecks/projections/deploy/fargate/yaml.rb +1 -1
  616. data/lib/hecks/projections/deploy/fargate.rb +51 -756
  617. data/lib/hecks/projections/deploy/lambda/pii.rb +49 -0
  618. data/lib/hecks/projections/deploy/lambda/stack/blocks.rb +118 -0
  619. data/lib/hecks/projections/deploy/lambda/stack/checks.rb +64 -0
  620. data/lib/hecks/projections/deploy/lambda/stack/deploy_chain.rb +119 -0
  621. data/lib/hecks/projections/deploy/lambda/stack/readers.rb +62 -0
  622. data/lib/hecks/projections/deploy/lambda/stack/reading.rb +170 -0
  623. data/lib/hecks/projections/deploy/lambda/stack/reading_web.rb +53 -0
  624. data/lib/hecks/projections/deploy/lambda/stack/recipes.rb +112 -0
  625. data/lib/hecks/projections/deploy/lambda/stack/web.rb +57 -0
  626. data/lib/hecks/projections/deploy/lambda/stack.rb +54 -0
  627. data/lib/hecks/projections/deploy/lambda.rb +77 -1885
  628. data/lib/hecks/projections/deploy/preview/access_yaml.rb +8 -74
  629. data/lib/hecks/projections/deploy/preview/containers.rb +18 -7
  630. data/lib/hecks/projections/deploy/preview/routing_yaml.rb +15 -87
  631. data/lib/hecks/projections/deploy/preview/settings.rb +7 -4
  632. data/lib/hecks/projections/deploy/preview/task_yaml.rb +42 -106
  633. data/lib/hecks/projections/deploy/preview/template.rb +11 -106
  634. data/lib/hecks/projections/deploy/preview/yaml_text.rb +1 -1
  635. data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +1 -1
  636. data/lib/hecks/projections/deploy/scripts/settings.rb +14 -6
  637. data/lib/hecks/projections/deploy/scripts.rb +11 -9
  638. data/lib/hecks/projections/deploy/shared/rows.rb +48 -0
  639. data/lib/hecks/projections/deploy/shared.rb +89 -449
  640. data/lib/hecks/projections/deploy/shared_database_instance/templates/Makefile.tmpl +11 -0
  641. data/lib/hecks/projections/deploy/shared_database_instance/templates/README.md.tmpl +25 -0
  642. data/lib/hecks/projections/deploy/shared_database_instance/templates/rds.yaml.tmpl +180 -0
  643. data/lib/hecks/projections/deploy/shared_database_instance.rb +106 -0
  644. data/lib/hecks/projections/deploy/smoke.rb +15 -10
  645. data/lib/hecks/projections/deploy/template_diff/comparer.rb +21 -147
  646. data/lib/hecks/projections/deploy/template_diff/normalizer.rb +60 -0
  647. data/lib/hecks/projections/deploy/template_diff/value_diff.rb +136 -0
  648. data/lib/hecks/projections/deploy/template_diff.rb +8 -3
  649. data/lib/hecks/projections/deploy/templates/fargate/Dockerfile.tmpl +28 -0
  650. data/lib/hecks/projections/deploy/templates/fargate/Makefile.tmpl +63 -0
  651. data/lib/hecks/projections/deploy/templates/fargate/always_params.tmpl +4 -0
  652. data/lib/hecks/projections/deploy/templates/fargate/deploy_plain.tmpl +1 -0
  653. data/lib/hecks/projections/deploy/templates/fargate/deploy_shared.tmpl +11 -0
  654. data/lib/hecks/projections/deploy/templates/fargate/mint_era_own.tmpl +44 -0
  655. data/lib/hecks/projections/deploy/templates/fargate/mint_era_shared.tmpl +8 -0
  656. data/lib/hecks/projections/deploy/templates/fargate/missing_owner.tmpl +9 -0
  657. data/lib/hecks/projections/deploy/templates/fargate/oauth_params.tmpl +7 -0
  658. data/lib/hecks/projections/deploy/templates/fargate/oauth_task_env.tmpl +4 -0
  659. data/lib/hecks/projections/deploy/templates/fargate/oauth_task_policy.tmpl +7 -0
  660. data/lib/hecks/projections/deploy/templates/fargate/owning_params.tmpl +33 -0
  661. data/lib/hecks/projections/deploy/templates/fargate/template.yaml.tmpl +281 -0
  662. data/lib/hecks/projections/deploy/templates/lambda/Makefile.tmpl +218 -0
  663. data/lib/hecks/projections/deploy/templates/lambda/aurora_depends.tmpl +18 -0
  664. data/lib/hecks/projections/deploy/templates/lambda/build_dispatch_none.tmpl +10 -0
  665. data/lib/hecks/projections/deploy/templates/lambda/build_pg.tmpl +15 -0
  666. data/lib/hecks/projections/deploy/templates/lambda/build_plain.tmpl +2 -0
  667. data/lib/hecks/projections/deploy/templates/lambda/build_web.tmpl +11 -0
  668. data/lib/hecks/projections/deploy/templates/lambda/env_blind_guard.tmpl +4 -0
  669. data/lib/hecks/projections/deploy/templates/lambda/mint_era_own.tmpl +122 -0
  670. data/lib/hecks/projections/deploy/templates/lambda/mint_era_shared.tmpl +47 -0
  671. data/lib/hecks/projections/deploy/templates/lambda/missing_owner.tmpl +9 -0
  672. data/lib/hecks/projections/deploy/templates/lambda/nat_comment_oauth.tmpl +14 -0
  673. data/lib/hecks/projections/deploy/templates/lambda/nat_comment_plain.tmpl +3 -0
  674. data/lib/hecks/projections/deploy/templates/lambda/oauth_note.tmpl +8 -0
  675. data/lib/hecks/projections/deploy/templates/lambda/params_oauth.tmpl +13 -0
  676. data/lib/hecks/projections/deploy/templates/lambda/params_shared.tmpl +33 -0
  677. data/lib/hecks/projections/deploy/templates/lambda/pg_native.tmpl +71 -0
  678. data/lib/hecks/projections/deploy/templates/lambda/pii_oac.tmpl +8 -0
  679. data/lib/hecks/projections/deploy/templates/lambda/pii_permission.tmpl +8 -0
  680. data/lib/hecks/projections/deploy/templates/lambda/pii_resources.tmpl +116 -0
  681. data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge.tmpl +30 -0
  682. data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge_oauth.tmpl +12 -0
  683. data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge_plain.tmpl +7 -0
  684. data/lib/hecks/projections/deploy/templates/lambda/rename_schema_own.tmpl +93 -0
  685. data/lib/hecks/projections/deploy/templates/lambda/rename_schema_shared.tmpl +7 -0
  686. data/lib/hecks/projections/deploy/templates/lambda/rust_oauth_env.tmpl +17 -0
  687. data/lib/hecks/projections/deploy/templates/lambda/rust_oauth_policy.tmpl +16 -0
  688. data/lib/hecks/projections/deploy/templates/lambda/rust_session_secret.tmpl +13 -0
  689. data/lib/hecks/projections/deploy/templates/lambda/samconfig.toml.tmpl +12 -0
  690. data/lib/hecks/projections/deploy/templates/lambda/shared_note.tmpl +6 -0
  691. data/lib/hecks/projections/deploy/templates/lambda/sync_oauth.tmpl +23 -0
  692. data/lib/hecks/projections/deploy/templates/lambda/template.yaml.tmpl +187 -0
  693. data/lib/hecks/projections/deploy/templates/lambda/translation_own.tmpl +46 -0
  694. data/lib/hecks/projections/deploy/templates/lambda/translation_shared.tmpl +2 -0
  695. data/lib/hecks/projections/deploy/templates/lambda/web_function.tmpl +207 -0
  696. data/lib/hecks/projections/deploy/templates/lambda/web_google_oauth_env.tmpl +12 -0
  697. data/lib/hecks/projections/deploy/templates/lambda/web_no_oauth_env.tmpl +7 -0
  698. data/lib/hecks/projections/deploy/templates/lambda/web_oauth_policy.tmpl +4 -0
  699. data/lib/hecks/projections/deploy/templates/lambda/webhook_secret_resource.tmpl +20 -0
  700. data/lib/hecks/projections/deploy/templates/preview/alb.tmpl +8 -0
  701. data/lib/hecks/projections/deploy/templates/preview/alb_security_group.tmpl +11 -0
  702. data/lib/hecks/projections/deploy/templates/preview/assume_role.tmpl +6 -0
  703. data/lib/hecks/projections/deploy/templates/preview/base_parameters.tmpl +24 -0
  704. data/lib/hecks/projections/deploy/templates/preview/cluster.tmpl +4 -0
  705. data/lib/hecks/projections/deploy/templates/preview/container_secret.tmpl +9 -0
  706. data/lib/hecks/projections/deploy/templates/preview/db_init_script.sh.tmpl +23 -0
  707. data/lib/hecks/projections/deploy/templates/preview/db_init_secrets.tmpl +5 -0
  708. data/lib/hecks/projections/deploy/templates/preview/db_init_task.tmpl +39 -0
  709. data/lib/hecks/projections/deploy/templates/preview/desired_count.tmpl +5 -0
  710. data/lib/hecks/projections/deploy/templates/preview/distribution.tmpl +24 -0
  711. data/lib/hecks/projections/deploy/templates/preview/execution_role.tmpl +16 -0
  712. data/lib/hecks/projections/deploy/templates/preview/header.tmpl +16 -0
  713. data/lib/hecks/projections/deploy/templates/preview/ingress.tmpl +8 -0
  714. data/lib/hecks/projections/deploy/templates/preview/listener.tmpl +9 -0
  715. data/lib/hecks/projections/deploy/templates/preview/listener_rule.tmpl +11 -0
  716. data/lib/hecks/projections/deploy/templates/preview/log_group.tmpl +5 -0
  717. data/lib/hecks/projections/deploy/templates/preview/log_options.tmpl +5 -0
  718. data/lib/hecks/projections/deploy/templates/preview/outputs.tmpl +14 -0
  719. data/lib/hecks/projections/deploy/templates/preview/service.tmpl +17 -0
  720. data/lib/hecks/projections/deploy/templates/preview/session_secret.tmpl +11 -0
  721. data/lib/hecks/projections/deploy/templates/preview/target_group.tmpl +9 -0
  722. data/lib/hecks/projections/deploy/templates/preview/task_definition.tmpl +15 -0
  723. data/lib/hecks/projections/deploy/templates/preview/task_role.tmpl +22 -0
  724. data/lib/hecks/projections/deploy/templates/shared/aurora_db.tmpl +52 -0
  725. data/lib/hecks/projections/deploy/templates/shared/bastion.tmpl +74 -0
  726. data/lib/hecks/projections/deploy/templates/shared/bastion_own_public.tmpl +41 -0
  727. data/lib/hecks/projections/deploy/templates/shared/bastion_reuse_public.tmpl +10 -0
  728. data/lib/hecks/projections/deploy/templates/shared/nat_gateway.tmpl +102 -0
  729. data/lib/hecks/projections/deploy/templates/shared/oauth_egress.tmpl +17 -0
  730. data/lib/hecks/projections/deploy/templates/shared/plain_db.tmpl +16 -0
  731. data/lib/hecks/projections/deploy/templates/shared/vpc_and_database.tmpl +67 -0
  732. data/lib/hecks/projections/deploy/text_template.rb +35 -0
  733. data/lib/hecks/projections/deploy/vercel/settings.rb +83 -0
  734. data/lib/hecks/projections/deploy/vercel.rb +134 -0
  735. data/lib/hecks/projections/diagrams/dispatch.rb +114 -0
  736. data/lib/hecks/projections/diagrams/statecharts.rb +59 -0
  737. data/lib/hecks/projections/diagrams/structure.rb +114 -0
  738. data/lib/hecks/projections/diagrams.rb +33 -256
  739. data/lib/hecks/projections/glossary/entries.rb +140 -0
  740. data/lib/hecks/projections/glossary/html/page.rb +96 -0
  741. data/lib/hecks/projections/glossary/html/parser.rb +66 -0
  742. data/lib/hecks/projections/glossary/html/sections.rb +78 -0
  743. data/lib/hecks/projections/glossary/html.rb +7 -179
  744. data/lib/hecks/projections/glossary/index.rb +45 -0
  745. data/lib/hecks/projections/glossary/markdown.rb +22 -11
  746. data/lib/hecks/projections/glossary/mermaid.rb +44 -31
  747. data/lib/hecks/projections/glossary/sensitivity.rb +7 -4
  748. data/lib/hecks/projections/glossary/sentences/value_objects.rb +77 -0
  749. data/lib/hecks/projections/glossary/sentences.rb +42 -81
  750. data/lib/hecks/projections/glossary/slugs.rb +33 -0
  751. data/lib/hecks/projections/glossary.rb +22 -190
  752. data/lib/hecks/projections/model.rb +20 -14
  753. data/lib/hecks/projections/rust_vocabulary/arguments/support.rb +33 -0
  754. data/lib/hecks/projections/rust_vocabulary/arguments.rb +171 -0
  755. data/lib/hecks/projections/rust_vocabulary/enum_body.rb +114 -0
  756. data/lib/hecks/projections/rust_vocabulary/tests.rb +144 -0
  757. data/lib/hecks/projections/rust_vocabulary.rb +24 -293
  758. data/lib/hecks/projections/site/admin.rb +15 -9
  759. data/lib/hecks/projections/site/admin_cms/templates/membership.rb +115 -0
  760. data/lib/hecks/projections/site/admin_cms/templates/session_strategy.rb +90 -0
  761. data/lib/hecks/projections/site/admin_cms/templates/sso.rb +101 -0
  762. data/lib/hecks/projections/site/admin_cms/templates/sso_tail.rb +54 -0
  763. data/lib/hecks/projections/site/admin_cms/templates/users.rb +83 -0
  764. data/lib/hecks/projections/site/admin_cms/templates.rb +14 -369
  765. data/lib/hecks/projections/site/admin_cms.rb +15 -9
  766. data/lib/hecks/projections/site/edge/behaviours.rb +10 -6
  767. data/lib/hecks/projections/site/edge/checks.rb +30 -80
  768. data/lib/hecks/projections/site/edge/findings.rb +28 -0
  769. data/lib/hecks/projections/site/edge/route_checks.rb +110 -0
  770. data/lib/hecks/projections/site/edge/row_reader.rb +52 -0
  771. data/lib/hecks/projections/site/edge/rules.rb +28 -26
  772. data/lib/hecks/projections/site/edge.rb +20 -31
  773. data/lib/hecks/projections/site/live_edge.rb +9 -7
  774. data/lib/hecks/projections/site/payload/fields/definitions.rb +90 -0
  775. data/lib/hecks/projections/site/payload/fields/readers.rb +69 -0
  776. data/lib/hecks/projections/site/payload/fields.rb +14 -111
  777. data/lib/hecks/projections/site/payload/lifecycle/text.rb +84 -0
  778. data/lib/hecks/projections/site/payload/lifecycle/text_tail.rb +106 -0
  779. data/lib/hecks/projections/site/payload/lifecycle.rb +8 -166
  780. data/lib/hecks/projections/site/payload/model.rb +22 -22
  781. data/lib/hecks/projections/site/payload/specs/wire.rb +69 -0
  782. data/lib/hecks/projections/site/payload/specs.rb +24 -68
  783. data/lib/hecks/projections/site/payload_driver.rb +19 -17
  784. data/lib/hecks/projections/site/root_rows.rb +12 -4
  785. data/lib/hecks/projections/site/routes_ts/helpers.rb +79 -0
  786. data/lib/hecks/projections/site/routes_ts/listings.rb +75 -0
  787. data/lib/hecks/projections/site/routes_ts/navigation.rb +79 -0
  788. data/lib/hecks/projections/site/routes_ts.rb +27 -175
  789. data/lib/hecks/projections/site/site_admin/access.rb +104 -0
  790. data/lib/hecks/projections/site/site_admin/session.rb +127 -0
  791. data/lib/hecks/projections/site/site_admin.rb +12 -219
  792. data/lib/hecks/projections/site/site_cdn.rb +12 -7
  793. data/lib/hecks/projections/site/site_host/dockerfile.rb +75 -0
  794. data/lib/hecks/projections/site/site_host/templates.rb +19 -67
  795. data/lib/hecks/projections/site/site_root/workflow.rb +65 -0
  796. data/lib/hecks/projections/site/site_root.rb +3 -54
  797. data/lib/hecks/projections/site/table/checks.rb +28 -57
  798. data/lib/hecks/projections/site/table/link_builder.rb +14 -5
  799. data/lib/hecks/projections/site/table/navigation_checks.rb +75 -0
  800. data/lib/hecks/projections/site/table/row_builder.rb +31 -53
  801. data/lib/hecks/projections/site/table/row_defaults.rb +65 -0
  802. data/lib/hecks/projections/site/table.rb +9 -5
  803. data/lib/hecks/projections/vocabulary.rb +34 -31
  804. data/lib/hecks/projections.rb +2 -0
  805. data/lib/hecks/projector/cli_audience.rb +42 -0
  806. data/lib/hecks/projector/cli_projector/claims.rb +149 -0
  807. data/lib/hecks/projector/cli_projector/command_help.rb +65 -0
  808. data/lib/hecks/projector/cli_projector/command_specs.rb +133 -0
  809. data/lib/hecks/projector/cli_projector/listing.rb +100 -0
  810. data/lib/hecks/projector/cli_projector/option_specs.rb +116 -0
  811. data/lib/hecks/projector/cli_projector/query_specs.rb +67 -0
  812. data/lib/hecks/projector/cli_projector/usage.rb +101 -0
  813. data/lib/hecks/projector/cli_projector.rb +15 -532
  814. data/lib/hecks/projector/docs_projector/attributes.rb +78 -0
  815. data/lib/hecks/projector/docs_projector/behaviour.rb +127 -0
  816. data/lib/hecks/projector/docs_projector/closing.rb +40 -0
  817. data/lib/hecks/projector/docs_projector.rb +58 -192
  818. data/lib/hecks/projector/exporter/bindings.rb +174 -0
  819. data/lib/hecks/projector/exporter/translations.rb +127 -0
  820. data/lib/hecks/projector/exporter.rb +8 -279
  821. data/lib/hecks/projector/narrate_projector/commands.rb +108 -0
  822. data/lib/hecks/projector/narrate_projector/reactions.rb +33 -0
  823. data/lib/hecks/projector/narrate_projector.rb +60 -160
  824. data/lib/hecks/projector.rb +22 -13
  825. data/lib/hecks/quality_control/adapters/agent_profile.rb +25 -16
  826. data/lib/hecks/quality_control/adapters/github_checks.rb +49 -6
  827. data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +1 -1
  828. data/lib/hecks/quality_control/adapters/github_issues.rb +22 -10
  829. data/lib/hecks/quality_control/cli/qa_discover_external_domains/parsing.rb +54 -0
  830. data/lib/hecks/quality_control/cli/qa_discover_external_domains/reporting.rb +44 -0
  831. data/lib/hecks/quality_control/cli/qa_discover_external_domains/scanning.rb +119 -0
  832. data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +28 -155
  833. data/lib/hecks/quality_control/cli/qa_domain_novelty/verdict.rb +76 -0
  834. data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +33 -66
  835. data/lib/hecks/quality_control/cli/qa_generated_domains/arguments.rb +62 -0
  836. data/lib/hecks/quality_control/cli/qa_generated_domains/blueprints.rb +45 -0
  837. data/lib/hecks/quality_control/cli/qa_generated_domains/evaluation.rb +107 -0
  838. data/lib/hecks/quality_control/cli/qa_generated_domains/promotion.rb +107 -0
  839. data/lib/hecks/quality_control/cli/qa_generated_domains/reporting.rb +97 -0
  840. data/lib/hecks/quality_control/cli/qa_generated_domains/shrinking.rb +70 -0
  841. data/lib/hecks/quality_control/cli/qa_generated_domains.rb +43 -327
  842. data/lib/hecks/quality_control/cli/qa_log_bug/arguments.rb +55 -0
  843. data/lib/hecks/quality_control/cli/qa_log_bug/proof.rb +65 -0
  844. data/lib/hecks/quality_control/cli/qa_log_bug.rb +18 -81
  845. data/lib/hecks/quality_control/cli/qa_mine_combinations/arguments.rb +54 -0
  846. data/lib/hecks/quality_control/cli/qa_mine_combinations/booting.rb +96 -0
  847. data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +45 -109
  848. data/lib/hecks/quality_control/cli/qa_open_pr/arguments.rb +55 -0
  849. data/lib/hecks/quality_control/cli/qa_open_pr/recording.rb +79 -0
  850. data/lib/hecks/quality_control/cli/qa_open_pr/rules.rb +122 -0
  851. data/lib/hecks/quality_control/cli/qa_open_pr.rb +41 -200
  852. data/lib/hecks/quality_control/cli/qa_postgres_migrate/copying.rb +45 -0
  853. data/lib/hecks/quality_control/cli/qa_postgres_migrate/reporting.rb +33 -0
  854. data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +37 -63
  855. data/lib/hecks/quality_control/cli/qa_postgres_role/ownership.rb +57 -0
  856. data/lib/hecks/quality_control/cli/qa_postgres_role.rb +66 -71
  857. data/lib/hecks/quality_control/cli/qa_pr_check/checking.rb +118 -0
  858. data/lib/hecks/quality_control/cli/qa_pr_check/reporting.rb +54 -0
  859. data/lib/hecks/quality_control/cli/qa_pr_check.rb +28 -145
  860. data/lib/hecks/quality_control/cli/qa_seed_angles/seed.rb +80 -0
  861. data/lib/hecks/quality_control/cli/qa_seed_angles.rb +13 -86
  862. data/lib/hecks/quality_control/cli/qa_sweep/all_mode/children.rb +80 -0
  863. data/lib/hecks/quality_control/cli/qa_sweep/all_mode/report.rb +125 -0
  864. data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +63 -193
  865. data/lib/hecks/quality_control/cli/qa_sweep/checks/boundary.rb +92 -0
  866. data/lib/hecks/quality_control/cli/qa_sweep/checks/engines.rb +92 -0
  867. data/lib/hecks/quality_control/cli/qa_sweep/checks/seeds.rb +86 -0
  868. data/lib/hecks/quality_control/cli/qa_sweep/checks/shrinking.rb +69 -0
  869. data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +10 -248
  870. data/lib/hecks/quality_control/cli/qa_sweep/conclusion.rb +60 -0
  871. data/lib/hecks/quality_control/cli/qa_sweep/depth.rb +61 -0
  872. data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +27 -13
  873. data/lib/hecks/quality_control/cli/qa_sweep/finding_report/shrunk.rb +42 -0
  874. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +40 -41
  875. data/lib/hecks/quality_control/cli/qa_sweep/parsing/validation.rb +70 -0
  876. data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +35 -65
  877. data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +41 -22
  878. data/lib/hecks/quality_control/cli/qa_sweep/scratch.rb +67 -0
  879. data/lib/hecks/quality_control/cli/qa_sweep/seat.rb +94 -0
  880. data/lib/hecks/quality_control/cli/qa_sweep/seed_loop.rb +157 -0
  881. data/lib/hecks/quality_control/cli/qa_sweep/target_setup.rb +115 -0
  882. data/lib/hecks/quality_control/cli/qa_sweep.rb +22 -445
  883. data/lib/hecks/quality_control/cli/qa_tick/output.rb +107 -0
  884. data/lib/hecks/quality_control/cli/qa_tick/preflight.rb +95 -0
  885. data/lib/hecks/quality_control/cli/qa_tick.rb +42 -175
  886. data/lib/hecks/query_ir/formatting.rb +86 -0
  887. data/lib/hecks/query_ir/rules.rb +132 -0
  888. data/lib/hecks/query_ir/touchpoints.rb +104 -0
  889. data/lib/hecks/query_ir.rb +33 -281
  890. data/lib/hecks/query_ir_mcp/tools.rb +68 -0
  891. data/lib/hecks/query_ir_mcp.rb +27 -71
  892. data/lib/hecks/query_specification/common/comparison.rb +25 -5
  893. data/lib/hecks/query_specification/common/dsl.rb +1 -1
  894. data/lib/hecks/query_specification/common/null_policy.rb +9 -6
  895. data/lib/hecks/query_specification/common/options.rb +21 -14
  896. data/lib/hecks/query_specification/field_path.rb +5 -2
  897. data/lib/hecks/query_specification/hop_path.rb +15 -18
  898. data/lib/hecks/release/lane.rb +22 -0
  899. data/lib/hecks/release/runner/clean_tree.rb +2 -2
  900. data/lib/hecks/release/runner/commands.rb +1 -1
  901. data/lib/hecks/release/runner/options.rb +82 -0
  902. data/lib/hecks/release/runner/preflight.rb +12 -7
  903. data/lib/hecks/release/runner/publishing.rb +86 -0
  904. data/lib/hecks/release/runner/tagger.rb +8 -3
  905. data/lib/hecks/release/runner.rb +40 -156
  906. data/lib/hecks/rendering.rb +13 -9
  907. data/lib/hecks/router/door.rb +37 -0
  908. data/lib/hecks/router/namespace_installer.rb +45 -83
  909. data/lib/hecks/router/options_proxy.rb +44 -0
  910. data/lib/hecks/runtime/adapter_lookup.rb +45 -24
  911. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -8
  912. data/lib/hecks/runtime/command_interpreter/delegation.rb +116 -0
  913. data/lib/hecks/runtime/command_interpreter/enforcement.rb +38 -0
  914. data/lib/hecks/runtime/command_interpreter/hydration.rb +139 -0
  915. data/lib/hecks/runtime/command_interpreter/list_mutations.rb +98 -0
  916. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +67 -114
  917. data/lib/hecks/runtime/command_interpreter/persisting.rb +96 -0
  918. data/lib/hecks/runtime/command_interpreter.rb +57 -352
  919. data/lib/hecks/runtime/command_rules/admissibility.rb +64 -147
  920. data/lib/hecks/runtime/command_rules/arithmetic.rb +13 -72
  921. data/lib/hecks/runtime/command_rules/authorization.rb +9 -9
  922. data/lib/hecks/runtime/command_rules/emission.rb +13 -14
  923. data/lib/hecks/runtime/command_rules/guard_state.rb +49 -0
  924. data/lib/hecks/runtime/command_rules/invariants.rb +84 -0
  925. data/lib/hecks/runtime/command_rules/operands.rb +88 -0
  926. data/lib/hecks/runtime/command_rules/references.rb +59 -57
  927. data/lib/hecks/runtime/command_rules/tenant_boundary.rb +69 -0
  928. data/lib/hecks/runtime/dependency_planning/analyzer.rb +90 -0
  929. data/lib/hecks/runtime/dependency_planning/expression_reads.rb +73 -0
  930. data/lib/hecks/runtime/dependency_planning/mutation_analysis.rb +89 -0
  931. data/lib/hecks/runtime/dependency_planning/rule_analysis.rb +82 -0
  932. data/lib/hecks/runtime/dependency_planning.rb +3 -250
  933. data/lib/hecks/runtime/dispatcher/queries.rb +62 -0
  934. data/lib/hecks/runtime/dispatcher/result.rb +55 -0
  935. data/lib/hecks/runtime/dispatcher/routing.rb +107 -0
  936. data/lib/hecks/runtime/dispatcher.rb +64 -209
  937. data/lib/hecks/runtime/entity_element/location.rb +124 -0
  938. data/lib/hecks/runtime/entity_element/mutations.rb +150 -0
  939. data/lib/hecks/runtime/entity_element.rb +5 -177
  940. data/lib/hecks/runtime/entity_interpreter/enforcement.rb +51 -0
  941. data/lib/hecks/runtime/entity_interpreter/locating.rb +62 -0
  942. data/lib/hecks/runtime/entity_interpreter/resolution.rb +42 -0
  943. data/lib/hecks/runtime/entity_interpreter/saving.rb +49 -0
  944. data/lib/hecks/runtime/entity_interpreter.rb +45 -164
  945. data/lib/hecks/runtime/identity.rb +15 -9
  946. data/lib/hecks/runtime/instance.rb +11 -7
  947. data/lib/hecks/runtime/interpreting.rb +16 -8
  948. data/lib/hecks/runtime/invocation.rb +3 -155
  949. data/lib/hecks/runtime/invocation_builder.rb +132 -0
  950. data/lib/hecks/runtime/invocation_facts.rb +87 -0
  951. data/lib/hecks/runtime/loader/boot_steps.rb +96 -0
  952. data/lib/hecks/runtime/loader/described.rb +27 -0
  953. data/lib/hecks/runtime/loader.rb +27 -114
  954. data/lib/hecks/runtime/outbox/consumer_runner.rb +40 -0
  955. data/lib/hecks/runtime/outbox/fanout.rb +82 -0
  956. data/lib/hecks/runtime/outbox/relay.rb +149 -0
  957. data/lib/hecks/runtime/outbox.rb +3 -214
  958. data/lib/hecks/runtime/policy_interpreter/arguments.rb +67 -0
  959. data/lib/hecks/runtime/policy_interpreter/fan_out.rb +96 -0
  960. data/lib/hecks/runtime/policy_interpreter.rb +22 -137
  961. data/lib/hecks/runtime/port_operation_interpreter.rb +18 -17
  962. data/lib/hecks/runtime/query_interpreter/arguments.rb +51 -0
  963. data/lib/hecks/runtime/query_interpreter/entity_rows.rb +82 -0
  964. data/lib/hecks/runtime/query_interpreter/outside_answer.rb +89 -0
  965. data/lib/hecks/runtime/query_interpreter.rb +43 -191
  966. data/lib/hecks/runtime/reaction_invocation/identities.rb +92 -0
  967. data/lib/hecks/runtime/reaction_invocation/target_resolution.rb +88 -0
  968. data/lib/hecks/runtime/reaction_invocation.rb +66 -183
  969. data/lib/hecks/runtime/reaction_outcome.rb +7 -3
  970. data/lib/hecks/runtime/read_model_interpreter/head_ordering.rb +49 -0
  971. data/lib/hecks/runtime/read_model_interpreter/reductions.rb +123 -0
  972. data/lib/hecks/runtime/read_model_interpreter/shaping.rb +100 -0
  973. data/lib/hecks/runtime/read_model_interpreter.rb +71 -214
  974. data/lib/hecks/runtime/reference_hop.rb +11 -11
  975. data/lib/hecks/runtime/refusal_wording.rb +11 -8
  976. data/lib/hecks/runtime/registry/chapter_verification.rb +84 -0
  977. data/lib/hecks/runtime/registry/declarations.rb +17 -0
  978. data/lib/hecks/runtime/registry/durability_warnings.rb +71 -0
  979. data/lib/hecks/runtime/registry/hecksagon_rules.rb +124 -0
  980. data/lib/hecks/runtime/registry/merging.rb +49 -0
  981. data/lib/hecks/runtime/registry/providers.rb +139 -0
  982. data/lib/hecks/runtime/registry/query_verification.rb +144 -0
  983. data/lib/hecks/runtime/registry/read_repository.rb +61 -0
  984. data/lib/hecks/runtime/registry/runtime_state.rb +27 -0
  985. data/lib/hecks/runtime/registry/saga_persistence.rb +12 -8
  986. data/lib/hecks/runtime/registry/verification.rb +45 -389
  987. data/lib/hecks/runtime/registry/world_defaults.rb +3 -3
  988. data/lib/hecks/runtime/registry.rb +58 -296
  989. data/lib/hecks/runtime/remote_dispatcher.rb +47 -31
  990. data/lib/hecks/runtime/saga_interpreter/compensation.rb +90 -0
  991. data/lib/hecks/runtime/saga_interpreter/correlation.rb +19 -10
  992. data/lib/hecks/runtime/saga_interpreter/delivery.rb +147 -0
  993. data/lib/hecks/runtime/saga_interpreter/lifecycle.rb +63 -0
  994. data/lib/hecks/runtime/saga_interpreter/transitions.rb +112 -0
  995. data/lib/hecks/runtime/saga_interpreter.rb +41 -320
  996. data/lib/hecks/runtime/tenant_check.rb +14 -9
  997. data/lib/hecks/runtime/value/admission.rb +28 -19
  998. data/lib/hecks/runtime/value/coercion.rb +55 -404
  999. data/lib/hecks/runtime/value/entity_list_coercion.rb +27 -29
  1000. data/lib/hecks/runtime/value/field_checks.rb +57 -100
  1001. data/lib/hecks/runtime/value/flags.rb +65 -0
  1002. data/lib/hecks/runtime/value/identifiers.rb +64 -0
  1003. data/lib/hecks/runtime/value/references.rb +195 -0
  1004. data/lib/hecks/runtime/value/shape_checks.rb +61 -0
  1005. data/lib/hecks/runtime/value/validation.rb +125 -0
  1006. data/lib/hecks/runtime/value.rb +18 -6
  1007. data/lib/hecks/rust_build/conformance/surface.rb +75 -0
  1008. data/lib/hecks/rust_build/conformance.rb +27 -59
  1009. data/lib/hecks/rust_build/conformance_fuzz.rb +26 -15
  1010. data/lib/hecks/rust_build/coverage.rb +32 -104
  1011. data/lib/hecks/rust_build/coverage_parts/expected.rb +68 -0
  1012. data/lib/hecks/rust_build/coverage_parts/printer.rb +75 -0
  1013. data/lib/hecks/rust_build/host.rb +23 -13
  1014. data/lib/hecks/rust_build/kernel_input.rb +19 -12
  1015. data/lib/hecks/rust_build/native_build.rb +48 -16
  1016. data/lib/hecks/rust_build/project_rust/domain_loader.rb +75 -0
  1017. data/lib/hecks/rust_build/project_rust/root_mod/notes.rb +66 -0
  1018. data/lib/hecks/rust_build/project_rust/root_mod.rb +22 -55
  1019. data/lib/hecks/rust_build/project_rust/target_ir.rb +74 -0
  1020. data/lib/hecks/rust_build/project_rust.rb +21 -89
  1021. data/lib/hecks/rust_build/wasm.rb +27 -7
  1022. data/lib/hecks/rust_build/wasm_browser.rb +7 -7
  1023. data/lib/hecks/rust_build/write_if_changed.rb +3 -6
  1024. data/lib/hecks/rust_build.rb +7 -3
  1025. data/lib/hecks/storehouse/audit.rb +106 -0
  1026. data/lib/hecks/storehouse/callers.rb +73 -0
  1027. data/lib/hecks/storehouse/dispatching.rb +149 -0
  1028. data/lib/hecks/storehouse/introspection.rb +145 -0
  1029. data/lib/hecks/storehouse/querying.rb +78 -0
  1030. data/lib/hecks/storehouse.rb +43 -451
  1031. data/lib/hecks/tickets/bluebook/tickets.bluebook +29 -0
  1032. data/lib/hecks/tools/argument_gate_matrix/dispatching.rb +69 -0
  1033. data/lib/hecks/tools/argument_gate_matrix/rows.rb +121 -0
  1034. data/lib/hecks/tools/argument_gate_matrix/violations.rb +108 -0
  1035. data/lib/hecks/tools/argument_gate_matrix.rb +43 -212
  1036. data/lib/hecks/tools/ci_gate_decision.rb +21 -14
  1037. data/lib/hecks/tools/ci_gates.rb +40 -26
  1038. data/lib/hecks/tools/comment_style/baseline.rb +41 -0
  1039. data/lib/hecks/tools/comment_style/caps_words.rb +104 -0
  1040. data/lib/hecks/tools/comment_style/cli.rb +121 -0
  1041. data/lib/hecks/tools/comment_style/dictionary.rb +60 -0
  1042. data/lib/hecks/tools/comment_style/fixing.rb +119 -0
  1043. data/lib/hecks/tools/comment_style/long_blocks.rb +51 -0
  1044. data/lib/hecks/tools/comment_style/masking.rb +94 -0
  1045. data/lib/hecks/tools/comment_style/patterns.rb +61 -0
  1046. data/lib/hecks/tools/comment_style/run.rb +161 -0
  1047. data/lib/hecks/tools/comment_style/signature.rb +59 -0
  1048. data/lib/hecks/tools/comment_style/source_file.rb +105 -0
  1049. data/lib/hecks/tools/comment_style/structure_checks.rb +113 -0
  1050. data/lib/hecks/tools/comment_style/text_checks.rb +67 -0
  1051. data/lib/hecks/tools/comment_style/vocabulary.rb +55 -0
  1052. data/lib/hecks/tools/comment_style/walker.rb +136 -0
  1053. data/lib/hecks/tools/comment_style.rb +17 -1000
  1054. data/lib/hecks/tools/corpus_report.rb +26 -16
  1055. data/lib/hecks/tools/deploy_recipe/generation.rb +59 -0
  1056. data/lib/hecks/tools/deploy_recipe/targets.rb +115 -0
  1057. data/lib/hecks/tools/deploy_recipe/worlds.rb +115 -0
  1058. data/lib/hecks/tools/deploy_recipe.rb +72 -176
  1059. data/lib/hecks/tools/deploy_recipe_lint/checks.rb +78 -0
  1060. data/lib/hecks/tools/deploy_recipe_lint/fixtures.rb +88 -0
  1061. data/lib/hecks/tools/deploy_recipe_lint/makefile.rb +84 -0
  1062. data/lib/hecks/tools/deploy_recipe_lint.rb +29 -192
  1063. data/lib/hecks/tools/drop_implicit_append_fields.rb +20 -12
  1064. data/lib/hecks/tools/era_projection_backfill.rb +50 -33
  1065. data/lib/hecks/tools/era_reattest/reporting.rb +55 -0
  1066. data/lib/hecks/tools/era_reattest.rb +32 -43
  1067. data/lib/hecks/tools/evolve_run/arguments.rb +49 -0
  1068. data/lib/hecks/tools/evolve_run/words.rb +60 -0
  1069. data/lib/hecks/tools/evolve_run.rb +43 -90
  1070. data/lib/hecks/tools/fuzz_sweep/findings.rb +106 -0
  1071. data/lib/hecks/tools/fuzz_sweep/options.rb +80 -0
  1072. data/lib/hecks/tools/fuzz_sweep/pool.rb +74 -0
  1073. data/lib/hecks/tools/fuzz_sweep/reporting.rb +110 -0
  1074. data/lib/hecks/tools/fuzz_sweep.rb +91 -272
  1075. data/lib/hecks/tools/gate.rb +31 -16
  1076. data/lib/hecks/tools/heki_compaction.rb +63 -42
  1077. data/lib/hecks/tools/hoist_local_givens/rewriting.rb +119 -0
  1078. data/lib/hecks/tools/hoist_local_givens.rb +89 -157
  1079. data/lib/hecks/tools/journal_compaction.rb +40 -31
  1080. data/lib/hecks/tools/lanes/files.rb +80 -0
  1081. data/lib/hecks/tools/lanes/live.rb +40 -0
  1082. data/lib/hecks/tools/lanes/rows.rb +45 -0
  1083. data/lib/hecks/tools/lanes/ruleset.rb +66 -0
  1084. data/lib/hecks/tools/lanes/watch_workflow.rb +82 -0
  1085. data/lib/hecks/tools/lanes/workflow.rb +79 -0
  1086. data/lib/hecks/tools/lanes.rb +82 -0
  1087. data/lib/hecks/tools/mutation_run.rb +73 -0
  1088. data/lib/hecks/tools/oidc_manifests.rb +10 -9
  1089. data/lib/hecks/tools/query_ir_run.rb +7 -3
  1090. data/lib/hecks/tools/regeneration_run.rb +40 -26
  1091. data/lib/hecks/tools/rust_comment_style/caps_words.rb +98 -0
  1092. data/lib/hecks/tools/rust_comment_style/fixing.rb +102 -0
  1093. data/lib/hecks/tools/rust_comment_style/masking.rb +85 -0
  1094. data/lib/hecks/tools/rust_comment_style/run.rb +94 -0
  1095. data/lib/hecks/tools/rust_comment_style/source_file.rb +71 -0
  1096. data/lib/hecks/tools/rust_comment_style/structure.rb +79 -0
  1097. data/lib/hecks/tools/rust_comment_style/text_checks.rb +63 -0
  1098. data/lib/hecks/tools/rust_comment_style/tokenizer.rb +102 -0
  1099. data/lib/hecks/tools/rust_comment_style.rb +38 -535
  1100. data/lib/hecks/tools/sequence_script.rb +20 -14
  1101. data/lib/hecks/tools/site_routes/cli.rb +70 -0
  1102. data/lib/hecks/tools/site_routes/root_files.rb +59 -0
  1103. data/lib/hecks/tools/site_routes/templates.rb +77 -0
  1104. data/lib/hecks/tools/site_routes.rb +84 -160
  1105. data/lib/hecks/tools/tail_merge.rb +45 -37
  1106. data/lib/hecks/tools/tenant_provisioning.rb +45 -31
  1107. data/lib/hecks/tools/tools_doc.rb +42 -19
  1108. data/lib/hecks/tools/translation_audit/domain_loading.rb +71 -0
  1109. data/lib/hecks/tools/translation_audit/edges.rb +71 -0
  1110. data/lib/hecks/tools/translation_audit/verdicts.rb +107 -0
  1111. data/lib/hecks/tools/translation_audit.rb +30 -161
  1112. data/lib/hecks/tools/translation_scaffold/reporting.rb +40 -0
  1113. data/lib/hecks/tools/translation_scaffold.rb +77 -60
  1114. data/lib/hecks/tools.rb +2 -0
  1115. data/lib/hecks/vendoring.rb +37 -11
  1116. data/lib/hecks/version.rb +1 -1
  1117. data/lib/hecks/vocabulary.rb +18 -1
  1118. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +7 -9
  1119. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +8 -6
  1120. data/prebuilt/945481eefbdb584649d45f256307053558966a868b9c38dee7ee88f8169610f8.marshal +0 -0
  1121. data/prebuilt/a0818e2de67364dc1ab22868b6cbf869c62da6f8d9b924c778fa5cce2e76ee94.marshal +0 -0
  1122. data/prebuilt/verdicts-be73f0df9eee0abe2f4aadc968321c4b919d19d424a3ccfe1777a71dabf7d9e7.json +1 -0
  1123. data/qa/settings.yml +1 -0
  1124. data/rust/.cargo/mutants.toml +8 -0
  1125. data/rust/host/Cargo.toml +5 -0
  1126. data/rust/host/HECKS_RELEASE +1 -1
  1127. data/rust/host/src/api.rs +28 -5
  1128. data/rust/host/src/auth.rs +43 -1
  1129. data/rust/host/src/boundary_fuzz/api.rs +260 -0
  1130. data/rust/host/src/boundary_fuzz/auth.rs +119 -0
  1131. data/rust/host/src/boundary_fuzz/expr_json.rs +158 -0
  1132. data/rust/host/src/boundary_fuzz/ir.rs +78 -0
  1133. data/rust/host/src/boundary_fuzz/server.rs +227 -0
  1134. data/rust/host/src/boundary_fuzz/web.rs +125 -0
  1135. data/rust/host/src/fuzz_support.rs +165 -0
  1136. data/rust/host/src/ir.rs +4 -0
  1137. data/rust/host/src/main.rs +9 -4
  1138. data/rust/host/src/secrets.rs +44 -0
  1139. data/rust/host/src/server.rs +6 -1
  1140. data/rust/host/src/web.rs +14 -5
  1141. data/rust/parser/fuzz/.gitignore +4 -0
  1142. data/rust/parser/fuzz/Cargo.lock +89 -0
  1143. data/rust/parser/fuzz/Cargo.toml +27 -0
  1144. data/rust/parser/fuzz/README.md +19 -0
  1145. data/rust/parser/fuzz/fuzz_targets/chapter.rs +50 -0
  1146. data/rust/parser/fuzz/fuzz_targets/resolve.rs +35 -0
  1147. data/rust/parser/src/parse/command.rs +14 -2
  1148. data/rust/parser/src/parse/mod.rs +25 -0
  1149. data/rust/parser/src/ruby_value.rs +95 -6
  1150. data/rust/src/kernel/dispatch.rs +4 -0
  1151. data/rust/src/kernel/dispatch_guard_tests.rs +506 -0
  1152. data/rust/src/kernel/json.rs +34 -3
  1153. data/rust/src/kernel/orchestrate.rs +4 -0
  1154. data/rust/src/kernel/orchestrate_guard_tests.rs +708 -0
  1155. metadata +640 -3
  1156. /data/lib/hecks/bluebook/behaviour/{hexagon.rb → hecksagon.rb} +0 -0
@@ -26,11 +26,10 @@ module Hecks
26
26
  @max_prefix_depth = max_prefix_depth
27
27
  @corpus = []
28
28
  @seen = Set.new
29
+ @runtime_seen = Set.new
29
30
  @verb_hits = Hash.new(0)
30
31
  @declared_verbs = Set.new
31
- @seeds = 0
32
- @spliced = 0
33
- @seeds_with_new = 0
32
+ @seeds = @spliced = @seeds_with_new = 0
34
33
  end
35
34
 
36
35
  # Builds this seed's plan: a possible corpus splice, plus the verbs to favor.
@@ -40,42 +39,44 @@ module Hecks
40
39
  def plan(seed)
41
40
  random = Random.new(seed)
42
41
  prefix = nil
43
- if !@corpus.empty? && random.rand < @splice_probability
44
- entry = @corpus[random.rand(@corpus.size)]
45
- prefix = entry[:spec].merge("steps" => random.rand(1..entry[:attempts]))
46
- end
42
+ prefix = splice_prefix(random) if !@corpus.empty? && random.rand < @splice_probability
47
43
  Plan.new(prefix: prefix, favor: rare_verbs)
48
44
  end
49
45
 
50
46
  # Folds one seed's trace into the running coverage; admits a corpus entry if it reached
51
- # a new tuple.
47
+ # a new tuple, or, when `runtime` is given, a new runtime line or branch.
52
48
  #
53
49
  # @param seed [Integer] the seed the trace was generated from
54
50
  # @param plan [Fuzzing::CoverageCampaign::Plan] the plan that seed ran with
55
51
  # @param trace [Fuzzing::SequenceGenerator::Trace] from `SequenceGenerator.trace`
52
+ # @param runtime [Enumerable<String>, nil] keys from `RuntimeCoverage.measure`; nil when
53
+ # runtime feedback is off, which leaves admission to tuples alone
56
54
  # @return [void]
57
- def record(seed, plan, trace)
58
- @seeds += 1
59
- @spliced += 1 if plan.spliced?
60
- @declared_verbs.merge(trace.verbs)
61
-
62
- new_at = trace.coverage.filter_map do |index, tuple|
63
- @verb_hits[tuple.split(" | ").first] += 1
64
- index if @seen.add?(tuple)
65
- end
66
- return if new_at.empty?
55
+ def record(seed, plan, trace, runtime: nil)
56
+ tally(plan, trace)
57
+ new_at = new_tuple_steps(trace)
58
+ fresh_runtime = new_runtime?(runtime)
59
+ return if new_at.empty? && !fresh_runtime
67
60
 
68
61
  @seeds_with_new += 1
69
- admit(seed, plan, new_at.max + 1)
62
+ # A tuple cuts the entry at the step that reached it; a runtime key is not tied to a step,
63
+ # so a seed that reached only new runtime keeps its whole sequence.
64
+ admit(seed, plan, new_at.empty? ? [trace.steps.size, 1].max : new_at.max + 1)
70
65
  end
71
66
 
67
+ # The number of distinct runtime lines and branches reached so far; zero while runtime
68
+ # feedback is off.
69
+ def runtime_seen = @runtime_seen.size
70
+
72
71
  # The number of distinct coverage tuples reached so far.
73
72
  def tuples_seen = @seen.size
74
73
 
75
74
  # One line of running totals: tuples seen, seeds run, seeds with new coverage, splices.
76
75
  def summary
77
- "coverage: #{@seen.size} distinct (verb, kind, state, mutation, outcome) tuple(s) over #{@seeds} seed(s); " \
78
- "#{@seeds_with_new} seed(s) reached something new; #{@spliced} spliced from a corpus of #{@corpus.size}"
76
+ runtime = @runtime_seen.empty? ? "" : " and #{@runtime_seen.size} runtime line/branch key(s)"
77
+ "coverage: #{@seen.size} distinct (verb, kind, state, mutation, outcome) tuple(s)#{runtime} over " \
78
+ "#{@seeds} seed(s); #{@seeds_with_new} seed(s) reached something new; " \
79
+ "#{@spliced} spliced from a corpus of #{@corpus.size}"
79
80
  end
80
81
 
81
82
  # Serializes the accumulated corpus and coverage knowledge, JSON-safe, so a later process can
@@ -83,10 +84,12 @@ module Hecks
83
84
  # favor count, corpus and prefix-depth bounds — are configuration a caller supplies fresh each
84
85
  # time, not state, so they are not part of this.
85
86
  #
86
- # @return [Hash] with string keys "corpus", "seen", "verb_hits", "declared_verbs"
87
+ # @return [Hash] with string keys "corpus", "seen", "runtime_seen", "verb_hits" and
88
+ # "declared_verbs"
87
89
  def to_h
88
90
  { "corpus" => @corpus.map { |entry| { "spec" => entry[:spec], "attempts" => entry[:attempts] } },
89
91
  "seen" => @seen.to_a,
92
+ "runtime_seen" => @runtime_seen.to_a.sort,
90
93
  "verb_hits" => @verb_hits.dup,
91
94
  "declared_verbs" => @declared_verbs.to_a }
92
95
  end
@@ -99,9 +102,8 @@ module Hecks
99
102
  def restore!(state)
100
103
  state = state.transform_keys(&:to_s)
101
104
  @corpus = Array(state["corpus"]).map { |entry| { spec: entry["spec"], attempts: entry["attempts"] } }
102
- @seen = Set.new(Array(state["seen"]))
105
+ @seen, @runtime_seen, @declared_verbs = %w[seen runtime_seen declared_verbs].map { |key| Set.new(Array(state[key])) }
103
106
  @verb_hits = Hash.new(0).merge(state["verb_hits"] || {})
104
- @declared_verbs = Set.new(Array(state["declared_verbs"]))
105
107
  end
106
108
 
107
109
  # Builds a campaign that already knows what a prior campaign's `#to_h` reached, configured
@@ -121,6 +123,29 @@ module Hecks
121
123
 
122
124
  private
123
125
 
126
+ def tally(plan, trace)
127
+ @seeds += 1
128
+ @spliced += 1 if plan.spliced?
129
+ @declared_verbs.merge(trace.verbs)
130
+ end
131
+
132
+ # The step indexes whose tuples nothing had reached before; each tuple's verb counts as a hit.
133
+ def new_tuple_steps(trace)
134
+ trace.coverage.filter_map do |index, tuple|
135
+ @verb_hits[tuple.split(" | ").first] += 1
136
+ index if @seen.add?(tuple)
137
+ end
138
+ end
139
+
140
+ def new_runtime?(runtime)
141
+ runtime.to_a.map { |key| @runtime_seen.add?(key) }.any?
142
+ end
143
+
144
+ def splice_prefix(random)
145
+ entry = @corpus[random.rand(@corpus.size)]
146
+ entry[:spec].merge("steps" => random.rand(1..entry[:attempts]))
147
+ end
148
+
124
149
  def admit(seed, plan, attempts)
125
150
  return if depth(plan.prefix) + 1 > @max_prefix_depth
126
151
 
@@ -0,0 +1,74 @@
1
+ require "json"
2
+ require_relative "../nondeterministic"
3
+ require_relative "../rust_gap_manifest"
4
+
5
+ module Hecks
6
+ module Fuzzing
7
+ module Differential
8
+ # Puts a Ruby replay and a Rust binary's output into the same wire shapes and lists the
9
+ # fields on which they disagree, after dropping what the binary's gap manifest tolerates.
10
+ module WireComparison
11
+ module_function
12
+
13
+ # Round-trips `value` through JSON so it compares as plain wire data.
14
+ def jsonify(value) = JSON.parse(JSON.generate(value))
15
+
16
+ # Ruby's result in the wire shapes the Rust output is compared against.
17
+ def ruby_view(ruby_result)
18
+ { instances: jsonify(ruby_result[:instances]), events: jsonify(ruby_result[:events]),
19
+ refusals: refusal_rows(ruby_result[:refusals]),
20
+ queries: jsonify(ruby_result[:queries].map { |row| Nondeterministic.strip(row, :query_row) }),
21
+ sagas: jsonify(ruby_result[:sagas]),
22
+ dry_runs: dry_run_rows(ruby_result[:dry_runs]) }
23
+ end
24
+
25
+ def dry_run_rows(dry_runs) = dry_runs.map { |d| { "verb" => d[:verb].to_s, "ok" => d[:ok] } }
26
+
27
+ def refusal_rows(refusals)
28
+ refusals.map { |r| { "verb" => r[:verb].to_s, "kind" => r[:kind].to_s.split("::").last, "error" => r[:error] } }
29
+ end
30
+
31
+ # One `{field:, ruby:, rust:}` entry per wire field on which the two engines disagree.
32
+ def differential_divergences(differ, ruby_result, rust_output, binary)
33
+ view = ruby_view(ruby_result)
34
+ kept = Differential.manifest_partition(RustGapManifest.for_binary(binary),
35
+ ruby_refusals: view[:refusals], rust_refusals: rust_output["refusals"],
36
+ ruby_queries: view[:queries], rust_queries: rust_output["queries"])
37
+ differ.structural_skips.merge(kept[:skipped])
38
+ plain_divergences(view, rust_output) + kept[:stale] + kept_divergences(differ, ruby_result, view, rust_output, kept)
39
+ end
40
+
41
+ def plain_divergences(view, rust_output)
42
+ [compare("instances", view[:instances], rust_output["instances"]),
43
+ compare("events", view[:events], rust_output["events"])].compact
44
+ end
45
+
46
+ def kept_divergences(differ, ruby_result, view, rust_output, kept)
47
+ [compare("refusals", *kind_rows(kept)),
48
+ compare("queries", *wire_queries(differ, kept)),
49
+ compare("sagas", view[:sagas], rust_output["sagas"]),
50
+ compare("reactions", *reactions(differ, ruby_result, rust_output)),
51
+ compare("dry_runs", view[:dry_runs], Array(rust_output["dry_runs"]).map { |d| d.slice("verb", "ok") })].compact
52
+ end
53
+
54
+ def kind_rows(kept)
55
+ by_kind = ->(row) { row.slice("verb", "kind") }
56
+ [kept[:ruby_refusals].map(&by_kind), kept[:rust_refusals].map(&by_kind)]
57
+ end
58
+
59
+ def wire_queries(differ, kept)
60
+ wordless = ->(row) { differ.reduce_to_wire_precision(row.except("error", "reference_error")) }
61
+ [kept[:ruby_queries].map(&wordless), kept[:rust_queries].map(&wordless)]
62
+ end
63
+
64
+ def reactions(differ, ruby_result, rust_output)
65
+ cross_domain = differ.cross_domain_policy_names(rust_output)
66
+ [jsonify(ruby_result[:reactions]).reject { |r| cross_domain.include?(r["policy"]) },
67
+ rust_output.fetch("reactions")]
68
+ end
69
+
70
+ def compare(field, ruby, rust) = ruby == rust ? nil : { field: field, ruby: ruby, rust: rust }
71
+ end
72
+ end
73
+ end
74
+ end
@@ -6,6 +6,7 @@ require_relative "self_consistency"
6
6
  require_relative "rust_gap_manifest"
7
7
  require_relative "../rust_build/kernel_input"
8
8
  require_relative "nondeterministic"
9
+ require_relative "differential/wire_comparison"
9
10
 
10
11
  module Hecks
11
12
  module Fuzzing
@@ -30,18 +31,26 @@ module Hecks
30
31
  # @return [Hash] the four row lists with tolerated verbs removed, `skipped:` (a
31
32
  # `Set<String>` of tolerated verbs reached) and `stale:` (`Array<Hash>` divergences)
32
33
  def manifest_partition(gaps, ruby_refusals:, rust_refusals:, ruby_queries:, rust_queries:)
33
- verb_of = ->(row) { row.key?("verb") ? row["verb"] : row["query"] }
34
- declared = ->(row) { gaps.not_generated?(verb_of.call(row)) }
35
- stale = rust_queries.select(&declared).map do |row|
34
+ declared = ->(row) { gaps.not_generated?(wire_verb(row)) }
35
+ lists = { ruby_refusals: ruby_refusals, rust_refusals: rust_refusals,
36
+ ruby_queries: ruby_queries, rust_queries: rust_queries }
37
+ reached = (ruby_refusals + rust_refusals + ruby_queries).select(&declared)
38
+ lists.transform_values { |rows| rows.reject(&declared) }
39
+ .merge(skipped: reached.to_set { |row| wire_verb(row) },
40
+ stale: stale_rows(gaps, rust_queries.select(&declared)))
41
+ end
42
+
43
+ # The verb a refusal row names, or the query a query row names.
44
+ def wire_verb(row) = row.key?("verb") ? row["verb"] : row["query"]
45
+
46
+ # One divergence per tolerated query the Rust binary answered anyway.
47
+ def stale_rows(gaps, answered)
48
+ answered.map do |row|
36
49
  { field: "manifest", verb: row["query"],
37
- detail: "#{row['query']} is declared generated: false in manifest.json " \
38
- "(#{gaps.not_generated(row['query']).values_at('gap_class', 'construct').join('/')}), " \
50
+ detail: "#{row["query"]} is declared generated: false in manifest.json " \
51
+ "(#{gaps.not_generated(row["query"]).values_at("gap_class", "construct").join("/")}), " \
39
52
  "but the Rust binary answered it — regenerate with hecks project_rust" }
40
53
  end
41
- reached = (ruby_refusals + rust_refusals + ruby_queries).select(&declared)
42
- { ruby_refusals: ruby_refusals.reject(&declared), rust_refusals: rust_refusals.reject(&declared),
43
- ruby_queries: ruby_queries.reject(&declared), rust_queries: rust_queries.reject(&declared),
44
- skipped: reached.to_set(&verb_of), stale: stale }
45
54
  end
46
55
 
47
56
  # Runs the standard property battery on a replayed history.
@@ -63,95 +72,61 @@ module Hecks
63
72
  history[:self_consistency].values.flatten(1)
64
73
  end
65
74
 
66
- # rubocop:disable-next Metrics/AbcSize
67
- # rubocop:disable-next Metrics/CyclomaticComplexity
68
- # rubocop:disable-next Metrics/PerceivedComplexity
69
- # rubocop:disable-next Metrics/MethodLength
70
75
  # @param differ [Object] duck-typed `RustConformanceHelpers` interface
71
76
  # @param domain_path [String] the domain directory to replay
72
77
  # @param steps [Array<Hash>] the step sequence replayed on both engines
73
78
  # @param binary [String] the compiled Rust conformance binary
74
- # @param modes [Array<Symbol>] `:differential` (always run), `:self_consistency`,
75
- # `:properties_in_differential`, `:adapter_parity_sqlite`
76
- # @param adapter_parity_sqlite [Proc, nil] the caller's comparison; `nil` skips the mode
79
+ # @param options [Hash] `modes:` (required), an Array of Symbols: `:differential` (always
80
+ # run), `:self_consistency`, `:properties_in_differential`, `:adapter_parity_sqlite`; and
81
+ # `adapter_parity_sqlite:`, the caller's comparison as a Proc, or `nil` (the default) to
82
+ # skip that mode
77
83
  # @return [Hash{Symbol => Array<Hash>}] one divergence list per active mode
78
- def diff(differ, domain_path, steps, binary, modes:, adapter_parity_sqlite: nil)
79
- self_consistency = modes.include?(:self_consistency)
80
- ruby_result = Replay.call(domain_path, steps, self_consistency: self_consistency)
81
- ruby_instances = JSON.parse(JSON.generate(ruby_result[:instances]))
82
- ruby_events = JSON.parse(JSON.generate(ruby_result[:events]))
83
- ruby_refusals = ruby_result[:refusals].map do |r|
84
- { "verb" => r[:verb].to_s, "kind" => r[:kind].to_s.split("::").last, "error" => r[:error] }
85
- end
86
- ruby_queries = JSON.parse(JSON.generate(ruby_result[:queries].map { |row| Nondeterministic.strip(row, :query_row) }))
87
- ruby_sagas = JSON.parse(JSON.generate(ruby_result[:sagas]))
88
- ruby_dry_runs = ruby_result[:dry_runs].map { |d| { "verb" => d[:verb].to_s, "ok" => d[:ok] } }
84
+ def diff(differ, domain_path, steps, binary, **options)
85
+ modes, adapter_parity = diff_options(options)
86
+ ruby_result = Replay.call(domain_path, steps, self_consistency: modes.include?(:self_consistency))
87
+ outcomes = mode_outcomes(ruby_result, modes, adapter_parity)
88
+ stdout, status = Open3.capture2(binary, stdin_data: RustBuild::KernelInput.json(domain_path, steps))
89
+ return outcomes.merge(differential: [process_failure(status, stdout)]) unless status.success?
89
90
 
90
- outcomes = {}
91
- outcomes[:properties_in_differential] = property_divergences(ruby_result) if modes.include?(:properties_in_differential)
92
- if modes.include?(:adapter_parity_sqlite) && adapter_parity_sqlite
93
- outcomes[:adapter_parity_sqlite] = adapter_parity_sqlite.call
94
- end
91
+ rust_outcomes = rust_outcomes(differ, ruby_result, JSON.parse(stdout), binary, modes.include?(:self_consistency))
92
+ outcomes.merge(rust_outcomes)
93
+ end
95
94
 
96
- stdout, status = Open3.capture2(binary, stdin_data: RustBuild::KernelInput.json(domain_path, steps))
97
- unless status.success?
98
- return outcomes.merge(differential: [{ field: "process",
99
- detail: "rust binary exited #{status.exitstatus}: #{stdout}" }])
100
- end
95
+ # Splits the keywords of `diff` into the modes and the parity hook, refusing any other.
96
+ def diff_options(options)
97
+ unknown = options.keys - [:modes, :adapter_parity_sqlite]
98
+ raise ArgumentError, "unknown keyword: #{unknown.first.inspect}" if unknown.any?
99
+
100
+ [options.fetch(:modes) { raise ArgumentError, "missing keyword: :modes" }, options[:adapter_parity_sqlite]]
101
+ end
101
102
 
102
- rust_output = JSON.parse(stdout)
103
- rust_live_instances = JSON.parse(JSON.generate(rust_output["instances"])) if self_consistency
103
+ # The `:differential` outcome, plus `:self_consistency` when that mode is active.
104
+ def rust_outcomes(differ, ruby_result, rust_output, binary, self_consistency)
105
+ live_instances = WireComparison.jsonify(rust_output["instances"]) if self_consistency
104
106
  differ.strip_emitted_flags!(rust_output["instances"])
105
107
  differ.strip_emitted_flags!(rust_output["queries"])
106
108
  differ.strip_occurred_at!(rust_output["events"])
109
+ outcomes = { differential: WireComparison.differential_divergences(differ, ruby_result, rust_output, binary) }
110
+ outcomes[:self_consistency] = rust_self_consistency(ruby_result, binary, differ, live_instances) if self_consistency
111
+ outcomes
112
+ end
107
113
 
108
- divergences = []
109
- divergences << { field: "instances", ruby: ruby_instances, rust: rust_output["instances"] } \
110
- unless rust_output["instances"] == ruby_instances
111
- divergences << { field: "events", ruby: ruby_events, rust: rust_output["events"] } \
112
- unless rust_output["events"] == ruby_events
113
-
114
- kept = manifest_partition(RustGapManifest.for_binary(binary),
115
- ruby_refusals: ruby_refusals, rust_refusals: rust_output["refusals"],
116
- ruby_queries: ruby_queries, rust_queries: rust_output["queries"])
117
- differ.structural_skips.merge(kept[:skipped])
118
- divergences.concat(kept[:stale])
119
-
120
- by_kind = ->(r) { r.slice("verb", "kind") }
121
- rust_refusals = kept[:rust_refusals].map(&by_kind)
122
- kept_ruby_refusals = kept[:ruby_refusals].map(&by_kind)
123
- divergences << { field: "refusals", ruby: kept_ruby_refusals, rust: rust_refusals } \
124
- unless rust_refusals == kept_ruby_refusals
125
-
126
- wordless = ->(row) { differ.reduce_to_wire_precision(row.except("error", "reference_error")) }
127
- rust_queries = kept[:rust_queries].map(&wordless)
128
- kept_ruby_queries = kept[:ruby_queries].map(&wordless)
129
- divergences << { field: "queries", ruby: kept_ruby_queries, rust: rust_queries } \
130
- unless rust_queries == kept_ruby_queries
131
-
132
- divergences << { field: "sagas", ruby: ruby_sagas, rust: rust_output["sagas"] } \
133
- unless rust_output["sagas"] == ruby_sagas
134
-
135
- cross_domain = differ.cross_domain_policy_names(rust_output)
136
- kept_ruby_reactions = JSON.parse(JSON.generate(ruby_result[:reactions]))
137
- .reject { |r| cross_domain.include?(r["policy"]) }
138
- rust_reactions = rust_output.fetch("reactions")
139
- divergences << { field: "reactions", ruby: kept_ruby_reactions, rust: rust_reactions } \
140
- unless rust_reactions == kept_ruby_reactions
141
-
142
- rust_dry_runs = Array(rust_output["dry_runs"]).map { |d| d.slice("verb", "ok") }
143
- divergences << { field: "dry_runs", ruby: ruby_dry_runs, rust: rust_dry_runs } \
144
- unless rust_dry_runs == ruby_dry_runs
145
- outcomes[:differential] = divergences
114
+ # The modes that run on the Ruby side alone, before the binary is touched.
115
+ def mode_outcomes(ruby_result, modes, adapter_parity)
116
+ outcomes = {}
117
+ outcomes[:properties_in_differential] = property_divergences(ruby_result) if modes.include?(:properties_in_differential)
118
+ outcomes[:adapter_parity_sqlite] = adapter_parity.call if modes.include?(:adapter_parity_sqlite) && adapter_parity
119
+ outcomes
120
+ end
146
121
 
147
- if self_consistency
148
- outcomes[:self_consistency] =
149
- self_consistency_divergences(ruby_result) +
150
- SelfConsistency.check_rust_rehydration(binary, differ, rust_live_instances) +
151
- SelfConsistency.check_rust_idempotency(binary, differ, rust_live_instances)
152
- end
122
+ def process_failure(status, stdout)
123
+ { field: "process", detail: "rust binary exited #{status.exitstatus}: #{stdout}" }
124
+ end
153
125
 
154
- outcomes
126
+ def rust_self_consistency(ruby_result, binary, differ, rust_live_instances)
127
+ self_consistency_divergences(ruby_result) +
128
+ SelfConsistency.check_rust_rehydration(binary, differ, rust_live_instances) +
129
+ SelfConsistency.check_rust_idempotency(binary, differ, rust_live_instances)
155
130
  end
156
131
  end
157
132
  end
@@ -0,0 +1,70 @@
1
+ module Hecks
2
+ module Fuzzing
3
+ module DomainGenerator
4
+ # Renders the blocks a blueprint nests inside aggregates and entities: value objects,
5
+ # lifecycles and commands.
6
+ module BlockRendering
7
+ def render_value_object(name, value_object, indent)
8
+ body = value_object_body(name, value_object)
9
+ ["", "#{indent}value_object #{name.inspect} do", *body.map { |line| "#{indent} #{line}" }, "#{indent}end"]
10
+ end
11
+
12
+ def value_object_body(name, value_object)
13
+ case value_object["kind"]
14
+ when "string" then string_body(name)
15
+ when "positive" then ["attribute :value, Integer", "invariant(#{"a #{name} is positive".inspect}) { value.positive? }"]
16
+ when "integer" then ["attribute :value, Integer"]
17
+ when "closed" then ["attribute :value, String, one_of: #{value_object["members"].inspect}"]
18
+ end
19
+ end
20
+
21
+ def string_body(name)
22
+ ["attribute :value, String, pattern: '[^ \\t\\n\\r]'",
23
+ "invariant(#{"a #{name} is not blank".inspect}) { !value.to_s.empty? }"]
24
+ end
25
+
26
+ def render_lifecycle(lifecycle, indent)
27
+ ["", "#{indent}lifecycle :#{lifecycle["field"]}, default: #{lifecycle["default"].inspect} do",
28
+ *lifecycle["transitions"].map { |transition| render_transition(transition, indent) },
29
+ "#{indent}end"]
30
+ end
31
+
32
+ def render_transition(transition, indent)
33
+ from = transition["from"].size == 1 ? transition["from"].first.inspect : transition["from"].inspect
34
+ "#{indent} transition #{transition["command"].inspect} => #{transition["to"].inspect}, from: #{from}"
35
+ end
36
+
37
+ def render_command(command, self_name, indent)
38
+ ["", "#{indent}command #{command["name"].inspect} do",
39
+ *command_header(command, self_name, indent),
40
+ *command_body(command, indent),
41
+ "#{indent}end"]
42
+ end
43
+
44
+ # A command's role, goal and references.
45
+ def command_header(command, self_name, indent)
46
+ out = []
47
+ out << "#{indent} role #{command["role"].inspect}" if command["role"]
48
+ out << "#{indent} goal #{"#{command["name"]} it".inspect}"
49
+ out << "#{indent} reference_to #{self_name}" if self_name && !command["creates"]
50
+ out + command["references"].map { |target| "#{indent} reference_to #{target}" }
51
+ end
52
+
53
+ # A command's arguments, givens, sets and emitted events.
54
+ def command_body(command, indent)
55
+ [*command["args"].map { |arg| "#{indent} #{render_attribute(arg)}" },
56
+ *command["givens"].map { |given| "#{indent} given(#{given["label"].inspect}) { #{given["expr"]} }" },
57
+ *command["sets"].map { |set| "#{indent} #{render_set(set)}" },
58
+ *command["emits"].map { |event| "#{indent} emits #{event.inspect}" }]
59
+ end
60
+
61
+ def render_set(set)
62
+ return "sets :#{set["target"]}, to: :#{set["to"]}" if set["to"]
63
+ return "sets :#{set["target"]}, append: { #{set["append"].map { |k, v| "#{k}: :#{v}" }.join(", ")} }" if set["append"]
64
+
65
+ "sets :#{set["target"]}"
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,105 @@
1
+ module Hecks
2
+ module Fuzzing
3
+ module DomainGenerator
4
+ class Builder
5
+ # The shapes a form puts on one aggregate's attributes and rules: lifecycle, query, list,
6
+ # closed set, default and optional attributes.
7
+ module AttributeShapes
8
+ private
9
+
10
+ def lifecycle(aggregate)
11
+ return if aggregate["lifecycle"]
12
+
13
+ name = aggregate["name"]
14
+ command(aggregate, "Close")
15
+ command(aggregate, "Reopen")
16
+ aggregate["lifecycle"] = { "field" => "status", "default" => "open", "transitions" => [
17
+ { "command" => "Close", "to" => "closed", "from" => ["open"], "requires" => ["command:#{name}.Close"] },
18
+ { "command" => "Reopen", "to" => "open", "from" => ["closed"], "requires" => ["command:#{name}.Reopen"] }
19
+ ] }
20
+ end
21
+
22
+ def query(aggregate)
23
+ return if aggregate["queries"].any? { |query| query["name"] == "Listed" }
24
+
25
+ where = if aggregate["lifecycle"] || chance?(0.5)
26
+ lifecycle(aggregate)
27
+ { "field" => "status", "value" => "open", "requires" => ["lifecycle:#{aggregate["name"]}"] }
28
+ else
29
+ priority_where(aggregate)
30
+ end
31
+ aggregate["queries"] << { "name" => "Listed", "wheres" => [where], "order_by" => aggregate["identity"].first }
32
+ end
33
+
34
+ def priority_where(aggregate)
35
+ members = closed_set(aggregate)
36
+ { "field" => "priority.value", "value" => members.first,
37
+ "requires" => ["attribute:#{aggregate["name"]}.priority"] }
38
+ end
39
+
40
+ def list_attr(aggregate)
41
+ name = aggregate["name"]
42
+ return if aggregate["attributes"].any? { |attribute| attribute["name"] == "tags" }
43
+
44
+ vo(aggregate, "#{name}Tag", "string")
45
+ aggregate["attributes"] << { "name" => "tags", "type" => "#{name}Tag", "list" => true }
46
+ command(aggregate, "Retag", args: [{ "name" => "tags", "type" => "#{name}Tag", "list" => true }],
47
+ sets: [{ "target" => "tags", "requires" => ["attribute:#{name}.tags"] }])
48
+ end
49
+
50
+ def closed_set(aggregate)
51
+ name = aggregate["name"]
52
+ existing = aggregate["vos"]["#{name}Priority"]
53
+ return existing["members"] if existing
54
+
55
+ members = CLOSED_SETS.sample(random: @random)
56
+ vo(aggregate, "#{name}Priority", "closed", members: members)
57
+ aggregate["attributes"] << { "name" => "priority", "type" => "#{name}Priority", "optional" => true }
58
+ command(aggregate, "Prioritize", args: [{ "name" => "priority", "type" => "#{name}Priority" }],
59
+ sets: [{ "target" => "priority", "requires" => ["attribute:#{name}.priority"] }])
60
+ members
61
+ end
62
+
63
+ def default_attr(aggregate)
64
+ name = aggregate["name"]
65
+ return if aggregate["attributes"].any? { |attribute| attribute["name"] == "score" }
66
+
67
+ vo(aggregate, "#{name}Score", "integer")
68
+ aggregate["attributes"] << { "name" => "score", "type" => "#{name}Score", "default" => 0 }
69
+ add_rescore(aggregate, name)
70
+ score_invariant(aggregate, name) if chance?(0.5)
71
+ end
72
+
73
+ def add_rescore(aggregate, name)
74
+ score = "attribute:#{name}.score"
75
+ command(aggregate, "Rescore", args: [{ "name" => "amount", "type" => "#{name}Score" }], givens: score_givens(name),
76
+ sets: [{ "target" => "score", "to" => "amount", "requires" => [score] }])
77
+ end
78
+
79
+ def score_invariant(aggregate, name)
80
+ aggregate["invariants"] << { "label" => "a score is never negative", "expr" => "score.value >= 0",
81
+ "requires" => ["attribute:#{name}.score"] }
82
+ end
83
+
84
+ # Half the time, a given that a score never drops.
85
+ def score_givens(name)
86
+ return [] unless chance?(0.5)
87
+
88
+ [{ "label" => "a score never drops", "expr" => "amount.value >= score.value",
89
+ "requires" => ["attribute:#{name}.score"] }]
90
+ end
91
+
92
+ def optional_arg(aggregate)
93
+ name = aggregate["name"]
94
+ return if aggregate["attributes"].any? { |attribute| attribute["name"] == "note" }
95
+
96
+ vo(aggregate, "#{name}Note", "string")
97
+ aggregate["attributes"] << { "name" => "note", "type" => "#{name}Note", "optional" => true }
98
+ command(aggregate, "Annotate", args: [{ "name" => "note", "type" => "#{name}Note", "optional" => true }],
99
+ sets: [{ "target" => "note", "requires" => ["attribute:#{name}.note"] }])
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end