hecks 2.7.0 → 2.9.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 (463) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +11 -0
  3. data/lib/hecks/adapters/driven/claude_code.rb +4 -104
  4. data/lib/hecks/adapters/driven/d1.rb +44 -237
  5. data/lib/hecks/adapters/driven/folder.rb +17 -76
  6. data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
  7. data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
  8. data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
  9. data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
  10. data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
  11. data/lib/hecks/adapters/driven/heki.rb +13 -42
  12. data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
  13. data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
  14. data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
  15. data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
  16. data/lib/hecks/adapters/driven/lambda.rb +10 -84
  17. data/lib/hecks/adapters/driven/local_storage.rb +5 -40
  18. data/lib/hecks/adapters/driven/memory.rb +18 -99
  19. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
  20. data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
  21. data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
  22. data/lib/hecks/adapters/driven/postgres/reconnect.rb +4 -30
  23. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
  24. data/lib/hecks/adapters/driven/postgres.rb +145 -134
  25. data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
  26. data/lib/hecks/adapters/driven/prism.rb +7 -30
  27. data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
  28. data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
  29. data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
  30. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
  31. data/lib/hecks/adapters/driven/sqlite.rb +128 -65
  32. data/lib/hecks/adapters/driven/tenant_provisioner.rb +15 -37
  33. data/lib/hecks/adapters/driven.rb +5 -36
  34. data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
  35. data/lib/hecks/behaviors/dsl.rb +7 -25
  36. data/lib/hecks/behaviors/expectations.rb +32 -142
  37. data/lib/hecks/behaviors/ir.rb +7 -20
  38. data/lib/hecks/behaviors/rspec.rb +6 -17
  39. data/lib/hecks/behaviors/runner.rb +10 -34
  40. data/lib/hecks/behaviors.rb +4 -8
  41. data/lib/hecks/bluebook/aggregate.rb +9 -75
  42. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
  43. data/lib/hecks/bluebook/assembly/build.rb +4 -15
  44. data/lib/hecks/bluebook/assembly/contract.rb +15 -136
  45. data/lib/hecks/bluebook/assembly/contracts.rb +54 -174
  46. data/lib/hecks/bluebook/assembly/marks.rb +31 -223
  47. data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
  48. data/lib/hecks/bluebook/assembly.rb +6 -45
  49. data/lib/hecks/bluebook/attribute.rb +12 -61
  50. data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -39
  51. data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
  52. data/lib/hecks/bluebook/behaviour/chapter.rb +17 -42
  53. data/lib/hecks/bluebook/behaviour/command.rb +14 -66
  54. data/lib/hecks/bluebook/behaviour/domain_port.rb +4 -20
  55. data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
  56. data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
  57. data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
  58. data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
  59. data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
  60. data/lib/hecks/bluebook/behaviour/read_model.rb +38 -26
  61. data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
  62. data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
  63. data/lib/hecks/bluebook/capabilities.rb +17 -49
  64. data/lib/hecks/bluebook/chapter.rb +10 -48
  65. data/lib/hecks/bluebook/command.rb +23 -81
  66. data/lib/hecks/bluebook/domain_port.rb +14 -63
  67. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
  68. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
  69. data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
  70. data/lib/hecks/bluebook/dsl/binding_proxy.rb +17 -65
  71. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +86 -708
  72. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +56 -170
  73. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +1 -0
  74. data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
  75. data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
  76. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +12 -87
  77. data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
  78. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
  79. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +26 -189
  80. data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
  81. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
  82. data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
  83. data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
  84. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
  85. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
  86. data/lib/hecks/bluebook/dsl/query_builder.rb +11 -42
  87. data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
  88. data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
  89. data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
  90. data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
  91. data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
  92. data/lib/hecks/bluebook/dsl/world_builder.rb +19 -106
  93. data/lib/hecks/bluebook/entity.rb +13 -71
  94. data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
  95. data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
  96. data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
  97. data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
  98. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
  99. data/lib/hecks/bluebook/expression/resolver.rb +37 -660
  100. data/lib/hecks/bluebook/hexagon.rb +5 -28
  101. data/lib/hecks/bluebook/lifecycle.rb +5 -16
  102. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
  103. data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
  104. data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
  105. data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
  106. data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
  107. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +24 -176
  108. data/lib/hecks/bluebook/meta_validator/shapes.rb +54 -268
  109. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -308
  110. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
  111. data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
  112. data/lib/hecks/bluebook/meta_validator.rb +79 -349
  113. data/lib/hecks/bluebook/model_check/client_profile.rb +10 -91
  114. data/lib/hecks/bluebook/model_check.rb +102 -600
  115. data/lib/hecks/bluebook/pattern_subset.rb +11 -69
  116. data/lib/hecks/bluebook/process_manager.rb +13 -83
  117. data/lib/hecks/bluebook/project_loader.rb +3 -39
  118. data/lib/hecks/bluebook/project_register.rb +12 -60
  119. data/lib/hecks/bluebook/query.rb +9 -48
  120. data/lib/hecks/bluebook/read_model.rb +57 -81
  121. data/lib/hecks/bluebook/reference.rb +7 -41
  122. data/lib/hecks/bluebook/smoke_test.rb +8 -98
  123. data/lib/hecks/bluebook/synthesizer.rb +13 -62
  124. data/lib/hecks/bluebook/translation.rb +26 -62
  125. data/lib/hecks/bluebook/value_object.rb +11 -36
  126. data/lib/hecks/bluebook.rb +5 -22
  127. data/lib/hecks/cache_dir.rb +84 -0
  128. data/lib/hecks/cli/document.rb +86 -0
  129. data/lib/hecks/cli/ir.rb +45 -0
  130. data/lib/hecks/cli/mcp.rb +31 -0
  131. data/lib/hecks/cli/mcp_door.rb +366 -0
  132. data/lib/hecks/cli/model_check.rb +203 -0
  133. data/lib/hecks/cli/project_cli.rb +90 -0
  134. data/lib/hecks/cli/project_diagrams.rb +36 -0
  135. data/lib/hecks/cli/run.rb +173 -0
  136. data/lib/hecks/cli/smoke_test.rb +45 -0
  137. data/lib/hecks/cli/stores.rb +53 -0
  138. data/lib/hecks/cli.rb +160 -0
  139. data/lib/hecks/construct.rb +8 -34
  140. data/lib/hecks/deploy/bluebook/deploy.bluebook +33 -142
  141. data/lib/hecks/deploy/bluebook/deploy.hecksagon +2 -9
  142. data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
  143. data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
  144. data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
  145. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
  146. data/lib/hecks/embryonaut_bluebook.rb +4 -71
  147. data/lib/hecks/facade/cli_door.rb +24 -106
  148. data/lib/hecks/facade/cli_runner.rb +28 -172
  149. data/lib/hecks/facade/command_request.rb +13 -33
  150. data/lib/hecks/facade/handle.rb +34 -121
  151. data/lib/hecks/facade/json_door.rb +31 -146
  152. data/lib/hecks/facade/surface/aggregate_door.rb +39 -104
  153. data/lib/hecks/facade/surface/chapter.rb +10 -54
  154. data/lib/hecks/facade/surface.rb +8 -23
  155. data/lib/hecks/facade.rb +10 -25
  156. data/lib/hecks/forms/app.rb +15 -70
  157. data/lib/hecks/forms/command_form_renderer.rb +10 -29
  158. data/lib/hecks/forms/field_renderer.rb +17 -156
  159. data/lib/hecks/forms/field_shape.rb +30 -222
  160. data/lib/hecks/forms/html.rb +12 -47
  161. data/lib/hecks/forms/index_renderer.rb +1 -4
  162. data/lib/hecks/forms/page.rb +3 -9
  163. data/lib/hecks/forms/params.rb +14 -60
  164. data/lib/hecks/forms/port_argument.rb +2 -19
  165. data/lib/hecks/forms/query_form_renderer.rb +4 -79
  166. data/lib/hecks/forms/record_renderer.rb +8 -75
  167. data/lib/hecks/forms/record_table.rb +7 -50
  168. data/lib/hecks/forms/reference_options.rb +3 -30
  169. data/lib/hecks/forms/value_object_shape.rb +8 -35
  170. data/lib/hecks/forms.rb +5 -33
  171. data/lib/hecks/fqn.rb +5 -12
  172. data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
  173. data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
  174. data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
  175. data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
  176. data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
  177. data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
  178. data/lib/hecks/framework.rb +11 -80
  179. data/lib/hecks/freezer.rb +5 -39
  180. data/lib/hecks/grammar/expression.bluebook +15 -40
  181. data/lib/hecks/grammar/translation.bluebook +3 -6
  182. data/lib/hecks/grammar.rb +16 -41
  183. data/lib/hecks/ir.rb +14 -83
  184. data/lib/hecks/language/adapter.bluebook +2 -7
  185. data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
  186. data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
  187. data/lib/hecks/language/bluebook/bluebook.bluebook +15 -83
  188. data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
  189. data/lib/hecks/language/bluebook/command.bluebook +27 -144
  190. data/lib/hecks/language/bluebook/entity.bluebook +24 -97
  191. data/lib/hecks/language/bluebook/policy.bluebook +16 -67
  192. data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
  193. data/lib/hecks/language/bluebook/projection.bluebook +126 -60
  194. data/lib/hecks/language/bluebook/query.bluebook +12 -43
  195. data/lib/hecks/language/bluebook/shape.bluebook +23 -73
  196. data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
  197. data/lib/hecks/language/bluebook/vocabulary.bluebook +98 -197
  198. data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
  199. data/lib/hecks/language/hecksagon/domain_port.bluebook +4 -19
  200. data/lib/hecks/language/hecksagon/hecksagon.bluebook +6 -25
  201. data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
  202. data/lib/hecks/language/oidc.json +35 -0
  203. data/lib/hecks/language/port.bluebook +4 -17
  204. data/lib/hecks/language/translation/translation.bluebook +3 -9
  205. data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
  206. data/lib/hecks/language/world/wiring.bluebook +1 -3
  207. data/lib/hecks/language/world/world.bluebook +5 -7
  208. data/lib/hecks/literal.rb +8 -50
  209. data/lib/hecks/mcp_door_scope.rb +95 -0
  210. data/lib/hecks/mcp_stdio_guard.rb +4 -41
  211. data/lib/hecks/naming.rb +29 -137
  212. data/lib/hecks/ports/access_control.rb +7 -23
  213. data/lib/hecks/ports/agent/answers.rb +5 -23
  214. data/lib/hecks/ports/agent.rb +47 -172
  215. data/lib/hecks/ports/authentication.rb +12 -39
  216. data/lib/hecks/ports/authorization.rb +16 -43
  217. data/lib/hecks/ports/clock.rb +5 -45
  218. data/lib/hecks/ports/extraction.rb +7 -12
  219. data/lib/hecks/ports/identity_assignment.rb +8 -29
  220. data/lib/hecks/ports/identity_generation.rb +6 -29
  221. data/lib/hecks/ports/identity_resolution.rb +2 -10
  222. data/lib/hecks/ports/key_vault.rb +9 -45
  223. data/lib/hecks/ports/persistence/append_only.rb +62 -65
  224. data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
  225. data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
  226. data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
  227. data/lib/hecks/ports/persistence/plugin.rb +13 -42
  228. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +38 -141
  229. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
  230. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +16 -84
  231. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +7 -26
  232. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +3 -22
  233. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
  234. data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
  235. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
  236. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
  237. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
  238. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
  239. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
  240. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
  241. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +18 -75
  242. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
  243. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
  244. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
  245. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
  246. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
  247. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +14 -115
  248. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
  249. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +127 -554
  250. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
  251. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
  252. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
  253. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
  254. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
  255. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
  256. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +9 -25
  257. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +22 -122
  258. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
  259. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
  260. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
  261. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
  262. data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
  263. data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
  264. data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
  265. data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
  266. data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
  267. data/lib/hecks/ports/persistence/state_codec.rb +23 -103
  268. data/lib/hecks/ports/persistence.rb +7 -14
  269. data/lib/hecks/ports/projection.rb +42 -84
  270. data/lib/hecks/ports/query/in_memory.rb +10 -58
  271. data/lib/hecks/ports/query/ordering.rb +11 -32
  272. data/lib/hecks/ports/query.rb +14 -37
  273. data/lib/hecks/ports.rb +2 -8
  274. data/lib/hecks/projections/bootstrap_table.rb +11 -43
  275. data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
  276. data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
  277. data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
  278. data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
  279. data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
  280. data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
  281. data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
  282. data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
  283. data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
  284. data/lib/hecks/projections/deploy/fargate.rb +35 -202
  285. data/lib/hecks/projections/deploy/lambda.rb +151 -679
  286. data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
  287. data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
  288. data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
  289. data/lib/hecks/projections/deploy/preview/script.rb +2 -14
  290. data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
  291. data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
  292. data/lib/hecks/projections/deploy/preview/template.rb +2 -58
  293. data/lib/hecks/projections/deploy/preview.rb +2 -67
  294. data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
  295. data/lib/hecks/projections/deploy/scripts.rb +4 -57
  296. data/lib/hecks/projections/deploy/shared.rb +47 -146
  297. data/lib/hecks/projections/deploy/smoke.rb +4 -61
  298. data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
  299. data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
  300. data/lib/hecks/projections/deploy/template_diff.rb +5 -57
  301. data/lib/hecks/projections/diagrams.rb +20 -582
  302. data/lib/hecks/projections/glossary/html.rb +14 -130
  303. data/lib/hecks/projections/glossary/markdown.rb +8 -69
  304. data/lib/hecks/projections/glossary/mermaid.rb +9 -66
  305. data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
  306. data/lib/hecks/projections/glossary/sentences.rb +14 -159
  307. data/lib/hecks/projections/glossary.rb +30 -222
  308. data/lib/hecks/projections/ir.rb +3 -10
  309. data/lib/hecks/projections/model/deviations.rb +15 -42
  310. data/lib/hecks/projections/model.rb +12 -51
  311. data/lib/hecks/projections/oidc.rb +12 -56
  312. data/lib/hecks/projections/parser_table.rb +9 -28
  313. data/lib/hecks/projections/reference.rb +9 -16
  314. data/lib/hecks/projections/rust_vocabulary.rb +12 -250
  315. data/lib/hecks/projections/shape.rb +3 -29
  316. data/lib/hecks/projections/statements.rb +7 -86
  317. data/lib/hecks/projections/vocabulary.rb +6 -22
  318. data/lib/hecks/projections.rb +2 -16
  319. data/lib/hecks/projector/cli_projector.rb +60 -375
  320. data/lib/hecks/projector/docs_projector.rb +10 -201
  321. data/lib/hecks/projector/exporter.rb +46 -138
  322. data/lib/hecks/projector/ir_projector.rb +2 -9
  323. data/lib/hecks/projector/narrate_projector.rb +15 -189
  324. data/lib/hecks/projector/target.rb +13 -76
  325. data/lib/hecks/projector.rb +30 -121
  326. data/lib/hecks/query_specification/common/comparators.rb +5 -26
  327. data/lib/hecks/query_specification/common/comparison.rb +35 -143
  328. data/lib/hecks/query_specification/common/dsl.rb +8 -24
  329. data/lib/hecks/query_specification/common/null_policy.rb +20 -70
  330. data/lib/hecks/query_specification/common/options.rb +2 -6
  331. data/lib/hecks/query_specification/common/where_clause.rb +2 -10
  332. data/lib/hecks/query_specification/field_path.rb +37 -77
  333. data/lib/hecks/query_specification/hop_path.rb +12 -76
  334. data/lib/hecks/release/gem_pin.rb +2 -26
  335. data/lib/hecks/release/runner/ci_publisher.rb +93 -0
  336. data/lib/hecks/release/runner/commands.rb +66 -0
  337. data/lib/hecks/release/runner/console.rb +52 -0
  338. data/lib/hecks/release/runner/gem_publisher.rb +43 -0
  339. data/lib/hecks/release/runner/git.rb +48 -0
  340. data/lib/hecks/release/runner/npm_publisher.rb +75 -0
  341. data/lib/hecks/release/runner/preflight.rb +104 -0
  342. data/lib/hecks/release/runner/published.rb +55 -0
  343. data/lib/hecks/release/runner/tagger.rb +80 -0
  344. data/lib/hecks/release/runner.rb +215 -0
  345. data/lib/hecks/rendering.rb +4 -26
  346. data/lib/hecks/router/namespace_installer.rb +12 -36
  347. data/lib/hecks/router.rb +4 -8
  348. data/lib/hecks/runtime/aggregate_lock.rb +8 -33
  349. data/lib/hecks/runtime/boot_gates.rb +3 -18
  350. data/lib/hecks/runtime/caller.rb +19 -59
  351. data/lib/hecks/runtime/capability_graph.rb +5 -21
  352. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
  353. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +23 -160
  354. data/lib/hecks/runtime/command_interpreter.rb +125 -307
  355. data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
  356. data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
  357. data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
  358. data/lib/hecks/runtime/command_rules/emission.rb +8 -21
  359. data/lib/hecks/runtime/command_rules/references.rb +23 -202
  360. data/lib/hecks/runtime/dependency_planning.rb +30 -102
  361. data/lib/hecks/runtime/dispatcher.rb +82 -241
  362. data/lib/hecks/runtime/entity_element.rb +40 -462
  363. data/lib/hecks/runtime/entity_interpreter.rb +65 -220
  364. data/lib/hecks/runtime/errors.rb +32 -115
  365. data/lib/hecks/runtime/event.rb +3 -25
  366. data/lib/hecks/runtime/identity.rb +18 -154
  367. data/lib/hecks/runtime/instance.rb +18 -150
  368. data/lib/hecks/runtime/interpreting.rb +11 -70
  369. data/lib/hecks/runtime/invocation.rb +28 -164
  370. data/lib/hecks/runtime/loader.rb +48 -186
  371. data/lib/hecks/runtime/outbox.rb +38 -261
  372. data/lib/hecks/runtime/policy_interpreter.rb +38 -200
  373. data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
  374. data/lib/hecks/runtime/query_interpreter.rb +45 -187
  375. data/lib/hecks/runtime/reaction_invocation.rb +36 -138
  376. data/lib/hecks/runtime/read_model_interpreter.rb +139 -208
  377. data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
  378. data/lib/hecks/runtime/reference_hop.rb +8 -81
  379. data/lib/hecks/runtime/refusal_wording.rb +8 -89
  380. data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
  381. data/lib/hecks/runtime/registry/verification.rb +52 -225
  382. data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
  383. data/lib/hecks/runtime/registry.rb +103 -244
  384. data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
  385. data/lib/hecks/runtime/routing.rb +4 -15
  386. data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
  387. data/lib/hecks/runtime/saga_interpreter.rb +79 -263
  388. data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
  389. data/lib/hecks/runtime/tenant_check.rb +6 -68
  390. data/lib/hecks/runtime/tenant_scope.rb +3 -28
  391. data/lib/hecks/runtime/value/admission.rb +16 -67
  392. data/lib/hecks/runtime/value/coercion.rb +155 -641
  393. data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
  394. data/lib/hecks/runtime/value.rb +12 -84
  395. data/lib/hecks/runtime.rb +17 -65
  396. data/lib/hecks/storehouse.rb +146 -567
  397. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
  398. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
  399. data/lib/hecks/vendoring/git_environment.rb +2 -8
  400. data/lib/hecks/vendoring/git_source.rb +4 -10
  401. data/lib/hecks/vendoring.rb +7 -46
  402. data/lib/hecks/version.rb +3 -14
  403. data/lib/hecks/vocabulary.rb +5 -0
  404. data/lib/hecks.rb +32 -82
  405. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
  406. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
  407. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
  408. metadata +30 -59
  409. data/lib/hecks/bench/cli.rb +0 -74
  410. data/lib/hecks/bench/environment.rb +0 -100
  411. data/lib/hecks/bench/postgres_probe.rb +0 -41
  412. data/lib/hecks/bench/report.rb +0 -116
  413. data/lib/hecks/bench/ruby_runner.rb +0 -151
  414. data/lib/hecks/bench/run.rb +0 -55
  415. data/lib/hecks/bench/rust_runner.rb +0 -165
  416. data/lib/hecks/bench/stats.rb +0 -75
  417. data/lib/hecks/bench/suite.rb +0 -172
  418. data/lib/hecks/bench/workload.rb +0 -137
  419. data/lib/hecks/bench.rb +0 -28
  420. data/lib/hecks/codemod.rb +0 -443
  421. data/lib/hecks/corpus.rb +0 -479
  422. data/lib/hecks/doc/reference.rb +0 -585
  423. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -684
  424. data/lib/hecks/fuzzing/combination_miner.rb +0 -178
  425. data/lib/hecks/fuzzing/concurrent_dispatch.rb +0 -469
  426. data/lib/hecks/fuzzing/coverage_campaign.rb +0 -161
  427. data/lib/hecks/fuzzing/differential.rb +0 -192
  428. data/lib/hecks/fuzzing/domain_generator.rb +0 -871
  429. data/lib/hecks/fuzzing/era_boundary.rb +0 -154
  430. data/lib/hecks/fuzzing/form_census.rb +0 -285
  431. data/lib/hecks/fuzzing/generated_domain_check.rb +0 -171
  432. data/lib/hecks/fuzzing/invalid_value_generator.rb +0 -125
  433. data/lib/hecks/fuzzing/isolated_boot.rb +0 -658
  434. data/lib/hecks/fuzzing/nondeterministic.rb +0 -79
  435. data/lib/hecks/fuzzing/persistence_parity.rb +0 -253
  436. data/lib/hecks/fuzzing/properties/corrections.rb +0 -125
  437. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +0 -688
  438. data/lib/hecks/fuzzing/properties/guards.rb +0 -398
  439. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +0 -399
  440. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +0 -137
  441. data/lib/hecks/fuzzing/properties/outbox.rb +0 -180
  442. data/lib/hecks/fuzzing/properties/querying.rb +0 -260
  443. data/lib/hecks/fuzzing/properties.rb +0 -267
  444. data/lib/hecks/fuzzing/qa_settings.rb +0 -164
  445. data/lib/hecks/fuzzing/replay.rb +0 -930
  446. data/lib/hecks/fuzzing/rotation_priority.rb +0 -114
  447. data/lib/hecks/fuzzing/rust_gap_manifest.rb +0 -139
  448. data/lib/hecks/fuzzing/self_consistency.rb +0 -825
  449. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +0 -532
  450. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +0 -171
  451. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +0 -127
  452. data/lib/hecks/fuzzing/sequence_generator/picker.rb +0 -116
  453. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +0 -138
  454. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +0 -344
  455. data/lib/hecks/fuzzing/sequence_generator.rb +0 -311
  456. data/lib/hecks/fuzzing/shrinker.rb +0 -309
  457. data/lib/hecks/fuzzing/structural_skips.rb +0 -53
  458. data/lib/hecks/fuzzing/sweep_depth.rb +0 -61
  459. data/lib/hecks/fuzzing/target_capabilities.rb +0 -255
  460. data/lib/hecks/fuzzing/value_generator.rb +0 -340
  461. data/lib/hecks/fuzzing.rb +0 -23
  462. data/lib/hecks/grammar/evolve.rb +0 -524
  463. data/lib/hecks/query_ir.rb +0 -482
@@ -1,340 +0,0 @@
1
- require_relative "../runtime/value"
2
-
3
- module Hecks
4
- module Fuzzing
5
- # One attribute, one value — in the exact JSON shape the hand-written
6
- # corpus already uses (a value-object-typed attribute is a nested hash keyed
7
- # by its own field names ; a reference is the bare ID of the head it points
8
- # at, because that is what a reference is). Everything
9
- # returned is a plain, JSON-safe Ruby value : String keys throughout, never
10
- # symbols, so a generated step can be dumped straight to JSON.
11
- #
12
- # Biased toward the edge cases a hand-written corpus tends to under-sample —
13
- # empty strings, quotes, commas, unicode, zero, negative numbers — because
14
- # `marks.rb` names literal-encoding loss "the largest family of bug in this
15
- # codebase," and a fixed corpus of a few dozen examples rarely happens to
16
- # exercise the boundary that actually breaks. But mostly not : an attribute
17
- # named `email`/`currency` almost always needs a specific shape just to get
18
- # past its own invariant (`address.include?("@")`, `currency.size == 3`) —
19
- # banking's very first fuzz run never got past Customer.Register, because
20
- # no plain random word ever contains "@". Reaching deep state matters more
21
- # than edge-casing every single field every single time, so the "normal"
22
- # path is now name-aware for the couple of shapes that are genuinely
23
- # common across domains, and edge cases stay real but less frequent.
24
- module ValueGenerator
25
- module_function
26
-
27
- EDGE_CASE_PROBABILITY = 0.2
28
- INVALID_MEMBER_PROBABILITY = 0.1
29
- INVALID_REFERENCE_PROBABILITY = 0.2
30
- # `Value.for_attribute` → `fields_for`'s own bare-scalar branch
31
- # (lib/hecks/runtime/value/coercion.rb) has accepted a bare
32
- # `"large"` in place of `{"value" => "large"}` for any single-field
33
- # value object since 86727afd — but until this generator actually
34
- # produces that shape, nothing exercises it: neither the adapter-
35
- # agreement gate nor the Rust/WASM `from_json` codegen (rust/project/
36
- # json_codec.rb) can ever be caught drifting on a shape they're
37
- # never handed.
38
- BARE_SCALAR_PROBABILITY = 0.2
39
-
40
- STRING_EDGE_CASES = [
41
- "", "x", "with \"quotes\"", "with, a comma", "with a \\backslash",
42
- "unicode héllo wörld 🎉", "x" * 200, " leading and trailing "
43
- ].freeze
44
- # PRD 05 (numeric-boundary-coverage) — Bignum (`2**100`, past i64's
45
- # own ceiling, which Ruby's own `Integer` has no such ceiling for —
46
- # `rust/src/kernel/json.rs`'s own `integral_i64` doc comment names
47
- # exactly this: a Rust kernel value cannot represent it, so this
48
- # exercises a real cross-runtime capability gap, not a Ruby-only
49
- # edge) and its negative twin. Both round-trip through Ruby's own
50
- # arithmetic/JSON cleanly (confirmed directly: `(2**100).clamp(...)`
51
- # and `JSON.generate(2**100)` both just work — Integer has no
52
- # ceiling here), so nothing in this runtime needed a fix for these;
53
- # they're included so a real generated sequence occasionally
54
- # produces the value at all, since nothing had, repo-wide, before.
55
- INTEGER_EDGE_CASES = [0, -1, 2_147_483_647, -2_147_483_648, 2**100, -(2**100)].freeze
56
- # BUG#35 (QualityControl QA ledger, `lease-clock-json-precision`) —
57
- # a Bignum edge case (`2**100`, above) landing on an Integer-typed
58
- # clock or count reading fires the already-catalogued `Json::Num`/
59
- # f64 precision-loss class (`rust/src/kernel/json.rs`'s
60
- # `parse_number` parses every number through `s.parse::<f64>()`
61
- # before any target-type conversion runs, and `Json::Num` is a
62
- # plain `f64` end to end — see that file's own header) on a new
63
- # site every time a new clock/count-shaped field is authored,
64
- # without adding any new coverage: both engines already refuse
65
- # (`TypeMismatch`, out of `i64` range either way) for this shape,
66
- # `tenant_ledger`'s own NOTES.md already logged the identical class
67
- # on a stored money attribute, and `spec/support/
68
- # rust_conformance_helpers.rb`'s own `reduce_to_wire_precision`
69
- # already documents and normalizes past the wire format's own loss
70
- # for a query's echoed args. An exact-integer Rust JSON
71
- # deserialization path was considered and rejected as this
72
- # generator's own fix instead: `Json::Num(f64)` is pattern-matched
73
- # throughout `rust/src/kernel` (query_comparators.rs,
74
- # query_ordering.rs, read_model.rs, named_query.rs, this kernel's
75
- # own `Fielded` impl, arithmetic overflow checks) and emitted by
76
- # codegen (`rust/project/reactions.rb`, `rust/codegen/src/
77
- # reactions.rs`) — adding a second, exact-integer numeric variant
78
- # would mean auditing and updating every one of those sites, a
79
- # refactor of the JSON layer itself, not a one-domain fix (exactly
80
- # the ledger's own stated concern: "risks affecting every other
81
- # domain's large-integer handling"). So instead, per the ledger's
82
- # own sanctioned fallback: an Integer-typed field whose name reads
83
- # as a clock or a count is capped to a narrower, still-real
84
- # edge-case pool below (still exercises the ordinary i32
85
- # boundaries, just never a value past f64's own 2**53 exact-
86
- # integer ceiling) — every other Integer-typed field (a money
87
- # amount, an identity sequence, anything not clock/count-shaped)
88
- # still draws from the full `INTEGER_EDGE_CASES` pool above,
89
- # unchanged.
90
- SAFE_INTEGER_EDGE_CASES = [0, -1, 2_147_483_647, -2_147_483_648].freeze
91
- # Matched against the value object's own declared name plus the
92
- # attribute's own name (`value_for`'s `"#{context} #{attribute.
93
- # name}"`, e.g. "LeaseInstant value", "RetryCount value") — a
94
- # clock reading ("instant"/"clock"/"expir(es/y)"/"ttl"/"now"/
95
- # "timestamp"/"epoch") or a quantity capped by a policy ("count").
96
- # Deliberately narrow: matches the ledger's own "clock/count"
97
- # wording exactly, not every plausibly-large-looking name (an
98
- # "amount"/"cents"/"sequence" field is not clock/count-shaped and
99
- # keeps the full Bignum edge-case pool).
100
- CLOCK_OR_COUNT_NAME_PATTERN = /clock|instant|expir|ttl|\bnow\b|timestamp|epoch|count/i
101
- # NaN and +/-Infinity — the real find (see `spec/runtime/
102
- # numeric_boundary_spec.rb`): `Value::Coercion#check_numeric_fields`
103
- # type-checks all three (each really is a Float) before they can
104
- # reach either `CommandRules::Arithmetic#clamp` (raw
105
- # `ArgumentError`, not a domain refusal) or `JSON.generate`
106
- # (`JSON::GeneratorError`, also not a domain refusal) — both fixed
107
- # at the source, so these are safe to generate. -0.0 is
108
- # deliberately included too even though it was already safe
109
- # (finite, round-trips through JSON as `-0.0` cleanly) — a signed
110
- # zero is exactly the kind of boundary a hand-written corpus never
111
- # happens to type, and the fuzzer existing to cover it is the
112
- # point.
113
- FLOAT_EDGE_CASES = [0.0, -0.0, -0.5, -100.25, Float::NAN, Float::INFINITY, -Float::INFINITY].freeze
114
- WORDS = %w[alpha bravo charlie delta echo foxtrot golf hotel india juliet].freeze
115
- CURRENCY_CODES = %w[USD EUR GBP JPY].freeze
116
-
117
- # The value for one command/query/value-object attribute. `known_ids` is
118
- # `{aggregate_or_entity_name => [scalar id, ...]}`, supplied by the
119
- # sequence generator — a reference draws a real id from it most of the
120
- # time and a fabricated one sometimes, to exercise NotFound as often as
121
- # the happy path.
122
- # `context` carries the enclosing value object's own declared name down
123
- # into a nested primitive field — `EmailAddress`'s `address` field is
124
- # what actually needs to look email-shaped, but the field itself is
125
- # just named "address"; the VO's own name is where "email" lives. A
126
- # combined hint catches both spellings without needing to guess which
127
- # level a domain happened to name the thing on.
128
- #
129
- # @param attribute [Bluebook::Attribute] the attribute to generate a value for
130
- # @param aggregate [Bluebook::Aggregate] the aggregate `attribute` belongs to;
131
- # resolves a same-chapter identity value object
132
- # @param random [Random] the RNG driving every draw this call makes
133
- # @param known_ids [Hash{String => Array<String>}] known real ids, keyed by
134
- # aggregate or entity name; a reference draws from this pool
135
- # @param context [String, nil] the enclosing value object's own declared name,
136
- # for name-aware primitive generation; nil at the top level
137
- # @return [String, Integer, Float, Boolean, Hash] a JSON-safe value in the corpus's
138
- # own shape: a nested Hash for a value-object-typed attribute, a bare id String
139
- # for a reference, or a plain primitive otherwise
140
- def value_for(attribute, aggregate, random:, known_ids: {}, context: nil)
141
- return reference_value(attribute, random: random, known_ids: known_ids) if attribute.reference?
142
-
143
- # Local first, falling back to a same-chapter identity value object
144
- # declared on a sibling aggregate — the exact resolution
145
- # `Value.value_object_for` already does for a real dispatch
146
- # (runtime/value/coercion.rb). `safe_deposit_boxes.bluebook`'s own
147
- # `attribute :customer, CustomerNumber` is declared on SafeDepositBox
148
- # but CustomerNumber itself lives on Customer; without this fallback
149
- # the generator raised "does not know primitive type" for any such
150
- # cross-aggregate identity attribute rather than reusing the same
151
- # lookup the runtime relies on.
152
- value_object = Runtime::Value.value_object_for(aggregate, attribute.type.to_s)
153
- return object_for(value_object, aggregate, random: random, known_ids: known_ids) if value_object
154
-
155
- primitive(attribute.type.to_s, random: random, name: "#{context} #{attribute.name}")
156
- end
157
-
158
- # Generates a nested value for a whole value object: a random admitted
159
- # row for a closed set, or a value per declared attribute otherwise —
160
- # occasionally unwrapped to a bare scalar for a genuinely single-field
161
- # value object.
162
- #
163
- # @param value_object [Bluebook::ValueObject] the value object to generate a value for
164
- # @param aggregate [Bluebook::Aggregate] the aggregate `value_object` is reached
165
- # from, forwarded to nested `value_for` calls
166
- # @param random [Random] the RNG driving every draw this call makes
167
- # @param known_ids [Hash{String => Array<String>}] known real ids, keyed by
168
- # aggregate or entity name, forwarded to nested `value_for` calls
169
- # @return [Hash, Object] `{field name => value, ...}` for each declared attribute
170
- # or closed-set member; unwrapped to that lone value directly when the value
171
- # object has exactly one field and the bare-scalar draw hits
172
- def object_for(value_object, aggregate, random:, known_ids:)
173
- fields =
174
- if value_object.closed_set? && !value_object.members.empty?
175
- return invalid_member(value_object, random: random) if random.rand < INVALID_MEMBER_PROBABILITY
176
-
177
- member = value_object.members.sample(random: random)
178
- member.to_h { |field, value| [field.to_s, value] }
179
- else
180
- value_object.attributes.to_h do |field|
181
- [field.name.to_s,
182
- value_for(field, aggregate, random: random, known_ids: known_ids, context: value_object.hecks_name)]
183
- end
184
- end
185
-
186
- # `fields.size == 1` — the same test `Behaviour::ValueObject#
187
- # sole_attribute` names: a genuinely single-field value object,
188
- # not merely "this particular closed-set member happened to pick
189
- # one field." Unwrapping only here, not in `invalid_member`
190
- # above — a deliberately-wrong combination stays a Hash so its
191
- # own wrongness is what gets exercised, not a second, unrelated
192
- # shape question.
193
- return fields.values.first if fields.size == 1 && random.rand < BARE_SCALAR_PROBABILITY
194
-
195
- fields
196
- end
197
-
198
- # A combination that (almost certainly) isn't one of the closed set's
199
- # admitted rows — deliberately, to exercise the refusal a `one_of`
200
- # exists to enforce, not just its happy path.
201
- #
202
- # @param value_object [Bluebook::ValueObject] the closed-set value object to
203
- # generate a non-admitted combination for
204
- # @param random [Random] the RNG driving every draw this call makes
205
- # @return [Hash] `{field name => value, ...}` for every declared attribute, each
206
- # drawn independently rather than sampled from an admitted row
207
- def invalid_member(value_object, random:)
208
- value_object.attributes.to_h do |field|
209
- [field.name.to_s, primitive(field.type.to_s, random: random, name: field.name.to_s)]
210
- end
211
- end
212
-
213
- # The ID itself, unwrapped: the payload gate refuses a reference stored
214
- # wrapped as `{"value" => id}`, so a fuzzer emitting that shape would
215
- # have every generated reference refused and the silent guard would
216
- # report the fuzzer broken rather than the runtime.
217
- #
218
- # @param attribute [Bluebook::Attribute] the reference-typed attribute to
219
- # generate a value for
220
- # @param random [Random] the RNG driving every draw this call makes
221
- # @param known_ids [Hash{String => Array<String>}] known real ids, keyed by
222
- # aggregate or entity name; looked up under `attribute.type.target_name`
223
- # @return [String] a real id drawn from the matching pool most of the time; a
224
- # fabricated `"missing-..."` id when the pool is empty or the invalid-reference
225
- # draw hits
226
- def reference_value(attribute, random:, known_ids:)
227
- pool = known_ids[attribute.type.target_name.to_s] || []
228
- return "missing-#{random.bytes(4).unpack1('H*')}" if pool.empty? || random.rand < INVALID_REFERENCE_PROBABILITY
229
-
230
- pool.sample(random: random)
231
- end
232
-
233
- # Generates a value for one Ruby-primitive-typed attribute.
234
- #
235
- # @param type_name [String] the primitive type name: `"String"`, `"Integer"`,
236
- # `"Float"`, `"TrueClass"`, or `"FalseClass"`
237
- # @param random [Random] the RNG driving every draw this call makes
238
- # @param name [String, nil] a name hint (attribute name, optionally
239
- # context-prefixed) that draws an email-/currency-shaped string or a
240
- # clock/count-shaped integer
241
- # @return [String, Integer, Float, Boolean] a value of the type `type_name` names
242
- # @raise [ArgumentError] if `type_name` names anything else
243
- def primitive(type_name, random:, name: nil)
244
- case type_name
245
- when "String" then string_value(random, name: name)
246
- when "Integer" then integer_value(random, name: name)
247
- when "Float" then float_value(random)
248
- when "TrueClass", "FalseClass" then random.rand(2).zero?
249
- else raise ArgumentError, "ValueGenerator does not know primitive type #{type_name.inspect}"
250
- end
251
- end
252
-
253
- # Generates a String value, name-aware for the couple of shapes that
254
- # need to look a specific way to get past their own invariant.
255
- #
256
- # @param random [Random] the RNG driving every draw this call makes
257
- # @param name [String, nil] a name hint; an `"email"` or `"currency"` match
258
- # draws a shaped value instead of random words
259
- # @return [String] an edge-case string, an email address, a currency code, or
260
- # 1-3 random words joined by spaces
261
- def string_value(random, name: nil)
262
- return STRING_EDGE_CASES.sample(random: random) if random.rand < EDGE_CASE_PROBABILITY
263
- return email_value(random) if name&.match?(/email/i)
264
- return CURRENCY_CODES.sample(random: random) if name&.match?(/currency/i)
265
-
266
- Array.new(random.rand(1..3)) { WORDS.sample(random: random) }.join(" ")
267
- end
268
-
269
- # Generates a fabricated, syntactically valid email address.
270
- #
271
- # @param random [Random] the RNG driving every draw this call makes
272
- # @return [String] a `"word@word.example"` address
273
- def email_value(random)
274
- "#{WORDS.sample(random: random)}@#{WORDS.sample(random: random)}.example"
275
- end
276
-
277
- # Generates an Integer value, skewed positive.
278
- #
279
- # Skewed positive : `cents.positive?`/`!cents.negative?`-style
280
- # invariants are common across this codebase's example domains, and a
281
- # sequence that can never get past one never reaches the state a deeper
282
- # bug would need. Zero and negative are still real, reachable outcomes —
283
- # via the edge-case pool, deliberately, not by starving them entirely.
284
- #
285
- # @param random [Random] the RNG driving every draw this call makes
286
- # @param name [String, nil] a name hint; a clock/count-shaped match narrows
287
- # the edge-case pool to `SAFE_INTEGER_EDGE_CASES`
288
- # @return [Integer] an edge-case integer sometimes, else a random count in 1..1000
289
- def integer_value(random, name: nil)
290
- if random.rand < EDGE_CASE_PROBABILITY
291
- pool = clock_or_count_shaped?(name) ? SAFE_INTEGER_EDGE_CASES : INTEGER_EDGE_CASES
292
- return pool.sample(random: random)
293
- end
294
-
295
- random.rand(1..1000)
296
- end
297
-
298
- # Reports whether a field name reads as a clock reading or a
299
- # policy-capped count, per `CLOCK_OR_COUNT_NAME_PATTERN`'s own comment.
300
- #
301
- # @param name [String, nil] the name to test
302
- # @return [Boolean] true if `name` matches the clock/count name pattern
303
- def clock_or_count_shaped?(name)
304
- name.to_s.match?(CLOCK_OR_COUNT_NAME_PATTERN)
305
- end
306
-
307
- # Generates a Float value.
308
- #
309
- # @param random [Random] the RNG driving every draw this call makes
310
- # @return [Float] an edge-case float sometimes, else a random value in
311
- # 0.01..1000.0, rounded to 2 decimal places
312
- def float_value(random)
313
- return FLOAT_EDGE_CASES.sample(random: random) if random.rand < EDGE_CASE_PROBABILITY
314
-
315
- random.rand(0.01..1000.0).round(2)
316
- end
317
-
318
- # The bare scalar a generated identity value stands for, for recording into
319
- # `known_ids`. An identity is declared as a value object, so this opens one ;
320
- # a reference pointing at this record is already that scalar and needs no
321
- # opening at all — the two are different readings, not interchangeable.
322
- #
323
- # @param identity_value [Hash, Object] a generated identity value, as `value_for`
324
- # produced it — a Hash for a multi-field value object, or the bare scalar already
325
- # for a single-field one
326
- # @return [String] the identity's bare scalar, stringified
327
- def scalar_of(identity_value)
328
- identity_value.is_a?(Hash) ? identity_value.values.first.to_s : identity_value.to_s
329
- end
330
-
331
- # Generates a fabricated id unrelated to anything `known_ids` tracks.
332
- #
333
- # @param random [Random] the RNG driving every draw this call makes
334
- # @return [String] a `"gen-"`-prefixed id with 8 random hex characters
335
- def random_id(random)
336
- "gen-#{random.bytes(4).unpack1('H*')}"
337
- end
338
- end
339
- end
340
- end
data/lib/hecks/fuzzing.rb DELETED
@@ -1,23 +0,0 @@
1
- module Hecks
2
- # The fuzzing toolkit bin/fuzz and bin/generate drive. Not required by
3
- # lib/hecks.rb on purpose — a booted domain never needs it.
4
- module Fuzzing
5
- end
6
- end
7
-
8
- require_relative "fuzzing/value_generator"
9
- require_relative "fuzzing/invalid_value_generator"
10
- require_relative "fuzzing/sequence_generator"
11
- require_relative "fuzzing/nondeterministic"
12
- require_relative "fuzzing/replay"
13
- require_relative "fuzzing/shrinker"
14
- require_relative "fuzzing/properties"
15
- require_relative "fuzzing/qa_settings"
16
- require_relative "fuzzing/rotation_priority"
17
- require_relative "fuzzing/sweep_depth"
18
- require_relative "fuzzing/persistence_parity"
19
- require_relative "fuzzing/form_census"
20
- require_relative "fuzzing/target_capabilities"
21
- require_relative "fuzzing/rust_gap_manifest"
22
- require_relative "fuzzing/structural_skips"
23
- require_relative "fuzzing/coverage_campaign"